1. 先搞清楚 MCP 和 RAG 到底解决什么问题

如果你正在处理大模型(LLM)如何连接外部数据或工具的问题,大概率已经听过 RAG(检索增强生成)和最近出现的 MCP(模型上下文协议)。这两个方案都不是为了替代大模型本身,而是为了解决 LLM 的两个核心短板:知识更新慢(训练数据有截止日期)和无法直接操作外部系统(数据库、API、文件等)。

RAG 的思路是把外部知识库(比如公司文档、最新资料)通过检索器实时查询,把相关片段作为上下文喂给 LLM,让模型基于这些新鲜信息生成回答。它主要增强的是模型的“知识面”,适合问答、文档分析、客服这类需要事实准确性的场景。

MCP 则更偏向“操作能力”。它定义了一套标准协议,让 LLM 可以通过结构化方式调用外部工具(比如执行代码、查询数据库、操作文件)。MCP 的核心是让模型能“做事情”,而不仅仅是“回答问题”。它更适合需要多步执行、状态维护、工具调用的自动化流程,比如数据分析流水线、自动化报告生成、跨系统任务协调。

简单说,RAG 是给模型“喂资料”,MCP 是给模型“装手柄”。如果你的需求是让模型回答得更准、更有依据,先看 RAG;如果你需要模型能自动执行一连串操作,MCP 更值得投入。

2. 从实际场景看 RAG 和 MCP 的分工

2.1 RAG 的典型落地场景

RAG 系统通常包含三个核心环节:文档处理、检索器、生成器。文档处理阶段会把你的知识库(PDF、Word、网页等)拆分成片段,转换成向量存入向量数据库。检索器根据用户问题,从向量库中找到最相关的几个片段。生成器把问题和这些片段一起交给 LLM,让模型合成最终答案。

我一般会先确认知识库的更新频率。如果资料变动不频繁(比如产品手册、历史文档),RAG 的效果最稳定。但如果你需要处理实时数据(比如今天的股价、新闻),就要考虑检索器能否对接动态数据源,以及如何平衡检索速度和答案质量。

另一个关键点是片段划分策略。很多人直接按固定长度切分,但遇到表格、代码块或多段落说明时,容易把完整信息切断。我更建议根据文档结构(标题、段落、表格边界)做智能切分,或者至少测试不同 chunk size 对答案连贯性的影响。

2.2 MCP 的适用边界

MCP 协议的核心是定义了一套工具调用规范。模型不需要知道工具的具体实现,只需要按照 MCP 格式发起请求,由 MCP Server 接管实际执行。比如你可以封装一个“查询数据库”工具,模型只需要说出“请查询上个月的销售数据”,MCP 会自动转换成 SQL 查询并返回结果。

这种模式特别适合流程固定的重复任务。比如每天早上的数据简报:模型先调用“获取昨日订单”工具,再调用“计算增长率”工具,最后调用“生成简报邮件”工具。整个过程模型只负责逻辑编排,具体执行由各个工具保障。

但 MCP 对工具设计的可靠性要求很高。如果某个工具经常超时或返回异常格式,整个链条就会失败。所以前期重点不是让模型学会所有工具,而是确保每个工具都有清晰的输入输出、错误处理和日志记录。

2.3 什么时候该考虑结合使用

在实际项目里,RAG 和 MCP 经常需要配合。比如一个智能客服场景:用户问“我的订单 12345 到哪里了”,先用 RAG 从帮助文档里检索“订单查询方法”,如果发现需要调用 API,再通过 MCP 执行“查询物流”工具。这样既保证了回答有依据,又能完成实际操作。

结合的关键是控制好上下文长度。RAG 检索的结果和 MCP 调用的结果都会占用 LLM 的上下文窗口。如果每一步都返回大量数据,容易导致窗口溢出或模型忽略关键信息。通常我会设置检索结果数量上限,并对 MCP 工具返回做摘要处理,只保留核心字段。

3. 本地部署和资源占用的实际考量

3.1 RAG 系统的资源组成

一个完整的 RAG 系统至少需要三部分资源:文档处理流水线、向量数据库、LLM 服务。文档处理阶段比较吃 CPU 和内存,尤其是解析复杂格式(扫描 PDF、带表格的文档)时。向量数据库对内存要求高,检索速度取决于向量索引规模和硬件性能。

LLM 部分是最灵活的。如果对响应速度要求高,可以考虑本地部署 7B~13B 参数量的模型(比如 Llama、Qwen 系列),需要 8GB~16GB 显存。如果只是内部试用,先用 OpenAI 或国内云厂商的 API 验证效果,再决定是否自建。

我一般建议分阶段部署:先用云服务跑通全流程,再逐步把检索器和向量数据库迁移到本地,最后根据调用量决定是否自建 LLM。这样避免一开始就投入大量硬件,却卡在文档处理或检索优化上。

