拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

AI工程化实战:从零搭建文档问答系统的完整路径

AI工程化实战:从零搭建文档问答系统的完整路径

不开源的话,光“怎么把模型塞进自己的服务里”就是一个大坑;开了源,部署、微调、数据管线的活又是一套完全不同的技能树。我身边不少人是在这一步被劝退的,要么被“AI”两个字吓住,要么被铺天盖地的教程带偏,跑了个demo就以为懂工程了,真上线才发现连日志都不知道怎么查。所以这次我干脆以自己最近从零搭建的一套文档问答系统为线索,把AI工程化的完整路径拆开揉碎讲一遍——从数据准备、模型选型、微调决策,到部署监控、成本优化、故障排查。这套流程不依赖某一家云厂商,也不绑定某个特定的模型,你在自己的电脑上、自己的服务器上,都能照着走一遍。

1. 决定做AI工程化之前,先想清楚“工程化”和“写脚本”的分界线在哪里

1.1 我接到的第一个AI项目的真实起点

事情要从一个很普通的业务需求说起:公司内部有大量产品文档、技术手册和客服问答记录,散落在不同的wiki和共享盘里,每次找答案都要翻半天。老板的想法很简单——“搞个AI问答机器人呗,把文档喂进去,让它自己回答。”听起来像是个周末就能搞定的小项目,但真正开始动手我才发现,这压根不是一个“训练模型”的问题,而是一个系统性的工程问题。

最直接的冲击来自数据:几千篇文档格式五花八门,有PDF、有Word、有Markdown,还有不少扫描件。每份文档的排版、层级、术语都不同,有的甚至带页眉页脚和表格。我原以为“喂给AI”是个简单动作,实际上你要先解决“怎么把文档变成模型能理解的干净文本”这件事。等到数据清洗完,又一个问题冒出来了:模型到底该用哪个?用商用API还是开源模型?要不要微调?向量检索该怎么做?回答质量怎么评估?上线后用户多了怎么办?这些问题没有一个能在写脚本的阶段想到,但它们恰恰是“工程化”的真正含义。

1.2 工程化的核心元器件拆解:数据层、训练层、部署层、监控层

如果让我用一个类比来说明AI工程化和普通脚本的区别,我会说:写脚本像是做一个手工零件,虽然能用,但只能解决当下的一个问题;工程化则是搭一条流水线,要考虑原料供应、加工流程、质检标准、故障检修,还要算生产效率。对AI系统来说,这条流水线至少包含四个核心层,缺一不可。

第一层是数据层,负责原料的采集、清洗、切分和版本管理。没有这一层,后面的一切都是空中楼阁。第二层是训练层(或者更广义地说,模型层),包含模型选型、微调、评测,你要搞清楚“现成的模型够不够用”“要不要为特定领域再训练一步”。第三层是部署层,涉及推理服务、接口封装、资源调度和并发控制,它决定系统能不能在真实流量下稳定跑起来。第四层是监控层,做的是日志收集、质量评估、效果回归和告警,没有它,你就像一个蒙着眼睛开车的人。

我当时犯的一个典型错误,就是一开始把注意力全放在第二层,天天琢磨“该用哪个模型”,结果数据没整理、评测没设计,等到模型接进来才发现连个客观标准来判断好坏都没有。这是新手最容易踩的坑——你以为是模型不够强,其实是工程链路上的其他环节在拖后腿。

2. 从零搭建的第一关:数据收集、清洗与验证,远比模型选型更耗时

2.1 数据从哪来:冷启动阶段的三种来源和取舍

对于一套从零开始的AI系统,数据收集永远是最先要面临的现实问题。我当时面对的是三种典型来源:第一是企业内部的wiki和知识库,导出后是HTML或者Markdown格式,结构相对清晰,但噪声大,夹带着导航栏、广告位和大量无关链接;第二是历史客服对话记录,以Excel和CSV为主,口语化严重,错别字多,还有各种脱敏不彻底的风险;第三是产品PDF手册,最头疼,因为它们里大量内容是表格和图片,PDF解析器稍微不给力,内容就乱成一团。

面对这三种来源,我的处理策略是分优先级:先处理wiki和Markdown类数据,因为它们质量相对高,能快速构建一个可用的初始语料库;其次处理PDF手册,但OCR和版面解析要额外投入精力;最后才处理客服对话记录,因为它们需要大量的清洗和脱敏。如果你反过来,一上来就跟最脏的数据较劲,大概率第一周就被干趴下了。我建议冷启动阶段的原则是“先让系统跑起来,再逐步喂更多数据”,别指望一次就把所有数据完美入库。

