从零搭建一个中医养生 Agent:LangChain ReAct + FastAPI 实战

0 阅读5分钟

从零搭建一个中医养生 Agent:LangChain ReAct + FastAPI 实战

本文记录了我为“小甘草”中医养生助手构建 AI Agent 的核心过程,包括工具函数定义、LangChain ReAct Agent 搭建、本地 Ollama 集成及 FastAPI 服务封装。使用 LangChain 官方组件,兼顾开发效率与可控性。

一、背景与目标

项目简介:小甘草是一个中医养生咨询平台,用户可以通过对话询问体质、获取食疗穴位建议。
为什么需要 Agent?需要主动调用工具(查体质、生成方案、查天气等),而非简单的问答。

  • 技术选型:Python + LangChain(create_react_agent + AgentExecutor)+ Ollama(本地模型)+ FastAPI。
  • 本文目标:分享从零到可用的 Agent 服务搭建过程,包括工具函数、Agent 配置、FastAPI 封装及与 Node.js 后端的集成思路。

二、整体架构

image.png

  • 前端:Vue 3
  • 后端:Node.js(处理用户认证、体质问卷等,调用 Agent 服务)
  • Agent 服务:Python + FastAPI + LangChain(create_react_agent
  • 模型:本地 Ollama(Qwen2-1.5B)或 DeepSeek API
  • 存储:Supabase(业务数据)+ ChromaDB(向量知识库,后续)

三、阶段 0:环境准备与基础设施

3.1 创建虚拟环境与安装依赖

python -m venv venv
venv\Scripts\activate
pip install fastapi uvicorn langchain langchain-community langchain-openai python-dotenv

3.2 目录结构

agent-service/
├── agents/
├── tools/
├── models/
├── rag/
├── memory/
├── utils/
├── .env
├── requirements.txt
└── main.py

3.3 环境变量配置(.env)

DEEPSEEK_API_KEY=xxx   # 或使用 Ollama

3.4 锁定依赖版本

pip freeze > requirements.txt

四、阶段 1:工具函数开发(纯 Python,不依赖 LLM)

4.1 设计原则

  • 工具函数只做确定性操作(查数据库、调 API、计算),不包含 LLM 调用。
  • 每个工具必须有清晰的 docstring,供 LangChain 自动提取描述。
  • 返回格式统一(字符串或 JSON)。

4.2 实现示例:获取用户体质

# tools/constitution.py
from langchain.tools import tool

@tool
def get_user_constitution(user_id: str) -> str:
    """根据用户ID获取中医体质类型"""
    # mock 实现,后续替换为 Supabase 查询
    return "气虚质"

4.3 其他工具

  • generate_wellness_plan:返回 mock JSON 方案。
  • search_tcm_knowledge:返回固定文本(后续接入 RAG)。
  • get_weather_solar_term:调用天气 API。
  • create_reminder:调用 Node.js 提醒接口。
  • analyze_health_trend:查询历史体质趋势。

4.4 单元测试(未完成)

注:目前工具函数尚未编写完整的单元测试,计划在后续补充。

五、阶段 2:LangChain ReAct Agent 搭建

5.1 为什么选择 LangChain 官方 Agent?

  • 避免重复造轮子,专注业务逻辑。
  • create_react_agent + AgentExecutor 提供了稳定的 ReAct 循环实现。
  • 内置工具调用解析、错误处理、中间步骤记录(verbose=True)。
  • 与 LangChain 生态无缝集成(后续可轻松添加记忆、RAG 等)。

5.2 初始化 LLM(本地 Ollama)

from langchain_ollama import ChatOllama

llm = ChatOllama(
    model="qwen2:1.5b",
    temperature=0.7,
    base_url="http://localhost:11434"
)

如果使用 DeepSeek API,替换为 ChatOpenAI 并配置 base_url。

5.3 绑定工具

tools = [get_user_constitution, generate_wellness_plan]

5.4 设计 ReAct Prompt 模板

from langchain.prompts import PromptTemplate

prompt = PromptTemplate.from_template("""
你是一个专业的中医养生助手,名叫小甘草。你可以使用以下工具:

{tools}

工具名称:{tool_names}

请严格按照以下格式回答:
Question: 用户的问题
Thought: 思考需要做什么
Action: 工具名称(必须是 [{tool_names}] 之一)
Action Input: 工具的输入参数(JSON格式,例如 {{"user_id": "123"}})
Observation: 工具返回的结果
... (重复)
Final Answer: 最终回答

开始!

Question: {input}
Thought: {agent_scratchpad}
""")

5.5 创建 Agent 和执行器

from langchain.agents import AgentExecutor, create_react_agent

agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,   # 打印中间步骤
    max_iterations=5,
    handle_parsing_errors=True,
)

