在运行时,我们可能需要将值传递给工具,例如用户 ID,出于安全原因,该值应由应用程序逻辑设置,而不是由 LLM 控制。LLM 应该只管理其预期的参数。LangChain 工具使用Runnable接口,其中的方法invoke通过参数接受运行时信息RunnableConfig。在以下示例中,我们将设置一个代理,使用工具来管理用户喜爱的宠物(添加、读取和删除条目),同时通过应用程序逻辑修复用户 ID,并让聊天模型控制其他参数。
from typing import List
from langchain_core.tools import tool
from langchain_core.runnables.config import RunnableConfig
from langgraph.prebuilt import ToolNode
user_to_pets = {}
@tool
def update_favorite_pets(
# 注意:config 参数不需要添加到文档字符串中,因为我们不希望它包含在附加到 LLM 的函数签名中
pets: List[str],
config: RunnableConfig,
) -> None:
"""添加最喜欢的宠物列表。
参数:
pets: 要设置的最喜欢的宠物列表。
"""
user_id = config.get("configurable", {}).get("user_id")
user_to_pets[user_id] = pets
@tool
def delete_favorite_pets(config: RunnableConfig) -> None:
"""删除最喜欢的宠物列表。"""
user_id = config.get("configurable", {}).get("user_id")
if user_id in user_to_pets:
del user_to_pets[user_id]
@tool
def list_favorite_pets(config: RunnableConfig) -> None:
"""列出最喜欢的宠物(如果有)。"""
user_id = config.get("configurable", {}).get("user_id")
return ", ".join(user_to_pets.get(user_id, []))
tools = [update_favorite_pets, delete_favorite_pets, list_favorite_pets]
tool_node = ToolNode(tools)
from langgraph.graph import StateGraph, MessagesState
from langchain_ollama import ChatOllama
import base_conf
model_with_tools = ChatOllama(base_url=base_conf.base_url,
model=base_conf.model_name,
temperature=0).bind_tools(tools)
可以看到,要做到将config传入tools,只需要使用 RunnableConfig类型作为tools的入参即可。这个入参不会被LLM识别到,但是在tools调用的时候toolnode会把config传过去。
该代理将一些查询作为输入,然后反复调用工具,直到它拥有足够的信息来解决查询,是一个非常简单的流程,之前的教程中已经出现过很多次了。from typing import Literal
from langgraph.graph import StateGraph, MessagesState, START, END
def should_continue(state: MessagesState):
messages = state["messages"]
last_message = messages[-1]
if last_message.tool_calls:
return "tools"
return END
def call_model(state: MessagesState):
messages = state["messages"]
response = model_with_tools.invoke(messages)
return {"messages": [response]}
builder = StateGraph(MessagesState)
# Define the two nodes we will cycle between
builder.add_node("agent", call_model)
builder.add_node("tools", tool_node)
builder.add_edge(START, "agent")
builder.add_conditional_edges("agent", should_continue, ["tools", END])
builder.add_edge("tools", "agent")
graph = builder.compile()
from langchain_core.messages import HumanMessage
user_to_pets.clear() # Clear the state
print(f"运行前的用户信息: {user_to_pets}")
inputs = {"messages": [HumanMessage(content="我最喜欢的宠物是猫和狗")]}
for chunk in graph.stream(
inputs, {"configurable": {"user_id": "123"}}, stream_mode="values"
):
chunk["messages"][-1].pretty_print()
print(f"运行后的用户信息: {user_to_pets}")
运行前的用户信息: {}
================================ Human Message =================================
我最喜欢的宠物是猫和狗
================================== Ai Message ==================================
Tool Calls:
update_favorite_pets (a15a67f9-ab80-48e2-842a-586d0c00a8f1)
Call ID: a15a67f9-ab80-48e2-842a-586d0c00a8f1
Args:
pets: ['猫', '狗']
================================= Tool Message =================================
Name: update_favorite_pets
null
================================== Ai Message ==================================
我已经为您更新了最喜欢的宠物列表,现在您的最爱是猫和狗。您还需要其他帮助吗?
运行后的用户信息: {'123': ['猫', '狗']}
可以看到,已经获取到了{"user_id": "123"}的config信息!