LangChain系列文章
代理动态调用工具。这些工具调用的结果被添加回提示,以便代理可以规划下一步行动。根据使用的工具和它们的调用方式,代理提示很容易变得比模型上下文窗口更大。
使用LCEL,可以轻松添加自定义功能来管理链或代理中提示的大小。让我们看一个简单的代理示例,可以搜索维基百科获取信息。
# !pip install langchain wikipedia
from operator import itemgetter
from langchain.agents import AgentExecutor, load_tools
from langchain.agents.format_scratchpad import format_to_openai_function_messages
from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.prompts.chat import ChatPromptValue
from langchain.tools import WikipediaQueryRun
from langchain_community.chat_models import ChatOpenAI
from langchain_community.tools.convert_to_openai import format_tool_to_openai_function
from langchain_community.utilities import WikipediaAPIWrapper
from dotenv import load_dotenv # 导入从 .env 文件加载环境变量的函数
load_dotenv() # 调用函数实际加载环境变量
from langchain.globals import set_debug # 导入在 langchain 中设置调试模式的函数
set_debug(True) # 启用 langchain 的调试模式
wiki = WikipediaQueryRun(
api_wrapper=WikipediaAPIWrapper(top_k_results=5, doc_content_chars_max=10_000)
)
tools = [wiki]
prompt = ChatPromptTemplate.from_messages(
[
("system", "你是一个很有帮助的助手"),
("user", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
]
)
llm = ChatOpenAI()
agent = (
{
"input": itemgetter("input"),
"agent_scratchpad": lambda x: format_to_openai_function_messages(
x["intermediate_steps"]
),
}
| prompt
| llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])
| OpenAIFunctionsAgentOutputParser()
)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
response = agent_executor.invoke(
{
"input": "现任美国总统是谁?他们来自哪个州?他们州的州鸟是什么?那只鸟的学名是什么?"
}
)
print('response >> ', response)
很遗憾,在我们的模型上下文窗口中,我们的代理还没能得到最终答案之前就已经用完了空间。LangSmith trace
BadRequestError: Error code: 400 - {'error': {'message': "This model's maximum context length is 4097 tokens. However, your messages resulted in 5478 tokens (5410 in the messages, 68 in the functions). Please reduce the length of the messages or functions.", 'type': 'invalid_request_error', 'param': 'messages', 'code': 'context_length_exceeded'}}
现在让我们添加一些提示处理逻辑。为了保持简单,如果我们的消息有太多的标记,我们将开始在聊天记录中删除最早的AI、功能消息对(这是模型工具调用消息和随后的工具输出消息)。
def condense_prompt(prompt: ChatPromptValue) -> ChatPromptValue:
messages = prompt.to_messages()
num_tokens = llm.get_num_tokens_from_messages(messages)
ai_function_messages = messages[2:]
while num_tokens > 4_000:
ai_function_messages = ai_function_messages[2:]
num_tokens = llm.get_num_tokens_from_messages(
messages[:2] + ai_function_messages
)
messages = messages[:2] + ai_function_messages
return ChatPromptValue(messages=messages)
agent = (
{
"input": itemgetter("input"),
"agent_scratchpad": lambda x: format_to_openai_function_messages(
x["intermediate_steps"]
),
}
| prompt
| condense_prompt
| llm.bind(functions=[format_tool_to_openai_function(t) for t in tools])
| OpenAIFunctionsAgentOutputParser()
)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_executor.invoke(
{
"input": "Who is the current US president? What's their home state? What's their home state's bird? What's that bird's scientific name?"
}
)
输出结果
{'input': "Who is the current US president? What's their home state? What's their home state's bird? What's that bird's scientific name?",
'output': 'The current US president is Joe Biden. His home state is Delaware. The state bird of Delaware is the Delaware Blue Hen. Its scientific name is Gallus gallus domesticus.'}
https://github.com/zgpeace/pets-name-langchain/tree/develop
https://python.langchain.com/docs/expression_language/cookbook/prompt_size