基于LangChain、LangGraph与LangSmith构建医疗问诊AI Agent全流程解析
这次我们来看一个医疗问诊 Agent 的实现案例。这个项目不是一个具体的开源工具包,而是一个典型的 AI Agent 应用场景构建过程,它清晰地展示了如何利用 LangChain、LangGraph 和 LangSmith 这三个核心框架来打造一个具备复杂逻辑的智能体。对于想入门 AI Agent 开发,特别是想理解这几个框架如何协同工作的开发者来说,这个案例非常有价值。
它的核心不是提供一个“开箱即用”的医疗诊断工具,而是通过一个贴近实际的场景,拆解 Agent 开发中的关键环节:如何编排任务流程、如何管理状态、如何集成工具、以及如何调试和监控。本文将带你从零开始,理解如何将这些框架组合起来,构建一个能处理多轮对话、调用知识库、并生成结构化诊疗建议的智能体。
本文适合有一定 Python 基础,对 LLM 应用开发感兴趣,希望从“调用 API”进阶到“构建智能工作流”的开发者。我们将重点关注这三个框架的分工、集成方式、以及在实际开发中可能遇到的坑。虽然不涉及显存或 GPU 门槛,但我们会关注另一个关键“资源”:Token 消耗与 API 成本控制。
1. 核心能力速览:框架分工与项目定位
首先,我们需要明确 LangChain、LangGraph 和 LangSmith 在这个医疗问诊 Agent 项目中各自扮演的角色。它们不是三个可任选其一的替代品,而是构建生产级 Agent 的不同层面的工具。
| 能力项 | 说明 | 在医疗问诊 Agent 中的体现 |
|---|---|---|
| LangChain | 基础组件与标准接口 。提供与 LLM 对话、连接向量数据库、调用工具(如计算器、搜索)的标准模块。 | 用于封装与 OpenAI/Gemini 等模型的对话链(Chain),集成医疗知识库的检索器(Retriever),定义“症状分析”、“用药查询”等基础工具(Tool)。 |
| LangGraph | 复杂工作流与状态管理 。用于构建有状态、多步骤、带循环和条件分支的 Agent 执行图。 | 用于定义问诊流程:用户输入 -> 意图判断 -> 检索知识 -> 分析症状 -> 生成建议 -> 是否需要追问 -> (循环) -> 最终输出。它管理整个对话的“状态”(State)。 |
| LangSmith | 开发调试与运维监控 。提供链/图的跟踪、可视化、测试、评估和监控平台。 | 用于记录每一次问诊的完整执行轨迹,查看 LLM 的输入输出,分析耗时和 Token 消耗,评估 Agent 回复的质量,监控生产环境下的运行情况。 |
| 项目类型 | AI Agent 应用开发示范 | 一个教学/示范性质的项目,展示如何将三个框架组合解决复杂问题。 |
| 硬件门槛 | 无特殊要求,依赖云 LLM API | 主要成本为 LLM API 调用费用(如 OpenAI GPT-4)。本地运行只需能运行 Python 的环境。 |
| 核心功能 | 多轮医疗问诊、知识检索、结构化输出 | 模拟医生问诊流程,结合医学知识库,生成包含可能疾病、建议检查、生活建议的结构化回答。 |
| 适合场景 | AI Agent 学习、复杂工作流原型开发、LLM 应用调试 | 开发者学习 Agent 架构,企业构建内部专家系统原型,需要可观测性的 LLM 应用场景。 |
简单来说: LangChain 提供了砖块(工具、记忆、检索),LangGraph 提供了设计图和施工流程(将砖块组装成有逻辑的房子),而 LangSmith 提供了监理和质检(确保房子盖得对、盖得好)。
2. 适用场景与使用边界
这个医疗问诊 Agent 案例主要服务于学习和原型验证目的。
它适合谁:
- AI 应用开发者 :想了解如何超越简单问答,构建具有复杂逻辑链的智能体。
- 技术决策者/架构师 :评估 LangChain 生态是否适合用于构建企业内部的智能客服、审批流程、诊断系统等。
- 学生与研究人员 :需要一个完整的、可运行的案例来理解 Agent 的架构思想和实现细节。
它能解决什么问题:
- 技术选型困惑 :直观展示 LangChain、LangGraph、LangSmith 分别做什么,以及为什么需要它们三者。
- 工作流设计样板 :提供一个包含“判断-执行-循环”的图结构样板,可快速修改用于其他领域(如法律咨询、技术支持)。
- 调试与监控实践 :给出一个从开发到观测的完整闭环,让开发者体验如何追踪一个复杂 Agent 的每一次内部决策。
它不适合什么场景:
- 直接用于真实医疗诊断 :这是一个技术演示项目,其医学知识库通常是公开的、通用的数据集(如医学百科),不具备临床诊断的准确性和权威性。 绝对不可 用于真实病情诊断。
- 开箱即用的生产系统 :它缺乏用户认证、数据加密、审计日志、模型备案等生产级功能,需要大量二次开发和合规改造。
- 替代简单的 LLM 调用 :如果需求只是单轮问答或文本总结,直接调用 LLM API 或使用 LangChain 的简单 Chain 即可,引入 LangGraph 会增加不必要的复杂度。
重要边界与合规提醒:
- 非医疗设备 :本项目构建的 Agent 是软件原型,不属于医疗器械。任何涉及生命健康的领域,应用都必须遵循相关法律法规,并接受专业人员的监督。
- 知识库版权 :使用的医学知识库必须确保来源合法,拥有使用授权。
- 数据隐私 :如果处理真实用户问诊数据,必须实施严格的匿名化、加密和访问控制,符合《个人信息保护法》等数据安全法规。
- 结果免责 :必须向最终用户明确提示,输出内容仅为参考信息,不能替代专业医生诊断。
3. 环境准备与前置条件
在开始构建之前,需要准备好基础的开发环境和必要的账户。
1. 基础开发环境:
- 操作系统 :Windows 10/11, macOS, 或 Linux (如 Ubuntu 20.04+)。
- Python 版本 :推荐 Python 3.10 或 3.11。避免使用 Python 3.12+ 可能存在的某些库兼容性问题。
- 包管理工具 :使用
pip或conda。
2. 核心框架安装: 我们将安装 LangChain 的核心包、LangGraph 以及 LangSmith 的 SDK。
# 创建并激活虚拟环境(推荐)
python -m venv venv
# Windows:
venv\Scripts\activate
# Linux/macOS:
source venv/bin/activate
# 安装核心框架
pip install langchain langgraph langsmith
# 安装可选但常用的依赖
pip install openai tiktoken # 用于 OpenAI 模型调用和 Token 计数
pip install chromadb pypdf # 用于构建示例知识库(向量数据库和 PDF 解析)
3. 云服务 API 密钥:
- LLM 提供商 :你需要一个 OpenAI API 密钥(或 Anthropic、Gemini 等 LangChain 支持的模型)。本项目以 OpenAI 为例。
- 访问 OpenAI Platform 创建密钥。
- 将密钥设置为环境变量:
# Windows (PowerShell) $env:OPENAI_API_KEY="your-api-key-here" # Linux/macOS export OPENAI_API_KEY="your-api-key-here"
- LangSmith 账户 (用于跟踪和监控):
- 访问 LangSmith 注册并创建 API 密钥。
- 同样设置为环境变量:
export LANGCHAIN_API_KEY="your-langsmith-api-key-here" export LANGCHAIN_TRACING_V2="true" export LANGCHAIN_PROJECT="Medical-Agent-Demo" # 你的项目名 - 设置后,所有运行记录将自动同步到你的 LangSmith 项目面板。
4. 知识库素材(可选,用于模拟检索): 准备一些医学相关的文本或 PDF 文件,例如公共卫生指南、疾病百科摘要等,用于构建一个本地的示例向量数据库。
4. 项目结构与核心模块搭建
我们按照“自底向上”的顺序来构建这个 Agent:先准备工具和知识,再定义单步动作,最后用图编排整个流程。
4.1 第一步:利用 LangChain 构建基础能力
首先,我们用 LangChain 创建这个 Agent 所需的“砖块”。
1. 创建 LLM 调用实例: 这是所有智能的源头。
from langchain_openai import ChatOpenAI
# 使用 GPT-4 或 GPT-3.5-Turbo。注意控制成本。
llm = ChatOpenAI(model="gpt-4-turbo-preview", temperature=0.1)
# temperature 调低使输出更稳定,适合任务型 Agent。
2. 创建医疗知识检索器: 模拟一个拥有医学知识的“大脑外挂”。
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
# 1. 加载文档 (示例:加载一个假设的“家庭医疗指南.pdf”)
loader = PyPDFLoader("./data/family_medical_guide.pdf") # 请准备你的PDF文件
documents = loader.load()
# 2. 分割文本
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
texts = text_splitter.split_documents(documents)
# 3. 创建向量数据库
embeddings = OpenAIEmbeddings() # 需要 OPENAI_API_KEY
vectorstore = Chroma.from_documents(texts, embeddings, persist_directory="./chroma_db")
retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) # 检索最相关的3个片段
这段代码创建了一个本地向量数据库。在生产环境中,你可能需要连接已有的医学知识库或使用更专业的向量数据库如 Weaviate、Pinecone。
3. 定义 Agent 可用的工具: 工具是 Agent 与世界交互的手脚。我们定义几个简单的工具。
from langchain.tools import tool
from typing import Optional
@tool
def search_medical_knowledge(query: str) -> str:
"""根据用户问题,检索相关的医学知识。"""
docs = retriever.get_relevant_documents(query)
return "\n\n".join([doc.page_content for doc in docs])
@tool
def analyze_symptoms(symptom_description: str) -> str:
"""分析症状描述,初步归纳可能的疾病方向。调用LLM进行分析。"""
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你是一位经验丰富的全科医生助理。请根据以下症状描述,列出3-5种最可能的疾病方向,并简要说明理由。只输出分析结果。"),
("human", "症状:{symptoms}")
])
chain = prompt | llm
return chain.invoke({"symptoms": symptom_description}).content
@tool
def format_final_advice(disease_analysis: str, knowledge_context: str) -> str:
"""整合疾病分析和医学知识,生成最终给患者的建议,包括就医建议和家庭护理。"""
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你正在生成一份患者咨询报告。请基于疾病可能性分析和相关医学知识,生成一份结构清晰、语气关切的最终建议。"),
("human", "疾病可能性分析:\n{analysis}\n\n相关医学知识:\n{context}")
])
chain = prompt | llm
return chain.invoke({"analysis": disease_analysis, "context": knowledge_context}).content
现在,我们有了知识库 ( retriever )、大模型 ( llm ) 和三个工具 ( search_medical_knowledge , analyze_symptoms , format_final_advice )。接下来,需要用 LangGraph 把它们串起来。
5. 使用 LangGraph 编排问诊工作流
LangGraph 的核心是 State(状态) 和 Graph(图) 。状态是一个字典,保存着对话的上下文;图由节点(函数)和边(条件)组成,定义了执行流程。
5.1 定义状态
首先,我们定义这个医疗问诊 Agent 需要记住哪些信息。
from typing import TypedDict, Annotated, List
import operator
class AgentState(TypedDict):
"""定义Agent的对话状态。"""
# 用户输入
user_input: str
# 当前对话轮次
conversation_turn: int
# 从用户描述中提取的关键症状
extracted_symptoms: str
# 检索到的医学知识
medical_knowledge: str
# 症状分析结果
symptom_analysis: str
# 是否需要进一步追问(由LLM判断)
need_clarification: bool
# 追问的问题
clarification_question: str
# 最终输出的建议
final_advice: str
# 执行过程中的消息记录(用于LLM上下文)
messages: Annotated[List, operator.add]
5.2 构建图节点
每个节点是一个函数,它读取和修改 State 。
节点1:路由节点(判断意图) 这是第一个节点,决定本次对话要做什么。
from langgraph.graph import StateGraph, END
def route_question(state: AgentState):
"""根据用户输入和历史,判断是开始新问诊、继续追问还是结束。"""
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "你是医疗问诊Agent的调度中心。请分析用户输入。如果用户描述了新的症状,请说'new_case'。如果用户是在回答上一个追问,请说'clarify'。如果用户表示感谢或结束,请说'end'。只输出这三个词之一。"),
("human", "用户输入:{input}\n当前轮次:{turn}")
])
chain = prompt | llm
decision = chain.invoke({"input": state["user_input"], "turn": state["conversation_turn"]}).content.strip().lower()
if decision == "new_case":
return {"conversation_turn": state["conversation_turn"] + 1, "extracted_symptoms": state["user_input"]}
elif decision == "clarify":
return {"need_clarification": False} # 收到澄清,继续流程
elif decision == "end":
return {"final_advice": "感谢咨询,请保重身体。"}
else:
# 默认按新病例处理
return {"conversation_turn": state["conversation_turn"] + 1, "extracted_symptoms": state["user_input"]}
节点2:检索知识节点
def retrieve_knowledge(state: AgentState):
"""根据提取的症状,检索相关医学知识。"""
knowledge = search_medical_knowledge.invoke(state["extracted_symptoms"])
return {"medical_knowledge": knowledge}
节点3:分析症状节点
def analyze_symptoms_node(state: AgentState):
"""调用工具分析症状。"""
analysis = analyze_symptoms.invoke(state["extracted_symptoms"])
return {"symptom_analysis": analysis}
节点4:判断是否需要追问节点
def should_clarify(state: AgentState):
"""根据现有信息,判断是否需要向用户追问更多细节。"""
from langchain_core.prompts import ChatPromptTemplate
context = f"症状:{state['extracted_symptoms']}\n初步分析:{state['symptom_analysis']}\n相关知识:{state['medical_knowledge'][:500]}..."
prompt = ChatPromptTemplate.from_messages([
("system", "作为医生,根据现有信息,你是否需要询问患者更多细节(如症状持续时间、具体部位、年龄等)才能给出更靠谱的建议?如果需要,请生成一个具体的追问问题。如果不需要,请说'NO'。"),
("human", "{context}")
])
chain = prompt | llm
result = chain.invoke({"context": context}).content.strip()
if result != "NO" and len(result) > 5:
return {"need_clarification": True, "clarification_question": result}
else:
return {"need_clarification": False}
节点5:生成最终建议节点
def generate_advice(state: AgentState):
"""整合所有信息,生成最终建议。"""
advice = format_final_advice.invoke({
"disease_analysis": state["symptom_analysis"],
"knowledge_context": state["medical_knowledge"]
})
return {"final_advice": advice}
节点6:生成追问节点
def ask_clarification(state: AgentState):
"""直接返回需要追问的问题。"""
return {"final_advice": state["clarification_question"]}
5.3 组装图并设置条件边
现在,我们把所有节点组装起来,并定义它们之间的流转逻辑。
# 初始化图
workflow = StateGraph(AgentState)
# 添加节点
workflow.add_node("route", route_question)
workflow.add_node("retrieve", retrieve_knowledge)
workflow.add_node("analyze", analyze_symptoms_node)
workflow.add_node("decide_clarify", should_clarify)
workflow.add_node("generate", generate_advice)
workflow.add_node("ask", ask_clarification)
# 设置入口点
workflow.set_entry_point("route")
# 添加边(定义节点执行后的流向)
workflow.add_edge("route", "retrieve") # 路由后总是先检索知识
workflow.add_edge("retrieve", "analyze") # 检索后分析症状
workflow.add_edge("analyze", "decide_clarify") # 分析后决定是否追问
# 条件边:根据是否需要追问,决定下一步
from langgraph.graph import END
def decide_after_clarify(state):
if state.get("need_clarification"):
return "ask" # 需要追问,跳转到提问节点
else:
return "generate" # 不需要,直接生成建议
workflow.add_conditional_edges(
"decide_clarify",
decide_after_clarify,
{
"ask": "ask",
"generate": "generate",
}
)
# 设置终点
workflow.add_edge("ask", END) # 追问后,本轮结束,等待用户下一次输入(新一轮`route`)
workflow.add_edge("generate", END) # 生成建议后,本轮结束
# 编译图
app = workflow.compile()
至此,一个具备基本多轮对话能力的医疗问诊 Agent 图就构建完成了。你可以通过 app.invoke() 来运行它。
6. 运行、测试与 LangSmith 监控
6.1 运行你的 Agent
# 初始化一个状态
initial_state = {
"user_input": "我最近三天一直头痛,还有点发烧。",
"conversation_turn": 0,
"extracted_symptoms": "",
"medical_knowledge": "",
"symptom_analysis": "",
"need_clarification": False,
"clarification_question": "",
"final_advice": "",
"messages": []
}
# 运行图
try:
final_state = app.invoke(initial_state)
print("=== 最终建议 ===")
print(final_state["final_advice"])
except Exception as e:
print(f"运行出错:{e}")
6.2 在 LangSmith 中查看执行轨迹
这是 LangSmith 的核心价值所在。只要你正确设置了 LANGCHAIN_API_KEY ,上面的 app.invoke() 调用会自动在 LangSmith 上创建一次跟踪(Trace)。
- 打开 LangSmith 并登录。
- 进入你设置的项目(如
Medical-Agent-Demo)。 - 你应该能看到刚刚运行的记录。点击进入详情。
- 在这里,你可以看到:
- 完整的执行流程图 :清晰地展示了从
route到retrieve、analyze、decide_clarify,再到generate或ask的完整路径。 - 每个节点的输入输出 :点击任意节点,可以看到调用工具时的具体参数、LLM 的 Prompt 和 Response。
- 耗时分析 :每个步骤花费的时间,帮你定位性能瓶颈。
- Token 消耗 :每次调用 LLM 消耗的 Token 数,用于成本核算。
- 异常信息 :如果运行出错,会在这里清晰显示。
- 完整的执行流程图 :清晰地展示了从
通过 LangSmith,调试 Agent 从“黑盒”变成了“白盒” 。你可以精确地知道是哪个节点的 LLM 判断失误,还是工具调用返回了空信息,从而有针对性地优化 Prompt 或逻辑。
7. 功能测试与效果验证策略
对于这样一个工作流复杂的 Agent,测试不能只靠一次运行。我们需要系统性地验证各个环节。
| 测试类型 | 测试目的 | 输入示例 | 预期结果与成功标准 |
|---|---|---|---|
| 单轮完整问诊 | 验证主流程是否通畅。 | “我喉咙痛,咳嗽有黄痰。” | 1. 成功检索到“上呼吸道感染”等相关知识。 2. 症状分析节点输出合理的疾病可能性列表。 3. 最终生成包含“建议就医”、“多喝水”等要点的结构化建议。 |
| 触发追问分支 | 验证条件逻辑是否正确。 | “我肚子疼。”(信息不完整) | 1. decide_clarify 节点判断 need_clarification 为 True。 2. 流程走向 ask 节点。 3. 最终输出一个具体的追问问题,如“请问疼痛具体在哪个部位?是左上腹还是右下腹?” |
| 多轮对话衔接 | 验证状态管理是否有效。 | 第一轮: “我头痛。” -> Agent追问: “是哪种痛?胀痛还是刺痛?” 第二轮: “是胀痛,还有点头晕。” |
1. 第二轮输入时, route 节点能正确识别为 clarify 。 2. Agent 能结合第一轮的症状(头痛)和第二轮的澄清(胀痛、头晕)进行综合分析和检索。 3. 最终建议应比第一轮更精准。 |
| 知识检索有效性 | 验证向量数据库是否工作。 | 输入一个知识库中存在的特定术语,如“糖尿病足护理”。 | retrieve 节点返回的 medical_knowledge 字段包含相关文本片段,而不是无关内容。 |
| 异常输入处理 | 验证鲁棒性。 | 输入“谢谢,不用了。”或无关文本“今天天气真好”。 | 1. route 节点能识别为 end 或合理处理。 2. 流程正常结束,不抛出未处理异常。 |
| LangSmith 跟踪 | 验证可观测性。 | 任何一次正常调用。 | 在 LangSmith 平台能查到本次运行的完整轨迹图,所有节点的输入输出可见。 |
效果验证的核心 :不仅要看最终输出是否“通顺”,更要通过 LangSmith 跟踪 ,检查每个中间节点的决策是否符合预期。例如, should_clarify 节点生成的追问问题是否具体、必要? route 节点的意图分类是否准确?
8. 资源占用、性能与成本观察
对于此类基于云 LLM API 的 Agent,主要“资源”是 API 调用成本 和 响应延迟 。
1. Token 消耗与成本:
- 主要消耗点 :
route_question:每次用户输入都调用,但 Prompt 短,消耗少。analyze_symptoms和format_final_advice:这两个节点包含主要分析任务,Prompt 较长,消耗 Token 最多。should_clarify:每次判断是否追问时调用。search_medical_knowledge:检索本身不消耗 Token,但检索到的文本会作为上下文送入后续的 LLM 调用, 显著增加 Token 数 。
- 优化策略 :
- 知识检索优化 :调整
search_kwargs={"k": 3}中的k值,返回更少但更精确的片段。使用MMR等搜索类型去重。 - 上下文压缩 :在将检索结果喂给 LLM 前,使用
ContextualCompressionRetriever进行摘要或过滤。 - 选择模型 :在非核心分析环节(如
route)使用更便宜的模型(如gpt-3.5-turbo)。
- 知识检索优化 :调整
2. 响应延迟:
- 主要瓶颈 :
- LLM API 调用 :尤其是 GPT-4,每次生成响应可能有数百毫秒到数秒的延迟。
- 网络延迟 :与 OpenAI 服务器的网络状况。
- 检索延迟 :如果向量数据库在远程或数据量大,检索可能变慢。
- 优化策略 :
- 异步调用 :LangGraph 支持异步节点,如果流程中某些步骤不严格依赖前序结果,可考虑异步执行。
- 缓存 :对频繁出现的相似用户查询(如“感冒症状”),可以使用 LangChain 的缓存组件,避免重复调用 LLM 和检索。
- 本地小模型 :对于路由、分类等简单任务,可尝试使用本地部署的小模型(如通过 Ollama 运行
llama3),大幅降低延迟和成本。
3. 本地资源占用:
- 内存/CPU :运行 LangChain/LangGraph 脚本本身占用很小。主要压力来自:
- 向量数据库 :Chroma 在本地运行时会加载索引到内存。知识库越大,内存占用越高。
- 嵌入模型 :如果使用本地嵌入模型(如
all-MiniLM-L6-v2),推理时需要 CPU/GPU 资源。
- 磁盘空间 :用于存储向量数据库索引文件(
./chroma_db)和缓存的模型文件。
9. 常见问题与排查方法
在开发此类 Agent 时,你会遇到一些典型问题。以下是排查思路。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
运行时报 KeyError |
在 State 中引用了尚未定义的键。 |
检查报错行数,对应节点的返回值字典中是否包含了 State 中定义的所有必需键? |
确保每个节点函数返回的字典键名与 AgentState 定义完全一致。初始化 initial_state 时给所有键赋初始值(空字符串或空列表)。 |
| Agent 陷入死循环 | 条件边逻辑有误,导致在两个节点间来回跳转。 | 在 LangSmith 中查看执行轨迹图,检查循环发生在哪两个节点之间。检查 decide_after_clarify 这类条件函数的逻辑。 |
确保条件函数返回的结果一定能映射到某个已定义的边。为循环设置最大迭代次数,在 State 中添加 step_count 并在图中检查。 |
| LLM 调用超时或失败 | API 密钥错误、网络问题、额度不足、模型超载。 | 查看 LangSmith 中失败节点的详细日志。在代码中捕获 openai.APIError 异常。 |
检查环境变量 OPENAI_API_KEY 。添加重试机制(LangChain 内置)。考虑切换模型或备用 API 端点。 |
| 知识检索结果不相关 | 嵌入模型不匹配、文本分割不当、搜索参数 k 值不合适。 |
检查检索到的文本片段,看是否与查询语义相关。尝试不同的 chunk_size 和 chunk_overlap 。 |
优化文本分割策略。尝试不同的嵌入模型。使用混合搜索(MMR)平衡相关性与多样性。清洗知识库源数据。 |
route 节点判断不准 |
Prompt 指令不清晰或示例不足。 | 在 LangSmith 中查看 route 节点的输入和输出,看 LLM 是否误解了指令。 |
优化 Prompt,提供更明确的指令和少量示例(Few-shot)。或者,使用更简单的规则(如关键词匹配)进行初筛。 |
| 最终建议空洞或格式化错误 | format_final_advice 工具的 Prompt 不够具体,或输入信息质量差。 |
检查输入给该工具的参数 disease_analysis 和 knowledge_context 是否充实。 |
强化该工具的 Prompt,要求其以特定格式(如 Markdown 列表)输出。在前置节点确保输入信息的质量。 |
| LangSmith 看不到跟踪记录 | 环境变量未生效、项目名错误、网络问题。 | 1. 在 Python 中打印 os.getenv(“LANGCHAIN_API_KEY”) 确认。 2. 检查 LangSmith 网站上的项目名是否匹配。 |
确保在运行脚本的终端中正确设置了环境变量。检查 LANGCHAIN_TRACING_V2 是否为 ”true” 。 |
10. 最佳实践与项目演进建议
基于这个医疗问诊 Agent 原型,你可以遵循以下实践将其变得更实用、更健壮。
1. 工程化与代码组织:
- 模块化 :将工具定义、图构建、状态定义、Prompt 模板分别放在不同的
.py文件中。 - 配置管理 :使用
pydantic-settings或python-dotenv管理 API 密钥、模型名称、检索参数等配置。 - 版本控制 :对 Prompt、图结构、工具定义进行版本管理,便于回滚和对比实验。
2. 提升 Agent 能力:
- 更复杂的工具 :集成真实的医疗 API(需合规授权),如药品数据库查询、医院科室推荐。
- 记忆机制 :使用 LangChain 的
ConversationBufferMemory或ConversationSummaryMemory,让 Agent 记住更长的对话历史。 - 多智能体协作 :使用 LangGraph 的
MultiAgent特性,模拟“分诊护士”、“专科医生”、“药剂师”等多个角色协作问诊。 - 流式输出 :对于最终建议,实现逐字或逐句的流式输出,提升用户体验。
3. 强化评估与监控:
- 定义评估指标 :在 LangSmith 中创建数据集,定义“建议相关性”、“医学安全性”、“回答完整性”等评估标准。
- 自动化测试 :编写 pytest 用例,模拟各种用户输入,确保核心流程稳定。
- 生产环境监控 :利用 LangSmith 的监控功能,设置警报,关注异常高的失败率或延迟。
4. 合规与安全加固:
- 输入输出过滤 :对用户输入和 Agent 输出进行敏感词过滤和内容安全审核。
- 审计日志 :记录所有用户交互和 Agent 决策,满足合规审计要求。
- 医生审核回路 :设计机制,将高风险或不确定的建议标记出来,交由人类医生复核。
构建一个实用的 AI Agent 是一个迭代过程。从这个医疗问诊的案例出发,理解 LangChain、LangGraph、LangSmith 如何各司其职,你就掌握了拆解复杂问题、设计工作流、并实现可观测、可调试智能系统的核心方法。接下来,你可以尝试将这套架构应用到客服、教育、内容创作等更多领域,打造真正解决实际问题的智能体。
更多推荐

所有评论(0)