目录

代码实操·下

1.SimpleBot

2.MemoryBot

3.ReActAgent

4.AssistantGraph

5.RAG_Agent


如果足够勇敢,应该继续扛起问题往前走,直到因果成熟自动脱落,人对问题的解决方式,不是试图找到答案,而是背负到可以解决的那一天。                

                                                                                                                        —— 25.10.19

代码实操·下

1.SimpleBot

os:os 是 Python 标准库的内置模块,无需额外安装,导入即可使用(代码中 import os 就是导入该模块)。它封装了不同操作系统(Windows、Linux、macOS 等)的底层接口,让开发者可以用统一的代码实现跨平台的系统操作,无需针对不同系统编写不同逻辑。

typing:Python 标准库模块,提供类型提示工具,用于指定变量、函数参数 / 返回值的类型,支持静态类型检查(如 IDE 提示、mypy 校验),增强代码可读性和健壮性。

TypedDict:typing模块中的类型工具,用于定义结构化字典类型,明确指定字典中每个键对应的 value 类型。例如代码中通过它约束AgentState必须包含message: str字段,确保字典结构可预期。

List:在 Python 的 typing 模块中,List 是用于类型提示的泛型工具,用于明确指定 “列表(list)中元素的类型”。

langgraph.graph:LangGraph 框架的核心模块,包含构建状态化工作流的关键类(如StateGraph),用于定义节点(Nodes)、边(Edges)、状态(State)及流转逻辑,是搭建智能体工作流的基础。

langchain_core: LangChain 的核心模块,包含了构建 LangChain 应用的基础组件和抽象接口。它定义了消息处理、提示模板、链(Chain)、工具调用等核心功能的底层逻辑,是整个框架的 "骨架"。几乎所有 LangChain 的高级功能都依赖于langchain_core提供的基础定义。

langchain_core.messages.HumanMessage:HumanMessage 是 langchain_core.messages 模块中定义的人类用户消息类型,用于在对话流程中明确标记 "来自用户的输入"。

langchain_openai:LangChain 专门用于集成 OpenAI 服务的模块,封装了 OpenAI 的 API 调用逻辑(如聊天模型、嵌入模型、函数调用等),让开发者可以在 LangChain 框架中便捷地使用 OpenAI 的模型(如 GPT-3.5、GPT-4 等)。

ChatOpenAI:langchain_openai 模块中定义的OpenAI 聊天模型类,用于实例化 OpenAI 的对话模型(如gpt-3.5-turbogpt-4),是连接 LangChain 与 OpenAI 聊天接口的核心组件。

StateGraph:LangGraph 框架的核心类,用于定义和构建基于状态的工作流图(Stateful Workflow Graph)。它是组织节点(Nodes)、状态(State)和流转规则(Edges)的 “脚手架”,能够将分散的处理逻辑(节点)串联成一个可执行的、状态可控的完整流程。

START:LangGraph 内置的常量,用于标识 “工作流的第一个执行节点” 的逻辑起点(是框架层面的 “流程入口符号”,而非用户自定义的变量)。

END:LangGraph 内置的常量,用于标识 “工作流的最终停止位置” 的逻辑终点(是框架层面的 “流程出口符号”,而非用户自定义的变量)。

os.getenv():Python os 模块的核心函数,用于安全读取操作系统的环境变量值,核心价值是避免将敏感信息(如 API 密钥)硬编码到代码中,同时支持不同环境(开发 / 测试 / 生产)灵活切换配置。

参数名 类型 默认值 描述
key str 必填参数,要读取的环境变量名称(如你代码中的 "DASHSCOPE_API_KEY")。
default 任意类型 None 可选参数,当 key 对应的环境变量不存在时,返回的默认值(可设为字符串、数字等)。

messages:List[HumanMessage](人类消息列表,定义在AgentState中),存储对话流程中的 “用户消息” 集合。

qw_model:ChatOpenAI实例,配置好的 “通义千问” 大模型客户端。

ChatOpenAI():初始化 OpenAI 聊天模型(如 GPT-3.5、GPT-4)的实例,用于调用 OpenAI 的对话 API。

