这类工具最值得先看的不是功能列表,而是能不能在普通环境里稳定跑起来,以及新手从哪一步开始才能不卡在环境配置上。吴恩达的提示词工程课程材料,结合 LangGraph、RAG 和 Agent 这些概念,听起来很强大,但很多人在第一步“跑起来”就放弃了。我更建议把第一次测试拆成三步:启动、单条任务、批量任务。

核心不是去争论哪个框架最好,而是先理解每个组件解决的具体问题。提示词工程(Prompt Engineering)是让大模型听懂你话的“翻译”技巧;RAG(检索增强生成)是给模型一本“参考书”,让它回答得更准;Agent(智能体)是让模型能“自己动手”执行多步骤任务;而 LangGraph 这类框架,则是把这些能力像搭积木一样连接起来的“脚手架”。如果你正在开发基于大模型的应用,或者想系统学习如何构建一个能查文档、能推理、能执行复杂流程的 AI 助手,那么这套组合是当前最值得投入时间实践的技术栈之一。

下面按实际落地顺序拆一遍,从环境准备到跑通第一个能查文档、能推理的智能体。

1. 先理清核心概念:别被术语吓住,它们各自解决一个具体问题

很多人一上来就被 LangGraph、RAG、Agent 这些词绕晕了,然后陷入无休止的框架对比。其实,你应该先抛开框架名字,想清楚你要做什么。

1.1 提示词工程:不是魔法咒语,是清晰的需求说明书

提示词工程(Prompt Engineering)的核心就一句话: 用模型能理解的方式,把你的任务说清楚 。它不是去搜寻什么“万能提示词”,而是学习如何结构化你的需求。

一个常见的误区是,以为提示词越长、越详细越好。实际上,对于大多数模型,清晰、具体、有步骤的提示更有效。例如,如果你想让模型总结一份文档,对比以下两种说法:

  • 模糊提示 :“总结一下这个文档。”
  • 工程化提示

    你是一个专业的文档分析师。请按照以下步骤处理我提供的文档:

    1. 提取文档的核心论点(不超过3个)。
    2. 列出支持每个论点的关键证据或数据。
    3. 用一段话(200字以内)概括文档的主要结论和潜在影响。
    4. 如果文档涉及专业术语,请用括号附上简短解释。 请基于以下文档内容进行操作:[此处粘贴文档]

后者给出了角色、步骤、输出格式和具体指令,模型“犯错”的空间就小得多。在后续结合 RAG 和 Agent 时,你构造的每一个查询、每一条指令,都是提示词工程的应用。

1.2 RAG:给模型一本“参考书”,告别胡编乱造

大模型有个通病:知识可能过时,且会对不知道的事情“自信地胡说八道”(幻觉)。RAG(Retrieval-Augmented Generation,检索增强生成)就是为了解决这个问题。

它的工作流程像极了人类查资料写报告:

  1. 知识库准备 :把你的文档(PDF、Word、网页等)切分成片段,转换成向量(一种数学表示),存入向量数据库。
  2. 检索 :当用户提问时,将问题也转换成向量,去数据库里找出最相关的几个文档片段。
  3. 增强生成 :把找到的相关片段和用户问题一起,作为“上下文”送给大模型,让它基于这些确凿的资料生成答案。

这样,答案的根基是你的私有文档,既保证了准确性,又扩展了模型的知识边界。 判断一个 RAG 系统是否有效,关键看两点:检索到的内容是否真的相关(召回率),以及生成的答案是否严格依据检索内容(忠实度)

1.3 Agent:从“问答机”升级为“执行者”

如果大模型只是一个问答机,那它的能力是有限的。Agent(智能体)赋予模型“行动”的能力。一个典型的 Agent 包含几个核心部分:

  • 规划 :理解目标,拆解成子任务(比如:先查天气,再推荐穿搭,最后生成出行建议)。
  • 工具使用 :调用外部 API 或函数来获取信息或执行操作(比如:搜索网络、查询数据库、运行代码)。
  • 记忆 :记住对话历史和中间结果,保持上下文连贯。

LangGraph 这类框架的核心价值,就是把规划、工具调用、状态管理这些流程,用“图”(Graph)的形式可视化、可编程地定义出来。一个节点可以是一个 LLM 调用,一个边代表执行流向。

1.4 LangGraph vs LangChain:不是替代,是分工

这是搜索热词里的高频问题。简单来说:

  • LangChain :是一个庞大的“工具箱”,提供了连接大模型、向量库、各种工具的链(Chain)和大量现成组件。它功能全面,但构建复杂、有状态的 Agent 时,代码可能变得难以管理和调试。
  • LangGraph :是建立在 LangChain 之上的一个“流程编排器”。它专门用于构建有状态、多步骤的智能体工作流。它用“图”来明确定义执行步骤和状态流转,使得复杂 Agent 的逻辑更清晰、更易于控制(比如暂停、循环、分支)。

对于新手,我建议的路径是:先用 LangChain 快速理解组件(模型、向量库、提示模板),当你需要构建一个需要反复决策、循环执行或复杂分支的智能体时,再深入 LangGraph。

2. 搭建你的第一个可运行环境:从最小依赖开始

理论懂了,下一步是让代码跑起来。环境配置是第一个拦路虎,原则是: 从最简单、依赖最少的方式开始 。不要一上来就追求完整的本地部署。

2.1 核心依赖清单

你需要准备以下几样东西,按优先级排列:

  1. Python 环境 :3.8 或以上版本。强烈建议使用 conda venv 创建独立的虚拟环境。
  2. 大模型 API 密钥 :这是大脑。对于学习和原型开发,直接使用云 API 是最快、最稳定的方式。例如 OpenAI 的 GPT 系列、 Anthropic 的 Claude 系列或国内可访问的合规大模型 API。 不要尝试在个人电脑上本地运行百亿参数模型,除非你有专业显卡和充足显存。
  3. 向量数据库 :这是 RAG 的“书架”。初期学习,使用内存型或轻量级本地向量库,完全够用。
  4. 开发框架 :LangChain 和 LangGraph。

2.2 一步步安装与配置

在你的项目目录下,按顺序操作:

# 1. 创建并激活虚拟环境 (以 conda 为例)
conda create -n ai-agent python=3.10
conda activate ai-agent

# 2. 安装核心框架
pip install langchain langgraph langchain-community

# 3. 安装一个嵌入模型和向量库
# 嵌入模型用于将文本转成向量。初期可以使用本地轻量模型,比如 sentence-transformers
pip install sentence-transformers
# 向量库使用轻量的 Chroma(内存模式)
pip install chromadb

# 4. 安装文本加载器(用于读取你的文档)
pip install pypdf  # 用于读取PDF
pip install python-docx  # 用于读取Word
# LangChain 提供了统一的文档加载接口
pip install langchain-community

接下来,配置你的大模型 API。假设你使用 OpenAI(其他模型类似,需查看对应 LangChain 文档):

# 在你的代码开头,或一个单独的 config.py 文件中
import os
from langchain_openai import ChatOpenAI

# 设置环境变量(确保你的API_KEY已准备好)
os.environ["OPENAI_API_KEY"] = "你的-api-key-here"

# 初始化一个聊天模型
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
# temperature 控制创造性,0表示更确定、更少随机性,适合任务执行。

关键点 temperature 参数很重要。对于 Agent 执行任务,通常设低(如 0-0.2),让它更确定、更少“瞎编”。对于创意生成,可以调高。

2.3 验证环境:跑通第一个对话

创建一个简单的 test_env.py 文件:

from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage

llm = ChatOpenAI(model="gpt-3.5-turbo")
response = llm.invoke([HumanMessage(content="你好,请用一句话介绍你自己。")])
print(response.content)

运行它:

python test_env.py

如果成功返回一句自我介绍,恭喜你,最核心的模型连接成功了。如果报错,大概率是网络问题或 API 密钥错误,根据错误信息排查。

3. 构建你的第一个 RAG 系统:让模型学会“查资料”