2.2 清洗脚本里的那些细节:去重、去噪、格式归一化

数据清洗是这个阶段最无聊但又最不能跳过的工作。我给你看几个我实际遇到的细节,你就明白它有多琐碎:

  • 文档去重:同一个文档在不同目录下有多个版本,内容相似但又不完全相同。我用的是MinHash近似去重,先把文本分片成n-gram集合,再算Jaccard相似度,相似度超过0.85的文档标记为重复,人工确认后丢弃旧版本。这个方案对长文档很有效,但对短文本容易误伤,所以阈值要调。
  • 格式归一化:编码统一转成UTF-8,换行符统一成\n,全角半角符号统一,标题层级统一成#式Markdown。这些看似无关紧要的差异,到了文本切分和向量化阶段都会变成隐患。比如全角逗号和半角逗号混在一起,切出来的文本块就可能带上莫名其妙的空字符。
  • 页眉页脚和导航噪声:从wiki导出的HTML里要专门写规则去掉“相关文章”“目录导航”这些区块;从PDF解析出来的内容要去掉页眉、页码和页脚的重复文本。我一开始偷懒没做这一步,结果向量检索时经常命中的是“第3页共20页”这种垃圾片段,气得我半夜爬起来加正则。

这一步给我的最大体会是:清洗脚本本身不复杂,复杂的是你必须对数据内容有足够敏感度。别急着写自动化,先抽样看50条原始数据,摸清噪声规律,再动手设计规则。

2.3 验证集怎么构建:标注一致性比想象中更关键

清洗完数据,下一步不是急着灌进向量库,而是先构建一套可以用来评估后续模型效果的“金标准”数据。我当时的方法是从各个业务部门收集了200个真实问题,每个问题由两个人分别标注标准答案和对应的参考文档片段,然后比对标注一致性。标注不一致的地方,去和业务方确认,最终形成一份带标准答案的验证集。

这个过程比想象中耗时,但价值巨大。因为后面不管你是调prompt、切文本块,还是换模型、做微调,都要靠这套验证集来量化“变好了还是变坏了”。没有验证集,你的所有优化都是凭感觉,很容易被几个典型案例误导。我后来还做了一步扩展:把验证集里的每个问题按类型打标(事实型、操作型、对比型、主观型),这样评测时能看清系统在哪类问题上表现差,从而倒推优化方向。

3. 模型选型与微调的真实决策过程:跑通demo只是万里长征第一步

3.1 选型背后要算的三笔账:性能、成本、可控性

数据备好了,终于到了选模型环节。但请注意,选模型绝不是一个单纯比“谁聪明”的过程,而是要算三笔账:性能、成本、可控性。性能包括理解能力、生成质量和检索能力;成本包括训练成本、推理成本和人力成本;可控性则包括数据隐私、本地部署可行性、以及你是否能对模型行为进行干预。

我当时对比了商用API和开源模型两大路线。商用API的优势是开箱即用、效果优秀,尤其在国内服务方对中文理解做得相当好;劣势是按量计费,高频调用时成本飙升,而且数据要出内网,过不了信息安全这关。开源模型如Qwen系列、ChatGLM系列等,优势是部署在自己服务器上,数据不出内网,没有按量计费的压力,劣势是对硬件资源和工程能力要求高。综合下来,我最终选了开源模型作为底座,因为合规和成本这两项权重在我们场景里远高于那点性能差距。

如果你面临同样的选择,我建议你把决策表拉出来,按每个维度的权重打分,而不是被单点性能吸引。表1是我当时用的简化版比较表:

决策维度商用API开源模型(本地部署)
中文理解效果优良好(取决于具体型号)
单次调用成本按量计费,长期偏高主要是硬件折旧和电费
数据隐私合规依赖服务商承诺数据完全本地,可控
二次开发自由度低,只能调接口高,可微调、可定制
工程复杂度低高,需自建服务
上线速度快较慢

3.2 微调的判断标准:什么时候该微调,什么时候不该

