一、schema 数据结构
1.定义全局共享数据的容器
2.可以自定义输入和输出的内容和结构
from langgraph.graph import StateGraph, START, END
from typing_extensions import TypedDict
#定义输入Schema
class InputState(TypedDict):
question: str
# 定义输出Schema
class OutputState(TypedDict):
answer: str
# 结合输入和输出,定义总体模式
class OverallState(InputState, OutputState):
pass
# 定义处理输入并生成答案的节点
def answer_node(state: InputState):
return {"answer": "hello!", "question": state["question"]}
# 使用指定的输入和输出模式构建图形
builder = StateGraph(OverallState, input_schema=InputState, output_schema=OutputState)
builder.add_node(answer_node)
builder.add_edge(START, "answer_node")
builder.add_edge("answer_node", END)
graph = builder.compile()
print(graph.invoke({"question": "hi"}))
二、reducer消息归约器
1.消息的追加存储
2.后续只需要把新的消息加入字段
下面两种归约器等价,
在进行消息返回的时候,一定要指定明确是那个角色的消息
# #使用内置归约器
# class BuiltInReducerState(TypedDict):
# messages: Annotated[list[AnyMessage], add_messages]
# extra_field: int
# #使用预构建状态,已经包含内置归约器
# class PreBuildState(MessagesState):
# extra_field: int
消息调用示例,两种格式,注意是列表格式
# 1
conversation.invoke({
"messages": [
("user", "你好"),
("assistant", "你好!我是你的 AI 助手,有什么我可以帮你的吗?")
]
})
# 2
input_data = {
"messages": [
SystemMessage(content="你是一个专业的翻译官"),
HumanMessage(content="Hello"),
AIMessage(content="你好"),
HumanMessage(content="How are you?")
]
}
print(conversation.invoke(input_data))
规约器使用示例,消息的叠加展示
from typing import TypedDict, Annotated, Sequence
from langchain_core.messages import HumanMessage, AIMessage, BaseMessage, SystemMessage, AnyMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END, add_messages, MessagesState
import operator
import os
from agent01.app.utils.get_llm_model import get_llm_model
model = get_llm_model()
# ================== 类型定义 ==================
# #使用内置归约器
# class BuiltInReducerState(TypedDict):
# messages: Annotated[list[AnyMessage], add_messages]
# extra_field: int
# #使用预构建状态,已经包含内置归约器
class PreBuildState(MessagesState):
extra_field: int
# ================== 节点函数优化 ==================
def handle_user_input(state: PreBuildState):
"""处理用户输入节点"""
try:
print(f"handle_user_input_node state:{state}")
user_input = input("\n用户输入(输入'退出'结束): ").strip()
if user_input.lower() == "退出":
print("正在结束对话...")
# 保留历史记录并追加新消息
return {"messages": [HumanMessage(content=user_input)]}
except KeyboardInterrupt:
return END
def generate_ai_response(state: PreBuildState):
"""生成AI响应节点(增加错误处理)"""
try:
print(f"generate_ai_response_node state:{state}")
# 使用最近6条消息保持上下文连贯性
recent_history = state["messages"][-6:]
response = model.invoke(recent_history)
# print("模型答复:",response)
return {"messages": [response]}
except Exception as e:
error_msg = f"系统暂时无法响应,请稍后再试(错误代码:{str(e)[:30]})"
return {"messages": [AIMessage(content=error_msg)]}
# ================== 对话图构建 ==================
# 1. 增加一个路由函数,决定是继续还是结束
def should_continue(state: PreBuildState):
last_message = state["messages"][-1].content
if last_message == "退出":
return END
return "ai_response"
# 2. 调整图的构建逻辑
builder = StateGraph(PreBuildState)
builder.add_node("user_input", handle_user_input)
builder.add_node("ai_response", generate_ai_response)
builder.set_entry_point("user_input")
# 使用条件边:用户输入后,判断是去 AI 还是结束
builder.add_conditional_edges(
"user_input",
should_continue
)
# AI 回答完后,跳回用户输入,等待下一句
builder.add_edge("ai_response", "user_input")
conversation = builder.compile()
# 3. 外部只需要调用一次 invoke
# 系统消息作为初始状态传入,之后它会一直留在 state["messages"] 里
final_result = conversation.invoke({
"messages": [("system", "你是一个对话助手")]
})
print(final_result)
print("最终对话结束。")
aa