Skip to content

Commit

Permalink
fix: update tools and prompts for create_structured_chat_agent
Browse files Browse the repository at this point in the history
  • Loading branch information
nobu007 committed May 18, 2024
1 parent 996ae12 commit a7630e7
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 107 deletions.
2 changes: 1 addition & 1 deletion src/codeinterpreterapi/agents/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,6 @@ def create_agent_and_executor_experimental(llm, tools, verbose, is_ja) -> AgentE
print("create_agent_and_executor agent=", str(type(agent)))

# agent_executor
agent_executor = load_agent_executor(llm, tools, verbose=verbose)
agent_executor = load_agent_executor(llm, tools, verbose=verbose, is_ja=is_ja)

return agent_executor
51 changes: 14 additions & 37 deletions src/codeinterpreterapi/agents/plan_and_execute/agent_executor.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
from typing import List, Optional

from langchain.agents.agent import AgentExecutor, AgentOutputParser
from langchain.agents.structured_chat.base import StructuredChatAgent
from langchain.agents.structured_chat.base import StructuredChatAgent, create_structured_chat_agent
from langchain.tools import BaseTool
from langchain_core.callbacks import BaseCallbackManager
from langchain_core.language_models import BaseLanguageModel
from langchain_experimental.plan_and_execute.executors.base import ChainExecutor

from codeinterpreterapi.agents.plan_and_execute.prompts import (
FORMAT_INSTRUCTIONS,
FORMAT_INSTRUCTIONS_JA,
HUMAN_MESSAGE_TEMPLATE,
SUFFIX,
SUFFIX_JA,
TASK_PREFIX,
TOOLS_PREFIX,
TOOLS_PREFIX_JA,
)
from codeinterpreterapi.agents.plan_and_execute.prompts import create_structured_chat_agent_prompt


