发布时间:2026-04-09 22:58:16编辑:123阅读(5)
LangGraph中多轮对话实现方法
将大模型接入到LangGraph工作流程中,并允许动态消息处理以及与模型的交互。
大模型应用都是接受消息列表作为输入,就像LangChain中的ChatModel,需要接收Message对象列表作为输入。这些消息有多种形式,例如HumanMessage(用户输入)或AIMessage(大模型响应)。这种消息格式其实就与我们之前介绍的StateGraph(dict)结构有一些区别。
因此对于消息序列格式的state,一种更简单的方法就是使用LangGraph预构建的add_messages函数,这个更高级的状态所实现的是:对于全新的消息,它会附加到现有列表,同时它也会正确处理现有消息的更新。
代码如下:
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph,START,END
from langgraph.graph.message import add_messages
from langchain_ollama import ChatOllama
class State(TypedDict):
messages: Annotated[list, add_messages]
graph_builder = StateGraph(State)
model = ChatOllama(
model="qwen3:8b",
temperature=0,
top_p=0.95,
)
def chat_bot(state: State):
response = model.invoke(state["messages"])
return {"messages": [response]}
# 添加节点
graph_builder.add_node("chat_bot", chat_bot)
# 添加边
graph_builder.add_edge(START, 'chat_bot')
graph_builder.add_edge( 'chat_bot', END)
graph = graph_builder.compile()
final_state = graph.invoke({"messages": ["你好,你是谁"]})
print(final_state['messages'][-1].content)
with open("graph4.png", "wb") as f:
f.write(graph.get_graph(xray=True).draw_mermaid_png())运行结果:
你好!我是通义千问,由通义实验室研发的超大规模语言模型。我能够帮助你回答问题、创作文字、编程、分析数据等等。如果你有任何需要帮助的地方,欢迎随时告诉我!😊
结构图:

