Skip to content

Commit

Permalink
feat: add agents/plan_and_execute
Browse files Browse the repository at this point in the history
  • Loading branch information
nobu007 committed May 15, 2024
1 parent 7907dde commit 0361f9d
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/codeinterpreterapi/agents/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

3 changes: 1 addition & 2 deletions src/codeinterpreterapi/agents/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

from langchain.agents import AgentExecutor, BaseSingleActionAgent, ConversationalAgent, ConversationalChatAgent
from langchain.agents.openai_functions_agent.base import OpenAIFunctionsAgent
from langchain.chat_models.base import BaseChatModel
from langchain.memory.buffer import ConversationBufferMemory
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts.chat import MessagesPlaceholder
from langchain_experimental.plan_and_execute import PlanAndExecute, load_agent_executor, load_chat_planner
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_openai import AzureChatOpenAI, ChatOpenAI

from codeinterpreterapi.agents.plan_and_execute.agent_executor import load_agent_executor
from codeinterpreterapi.config import settings


Expand Down
2 changes: 2 additions & 0 deletions src/codeinterpreterapi/agents/plan_and_execute/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# agent_executor.py
# https://github.com/langchain-ai/langchain/blob/3ee07473821906a29d944866a2ededb41148f234/libs/experimental/langchain_experimental/plan_and_execute/executors/agent_executor.py
74 changes: 74 additions & 0 deletions src/codeinterpreterapi/agents/plan_and_execute/agent_executor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from typing import List, Optional

from langchain.agents.agent import AgentExecutor, AgentOutputParser
from langchain.agents.structured_chat.base import StructuredChatAgent
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,
)


def load_agent_executor(
llm: BaseLanguageModel,
tools: List[BaseTool],
callback_manager: Optional[BaseCallbackManager] = None,
output_parser: Optional[AgentOutputParser] = None,
verbose: bool = False,
include_task_in_prompt: bool = False,
is_ja: str = True,
) -> ChainExecutor:
"""
Load an agent executor.
Args:
llm: BaseLanguageModel
tools: List[BaseTool]
verbose: bool. Defaults to False.
include_task_in_prompt: bool. Defaults to False.
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(
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,
# memory_prompts = memory_prompts,
)
agent_executor = AgentExecutor.from_agent_and_tools(agent=agent, tools=tools, verbose=verbose)
return ChainExecutor(chain=agent_executor)
88 changes: 88 additions & 0 deletions src/codeinterpreterapi/agents/plan_and_execute/prompts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from textwrap import dedent

from langchain_core.prompts import PromptTemplate
from langchain_experimental.tot.prompts import JSONListOutputParser

HUMAN_MESSAGE_TEMPLATE = """Previous steps: {previous_steps}
Current objective: {current_step}
{agent_scratchpad}"""

TASK_PREFIX = """{objective}
"""

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).
Valid "action" values: "Final Answer" or {tool_names}
Provide only ONE action per $JSON_BLOB, as shown:
```
{{{{
"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"
}}}}
```"""
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


def get_plan_and_execute_prompt(is_ja: bool) -> str:
"""Get the main prompt for plan_and_execute."""
if is_ja:
return FORMAT_INSTRUCTIONS_JA
else:
return FORMAT_INSTRUCTIONS
1 change: 1 addition & 0 deletions src/codeinterpreterapi/planners/planners.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ class CodeInterpreterPlanner:
@staticmethod
def choose_planner(llm: BaseLanguageModel, is_ja: bool) -> LLMPlanner:
system_prompt = SYSTEM_PROMPT_PLANNER_JA if is_ja else SYSTEM_PROMPT_PLANNER
print("system_prompt(planner)=", system_prompt)
planner = load_chat_planner(llm, system_prompt=system_prompt)
return planner

0 comments on commit 0361f9d

Please sign in to comment.