很多教程一上来就教你微调模型,但微调绝不是默认选项。我在这个项目里一度陷入“不微调等于不专业”的焦虑中,后来做了几轮对比实验才冷静下来。判断要不要微调,我总结出三条标准:模型是否在目标领域频繁出错、领域知识是否需要内化到参数里、以及是否有足够的高质量标注数据。

以我的文档问答场景为例,我先用未微调的模型配合全文检索测试,发现它应对“标准操作流程”“故障排查”这类问题效果不错,但在“产品版本差异”“专有名词解释”上频繁出错。这说明通用能力够用,缺的是特定领域知识。此时有两个选择:一是基于检索增强(RAG)把知识塞进上下文,二是微调把知识内化进参数。RAG的优点是灵活、无需训练,缺点是回答质量依赖检索质量,且上下文长度有限;微调的优点是一劳永逸,缺点是成本高、有灾难性遗忘风险。

我最终的策略是“先RAG后微调”:先用检索增强把绝大多数问题解决掉,再针对检索也解决不了的极小部分疑难case做微调。这种分层策略的好处是省资源、见效快、风险可控。

3.3 实测对比:base模型、RAG方案、微调模型的效果差异

这里把实测数据放出来供参考。我用前面说过的200道验证题做了三类方案的对比:

  • 纯base模型:直接问,不检索。准确率只有63%,而且很多回答“一本正经地胡说八道”,因为它没有外部知识来源。
  • base模型+RAG:先检索再生成。准确率提升到86%,尤其在事实型问题上进步明显。
  • 微调模型+RAG:在检索基础上进一步微调,准确率到了91%。提升主要集中在专有名词解释和复杂指令跟随上,但V100级别的单卡训练花了两天,数据标注花了三个星期。

这个结果告诉我们:对多数业务场景,RAG带来的收益远超微调,微调更像是锦上添花。我见过不少团队一上来就微调,结果训练数据质量不行,微调后的模型反而变笨了。所以我的建议是:先用最轻量的方案把系统跑起来,用数据说话,再决定是否投入更大的训练成本。

4. 部署上线的工程细节:推理服务、评估回放与模型版本管理

4.1 推理服务三个容易忽略的细节:显存管理、动态批处理、超时重试

模型选好、效果验证通过之后,真正的工程挑战才刚开始。部署推理服务时,有三个细节最容易被忽略,我一个个说。

第一个是显存管理。很多人以为只要模型能加载进显存就算完,实际上还要考虑推理时的KV Cache和临时张量。以ChatGLM3-6B为例,FP16全精度加载权重约12GB,推理时KV Cache可能再占2-4GB,所以你至少需要24GB显存的显卡(如3090/4090)才能舒服地跑并发。我一开始用T4的16GB显存硬扛,结果一上并发就OOM,才明白要预留buffer。实践上我建议把单卡并发数控制在8左右,不要为了省成本硬压并发,显存溢出导致的服务抖动代价更大。

第二个是动态批处理。推理框架(如vLLM)支持把多个请求拼成一个batch并行计算,吞吐量能提升好几倍。但动态批处理不是免费午餐,它会牺牲单请求延迟。我在实际压测中发现,batch size从1升到16,总吞吐能提升6倍,但单次响应时间会从800ms上升到2000ms。所以你要根据业务的延迟要求反推并发上限,而不是一味追求吞吐。

第三个是超时与重试。LLM推理天然存在不确定性,同一个问题,有时2秒返回,有时要20秒。所以接口超时不能设太短,我设为30秒;同时要做客户端重试机制,但要加退避策略,不然模型卡住的时候所有请求都重试,直接把服务打挂。这些细节,不在生产环境被虐几次,很难提前想到。

4.2 没有评估回放机制,你根本不知道新模型是变好还是变坏

这是我认为整个AI工程化里最重要、但最容易被忽视的环节。所谓“评估回放”,就是把历史线上请求存下来,当模型更新或参数调整时,用同一批历史请求重新跑一遍,自动对比新旧版本的输出质量。没有这个机制,你换模型只能靠肉眼抽查,换了也不知道是变好了还是变坏了。

我实现评估回放的方式很朴素:线上每次请求的输入、输出、检索的文档片段、用户反馈都存日志;每周抽一批代表性请求组成回归集;模型版本更新时,自动跑一遍回归集,按规则评分。评分有两层:一层是机器评分,用规则检查和内置评判模型打分;另一层是人工抽验,挑出分数波动最大的case来看。

