ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从零搭建生产级AI应用开发平台:Agent编排、多供应商与RAG实战

从零搭建生产级AI应用开发平台:Agent编排、多供应商与RAG实战 1. 为什么我要自己搭一套 AI 应用开发平台先说结论市面上能用的 Agent 框架我基本都摸过一遍从早期的 LangChain 到后来的各种编排工具最后促使我自己动手做 XXL-AI 的原因只有一个——没有一个平台能同时把「编排灵活度」「多供应商切换」「扩展能力」和「工程化落地」这四件事都做扎实。大部分框架的典型问题是Demo 跑起来很惊艳一上生产就露馅。要么是编排逻辑写死在代码里改一个流程要重新发版要么是模型供应商锁死想从一家换到另一家得改几十处调用要么是扩展能力弱想接个知识库、加个自定义工具得从底层改起。更别提工程化那部分——日志、监控、限流、重试、成本统计这些真正决定能不能上生产的东西很多框架压根没认真做。XXL-AI 这个项目就是冲着这些痛点去的。它的定位很明确一个面向生产环境的 AI 应用开发平台核心能力包括 Agent 编排、多供应商接入、MCP SKILL RAG 三层扩展体系以及一整套工程化底座。说白了它想解决的是「从想法到上线」这条链路上所有的脏活累活。这篇文章适合谁看如果你正在做 AI 应用开发被编排逻辑折磨过被供应商切换坑过或者正在纠结 RAG 到底怎么落地那这篇内容应该能给你不少参考。我会把每个模块的设计思路、实操细节、踩过的坑都摊开讲尽量做到你照着就能复现。2. 整体架构设计与核心思路拆解2.1 四层架构的分层逻辑XXL-AI 的整体架构我分成了四层从上到下依次是应用层、编排层、能力层、底座层。这个分层不是拍脑袋定的而是根据实际开发中「变化频率」来划分的——越往上变化越快越往下越稳定。应用层是面向具体业务场景的比如客服机器人、文档助手、代码审查工具。这一层变化最频繁今天做个新场景明天调个流程所以它必须足够轻不能有太多约束。编排层是 Agent 的核心负责定义「谁在什么时候做什么」。这一层的关键是可视化 可编程双模式——简单流程拖拽搞定复杂逻辑写代码扩展。我见过太多团队在纯可视化工具里挣扎稍微复杂点的条件分支就画不出来了。能力层就是 MCP、SKILL、RAG 这三块。MCP 负责对接外部工具和数据源SKILL 负责封装可复用的能力单元RAG 负责知识增强。这三者各司其职又能互相组合。底座层是工程化的部分模型供应商抽象、日志监控、限流熔断、成本统计、权限管理。这层最不起眼但决定了平台能不能扛住生产流量。提示分层的关键原则是「依赖单向」——上层可以调下层下层不能反向依赖上层。我见过不少项目因为底座层反向依赖了业务逻辑导致换个场景就得改底层非常痛苦。2.2 为什么选择「编排 扩展 底座」三件套很多人问我为什么不直接用一个现成的 Agent 框架非要自己搭我的回答是现成框架解决的是「能不能跑」我要解决的是「能不能规模化跑」。编排解决的是「流程怎么定义」。一个真实的 AI 应用流程往往不是线性的——有并行、有分支、有循环、有中断恢复。纯代码写编排改起来痛苦纯可视化画编排复杂场景画不出来。所以 XXL-AI 的做法是用 DSL 描述编排可视化工具生成 DSL代码也能直接写 DSL。这样既保证了灵活性又降低了门槛。扩展解决的是「能力怎么复用」。MCP 是工具接入的标准协议SKILL 是能力封装的单元RAG 是知识注入的方式。这三者组合起来能让一个 Agent 快速获得「查资料、调工具、用知识」的能力而不用每次从零写。底座解决的是「怎么稳定运行」。这部分最容易被忽视但恰恰是生产环境和 Demo 的分水岭。模型调用失败怎么重试供应商限流怎么切换成本超预算怎么告警这些问题不解决平台就是个玩具。2.3 多供应商抽象的设计取舍多供应商接入这块我踩过最大的坑就是抽象层次选错了。一开始我想做一个「万能接口」把所有供应商的差异都抹平结果发现根本做不到——不同供应商的参数、能力、返回格式差异太大强行统一反而丢了很多特性。后来我改成了两层抽象底层是「供应商适配器」每个供应商一个适配器负责把统一请求转成该供应商的格式上层是「能力接口」定义平台需要的能力比如对话、嵌入、重排由适配器实现。这样既保留了供应商特性又保证了上层调用的一致性。具体来说一个对话请求进来平台会先根据路由策略选一个供应商然后调用对应的适配器。适配器负责处理参数映射、鉴权、重试、错误转换。如果这个供应商挂了平台会自动降级到备用供应商。整个过程对上层透明。抽象层职责变化频率能力接口定义平台能力契约低供应商适配器处理供应商差异中路由策略决定用哪个供应商高降级熔断处理故障低这个设计的核心好处是加一个新供应商只需要写一个适配器不用动上层任何代码。我实测下来接一个新供应商平均半天就能搞定。3. Agent 编排的核心细节与实操要点3.1 编排 DSL 的设计哲学XXL-AI 的编排 DSL 我改了三版才定型。第一版是纯 JSON写起来太啰嗦第二版是 YAML可读性好但表达能力有限第三版是基于 YAML 的领域特定语法在 YAML 基础上加了变量引用、条件表达式、循环语法。一个最简单的编排定义长这样name: customer_service nodes: - id: receive type: input schema: question: string - id: classify type: llm model: gpt-4 prompt: | 判断用户问题类型{{question}} 只返回售前/售后/投诉 - id: route type: switch condition: {{classify.output}} cases: 售前: sales_flow 售后: after_sales_flow 投诉: complaint_flow这个 DSL 的关键设计点是节点之间通过变量引用连接而不是硬编码的连线。{{classify.output}}这种写法让流程的依赖关系一目了然也方便做静态分析——比如检测循环依赖、未定义变量。注意变量引用一定要做类型检查。我早期版本没做结果运行时才发现类型不匹配排查起来很痛苦。现在 DSL 编译阶段就会做类型推导提前报错。3.2 节点类型与执行引擎编排引擎支持的核心节点类型有这几类输入输出节点定义流程的入口和出口负责参数校验和结果格式化。LLM 节点调用大模型支持提示词模板、参数配置、输出解析。工具节点调用 MCP 工具或 SKILL支持参数映射和结果处理。控制节点条件分支、循环、并行、等待、中断。知识节点RAG 检索支持多路召回和重排。执行引擎的核心是状态机 事件驱动。每个节点执行完会发出事件引擎根据事件决定下一步。这样做的好处是支持中断恢复——如果流程执行到一半服务重启了可以从最后一个成功节点继续不用从头再来。执行引擎还有一个关键设计是并发控制。并行节点会同时执行多个分支但引擎会限制最大并发数避免打爆下游服务。这个限制可以在编排定义里配置也可以全局配置。3.3 实操从零编排一个多 Agent 协作流程光说理论没意思我拿一个实际场景来演示一个「技术文档问答」的多 Agent 协作流程。这个流程有三个 Agent检索 Agent 负责找相关文档推理 Agent 负责组织答案审核 Agent 负责检查答案质量。第一步定义检索 Agentname: retrieval_agent nodes: - id: embed type: llm model: embedding-model input: {{question}} - id: search type: rag index: tech_docs query_vector: {{embed.output}} top_k: 10 - id: rerank type: llm model: rerank-model query: {{question}} documents: {{search.output}} top_k: 3第二步定义推理 Agentname: reasoning_agent nodes: - id: generate type: llm model: gpt-4 prompt: | 根据以下文档回答问题 文档{{documents}} 问题{{question}} 要求只基于文档内容回答不确定的地方明确说明。第三步定义审核 Agentname: review_agent nodes: - id: check type: llm model: gpt-4 prompt: | 检查以下答案是否基于给定文档 答案{{answer}} 文档{{documents}} 返回PASS 或 FAIL 原因 - id: decide type: switch condition: {{check.output}} cases: PASS: end FAIL: reasoning_agent最后把三个 Agent 串起来name: doc_qa nodes: - id: retrieval type: agent ref: retrieval_agent - id: reasoning type: agent ref: reasoning_agent input: documents: {{retrieval.output}} - id: review type: agent ref: review_agent input: answer: {{reasoning.output}}这个流程跑下来实测效果比单 Agent 好很多。检索 Agent 专注找资料推理 Agent 专注组织答案审核 Agent 专注质量把关各司其职。审核不通过会自动回到推理 Agent 重来最多重试 3 次。3.4 编排的注意事项与踩坑记录第一个坑是循环控制。审核 Agent 失败后回到推理 Agent这个循环必须有次数限制否则可能死循环。我在 DSL 里加了max_iterations配置默认 3 次超过就强制结束并返回当前结果。第二个坑是上下文膨胀。多 Agent 协作时每个 Agent 的输出都会传给下一个如果不做裁剪上下文会越来越大最后超出模型窗口。我的做法是只传必要字段比如审核 Agent 只需要答案和文档不需要检索 Agent 的中间过程。第三个坑是错误传播。一个 Agent 失败了是让整个流程失败还是降级处理这个要按场景配置。我的默认策略是关键节点失败则流程失败非关键节点失败则降级。比如检索失败可以降级到只用模型知识回答但推理失败就没法降级了。4. MCP SKILL RAG 三层扩展体系4.1 MCP工具接入的标准协议MCP 这块我理解下来它的核心价值是把「工具接入」这件事标准化。在没有 MCP 之前每接一个工具都要写一套适配代码工具多了就是灾难。MCP 定义了工具的描述格式、调用协议、返回格式让工具可以像插件一样即插即用。XXL-AI 对 MCP 的支持分两部分作为 MCP 客户端能调用外部 MCP 服务作为 MCP 服务端能把平台能力暴露给其他系统。这两部分我都做了实测下来客户端用得更多。接一个 MCP 工具的过程大概是这样的mcp_servers: - name: filesystem transport: stdio command: npx args: [-y, modelcontextprotocol/server-filesystem, /data] - name: database transport: http url: http://localhost:8080/mcp headers: Authorization: Bearer {{token}}配置好之后平台会自动发现这些 MCP 服务提供的工具并在编排里可用。调用的时候直接引用工具名就行- id: read_file type: mcp server: filesystem tool: read_file input: path: {{file_path}}提示MCP 服务的鉴权信息不要硬编码在配置里用变量引用从环境变量或密钥管理服务注入。我见过有人把 token 直接写配置文件提交到仓库非常危险。4.2 SKILL可复用能力的封装单元SKILL 和 MCP 的区别我用一句话概括MCP 是「接外部工具」SKILL 是「封装内部能力」。MCP 解决的是「怎么调别人的东西」SKILL 解决的是「怎么把自己的东西复用起来」。一个 SKILL 本质上是一段可复用的编排逻辑加上输入输出定义。比如「文档摘要」这个 SKILLname: summarize description: 对长文档生成摘要 input: document: string max_length: integer output: summary: string nodes: - id: chunk type: split input: {{document}} chunk_size: 2000 - id: summarize_each type: map over: {{chunk.output}} nodes: - id: sum type: llm model: gpt-4 prompt: 总结以下内容{{item}} - id: merge type: llm model: gpt-4 prompt: | 合并以下摘要控制在 {{max_length}} 字以内 {{summarize_each.output}}SKILL 的好处是一次封装处处复用。我在多个项目里都用到了这个摘要 SKILL不用每次重写。而且 SKILL 可以嵌套——一个 SKILL 里可以调另一个 SKILL形成能力组合。SKILL 的管理我做了版本控制。每次修改 SKILL 会生成新版本编排里可以指定用哪个版本。这样升级 SKILL 不会影响正在运行的流程非常实用。4.3 RAG知识增强的落地细节RAG 这块是问得最多的也是坑最多的。我先说一个常见误区很多人以为 RAG 就是「向量检索 拼提示词」其实远不止。一个能用的 RAG 系统至少包含这几个环节文档解析、分块、嵌入、索引、检索、重排、生成。文档解析这块不同格式差异很大。PDF 要处理表格和图片Word 要处理样式Markdown 要处理代码块。我的做法是按格式选解析器解析结果统一成结构化文本。图片和表格单独提取作为元数据附加。分块是最影响效果的环节。分太大检索精度低分太小上下文不完整。我的经验值是500-1000 字一块重叠 100-200 字。但这不是固定的代码类文档要按函数分块法律文档要按条款分块。XXL-AI 支持自定义分块策略按文档类型配置。嵌入和索引这块关键是选对嵌入模型。中文场景我实测下来多语言模型比纯中文模型效果好因为很多技术文档是中英混合的。索引我用的是向量 关键词混合索引检索时两路召回再融合命中率比纯向量高不少。检索和重排是提升效果的关键。我的做法是先粗召回 20-50 条再用重排模型精排到 3-5 条。重排模型比嵌入模型更准但更慢所以只用在精排阶段。实测下来加了重排之后答案准确率能提升 20% 以上。生成这块提示词模板很关键。我的模板里会明确要求「只基于给定文档回答」「不确定就说不确定」「引用来源」。这样能有效减少幻觉。RAG 环节关键参数我的推荐值分块大小chunk_size500-1000 字分块重叠overlap100-200 字粗召回数top_k20-50精排数rerank_top_k3-5相似度阈值threshold0.74.4 三层体系怎么组合使用MCP、SKILL、RAG 这三者不是孤立的组合起来才能发挥最大价值。我举一个实际例子一个「合同审查」Agent。它用 RAG 检索相关法条和公司历史合同用 SKILL 封装「条款提取」「风险识别」这些可复用能力用 MCP 接入外部工具比如「企业信息查询」「印章识别」。整个流程是先 RAG 找相关法条再 SKILL 提取合同条款然后 MCP 查企业信息最后综合判断风险。这种组合的价值在于每个能力都专注做一件事通过编排组合成复杂能力。这比写一个巨大的单体 Agent 要好维护得多。5. 工程化底座的实现细节5.1 模型供应商抽象与路由多供应商这块前面说了是两层抽象。这里补充一下路由策略的实现。路由决策考虑这几个因素成本、延迟、可用性、能力匹配。成本这块每个供应商每个模型都有单价配置路由时会估算这次调用的成本优先选便宜的。延迟这块平台会实时统计每个供应商的响应时间优先选快的。可用性这块会做健康检查挂了的供应商自动剔除。能力匹配这块比如需要长上下文就选支持长上下文的模型。路由策略是可配置的不同场景可以用不同策略。比如客服场景优先延迟批处理场景优先成本。routing: strategy: cost_first fallback: - provider: openai model: gpt-4 - provider: anthropic model: claude-3 circuit_breaker: failure_threshold: 5 recovery_timeout: 60熔断这块我用的是经典的滑动窗口 失败率阈值。一个供应商在 60 秒内失败超过 5 次就熔断 60 秒期间请求走备用供应商。60 秒后放一个请求试探成功就恢复。5.2 日志、监控与成本统计工程化底座里我觉得最重要的是可观测性。一个 AI 应用出问题了你得能快速定位是哪个环节的问题。XXL-AI 的日志分三层请求日志、节点日志、模型调用日志。请求日志记录整个流程的输入输出、耗时、状态。节点日志记录每个节点的执行情况。模型调用日志记录每次模型调用的提示词、返回、token 数、成本。这三层日志通过 trace_id 关联排查问题时可以一路追下去。监控这块我做了几个关键指标QPS、P99 延迟、错误率、token 消耗、成本。这些指标按供应商、按模型、按场景维度统计方便发现异常。比如某个供应商的错误率突然升高或者某个场景的成本超预算都能及时告警。成本统计是很多团队忽视的但很重要。我见过有团队一个月烧了几万块才发现因为没做成本监控。XXL-AI 的成本统计精确到每次调用能按天、按场景、按用户维度汇总。5.3 限流、重试与降级限流这块我做了多级限流全局限流、供应商限流、用户限流。全局限流保护平台本身供应商限流保护下游用户限流防止单个用户打爆。重试策略要区分错误类型。网络错误、超时错误可以重试参数错误、鉴权错误不能重试。重试要用指数退避避免雪崩。我的默认配置是最多重试 3 次间隔 1s、2s、4s。降级策略按场景配置。比如模型调用失败可以降级到备用模型备用模型也失败可以降级到缓存结果缓存也没有就返回兜底话术。降级链路要提前设计好不能等出问题了才想。注意重试和降级都要考虑幂等性。如果一个操作不是幂等的重试可能导致重复执行。比如「下单」这种操作重试前要确认是否已经成功。5.4 权限与多租户如果平台要给多个团队用权限和多租户是必须的。XXL-AI 的权限模型是RBAC 资源隔离。角色分管理员、开发者、使用者权限控制到「能不能创建编排」「能不能调用某个 SKILL」「能不能看某个场景的日志」。多租户这块每个租户有独立的编排、SKILL、知识库、配置。租户之间数据隔离但可以共享公共的 MCP 工具和模型供应商。这样既保证了隔离性又避免了重复配置。6. 常见问题与排查技巧实录6.1 编排执行常见问题速查问题现象可能原因排查方法解决方案流程卡住不动节点等待外部响应看节点日志确认卡在哪个节点加超时配置超时后走降级变量引用报错变量名拼写错误或未定义检查 DSL 编译日志用编译期类型检查提前发现循环次数超限条件判断逻辑有问题看循环节点的执行记录检查条件表达式加日志上下文超限传递数据太多看模型调用的 token 数裁剪上下文只传必要字段并发冲突多个分支写同一变量看变量变更记录用局部变量避免共享状态6.2 RAG 效果差的排查思路RAG 效果差是最常见的问题我总结了一套排查流程第一步确认是检索问题还是生成问题。把检索到的文档单独拿出来看如果文档本身就不相关那是检索问题如果文档相关但答案不对那是生成问题。第二步如果是检索问题检查这几个点分块是否合理太大太小都不行、嵌入模型是否适合中文场景要用多语言模型、相似度阈值是否合适太高召回少太低噪音多、是否需要重排加了重排通常能提升。第三步如果是生成问题检查提示词模板。常见问题是提示词没有明确要求「只基于文档回答」导致模型自由发挥。另外要检查上下文是否太长太长的上下文会稀释关键信息。第四步如果都不行考虑换嵌入模型或加重排。我实测下来换一个更好的嵌入模型效果提升最明显。6.3 多供应商切换的坑多供应商切换有几个坑我踩过第一个坑是参数不兼容。不同供应商的参数名不一样比如有的叫max_tokens有的叫max_output_tokens。适配器要做好映射不能直接透传。第二个坑是返回格式不一致。有的返回content有的返回message.content有的返回choices[0].text。适配器要统一成平台格式。第三个坑是错误码不统一。限流错误有的返回 429有的返回 503。适配器要统一错误类型上层才能正确处理。第四个坑是能力差异。不是所有模型都支持函数调用、JSON 模式、流式输出。路由时要检查能力匹配不支持的特性要降级处理。6.4 性能优化的实操心得性能优化这块我最大的心得是先测量再优化。很多人一上来就优化结果优化了不关键的地方白费功夫。我的做法是先做全链路追踪找出耗时最长的环节。通常瓶颈在这几个地方模型调用占大头、RAG 检索如果索引大、工具调用如果外部服务慢。模型调用优化主要是缓存 并发。相同请求可以缓存结果多个独立调用可以并发。我实测下来加缓存能减少 30% 的调用量加并发能减少 50% 的延迟。RAG 检索优化主要是索引优化 召回策略。索引用 HNSW 比 IVF 快召回用混合检索比纯向量准。如果数据量大可以做分层索引先粗筛再精筛。工具调用优化主要是超时 降级。外部服务不可控必须设超时超时就走降级。我见过因为一个外部工具卡住导致整个流程挂掉的案例。7. 我在实际项目中的一些体会搭这套平台的过程中我最大的体会是AI 应用的难点不在模型而在工程。模型能力再强如果编排不灵活、扩展不方便、运行不稳定也做不出好产品。另一个体会是抽象要适度。抽象太少代码重复抽象太多灵活性差。XXL-AI 的抽象层次是我改了好几版才找到的平衡点——编排层足够灵活能力层足够复用底座层足够稳定。最后分享一个小技巧做 AI 应用一定要做灰度。新模型、新提示词、新流程先小流量试确认效果再全量。我见过太多直接全量上线结果效果崩了的案例。灰度不仅能降低风险还能积累对比数据帮你做决策。这套平台后续我还会继续迭代比如加入更多的编排节点类型、支持更多的供应商、优化 RAG 的检索效果。如果你也在做类似的事情欢迎交流踩过的坑可以一起填。
返回列表