def load_agent_executor(
Expand All @@ -40,34 +31,20 @@ def load_agent_executor(
Returns:
ChainExecutor
"""
input_variables = ["previous_steps", "current_step", "agent_scratchpad"]

# message_template
message_template = ""
if include_task_in_prompt:
input_variables.append("objective")
message_template += TASK_PREFIX
message_template += HUMAN_MESSAGE_TEMPLATE

# format_instructions, tools_prefix, suffix
if is_ja:
format_instructions = FORMAT_INSTRUCTIONS_JA
tools_prefix = TOOLS_PREFIX_JA
suffix = SUFFIX_JA
else:
format_instructions = FORMAT_INSTRUCTIONS
tools_prefix = TOOLS_PREFIX
suffix = SUFFIX
agent = StructuredChatAgent.from_llm_and_tools(
input_variables = ["previous_steps", "current_step", "agent_scratchpad", "tools", "tool_names"]
print("input_variables=", input_variables)
prompt = create_structured_chat_agent_prompt(is_ja)
print("prompt=", prompt.get_prompts())
agent = create_structured_chat_agent(
llm=llm,
tools=tools,
callback_manager=callback_manager,
output_parser=output_parser,
prefix=tools_prefix,
suffix=suffix,
human_message_template=message_template,
format_instructions=format_instructions,
input_variables=input_variables,
# callback_manager=callback_manager,
# output_parser=output_parser,
# prefix=tools_prefix,
# suffix=suffix,
prompt=prompt,
# format_instructions=format_instructions,
# input_variables=input_variables,
# memory_prompts = memory_prompts,
)
agent_executor = AgentExecutor.from_agent_and_tools(agent=agent, tools=tools, verbose=verbose)
Expand Down
159 changes: 96 additions & 63 deletions src/codeinterpreterapi/agents/plan_and_execute/prompts.py
Original file line number Diff line number Diff line change
@@ -1,88 +1,121 @@
from textwrap import dedent

from langchain_core.prompts import PromptTemplate
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder, PromptTemplate
from langchain_experimental.tot.prompts import JSONListOutputParser

HUMAN_MESSAGE_TEMPLATE = """Previous steps: {previous_steps}
SYSTEM_MESSAGE_TEMPLATE = '''Respond to the human as helpfully and accurately as possible. You have access to the following tools:
Current objective: {current_step}
{tools}
{agent_scratchpad}"""
Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).
TASK_PREFIX = """{objective}
Valid "action" values: "Final Answer" or {tool_names}
"""
Provide only ONE action per $JSON_BLOB, as shown:
TOOLS_PREFIX = (
"""Respond to the human as helpfully and accurately as possible. You have access to the following tools:"""
)
FORMAT_INSTRUCTIONS = """Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).
```
{{
"action": $TOOL_NAME,
"action_input": $INPUT
}}
```
Follow this format:
Question: input question to answer
Thought: consider previous and subsequent steps
Action:
```
$JSON_BLOB
```
Observation: action result
... (repeat Thought/Action/Observation N times)
Thought: I know what to respond
Action:
```
{{
"action": "Final Answer",
"action_input": "Final response to human"
}}
Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary.
Respond directly if appropriate. Format is Action:```$JSON_BLOB```then Observation
'''

HUMAN_MESSAGE_TEMPLATE = '''{input}
{agent_scratchpad}
(reminder to respond in a JSON blob no matter what)'''

SYSTEM_MESSAGE_TEMPLATE_JA = '''初期質問にできる限り丁寧かつ正確に答えてください。以下のツールが利用可能です:
{tools}
1つの $JSON_BLOB では常に単一のアクションで応答してください。
action は (TOOL_NAME) 、action_input は (INPUT) を使ってください。
Valid "action" values: "Final Answer" or {tool_names}
Provide only ONE action per $JSON_BLOB, as shown:
フォーマットは次のようになります。
```
{{{{
"action": $TOOL_NAME,
"action_input": $INPUT
}}}}
```
```
{{
"action": $TOOL_NAME,
"action_input": $INPUT
}}
```
Follow this format:
その後のシーケンスは以下の形式に従ってください:
Question: input question to answer
Thought: consider previous and subsequent steps
Question: 初期質問に正しく答えるための質問
Thought: 前後のステップを検討する
Action:
```
$JSON_BLOB
```
Observation: action result
... (repeat Thought/Action/Observation N times)
Thought: I know what to respond
Observation: アクションの結果
(Thought/Action/Observation をN回繰り返す)
Thought: 何を答えるべきかわかった
Action:
```
{{{{
"action": "Final Answer",
"action_input": "Final response to human"
}}}}
```"""
SUFFIX = """Begin! Reminder to ALWAYS respond with a valid json blob of a single action.
Use tools if necessary. Respond directly if appropriate.
Format is like this.
Action:```$JSON_BLOB```
Observation:
Thought:"""

TOOLS_PREFIX_JA = """できる限り丁寧かつ正確に人間の質問に答えてください。以下のツールが利用可能です:"""

FORMAT_INSTRUCTIONS_JA = """
始めましょう!常に単一のアクションの有効なJSONブロブで応答することを忘れないでください。
必要に応じてツールを使用してください。適切な場合は直接回答してください。
フォーマットは次のようにしてください。
Action:```$JSON_BLOB```
Observation:
Thought:
"""
SUFFIX_JA = """それでは始めましょう。常に単一のアクションの有効なJSON_BLOBで応答してください。
必要に応じてツールを使用してください。適切な場合は直接回答してください。
フォーマットは次のようにしてください。
Action:```$JSON_BLOB```
Observation:
Thought:"""


def get_tools_prefix_prompt(is_ja: bool) -> str:
"""Get the prefix prompt for plan_and_execute."""
if is_ja:
return TOOLS_PREFIX_JA
else:
return TOOLS_PREFIX
{{
"action": "最終回答",
"action_input": "初期質問への最終的な回答"
}}
```
それでは始めましょう。常に単一のアクションの有効なJSONブロブで応答することを忘れないでください。
必要に応じてツールを使用してください。
適切な場合は直接回答してください。
'''

HUMAN_MESSAGE_TEMPLATE_JA = '''{input}
{agent_scratchpad}
リマインダ: 何があっても $JSON_BLOB だけで応答するようにしてください。
'''


def get_plan_and_execute_prompt(is_ja: bool) -> str:
"""Get the main prompt for plan_and_execute."""
def create_structured_chat_agent_prompt(is_ja: bool = True):
if is_ja:
return FORMAT_INSTRUCTIONS_JA
prompt = ChatPromptTemplate.from_messages(
[
("system", SYSTEM_MESSAGE_TEMPLATE_JA),
MessagesPlaceholder("chat_history", optional=True),
("human", HUMAN_MESSAGE_TEMPLATE_JA),
]
)
else:
return FORMAT_INSTRUCTIONS
prompt = ChatPromptTemplate.from_messages(
[
("system", SYSTEM_MESSAGE_TEMPLATE),
MessagesPlaceholder("chat_history", optional=True),
("human", HUMAN_MESSAGE_TEMPLATE),
]
)
return prompt
4 changes: 3 additions & 1 deletion src/codeinterpreterapi/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ def __init__(
if self.is_local:
run_handler_func = self._run_handler_local
arun_handler_func = self._arun_handler_local
self.tools: list[BaseTool] = CodeInterpreterTools.get_all(additional_tools, run_handler_func, arun_handler_func)
self.llm: BaseLanguageModel = llm or CodeInterpreterLlm.get_llm()
self.tools: list[BaseTool] = CodeInterpreterTools.get_all(
additional_tools, run_handler_func, arun_handler_func, self.llm
)
self.log("self.llm=" + str(self.llm))

self.callbacks = callbacks
Expand Down
41 changes: 36 additions & 5 deletions src/codeinterpreterapi/tools/tools.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
from langchain_community.tools.shell.tool import ShellTool
from langchain_community.tools.shell.tool import BaseTool, ShellTool
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.tools import BaseTool, StructuredTool
from langchain_core.language_models import LLM, BaseLanguageModel, BaseLLM
from langchain_core.tools import StructuredTool, Tool
from langchain_experimental.chat_models.llm_wrapper import ChatWrapper
from langchain_experimental.llm_bash.base import LLMBashChain

from codeinterpreterapi.config import settings
from codeinterpreterapi.schema import CodeInput


class CodeInterpreterTools:
@staticmethod
def get_all(additional_tools: list[BaseTool], run_handler_func, arun_handler_func) -> list[BaseTool]:
def get_all(
additional_tools: list[BaseTool], llm: BaseLanguageModel, run_handler_func, arun_handler_func
) -> list[BaseTool]:
additional_tools = CodeInterpreterTools.get_python(additional_tools, run_handler_func, arun_handler_func)
additional_tools = CodeInterpreterTools.get_shell(additional_tools)
additional_tools = CodeInterpreterTools.get_web_search(additional_tools)
Expand Down Expand Up @@ -39,11 +44,37 @@ def get_python(additional_tools: list[BaseTool], run_handler_func, arun_handler_

@staticmethod
def get_shell(additional_tools: list[BaseTool]) -> list[BaseTool]:
tools = [ShellTool()]
"""
ShellTool cause this error. Should not use this.
pydantic.v1.error_wrappers.ValidationError: 1 validation error for ShellInput
commands
field required (type=value_error.missing)
"""
shell_tool = ShellTool()
shell_tool.description = shell_tool.description + f"args {shell_tool.args}".replace("{", "{{").replace(
"}", "}}"
)
tools = [shell_tool]
return additional_tools + tools

@staticmethod
def get_shell_v2(additional_tools: list[BaseTool], llm: BaseLanguageModel) -> list[BaseTool]:
"""
ShellTool cause this error. Should not use this.
pydantic.v1.error_wrappers.ValidationError: 1 validation error for ShellInput
commands
field required (type=value_error.missing)
"""
llm_runnable = ChatWrapper(llm=llm)
bash_chain = LLMBashChain.from_llm(llm=llm)
bash_tool = Tool(
name="Bash", func=bash_chain.invoke, description="Executes bash commands in a terminal environment."
)

tools = [bash_tool]
return additional_tools + tools

@staticmethod
def get_web_search(additional_tools: list[BaseTool]) -> list[BaseTool]:
# TODO: use ShellInput
tools = [TavilySearchResults(max_results=1)]
return additional_tools + tools

0 comments on commit a7630e7

Please sign in to comment.