LangGraph中MessageGraph源码功能解析

  1. LangGraph中State状态模式及相关操作
    • 状态定义与图构建
      • 知识点:使用 TypedDict 定义状态,通过StateGraph类实例化图,构建对话交互式程序时添加节点、设置启动点和边并编译图。
      • 代码对应
# 定义图的状态模式
class State(TypedDict):
    messages: Annotated[List[str], operator.add]
# 创建图的实例
builder = StateGraph(State)

这里定义了State类型,其中messages使用Annotatedoperator.add表示消息列表的更新方式为追加 。接着创建StateGraph实例builder,为后续构建图结构做准备。

  • 节点功能实现
  • 知识点chat_with_model节点接收用户输入,调用大模型实例的invoke方法生成响应并更新共享状态;convert_messages节点对上一节点的模型回复进行数据提取和格式化处理,转化为JSON格式输出。
  • 代码对应
# 实例化大模型
llm = ChatOpenAI(model='gpt-40')
# 定义处理模型对话的节点函数
def chat_with_model(state):
    print(state)
    print("-----")
    messages = state['messages']
    response = llm.invoke(messages)
    return {"messages": [response]}
# 定义数据提取节点函数
def convert_messages(state):
    EXTRACTION_PROMPT = """
    You are a data extraction specialist tasked with retrieving key information from the provided text. 
    Extract such information for the provided text and output it in JSON format. Outline the key data points you extract.
    """
    print(state)
    print("-------")
    messages = state['messages'][-1]
    messages = [
        SystemMessage(content=EXTRACTION_PROMPT),
        HumanMessage(content=state['messages'][-1].content)
    ]
    response = llm.invoke(messages)
    return {"messages": [response]}

实例化ChatOpenAI模型llmchat_with_model函数从输入的state中获取messages,调用llm.invoke生成响应,再将响应包装成新的messages返回 。convert_messages函数构建特定的提示信息,结合上一节点的回复,调用llm.invoke进行数据提取和格式化,最后返回处理后的消息。

  • 消息流转与状态更新
  • 知识点:消息在图中按节点顺序流转,每次流转更新共享状态中的消息列表,通过operator.add实现消息追加,运行图逻辑时需按state定义规范传递数据。
  • 代码对应:在添加节点、边、设置启动点及编译图的过程中体现消息流转与状态更新。
# 添加节点
builder.add_node("chat_with_model", chat_with_model)
builder.add_node("convert_messages", convert_messages)
# 设置启动点
builder.set_entry_point("chat_with_model")
# 添加边
builder.add_edge("chat_with_model", "convert_messages")
builder.add_edge("convert_messages", END)
# 编译图
graph = builder.compile()
# 运行图,输入问题
query = "你好,请你介绍一下你自己"
input_message = {"messages": [HumanMessage(content=query)]}
result = graph.invoke(input_message)
print(result)

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

在这里插入图片描述

添加chat_with_modelconvert_messages节点到图中 ,设置chat_with_model为启动点,定义消息从chat_with_modelconvert_messages再到END的流转路径,编译图后传入问题运行图逻辑,在这个过程中消息不断流转并更新状态。

  1. MessageGraph源码功能解析
  • 继承关系与初始化
  • 知识点MessageGraphStateGraph的子类,使用Annotated[list[AnyMessage], add_messages]初始化基类,状态由消息列表组成,通过add_messages函数管理消息列表更新。
  • 代码对应:在MessageGraph相关代码中体现继承和初始化关系。
from langgraph.graph.message import MessageGraph
class MessageGraph(StateGraph):
    def __init__(self) -> None:
        super().__init__(Annotated[list[AnyMessage], add_messages])

MessageGraph继承自StateGraph,在__init__方法中调用父类的初始化方法,传入Annotated[list[AnyMessage], add_messages],表明状态由消息列表组成且用add_messages管理更新。

  • add_messages函数机制
  • 知识点add_messages函数合并两个消息列表,按ID更新现有消息,默认状态为“仅附加”,新消息与现有消息ID相同则替换,否则追加。
  • 代码对应:在add_messages函数定义中明确其功能逻辑。