3.2 MCP 服务的轻量级部署方案

MCP 协议本身是轻量的,但工具的实现可能涉及各种依赖。比如一个“发送邮件”工具需要 SMTP 配置,“执行 SQL”工具需要数据库连接池。部署时重点考虑工具之间的隔离性和资源竞争。

对于测试环境,可以用单进程运行所有工具,但要有超时和重启机制。生产环境更建议用容器隔离每个工具,通过 MCP Server 统一调度。这样即使某个工具崩溃,也不会拖垮整个系统。

资源评估时,不要只看 LLM 的消耗,还要算上工具执行的开销。比如一个“生成图表”工具可能会临时占用大量内存,一个“视频转码”工具会吃满 CPU。最好对每个工具做压力测试,设定并发限制和资源配额。

3.3 低配置环境的可行性

如果只有普通 PC(无 GPU、16GB 内存),依然可以体验核心功能。RAG 方面,用轻量级向量数据库(Chroma、FAISS)和小模型(比如 2B 参数的 Embedding 模型)能处理万级文档。MCP 方面,先实现几个简单工具(文件读写、HTTP 请求),避免需要重型运行时的操作(视频处理、大规模计算)。

关键是把预期放对:低配置下不要追求毫秒级响应或大批量并发,重点验证流程是否通、结果是否准。等核心逻辑跑顺后,再针对瓶颈环节升级硬件或优化代码。

4. 实操步骤:从零搭建一个可运行的 demo

4.1 环境准备和依赖安装

先创建一个干净的 Python 环境(3.9+),避免包冲突。RAG 部分需要安装向量数据库库(如 chromadb)、文档解析库(如 unstructured)、Embedding 模型(如 sentence-transformers)。MCP 部分需要安装 MCP 协议库(如 modelcontextprotocol)和工具依赖。

# 创建虚拟环境
python -m venv rag_mcp_demo
source rag_mcp_demo/bin/activate  # Linux/macOS
# rag_mcp_demo\Scripts\activate  # Windows

# 安装核心包
pip install chromadb unstructured sentence-transformers
pip install modelcontextprotocol

如果遇到解析库的依赖问题(比如 PDF 需要 poppler),先按官方文档装系统级依赖,再装 Python 包。我一般会先试一个小文档(纯文本 TXT),确认基础流程能跑,再处理复杂格式。

4.2 构建最小 RAG 系统

第一步准备知识库:创建一个 docs/ 目录,放几个示例文档(比如公司介绍、产品说明)。用 Python 脚本完成以下步骤:

  1. 加载文档并切分(先按 500 字符长度简单切)
  2. 用 Embedding 模型转换成分块向量
  3. 存入 Chroma 向量数据库
  4. 实现检索函数:输入问题,返回 top-3 相关片段
from sentence_transformers import SentenceTransformer
import chromadb

# 初始化模型和数据库
model = SentenceTransformer('all-MiniLM-L6-v2')
client = chromadb.PersistentClient(path="./chroma_db")
collection = client.get_or_create_collection(name="docs")

# 文档处理示例(实际需要更复杂的解析逻辑)
documents = ["文档1内容...", "文档2内容..."]  # 从文件读取
embeddings = model.encode(documents).tolist()

# 存入向量库
collection.add(
    embeddings=embeddings,
    documents=documents,
    ids=[f"doc_{i}" for i in range(len(documents))]
)

# 检索函数
def retrieve(query, n_results=3):
    query_embedding = model.encode([query]).tolist()
    results = collection.query(
        query_embeddings=query_embedding,
        n_results=n_results
    )
    return results['documents'][0]

跑通后,用几个问题测试检索效果,观察返回的片段是否相关。如果效果不好,调整切分策略或换更大的 Embedding 模型。

4.3 添加 MCP 工具调用

接下来实现两个简单的 MCP 工具:获取当前时间和计算数字平方。先定义工具描述(名称、参数、说明),再实现执行逻辑。

from mcp import ClientSession, StdioServerParameters
import asyncio

# 工具定义
tools = [
    {
        "name": "get_current_time",
        "description": "获取当前系统时间",
        "parameters": {"type": "object", "properties": {}}
    },
    {
        "name": "calculate_square", 
        "description": "计算一个数字的平方",
        "parameters": {
            "type": "object",
            "properties": {
                "number": {"type": "number", "description": "输入数字"}
            },
            "required": ["number"]
        }
    }
]

# 工具实现
async def execute_tool(name, arguments):
    if name == "get_current_time":
        from datetime import datetime
        return {"result": datetime.now().isoformat()}
    elif name == "calculate_square":
        return {"result": arguments["number"] ** 2}
    else:
        return {"error": f"未知工具: {name}"}