5.6 命令行测试

result = executor.invoke({"input": "用户ID是 test123,问题:我最近总是疲劳"})
print(result["output"])

输出示例:

> Entering new AgentExecutor chain...
Thought: 需要先查询用户体质。
Action: get_user_constitution
Action Input: {"user_id": "test123"}
Observation: 气虚质
Thought: 现在生成养生方案。
Action: generate_wellness_plan
Action Input: {"constitution": "气虚质"}
Observation: {"diet": "多吃山药", ...}
Final Answer: 您属于气虚质,建议多吃山药、黄芪...

六、阶段 3:FastAPI 服务封装

6.1 创建 FastAPI 应用

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel

app = FastAPI()
app.add_middleware(CORSMiddleware, allow_origins=["*"])

6.2 定义请求/响应模型

class ChatRequest(BaseModel):
    user_id: str
    message: str

class ChatResponse(BaseModel):
    reply: str

6.3 实现 /chat 接口

@app.post("/chat", response_model=ChatResponse)
async def chat_endpoint(request: ChatRequest):
    full_input = f"用户ID是 {request.user_id},问题:{request.message}"
    result = executor.invoke({"input": full_input})
    return ChatResponse(reply=result["output"])

6.4 添加健康检查与错误处理

@app.get("/health")
async def health():
    return {"status": "ok"}

# 在接口内部添加 try-except 并记录日志

6.5 启动服务

uvicorn main:app --host 0.0.0.0 --port 8000 --reload

6.6 测试(Postman 或 curl)

curl -X POST http://localhost:8000/chat \
  -H "Content-Type: application/json" \
  -d '{"user_id": "test123", "message": "我最近总是疲劳"}'

七、踩坑与经验

7.1 模型不按格式输出

  • 原因:本地小模型指令遵循能力弱。
  • 解决:使用 DeepSeek API 或换用 llama3.2:1b;降低 temperature;强化 Prompt。

7.2 LangChain 版本兼容性

  • create_react_agent 在 LangChain 1.x 中已移除,需要使用 0.3.x 版本。
  • 建议使用 Python 3.10 环境安装 langchain==0.3.0

7.3 工具函数缺少 docstring

  • @tool 强制要求 docstring,否则报错。
  • 为每个工具补充清晰的三引号注释。

7.4 run() 方法弃用

  • AgentExecutor.run() 在 0.3.x 中已弃用,改用 invoke() 并传入字典。

八、后续计划

  • 完成工具函数的单元测试。
  • 接入自训练 Qwen-7B 模型(LoRA)。
  • 实现 RAG 知识库(ChromaDB + 自训嵌入模型)。
  • 前端可视化 Agent 思考过程。
  • 主动健康提醒(定时任务 + Agent 生成内容)。

九、总结

通过 LangChain 的 create_react_agent,我快速搭建了一个可用的 ReAct Agent,避免了手写循环的繁琐。结合 FastAPI 封装,Agent 能够轻松集成到现有的 Node.js 后端。整个过程虽然遇到不少坑,但收获巨大。

如果你也在构建类似的 AI Agent,欢迎留言交流。。


附录:环境要求

  • Python 3.10+
  • Ollama + qwen2:1.5b(或 DeepSeek API Key)
  • 依赖见 requirements.txt

以上建议仅供参考,身体不适请及时咨询专业医师。


这样大纲就与你实际使用的方案一致了。你可以根据这个结构填充内容,并如实说明工具测试尚未完成。需要我帮你调整某个章节的细节吗?