def add_messages(left: Messages, right: Messages) -> Messages:
    if not isinstance(left, list):
        left = [left]
    if not isinstance(right, list):
        right = [right]
    left = [message_chunk_to_message(m) for m in convert_to_messages(left)]
    right = [message_chunk_to_message(m) for m in convert_to_messages(right)]
    for m in left:
        if m.id is None:
            m.id = str(uuid.uuid4())
    for m in right:
        if m.id is None:
            m.id = str(uuid.uuid4())
    left_idx_by_id = {m.id: i for i, m in enumerate(left)}
    merged = left.copy()
    ids_to_remove = set()
    for m in right:
        if (existing_idx := left_idx_by_id.get(m.id)) is not None:
            if isinstance(m, RemoveMessage):
                ids_to_remove.add(m.id)
            else:
                merged[existing_idx] = m
        else:
            if isinstance(m, RemoveMessage):
                raise ValueError(
                    f"Attempting to delete a message with an ID that doesn't exist ({m.id})"
                )
            merged.append(m)
    merged = [m for m in merged if m.id not in ids_to_remove]
    return merged

函数先对输入的消息列表进行类型和格式处理,为无ID的消息生成ID,然后根据消息ID合并两个列表,存在相同ID时按规则替换或删除,最后返回合并后的消息列表。在这里插入图片描述
在这里插入图片描述

  • 消息图构建与操作示例
  • 知识点:可单独构建MessageGraph,添加节点并定义功能,设置启动点和终止点,编译后通过invoke方法传入用户问题实现交互,消息会生成唯一ID。
  • 代码对应
# 创建MessageGraph实例
builder = MessageGraph()
# 添加节点
builder.add_node("chatbot", lambda state: [("assistant", "你好,最帅气的人!")])
# 设置启动点和终止点
builder.set_entry_point("chatbot")
builder.set_finish_point("chatbot")
# 编译图
graph = builder.compile()
# 运行图,输入问题
query = "你好,请你介绍一下你自己"
input_message = [("user", query)]
result = graph.invoke(input_message)
print(result)

在这里插入图片描述

创建MessageGraph实例builder,添加chatbot节点,设置启动点和终止点为chatbot,编译图后传入问题运行,展示了MessageGraph的构建和交互过程。

  1. 构建对话交互式聊天机器人
  • 代码实现流程

在这里插入图片描述

在这里插入图片描述
知识点:理解state的定义模式和消息传递机制是构建应用的关键,高阶功能依赖于state的管理和使用。整个代码中state贯穿始终,节点函数通过操作state中的messages实现功能,消息传递在节点间进行,体现了state管理和消息传递的重要性。

  1. LangSmith基础使用入门
  • 工具作用
  • 知识点:LangSmith为基于大语言模型构建的应用程序提供全面的监控、调试和可观察性支持,能跟踪运行状态和结果。
  • 代码对应
import langsmith
from langsmith.tracing import start_trace, end_trace
# 启动LangSmith追踪
start_trace(project="my_project")
# 执行对话交互程序相关代码(这里简化,仅示意)
query = "你好,请你介绍一下你自己"
input_message = {"messages": [HumanMessage(content=query)]}
result = graph.invoke(input_message)
# 结束LangSmith追踪
end_trace()

通过start_trace启动追踪,在执行对话交互代码前后分别调用start_traceend_trace,可记录和观察应用程序在这段代码执行过程中的各种信息。

  • 知识点:在构建复杂AI Agent应用程序时,用于观察和调试中间交互流程,通过Web可视化页面了解节点运行情况。
  • 代码对应:在实际复杂项目中,结合上述代码,在多个关键节点前后添加追踪代码,在LangSmith的Web可视化页面查看每个节点的输入、输出、执行时间等信息,辅助调试和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值