现在,我们给模型配上“参考书”。目标是:上传一份 PDF 文档,然后问它关于这份文档的问题。

3.1 准备知识库:文档加载与处理

创建一个 rag_demo.py 文件:

import os
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma

# 1. 加载文档(假设你有一个 example.pdf 在同级目录)
loader = PyPDFLoader("./example.pdf")
documents = loader.load()

# 2. 分割文本
# 大模型有上下文长度限制,必须把长文档切分成小块。
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,  # 每个块大约500字符
    chunk_overlap=50  # 块之间重叠50字符,避免语义被切断
)
texts = text_splitter.split_documents(documents)
print(f"将文档切分成了 {len(texts)} 个片段")

# 3. 创建嵌入模型和向量库
# 使用本地嵌入模型,无需额外API
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2") # 一个轻量且效果不错的模型

# 将文本片段转换为向量并存储到 Chroma(持久化到本地目录 `./chroma_db`)
vectorstore = Chroma.from_documents(
    documents=texts,
    embedding=embeddings,
    persist_directory="./chroma_db"
)
vectorstore.persist() # 持久化保存
print("向量知识库已创建并保存。")

关键参数解释

  • chunk_size :太小会丢失上下文,太大会超出模型处理能力。500-1000 是常见起点。
  • chunk_overlap :防止一个句子或概念被硬生生切成两半。
  • persist_directory :向量库保存路径。下次启动可以直接加载,无需重新处理文档。

3.2 实现检索与问答链

在同一个文件中继续添加:

from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI

# 4. 加载之前保存的向量库
vectorstore = Chroma(
    persist_directory="./chroma_db",
    embedding_function=embeddings
)

# 5. 创建检索器
retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) # 检索最相关的3个片段

# 6. 创建问答链
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff", # 最简单的方式,将所有检索到的内容“塞”进提示词
    retriever=retriever,
    return_source_documents=True # 返回参考来源,便于验证
)

# 7. 提问
query = "这份文档中提到的核心挑战是什么?"
result = qa_chain.invoke({"query": query})
print("答案:", result["result"])
print("\n--- 参考来源 ---")
for i, doc in enumerate(result["source_documents"]):
    print(f"[片段 {i+1}]: {doc.page_content[:200]}...") # 打印前200字符

运行这个脚本,你应该能得到一个基于文档内容的答案,并看到它参考了哪些原文片段。 这是 RAG 的核心验证点:答案必须源自你提供的文档,而不是模型的固有知识。

3.3 常见问题与排查

  • 问题 :答案看起来是模型自己编的,与文档无关。
    • 排查 :首先打印 result[“source_documents”] ,看检索到的片段是否真的与问题相关。如果不相关,可能是:
      1. 嵌入模型不适合你的文本类型(中文/英文,专业领域)。
      2. 文本切分不合理,破坏了语义。
      3. 检索数量 k 太小,可以尝试增加到 4 或 5。
  • 问题 :处理速度很慢。
    • 排查 :如果是第一次创建向量库慢,是正常的(在计算向量)。如果是查询慢,检查是否每次都在重新加载和计算嵌入。确保使用了 persist_directory 并正确加载了已保存的向量库。
  • 问题 :提示 “context length exceeded”
    • 排查 chunk_size 太大,或者 chain_type=“stuff” 时检索到的片段总长度超过了模型上下文限制。可以减小 chunk_size k ,或者使用更复杂的 chain_type ,如 “map_reduce”

4. 用 LangGraph 构建第一个智能体:让模型学会“规划与执行”

RAG 让模型有了知识,Agent 则让模型有了手脚。我们用 LangGraph 构建一个简单的“研究助手”智能体:它先规划,然后用工具搜索网络,最后总结。

4.1 定义智能体的状态与节点

LangGraph 的核心是定义“状态”(State)和“节点”(Node)。状态是一个字典,在节点间传递;节点是执行单元。

创建一个 agent_demo.py 文件:

from typing import TypedDict, Annotated, List
import operator
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_community.tools import DuckDuckGoSearchRun
from langchain_core.messages import HumanMessage, SystemMessage

