前言在企业级知识库系统中用户通常通过自然语言进行提问。但用户的表达千变万化——有时候是想知道有哪些可用的知识助手有时候是指定某个助手回答问题更多时候是直接提问期望系统自行判断。这就要求我们的系统具备智能理解用户意图的能力。本文将围绕MCPModel Context Protocol思想结合 RAGFlow 知识库平台和 LangChain 框架详细介绍如何构建一套智能意图识别与分发系统让用户以最自然的方式进行知识检索。一、什么是 MCP为什么需要它MCPModel Context Protocol模型上下文协议是一种让 LLM 与外部工具进行标准化交互的协议。它的核心思想是LLM 不直接执行操作而是根据用户意图选择合适的工具工具函数作为能力单元被注册到系统中系统自动分析用户输入判断意图并调度对应工具在我们的场景中RAGFlow 知识库本身只能根据用户的文字描述进行查询。用户输入是自由表达的自然语言无法要求他们按照严格格式规范输入。因此引入 MCP 架构的目的就是让系统自动理解用户到底想做什么然后调用正确的工具去完成。二、整体架构我们将 MCP 工具模块拆分为三个层次层级文件职责工具层tool.py定义可调用的工具函数处理层handler.py意图分析 工具调度封装层chat.py对外暴露极简调用接口调用链路如下用户输入 → chat.py (RAGFlow_chat) → handler.py (analyze_user_intent → handle_user_query) → tool.py (list_assistant / choose_assistant / auto_assistant_answer) → RAGFlow API三、工具层tool.py工具层负责定义所有可被调用的原子能力。本系统共提供四个核心工具函数3.1 列出所有助手 —list_assistant()def list_assistant() - str: 列出所有可用的助手 return get_assistant_list()直接调用 RAGFlow API 获取当前所有知识助手的列表包含助手名称、功能介绍、关联知识库等信息。3.2 指定助手问答 —choose_assistant(assistant_name, question)def choose_assistant(assistant_name: str, question: str) - str: 使用指定的助手回答问题 answer create_ask_delete(assistant_name, question) return answer当用户明确说出用XX助手回答XX问题时系统会精确路由到该助手。3.3 智能匹配问答 —auto_assistant_answer(question)def auto_assistant_answer(question: str) - str: 自动选择合适的助手回答问题 流程获取助手列表 → LLM分析选择 → 调用选定助手 assistants_info get_assistant_list() system_prompt 你是一个助手选择器。请根据用户问题和助手列表 选择最适合回答该问题的助手。只返回助手名称不要添加任何解释。 selected_assistant call_llm(question, system_prompt).strip() answer create_ask_delete(selected_assistant, question) return answer这是最智能的模式——用户随便问系统自动判断该用哪个知识库。3.4 LLM 调用封装 —call_llm(prompt, instruction)def call_llm(prompt: str, instruction: str) - str: 调用大模型进行分析 prompt_template ChatPromptTemplate.from_messages([ (system, {instruction}), (human, {prompt}) ]) llm ChatOpenAI( api_keyos.getenv(DASHSCOPE_API_KEY), base_urlos.getenv(DASHSCOPE_BASE_URL), modelos.getenv(LLM_QWEN2.5) ) llm_chain prompt_template | llm response llm_chain.invoke({instruction: instruction, prompt: prompt}) return response.content使用 LangChain 的ChatPromptTemplateChatOpenAI构建调用链底层对接阿里百炼平台的通义千问模型。四、处理层handler.py —— 重点处理层是整个 MCP 架构的核心调度中枢负责理解意图 → 匹配资源 → 调度执行。4.1 意图分析 —analyze_user_intent()这是系统最关键的环节。它将用户输入分为三种意图def analyze_user_intent(user_query: str) - Tuple[str, Optional[str], Optional[str]]: 返回: (意图类型, 助手名称, 问题内容) 意图类型: - list_assistant → 查询助手列表 - choose_assistant → 指定助手问答 - auto_assistant_answer → 直接提问自动匹配 具体实现上通过向 LLM 发送精心设计的 system prompt 来完成分类system_prompt 你是一个用户意图分析器。判断用户输入属于以下哪种类型 1. 查询助手列表用户想知道有哪些可用的助手 2. 指定助手回答问题用户明确指定了某个助手来回答问题 3. 直接提问用户直接提出了问题没有指定助手 对于第2种情况需要提取出用户指定的助手名称。 请以JSON格式返回分析结果包含以下字段 - intent_type: list_assistant, choose_assistant, auto_assistant_answer - assistant_name: 如果指定了助手则返回名称否则为null 只返回JSON格式的结果不要包含任何其他解释或文本。LLM 返回 JSON 后代码会进行清理和解析对于 LLM 可能返回的 markdown 代码块包裹json ... 也做了容错处理。4.2 助手匹配 —find_best_matching_assistant()用户说的助手名称可能和系统中的不完全一致比如用户说法律助手系统里叫刑法法律助手。这个函数通过两级匹配来解决第一级子串模糊匹配—— 检查用户输入的助手名和系统助手名是否互为子串第二级LLM 语义匹配—— 如果模糊匹配失败交给 LLM 进行语义级别的理解匹配兜底策略—— 都匹配不上时回退到通用知识助手# 精确匹配 for name in assistant_names: if assistant_name in name or name in assistant_name: return name # LLM语义匹配 system_prompt 你是一个助手匹配器。根据用户提供的助手名称 从可用的助手列表中找出最匹配的那个。只返回最匹配的助手的完整名称。 matched_assistant call_llm(user_prompt, system_prompt).strip() # 兜底 return 通用知识助手4.3 请求处理入口 —handle_user_query()将意图分析和工具调度串联起来的主流程def handle_user_query(user_query: str) - str: # 1. 分析意图 intent_type, assistant_name, question analyze_user_intent(user_query) # 2. 按意图分发 if intent_type list_assistant: result list_assistant() elif intent_type choose_assistant and assistant_name: matched find_best_matching_assistant(assistant_name) result choose_assistant(matched, user_query) else: result auto_assistant_answer(user_query) return result另外还做了错误降级处理当指定助手回答失败时自动回退到auto_assistant_answer走智能匹配。五、封装层chat.py为了让外部调用方如 LangChain 主流程、FastAPI 接口等无需关心内部细节我们通过chat.py做了极简封装from RAGFlow_mcp.handler import handle_user_query, list_assistant def RAGFlow_chat(query: str) - str: 处理用户查询返回回答 return handle_user_query(query) def get_assistants() - str: 获取所有可用的助手列表 return list_assistant()外部只需两行代码即可完成一次完整的 MCP 智能问答from RAGFlow_mcp.chat import RAGFlow_chat answer RAGFlow_chat(瓦尔登湖在哪里) print(answer)六、运行效果测试用例test_queries [ 有哪些助手可以使用, # → list_assistant 用文学知识助手告诉我百年孤独的主角是谁, # → choose_assistant 空调的绝热工程怎么做 # → auto_assistant_answer ] for query in test_queries: result handle_user_query(query) print(result)输出示例查询助手列表返回所有助手的名称、功能介绍、关联知识库指定助手问答精确使用文学知识助手返回《百年孤独》的主角信息自动匹配问答系统自动将空调绝热工程路由到工程技术类知识库七、核心设计理念总结关注点分离工具定义tool、意图调度handler、对外接口chat三层解耦LLM 作为路由器利用 LLM 的理解能力来判断意图、匹配资源而非硬编码 if-else 规则优雅降级每一层都有容错和兜底策略指定助手失败 → 自动匹配 → 通用助手保证用户体验全程日志追踪使用 Python logging 记录每一步的耗时和结果便于排查线上问题八、项目完整信息知识库平台RAGFlowLLM 框架LangChain大模型阿里百炼 · 通义千问 2.5记忆存储MongoDB前端Vue.js 3总结本文详细拆解了基于 RAGFlow 和 LangChain 的 MCP 工具模块实现。核心思路是将用户的自然语言输入通过 LLM 进行意图分析再动态调度到最合适的知识库助手进行处理。这套架构不仅提升了用户的交互体验也为后续扩展更多工具能力如文档上传、知识库管理、多轮对话等提供了灵活的扩展基础。希望本文能为正在构建 RAG 知识库系统的同学提供一些参考和启发。
RAGFlow + MCP 工具实战:构建智能知识库问答系统
前言在企业级知识库系统中用户通常通过自然语言进行提问。但用户的表达千变万化——有时候是想知道有哪些可用的知识助手有时候是指定某个助手回答问题更多时候是直接提问期望系统自行判断。这就要求我们的系统具备智能理解用户意图的能力。本文将围绕MCPModel Context Protocol思想结合 RAGFlow 知识库平台和 LangChain 框架详细介绍如何构建一套智能意图识别与分发系统让用户以最自然的方式进行知识检索。一、什么是 MCP为什么需要它MCPModel Context Protocol模型上下文协议是一种让 LLM 与外部工具进行标准化交互的协议。它的核心思想是LLM 不直接执行操作而是根据用户意图选择合适的工具工具函数作为能力单元被注册到系统中系统自动分析用户输入判断意图并调度对应工具在我们的场景中RAGFlow 知识库本身只能根据用户的文字描述进行查询。用户输入是自由表达的自然语言无法要求他们按照严格格式规范输入。因此引入 MCP 架构的目的就是让系统自动理解用户到底想做什么然后调用正确的工具去完成。二、整体架构我们将 MCP 工具模块拆分为三个层次层级文件职责工具层tool.py定义可调用的工具函数处理层handler.py意图分析 工具调度封装层chat.py对外暴露极简调用接口调用链路如下用户输入 → chat.py (RAGFlow_chat) → handler.py (analyze_user_intent → handle_user_query) → tool.py (list_assistant / choose_assistant / auto_assistant_answer) → RAGFlow API三、工具层tool.py工具层负责定义所有可被调用的原子能力。本系统共提供四个核心工具函数3.1 列出所有助手 —list_assistant()def list_assistant() - str: 列出所有可用的助手 return get_assistant_list()直接调用 RAGFlow API 获取当前所有知识助手的列表包含助手名称、功能介绍、关联知识库等信息。3.2 指定助手问答 —choose_assistant(assistant_name, question)def choose_assistant(assistant_name: str, question: str) - str: 使用指定的助手回答问题 answer create_ask_delete(assistant_name, question) return answer当用户明确说出用XX助手回答XX问题时系统会精确路由到该助手。3.3 智能匹配问答 —auto_assistant_answer(question)def auto_assistant_answer(question: str) - str: 自动选择合适的助手回答问题 流程获取助手列表 → LLM分析选择 → 调用选定助手 assistants_info get_assistant_list() system_prompt 你是一个助手选择器。请根据用户问题和助手列表 选择最适合回答该问题的助手。只返回助手名称不要添加任何解释。 selected_assistant call_llm(question, system_prompt).strip() answer create_ask_delete(selected_assistant, question) return answer这是最智能的模式——用户随便问系统自动判断该用哪个知识库。3.4 LLM 调用封装 —call_llm(prompt, instruction)def call_llm(prompt: str, instruction: str) - str: 调用大模型进行分析 prompt_template ChatPromptTemplate.from_messages([ (system, {instruction}), (human, {prompt}) ]) llm ChatOpenAI( api_keyos.getenv(DASHSCOPE_API_KEY), base_urlos.getenv(DASHSCOPE_BASE_URL), modelos.getenv(LLM_QWEN2.5) ) llm_chain prompt_template | llm response llm_chain.invoke({instruction: instruction, prompt: prompt}) return response.content使用 LangChain 的ChatPromptTemplateChatOpenAI构建调用链底层对接阿里百炼平台的通义千问模型。四、处理层handler.py —— 重点处理层是整个 MCP 架构的核心调度中枢负责理解意图 → 匹配资源 → 调度执行。4.1 意图分析 —analyze_user_intent()这是系统最关键的环节。它将用户输入分为三种意图def analyze_user_intent(user_query: str) - Tuple[str, Optional[str], Optional[str]]: 返回: (意图类型, 助手名称, 问题内容) 意图类型: - list_assistant → 查询助手列表 - choose_assistant → 指定助手问答 - auto_assistant_answer → 直接提问自动匹配 具体实现上通过向 LLM 发送精心设计的 system prompt 来完成分类system_prompt 你是一个用户意图分析器。判断用户输入属于以下哪种类型 1. 查询助手列表用户想知道有哪些可用的助手 2. 指定助手回答问题用户明确指定了某个助手来回答问题 3. 直接提问用户直接提出了问题没有指定助手 对于第2种情况需要提取出用户指定的助手名称。 请以JSON格式返回分析结果包含以下字段 - intent_type: list_assistant, choose_assistant, auto_assistant_answer - assistant_name: 如果指定了助手则返回名称否则为null 只返回JSON格式的结果不要包含任何其他解释或文本。LLM 返回 JSON 后代码会进行清理和解析对于 LLM 可能返回的 markdown 代码块包裹json ... 也做了容错处理。4.2 助手匹配 —find_best_matching_assistant()用户说的助手名称可能和系统中的不完全一致比如用户说法律助手系统里叫刑法法律助手。这个函数通过两级匹配来解决第一级子串模糊匹配—— 检查用户输入的助手名和系统助手名是否互为子串第二级LLM 语义匹配—— 如果模糊匹配失败交给 LLM 进行语义级别的理解匹配兜底策略—— 都匹配不上时回退到通用知识助手# 精确匹配 for name in assistant_names: if assistant_name in name or name in assistant_name: return name # LLM语义匹配 system_prompt 你是一个助手匹配器。根据用户提供的助手名称 从可用的助手列表中找出最匹配的那个。只返回最匹配的助手的完整名称。 matched_assistant call_llm(user_prompt, system_prompt).strip() # 兜底 return 通用知识助手4.3 请求处理入口 —handle_user_query()将意图分析和工具调度串联起来的主流程def handle_user_query(user_query: str) - str: # 1. 分析意图 intent_type, assistant_name, question analyze_user_intent(user_query) # 2. 按意图分发 if intent_type list_assistant: result list_assistant() elif intent_type choose_assistant and assistant_name: matched find_best_matching_assistant(assistant_name) result choose_assistant(matched, user_query) else: result auto_assistant_answer(user_query) return result另外还做了错误降级处理当指定助手回答失败时自动回退到auto_assistant_answer走智能匹配。五、封装层chat.py为了让外部调用方如 LangChain 主流程、FastAPI 接口等无需关心内部细节我们通过chat.py做了极简封装from RAGFlow_mcp.handler import handle_user_query, list_assistant def RAGFlow_chat(query: str) - str: 处理用户查询返回回答 return handle_user_query(query) def get_assistants() - str: 获取所有可用的助手列表 return list_assistant()外部只需两行代码即可完成一次完整的 MCP 智能问答from RAGFlow_mcp.chat import RAGFlow_chat answer RAGFlow_chat(瓦尔登湖在哪里) print(answer)六、运行效果测试用例test_queries [ 有哪些助手可以使用, # → list_assistant 用文学知识助手告诉我百年孤独的主角是谁, # → choose_assistant 空调的绝热工程怎么做 # → auto_assistant_answer ] for query in test_queries: result handle_user_query(query) print(result)输出示例查询助手列表返回所有助手的名称、功能介绍、关联知识库指定助手问答精确使用文学知识助手返回《百年孤独》的主角信息自动匹配问答系统自动将空调绝热工程路由到工程技术类知识库七、核心设计理念总结关注点分离工具定义tool、意图调度handler、对外接口chat三层解耦LLM 作为路由器利用 LLM 的理解能力来判断意图、匹配资源而非硬编码 if-else 规则优雅降级每一层都有容错和兜底策略指定助手失败 → 自动匹配 → 通用助手保证用户体验全程日志追踪使用 Python logging 记录每一步的耗时和结果便于排查线上问题八、项目完整信息知识库平台RAGFlowLLM 框架LangChain大模型阿里百炼 · 通义千问 2.5记忆存储MongoDB前端Vue.js 3总结本文详细拆解了基于 RAGFlow 和 LangChain 的 MCP 工具模块实现。核心思路是将用户的自然语言输入通过 LLM 进行意图分析再动态调度到最合适的知识库助手进行处理。这套架构不仅提升了用户的交互体验也为后续扩展更多工具能力如文档上传、知识库管理、多轮对话等提供了灵活的扩展基础。希望本文能为正在构建 RAG 知识库系统的同学提供一些参考和启发。