上篇文章给大家预告了我在研究些 RAG+MCP(大模型上下文协议)的事,前后断断续续写了四天,终于完成了这篇稿子,这篇试图说清楚两个事情:
1、从复杂提示词引导模型调用工具开始,到 MCP 作为统一协议标准的变化过程;
2、小试牛刀的演示下在传统 RAG 基础上,针对机械加工场景结合 MCP 的一些功能延展示例。
以下,enjoy:
1、先说说大模型 API 调用
先简单回顾下最简单的大模型基础聊天应用开发,也就是直接按照目标 LLM 的官方 API 文档进行请求的做法。例如,如果我们要通过 Python 调用 DeepSeek-R1 模型进行问答,按照官方文档说明示例如下:
因为大多数模型厂商都是兼容 OpenAI 规范的,也就是说在使用 OpenAI SDK 请求方式下,直接替换上述的 base_url 换成其他模型地址,都是可以实现请求响应的。比如如果要请求Qwen 系列模型,那base_url 就替换成: https://dashscope.aliyuncs.com/compatible-mode/v1 。进一步说,如果要想实现多轮对话,让大模型“拥有记忆”满足追问,以阿里的 QWQ 模型为例,可以把content字段通过{'role': 'assistant', 'content':拼接后的流式输出 content}添加到上下文。(注:无需添加reasoning_content字段)
2、复杂提示词工程的缘起
上面提到的聊天应用,只是基于 LLM 的已有知识,回答效果在有些场景下不符合预期。毕竟,LLM 在训练完成的那一刻,它所掌握的知识就冻结了。这显然是回答不了具有时效性或者准确来说是超出 LLM 训练截止完成以前时间的问题,当然还包括私有化的信息等。
简而言之,通过引入外部工具,可以让 LLM 和外部世界进行交互。OpenAI 在 23年6月正式推出了 Function Calling 功能,最初在 GPT-3.5和 GPT-4 模型上实现。不过,在正式介绍这个 Fucntion Calling 功能之前,先来聊下在此之前通过复杂提示词引导模型调用工具的尝试。
以 get_current_weather 和 get_current_weather 两个 tool 为例,下文进行相关实现方式的对比说明。
示例运行展示效果如下:
总结来说,这种复杂提示词的做法,主要包括以下四个特征:
- 在系统提示中详细说明输出格式
- 使用特定的分隔符和标记(如 XML 标签)
- 通过正则表达式解析模型输出提取"函数调用"
- 在对话历史中包含工具使用示例
这种做法的局限性首先就是表现为格式不可靠,大模型可能不一致地遵循指令。毕竟 Transformer 的底层逻辑还是 Next token prediction。其次,对于复杂参数结构就更加不靠谱。当然还有例如参数验证困难、占用大量提示词空间等问题,就不一一赘述了。
不过,需要给这种做法正名的是,对于简单场景,可以考虑使用此类提示词方法,实现成本低,也不依赖特定模型能力,但同时需要始终警惕模型输出的不确定性。
3、Function Calling 初露锋芒
上述提到的通过提示词来引导模型调用工具的尝试,OpenAI 将其标准化并作为 API 的一部分提供,也就有了现在大家所说的 Function Calling。
3.1创新之处
相比于提示词引导模型调用工具的方法,主要创新之处体现在以下几点:
结构化输出:
确保模型能以预定义的 JSON 格式输出函数调用参数,提高了可解析性和可靠性
函数定义明确:
通过函数模式(schema)清晰定义名称、描述、参数类型等
降低解析复杂度:
开发者不需要编写复杂的文本解析逻辑
提高准确性:
减少了模型在生成函数调用时的"幻觉"问题
简化开发流程:
标准化了大模型与外部工具的交互方式
BTW,并不是所有的 LLM 都支持 Function Calling,因为模型要支持 Function Calling 通常需要专门的训练或微调。具体来说,需要在预训练或者微调阶段引入函数调用的示例,训练模型理解函数模式(schema),学习如何生成符合预期格式的 json 输出,以及理解参数类型和约束条件等。
3.2实现机制
那大模型的工具选择和调用具体关键机制是什么样的呢,这里提供一个 Qwen 模型的简单示例,具体实现上大致分为两步:
1、意图推理与工具匹配
- 大模型会基于用户输入,对可用工具的描述和参数进行语义理解
- 模型会通过自然语言理解和推理,判断是否需要调用工具,以及调用哪个具体的工具
这个过程是自动的,不需要开发者手动硬编码每一个判断逻辑
2、智能参数填充
- 模型能够从对话上下文中提取必要的参数信息
- 对于需要特定参数的函数,模型可以智能地填充这些参数值
例如,如果用户问:
"现在几点了?" → 模型可能调用 get_current_time"
北京今天天气怎么样?" → 模型可能调用 get_current_weather,并自动填充 locatinotallow="北京"
总结来说,关键实现包括:
- 工具描述(description)提供语义线索
- 参数定义(parameters)指导参数填充
- 模型的上下文理解和推理能力
尽管看起来很强大,但 Function Calling 会比较依赖模型的理解能力,而且工具描述的质量直接影响调用准确性,所以也存在误解或错误调用的可能性。
3.3Function Calling vs 传统硬编码
看到这里,可能会有盆友会疑惑 Function Calling 和传统手动函数调用外部工具实现逻辑的差别是啥。同样参照上述提到的两个 tool,附上一个传统硬编码的做法示例:
示例运行结果:
这个示例清晰地展示了传统手动触发方法的局限性:代码逻辑复杂、扩展性差、对用户输入的理解能力有限。相比之下,Function Calling 提供了一种更智能、更灵活的工具调用范式。
4、GPTs 的试图”大一统“
在正式说到 MCP 之前,还需要再聊下 GPTs 的故事。上述提到的 Function Calling 固然有很多好处,但是全部自己手动写似乎有点太麻烦,于是大聪明 OpenAI 就在 23 年 11 月初的开发者大会上,首次介绍了 GPTs 的概念,用户不需要任何编程知识,只需要通过自然语言指令和上传知识库,就能够轻松的定制自己的个性化 GPT。p.s.此举还有个实际效果是让全球开发者主动的为 ChatGPT 开发 Funtion Calling 工具。
此处忽略后来的狗血宫斗插曲,GPT Store 在 24 年 1 月对外正式发布,我查到的数据是,截止到 24 年1月份,用户自主创建的 GPTs 据说就超过了 300 万个。
想起我 23 年 11 月 11 号发布第一个自己的 GPTs 的时候,当时看到 GPTs 导航站的统计有 4000+个,当时感慨发布一周就这么快上新,不曾想后来会如此井喷。
下面展示一个获取当前时间的 GPTs 示例,并解释其工作机制。
4.1核心文件解析
1、manifest.json
定义 GPT 的基本元数据
指定 API 交互方式
提供人类和模型可读的描述
配置身份验证和 API 接入点
2、 openapi.yaml
定义具体的 API 接口规范
描述可用的端点、参数和响应结构
提供工具调用的接口约定
4.2使用场景示例
"现在几点了?"、"北京现在是什么时间?"、"告诉我纽约当前时间"
GPT 会根据这些问题:
识别时间查询意图
选择/current-time接口
传入相应的 timezone 参数
4.3局限性
GPTs 完全绑定 OpenAI 生态系统,不兼容其他大模型平台(Anthropic、Google 等),无法跨平台移植和使用。在功能实现方面,工具调用方式高度标准化,缺乏灵活的参数传递机制,不支持复杂的状态管理,也无法实现复杂的工作流编排。另外从托管方式上看,完全依赖 OpenAI 云平台,不支持私有化部署,无法进行深度定制和二次开发等。
总结来说,GPTs 本质上是一个封闭、受限的生态系统,适合快速构建简单的交互工具,但对于需要高度定制和灵活性的场景,其局限性非常明显。对于追求技术自主可控的企业和开发者,GPTs 并不是一个好的选择。
5、MCP 推出的偶然和必然
模型上下文协议 (MCP) 24 年 11 月由 Anthropic 发布,总结来说就是两个要点,首先是一个协议兼容所有的 AI 应用,另外在 Function Calling 基础上增加了资源和提示词的功能。
5.1工具调用示例
先看下 MCP 实现工具调用示例, 这里以 get_current_time 的工具为例:
用户提问:现在几点了?
MCP 执行流程:
1、请求阶段:
2、模型响应阶段
3、工具执行阶段:系统执行get_current_time函数,返回结果
4、最终响应
5.2执行步骤拆解
用户查询解析:
模型分析用户问题,确定需要调用哪个工具
对于需要参数的工具,提取必要参数(如城市名称)
工具调用请求生成:
模型生成标准化的工具调用请求,包含工具名称和参数
每个工具调用都有唯一 ID,方便后续追踪
工具执行:
系统接收工具调用请求
执行相应函数并获取结果
结果整合与回复生成:
模型接收工具调用结果
将结果整合到上下文中
生成自然语言回复给用户
5.3MCP 资源访问控制
MCP 的资源访问控制功能可以精确定义大模型如何安全地访问企业内部资源。以机械加工企业部署 RAG 系统访问 MySQL 数据库为例做个效果演示:
执行过程
权限验证层:系统首先验证当前用户对材料数据库的访问权限
资源边界定义:MCP 限制只能访问特定表(材料标准和质量测试)
查询限制:只允许读取操作,禁止写入或修改
数据筛选:可设置只返回非机密等级的标准数据
5.4实际应用优势
数据隔离:确保 LLM 只能访问授权表,无法看到客户数据、财务信息等敏感数据
审计追踪:记录所有数据库查询,便于合规审计
精细控制:可针对不同部门用户设置不同的数据访问范围
防止 SQL 注入:MCP 可以验证和清理查询请求,增强安全性
5.5提示词增强功能
MCP 的提示词增强功能可以为 LLM 提供额外上下文和专业指导,使其更好地处理专业领域问题,此处同样以机械加工企业为例:
5.6应用场景与优势
专业术语统一
系统能理解并使用企业内部特定术语(如"HC-1500"指特定型号的加工中心)
确保回答符合企业标准规范和命名习惯
流程标准化
强制模型按照企业工艺流程标准回答问题
例如:CNC 故障诊断必须先检查安全状态,再进行电气和机械系统排查
知识融合
例如:将 ISO 标准与企业内部工艺规范结合
安全与合规保障
针对高风险操作自动添加安全警告
例如:加工特殊材料时提示需要特定防护措施和环保要求
5.7具体应用实例
机械设备故障诊断
工艺参数推荐
质量辅助控制
6、RAGFlow 与 MCP 整合方案示例
为了实现企业多源数据的接入,这里演示下最近项目中初步实践通过 MCP 将 MySQL、EMS 等系统数据整合到 RAGFlow 框架中做法,供参考。
6.1架构设计
6.2参考案例
场景:工程师查询设备故障和相关维修历史
(此处打个广告,相关示例源码请移步我的知识星球)
1、用户查询
2、系统处理流程
MCP 请求生成
数据库查询执行:系统从 MySQL 数据库中查询 HC-2000 的维修记录工具执行结果
向量检索补充:同时系统从向量数据库检索与"E-35 错误"相关的设备手册和技术文档
最终回复生成:系统综合数据库查询结果和向量检索结果,生成完整回答
用户获得回答
7、整合技术要点
保持模块化设计
将 MCP 适配器作为独立模块添加,不破坏现有 RAGFlow 核心功能
使用适配器模式连接 RAGFlow 和企业数据源
统一资源访问接口
为所有数据源(向量库、MySQL、EMS 等)创建统一的资源访问接口
确保权限控制一致性
查询路由机制
开发智能查询路由,自动决定是使用向量检索还是结构化数据查询
支持混合查询模式,综合多种数据源结果
缓存与性能优化
对频繁查询的数据库结果进行缓存
使用批处理减少数据库连接开销
部署考虑
确保数据库连接器在企业内网环境正确配置
处理网络隔离环境下的连接问题
8、LLM 工具调用技术演进的一点思考
从复杂提示词→Function Calling→GPTs 插件→MCP 协议的技术演进路径,非常类似于几个经典技术标准化的发展历程,特别是 Web 技术、互联网协议和 API 标准化的过程。以 Web API 的标准化进程类比,
Web API 演进 | AI 工具调用演进 |
早期:RPC(远程过程调用)各自实现 | 早期:提示词工程中的工具调用 |
发展期:SOAP 和 XML-RPC 等框架 | 发展期:Function Calling 的 JSON 结构化调用 |
成熟期:REST API 成为主流 | 成熟期:GPTs 等平台专属实现 |
统一期:GraphQL 等新一代标准 | 统一期:MCP 作为统一协议 |
观察 LLM 工具调用和相关技术标准的发展,似乎可以归纳出技术标准化的普遍规律:
探索期:
各方以自己的方式解决问题(提示词工程)
初步标准化:
出现基础结构化方案(Function Calling)
平台主导期:
主要平台推出自己的解决方案(GPTs 插件)
开放标准期:
形成统一开放标准(MCP 协议)
从历史经验看,统一标准的出现通常会带来技术领域的爆发式增长,如 Web 标准统一后的互联网繁荣。MCP 协议的出现,很可能标志着 LLM 工具生态即将进入一个快速发展、广泛应用的新阶段。
25 年由此说来,值得期待更多垂直场景的最佳实践了。