参数名 类型 默认值 描述
model_name str "gpt-3.5-turbo" 模型名称(如"gpt-4""gpt-3.5-turbo-1106"
temperature float 0.7 输出随机性(0-1,0 为确定性输出,1 为最大随机性)
api_key str None OpenAI API 密钥(默认从环境变量OPENAI_API_KEY读取)
base_url str None API 基础地址(默认"https://api.openai.com/v1",可用于代理或自定义服务)
max_tokens int None 生成内容的最大 token 数(默认由模型限制决定)
timeout int None API 调用超时时间(秒)
streaming bool False 是否启用流式输出(实时返回部分结果)
default_headers dict None 额外的 HTTP 请求头

response:模型返回的消息对象,AI 模型对用户消息的回复结果。

state:state 是 AgentState 类型的实例(AgentState 是一个 TypedDict,定义了状态的结构)。

state["messages"]:List[HumanMessage](人类消息列表)。存储当前对话状态中的 “用户输入消息集合”,是连接用户输入与模型处理的核心数据载体。

.invoke():执行一次调用,传入输入并返回处理结果(同步方法)。

参数名 类型 默认值 描述
input 多样(如list[Message]strdict 输入内容(聊天模型通常接受消息列表,如[HumanMessage(...)]
config dict None 调用配置(如{"tags": ["tag1"]}用于日志标记,"max_concurrency"控制并发)
**kwargs 多样 额外参数(如部分模型支持stop列表,指定终止生成的字符串)

graph:StateGraph实例,定义工作流的 “状态图” 对象。

StateGraph():创建一个状态图(有向图),用于定义多步骤工作流(如对话流程、工具调用逻辑),支持节点状态流转。

参数名 类型 默认值 描述
name str None 状态图的名称(用于标识和日志)

.add_node():向状态图中添加一个节点(节点对应一个处理函数,负责处理当前状态并返回新状态)。

参数名 类型 默认值 描述
name str 节点唯一名称(用于标识节点)
func Callable 节点处理函数(输入为当前状态state,返回更新后的状态或流转指令)

.add_edge():定义节点之间的边(流转关系),指定从一个节点到另一个节点的跳转规则。

参数名 类型 默认值 描述
start_node str 起始节点名称(边的起点)
end_node str 或 Callable 目标节点名称(边的终点);若为函数,则根据当前状态动态返回目标节点

agent:StateGraph编译后的可执行对象,可直接调用的 “智能体” 实例,用于执行graph定义的工作流。

.compile():编译状态图,生成可执行的Runnable对象(用于运行工作流)。

参数名 类型 默认值 描述
config dict None 编译配置(如{"verbose": True}开启详细日志)

Ipython:IPython 是一个增强的交互式 Python 环境(Interactive Python 的缩写),它在标准 Python 解释器的基础上增加了许多功能,比如:

  • 支持语法高亮、自动补全、命令历史记录;
  • 可以直接运行 shell 命令(如 !ls);
  • 支持交互式可视化(如图表、图像显示);
  • 提供 “魔法命令”(如 %run%matplotlib)简化工作流。

它是 Jupyter Notebook/Lab 的核心依赖,广泛用于数据分析、机器学习等交互式开发场景。

Ipython.display:是 IPython 内置的一个模块,专门用于在交互式环境(如 Jupyter Notebook)中显示各种类型的内容,包括但不限于:

  • 文本、HTML、Markdown;
  • 图像(PNG、JPG 等);
  • 音频、视频;
  • 复杂对象(如 Pandas DataFrame、Matplotlib 图表)。

它提供了一系列工具函数和类,让开发者可以方便地在交互式界面中展示多样化的输出。

Image:IPython.display 模块中的一个,用于创建 “可显示的图像对象”,主要作用是:

  • 加载图像资源(支持本地文件路径、网络 URL、二进制图像数据);
  • 配置图像的显示参数(如宽度、高度、格式);
  • 配合 display 函数在 Jupyter 等环境中直接显示图像。

display:IPython.display 模块中的一个函数,用于在交互式环境中显示对象。它的核心作用是:

  • 接收各种类型的对象(如 Image 对象、字符串、HTML 片段、Pandas 表格等);
  • 根据对象类型自动选择合适的方式渲染并展示(例如,对 Image 对象会显示图片,对 HTML 字符串会解析为网页元素)。

display():在交互式环境(如 Jupyter Notebook)中显示对象(图像、HTML、文本等)。

参数名 类型 默认值 描述
obj 多样(如ImagestrHTML 要显示的对象
** kwargs 多样 额外显示参数(如clear=True清除之前的输出)

Image():创建图像对象(IPython 中用于显示图像,PIL 中用于图像处理)。

参数名(IPython.display.Image) 类型 默认值 描述
data bytes None 图像二进制数据
filename str None 图像文件路径(优先于data
format str None 图像格式(如"png""jpg",自动从文件推断)
width int None 显示宽度(像素)
height int None 显示高度(像素)

.get_graph():获取状态图的内部结构(通常为Graph对象,包含节点和边的元数据)。

.draw_mermaid_png():将图结构转换为 Mermaid 语法,并生成 PNG 图像(需安装mermaid-cli)。

参数名 类型 默认值 描述
path str None 图像保存路径(如"graph.png",不指定则返回二进制数据)
** kwargs 多样 Mermaid 绘图参数(如"theme": "dark"设置主题)
import os
from typing import TypedDict, List
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, START, END
# from dotenv import load_dotenv

class AgentState(TypedDict):
    """Agent state."""

    messages: List[HumanMessage]

# qwen模型
qw_model = ChatOpenAI(
    model="qwen-max",           # 通义千问
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

def process(state: AgentState)-> AgentState:
    '''
    Process the agent state
    :param state:
    :return:
    '''
    response = qw_model.invoke(state["messages"])
    print(f"\nAI: {response.content}")
    return state

graph = StateGraph(AgentState)
graph.add_node("process", process)
graph.add_edge(START, "process")
graph.add_edge("process", END)

agent = graph.compile()

# Optional: Display the graph (requires IPython)
from IPython.display import Image, display

display(Image(agent.get_graph().draw_mermaid_png()))

user_input:str(字符串),存储用户输入的文本内容,是对话的 “用户输入源”。

input():Python 内置函数,核心作用是从标准输入(通常是键盘)获取用户输入,并将输入内容以字符串形式返回。

参数名 类型 默认值 描述
prompt str None 可选参数,用于显示给用户的提示文本。若提供该参数,会先在控制台打印提示文本,再等待用户输入;若不提供,则直接等待用户输入(无提示)。
user_input = input("User:")
while user_input != "exit":
    state = agent.invoke({"messages": [HumanMessage(content=user_input)]})
    user_input = input("User:")

用户输入:

1.hello

2.introduce yourself


2.MemoryBot

os:os 是 Python 标准库的内置模块,无需额外安装,导入即可使用(代码中 import os 就是导入该模块)。它封装了不同操作系统(Windows、Linux、macOS 等)的底层接口,让开发者可以用统一的代码实现跨平台的系统操作,无需针对不同系统编写不同逻辑。

typing:Python 标准库模块,提供类型提示工具,用于指定变量、函数参数 / 返回值的类型,支持静态类型检查(如 IDE 提示、mypy 校验),增强代码可读性和健壮性。

TypedDict:typing模块中的类型工具,用于定义结构化字典类型,明确指定字典中每个键对应的 value 类型。例如代码中通过它约束AgentState必须包含message: str字段,确保字典结构可预期。

List:在 Python 的 typing 模块中,List 是用于类型提示的泛型工具,用于明确指定 “列表(list)中元素的类型”。

Union:Python 标准库 typing 模块中的类型提示工具,用于明确标注 “某个变量 / 参数 / 返回值可以是多个指定类型中的任意一种”,核心作用是提升代码的可读性和类型检查的准确性(尤其在大型项目或多人协作中)。

langgraph.graph:LangGraph 框架的核心模块,包含构建状态化工作流的关键类(如StateGraph),用于定义节点(Nodes)、边(Edges)、状态(State)及流转逻辑,是搭建智能体工作流的基础。

langchain_core: LangChain 的核心模块,包含了构建 LangChain 应用的基础组件和抽象接口。它定义了消息处理、提示模板、链(Chain)、工具调用等核心功能的底层逻辑,是整个框架的 "骨架"。几乎所有 LangChain 的高级功能都依赖于langchain_core提供的基础定义。

langchain_core.messages.AIMessage:LangChain 核心模块 langchain_core.messages 中定义的AI 消息类型类,用于在对话流程中明确标记 “由 AI 模型生成的回复内容”,是对话状态管理的核心载体之一(与你之前了解的 HumanMessage 对应:HumanMessage 是用户输入,AIMessage 是 AI 输出)。

langchain_core.messages.HumanMessage:HumanMessage 是 langchain_core.messages 模块中定义的人类用户消息类型,用于在对话流程中明确标记 "来自用户的输入"。

属性名 类型 描述
content str AI 回复的核心文本内容(最常用属性,如 ai_msg.content 即可获取回复文本)。
additional_kwargs dict 额外元数据(如模型名称、生成时间戳、token 消耗等,可选)。
tool_calls List[ToolCall] AI 触发的工具调用信息(若 AI 需要调用工具,会在此处存储工具名称、参数等,如调用搜索工具时的关键词)。
id str 消息唯一标识(自动生成,用于区分不同消息)。

langchain_openai:LangChain 专门用于集成 OpenAI 服务的模块,封装了 OpenAI 的 API 调用逻辑(如聊天模型、嵌入模型、函数调用等),让开发者可以在 LangChain 框架中便捷地使用 OpenAI 的模型(如 GPT-3.5、GPT-4 等)。

ChatOpenAI:langchain_openai 模块中定义的OpenAI 聊天模型类,用于实例化 OpenAI 的对话模型(如gpt-3.5-turbogpt-4),是连接 LangChain 与 OpenAI 聊天接口的核心组件。

StateGraph:LangGraph 框架的核心类,用于定义和构建基于状态的工作流图(Stateful Workflow Graph)。它是组织节点(Nodes)、状态(State)和流转规则(Edges)的 “脚手架”,能够将分散的处理逻辑(节点)串联成一个可执行的、状态可控的完整流程。

START:LangGraph 内置的常量,用于标识 “工作流的第一个执行节点” 的逻辑起点(是框架层面的 “流程入口符号”,而非用户自定义的变量)。

END:LangGraph 内置的常量,用于标识 “工作流的最终停止位置” 的逻辑终点(是框架层面的 “流程出口符号”,而非用户自定义的变量)。

messages:List[HumanMessage](人类消息列表,定义在AgentState中),存储对话流程中的 “用户消息” 集合。

messages_AI:专门用于存储 AI 模型生成的回复消息集合,是对话状态中 “AI 输出” 的独立载体,与 “用户输入”(HumanMessage)形成明确区分。

字段名 存储内容 优势 适用场景
messages 用户消息(HumanMessage)+ AI 消息(AIMessage 无需拆分,直接作为 “对话历史” 传给模型 多轮对话中需让模型基于完整历史上下文生成回复
messages_AI 仅 AI 消息(AIMessage 单独管理 AI 输出,无需筛选即可获取历史回复 需要单独统计、回溯或复用 AI 回复的场景(如生成总结)

response:模型返回的消息对象,AI 模型对用户消息的回复结果。

qw_model:ChatOpenAI实例,配置好的 “通义千问” 大模型客户端。

.invoke():执行一次调用,传入输入并返回处理结果(同步方法)。

参数名 类型 默认值 描述
input 多样(如list[Message]strdict 输入内容(聊天模型通常接受消息列表,如[HumanMessage(...)]
config dict None 调用配置(如{"tags": ["tag1"]}用于日志标记,"max_concurrency"控制并发)
**kwargs 多样 额外参数(如部分模型支持stop列表,指定终止生成的字符串)

ChatOpenAI():初始化 OpenAI 聊天模型(如 GPT-3.5、GPT-4)的实例,用于调用 OpenAI 的对话 API。

参数名 类型 默认值 描述
model_name str "gpt-3.5-turbo" 模型名称(如"gpt-4""gpt-3.5-turbo-1106"
temperature float 0.7 输出随机性(0-1,0 为确定性输出,1 为最大随机性)
api_key str None OpenAI API 密钥(默认从环境变量OPENAI_API_KEY读取)
base_url str None API 基础地址(默认"https://api.openai.com/v1",可用于代理或自定义服务)
max_tokens int None 生成内容的最大 token 数(默认由模型限制决定)
timeout int None API 调用超时时间(秒)
streaming bool False 是否启用流式输出(实时返回部分结果)
default_headers dict None 额外的 HTTP 请求头

state:state 是 AgentState 类型的实例(AgentState 是一个 TypedDict,定义了状态的结构)。

state["messages"]:List[HumanMessage](人类消息列表)。存储当前对话状态中的 “用户输入消息集合”,是连接用户输入与模型处理的核心数据载体。

graph:StateGraph实例,定义工作流的 “状态图” 对象。

StateGraph():创建一个状态图(有向图),用于定义多步骤工作流(如对话流程、工具调用逻辑),支持节点状态流转。

参数名 类型 默认值 描述
name str None 状态图的名称(用于标识和日志)

.add_node():向状态图中添加一个节点(节点对应一个处理函数,负责处理当前状态并返回新状态)。

参数名 类型 默认值 描述
name str 节点唯一名称(用于标识节点)
func Callable 节点处理函数(输入为当前状态state,返回更新后的状态或流转指令)

.add_edge():定义节点之间的边(流转关系),指定从一个节点到另一个节点的跳转规则。

参数名 类型 默认值 描述
start_node str 起始节点名称(边的起点)
end_node str 或 Callable 目标节点名称(边的终点);若为函数,则根据当前状态动态返回目标节点

agent:StateGraph编译后的可执行对象,可直接调用的 “智能体” 实例,用于执行graph定义的工作流。

.compile():编译状态图,生成可执行的Runnable对象(用于运行工作流)。

参数名 类型 默认值 描述
config dict None 编译配置(如{"verbose": True}开启详细日志)

Ipython:IPython 是一个增强的交互式 Python 环境(Interactive Python 的缩写),它在标准 Python 解释器的基础上增加了许多功能,比如:

  • 支持语法高亮、自动补全、命令历史记录;
  • 可以直接运行 shell 命令(如 !ls);
  • 支持交互式可视化(如图表、图像显示);
  • 提供 “魔法命令”(如 %run%matplotlib)简化工作流。

它是 Jupyter Notebook/Lab 的核心依赖,广泛用于数据分析、机器学习等交互式开发场景。

Ipython.display:是 IPython 内置的一个模块,专门用于在交互式环境(如 Jupyter Notebook)中显示各种类型的内容,包括但不限于:

  • 文本、HTML、Markdown;
  • 图像(PNG、JPG 等);
  • 音频、视频;
  • 复杂对象(如 Pandas DataFrame、Matplotlib 图表)。

它提供了一系列工具函数和类,让开发者可以方便地在交互式界面中展示多样化的输出。

Image:IPython.display 模块中的一个,用于创建 “可显示的图像对象”,主要作用是:

  • 加载图像资源(支持本地文件路径、网络 URL、二进制图像数据);
  • 配置图像的显示参数(如宽度、高度、格式);
  • 配合 display 函数在 Jupyter 等环境中直接显示图像。

display:IPython.display 模块中的一个函数,用于在交互式环境中显示对象。它的核心作用是:

  • 接收各种类型的对象(如 Image 对象、字符串、HTML 片段、Pandas 表格等);
  • 根据对象类型自动选择合适的方式渲染并展示(例如,对 Image 对象会显示图片,对 HTML 字符串会解析为网页元素)。

display():在交互式环境(如 Jupyter Notebook)中显示对象(图像、HTML、文本等)。

参数名 类型 默认值 描述
obj 多样(如ImagestrHTML 要显示的对象
** kwargs 多样 额外显示参数(如clear=True清除之前的输出)

Image():创建图像对象(IPython 中用于显示图像,PIL 中用于图像处理)。

参数名(IPython.display.Image) 类型 默认值 描述
data bytes None 图像二进制数据
filename str None 图像文件路径(优先于data
format str None 图像格式(如"png""jpg",自动从文件推断)
width int None 显示宽度(像素)
height int None 显示高度(像素)

.get_graph():获取状态图的内部结构(通常为Graph对象,包含节点和边的元数据)。

.draw_mermaid_png():将图结构转换为 Mermaid 语法,并生成 PNG 图像(需安装mermaid-cli)。

参数名 类型 默认值 描述
path str None 图像保存路径(如"graph.png",不指定则返回二进制数据)
** kwargs 多样 Mermaid 绘图参数(如"theme": "dark"设置主题)
import os
from typing import TypedDict, List, Union
from langchain_core.messages import HumanMessage, AIMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, START, END
# from dotenv import load_dotenv

class AgentState(TypedDict):
    """
    Agent state.
    HumanMessage、AIMessage是langchain_core.messages中的类,是一种内置的数据类型
    """
    messages: List[Union[HumanMessage, AIMessage]]
    '''
    messages: List[HumanMessage]
    messages_AI: List[AIMessage]
    '''

# qwen模型
qw_model = ChatOpenAI(
    model="qwen-max",           # 通义千问
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

def process(state: AgentState) -> AgentState:
    '''
    This node will solve the request you input.
    :param state:
    :return:
    '''
    response = qw_model.invoke(state["messages"])

    state["messages"].append(AIMessage(content=response.content))
    print(f"\nAI: {response.content}")
    print("Current State:",  state["messages"])
    return state


graph = StateGraph(AgentState)
graph.add_node("process", process)
graph.add_edge(START, "process")
graph.add_edge("process", END)

agent = graph.compile()

# Optional: Display the graph (requires IPython)
from IPython.display import Image, display

display(Image(agent.get_graph().draw_mermaid_png()))

conversation_history:List[Union[HumanMessage, AIMessage]],全程维护对话的完整历史记录,是连接 “用户输入→AI 处理→历史回溯” 的核心数据载体。

user_input:str(字符串),存储用户输入的文本内容,是对话的 “用户输入源”。

input():Python 内置函数,核心作用是从标准输入(通常是键盘)获取用户输入,并将输入内容以字符串形式返回。

参数名 类型 默认值 描述
prompt str None 可选参数,用于显示给用户的提示文本。若提供该参数,会先在控制台打印

.append():在列表的末尾添加一个元素,直接修改原列表(无返回值),常用于动态扩展列表内容(如你代码中向 conversation_history 添加用户消息)。

参数名 类型 是否必填 描述
object 任意类型 要添加到列表末尾的元素(可以是字符串、数字、对象等,如你代码中的 HumanMessage 对象)。

agent:StateGraph编译后的可执行对象,可直接调用的 “智能体” 实例,用于执行graph定义的工作流。

result["messages"]:List[Union[HumanMessage, AIMessage]],传递 AI 处理后的 “完整消息集合”,是 conversation_history 更新的 “数据源”。

open():打开一个文件,并返回文件对象(file object),是文件读写操作的 “入口”(如你代码中打开 conversation_history.txt 保存对话日志)。

参数名 类型 默认值 是否必填 描述
file str 要打开的文件路径(可以是绝对路径,如 C:/logs.txt;或相对路径,如 ./history.txt)。
mode str 'r' 打开模式(决定文件可执行的操作):- 'r':只读(默认);- 'w':写入(覆盖原内容);- 'a':追加(在原内容后添加);- 'r+':读写;带 b 表示二进制模式(如 'wb' 二进制写入)。
encoding str None 文本文件的编码格式(如 'utf-8''gbk',你的代码中用 'utf-8' 确保中文正常写入)。
errors str None 编码错误处理方式(如 'strict' 严格报错、'ignore' 忽略错误)。
buffering int -1 缓冲策略(-1 表示使用默认缓冲,0 表示无缓冲,正数表示缓冲区大小)。

.write():向打开的文件中写入字符串内容,返回写入的字符数(仅文本模式有效;二进制模式下需传入字节流,且方法为 .write(bytes))。

参数名 类型 是否必填 描述
string str 要写入文件的字符串(文本模式);若为二进制模式,需传入 bytes 类型数据。

isinstance():检查一个对象是否是指定类(或元组中的任意类)的实例,返回布尔值(True/False),常用于类型判断(如你代码中区分 HumanMessage 和 AIMessage)。

参数名 类型 是否必填 描述
object 任意对象 需要检查类型的对象(如你代码中的 message)。
classinfo 类 / 类的元组 用于判断的类(如 HumanMessage),或多个类组成的元组(如 (HumanMessage, AIMessage),只要对象是其中任一类的实例,就返回 True)。
conversation_history = []

user_input = input("User: ")
while user_input != "exit":
    conversation_history.append(HumanMessage(content=user_input))

    result = agent.invoke({"messages":conversation_history})

    print(result["messages"])
    conversation_history = result["messages"]

    user_input = input("User: ")

with open("conversation_history.txt", "w", encoding="utf-8") as f:
    f.write("Your Conversation Log:\n")
    for message in conversation_history:
        if isinstance(message, HumanMessage):
            f.write(f"User: {message.content}\n")
        elif isinstance(message, AIMessage):
            f.write(f"AI: {message.content}\n")
    f.write("End of Conversation Log.")

print("Conversation history saved to conversation_history.txt")

用户输入:

what day is today?

how are you?

please introduce yourself


3.ReActAgent

typing:提供类型提示(Type Hints) 相关的工具,用于在代码中标注变量、函数参数、返回值的类型,提升代码可读性和静态类型检查能力(如配合 mypy 工具)。

Annotated:为类型添加元数据(metadata),格式为 Annotated[type, metadata],其中 type 是基础类型,metadata 是附加信息(可多个)。在保留类型提示的同时,传递额外信息(如校验规则、描述等),常见于数据验证、框架配置等场景。

Sequence:标注 “序列类型”(如列表 list、元组 tuple、字符串 str 等可迭代且有序的对象),等价于 “任何实现了 collections.abc.Sequence 接口的类型”。相比具体类型(如 list),Sequence 更抽象,允许传入多种序列类型,提升代码灵活性。

TypedDict:类型提示工具,定义具有固定键和值类型的字典,明确指定字典中每个键对应的 value 类型,类似 “结构化字典”。在需要严格约束字典结构的场景(如状态管理、API 参数)中使用,替代普通 dict 以提升类型安全性。

os:提供与操作系统交互的接口,实现跨平台的系统级操作(如文件路径处理、环境变量读取、进程管理等)。

langchain_core:提供 LangChain 应用的基础组件和抽象接口,是整个框架的 “骨架”,包含消息处理、提示模板、工具调用、链(Chain)等核心功能的底层定义。

langchain_core.messages:定义对话中各类消息的数据结构和基类,统一消息格式,支持多轮对话的上下文管理。

langchain_core.messages.HumanMessage:封装人类用户的输入消息,明确标记 “来自用户的内容”,是对话流程中 “用户侧” 消息的载体。

langchain_core.messages.AIMessage:封装AI 模型生成的回复消息,明确标记 “来自 AI 的内容”,是对话流程中 “AI 侧” 消息的载体。

langchain_core.messages.BaseMessage:所有消息类型(HumanMessageAIMessage 等)的抽象父类,定义了消息的通用属性(如 contentid)和方法,确保消息类型的一致性。

langchain_core.messages.ToolMessage:封装工具调用的返回结果(如调用搜索引擎、数据库后的响应),用于将工具输出传递给 AI 模型,作为生成回复的依据。

langchain_core.messages.SystemMessage:封装系统提示消息(如 AI 的角色定义、行为规则),用于指导 AI 的回复风格或逻辑(优先级通常高于用户消息)。

langchain_openai:封装 OpenAI 及兼容 OpenAI API 的模型(如通义千问、智谱 AI 等)的调用逻辑,提供统一接口用于调用聊天模型、嵌入模型等。

ChatOpenAI:实例化 OpenAI 风格的聊天模型(如 gpt-3.5-turbo、通义千问 qwen-max),提供 invoke 等方法调用模型生成回复。

langgraph:用于构建多步骤工作流或智能体(Agent),通过 “状态图(有向图)” 定义节点(处理逻辑)和边(流转规则),支持复杂流程的可视化和执行。

langgraph.graph:提供构建状态图的基础组件,如状态图类、节点 / 边操作函数、特殊节点(如开始 / 结束)等。

langgraph.graph.StateGraph:创建一个状态图实例,用于定义工作流的结构(节点、边、状态类型),是构建工作流的核心对象。

langgraph.graph.END:表示状态图的结束节点,用于标记工作流的终止点(如 graph.add_edge("final_node", END) 表示流程到 final_node 后结束)。

langgraph.graph.add_messages:用于更新状态中的消息列表(如对话历史),自动将新消息(如用户输入、AI 回复)追加到状态的 messages 字段中,简化状态维护逻辑。

langgraph.prebuilt:提供开箱即用的组件(如工具节点、对话节点),避免重复开发常见功能,加速工作流搭建。

langgraph.prebuilt.ToolNode:封装工具调用的逻辑,作为状态图中的一个节点,负责解析 AI 的 tool_calls 指令、执行对应的工具(如函数、API)、并将结果包装为 ToolMessage 回传给状态。

langchain_core.tools:定义工具的抽象接口和基础结构,规范 “可被 AI 调用的工具”(如函数、API)的格式,确保工具能被 LangChain 组件识别和调用。

langchain_core.tools.tool:将普通 Python 函数标记为 **“可被 AI 调用的工具”**,自动生成工具的元数据(如名称、描述、参数类型),供 AI 模型判断何时及如何调用该工具。

messages:messages 是 AgentState(基于 TypedDict 定义的 “智能体状态结构”)中的核心状态字段,是整个对话与工具调用流程的 “数据载体”。

@tool:langchain_core.tools 模块提供的装饰器(Python 装饰器语法,用 @ 标识,作用于函数)。将普通 Python 函数 “改造” 为AI 可识别、可调用的工具—— 无需手动编写工具元数据(如 “工具叫什么、能做什么、需要哪些参数”),装饰器会自动提取函数信息生成标准格式的工具描述。

tools:一个工具列表,存储了所有被 @tool 装饰后、可供 AI 调用的工具函数。

qw_model:配置完成的通义千问模型客户端,由 ChatOpenAI 类初始化并绑定工具后生成,具备 “自然语言对话 + 工具调用” 的双重能力。

ChatOpenAI():初始化 OpenAI 聊天模型(如 GPT-3.5、GPT-4)的实例,用于调用 OpenAI 的对话 API。

参数名 类型 默认值 描述
model_name str "gpt-3.5-turbo" 模型名称(如"gpt-4""gpt-3.5-turbo-1106"
temperature float 0.7 输出随机性(0-1,0 为确定性输出,1 为最大随机性)
api_key str None OpenAI API 密钥(默认从环境变量OPENAI_API_KEY读取)
base_url str None API 基础地址(默认"https://api.openai.com/v1",可用于代理或自定义服务)
max_tokens int None 生成内容的最大 token 数(默认由模型限制决定)
timeout int None API 调用超时时间(秒)
streaming bool False 是否启用流式输出(实时返回部分结果)
default_headers dict None 额外的 HTTP 请求头

ChatOpenAI().bind_tools():为 AI 模型绑定可调用的工具列表,让模型知道 “可以使用哪些工具”,并在生成回复时自动判断是否需要调用工具(如调用函数、API 等),生成符合格式的工具调用指令(用于后续执行工具)。

参数名 类型 默认值 描述
tools List[BaseTool] 或 List[dict] 必需参数,要绑定的工具列表。- 可以是 langchain_core.tools.BaseTool 的实例(如通过 @tool 装饰器定义的工具);- 也可以是工具元数据字典(包含 namedescriptionparameters 等字段)。
tool_choice str 或 dict 或 None "auto" 控制模型是否 / 如何选择工具:- "auto":模型自主决定是否调用工具;- "none":不允许调用工具(仅生成自然语言回复);- 工具名称(如 "calculate"):强制调用指定工具;- 字典(如 {"type": "function", "function": {"name": "calculate"}}):更精细的强制调用配置。
**kwargs 任意 其他传递给模型的参数(如 temperature 等,但通常在初始化 ChatOpenAI 时设置)。

system_prompt:是 model_call 函数中定义的系统提示消息,由 SystemMessage 类创建,是指导 AI 行为的 “底层规则”。

SystemMessage():定义系统提示消息,用于向 AI 模型传递 “角色设定、行为规则、背景信息” 等底层指令,指导模型的回复风格、逻辑或功能边界(优先级通常高于用户消息)。

参数名 类型 默认值 描述
content str 必需参数,系统提示的文本内容(核心指令,如角色定义、规则说明)。
additional_kwargs dict {} 可选参数,附加元数据(如消息 ID、时间戳等,通常无需手动设置)。
response_metadata dict {} 可选参数,模型返回的元数据(如生成时间、token 数,一般由模型自动填充)。

.invoke():执行一次调用,传入输入并返回处理结果(同步方法)。

参数名 类型 默认值 描述
input 多样(如list[Message]strdict 输入内容(聊天模型通常接受消息列表,如[HumanMessage(...)]
config dict None 调用配置(如{"tags": ["tag1"]}用于日志标记,"max_concurrency"控制并发)
**kwargs 多样 额外参数(如部分模型支持stop列表,指定终止生成的字符串)

state:state 是 AgentState 类型的实例(AgentState 是一个 TypedDict,定义了状态的结构)。

state["messages"]:List[HumanMessage](人类消息列表)。存储当前对话状态中的 “用户输入消息集合”,是连接用户输入与模型处理的核心数据载体。

last_message:列表的最后一个元素,即 “当前对话流程中最新产生的消息”,作为 “流程判断的数据源”:should_continue 函数的核心逻辑是 “基于最新消息的内容,决定下一步做什么”,而 last_message 就是这个 “最新消息” 的载体。

last_message.tool_calls:tool_calls 是 AIMessage 类(AI 回复消息)的专属属性HumanMessageToolMessage 等其他消息类型无此属性),用于存储 “AI 模型生成的工具调用指令”。

response:模型返回的消息对象,AI 模型对用户消息的回复结果。

graph:StateGraph实例,定义工作流的 “状态图” 对象。

StateGraph():创建一个状态图(有向图),用于定义多步骤工作流(如对话流程、工具调用逻辑),支持节点状态流转。

参数名 类型 默认值 描述
name str None 状态图的名称(用于标识和日志)

.add_node():向状态图中添加一个节点(节点对应一个处理函数,负责处理当前状态并返回新状态)。

参数名 类型 默认值 描述
name str 节点唯一名称(用于标识节点)
func Callable 节点处理函数(输入为当前状态state,返回更新后的状态或流转指令)

.add_edge():定义节点之间的边(流转关系),指定从一个节点到另一个节点的跳转规则。

参数名 类型 默认值 描述
start_node str 起始节点名称(边的起点)
end_node str 或 Callable 目标节点名称(边的终点);若为函数,则根据当前状态动态返回目标节点

app:StateGraph编译后的可执行对象,可直接调用的 “智能体” 实例,用于执行graph定义的工作流。

.add_conditional_edges():langgraph.graph.StateGraph 类的核心方法,用于在状态图中添加 “条件分支边”—— 即根据动态条件(如当前状态、AI 决策结果)自动决定从一个节点跳转到哪个目标节点,实现工作流的灵活分支逻辑(类似编程中的 if-else 判断)。

参数名 类型 是否必填 描述
start_node str 起始节点的名称(边的起点,如你的代码中的 "our_agent",即 “AI 模型调用节点”)。
condition Callable 条件判断函数,接收当前状态(state)作为输入,返回一个分支标识(如字符串 "continue" 或 "end"),用于决定跳转方向。在你的代码中,should_continue 就是这个函数:检查最新消息是否有工具调用指令,返回 "continue"(需调用工具)或 "end"(无需调用)。
destinations dict 分支标识与目标节点的映射字典,格式为 {分支标识: 目标节点名称或特殊节点(如END)}。在你的代码中,{"continue": "tools", "end": END} 表示:若 condition 返回 "continue",则跳转到 "tools" 节点(执行工具);若返回 "end",则跳转到 END(流程结束)。

.compile():编译状态图,生成可执行的Runnable对象(用于运行工作流)。

参数名 类型 默认值 描述
config dict None 编译配置(如{"verbose": True}开启详细日志)

Ipython:IPython 是一个增强的交互式 Python 环境(Interactive Python 的缩写),它在标准 Python 解释器的基础上增加了许多功能,比如:

  • 支持语法高亮、自动补全、命令历史记录;
  • 可以直接运行 shell 命令(如 !ls);
  • 支持交互式可视化(如图表、图像显示);
  • 提供 “魔法命令”(如 %run%matplotlib)简化工作流。

它是 Jupyter Notebook/Lab 的核心依赖,广泛用于数据分析、机器学习等交互式开发场景。

Ipython.display:是 IPython 内置的一个模块,专门用于在交互式环境(如 Jupyter Notebook)中显示各种类型的内容,包括但不限于:

  • 文本、HTML、Markdown;
  • 图像(PNG、JPG 等);
  • 音频、视频;
  • 复杂对象(如 Pandas DataFrame、Matplotlib 图表)。

它提供了一系列工具函数和类,让开发者可以方便地在交互式界面中展示多样化的输出。

Image:IPython.display 模块中的一个,用于创建 “可显示的图像对象”,主要作用是:

  • 加载图像资源(支持本地文件路径、网络 URL、二进制图像数据);
  • 配置图像的显示参数(如宽度、高度、格式);
  • 配合 display 函数在 Jupyter 等环境中直接显示图像。

display:IPython.display 模块中的一个函数,用于在交互式环境中显示对象。它的核心作用是:

  • 接收各种类型的对象(如 Image 对象、字符串、HTML 片段、Pandas 表格等);
  • 根据对象类型自动选择合适的方式渲染并展示(例如,对 Image 对象会显示图片,对 HTML 字符串会解析为网页元素)。

display():在交互式环境(如 Jupyter Notebook)中显示对象(图像、HTML、文本等)。

参数名 类型 默认值 描述
obj 多样(如ImagestrHTML 要显示的对象
** kwargs 多样 额外显示参数(如clear=True清除之前的输出)

Image():创建图像对象(IPython 中用于显示图像,PIL 中用于图像处理)。

参数名(IPython.display.Image) 类型 默认值 描述
data bytes None 图像二进制数据
filename str None 图像文件路径(优先于data
format str None 图像格式(如"png""jpg",自动从文件推断)
width int None 显示宽度(像素)
height int None 显示高度(像素)

.get_graph():获取状态图的内部结构(通常为Graph对象,包含节点和边的元数据)。

.draw_mermaid_png():将图结构转换为 Mermaid 语法,并生成 PNG 图像(需安装mermaid-cli)。

参数名 类型 默认值 描述
path str None 图像保存路径(如"graph.png",不指定则返回二进制数据)
** kwargs 多样 Mermaid 绘图参数(如"theme": "dark"设置主题)
from typing import Annotated, Sequence, TypedDict
import os
from langchain_core.messages import HumanMessage, AIMessage, BaseMessage, ToolMessage, SystemMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END, add_messages
from langgraph.prebuilt import ToolNode
from langchain_core.tools import tool


class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], add_messages]


@tool
def add(a: int, b: int):
    '''
    This is an addition function that adds two numbers together.
    :param a:
    :param b:
    :return:
    '''
    return a + b

@tool
def subtract(a: int, b: int):
    '''
    This is an addition function that adds two numbers together.
    :param a:
    :param b:
    :return:
    '''
    return a - b

@tool
def multiply(a: int, b: int):
    '''
    This is an addition function that adds two numbers together.
    :param a:
    :param b:
    :return:
    '''
    return a * b


@tool
def divide(a: int, b: int):
    '''
    This is an addition function that adds two numbers together.
    :param a:
    :param b:
    :return:
    '''
    if b == 0:
        return "Error: Division by zero"
    return a / b


tools = [add, subtract, multiply, divide]

# qwen模型
qw_model = ChatOpenAI(
    model="qwen-max",  # 通义千问
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
).bind_tools(tools)


def model_call(state: AgentState) -> AgentState:
    system_prompt = SystemMessage(content=
                                  "You are my AI assistant, please answer my query to the best of your ability."
                                  )
    response = qw_model.invoke([system_prompt] + state["messages"])
    # state["messages"]。append(...)
    # return state
    return {"messages": [response]}


def should_continue(state: AgentState):
    messages = state["messages"]
    last_message = messages[-1]
    if not last_message.tool_calls:
        return "end"
    else:
        return "continue"


graph = StateGraph(AgentState)
graph.add_node("our_agent", model_call)
tool_node = ToolNode(tools=tools)
graph.add_node("tools", tool_node)

graph.set_entry_point("our_agent")

graph.add_conditional_edges(
    "our_agent",
    should_continue,
    {
        "continue": "tools",
        "end": END
    }
)

graph.add_edge("tools", "our_agent")

app = graph.compile()

# Optional: Display the graph (requires IPython)
from IPython.display import Image, display

display(Image(app.get_graph().draw_mermaid_png()))

stream:print_stream 函数的参数,实际传入的值是 app.stream(inputs, stream_mode="values") 的返回结果。

  • 其中 app 是 StateGraph 编译后的可执行对象(Runnable),其 .stream() 方法用于以流式方式获取智能体的处理结果
  • stream_mode="values" 是 .stream() 的参数,指定返回 “纯状态数据”(而非包含元数据的完整对象),让结果更简洁。

message:存储 “智能体当前步骤的关键交互信息”:

        元组 tuple:仅在初始输入阶段,对应 inputs 中 ("user", "内容") 的简化格式(LangGraph 会自动将其转换为 HumanMessage,但流式初始步骤可能暂存为元组);

        LangChain 消息对象:后续步骤中,多为 AIMessage(AI 的回复 / 工具调用指令)或 ToolMessage(工具执行结果)。

isinstance():检查一个对象是否是指定类(或元组中任意类)的实例,返回布尔值(True/False),核心用于 “类型安全检查”,避免因类型错误导致代码异常(如你之前代码中区分 HumanMessage 和 AIMessage)。

参数名 类型 是否必填 描述
object 任意对象 需要检查类型的目标对象(如你代码中的 messagelast_message)。
classinfo 类 / 类的元组 用于判断的 “类型标准”:- 单个类(如 HumanMessage):检查对象是否是该类的实例;- 类的元组(如 (HumanMessage, AIMessage)):检查对象是否是元组中任意一个类的实例(满足一个即返回 True)。

.pretty_print():格式化、易读的方式打印对象内容,自动处理缩进、换行、类型标识,避免直接打印对象时出现杂乱的内部属性(如 <HumanMessage content='你好' id='xxx'>)。

参数名 类型 默认值 是否必填 描述
width int 80 打印内容的最大宽度(超过宽度会自动换行,避免一行过长)。
indent int 2 缩进空格数(用于嵌套内容,如元数据的缩进,提升层次感)。
**kwargs 任意 额外格式化参数(如 color=True 开启彩色打印,部分实现支持该功能)。

inputs1:符合 AgentState 结构的初始输入字典—— 是智能体启动时的 “任务指令”,告诉智能体 “需要处理什么需求”。

inputs2:作为第二个测试用例,触发智能体处理 “多步骤计算 + 跨类型任务(计算→写诗)”

app:StateGraph编译后的可执行对象,可直接调用的 “智能体” 实例,用于执行graph定义的工作流。

.stream():流式方式获取结果,即 “逐步返回部分结果”(而非等待完整结果生成后一次性返回),常用于大模型生成文本时提升用户体验(如实时显示 AI 回复的每一个字符 / 段落)。与同步调用 .invoke()(等待完整结果)不同,.stream() 返回的是 “生成器(generator)”,需通过循环迭代获取每一块结果。

参数名 类型 默认值 是否必填 描述
input 多样(如 List[BaseMessage]dictstr 输入内容,与 .invoke() 的 input 格式一致(如 LLM 调用时传入消息列表,状态图调用时传入初始状态)。
config dict None 调用配置,如日志标记({"tags": ["stream-call"]})、超时时间({"timeout": 30})等。
**kwargs 任意 额外参数,根据所属对象不同可能有差异(如部分模型支持 stop 列表,指定终止生成的字符串)。
def print_stream(stream):
    for s in stream:
        message = s["messages"][-1]
        if isinstance(message, tuple):
            print(message)
        else:
            message.pretty_print()


inputs1 = {"messages": [("user", "Add 11 + 4, Add 1 + 14, Add 9 + 28")]}
print_stream(app.stream(inputs1, stream_mode = "values"))

inputs2 = {"messages": [("user", "Add 11 + 4 and then subtract 3, "
                                 "Add 1 + 14 and then multiply 2, "
                                 "Add 9 + 28 and then divide 4, "
                                 "divide 5 / 6 and then subtract 1 and then tell me a poem"
                         )]}
print_stream(app.stream(inputs2, stream_mode = "values"))


4.AssistantGraph

typing:提供类型提示(Type Hints) 相关的工具,用于在代码中标注变量、函数参数、返回值的类型,提升代码可读性和静态类型检查能力(如配合 mypy 工具)。

Annotated:为类型添加元数据(metadata),格式为 Annotated[type, metadata],其中 type 是基础类型,metadata 是附加信息(可多个)。在保留类型提示的同时,传递额外信息(如校验规则、描述等),常见于数据验证、框架配置等场景。

Sequence:标注 “序列类型”(如列表 list、元组 tuple、字符串 str 等可迭代且有序的对象),等价于 “任何实现了 collections.abc.Sequence 接口的类型”。相比具体类型(如 list),Sequence 更抽象,允许传入多种序列类型,提升代码灵活性。

TypedDict:类型提示工具,定义具有固定键和值类型的字典,明确指定字典中每个键对应的 value 类型,类似 “结构化字典”。在需要严格约束字典结构的场景(如状态管理、API 参数)中使用,替代普通 dict 以提升类型安全性。

os:提供与操作系统交互的接口,实现跨平台的系统级操作(如文件路径处理、环境变量读取、进程管理等)。

langchain_core:提供 LangChain 应用的基础组件和抽象接口,是整个框架的 “骨架”,包含消息处理、提示模板、工具调用、链(Chain)等核心功能的底层定义。

langchain_core.messages:定义对话中各类消息的数据结构和基类,统一消息格式,支持多轮对话的上下文管理。

langchain_core.messages.HumanMessage:封装人类用户的输入消息,明确标记 “来自用户的内容”,是对话流程中 “用户侧” 消息的载体。

langchain_core.messages.AIMessage:封装AI 模型生成的回复消息,明确标记 “来自 AI 的内容”,是对话流程中 “AI 侧” 消息的载体。

langchain_core.messages.BaseMessage:所有消息类型(HumanMessageAIMessage 等)的抽象父类,定义了消息的通用属性(如 contentid)和方法,确保消息类型的一致性。

langchain_core.messages.ToolMessage:封装工具调用的返回结果(如调用搜索引擎、数据库后的响应),用于将工具输出传递给 AI 模型,作为生成回复的依据。

langchain_core.messages.SystemMessage:封装系统提示消息(如 AI 的角色定义、行为规则),用于指导 AI 的回复风格或逻辑(优先级通常高于用户消息)。

langchain_openai:封装 OpenAI 及兼容 OpenAI API 的模型(如通义千问、智谱 AI 等)的调用逻辑,提供统一接口用于调用聊天模型、嵌入模型等。

ChatOpenAI:实例化 OpenAI 风格的聊天模型(如 gpt-3.5-turbo、通义千问 qwen-max),提供 invoke 等方法调用模型生成回复。

langgraph:用于构建多步骤工作流或智能体(Agent),通过 “状态图(有向图)” 定义节点(处理逻辑)和边(流转规则),支持复杂流程的可视化和执行。

langgraph.graph:提供构建状态图的基础组件,如状态图类、节点 / 边操作函数、特殊节点(如开始 / 结束)等。

langgraph.graph.StateGraph:创建一个状态图实例,用于定义工作流的结构(节点、边、状态类型),是构建工作流的核心对象。

langgraph.graph.END:表示状态图的结束节点,用于标记工作流的终止点(如 graph.add_edge("final_node", END) 表示流程到 final_node 后结束)。

langgraph.graph.add_messages:用于更新状态中的消息列表(如对话历史),自动将新消息(如用户输入、AI 回复)追加到状态的 messages 字段中,简化状态维护逻辑。

langgraph.prebuilt:提供开箱即用的组件(如工具节点、对话节点),避免重复开发常见功能,加速工作流搭建。

langgraph.prebuilt.ToolNode:封装工具调用的逻辑,作为状态图中的一个节点,负责解析 AI 的 tool_calls 指令、执行对应的工具(如函数、API)、并将结果包装为 ToolMessage 回传给状态。

langchain_core.tools:定义工具的抽象接口和基础结构,规范 “可被 AI 调用的工具”(如函数、API)的格式,确保工具能被 LangChain 组件识别和调用。

langchain_core.tools.tool:将普通 Python 函数标记为 **“可被 AI 调用的工具”**,自动生成工具的元数据(如名称、描述、参数类型),供 AI 模型判断何时及如何调用该工具。

document_content:存储当前文档完整内容的全局字符串变量,贯穿整个系统运行过程。作为文档内容的 “唯一数据源”,实现:

  1. 状态共享:所有函数(updateour_agent)均可访问和修改,确保人机协作中内容一致;
  2. 状态展示:在system_prompt中实时展示当前文档内容,让模型和用户清晰了解文档进度;
  3. 持久化基础:save工具通过读取该变量的值,将内容写入本地文件。

global:Python 中的关键字,核心作用是在函数内部声明变量为 “全局变量”,允许函数修改全局作用域(函数外部)中定义的该变量,而非创建一个同名的局部变量。

content:用户指定的文档新内容,是update工具的核心参数(字符串类型)。替换全局变量document_content的旧值,实现文档内容的更新或起草。

messages:messages 是 AgentState(基于 TypedDict 定义的 “智能体状态结构”)中的核心状态字段,是整个对话与工具调用流程的 “数据载体”。

@tool:langchain_core.tools 模块提供的装饰器(Python 装饰器语法,用 @ 标识,作用于函数)。将普通 Python 函数 “改造” 为AI 可识别、可调用的工具—— 无需手动编写工具元数据(如 “工具叫什么、能做什么、需要哪些参数”),装饰器会自动提取函数信息生成标准格式的工具描述。

tools:一个工具列表,存储了所有被 @tool 装饰后、可供 AI 调用的工具函数。

.endswith():Python 字符串(str)的实例方法,用于检查字符串是否以指定的 “后缀” 结尾,返回布尔值 True(是)或 False(否)。核心用途是快速判断字符串的结尾特征(如文件扩展名、句子结尾符号等)。

参数名 类型 默认值 是否必填 描述
suffix str 或 tuple 要检查的目标后缀:- 若为字符串(如 ".txt"):检查原字符串是否以该字符串结尾;- 若为元组(如 (".txt", ".pdf")):检查原字符串是否以元组中任意一个字符串结尾(满足一个即返回 True)。
start int 0 可选参数,指定检查的 “起始位置”(即从字符串的第 start 个索引开始截取子字符串,再判断该子字符串是否以 suffix 结尾)。
end int 字符串长度 可选参数,指定检查的 “结束位置”(即截取子字符串到第 end 个索引为止,再判断该子字符串是否以 suffix 结尾)。

filename:用户指定的文档保存名称,是save工具的核心参数(字符串类型)。确定文档保存到本地的文件名及路径(默认保存在当前目录)。

open():打开一个文件,并返回文件对象(file object),是文件读写操作的 “入口”(如你代码中打开 conversation_history.txt 保存对话日志)。

参数名 类型 默认值 是否必填 描述
file str 要打开的文件路径(可以是绝对路径,如 C:/logs.txt;或相对路径,如 ./history.txt)。
mode str 'r' 打开模式(决定文件可执行的操作):- 'r':只读(默认);- 'w':写入(覆盖原内容);- 'a':追加(在原内容后添加);- 'r+':读写;带 b 表示二进制模式(如 'wb' 二进制写入)。
encoding str None 文本文件的编码格式(如 'utf-8''gbk',你的代码中用 'utf-8' 确保中文正常写入)。
errors str None 编码错误处理方式(如 'strict' 严格报错、'ignore' 忽略错误)。
buffering int -1 缓冲策略(-1 表示使用默认缓冲,0 表示无缓冲,正数表示缓冲区大小)。

.write():向打开的文件中写入字符串内容,返回写入的字符数(仅文本模式有效;二进制模式下需传入字节流,且方法为 .write(bytes))。

参数名 类型 是否必填 描述
string str 要写入文件的字符串(文本模式);若为二进制模式,需传入 bytes 类型数据。

isinstance():检查一个对象是否是指定类(或元组中的任意类)的实例,返回布尔值(True/False),常用于类型判断(如你代码中区分 HumanMessage 和 AIMessage)。

参数名 类型 是否必填 描述
object 任意对象 需要检查类型的对象(如你代码中的 message)。
classinfo 类 / 类的元组 用于判断的类(如 HumanMessage),或多个类组成的元组(如 (HumanMessage, AIMessage),只要对象是其中任一类的实例,就返回 True)。

qw_model:配置完成的通义千问模型客户端,由 ChatOpenAI 类初始化并绑定工具后生成,具备 “自然语言对话 + 工具调用” 的双重能力。

ChatOpenAI():初始化 OpenAI 聊天模型(如 GPT-3.5、GPT-4)的实例,用于调用 OpenAI 的对话 API。

参数名 类型 默认值 描述
model_name str "gpt-3.5-turbo" 模型名称(如"gpt-4""gpt-3.5-turbo-1106"
temperature float 0.7 输出随机性(0-1,0 为确定性输出,1 为最大随机性)
api_key str None OpenAI API 密钥(默认从环境变量OPENAI_API_KEY读取)
base_url str None API 基础地址(默认"https://api.openai.com/v1",可用于代理或自定义服务)
max_tokens int None 生成内容的最大 token 数(默认由模型限制决定)
timeout int None API 调用超时时间(秒)
streaming bool False 是否启用流式输出(实时返回部分结果)
default_headers dict None 额外的 HTTP 请求头

ChatOpenAI().bind_tools():为 AI 模型绑定可调用的工具列表,让模型知道 “可以使用哪些工具”,并在生成回复时自动判断是否需要调用工具(如调用函数、API 等),生成符合格式的工具调用指令(用于后续执行工具)。

参数名 类型 默认值 描述
tools List[BaseTool] 或 List[dict] 必需参数,要绑定的工具列表。- 可以是 langchain_core.tools.BaseTool 的实例(如通过 @tool 装饰器定义的工具);- 也可以是工具元数据字典(包含 namedescriptionparameters 等字段)。
tool_choice str 或 dict 或 None "auto" 控制模型是否 / 如何选择工具:- "auto":模型自主决定是否调用工具;- "none":不允许调用工具(仅生成自然语言回复);- 工具名称(如 "calculate"):强制调用指定工具;- 字典(如 {"type": "function", "function": {"name": "calculate"}}):更精细的强制调用配置。
**kwargs 任意 其他传递给模型的参数(如 temperature 等,但通常在初始化 ChatOpenAI 时设置)。

system_prompt:是 model_call 函数中定义的系统提示消息,由 SystemMessage 类创建,是指导 AI 行为的 “底层规则”。

SystemMessage():定义系统提示消息,用于向 AI 模型传递 “角色设定、行为规则、背景信息” 等底层指令,指导模型的回复风格、逻辑或功能边界(优先级通常高于用户消息)。

参数名 类型 默认值 描述
content str 必需参数,系统提示的文本内容(核心指令,如角色定义、规则说明)。
additional_kwargs dict {} 可选参数,附加元数据(如消息 ID、时间戳等,通常无需手动设置)。
response_metadata dict {} 可选参数,模型返回的元数据(如生成时间、token 数,一般由模型自动填充)。

.invoke():执行一次调用,传入输入并返回处理结果(同步方法)。

参数名 类型 默认值 描述
input 多样(如list[Message]strdict 输入内容(聊天模型通常接受消息列表,如[HumanMessage(...)]
config dict None 调用配置(如{"tags": ["tag1"]}用于日志标记,"max_concurrency"控制并发)
**kwargs 多样 额外参数(如部分模型支持stop列表,指定终止生成的字符串)

user_input:用户在终端输入的自然语言指令,是触发系统行为的 “指令源”。

user_message:user_input封装为 LangChain 标准的HumanMessage对象,统一消息格式,确保user_input能与系统提示、AI 响应等其他消息类型(如SystemMessageAIMessage)兼容,便于all_messages整合和模型识别。

HumanMessage():创建 人类用户消息对象,专门用于在 LangChain 对话流程中 “标记用户输入内容”,与 AI 生成的 AIMessage、工具返回的 ToolMessage 形成明确区分,是对话状态管理的核心载体之一。

参数名 类型 默认值 是否必填 描述
content str 用户消息的核心文本内容(如 “你好”“计算 3*4”),是 HumanMessage 的核心字段。
additional_kwargs dict {} 附加元数据(如用户 ID、消息时间戳等自定义信息),示例:{"user_id": "123", "timestamp": "2024-05-20"}
response_metadata dict {} 模型回复相关的元数据(通常由模型自动填充,用户创建 HumanMessage 时无需手动设置)。

list():Python 内置函数,

        创建空列表:当无参数时,返回一个空列表([]);

        转换可迭代对象为列表:当传入可迭代对象(如元组、字符串、生成器等)时,将其转换为列表,便于后续列表操作(如 append()、索引访问)。

参数名 类型 默认值 是否必填 描述
iterable 可迭代对象 可选参数,指能被循环遍历的对象(如元组、字符串、集合、生成器等)。- 若传入,返回该对象转换后的列表;- 若不传入,返回空列表 []

all_messages:整合 “系统提示 + 历史对话消息 + 当前用户输入” 的完整消息列表,是模型(qw_model)的最终输入。

hasattr():检查一个 对象是否具有指定名称的属性或方法,返回布尔值 True(有)或 False(无)。

参数名 类型 是否必填 描述
object 任意 Python 对象 需要检查属性的目标对象(如 HumanMessage 实例、AIMessage 实例、自定义类实例等)。
name str 要检查的 “属性名或方法名”(必须是字符串格式),如 "content"(属性)、"pretty_print"(方法)、"tool_calls"(属性)。

.lower():将字符串中的 所有大写英文字母转换为小写,非英文字母字符(如数字、符号、中文)保持不变,返回转换后的新字符串(原字符串不会被修改)。

graph:StateGraph实例,定义工作流的 “状态图” 对象。

StateGraph():创建一个状态图(有向图),用于定义多步骤工作流(如对话流程、工具调用逻辑),支持节点状态流转。

参数名 类型 默认值 描述
name str None 状态图的名称(用于标识和日志)

.set_entry_point():langgraph.graph.StateGraph 类的核心方法,用于指定状态图(工作流)的 “入口节点”—— 即整个流程的起始点,定义了智能体从哪个节点开始执行任务(类似程序的 main 函数,是流程的第一个执行步骤)。

参数名 类型 是否必填 描述
node_name str 入口节点的名称(字符串),该节点必须是已通过 graph.add_node() 方法添加到状态图中的节点(否则会报错)。

.add_node():向状态图中添加一个节点(节点对应一个处理函数,负责处理当前状态并返回新状态)。

参数名 类型 默认值 描述
name str 节点唯一名称(用于标识节点)
func Callable 节点处理函数(输入为当前状态state,返回更新后的状态或流转指令)

.add_edge():定义节点之间的边(流转关系),指定从一个节点到另一个节点的跳转规则。

参数名 类型 默认值 描述
start_node str 起始节点名称(边的起点)
end_node str 或 Callable 目标节点名称(边的终点);若为函数,则根据当前状态动态返回目标节点

.add_conditional_edges():langgraph.graph.StateGraph 类的核心方法,用于在状态图中添加 “条件分支边”—— 即根据动态条件(如当前状态、AI 决策结果)自动决定从一个节点跳转到哪个目标节点,实现工作流的灵活分支逻辑(类似编程中的 if-else 判断)。

参数名 类型 是否必填 描述
start_node str 起始节点的名称(边的起点,如你的代码中的 "our_agent",即 “AI 模型调用节点”)。
condition Callable 条件判断函数,接收当前状态(state)作为输入,返回一个分支标识(如字符串 "continue" 或 "end"),用于决定跳转方向。在你的代码中,should_continue 就是这个函数:检查最新消息是否有工具调用指令,返回 "continue"(需调用工具)或 "end"(无需调用)。
destinations dict 分支标识与目标节点的映射字典,格式为 {分支标识: 目标节点名称或特殊节点(如END)}。在你的代码中,{"continue": "tools", "end": END} 表示:若 condition 返回 "continue",则跳转到 "tools" 节点(执行工具);若返回 "end",则跳转到 END(流程结束)。

app:StateGraph编译后的可执行对象,可直接调用的 “智能体” 实例,用于执行graph定义的工作流。

.compile():编译状态图,生成可执行的Runnable对象(用于运行工作流)。

参数名 类型 默认值 描述
config dict None 编译配置(如{"verbose": True}开启详细日志)

Ipython:IPython 是一个增强的交互式 Python 环境(Interactive Python 的缩写),它在标准 Python 解释器的基础上增加了许多功能,比如:

  • 支持语法高亮、自动补全、命令历史记录;
  • 可以直接运行 shell 命令(如 !ls);
  • 支持交互式可视化(如图表、图像显示);
  • 提供 “魔法命令”(如 %run%matplotlib)简化工作流。

它是 Jupyter Notebook/Lab 的核心依赖,广泛用于数据分析、机器学习等交互式开发场景。

Ipython.display:是 IPython 内置的一个模块,专门用于在交互式环境(如 Jupyter Notebook)中显示各种类型的内容,包括但不限于:

  • 文本、HTML、Markdown;
  • 图像(PNG、JPG 等);
  • 音频、视频;
  • 复杂对象(如 Pandas DataFrame、Matplotlib 图表)。

它提供了一系列工具函数和类,让开发者可以方便地在交互式界面中展示多样化的输出。

Image:IPython.display 模块中的一个,用于创建 “可显示的图像对象”,主要作用是:

  • 加载图像资源(支持本地文件路径、网络 URL、二进制图像数据);
  • 配置图像的显示参数(如宽度、高度、格式);
  • 配合 display 函数在 Jupyter 等环境中直接显示图像。

display:IPython.display 模块中的一个函数,用于在交互式环境中显示对象。它的核心作用是:

  • 接收各种类型的对象(如 Image 对象、字符串、HTML 片段、Pandas 表格等);
  • 根据对象类型自动选择合适的方式渲染并展示(例如,对 Image 对象会显示图片,对 HTML 字符串会解析为网页元素)。

display():在交互式环境(如 Jupyter Notebook)中显示对象(图像、HTML、文本等)。

参数名 类型 默认值 描述
obj 多样(如ImagestrHTML 要显示的对象
** kwargs 多样 额外显示参数(如clear=True清除之前的输出)

Image():创建图像对象(IPython 中用于显示图像,PIL 中用于图像处理)。

参数名(IPython.display.Image) 类型 默认值 描述
data bytes None 图像二进制数据
filename str None 图像文件路径(优先于data
format str None 图像格式(如"png""jpg",自动从文件推断)
width int None 显示宽度(像素)
height int None 显示高度(像素)

.get_graph():获取状态图的内部结构(通常为Graph对象,包含节点和边的元数据)。

.draw_mermaid_png():将图结构转换为 Mermaid 语法,并生成 PNG 图像(需安装mermaid-cli)。

参数名 类型 默认值 描述
path str None 图像保存路径(如"graph.png",不指定则返回二进制数据)
** kwargs 多样 Mermaid 绘图参数(如"theme": "dark"设置主题)
'''
我们公司的工作效率不高!我们在起草文件上花费了太多时间,这需要解决!
对于这家公司来说,你需要创建一个AI代理系统,该系统能够加速文档起草、电子邮件撰写等过程。
这个AI代理系统应具备“人机协作”功能,即人类能够持续提供反馈,而一旦人类对草稿感到满意,AI代理就应该停止工作。
该系统应具备以下特性:
1.运行快速
2.能够保存草稿
'''
from typing import Annotated, Sequence, TypedDict
import os
from langchain_core.messages import HumanMessage, AIMessage, BaseMessage, ToolMessage, SystemMessage
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langgraph.graph import StateGraph, START, END, add_messages
from langgraph.prebuilt import ToolNode
from langchain_core.tools import tool

'''
This is the global variable to store document content
'''
document_content = ""


class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], add_messages]


@tool
def update(content: str) -> str:
    '''
    update the document with the provided content
    :param content:
    :return:
    '''
    global document_content
    document_content = content
    return f"Document has been updated successfully! The current content is:\n {document_content}"


@tool
def save(filename: str) -> str:
    '''
    save the document to a text file and finish the process
    :param filename:Name for the text file
    :return:
    '''
    global document_content

    if not filename.endswith(".txt"):
        filename += ".txt"

    try:
        with open(filename, "w") as f:
            f.write(document_content)
        print(f"Document has been saved successfully as {filename}!")
        return f"Document has been saved successfully as {filename}!"

    except Exception as e:
        return f"Error while saving the document: {str(e)}"


tools = [update, save]

# qwen模型
qw_model = ChatOpenAI(
    model="qwen-max",  # 通义千问
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
).bind_tools(tools)


def our_agent(state: AgentState) -> AgentState:
    system_prompt = SystemMessage(content="You are a helpful assistant. You are given a document and a user query. "
                                          "Your task is to help the user find the answer to their query by updating "
                                          "the document and saving it as a text file."

                                          "if the user wantes to update the document, please type 'update' and "
                                          "provide the new content."
                                          "if the user wants to save the document, please type 'save' and provide the "
                                          "filename."
                                          "make sure to always show the current document state after modification"

                                          "The current document state is:\n{document_content}"
                                  )
    if not state["messages"]:
        user_input = "I`m ready to help you update a document. What would you like to create?"
        user_message = HumanMessage(content=user_input)
    else:
        user_input = input("\nWhat would you like to do with the document? ")
        print(f"\n User input: {user_input}")
        user_message = HumanMessage(content=user_input)

    all_messages = [system_prompt] + list(state["messages"]) + [user_message]
    response = qw_model.invoke(all_messages)

    print(f"\n AI:{response.content}")

    if hasattr(response, "tool_calls") and response.tool_calls:
        print(f"\n Using tool: {[tc['name'] for tc in response.tool_calls]}")
    return {"messages": list(state["messages"]) + [user_message, response]}


def should_continue(state):
    '''
    This function checks if the conversation should continue.
    :param state:
    :return:
    '''
    if not state["messages"]:
        return "continue"

    for message in reversed(state["messages"]):
        if (isinstance(message, ToolMessage) and
                "saved" in message.content.lower() and
                "document" in message.content.lower()):
            return "end"

        return "continue"

def print_messages(messages):
    '''
    Function to print the messages in a readable format.
    :param messages:
    :return:
    '''
    if not messages:
        return

    for message in messages:
        if isinstance(message, ToolMessage):
            print(f"\n Tool result: {message.content}")


graph = StateGraph(AgentState)

graph.add_node("agent", our_agent)
graph.add_node("tools", ToolNode(tools))

graph.set_entry_point("agent")

graph.add_edge("agent", "tools")

graph.add_conditional_edges(
    "tools",
    should_continue,
    {
        "continue": "agent",
        "end": END
    }
)

app = graph.compile()

# Optional: Display the graph (requires IPython)
from IPython.display import Image, display

display(Image(app.get_graph().draw_mermaid_png()))

state:state 是 AgentState 类型的实例(AgentState 是一个 TypedDict,定义了状态的结构)。

app:StateGraph编译后的可执行对象,可直接调用的 “智能体” 实例,用于执行graph定义的工作流。

stream:print_stream 函数的参数,实际传入的值是 app.stream(inputs, stream_mode="values") 的返回结果。

  • 其中 app 是 StateGraph 编译后的可执行对象(Runnable),其 .stream() 方法用于以流式方式获取智能体的处理结果
  • stream_mode="values" 是 .stream() 的参数,指定返回 “纯状态数据”(而非包含元数据的完整对象),让结果更简洁。

.stream():流式方式获取结果,即 “逐步返回部分结果”(而非等待完整结果生成后一次性返回),常用于大模型生成文本时提升用户体验(如实时显示 AI 回复的每一个字符 / 段落)。与同步调用 .invoke()(等待完整结果)不同,.stream() 返回的是 “生成器(generator)”,需通过循环迭代获取每一块结果。

参数名 类型 默认值 是否必填 描述
input 多样(如 List[BaseMessage]dictstr 输入内容,与 .invoke() 的 input 格式一致(如 LLM 调用时传入消息列表,状态图调用时传入初始状态)。
config dict None 调用配置,如日志标记({"tags": ["stream-call"]})、超时时间({"timeout": 30})等。
**kwargs 任意 额外参数,根据所属对象不同可能有差异(如部分模型支持 stop 列表,指定终止生成的字符串)。
def run_document_agent():
    print("\n =========DRAFTER==========")
    state = {"messages": []}

    for step in app.stream(state, stream_mode="values"):
        if "messages" in step:
            print_messages(step["messages"])

    print("\n =========DRAFTED=FINISHED==========")


run_document_agent()

用户输入:

help me to write a letter to my mom


5.RAG_Agent

os:提供与操作系统交互的接口,实现跨平台的系统级操作(如文件路径处理、环境变量读取、进程管理等)。

typing:提供类型提示(Type Hints) 相关的工具,用于在代码中标注变量、函数参数、返回值的类型,提升代码可读性和静态类型检查能力(如配合 mypy 工具)。

Annotated:为类型添加元数据(metadata),格式为 Annotated[type, metadata],其中 type 是基础类型,metadata 是附加信息(可多个)。在保留类型提示的同时,传递额外信息(如校验规则、描述等),常见于数据验证、框架配置等场景。

Sequence:标注 “序列类型”(如列表 list、元组 tuple、字符串 str 等可迭代且有序的对象),等价于 “任何实现了 collections.abc.Sequence 接口的类型”。相比具体类型(如 list),Sequence 更抽象,允许传入多种序列类型,提升代码灵活性。

TypedDict:类型提示工具,定义具有固定键和值类型的字典,明确指定字典中每个键对应的 value 类型,类似 “结构化字典”。在需要严格约束字典结构的场景(如状态管理、API 参数)中使用,替代普通 dict 以提升类型安全性。

langchain_core:提供 LangChain 应用的基础组件和抽象接口,是整个框架的 “骨架”,包含消息处理、提示模板、工具调用、链(Chain)等核心功能的底层定义。

langchain_core.messages:定义对话中各类消息的数据结构和基类,统一消息格式,支持多轮对话的上下文管理。

langchain_core.messages.HumanMessage:封装人类用户的输入消息,明确标记 “来自用户的内容”,是对话流程中 “用户侧” 消息的载体。

langchain_core.messages.AIMessage:封装AI 模型生成的回复消息,明确标记 “来自 AI 的内容”,是对话流程中 “AI 侧” 消息的载体。

langchain_core.messages.BaseMessage:所有消息类型(HumanMessageAIMessage 等)的抽象父类,定义了消息的通用属性(如 contentid)和方法,确保消息类型的一致性。

langchain_core.messages.ToolMessage:封装工具调用的返回结果(如调用搜索引擎、数据库后的响应),用于将工具输出传递给 AI 模型,作为生成回复的依据。

langchain_core.messages.SystemMessage:封装系统提示消息(如 AI 的角色定义、行为规则),用于指导 AI 的回复风格或逻辑(优先级通常高于用户消息)。

langchain_openai:封装 OpenAI 及兼容 OpenAI API 的模型(如通义千问、智谱 AI 等)的调用逻辑,提供统一接口用于调用聊天模型、嵌入模型等。

ChatOpenAI:实例化 OpenAI 风格的聊天模型(如 gpt-3.5-turbo、通义千问 qwen-max),提供 invoke 等方法调用模型生成回复。

langgraph:用于构建多步骤工作流或智能体(Agent),通过 “状态图(有向图)” 定义节点(处理逻辑)和边(流转规则),支持复杂流程的可视化和执行。

langgraph.graph:提供构建状态图的基础组件,如状态图类、节点 / 边操作函数、特殊节点(如开始 / 结束)等。

langgraph.graph.StateGraph:创建一个状态图实例,用于定义工作流的结构(节点、边、状态类型),是构建工作流的核心对象。

langgraph.graph.END:表示状态图的结束节点,用于标记工作流的终止点(如 graph.add_edge("final_node", END) 表示流程到 final_node 后结束)。

langchain_core.tools:定义工具的抽象接口和基础结构,规范 “可被 AI 调用的工具”(如函数、API)的格式,确保工具能被 LangChain 组件识别和调用。

langchain_core.tools.tool:将普通 Python 函数标记为 **“可被 AI 调用的工具”**,自动生成工具的元数据(如名称、描述、参数类型),供 AI 模型判断何时及如何调用该工具。

langchain_text_splitter:LangChain 框架下的文本拆分专用模块,专门解决 “长文本超出模型上下文限制” 的问题 —— 无论是大模型的输入长度限制,还是嵌入模型的向量生成长度限制,都需要将长文本拆分为短片段(称为 chunk),该模块提供了多种拆分策略(按字符、按 token、按语义等)。

langchain_text_splitter.RecursiveCharacterTextSplitter:langchain_text_splitter 模块中最常用、最推荐的拆分类,采用 “递归字符拆分策略”:按优先级从大到小的分隔符(如段落→换行→句子→空格)拆分文本,若拆分后仍超出长度限制,则继续递归拆分更小的单位,最大限度保留文本的语义连贯性(比如优先不拆分段落、句子)。

qw_model:调用通义千问大模型(qwen-max),用于生成回复或工具调用指令

ChatOpenAI():初始化 OpenAI 聊天模型(如 GPT-3.5、GPT-4)的实例,用于调用 OpenAI 的对话 API。

参数名 类型 默认值 描述
model_name str "gpt-3.5-turbo" 模型名称(如"gpt-4""gpt-3.5-turbo-1106"
temperature float 0.7 输出随机性(0-1,0 为确定性输出,1 为最大随机性)
api_key str None OpenAI API 密钥(默认从环境变量OPENAI_API_KEY读取)
base_url str None API 基础地址(默认"https://api.openai.com/v1",可用于代理或自定义服务)
max_tokens int None 生成内容的最大 token 数(默认由模型限制决定)
timeout int None API 调用超时时间(秒)
streaming bool False 是否启用流式输出(实时返回部分结果)
default_headers dict None 额外的 HTTP 请求头

embeddings:将文本(如 PDF 拆分后的片段)转换为数值向量(供 Chroma 向量库存储和检索)

DashScopeEmbeddings():LangChain 封装的阿里云 DashScope 文本嵌入模型类,用于将文本(如 PDF 片段)转换为数值向量,为向量库存储和相似性检索提供基础。

参数名 类型 默认值 描述
model str 无(必填) 嵌入模型名称,代码中使用 text-embedding-v1(DashScope 官方文本嵌入模型)。
dashscope_api_key str None DashScope 服务的 API 密钥,代码中从环境变量 DASHSCOPE_API_KEY 读取,用于权限验证。
api_base str None 可选,自定义 API 基础地址,默认使用 DashScope 官方地址,代码中未额外配置。
timeout int 60 可选,请求超时时间(秒),超过时间未响应则抛出错误。
**kwargs 任意 - 可选,其他传递给 DashScope API 的额外参数(如请求头、重试配置等)。

pdf_path:指定待加载的 PDF 文件路径(绝对路径)

os.path.exists():Python os.path 模块的内置函数,用于判断指定路径(文件或目录)是否存在,返回布尔值 True(存在)或 False(不存在),代码中用于校验 PDF 文件路径和向量库存储目录是否有效。

参数名 类型 默认值 描述
path str 无(必填) 待判断的路径字符串(绝对路径或相对路径),代码中用于校验 pdf_path 和 persist_directory

FileNotFoundError():Python 内置异常类,用于在 “指定文件不存在” 时主动抛出错误,明确提示文件缺失问题,代码中在 pdf_path 对应的文件不存在时调用。

参数名 类型 默认值 描述
msg str 无(必填) 错误提示信息,代码中使用 f"File {pdf_path} does not exist.",明确缺失的文件路径。

pdf_loader:读取 pdf_path 指向的 PDF 文件,将其解析为结构化的 “页面文档”

PyPDFLoader():LangChain langchain_community.document_loaders 模块的 PDF 加载类,用于读取本地 PDF 文件并解析为结构化的 Document 对象,每个 Document 对应 PDF 的一页或一段内容。

参数名 类型 默认值 描述
file_path str 无(必填) 待加载的 PDF 文件路径(绝对路径或相对路径),代码中传入 pdf_path
extract_images bool False 可选,是否提取 PDF 中的图片,默认不提取

.load():PyPDFLoader 类的核心方法,执行 PDF 文件加载与解析,将 PDF 的每一页转换为 langchain_core.documents.base.Document 对象,返回包含所有页面的列表。

pages:列表,存储加载后的 PDF 页面数据,每个元素是 Document 对象

text_splitter:将 PDF 的长文本(pages 中的 page_content)拆分为短片段,适配嵌入模型的长度限制

RecursiveCharacterTextSplitter():文本拆分类,用于将长文本(如 PDF 页面)拆分为短片段,适配嵌入模型的长度限制,同时通过重叠保留上下文连贯性。

参数名 类型 默认值 描述
chunk_size int 1000 单个文本片段的最大字符数,代码中使用 1000(避免超出嵌入模型上下文)。
chunk_overlap int 200 相邻片段的重叠字符数,代码中使用 200(确保语义连贯,避免拆分断裂)。
length_function Callable len 可选,计算文本长度的函数,默认用 len()(按字符数计算)。
separators List[str] ["\n\n", "\n", ". ", " ", ""] 可选,拆分文本的分隔符列表,按优先级尝试(默认优先按段落、换行拆分)。

pages_split:存储拆分后的文本片段,初始为 text_splitter.split_documents(pages) 的结果;

text_splitter.split_documents():对 Document 对象列表(如 pages)进行拆分,将每个 Document 的长文本拆分为多个短 Document,返回拆分后的 Document 列表,代码中用于拆分 PDF 页面为片段。

参数名 类型 默认值 描述
documents List[Document] 无(必填) 待拆分的 Document 对象列表,代码中传入 pages(加载后的 PDF 页面列表)。
**kwargs 任意 - 可选,额外拆分配置(如强制拆分规则),代码中未使用。

filtered_pages:过滤 pages_split 中的 “空文档” 或 “无效文本文档”,确保存入向量库的文本有意义

raw_content:从拆分后的文档对象 doc 中提取的原始文本内容,即 raw_content = doc.page_content

type():Python 内置函数,用于获取对象的类型,返回对象所属的类(如 strDocumentAIMessage 等),代码中用于调试,打印 raw_content 的类型以定位异常。

参数名 类型 默认值 描述
object 任意 Python 对象 无(必填) 待查询类型的对象,代码中传入 raw_content(PDF 片段的原始内容)。

str_content:“清洗后的数据”,通过类型转换和空白去除,确保内容有效且格式统一,是最终存入向量库的 “可用文本”。

.strip():Python 字符串的内置方法,用于去除字符串首尾的空白字符(包括空格 、换行符 \n、制表符 \t 等),返回处理后的新字符串(原字符串不变),代码中用于清洗 PDF 片段的空白。

persist_directory:指定 Chroma 向量库的 “持久化存储路径”(本地文件夹路径)

collection_name:指定 Chroma 向量库中的 “集合名称”(类似数据库中的 “表名”)

os.path.exists():Python os.path 模块的内置函数,核心作用是判断指定的文件或目录路径是否真实存在,返回布尔值 True(存在)或 False(不存在),是文件 / 目录操作前 “防错校验” 的常用工具。

参数名 类型 是否必填 描述
path str 待验证的路径字符串,支持绝对路径(如 r"F:\AI_BigModel\data\test.pdf")和相对路径(如 "./data/test.pdf");路径可指向文件或目录。

os.makedirs():ython os 模块的函数,用于递归创建目录(即若父目录不存在,会自动创建所有层级目录),避免手动创建多级目录的麻烦,代码中用于创建向量库的持久化存储目录。

参数名 类型 默认值 描述
path str 无(必填) 待创建的目录路径(绝对路径或相对路径),代码中传入 persist_directory
mode int 0o777 可选,目录权限(仅 Unix 系统有效),Windows 系统忽略该参数。
exist_ok bool False 可选,若目录已存在是否抛出错误:False(默认,抛出 FileExistsError)、True(不抛出,直接跳过),代码中未设置(需确保目录不存在或手动处理)。

chroma_client:Chroma 客户端,负责创建 / 复用集合、管理向量数据持久化

chromadb.PersistentClient():Chroma 向量库的持久化客户端类,用于创建或连接到本地持久化的 Chroma 向量库(数据存储在指定路径,程序重启后数据不丢失),代码中作为向量库的操作入口。

参数名 类型 默认值 描述
path str 无(必填) 向量库数据的存储路径,代码中传入 persist_directory(本地目录路径)。
**kwargs 任意 - 可选,额外客户端配置(如日志级别、超时),代码中未使用。

.get_or_create_collection():Chroma 客户端的方法,用于获取指定名称的集合(Collection),若不存在则创建(类似数据库中的 “表”,用于分类存储向量数据),代码中用于创建 / 复用 PDF_market 集合。

参数名 类型 默认值 描述
name str 无(必填) 集合名称,代码中传入 collection_name(即 PDF_market)。
metadata dict None 可选,集合的元数据(如描述、创建时间),代码中未设置。
embedding_function Callable None 可选,集合级别的嵌入函数(代码中通过 LangChain 的 Chroma 类统一配置,此处未设置)。

vectorstore:整合 Chroma 客户端与嵌入模型,提供 “文档存入” 和 “相似性检索” 的统一接口

Chroma():LangChain 封装的 Chroma 向量库类,用于整合 Chroma 客户端与嵌入模型,提供 “文档存入”“相似性检索” 的统一接口,适配 LangChain 的工作流,代码中创建向量库实例。

参数名 类型 默认值 描述
client chromadb.Client 无(必填) Chroma 客户端实例,代码中传入 chroma_client(持久化客户端)。
collection_name str 无(必填) 集合名称,代码中传入 collection_namePDF_market)。
embedding_function Embeddings 无(必填) 嵌入模型实例,代码中传入 embeddingsDashScopeEmbeddings 实例),用于自动生成文本向量。
**kwargs 任意 - 可选,额外配置(如文档 ID 生成规则),代码中未使用。

.add_documents():Chroma 向量库实例的方法,用于将 Document 对象列表存入向量库,自动调用绑定的嵌入模型生成向量,同时存储文档文本和元数据,代码中用于存入过滤后的 PDF 片段。

参数名 类型 默认值 描述
documents List[Document] 无(必填) 待存入的 Document 对象列表,代码中传入 pages_split(过滤后的 PDF 片段)。
ids List[str] None 可选,手动指定文档 ID 列表,若未设置则自动生成唯一 ID。
**kwargs 任意 - 可选,额外存储配置(如元数据过滤规则),代码中未使用。

retriever:根据用户查询(query),从 vectorstore 中检索 “最相似的文档片段”

.as_retriever():Chroma 向量库实例的方法,用于创建向量库检索器(Retriever),封装相似性检索逻辑,提供 invoke(query) 接口供工具调用,代码中创建 retriever 用于后续查询。

参数名 类型 默认值 描述
search_type str "similarity" 可选,检索算法类型:"similarity"(余弦相似性,默认)、"mmr"(最大边际相关性,减少结果冗余),代码中使用 "similarity"
search_kwargs dict {"k": 4} 可选,检索参数:"k"(返回 Top k 个相似结果)、"filter"(元数据过滤)等,代码中传入 {"k": 5}(返回 Top 5)。

@tool:langchain_core.tools 模块提供的装饰器(Python 装饰器语法,用 @ 标识,作用于函数)。将普通 Python 函数 “改造” 为AI 可识别、可调用的工具—— 无需手动编写工具元数据(如 “工具叫什么、能做什么、需要哪些参数”),装饰器会自动提取函数信息生成标准格式的工具描述。

tools:集中管理所有可被 AI 调用的工具,此处仅包含 retriever_tool

.invoke():LangChain 中 Runnable 类型对象(如 Retriever、ChatOpenAI、CompiledGraph)的统一调用方法,用于执行核心逻辑并返回结果,不同对象的 invoke() 功能不同,代码中涉及 3 类场景:

  • Retriever.invoke(query):执行相似性检索,返回相似文档列表;
  • ChatOpenAI.invoke(messages):调用大模型,返回 AI 消息(含文本或工具调用);
  • CompiledGraph.invoke(state):执行状态图流程,返回最终状态。
调用场景 参数名 类型 默认值 描述
Retriever.invoke() query str 无(必填) 用户查询文本,代码中传入 t['args'].get('query')(工具调用的查询参数)。
ChatOpenAI.invoke() messages List[BaseMessage] 无(必填) 消息列表(含 SystemMessage、HumanMessage 等),代码中传入 all_messages 或 messages
CompiledGraph.invoke() input Dict 无(必填) 状态图初始输入(符合 AgentState 结构),代码中传入 {"messages": [HumanMessage]}

llm:在 qw_model 基础上绑定 tools,让模型具备 “判断是否调用工具、生成工具调用指令” 的能力

.bind_tools():LangChain ChatOpenAI 类的方法,用于将工具列表绑定到大模型,让模型知道 “可调用哪些工具”,并能自动生成符合格式的工具调用指令(tool_calls),代码中用于绑定 retriever_tool

参数名 类型 默认值 描述
tools List[Tool] 或 List[dict] 无(必填) 待绑定的工具列表:可是 Tool 实例(如 retriever_tool)或工具元数据字典,代码中传入 tools[retriever_tool])。
tool_choice str 或 dict "auto" 可选,工具调用控制:"auto"(模型自主决定)、"none"(不调用工具)、工具名(强制调用指定工具),代码中未设置(默认 "auto")。
**kwargs 任意 - 可选,额外模型参数(如 temperature),代码中未使用。

system_prompt:AI 的系统提示,定义角色(回答 PDF 相关问题)和规则(必须用 retriever_tool 检索,引用文档内容)

tools_dict:将工具列表 tools 转为 “工具名称→工具实例” 的映射,方便快速通过工具名查找工具

message:llm.invoke(messages) 的返回结果,含 AI 的回复或工具调用指令;

messages:从 state["messages"] 复制对话历史,拼接 SystemMessage(system_prompt),形成完整的模型输入;

.append():Python 列表的内置方法,用于在列表末尾添加一个元素,直接修改原列表(无返回值,或返回 None),代码中用于拼接工具结果、消息列表等。

参数名 类型 默认值 描述
object 任意 无(必填) 待添加到列表的元素,代码中用于添加 doc(到 filtered_pages)、ToolMessage(到 res)等。

graph:StateGraph实例,定义工作流的 “状态图” 对象。

StateGraph():创建一个状态图(有向图),用于定义多步骤工作流(如对话流程、工具调用逻辑),支持节点状态流转。

参数名 类型 默认值 描述
name str None 状态图的名称(用于标识和日志)

.set_entry_point():langgraph.graph.StateGraph 类的核心方法,用于指定状态图(工作流)的 “入口节点”—— 即整个流程的起始点,定义了智能体从哪个节点开始执行任务(类似程序的 main 函数,是流程的第一个执行步骤)。

参数名 类型 是否必填 描述
node_name str 入口节点的名称(字符串),该节点必须是已通过 graph.add_node() 方法添加到状态图中的节点(否则会报错)。

.add_node():向状态图中添加一个节点(节点对应一个处理函数,负责处理当前状态并返回新状态)。

参数名 类型 默认值 描述
name str 节点唯一名称(用于标识节点)
func Callable 节点处理函数(输入为当前状态state,返回更新后的状态或流转指令)

.add_edge():定义节点之间的边(流转关系),指定从一个节点到另一个节点的跳转规则。

参数名 类型 默认值 描述
start_node str 起始节点名称(边的起点)
end_node str 或 Callable 目标节点名称(边的终点);若为函数,则根据当前状态动态返回目标节点

.add_conditional_edges():langgraph.graph.StateGraph 类的核心方法,用于在状态图中添加 “条件分支边”—— 即根据动态条件(如当前状态、AI 决策结果)自动决定从一个节点跳转到哪个目标节点,实现工作流的灵活分支逻辑(类似编程中的 if-else 判断)。

参数名 类型 是否必填 描述
start_node str 起始节点的名称(边的起点,如你的代码中的 "our_agent",即 “AI 模型调用节点”)。
condition Callable 条件判断函数,接收当前状态(state)作为输入,返回一个分支标识(如字符串 "continue" 或 "end"),用于决定跳转方向。在你的代码中,should_continue 就是这个函数:检查最新消息是否有工具调用指令,返回 "continue"(需调用工具)或 "end"(无需调用)。
destinations dict 分支标识与目标节点的映射字典,格式为 {分支标识: 目标节点名称或特殊节点(如END)}。在你的代码中,{"continue": "tools", "end": END} 表示:若 condition 返回 "continue",则跳转到 "tools" 节点(执行工具);若返回 "end",则跳转到 END(流程结束)。

rag_agent:StateGraph编译后的可执行对象,可直接调用的 “智能体” 实例,用于执行graph定义的工作流。

.compile():编译状态图,生成可执行的Runnable对象(用于运行工作流)。

参数名 类型 默认值 描述
config dict None 编译配置(如{"verbose": True}开启详细日志)

Ipython:IPython 是一个增强的交互式 Python 环境(Interactive Python 的缩写),它在标准 Python 解释器的基础上增加了许多功能,比如:

  • 支持语法高亮、自动补全、命令历史记录;
  • 可以直接运行 shell 命令(如 !ls);
  • 支持交互式可视化(如图表、图像显示);
  • 提供 “魔法命令”(如 %run%matplotlib)简化工作流。

它是 Jupyter Notebook/Lab 的核心依赖,广泛用于数据分析、机器学习等交互式开发场景。

Ipython.display:是 IPython 内置的一个模块,专门用于在交互式环境(如 Jupyter Notebook)中显示各种类型的内容,包括但不限于:

  • 文本、HTML、Markdown;
  • 图像(PNG、JPG 等);
  • 音频、视频;
  • 复杂对象(如 Pandas DataFrame、Matplotlib 图表)。

它提供了一系列工具函数和类,让开发者可以方便地在交互式界面中展示多样化的输出。

Image:IPython.display 模块中的一个,用于创建 “可显示的图像对象”,主要作用是:

  • 加载图像资源(支持本地文件路径、网络 URL、二进制图像数据);
  • 配置图像的显示参数(如宽度、高度、格式);
  • 配合 display 函数在 Jupyter 等环境中直接显示图像。

display:IPython.display 模块中的一个函数,用于在交互式环境中显示对象。它的核心作用是:

  • 接收各种类型的对象(如 Image 对象、字符串、HTML 片段、Pandas 表格等);
  • 根据对象类型自动选择合适的方式渲染并展示(例如,对 Image 对象会显示图片,对 HTML 字符串会解析为网页元素)。

display():在交互式环境(如 Jupyter Notebook)中显示对象(图像、HTML、文本等)。

参数名 类型 默认值 描述
obj 多样(如ImagestrHTML 要显示的对象
** kwargs 多样 额外显示参数(如clear=True清除之前的输出)

Image():创建图像对象(IPython 中用于显示图像,PIL 中用于图像处理)。

参数名(IPython.display.Image) 类型 默认值 描述
data bytes None 图像二进制数据
filename str None 图像文件路径(优先于data
format str None 图像格式(如"png""jpg",自动从文件推断)
width int None 显示宽度(像素)
height int None 显示高度(像素)

.get_graph():获取状态图的内部结构(通常为Graph对象,包含节点和边的元数据)。

.draw_mermaid_png():将图结构转换为 Mermaid 语法,并生成 PNG 图像(需安装mermaid-cli)。

参数名 类型 默认值 描述
path str None 图像保存路径(如"graph.png",不指定则返回二进制数据)
** kwargs 多样 Mermaid 绘图参数(如"theme": "dark"设置主题)
import os

from langchain_chroma import Chroma
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated, Sequence
from langchain_core.messages import BaseMessage, SystemMessage, HumanMessage, AIMessage, ToolMessage
from operator import add as add_messages
from langchain_openai import ChatOpenAI
from langchain_community.embeddings import DashScopeEmbeddings
# from langchain_openai import OpenAIEmbeddings
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.tools import tool
import chromadb

# qwen模型
qw_model = ChatOpenAI(
    model="qwen-max",  # 通义千问
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    temperature=0.7
)

embeddings = DashScopeEmbeddings(
    model="text-embedding-v1",  # 文本编码模型
    dashscope_api_key=os.getenv("DASHSCOPE_API_KEY"),
)

pdf_path = r"F:\AI_BigModel\appTest6\day6_LangGraph\data\deepseek-v3-1-4.pdf"

'''
Safety measure I have put for debugging purposes
'''
if not os.path.exists(pdf_path):
    raise FileNotFoundError(f"File {pdf_path} does not exist.")

# This is load the PDF
pdf_loader = PyPDFLoader(pdf_path)

try:
    pages = pdf_loader.load()
    print(f"PDF has been loaded successfully. Total pages: {len(pages)}")
except Exception as e:
    print(f"Error loading PDF: {e}")
    raise

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size = 1000,
    chunk_overlap = 200,
)

pages_split = text_splitter.split_documents(pages)

filtered_pages = []
for i, doc in enumerate(pages_split):
    # 打印原始内容的类型和值(关键:定位异常文档)
    raw_content = doc.page_content
    print(f"文档{i} | 类型: {type(raw_content)} | 原始内容: {repr(raw_content)}")

    # 强制转为字符串 + 去除首尾空白
    str_content = str(raw_content).strip()

    if str_content:  # 非空才保留
        doc.page_content = str_content
        filtered_pages.append(doc)
    else:
        print(f"文档{i} 内容为空或无效,已跳过")

pages_split = filtered_pages  # 替换为过滤后的文档列表

persist_directory = r"F:\AI_BigModel\appTest6\appTest6\day6_LangGraph\data"
collection_name = "PDF_market"

if not os.path.exists(persist_directory):
    os.makedirs(persist_directory)

try:
    # 1. 手动初始化Chroma客户端(避免from_documents内部参数冲突)
    chroma_client = chromadb.PersistentClient(path=persist_directory)
    chroma_client.get_or_create_collection(name=collection_name)

    # 2. 包装为LangChain VectorStore(仅传1次embedding_function)
    vectorstore = Chroma(
        client=chroma_client,
        collection_name=collection_name,
        embedding_function=embeddings
    )

    # 3. 手动添加文档
    vectorstore.add_documents(documents=pages_split)
    print(f"Created vectorstore successfully.")
except Exception as e:
    print(f"Error creating vectorstore: {str(e)}")
    raise

# Now we create our retriever
retriever = vectorstore.as_retriever(
    search_kwargs={"k": 5},
    search_type="similarity"
)

@ tool
def retriever_tool(query: str) -> str:
    '''
    This tool searches and returns the information from the deepseek-v3-1-4.pdf document.
    :param query:
    :return:
    '''
    docs = retriever.invoke(query)

    if not docs:
        return "No relevant information found."

    res = []
    for i, doc in enumerate(docs):
        res.append(f"Document {i+1}: \n{doc.page_content}\n")
    return "\n\n".join(res)


tools = [retriever_tool]

llm = qw_model.bind_tools(tools)

class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage] ,add_messages]

def should_continue(state: AgentState) -> bool:
    '''
    check if the agent should continue to chat
    :param state:
    :return:
    '''
    result = state["messages"][-1]
    return hasattr(result, "tool_calls") and len(result.tool_calls) > 0


system_prompt = """
You are a intelligent AI assistant who answers questions about the deepseek-v3-1-4.pdf document loaded into your knowledge base.
Use the retriever tool available to answer questions about the deepseek-v3-1-4.pdf data. You can make multiple calls if needed 
Please always cite the specific parts of the document you use in your answers.
"""

tools_dict = {our_tool.name: our_tool for our_tool in tools}


# LLM Agent
def call_llm(state: AgentState) -> AgentState:
    '''
    call the llm to generate a response
    :param state:
    :return:
    '''
    messages = list(state["messages"])
    messages = [SystemMessage( content=system_prompt)] + messages
    message = llm.invoke(messages)
    return {"messages": [message]}


# Retriever Agent
def take_action(state: AgentState) -> AgentState:
    '''
    call the retriever tool to get the relevant documents
    :param state:
    :return:
    '''
    tool_calls = state["messages"][-1].tool_calls
    res = []
    for t in tool_calls:
        print(f"Calling tool {t['name']} with input {t['args'].get('query', 'No query provided')}")

        if not t['name'] in tools_dict:
            print(f"Tool {t['name']} not found in tools")
            tool_res = "Incorrect Tool Name, Please Retry and Select tool from List of Available Tools"
        else:
            tool_res = tools_dict[t['name']].invoke(t['args'].get('query', 'No query provided'))
            print(f"Result length:{len(str(res))}")

        res.append(ToolMessage(tool_call_id=t['id'], name = t['name'], content = str(tool_res)))

    print("Tools Execution Complete. Back to the model")
    return {'messages': res}


graph = StateGraph(AgentState)
graph.add_node("llm", call_llm)
graph.add_node("retriever_agent", take_action)

graph.add_conditional_edges(
    "llm",
    should_continue,
    {True: "retriever_agent", False: END}
)

graph.add_edge("retriever_agent", "llm")
graph.set_entry_point("llm")

rag_agent = graph.compile()


# Optional: Display the graph (requires IPython)
from IPython.display import Image, display

display(Image(rag_agent.get_graph().draw_mermaid_png()))

user_input:仅在 running_agent() 函数中定义,通过 input("\nEnter your query: ") 从用户键盘输入获取,是 “用户需求的直接载体”。

input():从用户键盘获取输入,返回字符串类型的输入内容,常用于交互场景

参数名 类型 默认值 是否必填 描述
prompt str "" 可选的 “输入提示文本”,会在获取用户输入前显示在控制台,引导用户操作。

.lower():将字符串中的所有大写英文字母转换为小写,非英文字符(如数字、中文、符号)保持不变,返回新字符串(原字符串不修改),常用于 “不区分大小写判断”

messages:用户输入的标准化包装—— 将 user_input 转换为 LangChain 能识别的 HumanMessage,作为 rag_agent.invoke() 的输入参数。

HumanMessage():创建 “人类用户消息对象”,将用户输入的纯文本包装为 LangChain 框架可识别的消息格式,用于对话流程中标记 “用户输入”

参数名 类型 默认值 是否必填 描述
content str 用户消息的核心文本内容,即用户输入的具体内容(如你的代码中 HumanMessage(content=user_input)user_input 就是 content)。
additional_kwargs dict {} 可选的附加元数据,用于存储用户相关的额外信息(如用户 ID、输入时间戳),你的代码中未使用该参数。
response_metadata dict {} 可选的模型回复关联元数据(通常由模型自动填充,用户创建 HumanMessage 时无需手动设置),你的代码中未使用该参数。

res:是 **rag_agent.invoke() 的返回结果 **—— 包含智能体执行后的完整对话历史(messages 字段),其中 res["messages"][-1] 就是 AI 给用户的最终回复。

rag_agent:由 graph.compile() 生成 ——graph 是 StateGraph 实例(定义了节点、边、流程规则),compile() 会将流程逻辑转换为可调用的 “智能体”。

.invoke():启动编译后的 RAG 智能体(rag_agent),执行 “模型→工具→模型” 的完整流程,返回最终状态

参数名 类型 默认值 是否必填 描述
input dict 智能体的初始输入,需符合 AgentState 结构(核心包含 messages 字段)(如你的代码中 {"messages": [HumanMessage(content=user_input)]})。
**kwargs 任意 - 可选的额外流程参数(如日志配置、超时时间),你的代码中未额外传递。
def running_agent():
    print("\n===========RAG AGENT===========")
    while True:
        user_input = input("\nEnter your query: ")
        if user_input.lower() in ["exit", "quit"]:
            break

        messages = [HumanMessage(content=user_input)]
        res = rag_agent.invoke({"messages": messages})

        print("\n=======ANSWER======")
        print(res['messages'][-1].content)


running_agent()

用户输入:

introduce the deepseek model

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