这套机制上线后,我们避开了一次严重的“升级事故”——新模型在基准测试上分数更高,但实际在特定类型问题上全面退化,靠回放及时发现并回滚了版本。从此我坚信:没有评估回放的模型迭代就是耍流氓。

4.3 模型版本管理和回滚:比代码回滚更需要设计

传统软件都有版本管理,但模型版本管理更麻烦,因为模型文件动辄几个GB,而且一个线上服务可能在同时服务多个版本。我的做法是把模型服务分为“预发”和“生产”两套,模型文件放在对象存储里,通过带版本的路径引用。更新流程是:新模型先在预发跑评估回放,通过后再切生产,切的时候用负载均衡按10%灰度引流,观察几个小时后全量。

一旦线上发现问题,回滚操作就是改一个配置指针,把流量切回到上一个版本,整个操作一分钟之内完成。这个设计让我在后续几次模型迭代中都能大胆试错,因为我知道最差也能快速回退。如果没有这套机制,你一定会在“要不要升级”这件事上变得畏手畏脚,最后反而让系统停滞在旧版本上。

5. 成本、延迟与稳定性的三角博弈:我的实测数据与调优记录

5.1 成本拆解:训练、推理、存储分别花在哪

AI系统的成本和传统服务完全不同,它不是均匀分布在每台服务器上,而是集中在三个大头:训练成本、推理成本、存储成本。训练成本是一次性的,包括GPU租用或折旧、数据标注人力、实验试错消耗;推理成本是长期的,跟着线上流量走,模型越大、并发越高,这一项越惊人;存储成本则来自向量库、日志和模型版本,增长虽然慢,但容易被忽视。

我这套文档问答系统的成本结构大致是这样:训练阶段用了一张V100(租用),加上标注人力,约一周时间,折算下来约2000元;推理阶段部署了一台双卡服务器,电费加折旧每月约1500元;存储方面,向量库和日志每月几百元。整体算下来,比商用API在中等规模调用下(每月约5000元)略低,但如果流量翻十倍,本地推理的成本优势会更明显。这也解释了为什么很多AI应用在验证阶段用API,规模化之后反而转向自部署。

5.2 延迟优化三板斧:量化、缓存、路由策略

用户对问答系统的延迟感知是很敏感的,超过3秒就会觉得“卡”。我把延迟优化归纳成三板斧,亲测都有效。

第一板斧是量化。FP16转INT8能让模型体积缩小一半,推理速度提升30%-50%,而效果损失在可接受范围内(我实测准确率下降不到2%)。如果你用的是支持AWQ或GPTQ的模型,建议直接跑量化版本,性价比极高。第二板斧是缓存。高频问题(如“密码忘了怎么办”“如何申请权限”)命中缓存后可以直接返回,这一招能把有效QPS需求砍掉40%以上。但要注意,缓存必须设置过期时间和基于语义的相似度匹配,不然用户换了种问法就命中不了。第三板斧是路由策略。简单问题走小模型或规则引擎,复杂问题才走大模型,在大模型之前加一个意图分类器,能明显降低平均响应时间。我实测三类请求全走大模型时平均延迟2600ms,路由分流后降到1100ms,体验提升非常明显。

5.3 稳定性建设:限流、熔断与降级方案

稳定性的重要程度,是在你第一次线上事故后才真正理解的。我遇到的是典型的“热点问题雪崩”:一个内部公告引发大量员工同时提问同一个问题,结果模型服务被打满,请求排队时间飙升,最后整个系统陷入死锁。事后我补了三道防线,这也是我认为AI服务必备的稳定性组合拳。

第一道是限流:在网关层按用户维度设置单机QPS上限,超出部分直接返回排队提示,而不是让请求继续往后打。第二道是熔断:当模型服务的错误率超过阈值(我设的10%)或平均延迟超过5秒时,熔断器自动打开,后续请求快速失败,不再打到模型上,给它时间恢复。第三道是降级:熔断期间,自动切换到规则引擎版本(比如从向量库直接返回相关性最高的文档摘要),保证用户至少能拿到部分信息,而不是完全不可用。这三道防线让系统在最坏情况下也能“优雅失败”,而不是全线崩溃。

6. 一次pipeline偶发返回离谱答案的根因定位:排查链路与方法

6.1 现象:特定类型问题开始频繁“答非所问”

