https://langchain-ai.github.io/langgraph/tutorials/introduction/#part-4-human-in-the-loop
话说,AI不是任何时候的特别可靠的。人工智能技术出现以来,无法离开人工对信息,算法的干预。我们需要再AI智能体工作的过程中可控的调整和介入,那就要求langgraph这类框架具备人类交互相关的功能。
我们直接解析代码来的更清晰一点吧。LangGraph提供interrupt和Command两个接口来实现用户的交互。
- 实现这一功能的主要接口是
interrupt函数。在节点内部调用interrupt会暂停执行,并让用户输入内容。我们先添加一个工具,在工具节点中调用。
from langgraph.types import Command, interrupt
@tool
def human_assistance(query: str) -> str:
"""Request assistance from a human."""
human_response = interrupt({
"query": query})
return human_response["data"]
tools = [tool, human_assistance]
interrupt提供类似Python的input()功能,可以让用户在命令行中输入内容,humna_assistance工具被LLM调用的时候,LLM会把用户的问题转发到这里(query)。@tool装饰器告诉Graph这是一个工具,注意方法中的第一行,这是必填的docstring注释文本(也可以通过docstring参数传入human_assistance),LLM是根据这段文本来判断是否要调用这个工具,就是说每当用户对话中告诉AI,需要人类协助时,AI会调用这个工具,在命令行中请人类回答(通过interrupt方法)。
LangGraph需要持久层的记忆存储功能来支持人类用户的协助,能够依据用户反馈暂停和恢复执行。所以,memory还是配上:
memory = MemorySaver()
graph = graph_builder.compile(checkpointer=memory)
在对话聊天节点我们需要做点修改。AI对话返回的结果message,先看看返回的消息,如果返回的消息中,同时要用到两个工具(搜索和人类协助),则断言终止。这样做是为了防止恢复本节点运行时,又重复调用工具(interrupt设置时需要考虑到一些副作用)。
def chatbot(state: State):
message = llm_with_tools.invoke(state["messages"])
# Because we will be interrupting during tool execution,
# we disable parallel tool calling to avoid repeating any
# tool invocations when we resume.
assert len(message.tool_calls) <= 1
return {
"messages": [message]}
现在,我们硬编码提供一个用户提问:
user_input = "I need some expert guidance for building an AI agent. Could you request assistance for me?"
config = {
"configurable": {
"thread_id": "1"}}
events = graph.stream(
{
"messages": [{
"role": "user", "content": user_input}]},
config,
stream_mode="values",
)
for event in events:
if "messages" in event:
event["messages"][-1].pretty_print()
用户提出请AI帮我申请人工协助,这时,AI理解了用户的意思并查看工具箱里(tools)调用human_assistance工具。human_assistance会中断图的执行流(注意,不是中断整个应用程序)。输出的结果:
================================ Human Message ============================


2334

被折叠的 条评论
为什么被折叠?