# 1. 定义状态结构
class AgentState(TypedDict):
    question: str           # 用户的问题
    plan: List[str]        # 执行计划
    search_results: str    # 搜索到的信息
    final_answer: str      # 最终答案

# 2. 初始化工具和模型
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.2)
search_tool = DuckDuckGoSearchRun()

# 3. 定义各个节点函数
def planner_node(state: AgentState) -> AgentState:
    """规划节点:分析问题,拆解步骤"""
    messages = [
        SystemMessage(content="你是一个任务规划专家。请将复杂问题拆解为具体的、可执行的搜索步骤。"),
        HumanMessage(content=f"用户的问题是:{state['question']}\n请列出为了回答这个问题,需要依次搜索哪些关键信息。直接输出步骤列表,每步一行。")
    ]
    response = llm.invoke(messages)
    # 假设LLM返回的是文本形式的步骤列表
    plan = [step.strip() for step in response.content.split('\n') if step.strip()]
    return {"plan": plan}

def search_node(state: AgentState) -> AgentState:
    """搜索节点:执行计划中的搜索步骤"""
    all_results = []
    # 这里简化处理:只执行计划的第一步进行搜索
    if state['plan']:
        search_query = state['plan'][0]
        result = search_tool.run(search_query)
        all_results.append(f"搜索词:{search_query}\n结果:{result}\n")
    else:
        all_results.append("无明确搜索计划。")
    return {"search_results": "\n---\n".join(all_results)}

def answer_node(state: AgentState) -> AgentState:
    """回答节点:基于搜索结果为用户生成最终答案"""
    messages = [
        SystemMessage(content="你是一个信息分析员。请基于提供的搜索结果为用户的问题生成一个全面、准确的答案。"),
        HumanMessage(content=f"用户原问题:{state['question']}\n\n搜索到的信息如下:\n{state['search_results']}\n\n请生成最终答案。")
    ]
    response = llm.invoke(messages)
    return {"final_answer": response.content}

# 4. 构建图
workflow = StateGraph(AgentState)

# 添加节点
workflow.add_node("planner", planner_node)
workflow.add_node("searcher", search_node)
workflow.add_node("answerer", answer_node)

# 设置边(执行顺序)
workflow.set_entry_point("planner")
workflow.add_edge("planner", "searcher")
workflow.add_edge("searcher", "answerer")
workflow.add_edge("answerer", END)

# 编译图
app = workflow.compile()

# 5. 运行智能体
initial_state = {"question": "2024年巴黎奥运会中国代表团获得了多少枚金牌?", "plan": [], "search_results": "", "final_answer": ""}
final_state = app.invoke(initial_state)

print("最终答案:")
print(final_state["final_answer"])
print("\n执行计划:")
for i, step in enumerate(final_state["plan"]):
    print(f"{i+1}. {step}")

这个智能体虽然简单,但完整展示了 LangGraph 的流程:状态传递、节点分工、顺序执行。

4.2 理解 LangGraph 的关键要素

  • 状态(State) :是所有节点共享的“记忆体”。我们定义了一个 TypedDict 来规定它的结构。好的状态设计是构建复杂 Agent 的基础。
  • 节点(Node) :每个节点是一个函数,接收状态,修改状态的一部分,然后返回。节点应该职责单一。
  • 边(Edge) :决定流程走向。可以是固定顺序( add_edge ),也可以根据条件动态决定( add_conditional_edges ),这是实现循环和分支的关键。
  • 编译(Compile) :将图定义编译成一个可执行的应用( app )。

4.3 让智能体更强大:条件路由与循环

上面的例子是直线流程。真正的智能体需要“思考-行动-观察-再思考”的循环。修改 search_node 和图的逻辑,可以实现多步搜索:

from langgraph.graph import StateGraph, END
from langgraph.checkpoint import MemorySaver
from langgraph.graph.message import add_messages

# 使用更强大的状态,包含消息历史
class AgentState(TypedDict):
    messages: Annotated[List, add_messages] # LangGraph 提供的消息管理
    question: str
    search_count: int

