资讯详情

资讯详情

用大模型集成遗留系统:Function Calling与RAG落地实践

前阵子我接了个活儿要把两个互不相干、都快被时代忘掉的传统系统统一接到大模型上。一个是最早那批老库存系统另一个是散落着大量 FAQ 和操作文档的客服知识库。名字我就不说了但在很多公司里你一定见过类似的东西——界面停在十年前业务逻辑藏在 SQL 和 Excel 里换个人就玩不转。这个项目做完之后最大的感受是用大模型做集成真正值钱的不是“聊天”而是给它装上一双能理解旧系统的“手”。这篇文章想把整个思路、选型过程、落地步骤以及我踩过的坑原原本本写出来。无论你是想给公司老系统做个 AI 入口还是单纯好奇大模型怎么和遗留系统打交道这篇应该能给你一份可以直接参考的底稿。1. 项目拆解两套传统体系到底卡在哪里1.1 第一套体系跑了快十年的老库存系统先说第一套。这套库存系统是公司最早自己开发的后端用的还是那几年流行的 Java 版单体框架前端是 PC 时代的传统界面。数据库倒是不小所有仓库、采购、退换货的数据都在里面。但问题也很典型对外只开了很少的接口大部分数据得靠直接连数据库查业务逻辑大量写在存储过程里加了什么表、改了什么状态没有完整文档。最头疼的是这套系统里有大量“人肉规则”。比如某个型号的库存低于某个数值就要自动触发采购提醒但临界值不在配置表里而是写死在代码中的再比如某些商品在特定时间段不允许出库这个规则没人说得全只有操作了几年的老员工知道。我在梳理它的接口时发现正式文档只描述了十来个子系统的功能但实际能被稳定调用的也就五六个。想做集成光搞清楚“哪个字段对应哪个含义”就够呛。1.2 第二套体系没人愿意维护的知识文档库第二个体系看起来不像“系统”更像一堆散落文档。客服团队维护了一份知识库包含产品的常见问题、退换货流程、话术模板仓库团队又有自己的操作手册采购部门偶尔还会往里丢几份供应商说明。这些内容主要存在共享盘里格式极不统一有 Word、有 PDF、还有聊天记录导出的文本。表面上看知识库应该有很清晰的结构但实际内容严重重复且互相矛盾。比如客服规范里说退货要“原包装完整”仓库手册里写的是“外包装无明显破损即可”。这类信息人眼都容易看岔更别说程序了。新员工培训期很长很大程度上就是因为“真正的规矩”不在文档里都在老同事脑子里。这第二套体系最大的问题不是“没有数据”而是“数据太乱”。结构化的库存数据在一个系统里非结构化的文档知识又在另一个地方两套体系长期割裂。过去有人问“某型号库存够不够、能不能发”客服需要先去查库存系统再回来翻文档最后靠经验判断。流程又慢又容易出错。1.3 为什么不能推倒重来方案讨论时有人提过干脆把两套系统全部替换掉重新上一套现代化系统。但被我否了。原因不复杂老库存系统承载的业务流程非常具体所有上下游系统早就按它的接口做了对接贸然替换涉及大量旧数据迁移、接口重新适配、人员重新培训成本极高而且业务部门能接受的上线时间窗口非常短。知识文档也同理里面的内容虽然乱但覆盖了几年来的真实问题是宝贵的业务积累。如果推倒重来这些积累就丢了。与其推翻不如在不动原有体系的前提下加一层新能力让旧系统继续跑同时让 AI 能“看懂”它们、调用它们。所以最后定了方向给两套传统体系外面包一层大模型接口不碰老系统内部逻辑只做连接和翻译。这也是标题里“装进 AI”的真正含义。2. 选型思路为什么最后定了大模型当“总调度”2.1 我也试过RPA 脚本加硬编码接口一开始我看过市面上挺常见的套路用 RPA 模拟人在老系统界面里的点击配合一些固定脚本把数据从一个系统搬到另一个系统。这种方式对简单场景确实有效比如每天定时把库存表同步到某个报表里。但真做下来就会发现RPA 处理的是“固定流程”只要老系统界面按钮挪个位置或者弹窗文案变一下脚本就崩。库存系统虽然没有大改版但时不时会有一些小升级每次升级我们都要排查一堆脚本问题维护成本非常高。而且 RPA 只能模拟操作界面无法理解用户问的到底是库存量还是库位更不能在多个系统之间做动态判断。2.2 我也试过上中间件做企业服务总线另一个被提到的方案是引入中间件把两套系统的接口统一注册到一个服务总线上通过配置流程把它们串起来。这个思路在企业集成领域很成熟适合系统接口规范、流程明确的场景。问题是我们面对的旧库存系统根本谈不上“接口规范”很多交互要靠数据库视图去补客服知识库更是连正式 API 都没有。把这类系统强行往中间件上靠需要先写大量适配代码等于给每个旧系统再造一套服务层工作量不亚于重构。而且中间件的配置和部署都比较重一个小团队很难在短周期内撑起来。2.3 大模型做“翻译官”和“调度器”的逻辑后来我换了个角度想既然问题核心是“两套系统各自为政、交互方式不同”那能不能让一个更聪明的层来做翻译大模型具备理解自然语言、识别意图、生成结构化输出、调用外部工具的能力正好适合当这个“翻译官”。具体来说我不需要大模型去理解库存系统底层怎么存储只需要给它定义好“能调用的工具清单”它就能根据用户的问题自动选择工具、生成参数、发起调用。对客服知识库大模型可以结合检索技术从文档里抽取答案再叠加库存系统的鲜活数据给出一个综合回复。这个方案的选型逻辑没有那么玄乎核心就一句话让擅长理解的人大模型去协调几个不善表达的老系统而不是逼老系统学会新规矩。相比之下这种方式既有灵活性又不用动老系统的根基。3. 落地实操把两套老系统“接”进 AI 的四步走3.1 第一步给老系统清点“家底”列工具清单任何集成工作第一步永远是盘点。我把库存系统的数据库表、存储过程、接口文档全部过了一遍列出一份“老系统能力清单”。清单很细包括接口名、入参出参、能做什么、有什么限制。比如“查询库存余额”这个工具入参是 SKU 编码和仓库编码返回库存数量、预留数量、可用数量。知识库这边我把所有文档做了归类分成客服话术、商品知识、仓储规则、退换货策略几类。然后给每类文档做清洗——去重、纠错、统一格式。这里注意清洗不是改写业务内容而是把明显冲突和无效信息处理掉为后面做检索做准备。盘点完我生成了工具清单一览表。这个表非常重要后面大模型的调度能力全靠它来驱动。工具编号所属体系工具名入参出参T01库存系统查询实时库存SKU、仓库编码总库存、可用库存、预留库存T02库存系统查询流转记录SKU、起止时间入库单、出库单明细T03库存系统查询采购在途SKU采购单号、预计到货时间T04知识库检索相关文档问题描述文档片段、关联来源T05知识库查询退换货政策品类、时间政策文本摘要3.2 第二步用 Function Calling 定义模型的“手”工具清单出来后下一步就是让大模型知道这些工具存在。现在主流的大模型都支持函数调用机制原理非常简单给模型一份工具描述它遇到相应问题时会输出一个结构化的调用指令而不是自己拍脑袋回答。以库存系统为例我定义了一个查询库存的工具描述。关键部分如下{ name: query_inventory_balance, description: 根据SKU和仓库编码查询实时库存余额, parameters: { type: object, properties: { sku: { type: string, description: 商品编号例如 SKU-10023 }, warehouse: { type: string, description: 仓库编码例如 WH-01 } }, required: [sku, warehouse] } }这里有个细节值得说描述字段写得越清楚模型调用准确率越高。比如“仓库编码”如果不注明格式模型可能把中文仓库名直接填进去导致下游报错。所以定义工具时把格式、边界条件写在里面是减少后期脏数据的核心手段。对知识库系统我没有走函数调用而是用了另一种方式。先把文档切块并向量化建了一个小规模的检索库。用户提问时先做一次向量检索把相关片段拉出来再拼接进提示词让大模型基于这些片段回答。这种做法就是常说的 RAG检索增强生成。实际上它也是一种“工具”只不过工具的返回内容是文档片段。3.3 第三步写一个联接层藏住老系统的脾气工具定义好了还不能直接让用户请求去碰老系统。我在中间加了一个轻量的联接服务专门负责两件事一是接收大模型的调用指令转成老系统能识别的请求二是把老系统的原始返回转成大模型能理解的规范结构。这个联接层我用的是一个简单的后端服务里面封装了各系统的客户端。比如查询库存时大模型给出了 sku 和 warehouse联接层负责去调老库存系统暴露的接口把结果转成 JSON 返回。老系统返回慢、偶尔超时这些异常也都在联接层处理不会赤裸裸抛给用户。加这一层还有一个好处权限审计变得简单。所有请求都经过联接层谁在什么时间问了什么、调用了什么工具都可以记录。老系统不知道大模型的存在也不需要为它改造这就大大降低了项目风险。3.4 第四步接入 RAG把文档知识也变成可查询的内容第四步是把前面讲的检索能力真正嵌入对话流程。我设计了一个简单但有效的流程用户提问题先由调度模块判断问题适合调用工具还是检索文档还是两者都做。比如“XX 型号库存还有多少现在能退货吗”这个问题的答案既需要实时库存数据也需要退换货政策。系统就会同时触发库存查询工具和文档检索然后把两部分结果一起交给大模型组织语言。为了不让检索结果过于死板我把知识文档做了二次整理重要政策按“场景-条件-结论”重写比如“退货条件商品需未使用配件齐全签收后 7 天内可申请”。这种结构化文本的检索效果比把大段原文切块再检索要好很多因为答案更聚焦大模型生成时不容易被无关信息带偏。4. 关键细节模型不乱说话、旧系统不崩盘的兜底设计4.1 提示词里放“系统手册”而不是命令堆砌很多人以为让大模型调用工具就是把工具堆在提示词里就行。实际不是。我更推荐在提示词里维护一份“系统手册”明确告诉模型三件事我是谁、我能调用什么、我绝不能做什么。下面是当时系统提示词的压缩版示例你是一个企业智能助手负责处理与库存和客服知识相关的问题。 你可以调用外部工具获取实时库存和流转记录也可以参考知识库文档片段回答规则类问题。 规则 - 如果用户要求查询库存必须先调用查询工具不要根据猜测回答。 - 如果文档片段与实时数据冲突优先以实时数据为准。 - 如果工具返回错误或超时不要编造结果请明确告知系统暂时无法获取数据。 - 回答时使用简洁的书面语不要编造不存在的单据编号。这套提示词的精髓不是让模型更“聪明”而是给它设边界。边界越清楚越不会出现模型自己编一个库存数来糊弄人的情况。我在实际测试中发现加上这几条规则后幻觉概率大幅下降。4.2 返回结果用 JSON Schema 和枚举控制模型输出不稳定是常见问题。比如它回答“可用库存是 120 件”可以是自然语言也可以是一段话里带着表格。为了让下游稳定解析我规定了统一输出格式所有答案必须包含两个字段——summary给用户看的摘要和data结构化数据。我还做了更严格的约束像“库存状态”这类字段我直接在提示词里限定只能是可用、预警、缺货三个枚举值不允许模型自由发挥。类似地单据编码必须匹配指定正则格式。有了这些约束即使模型上下文有歧义最终生成的结构也能被程序安全消费。4.3 超时重试和降级策略老系统的接口稳定性一般高峰时段经常要等好几秒。我的联接层做了三层兜底第一层接口超时时间设为 5 秒超过就返回超时标记第二层对可重试的查询做一次重试最多重试两次第三层如果重试仍失败就降级为只返回知识库检索结果并在回复里注明“实时库存暂不可用已为您展示参考信息”。这套降级策略非常实用。因为用户问的问题往往是可以容忍部分信息的——比如“能不能退货”即使库存查不到只要政策信息够也能给出基本答复。不要追求所有问题都必须完成全部工具调用让系统在部分失败时仍能优雅应对才是生产环境该有的状态。5. 踩坑记录与排查速查表5.1 坑一老系统接口对输入格式极挑剔第一次联调时我发现库存接口返回空结果。排查了半天原因是日期格式老系统只接受“yyyy年MM月dd日”这种格式而我的联接层默认传的是“yyyy-MM-dd”。这种问题用大模型根本没法发现只能在联接层里做统一的格式转换把老系统的“方言”提前消化掉。教训在给大模型定义工具前先花时间把老系统所有参数的格式边界摸清楚宁可多试几次也别假设它符合常识。5.2 坑二大模型一本正经地编造字段测试阶段用户问“某商品在途订单到货时间”模型在没有调用采购在途查询工具的情况下直接回答“预计下周二到货”。这种错误很危险因为看起来非常可信。后面我在工具定义和提示词里都做了强化凡是涉及入库时间、库存数量的查询必须先调用对应工具且工具返回无数据时不允许推测。加了一轮自动检测逻辑程序判断答案中没有携带工具调用标记时就强制复审。这段时间消掉了绝大多数幻觉问题。5.3 坑三把整个手册塞给模型反而更傻最开始做知识库检索时我图省事把整个客服手册一次性拼进提示词里。结果模型回答时抓不住重点经常把很久之前的前提条件也引用出来答得又长又偏。后来改成“先检索再拼接”只把和当前问题最相关的 3 到 5 个片段传给模型回答质量立刻上来。这说明给模型的信息不是越多越好给对了才有效。这就是 RAG 的真正价值——它不是在炫技而是帮模型筛掉噪音。5.4 排查速查表问题常见信号原因对策接口返回为空日志显示请求成功但无数据日期格式、编码格式不匹配在联接层统一转换格式模型编造库存数用户询问实时库存模型直接回答工具调用缺失强制要求先调用工具回答过长且偏离用户问简单问题回复很冗长提示词塞入过多无关信息改用检索增强方式老系统响应超时用户等待过久老系统性能不足超时重试、降级策略文档答案冲突不同片段说法不一致原始文档本身矛盾清洗阶段统一口径这套系统上线后我给它起名叫“智能中转站”实际用下来最大的价值不在于某个单点能力而在于把两套老体系的“语言”统一了。旧系统继续跑它的流程大模型在中间当一个靠谱的调度员用户只面对一个对话入口不用再关心背后是哪个系统。最后再分享一个心得。这种集成项目技术难度不是最大的最难的是跟旧系统“和解”——你得接受它的格式怪、文档少、规则乱然后用一层巧妙的适配代码把这些问题藏起来。大模型的确让这件事容易了非常多但前提是你得先把它需要遵循的边界定义清楚。边界清楚了模型才不会乱来。希望我的这些踩坑经历能给你省点时间下次真遇到类似项目顺着这套思路走基本能绕开大多数暗坑。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →