1. 为什么我们需要重新审视 AI 应用开发平台
过去一年,我接触了不下二十个团队在搞 AI 应用落地,从几个人小团队到大厂创新部门都有。一个非常普遍的困境是:Demo 跑通只要两天,但真要上线一个能稳定服务几百上千用户的 AI 应用,往往要拖两三个月。问题出在哪?不是模型不够强,而是工程化底座太薄。
大多数人起步的方式是写一个 Python 脚本,调一下 API,拼几段 Prompt,本地跑得挺开心。可一旦要接入多个模型供应商、要管理不同版本的 Prompt、要让 AI 能调用外部工具、要接入企业知识库、要做权限和审计,整个项目就变成了一团乱麻。代码里到处是硬编码的 API Key,Prompt 散落在各个文件里,换个模型要改十几处地方,加一个新工具要重新理解整个调用链。
XXL-AI 这个项目标题里提到的几个关键词——Agent 编排、多供应商、MCP + SKILL + RAG 扩展、工程化底座——恰好对应了上面这些痛点。它想做的事情,是把 AI 应用开发从“手工作坊”推进到“流水线工厂”的阶段。说得直白一点:你不再需要从零搭建一套 Agent 调度系统,不需要自己造 RAG 检索层,不需要为每个模型供应商写适配代码,而是站在一个已经搭好的底座上,专注于你的业务逻辑。
这篇文章适合谁看?如果你正在做 AI 应用开发,或者准备把 AI 能力集成到现有系统里,又或者你是一个技术负责人正在评估 AI 中台方案,那这篇内容应该能给你不少参考。我会从整体设计思路讲到核心模块的实现细节,再分享一些实操中踩过的坑和排查技巧。全文基于我对这类平台的工程实践理解来展开,尽量做到“看完就能抄作业”。
2. 整体架构设计与核心思路拆解
2.1 从“脚本堆叠”到“平台化”的演进逻辑
大部分团队做 AI 应用的第一版,都是脚本堆叠。一个main.py里塞满了 Prompt 模板、API 调用、结果解析。这种做法的好处是快,坏处是没有任何复用性。第二个应用来了,复制粘贴改一改,第三个应用来了,再复制一遍。三个月后,你有了十几个版本的main.py,每个都略有不同,谁也不敢删。
XXL-AI 这类平台的核心思路,是把 AI 应用开发中的共性能力抽出来,做成可复用的组件。哪些是共性能力?我梳理了一下:
- 模型接入层:不同供应商的 API 协议不一样,请求格式、返回结构、流式输出方式都有差异。这一层要做统一封装。
- Agent 编排层:一个复杂任务往往需要多个 Agent 协作,谁先谁后、怎么传递上下文、失败了怎么重试,这些逻辑需要统一管理。
- 扩展能力层:MCP 负责工具调用,SKILL 负责封装特定领域能力,RAG 负责知识检索。这三者解决的是“让 AI 能做事”和“让 AI 知道得更多”的问题。
- 工程化底座:配置管理、日志追踪、权限控制、版本管理、监控告警。这些是让系统能稳定运行的基础设施。
这个分层逻辑不是拍脑袋想出来的,而是从大量实际项目中总结出来的。你去看任何一个成熟的 AI 应用平台,基本都逃不出这个框架。区别只在于每一层的实现深度和灵活度。
2.2 多供应商接入的设计取舍
多供应商接入这件事,看起来简单,做起来坑很多。最直接的做法是写一个if-else,根据供应商名字走不同分支。但这样做的后果是,每接一个新供应商就要改核心代码,违反开闭原则。
更合理的做法是定义一套统一的模型接口,每个供应商实现这个接口。接口需要覆盖哪些能力?我总结了几点:
| 能力项 | 说明 | 是否必须 |
|---|---|---|
| 同步对话 | 一次性返回完整结果 | 必须 |
| 流式对话 | 逐 token 返回,用于打字机效果 | 必须 |
| 函数调用 | 让模型输出结构化的工具调用请求 | 必须 |
| 多模态输入 | 支持图片、音频等输入 | 视场景 |
| 嵌入向量 | 用于 RAG 检索 | 视场景 |
| 参数配置 | 温度、最大 token 数等 | 必须 |
定义好接口之后,每个供应商的适配器只需要做一件事:把统一接口的请求翻译成该供应商的 API 格式,再把返回结果翻译回来。这样新增供应商时,只需要写一个适配器,不需要动核心逻辑。
注意:不同供应商对函数调用的支持程度差异很大。有些供应商只支持特定的 JSON Schema 格式,有些对嵌套结构支持不好。在设计统一接口时,建议以最严格的那个供应商为基准,其他供应商做向上兼容。
2.3 Agent 编排的核心模型
Agent 编排是这类平台最核心也最复杂的能力。什么叫编排?简单说就是定义多个 Agent 之间的协作关系。我见过几种常见的编排模式:
串行模式:Agent A 的输出作为 Agent B 的输入,依次执行。适合流程固定的场景,比如“先检索知识库,再生成回答,最后做事实核查”。
并行模式:多个 Agent 同时执行,最后汇总结果。适合需要多角度分析的场景,比如“同时从技术、成本、风险三个维度评估一个方案”。
条件分支模式:根据上一个 Agent 的输出决定下一步走哪个分支。适合需要动态决策的场景,比如“如果用户问的是技术问题,走技术 Agent;如果是售后问题,走客服 Agent”。
循环模式:Agent 反复执行直到满足某个条件。适合需要迭代优化的场景,比如“生成代码 → 运行测试 → 如果失败则修复 → 再测试”。
XXL-AI 的编排能力应该覆盖了以上几种模式。在实际使用中,我建议先从串行模式开始,把流程跑通,再逐步引入更复杂的编排逻辑。一上来就搞复杂的 DAG,调试起来会让你怀疑人生。
2.4 MCP、SKILL、RAG 三者的定位与协作
这三个概念经常被混在一起讨论,但它们的定位其实很清晰:
MCP解决的是“AI 怎么调用外部工具”的问题。它定义了一套标准协议,让 AI 能够以统一的方式发现和调用各种工具。你可以把它理解成 AI 世界的 USB 接口——不管什么设备,只要符合 USB 标准,就能插上去用。
SKILL解决的是“怎么把特定领域的能力封装成可复用的模块”的问题。一个 SKILL 可能包含多个工具调用、多段 Prompt、甚至多个 Agent 的协作逻辑。它比 MCP 更上层,更贴近业务。
RAG解决的是“AI 怎么获取外部知识”的问题。它通过检索增强生成的方式,让 AI 在回答问题时能够参考企业知识库中的内容,而不是只依赖训练时学到的知识。
三者的协作关系可以这样理解:用户发起一个请求,Agent 编排层决定需要哪些能力,然后通过 MCP 调用工具、通过 SKILL 执行领域逻辑、通过 RAG 检索相关知识,最后汇总生成回答。
3. 核心模块的实操要点与避坑指南
3.1 MCP 工具接入的完整流程
MCP 的接入流程,我把它拆成五步:
第一步:定义工具描述。每个工具需要提供名称、描述、参数 Schema。描述要写得让模型能理解什么时候该用这个工具。我见过很多工具描述写得太简略,导致模型根本不知道什么时候该调用。
第二步:实现工具逻辑。这是实际的业务代码,比如查询数据库、调用外部 API、执行计算等。注意要做好错误处理,因为工具调用失败时,模型需要知道失败原因才能决定下一步。
第三步:注册到 MCP Server。把工具注册到 MCP Server 上,让 Agent 能够发现它。注册信息包括工具描述、参数 Schema、调用地址等。
第四步:配置 Agent 的工具权限。不是每个 Agent 都需要访问所有工具。建议按最小权限原则配置,避免 Agent 调用不该调用的工具。
第五步:测试与调优。用各种边界情况测试工具调用,观察模型的调用决策是否合理。如果模型频繁调用错误的工具,可能需要调整工具描述或增加示例。
实操心得:工具描述里加上“什么时候不该用这个工具”的说明,能显著降低误调用率。比如“当用户询问天气时不要使用此工具,此工具仅用于查询订单状态”。
3.2 SKILL 封装的设计原则
SKILL 的设计,我总结了几条原则:
单一职责:一个 SKILL 只做一件事。比如“合同审查”是一个 SKILL,“简历筛选”是另一个 SKILL。不要把不相关的功能塞进同一个 SKILL。
输入输出明确:SKILL 的输入和输出都要有清晰的 Schema 定义。这样在编排时才能正确地传递数据。
可组合:SKILL 应该能被其他 SKILL 或 Agent 调用。这意味着它不能依赖特定的上下文,而应该通过参数接收所有需要的信息。
可测试:每个 SKILL 都应该能独立测试,不依赖完整的 Agent 编排环境。这样才能快速迭代。
版本管理:SKILL 的变更要有版本记录。因为 SKILL 的行为变化可能会影响依赖它的 Agent,需要能够回滚。
3.3 RAG 知识库的构建与检索优化
RAG 的构建流程,我把它分成四个阶段:
数据准备阶段:收集和清洗知识文档。这一步的工作量往往被低估。实际项目中,数据清洗可能占到整个 RAG 工作量的 60% 以上。文档格式五花八门,PDF、Word、Excel、网页、数据库导出,每种格式的解析方式都不一样。
切分与向量化阶段:把长文档切分成适合检索的片段,然后转成向量存入向量数据库。切分策略很关键,切得太碎会丢失上下文,切得太大会降低检索精度。我的经验是,中文文档每段控制在 300-500 字比较合适。
检索阶段:用户提问时,把问题转成向量,在向量数据库中检索最相似的片段。这里有几个优化点:一是使用混合检索(向量检索 + 关键词检索),二是加入重排序模型,三是对检索结果做去重和过滤。
生成阶段:把检索到的片段作为上下文,连同用户问题一起送给模型生成回答。注意要控制上下文长度,避免超出模型的 token 限制。
| 优化方向 | 具体做法 | 预期效果 |
|---|---|---|
| 切分优化 | 按语义切分而非固定长度 | 提升检索相关性 |
| 混合检索 | 向量 + 关键词双路召回 | 提升召回率 |
| 重排序 | 用交叉编码器对结果重排 | 提升 Top-K 精度 |
| 查询改写 | 用模型改写用户问题 | 提升检索命中率 |
| 上下文压缩 | 提取关键句而非全文 | 节省 token 消耗 |
3.4 工程化底座的必备能力
工程化底座是让系统能稳定运行的基础。我列一下我认为必备的能力:
配置管理:所有配置项集中管理,支持环境隔离(开发、测试、生产)。敏感信息如 API Key 要加密存储。
日志与追踪:每次请求都要有完整的调用链日志,包括输入、输出、耗时、token 消耗、工具调用记录等。出问题时能快速定位。
权限控制:不同用户/角色能访问的 Agent、工具、知识库要能精细控制。
限流与熔断:防止某个供应商的故障拖垮整个系统。当某个供应商的错误率超过阈值时,自动切换到备用供应商。
版本管理:Prompt、SKILL、Agent 配置都要有版本记录,支持灰度发布和快速回滚。
监控告警:关键指标如响应时间、错误率、token 消耗要有监控面板,异常时能及时告警。
4. 实操过程与核心环节实现
4.1 环境准备与基础配置
假设我们要搭建一个基于 XXL-AI 的智能客服系统。首先需要准备基础环境:
# 基础依赖 Python 3.10+ PostgreSQL 14+ # 存储配置和日志 Redis 7+ # 缓存和会话管理 Milvus 2.x # 向量数据库,用于 RAG配置文件的组织方式,我建议按模块拆分:
# config/model_providers.yaml providers: - name: provider_a type: openai_compatible base_url: https://api.example-a.com/v1 api_key: ${PROVIDER_A_KEY} models: - name: model-large max_tokens: 8192 supports_function_call: true - name: model-small max_tokens: 4096 supports_function_call: true - name: provider_b type: custom base_url: https://api.example-b.com/v2 api_key: ${PROVIDER_B_KEY}注意:API Key 不要直接写在配置文件里,用环境变量注入。生产环境建议接入密钥管理服务。
4.2 Agent 编排的配置与调试
定义一个客服 Agent 的编排配置:
# agents/customer_service.yaml name: customer_service_agent description: 智能客服 Agent,处理用户咨询 model: provider_a/model-large system_prompt: | 你是一个专业的客服助手。回答用户问题时,请遵循以下原则: 1. 先检索知识库,基于知识库内容回答 2. 如果知识库中没有相关信息,如实告知用户 3. 涉及订单查询时,调用订单查询工具 4. 保持礼貌和专业 tools: - order_query - refund_apply - knowledge_search rag: knowledge_base: customer_service_kb top_k: 5 score_threshold: 0.7调试 Agent 时,我习惯用“最小可复现”原则:先用最简单的输入测试,确认基本流程通了,再逐步增加复杂度。比如先测试纯知识库问答,再测试工具调用,最后测试多轮对话。
4.3 RAG 知识库的搭建实操
知识库搭建的第一步是数据接入。假设我们有一批客服文档,格式包括 PDF 和 Word:
from xxl_ai.rag import DocumentLoader, TextSplitter, VectorStore # 加载文档 loader = DocumentLoader() docs = loader.load_directory("./docs", formats=["pdf", "docx"]) # 切分文档 splitter = TextSplitter( chunk_size=400, chunk_overlap=50, separators=["\n\n", "\n", "。", ";", " "] ) chunks = splitter.split(docs) # 向量化并存储 store = VectorStore( provider="milvus", collection="customer_service_kb", embedding_model="provider_a/embedding-v2" ) store.add_documents(chunks)切分参数的选择依据:chunk_size=400是因为中文客服文档通常每段在 300-500 字之间,400 字能覆盖大部分完整语义单元。chunk_overlap=50是为了避免关键信息被切断。分隔符优先级从大到小,优先按段落切,其次按句子切。
4.4 多供应商切换与容灾配置
多供应商的价值在容灾时体现得最明显。配置示例:
# config/routing.yaml routing: default_provider: provider_a fallback_providers: - provider_b - provider_c rules: - condition: "error_rate > 0.1" action: "switch_to_fallback" - condition: "latency > 5000" action: "switch_to_fallback" - condition: "token_quota_exceeded" action: "switch_to_fallback"切换逻辑的实现要点:一是要记录每个供应商的健康状态,二是切换时要保持请求上下文不变,三是切换后要记录日志以便分析。
5. 常见问题与排查技巧实录
5.1 Agent 调用工具失败怎么办
这是最常见的问题。排查思路按以下顺序:
第一步:确认工具是否注册成功。检查 MCP Server 的日志,看工具是否在启动时成功注册。如果注册失败,通常是 Schema 格式有问题。
第二步:确认模型是否输出了正确的工具调用请求。查看模型的原始输出,看它是否生成了符合 Schema 的工具调用 JSON。如果格式不对,可能是 Prompt 中工具描述不够清晰。
第三步:确认工具执行是否报错。查看工具执行的日志,看是否有异常。常见问题包括参数类型不匹配、外部服务不可用、权限不足等。
第四步:确认结果是否正确返回给模型。有时候工具执行成功了,但结果没有正确传回模型,导致模型不知道工具已经执行完毕。
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 模型不调用工具 | 工具描述不清晰 | 优化描述,增加使用示例 |
| 调用参数错误 | Schema 定义不准确 | 检查参数类型和必填项 |
| 工具执行超时 | 外部服务响应慢 | 增加超时配置,优化外部服务 |
| 结果未返回 | 上下文传递丢失 | 检查编排配置中的数据流 |
| 频繁调用同一工具 | 模型陷入循环 | 增加最大调用次数限制 |
5.2 RAG 检索效果差的优化路径
RAG 检索效果差,通常表现为:检索到的内容与问题不相关,或者相关内容没有被检索到。优化路径如下:
先检查切分质量。把检索到的片段打印出来,看是否语义完整。如果片段被切得支离破碎,调整切分参数。
再检查向量模型。不同的向量模型在不同领域的表现差异很大。通用模型在专业领域的表现可能不如领域微调过的模型。
然后检查检索策略。纯向量检索在关键词匹配上表现较差。加入关键词检索做混合召回,通常能显著提升效果。
最后检查重排序。如果 Top-K 中有相关结果但排名靠后,加入重排序模型能改善。
实操心得:RAG 调优是一个迭代过程,不要指望一次配置就达到最佳效果。建议建立一个评估集,每次调整后用评估集测试,用数据驱动优化。
5.3 多供应商切换时的上下文丢失问题
这个问题比较隐蔽。当系统从供应商 A 切换到供应商 B 时,如果对话历史没有正确传递,用户会感觉“AI 失忆了”。
解决方案是:在编排层维护一个统一的对话上下文,与具体供应商解耦。每次请求时,从统一上下文中取出历史消息,转换成目标供应商的格式。切换供应商时,只需要重新转换格式,不需要重新构建上下文。
5.4 性能瓶颈的定位与优化
AI 应用的性能瓶颈通常出现在三个地方:模型推理、工具调用、知识检索。
定位方法:在调用链日志中记录每个环节的耗时,找出耗时最长的环节。
优化方向:
- 模型推理慢:换更小的模型、开启流式输出、使用缓存
- 工具调用慢:并行调用无依赖的工具、增加超时和重试
- 知识检索慢:优化向量索引、减少检索数量、加入缓存
6. 一些个人体会与后续扩展思路
做 AI 应用平台这件事,我最大的体会是:不要追求一步到位。我见过太多团队一开始就想做一个“万能平台”,结果做了半年还在改架构。更务实的做法是,先解决当前最痛的问题,比如先把多供应商接入做了,再把 RAG 做了,最后再搞复杂的 Agent 编排。每一步都产生可用的价值,而不是憋大招。
另一个体会是,可观测性比功能更重要。AI 应用的不确定性比传统软件大得多,同样的输入可能得到不同的输出。如果没有完善的日志和追踪,出了问题根本无从下手。我建议在项目初期就把日志和监控做好,后面会省很多事。
关于后续扩展,我觉得有几个方向值得关注:一是 Agent 的自我评估和自动优化,让 Agent 能根据反馈自动调整策略;二是更细粒度的权限控制,支持按数据行级别的访问控制;三是与更多外部系统的深度集成,比如工单系统、CRM 系统等。
最后分享一个小技巧:在调试 Agent 编排时,把每个步骤的输入输出都打印出来,用不同颜色区分不同 Agent 的输出。这样一眼就能看出是哪一步出了问题。这个习惯帮我节省了大量排查时间。