在某次模型版本升级后,系统整体准确率没有明显变化,但“版本对比类”问题开始频繁出现离谱答案——比如用户问“V2.1和V2.0有什么区别”,系统却回答“V2.1没有这个功能”。这类case在验证集上也有,但比例不大,一开始我没太在意,直到业务方专门来投诉,才意识到问题严重了。

我起初怀疑是模型变了,因为刚好是模型升级后出现的。于是先做了评估回放,把新旧模型在同样输入下的输出拉出来对比,结果发现:同一个问题的检索结果变了,旧模型能检索到正确的文档片段,新模型却检索到另一篇完全不相关的文档。这立刻把矛头指向了检索环节,而不是生成环节。

6.2 顺着数据链路排查:检索源变更、切块策略、向量偏差

定位到检索环节后,我开始逐步排查。第一个怀疑点是索引数据源:是不是索引更新任务出了问题,导致部分新文档没被写入向量库?查了任务日志,发现索引更新正常,但文档库里的确有部分文档的内容和源文件对不上——原来是清洗脚本在处理某种特定表格格式时,把表格的行列顺序打乱了,导致语义变化。

第二个怀疑点是文本切块策略。版本对比类文档通常用表格描述差异,而我的切块策略是按Markdown标题切分,一个表格被硬切成多块,单块语义不完整,检索时就失去了关键信息。这是很多RAG系统的通病:切块不是按“语义完整”来切,而是按“结构整齐”来切。第三个怀疑点是向量检索的相似度阈值。我检查后发现,由于切块不完整,相关文档片段的向量相似度被拉低,部分相关片段被阈值过滤掉了,剩下的不相关片段反而被召回。

6.3 根因确认与修复:一个清洗规则引发的连锁反应

顺藤摸瓜,最终确认了根因链条:清洗脚本里我没料到一个“表格识别”函数在特定目录下的PDF中,会把两列内容的顺序颠倒,导致生成的产品对比信息文本里“新版本”和“旧版本”的指代被互换。这种语义翻转在单看文本时几乎察觉不出来,但一旦和检索、生成联动,系统就会一本正经地给出完全相反的答案。

修复分两步。第一步是修正清洗脚本,针对这类表格增加行列校验逻辑,同时加入一条“自检规则”:凡是解析出的文本中包含“V2.0”“V2.1”这类版本号且同时出现在同一段,自动标记为人工复核候选。第二步是调整切块逻辑,改用滑动窗口加标题分割的混合策略,让表格内容尽可能完整保留在同一个块内,避免语义被切断。修复后,版本对比类问题的检索准确率从71%回升到94%。

6.4 这次故障给我留下的排查方法论:先数据后模型,先链路后节点

回头复盘,这次故障之所以难查,是因为表象在“生成”,根源却在“数据清洗”,跨越了整条流水线的好几个环节。我事后总结出一套排查顺序,之后遇到类似问题基本都按这个思路走:先查数据层(清洗、切块、索引有没有问题),再查检索层(召回质量、排序阈值),最后才查模型层(生成有没有跑偏)。这个顺序和大多数人的直觉相反,但在我接触的案例里,绝大多数“模型变笨了”的问题,根因都在数据链路。

具体做法上,我会在排查一开始就同时拉三份日志——输入日志、检索结果日志、模型输出日志——先看检索结果是否靠谱。如果检索结果是对的但输出错的,那是生成问题。如果检索结果就是错的,那就继续往前查索引和切块。用这种“从中间切开、向两边定位”的方式,能极大缩小排查范围,而不是一头扎进模型参数里瞎调。

写在最后的一点经验

一路从零走下来,最大的感受是:做AI工程化,真正考验人的不是那点模型调参的手艺,而是你能不能把数据、模型、部署、监控、成本这些环节捏合成一个整体系统。如果你现在正准备开一个类似的项目,我建议你从第一天起就按工程化的思路来,先搭好数据管道和评估机制,再谈模型选型和效果优化——因为效果问题可以迭代解决,但骨架没搭好,后面每一步都会给你埋雷。

最后分享一个小技巧:每次对系统做任何改动,无论改prompt、换模型、调切块还是改清洗规则,都把修改前后的验证集分数记录在一个表格里,附带修改说明。这个习惯帮我避免了很多“改着改着变回去了”的尴尬局面,也让我在向团队解释决策时有了客观依据。AI工程化没有银弹,但记录和回放,就是最好的防护网。

返回列表