使用langchain框架开发智能问答系统,需要有mcp服务和工具调用
从零开发带工具调用能力的智能问答系统,核心是把LLM(大脑)+ Tools(外部能力)+ Memory(记忆)+ Agent 编排四块拼起来。LangChain 现在的推荐做法是:业务内简单工具用@tool直接封装,跨系统、要复用的能力走MCP(Model Context Protocol)标准化接入。下面按可落地的顺序一步步来。
一、整体架构与选型
一个生产可用的问答智能体通常包含:
用户问题 → Agent(LLM 推理) → 选择工具 → 执行工具(API/MCP/RAG) → 观察结果 → 组织答案 ↑ | └─────────────── 多轮循环 ───────────────┘关键选型:
- 模型:支持 tool calling 的大模型(GPT-4o、Claude、Qwen、DeepSeek 等均可,通过
langchain-openai的base_url接兼容接口) - Agent 框架:
langchain+langgraph(LangChain 官方现在主推 LangGraph 做 Agent 编排) - 工具:
- 简单/业务紧耦合 →
@tool原生封装 - 跨系统/需复用/独立部署 →MCP Server,通过
langchain-mcp-adapters接入
- 简单/业务紧耦合 →
- MCP 与 Function Calling 的关系:互补而非替代。MCP 解决"工具接口标准化、多 Agent 共享",Function Calling 解决"单次模型如何调 API"。完整链路是:MCP Client 把 Server 的工具注册进来 → 转成模型的 tools 参数 → 模型用 Function Calling 选定工具 → Client 经 MCP Server 执行 → 结果回传模型。
二、环境准备
# 核心依赖pipinstalllangchain langchain-openai langchain-community langgraph pipinstalllangchain-mcp-adapters# MCP 适配器pipinstallpython-dotenv# 环境变量管理# 如需本地 MCP Server(Node 版)npminstall-g@modelcontextprotocol/server-filesystem.env文件:
OPENAI_API_KEY=你的key OPENAI_BASE_URL=模型代理地址(可选,用于对接兼容接口) MODEL_NAME=gpt-4o-mini三、Step 1:搭建最小可跑通的 Agent(原生 @tool)
先用最简单的计算器工具跑通"思考→选工具→执行→回答"闭环:
importosfromdotenvimportload_dotenvfromlangchain_openaiimportChatOpenAIfromlangchain.agentsimportAgentExecutor,create_tool_calling_agentfromlangchain_core.promptsimportChatPromptTemplate,MessagesPlaceholderfromlangchain_core.toolsimporttoolfromlangchain_community.chat_message_historiesimportFileChatMessageHistory load_dotenv()# 1. 自定义工具:用 @tool 装饰器封装@tooldefcalculator(num1:float,num2:float,op:str)->str:"""数字计算工具,用于两个数字运算 :param num1: 第一个数字 :param num2: 第二个数字 :param op: 运算符号,支持 + - * / """ifop=="+":res=num1+num2elifop=="-":res=num1-num2elifop=="*":res=num1*num2elifop=="/":res=num1/num2else:return"不支持该运算符"returnf"计算结果:{res}"tools=[calculator]# 2. 初始化 LLMllm=ChatOpenAI(model=os.getenv("MODEL_NAME","gpt-4o-mini"),temperature=0)# 3. Prompt 模板(必须包含 agent_scratchpad)prompt=ChatPromptTemplate.from_messages([("system","你是一个擅长使用工具完成任务的助手,优先调用工具获取结果,不要凭空编造数据。"),MessagesPlaceholder(variable_name="chat_history"),("user","{input}"),MessagesPlaceholder(variable_name="agent_scratchpad"),])# 4. 创建 Agent 与 Executoragent=create_tool_calling_agent(llm,tools,prompt)agent_executor=AgentExecutor(agent=agent,tools=tools,verbose=True)# 5. 持久化记忆history=FileChatMessageHistory("./agent_memory.json")whileTrue:user_input=input("\n请输入你的问题(输入 exit 退出):")ifuser_input=="exit":breakresp=agent_executor.invoke({"input":user_input,"chat_history":history.messages})print(f"AI:{resp['output']}")history.add_user_message(user_input)history.add_ai_message(resp["output"])💡工具描述的写法直接影响工具选择准确率。docstring 要写清:这个工具做什么、何时用、参数含义。模糊的描述会让模型乱调工具。
四、Step 2:接入外部 API 作为工具
真实问答系统几乎一定要调外部 REST API(订单查询、天气、搜索等)。用@tool封装 HTTP 请求即可:
importrequestsfromlangchain_core.toolsimporttool@tooldefquery_order(order_id:str)->str:"""查询订单状态,输入为订单ID(如 ORD12345)"""try:resp=requests.get(f"https://api.your-domain.com/orders/{order_id}",timeout=5)resp.raise_for_status()data=resp.json()returnf"订单{order_id}状态:{data.get('status')}, 物流:{data.get('tracking_no')}"exceptrequests.RequestExceptionase:returnf"查询失败:{e}"@tooldefget_weather(city:str)->str:"""获取指定城市的当前天气"""api_key=os.getenv("WEATHER_API_KEY")resp=requests.get("https://api.weatherapi.com/v1/current.json",params={"key":api_key,"q":city},timeout=5)data=resp.json()returnf"{city}:{data['current']['temp_c']}°C,{data['current']['condition']['text']}"工具开发的最佳实践:
- 异常处理:网络请求必须 try/except,返回友好错误信息而非抛异常
- 超时控制:所有 HTTP 调用设
timeout - 参数校验:用 Pydantic
StructuredTool做强类型校验 - 敏感信息:API Key 走环境变量,禁止硬编码
- 幂等性:工具最好设计为可重复调用
把 API 工具加入tools列表即可让 Agent 自主调用:
tools=[calculator,query_order,get_weather]五、Step 3:接入 MCP 服务(重点)
当工具需要跨项目复用、独立部署、或被多个 Agent 共享时,应该把它做成 MCP Server。
5.1 编写一个 MCP Server
用 Python 的 FastMCP 写一个提供数学工具的 Server(math_server.py):
frommcp.server.fastmcpimportFastMCP mcp=FastMCP("Math")@mcp.tool()defadd(a:int,b:int)->int:"""Add two numbers"""returna+b@mcp.tool()defmultiply(a:int,b:int)->int:"""Multiply two numbers"""returna*bif__name__=="__main__":mcp.run(transport="stdio")也可以用 Node.js 写,两端完全解耦,互不干扰。
5.2 在 LangChain 中接入 MCP 工具
langchain-mcp-adapters支持stdio(本地进程)和Streamable HTTP(远程服务)两种传输方式:
importasynciofromlangchain_mcp_adapters.clientimportMultiServerMCPClientfromlangchain.agentsimportcreate_agentasyncdefmain():# 连接多个 MCP Server(stdio + http 混合)client=MultiServerMCPClient({"math":{"command":"python","args":["./math_server.py"],"transport":"stdio",},"weather":{"url":"http://localhost:8000/mcp","transport":"http",}})tools=awaitclient.get_tools()print(f"加载了{len(tools)}个 MCP 工具")# 创建 Agentagent=create_agent("openai:gpt-4.1",tools)result=awaitagent.ainvoke({"messages":"what's (3 + 5) x 12?"})print(result["output"])asyncio.run(main())如果用 JS/TS,@langchain/mcp-adapters支持更丰富的配置(认证头、OAuth、自动重连等):
import{MultiServerMCPClient}from"@langchain/mcp-adapters";import{createAgent}from"langchain";import{ChatOpenAI}from"@langchain/openai";constclient=newMultiServerMCPClient({mcpServers:{math:{transport:"stdio",command:"npx",args:["-y","@modelcontextprotocol/server-math"],},weather:{url:"https://example.com/weather/mcp",headers:{Authorization:"Bearer token123"}}}});consttools=awaitclient.getTools();constmodel=newChatOpenAI({model:"gpt-4o-mini",temperature:0});constagent=createAgent({llm:model,tools});⚠️生产环境务必 Pin MCP Server 版本,避免远程 Server 升级导致工具签名变化。
5.3 原生 @tool vs MCP 怎么选
| 维度 | 原生@tool | MCP Server |
|---|---|---|
| 复用性 | 仅当前应用 | 任意 MCP 客户端可用 |
| 跨语言 | 不支持 | Python/Node/Rust 全兼容 |
| 部署 | 随应用一起 | 可独立部署、升级 |
| 适用场景 | 快速原型、1-2 个工具 | 多系统共享、需独立运维 |
经验法则:工具会被多个项目用到 → MCP;只是当前业务的简单封装 →@tool。
六、Step 4:RAG + Agent 组合(知识库问答)
纯工具调用适合"操作类"问题,但企业问答往往需要基于私有文档回答。把 RAG 检索也封装成一个工具即可:
fromlangchain_community.vectorstoresimportChromafromlangchain_openaiimportOpenAIEmbeddingsfromlangchain_core.toolsimporttool# 假设已构建好向量库vectorstore=Chroma(collection_name="docs",embedding_function=OpenAIEmbeddings())@tooldefsearch_knowledge_base(query:str)->str:"""在企业知识库中检索相关文档,用于回答产品、政策、规范类问题"""docs=vectorstore.similarity_search(query,k=3)return"\n\n".join([doc.page_contentfordocindocs])# 工具组合:RAG + API + 计算tools=[search_knowledge_base,query_order,calculator]这样 Agent 会根据问题自主决定:是查知识库、还是调 API、还是直接计算。
七、Step 5:生产级增强
7.1 多轮记忆与上下文
除了上面演示的FileChatMessageHistory,生产环境建议用 Redis 或数据库:
fromlangchain_redisimportRedisChatMessageHistory history=RedisChatMessageHistory(session_id="user_123",url="redis://localhost:6379")7.2 工具调用治理
- 工具数量控制:单个 Agent 工具数建议10-15 个以内,过多会干扰模型选择
- 超时与熔断:给每个工具设超时,失败重试 1-2 次
- 日志与追踪:用 LangSmith 或 OpenTelemetry 记录每次 tool call 的输入输出
- 权限控制:敏感工具(如退款、删除)加人工确认环节
7.3 错误处理模式
agent_executor=AgentExecutor(agent=agent,tools=tools,verbose=True,max_iterations=10,# 防止无限循环handle_parsing_errors=True,# 解析错误时优雅降级return_intermediate_steps=True,# 返回中间步骤便于调试)八、完整项目结构建议
my-agent/ ├── .env # API Keys ├── math_server.py # MCP Server(独立进程) ├── agent.py # 主 Agent 入口 ├── tools/ # 原生 @tool 工具 │ ├── api_tools.py # 外部 API 封装 │ └── rag_tool.py # 知识库检索工具 ├── config/ │ └── mcp_servers.json # MCP Server 配置 └── memory/ # 持久化记忆(如果用文件)启动 MCP 增强的 Agent:
importjsonfromlangchain_mcp_adapters.clientimportMultiServerMCPClientfromlangchain.agentsimportcreate_tool_calling_agent,AgentExecutorfromlangchain_openaiimportChatOpenAIfromlangchain_core.promptsimportChatPromptTemplate,MessagesPlaceholderfromtools.api_toolsimportquery_order,get_weatherfromtools.rag_toolimportsearch_knowledge_base# 1. 加载 MCP 配置withopen("config/mcp_servers.json")asf:mcp_config=json.load(f)["mcpServers"]# 2. 原生工具 + MCP 工具合并mcp_client=MultiServerMCPClient(mcp_config)mcp_tools=awaitmcp_client.get_tools()native_tools=[query_order,get_weather,search_knowledge_base]all_tools=native_tools+mcp_tools# 3. 构建 Agentllm=ChatOpenAI(model="gpt-4o-mini",temperature=0)prompt=ChatPromptTemplate.from_messages([("system","你是一个企业智能助手,可调用工具查询订单、天气、知识库等。优先用工具获取真实数据。"),MessagesPlaceholder("chat_history"),("user","{input}"),MessagesPlaceholder("agent_scratchpad"),])agent=create_tool_calling_agent(llm,all_tools,prompt)executor=AgentExecutor(agent=agent,tools=all_tools,verbose=True)# 4. 运行result=executor.invoke({"input":"查一下订单 ORD12345 的状态,并告诉我北京今天天气"})print(result["output"])九、调试与上线路径
- 本地跑通:用
verbose=True观察 Agent 的思考链 - 单元测试:对每个
@tool单独测试,确保输入输出符合预期 - 集成测试:用 LangSmith 追踪完整调用链路
- 生产部署:
- Agent 服务化(FastAPI 封装)
- MCP Server 独立部署,通过 HTTP 传输
- 加限流、鉴权、审计日志
- 监控工具调用成功率与耗时
📌最容易踩的坑:
- 忘记在 Prompt 里加
agent_scratchpad→ Agent 无法写入思考过程- 工具 docstring 太模糊 → 模型选错工具
- MCP Server 用 stdio 传输但路径不对 → 子进程拉起失败
- 工具执行时间长阻塞主线程 → 改用异步工具
按这个路径,从零搭建的智能问答系统既能查知识库(RAG),又能调业务 API,还能通过 MCP 复用外部工具生态——这才是 2026 年生产级 Agent 的标准形态。