然后设置 MCP 服务器,让 LLM 能通过标准输入输出调用这些工具。这里需要模拟 LLM 的请求格式,实际项目中会用 Claude 或 GPT 的 tool calling 功能。

4.4 连接 LLM 完成端到端流程

最后把 RAG 和 MCP 组合起来。流程如下:

  1. 用户输入问题
  2. 先用 RAG 检索相关知识片段
  3. 把问题、检索结果、可用工具描述一起发给 LLM
  4. LLM 决定是否需要调用工具,如需调用则通过 MCP 执行
  5. 收集工具执行结果,再次发给 LLM 生成最终回答

这个 demo 可以用 OpenAI API 或本地 Ollama 部署的模型测试。关键观察点是:模型是否能正确判断何时该检索、何时该调用工具;工具调用参数是否准确;最终回答是否连贯。

5. 生产环境的关键配置和排查点

5.1 RAG 系统的性能优化

检索速度主要取决于向量索引类型和硬件。对于百万级文档,HNSW 索引比暴力搜索快很多,但需要更多内存。如果查询 QPS 高,可以考虑在内存中缓存热点查询的检索结果。

另一个常忽略的点是 Embedding 模型的选择。通用模型(如 text-embedding-ada-002)覆盖面广但领域精度可能不足。如果你的文档专业性强(医学、法律、代码),用领域专用模型或微调现有模型能显著提升检索相关性。

我一般会设置检索质量监控:定期用一批标准问题测试,记录检索结果的相关性评分。如果评分持续下降,可能是文档更新后需要重新处理,或 Embedding 模型需要调整。

5.2 MCP 工具的可靠性和安全

工具调用最怕两件事:执行失败和安全漏洞。每个工具都应该有超时控制、输入验证、错误处理和详细日志。比如数据库查询工具要限制最大返回行数,文件操作工具要约束路径范围。

权限控制也很关键。不要用高权限账户运行 MCP Server,更不要让它能执行任意系统命令。通过工具白名单和参数校验,把风险操作隔离在沙箱内。

实际部署时,我建议先用模拟模式跑一遍:记录工具调用参数但不实际执行。确认模型生成的调用序列符合预期后,再开启真实执行。这样能避免测试阶段误删数据或发送垃圾邮件。

5.3 混合系统的故障排查顺序

当 RAG+MCP 系统出问题时,按这个顺序排查:

  1. 检查输入问题 :是否包含特殊字符、编码异常、超出长度限制
  2. 验证 RAG 检索 :检索结果是否相关、片段数量是否合理、向量库是否正常更新
  3. 检查工具调用 :MCP Server 是否存活、工具参数格式是否正确、执行是否超时
  4. 查看 LLM 交互 :上下文是否过长、模型是否误解指令、返回格式是否解析错误
  5. 审查系统资源 :内存、CPU、磁盘、网络是否达到瓶颈

日志要分层记录:用户问题、检索结果、工具调用请求、工具执行结果、模型生成内容。这样无论问题出在哪个环节,都能快速定位。

6. 常见误区与进阶方向

6.1 不要过度依赖单一方案

有些人试图用 RAG 解决所有问题,比如把操作步骤也存入知识库,让模型“读说明书”后生成操作命令。这种方案对简单任务有效,但遇到需要多状态维护的复杂流程时,远不如 MCP 的直接调用可靠。

反过来,也有人想用 MCP 工具实现所有知识查询,比如封装一个“搜索知识库”工具。这相当于重新造了一个检索器,而且失去了向量检索的语义匹配能力。

正确的思路是根据任务类型选择主导方案:事实查询主导用 RAG,操作流程主导用 MCP,混合任务设计好切换逻辑。

6.2 评估效果不要只看准确率

除了回答准确性,还要关注响应延迟、资源消耗、失败率和可维护性。一个准确率 95% 但平均响应 10 秒的系统,可能不如准确率 85% 但 1 秒内响应的系统实用。

对于 MCP 工具链,重点评估端到端成功率(从用户提问到最终完成的比例)和平均完成时间。单个工具再快,如果经常因为某个环节失败而重试,整体体验也会很差。

6.3 进阶优化方向

RAG 方面可以探索:多检索器融合(关键词+向量+图数据库)、检索结果重排序、对话历史感知的检索策略。MCP 方面值得尝试:工具调用规划优化、执行状态管理、工具自动发现与组合。

长期看,RAG 和 MCP 的界限会模糊。未来可能会出现统一框架,根据用户意图自动选择知识检索或工具调用,甚至混合执行。但现阶段,理解两者的设计哲学和适用场景,仍然是构建可靠 AI 应用的基础。

最后提醒一点:无论用哪种方案,都要预留人工审核或干预的接口。完全自主的系统在复杂环境下依然容易出错,关键业务至少要有日志审查和紧急停止机制。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