实用笔记:LangChain中的智能体AI——第三部分:在LangChain中调用工具
《实用笔记:LangChain中的智能体AI》操作指南——第三部分:LangChain中的工具调用功能,为采用该架构的团队提供合约、校验机制以及可直接插入的代码模块。
可将此内容视为《基于LangChain的智能体AI——第三部分:LangChain中的工具调用》中理念面向操作人员的简化版本:清晰的阶段划分、有序的代码模块,以及便于交接时参考的恢复说明。 将“概览”阶段视为可量化的界面使用效果最佳。在扩大范围之前,先记录一份理想的操作流程、一个失败案例以及对应的回滚说明。 在功能结果旁同时记录执行时间以及token或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外费用。
工具调用概念
在“工具调用概念”阶段,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 配置信息应置于应用程序代码之外。环境文件、密钥存储以及功能标志应集中存放于一个位置,以便操作人员无需查看整个系统结构即可进行审核。 在网关处进行身份验证,在数据层再次授权。仅凭承载令牌并不足以界定租户边界。
1. 系统配置
在“1 系统配置”阶段,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 需同时记录正常流程和故障恢复流程。重试机制、人工审核环节以及错误消息处理都是产品本身的组成部分,而非后续需要补充的功能。 在网关处进行身份验证,在数据层再次授权。仅凭承载令牌并不能作为租户边界。
OPENAI_API_KEY="<Your OpenAI API Key>"
TAVILY_API_KEY=<Your TAVILY API Key>
class BaseConfig(BaseSettings):
OPENAI_API_KEY: Optional[str]
PINECONE_API_KEY: Optional[str]
TAVILY_API_KEY: Optional[str]
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
2. 项目结构
在“2项目结构”阶段,应在修改代码之前明确输入内容、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。相比冗长的脚本,更应采用小型且可测试的单元。当某个步骤失败时,故障原因应能指向单一责任主体,而非复杂的流程链。在网关处进行身份验证,在数据层再次授权——仅凭承载令牌并不足以界定租户边界。
project/
|
├── tools
│ ├── get_sum.py # a simple LangChain tool example
| └── weather.py # get_weather LangChain tool using open source APIs
|
|── tool_call.py # implement tool-calling loop using LangChain tools
├── config.py # pydantic BaseConfig
├── .env # environment variable definition
├── .gitignore
└── requirements.txt # package requirements
3. LangChain工具
在3个LangChain工具阶段中,修改代码之前需先明确输入内容、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 将此阶段视为输入与经过验证的输出之间的契约。为相关成果命名,定义成功判定标准,并拒绝默许的半完成状态。 在网关处进行身份验证,在数据层再次授权。仅凭承载令牌并不足以界定租户边界。
3.1. 什么是LangChain工具?
在进入“3.1 什么是阶段”时,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。应在功能结果旁记录执行时间以及令牌或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外费用。
from langchain.tools import tool
@tool
def get_sum(a: int, b: int) -> int:
"""
get the summation of two integers
:param a: int, input integer
:param b: int, input integer
:return: int, the sum of a and b
"""
return a + b
3.2. 实现天气工具
在实施3.2阶段时,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 配置信息应置于应用程序代码之外。环境文件、密钥存储以及功能标志应集中存放于一个位置,这样操作人员无需查看整个系统结构即可进行审计。 在网关处进行身份验证,在数据层进行重新授权。仅凭承载令牌并不足以界定租户边界。
3.3 工具调用的概念
对于“3×3阶段概念”,在修改代码之前需明确输入参数、该步骤的负责人以及退出标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 需同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及死信处理都是产品本身的组成部分,而非后续需要补充的功能。 在网关处进行身份验证,在数据层再次授权。仅凭承载令牌并不足以界定租户边界。
3.4. LangChain中的工具调用
在3 4工具调用阶段,修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 相较于庞大的脚本,应优先选择小型且可测试的单元。当某个步骤失败时,故障原因应能明确指向单一责任主体,而非复杂的流程链。 在网关处进行身份验证,在数据层再次授权。仅凭承载令牌并不足以界定租户边界。 在3 4工具调用阶段,修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 除了功能结果外,还需记录执行时间以及令牌或查询成本。提前了解成本情况,可避免在流程从演示环境过渡到共享环境时出现意外账单。
3.4.1. 配置大语言模型与工具
在完成3 4 1配置阶段时,首先列出相关规范:所需输入、成功标志以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 将配置信息置于应用程序代码之外。环境文件、密钥存储以及功能开关应集中存放,以便操作人员无需查看整个系统结构即可进行审计。 缓存稳定的系统指令和工具架构。重复发送相同的开头信息是导致资源浪费的常见原因。
class WeatherAssistant:
def __init__(self):
# initialize llm
self.llm = ChatOpenAI(api_key=api_key, model="gpt-4o-mini", temperature=0)
# initialize a tool dictionary
self.tools = {"get_weather": get_weather,
"tavily_search": TavilySearch(max_results=3, tavily_api_key=TAVILY_API_KEY)}
# bind LangChain tools to llm
self.llm_with_tools = self.llm.bind_tools(list(self.tools.values()))
# initialize messages to store message list
self.messages = []
# System prompt
self.system_prompt = f"""You are a helpful assistant for question-answering tasks.
When users ask about weather, use the get_weather tool to get weather. For other questions,
use web_search. If you don't know the answer, just say that you don't know.
Be conversational and helpful in your responses."""
self.messages.append(SystemMessage(content=self.system_prompt))
3.4.2. 实现工具调用循环
在执行3 4 2实施阶段时,首先需写下接口契约:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及死信处理都是产品功能的一部分,而非后续需要补充的内容。 需为每次调用记录工具名称、参数哈希值、延迟时间以及执行结果。没有这些记录,调试代理将陷入无止境的循环,耗费大量时间。
async def chat(self, message: str):
# Wrap User message in a HumanMessage and add it to message list
self.messages.append(HumanMessage(content=message))
# Get AI response (it may or may not contain tool calls)
response = await self.llm_with_tools.ainvoke(self.messages)
self.messages.append(response)
# If there is any tool calls in the AI response
if response.tool_calls:
# process tool calls
for tool_call in response.tool_calls:
# retrieve function name from tool_call, then
# retrieve the tool from tool dictionary, and invoke it,
# append resulting tool message to message list
tool = self.tools[tool_call["name"]]
tool_result = await tool.ainvoke(tool_call)
self.messages.append(tool_result)
# Get final response after tool execution
final_response = await self.llm_with_tools.ainvoke(self.messages)
self.messages.append(final_response)
3.4.3 循环测试
在进行3 4 3测试阶段时,首先需明确接口规范:所需的输入参数、成功标志以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持一致性。 相比冗长的脚本,应优先选择小型且易于测试的单元。当某个步骤失败时,故障应能指向具体的责任模块,而非复杂的流程链。 需为每次调用记录工具名称、参数哈希值、延迟时间以及最终结果。没有这些记录,调试过程将会浪费大量时间。 在进行3 4 3测试阶段时,首先需明确接口规范:所需的输入参数、成功标志以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持一致性。 在功能结果旁还需记录执行时间以及代币或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外费用。
async def main():
print("hello tool calling!")
assistant = WeatherAssistant()
message = "What is the temperature in Tokyo?"
await assistant.chat(message)
for msg in assistant.messages:
msg.pretty_print()
if __name__ == "__main__":
asyncio.run(main())
4. 基本工具调用循环的局限性
将该阶段视为可测量的界面时,其四大局限性才能得到最佳发挥。在扩大范围之前,需先记录一份成功的示例、一个失败案例以及回滚说明。 配置应置于应用程序代码之外。环境文件、密钥存储和功能标志应集中存放,以便操作人员无需查看整个架构即可进行审计。 工具应具有明确的架构定义和清晰的副作用标签。主机需要在自动批准之前知道哪些调用会修改状态。
5. 总结
将“5个收尾总结阶段”视为可度量的工作面最为有效。在扩大范围之前,先记录一份最佳处理方案、一个失败案例以及回滚说明。同时文档化正常流程与恢复流程。重试机制、人工审核环节以及错误处理都属于产品功能的一部分,而非后续需要补充的内容。应提供具有明确结构规范和显式副作用标签的工具,以便主机在自动批准之前能够知晓哪些调用会改变系统状态。
运营检查清单
在处理运营检查清单阶段时,首先明确合同条款:所需输入、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。
将此阶段视为输入与经过验证的输出之间的契约。为相关成果命名,定义成功检测标准,并拒绝默许的部分完成状态。
记录每次调用的工具名称、参数哈希值、延迟时间以及执行结果。如果没有这些追踪信息,调试代理将陷入无限循环,耗费大量时间。
保持数据结构简洁且类型明确。嵌套的数据结构会掩盖具体是哪个节点设置了哪个字段,还会在中断后导致流程无法继续。
只要预算允许,就在持续集成过程中使用测试用例而非真实的付费 API 来对关键路径进行压力测试。
同时记录正常流程和故障恢复流程。重试机制、人工审核环节以及错误处理方式都是产品不可或缺的部分,而非后续需要补充的功能。
在升级技术栈之前,先冻结现有版本,为关键路径生成标准化的操作记录,并确认回滚步骤。共享环境需要设置速率限制、租户验证机制,以及明确的密钥轮换负责人。与其追求华丽的临时演示,不如注重扎实的可靠性。
d7ca1ebeb899的批处理说明:不要将提供者密钥放入仓库中,设定单会话令牌上限,并将转录内容存储在评估测试用例的旁边,以便后续模型更换时仍能保持可比性。