这个图的基本逻辑是:第一个节点调用大模型并生成一个输出,该输出是一个AIMessage对象类型,然后,第二个节点直接将前一个节点的AIMessage提取为具体的JSON格式,完成JSON的解析。
langgraph多消息请求:
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph,START,END
from langgraph.graph.message import add_messages
from langchain_ollama import ChatOllama
from langchain_core.messages import AIMessage,HumanMessage
class State(TypedDict):
messages: Annotated[list, add_messages]
graph_builder = StateGraph(State)
model = ChatOllama(
model="qwen3:8b",
temperature=0,
top_p=0.95,
)
def chat_bot(state: State):
response = model.invoke(state["messages"])
return {"messages": [response]}
# 添加节点
graph_builder.add_node("chat_bot", chat_bot)
# 添加边
graph_builder.add_edge(START, 'chat_bot')
graph_builder.add_edge( 'chat_bot', END)
graph = graph_builder.compile()
messages_list = [
HumanMessage(content="你好,我叫张三,好久不见"),
AIMessage(content="你好呀,我是CC,一名乐于助人的AI助手,很高兴认识你"),
HumanMessage(content="你还记得我叫什么名字吗?")
]
final_state = graph.invoke({"messages": messages_list})
print(final_state['messages'][-1].content)
with open("graph4.png", "wb") as f:
f.write(graph.get_graph(xray=True).draw_mermaid_png())运行结果
当然记得!你叫张三,上次见面已经很久了,真是想念啊!最近过得怎么样呀?有什么我可以帮你的吗?
langgraph多轮对话输入请求
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph,START,END
from langgraph.graph.message import add_messages
from langchain_ollama import ChatOllama
from langchain_core.messages import AIMessage,HumanMessage
class State(TypedDict):
messages: Annotated[list, add_messages]
graph_builder = StateGraph(State)
model = ChatOllama(
model="qwen3:8b",
temperature=0,
top_p=0.95,
)
def chat_bot(state: State):
response = model.invoke(state["messages"])
return {"messages": [response]}
# 添加节点
graph_builder.add_node("chat_bot", chat_bot)
# 添加边
graph_builder.add_edge(START, 'chat_bot')
graph_builder.add_edge( 'chat_bot', END)
graph = graph_builder.compile()
messages_list = [
]
while True:
try:
user_input = input("用户提问:")
if user_input.lower() in ['exit']:
print("退出,下次再见!")
break
messages_list.append(HumanMessage(content=user_input))
final_state = graph.invoke({"messages": messages_list})
print("小智:", final_state["messages"][-1].content)
messages_list.append(final_state["messages"][-1])
messages_list = messages_list[-50:]
except:
break运行结果:
用户提问:我是张三
小智: 哦,张三啊!很高兴认识你!今天有什么想聊的吗?或者需要帮忙的?我在这里陪着你呢~
用户提问:你能做什么
小智: 我是一个大型语言模型,可以帮你做很多事情!以下是一些我擅长的领域:
1. **知识问答**:解答各种学科、文化、科技等方面的问题。
2. **创作辅助**:帮你写故事、诗歌、剧本、邮件、文案等。
3. **逻辑推理**:解决数学题、编程问题、谜题等需要逻辑思考的任务。
4. **多语言翻译**:支持中英日韩等多国语言的互译。
5. **学习辅导**:提供学习建议、知识点总结、考试复习等帮助。
6. **日常对话**:陪你聊天、分享观点、讨论感兴趣的话题。
7. **代码生成**:根据需求生成或解释编程代码(如Python、Java等)。
8. **娱乐互动**:玩文字游戏、猜谜、讲故事等。
如果你有具体需求,可以告诉我,我会尽力帮你! 😊
用户提问:我叫什么
小智: 你叫张三!😊 之前你已经告诉我了,我这边都记着呢~ 有什么需要帮忙的吗?或者想聊点什么?
用户提问:exit
退出,下次再见!
借助MemorySaver高效搭建多轮对话机器人
MemorySaver的核心功能
1 短期记忆(线程级记忆)MemorySaver为每个thread_id保存和恢复对话状态(State),实现在同一会话中历史上下文记忆。
2 状态持久化 在每个节点运行后,State会自动存储;再次调用时,如果使用相同的thread_id,MemorySaver会恢复此前保存的状态,无需手动传递历史信息。
3 多会话隔离 通过不同的thread_id可实现会话隔离,允许多个用户并发交互且各自的对话互不干扰。
4 图状态快照与恢复 不仅包括对话历史,还保存整个工作流状态,可用于错误恢复、时间旅行、断点续跑、Human-in-the-loop等高级场景。
示例代码:
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph,START,END
from langgraph.graph.message import add_messages
from langchain_ollama import ChatOllama
from langgraph.checkpoint.memory import MemorySaver
# 定义状态类(会自动合并messages)
class State(TypedDict):
messages: Annotated[list, add_messages]
# 初始化模型
model = ChatOllama(
model="qwen3:8b",
temperature=0,
top_p=0.95,
)
# 定义聊天节点
def chatbot(state: State) -> State:
reply = model.invoke(state["messages"])
return {'messages': [reply]}
# 构建带MemorySaver的图
builder = StateGraph(State)
builder.add_node('chatbot', chatbot)
builder.add_edge(START, 'chatbot')
builder.add_edge('chatbot', END)
memory = MemorySaver()
graph = builder.compile(checkpointer=memory)
# 运行多轮对话,使用相同thread_id实现记忆
thread_config = {"configurable":{"thread_id":"session_10"}}
# 第一轮对话
state1 = graph.invoke({"messages":[{"role":"user", "content":"我叫张三"}]}, config=thread_config)
print(state1["messages"][-1].content)
# 第二轮对话
state2 = graph.invoke({"messages":[{"role":"user", "content":"我叫什么"}]}, config=thread_config)
print(state2["messages"][-1].content)
# 使用不同的thread_id,会开启全新对话
state3 = graph.invoke({"messages":[{"role":"user", "content":"我叫什么"}]},
config={"configurable":{"thread_id":"session_2"}})
print(state3["messages"][-1].content)
# 查看记忆
latest = graph.get_state(thread_config)
print(latest.values['messages']) # 包含全部轮次对话运行结果:
你好,张三!很高兴认识你。有什么我可以帮你的吗?是想讨论某个话题,还是需要解决某个问题?随时告诉我哦! 😊
你叫张三!😊 有什么我可以帮你的吗?
你好!我是通义千问,你可以叫我Qwen。有什么问题或需要帮助的地方吗?😊
[HumanMessage(content='我叫张三', additional_kwargs={}, response_metadata={}, id='e0301ee9-3630-41d5-a177-0ebb241bc923'), AIMessage(content='你好,张三!很高兴认识你。有什么我可以帮你的吗?是想讨论某个话题,还是需要解决某个问题?随时告诉我哦! 😊', additional_kwargs={}, response_metadata={'model': 'qwen3:8b', 'created_at': '2026-04-09T14:55:36.262431513Z', 'done': True, 'done_reason': 'stop', 'total_duration': 7435033223, 'load_duration': 3240815798, 'prompt_eval_count': 14, 'prompt_eval_duration': 37374857, 'eval_count': 169, 'eval_duration': 4069471189, 'logprobs': None, 'model_name': 'qwen3:8b', 'model_provider': 'ollama'}, id='lc_run--019d72bd-bd4c-79a1-bf8c-2abd404751c3-0', tool_calls=[], invalid_tool_calls=[], usage_metadata={'input_tokens': 14, 'output_tokens': 169, 'total_tokens': 183}), HumanMessage(content='我叫什么', additional_kwargs={}, response_metadata={}, id='df1a725d-ddbc-4d1b-8ca1-eb0850d1f26c'), AIMessage(content='你叫张三!😊 有什么我可以帮你的吗?', additional_kwargs={}, response_metadata={'model': 'qwen3:8b', 'created_at': '2026-04-09T14:55:41.274219069Z', 'done': True, 'done_reason': 'stop', 'total_duration': 5006213719, 'load_duration': 82059554, 'prompt_eval_count': 60, 'prompt_eval_duration': 50574398, 'eval_count': 201, 'eval_duration': 4812387113, 'logprobs': None, 'model_name': 'qwen3:8b', 'model_provider': 'ollama'}, id='lc_run--019d72bd-d824-77b2-84c4-4e7b4c34b6f3-0', tool_calls=[], invalid_tool_calls=[], usage_metadata={'input_tokens': 60, 'output_tokens': 201, 'total_tokens': 261})]
下一篇: 没有了
52474
52398
42499
39409
33845
30808
29568
24482
24341
22711
5°
46°
77°
267°
277°
279°
327°
269°
407°
389°