1.前言
之前一直使用 dify开发 agent,虽然功能很全面、效果也稳定,但是也存在流程固化、不灵活,以及 dify本身太重(内部包含10个容器)等问题。
故最近研究了大名顶顶的 langchain,先从函数调用开始,研究如何构建一个agent。
环境信息:
python-3.13、langchain-0.3.26
2.函数定义
可以把 python定义的函数注册到 langchain里面,然后大模型会根据用户的问题,自主决定应该调用的函数。
函数定义如下:
def get_weather(location: str):return f"{location} 的天气是晴天,22°C"def get_time(location: str):return f"{location} 的当前时间是 9:00 PM"tools = [Tool(name="get_weather", func=get_weather, description="查询城市天气"),Tool(name="get_time", func=get_time, description="查询城市当前时间"),
]
重点需要关注的是 Tool这个类,langchain提供的函数调用核心类,可以把普通的 python函数包装成大模型可以调用的形式。
其中,description比较关键,要清晰描述函数的功能,这样大模型才能根据用户的问题进行推导,然后决定调用这个函数。其次,函数的参数命名要符合参数的含义,在上面 地点就是 location最接近,这个是因为大模型要从用户问题中提取地点作为函数调用时的参数。
3.创建和运行Agent
首先,需要创建一个大模型对话模型,如下:
llm_cfg = {"base_url": "https://api.siliconflow.cn/v1","api_key": "sk-xx",
}
model = init_chat_model(model="Qwen/Qwen2.5-72B-Instruct", model_provider="openai", **llm_cfg
)
这里可以根据实际情况选择大模型接口,只要兼容 openai协议都可以这种方法初始化。
然后创建agent:
memory = MemorySaver()
agent_executor = create_react_agent(model, tools, checkpointer=memory)
最后,执行agent,并指定流式输出:
config = {"configurable": {"thread_id": "abc123"}}input_message = {"role": "user","content": "成都现在几点,天气怎么样?",
}i = 0
for step in agent_executor.stream({"messages": [input_message]}, config, stream_mode="values"
):messages = step["messages"]while i < len(messages):message = messages[i]if isinstance(message, HumanMessage):print(f"Human: {message.content}")elif isinstance(message, AIMessage):print(f"AI: {message.content}")elif isinstance(message, ToolMessage):print(f"Tool: {message.name}, result: {message.content}")i += 1
这里对流式接口的返回值做一个说明:
-
HumanMessage,用户的提问信息
-
AIMessage,大模型回复的内容
-
ToolMessage
工具调用情况,在实际项目中,都要单独渲染工具的执行情况,这一点使用 langchain确实很方便
最后的实现效果如下:
Human: 成都现在几点,天气怎么样?
AI:
Tool: get_time, result: 成都 的当前时间是 9:00 PM
Tool: get_weather, result: 成都 的天气是晴天,22°C
AI: 成都现在的当前时间是 9:00 PM,天气是晴天,温度为22°C。
可以看到,langchain很准确的提取出了 location=成都,然后调用 get_time和 get_weather函数,最后根据函数调用的结果回答用户的问题。
4.完整代码
为了方便感兴趣的朋友实操,这里贴一下依赖清单和完整代码。
requirements.txt
langchain
openai
langchain-community
langchain-openai
langgraph
完整代码:
from langchain.chat_models import init_chat_model
from langchain.tools import Tool
from langchain_core import messages
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent
from langchain_core.messages import HumanMessage, AIMessage, ToolMessagedef get_weather(location: str):return f"{location} 的天气是晴天,22°C"def get_time(location: str):return f"{location} 的当前时间是 9:00 PM"tools = [Tool(name="get_weather", func=get_weather, description="查询城市天气"),Tool(name="get_time", func=get_time, description="查询城市当前时间"),
]# 初始化 Agent
llm_cfg = {"base_url": "https://api.siliconflow.cn/v1","api_key": "sk-xx",
}
model = init_chat_model(model="Qwen/Qwen2.5-72B-Instruct", model_provider="openai", **llm_cfg
)
memory = MemorySaver()
agent_executor = create_react_agent(model, tools, checkpointer=memory)# Use the agent
config = {"configurable": {"thread_id": "abc123"}}input_message = {"role": "user","content": "成都现在几点,天气怎么样?",
}i = 0
for step in agent_executor.stream({"messages": [input_message]}, config, stream_mode="values"
):messages = step["messages"]while i < len(messages):message = messages[i]if isinstance(message, HumanMessage):print(f"Human: {message.content}")elif isinstance(message, AIMessage):print(f"AI: {message.content}")elif isinstance(message, ToolMessage):print(f"Tool: {message.name}, result: {message.content}")i += 1
5.总结
从本次函数调用这个例子来说,langchain框架确实好用,使用也比较简单,特别是对消息类型抽象为了:HumanMessage、AIMessage、ToolMessage,在项目落地过程中都是刚需。