def should_continue(state: AgentState) -> str:
    """判断是否继续搜索"""
    # 简单逻辑:如果搜索次数少于2次,且最新消息不是最终答案,就继续
    if state['search_count'] < 2 and "最终答案" not in state['messages'][-1].content:
        return "search"
    else:
        return "generate_answer"

# 在构建图时使用条件边
workflow = StateGraph(AgentState)
workflow.add_node("planner", planner_node)
workflow.add_node("searcher", search_node)
workflow.add_node("answerer”, answer_node)

workflow.set_entry_point("planner")
workflow.add_edge("planner", "searcher")
# 关键:条件路由。执行完 searcher 后,由 should_continue 函数决定下一步去哪
workflow.add_conditional_edges(
    "searcher",
    should_continue,
    {
        "search": "searcher", # 继续搜索
        "generate_answer": "answerer" # 去生成答案
    }
)
workflow.add_edge("answerer", END)

这样,智能体就可以根据中间结果,决定是继续搜索还是给出最终答案,实现了基本的自主性。

5. 将 RAG 与 Agent 融合:构建拥有私有知识的智能助手

单独能查资料(RAG),单独能规划执行(Agent),现在我们把它们结合起来,构建一个能利用你私有知识库进行复杂推理和任务执行的超级助手。

5.1 设计融合架构

思路是:在 Agent 的工具箱(Toolkit)里,增加一个“查询知识库”的工具。当 Agent 在规划或执行中,认为需要参考内部文档时,就调用这个工具。

我们基于之前的 RAG 和 Agent 代码进行整合:

# rag_agent_demo.py
import os
from typing import TypedDict, Annotated, List
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.tools import DuckDuckGoSearchRun
from langchain.agents import Tool, AgentExecutor, create_react_agent
from langchain_core.prompts import PromptTemplate
from langchain_core.messages import SystemMessage

# --- 第一部分:初始化 RAG 检索工具 ---
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
vectorstore = Chroma(persist_directory="./chroma_db", embedding_function=embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

def query_knowledge_base(query: str) -> str:
    """一个查询私有知识库的工具函数"""
    docs = retriever.get_relevant_documents(query)
    context = "\n\n".join([doc.page_content for doc in docs])
    if not context:
        return "在知识库中未找到相关信息。"
    # 可以在这里加入一个LLM调用,对检索结果进行精炼,这里直接返回上下文
    return f"根据知识库,相关信息如下:\n{context}"

# --- 第二部分:定义 Agent 的工具 ---
search_tool = DuckDuckGoSearchRun()
rag_tool = Tool(
    name="InternalKnowledgeBase",
    func=query_knowledge_base,
    description="当问题涉及公司内部文档、产品手册、私有资料时,使用此工具查询。输入是一个具体的问题或关键词。"
)

tools = [search_tool, rag_tool]

# --- 第三部分:使用 LangChain 的 ReAct Agent 框架 ---
llm = ChatOpenAI(model="gpt-4", temperature=0) # 使用能力更强的模型做Agent推理

# ReAct 提示模板鼓励模型“思考”和“行动”
prompt = PromptTemplate.from_template(
    """你是一个拥有内部知识库和网络搜索能力的智能助手。请遵循以下步骤:
1. 思考:分析用户问题,判断是否需要查询内部知识库或搜索网络。
2. 行动:如果需要,调用合适的工具。工具调用格式为:
    Action: 工具名
    Action Input: 工具的输入内容
3. 观察:你会收到工具返回的结果。
4. 重复思考、行动、观察,直到你认为可以给出最终答案。
5. 最终答案:基于所有观察,给出清晰、准确的回答。

当前对话:
{chat_history}
问题:{input}
思考:{agent_scratchpad}"""
)

agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True)

# --- 第四部分:运行测试 ---
question = "根据我们公司的产品手册,旗舰产品的主要技术优势是什么?另外,对比一下市面上同类产品的近期动态。"
result = agent_executor.invoke({"input": question, "chat_history": []})
print("\n" + "="*50)
print("最终答案:")
print(result["output"])

这个融合后的智能体,在面对问题时,会先“思考”:“这个问题关于公司产品,应该先查内部知识库”。然后调用 InternalKnowledgeBase 工具,获取私有文档信息。接着,它可能继续“思考”:“还需要了解市场动态”,于是调用网络搜索工具。最后,综合两者信息生成答案。

5.2 调试与优化技巧

  1. 开启详细日志 AgentExecutor(..., verbose=True) 会打印出 Agent 的思考过程、工具调用和结果,这是调试的黄金信息。
  2. 优化工具描述 :工具的 description 字段至关重要。Agent 根据描述决定是否以及何时调用工具。描述要准确说明工具的用途和输入格式。
  3. 处理解析错误 handle_parsing_errors=True 可以防止因为 Agent 输出格式偶尔不符合预期而导致整个流程崩溃。
  4. 控制循环 :Agent 可能会陷入“思考-调用-再思考”的死循环。可以通过设置 max_iterations 参数来限制最大步数。

6. 生产环境考量与进阶方向

当你跑通了 Demo,接下来就要考虑如何让它更健壮、更实用。

6.1 性能与稳定性

  • 异步处理 :对于批量处理用户查询,使用 ainvoke 等异步接口,避免阻塞。
  • 缓存 :对频繁查询的相似问题,对 LLM 响应和向量检索结果进行缓存,显著降低成本和提高速度。LangChain 提供了 RedisCache InMemoryCache 等组件。
  • 限流与降级 :对 API 调用进行限流,防止超额。当主要模型 API 不可用时,要有备用的模型或返回兜底答案。
  • 监控与日志 :记录每一次用户交互、工具调用、Token 消耗、响应时间。这对于分析成本、优化提示词、排查问题必不可少。

6.2 RAG 效果提升

  • 更好的文本分割 :尝试不同的分割策略,如按语义分割( SemanticSplitter ),而不是简单按字符长度。
  • 重排序(Rerank) :检索出 Top K 个片段后,使用一个更精细的模型(如 bge-reranker )对它们进行相关性重排序,只把最相关的几个送给 LLM,提升答案质量并节省 Token。
  • 元数据过滤 :在存储向量时,为每个片段添加元数据(如所属章节、文档类型、创建日期)。检索时,可以结合元数据进行过滤,实现更精准的查询。
  • 多轮对话 :在对话历史中维护上下文,将历史对话也纳入检索查询的构建中,使 RAG 能处理“你刚才说的那个功能”这类指代性问题。

6.3 Agent 能力增强

  • 工具学习 :让 Agent 能够学习使用新工具,而不仅仅是预定义的工具列表。
  • 长期记忆 :为 Agent 配备向量数据库存储对话历史,使其在长对话中保持一致性,并能回忆很久以前讨论过的事情。这可以通过 LangGraph 的检查点(Checkpoint)和持久化状态来实现。
  • 多智能体协作 :创建多个具有不同专长(如分析、写作、审核)的 Agent,让它们通过消息传递协同完成复杂任务。LangGraph 非常适合编排这种多智能体系统。
  • 验证与安全 :对 Agent 将要执行的操作(特别是写数据库、发邮件、调用付费 API)进行确认或审核,避免出现意外后果。

6.4 部署与集成

  • API 服务化 :使用 FastAPI 或 Flask 将你的智能体封装成 REST API,方便与其他系统集成。
  • 前端界面 :构建一个简单的 Web 聊天界面,使用 Streamlit、Gradio 或 Chainlit 可以快速原型。
  • 持续集成/持续部署 :像管理其他软件项目一样,为你的 AI 应用建立代码仓库、测试和部署流程。

我个人更建议先把单任务跑稳,再考虑批量和接口。这个方案真正落地时,最该盯住的不是功能列表,而是输入格式、资源占用和失败重试。踩过几次之后我发现,很多问题不是工具能力不够,而是前置环境和输入材料没有处理干净。从清晰的提示词,到干净的文档切片,再到定义明确的 Agent 状态和工具,每一步的严谨性,最终决定了整个系统的可靠程度。

更多推荐