☰
AI工程实战:从零搭建可靠、可迭代的AI应用系统
2026/10/1 18:20:58 网站建设 项目流程

去年年初,我接了一个内部工具优化的需求,一开始以为只是换个模型、调个参数,结果整整折腾了快两个月。那段时间让我彻底意识到:AI项目里真正难的从来不是模型本身,而是把模型放进一个可靠、可维护、可迭代的工程体系里。这也是我写这篇“ai-engineering-from-scratch”的初衷——把从零开始摸爬滚打总结出的路线、方法和坑整理出来,给准备入坑AI工程、或者正被“模型效果不错但上线总出问题”折磨的同行,一份能直接参考的实战清单。

这篇文章不聊晦涩的数学推导,也不堆概念,而是围绕一个真实的端到端AI项目,逐步拆解工程落地需要做哪些事、为什么要这么做、会遇到什么典型问题。适合三类人:一类是刚接触AI,想做点真实项目的开发者;一类是已经在调模型,但不知道怎么把能力稳定上线维护的算法工程师;还有一类是做测试、运维,想了解AI工程工作流该怎么设计的同学。

1. 从零起步:AI工程到底是什么,我靠什么把它跑通

1.1 算法、建模和AI工程,分工到底差在哪

很多新手会把“AI工程”和“算法建模”混为一谈,但它们其实是两件事。算法建模关注的是:给定数据和任务,怎么训练或选用一个效果达标的模型,核心是模型结构、损失函数、训练参数这些。而AI工程关注的是:这个模型怎么稳定地进入业务流程,怎么被人调用、被人监控、被人迭代,核心是系统架构、数据流、评估闭环、部署运维。

举个例子,训练一个文本分类模型,准确率95%,这在建模视角看是成功的。但从工程视角看,剩下的5%错误落到线上会产生什么后果?输入格式变了怎么办?模型服务挂了怎么降级?用户反馈怎么回流成新的训练数据?这些问题才是AI工程要解决的。

我自己第一次做AI项目时,就是只盯着准确率,模型测试集分数很好看,一上线就频繁出问题:用户换了一种问法,答案就偏了;请求一多,服务就超时;没有日志,出了问题完全不知道模型看到了什么输入、输出了什么结果。那段时间的体验就是:模型一切正常,但系统一直在报错。所以后来我重新整理思路,把“从零开始做AI工程”的路线定为:数据、模型、评估、部署,四个环节缺一不可。

1.2 从零到上线:一个AI功能要经历哪些环节

一个AI功能从想法到真正可用,大体要经过七个环节:需求定义、数据准备、方案选型、模型实现或微调、评估验证、服务化部署、监控迭代。

需求定义是最容易被跳过的,但也是最关键的。你要先搞清楚用户到底想问什么、容忍什么、紧急程度如何。比如做一个售后服务问答机器人,用户的真实目标是“快速解决问题”,而不是“回答得多有文采”。所以产品形态、允许的错误率、响应时间、成本上限,都要在需求阶段定清楚。

数据准备则决定了AI能力的上限。模型再强,没有贴合业务场景的数据,效果一样上不去。这里不只是“量够不够”,还要看覆盖度、噪声比例、标注一致性。方案选型则是“用大模型API还是开源模型微调”,需要综合效果、成本、数据安全、并发能力几个维度来判断。后面我会用实际案例展开讲。

1.3 我推荐的六个月学习路线

如果你是纯新手,建议不要一上来就啃深度学习框架,而是按“能跑通一个最小闭环”的思路走。我给身边同事推荐过一条路线,大致是这样:

  • 第一个月:补Python和数据处理基础,重点掌握pandas、requests、json处理,能独立完成数据清洗。
  • 第二个月:学习调用大模型API,理解Prompt的基本写法,学会用LangChain或类似工具做简单管线。
  • 第三个月:挑一个小场景(比如简历筛选、工单分类),完整做一遍数据准备、Prompt开发、效果评估。
  • 第四个月:学习FastAPI部署和服务化,把写好的推理逻辑封装成接口,用Docker跑起来。
  • 第五个月:加入RAG(检索增强生成)和Agent的概念,做一个带知识库的问答系统。
  • 第六个月:回头优化评估闭环,给项目加上自动化回归测试和监控日志。

这条路线不一定适合所有人,但核心思路是对的:先跑通一个端到端的窄业务,再逐步扩展深度。不要在第一步就陷在“我要不要学Transformer源码”里出不来。

2. 核心技能拆解:不敢说精通,但这四块绕不开

2.1 Python与数据处理:AI工程的地基

AI工程里几乎所有环节都绕不开数据处理。我见过不少同学,模型知识很扎实,但一遇到真实数据就手足无措,原因就是数据处理基本功没打牢。

具体来说,需要掌握的核心操作包括:读取csv、excel、json等各种格式;用pandas做去重、填充、筛选;对文本做基本的清洗,比如去除多余空格、统一大小写、处理乱码;把原始数据组装成适合模型输入的格式。

这里有一个很容易踩的坑:清洗规则不要拍脑袋定,要基于数据分布。比如你去重的时候发现重复率高达30%,不要直接全删,而是先查一下是否真有这么多重复,还是因为抓取逻辑有问题。我做过一个工单分类项目,最初清洗时把所有空格删掉,结果“客户经理”和“客户经 理”这两种写法全被合并了,反而破坏了原有文本结构。后来改成只去除多余空格,保留单空格分词。

我的建议是,所有数据处理步骤都用脚本记录,别在Excel里手动改完就继续。因为AI项目强调可复现,数据清洗逻辑也是要版本化的。这行代码注释清楚,下次换一批数据还能跑,团队协作时不至于靠“我记得当时我手改过”这种方式沟通。

2.2 模型调用与Prompt工程:把大模型用明白

现在很多AI工程都是在大模型API之上做应用,所以Prompt工程成了基本能力。我个人的理解是,Prompt工程本质上是“用一套更精确的语言约束模型行为”。

核心要素有三个:角色设定、任务描述、输入输出格式。角色设定让模型知道它该用什么身份思考,比如“你是售后服务专员,请用温和、简洁的口吻回复客户”。任务描述要清楚说明要做什么,最好包含边界条件,“如果信息不足,请不要猜测,直接说明需要补充的信息”。输入输出格式则要约定结构,比如“输出JSON,包含answer和confidence两个字段”。

还有一个容易被忽视的点:给模型“示例”。Few-shot示例比单纯描述规则更有效。比如你要模型抽取工单里的原因类别,与其写一大段规则,不如给3到5条“输入-输出”对照样例,模型会照猫画虎。

但Prompt工程也不是万能的。我试过很多次,靠反复改Prompt也无法消除某些错误,这时候就该考虑换方案,比如加上检索、加验证规则,或者微调小模型。所以“Prompt不稳定”不一定是你写得不努力,而是工程方案本身到了需要升级的时候。

2.3 评估与回归测试:AI项目的安全网

这是AI工程里最容易被砍掉,但最不该被砍掉的部分。纯传统软件开发里有单元测试、集成测试,AI项目也需要对应的评估机制。没有评估,你无法回答两件最基本的事:这次改动是变好了还是变坏了?能上线吗?

评估要分层:第一层是面向效果的指标,比如准确率、召回率、F1,或者回答任务里的人工打分;第二层是面向服务的指标,比如响应时间、超时率、失败率;第三层是面向业务的指标,比如用户问题解决率、转人工率。

回归测试的核心思路是维护一个“黄金评测集”。这个评测集里的样本要覆盖典型场景、边界情况、易错情况。每次修改Prompt或模型版本,都拿这份评测集跑一遍,对比结果。我习惯给每个样本标注预期答案,然后写一个自动对比脚本,输出通过率。

这里有一个很实用的经验:评测集规模不用太大,100到200条覆盖好场景就够。关键是样本质量要高,要能代表线上真实流量。千万不能用训练数据当评测集,否则结果虚高,线上立刻现原形。

2.4 部署与监控:让模型真正服务用户

模型只有被用户调用,才算产生价值。部署这一块,我推荐从FastAPI加Docker的组合入手,简单直接,社区资料多。

部署时最关心四件事:接口设计、并发控制、缓存、日志。接口设计尽量做到输入输出结构明确,不要直接把原始Prompt暴露给外部调用方,可以在服务层做隔离。并发控制尤其要注意,大模型推理往往比普通接口慢很多,如果不加队列和超时保护,一旦流量上来,服务会快速打崩。日志是监控的基础,至少要记录每次请求的输入、输出、耗时、模型版本、Prompt版本,这样线上出问题才能回溯。

监控层面,可以先从三个指标做起:请求量、平均耗时、错误率。如果使用了付费API,还要单独统计token消耗。刚开始不用上特别复杂的监控系统,记好日志、定期汇总就行。别一上来就搭Prometheus、Grafana全家桶,系统复杂了反而管不住。

3. 实操回放:我如何从零做出一个FAQ智能问答机器人

3.1 需求定义与方案选型,别急着选模型

这次项目背景很普通:公司内部有一个运维知识库,几百篇文档分散在wiki里,员工遇到问题习惯在群里问,但没人及时回答。需求就是做一个内部FAQ问答机器人,能根据知识库内容回答问题,回答不了就给出相关文档链接。

需求定下来后,我先做方案选型。候选方案有两个:微调一个小模型,让它记住知识库内容;或者用检索增强生成(RAG),先检索文档再让大模型总结回答。我最终选了RAG,原因有三个:

第一,知识库文档会持续更新,RAG不需要因为新增一篇文档就重新训练模型,只要把新文档切块入库就行;第二,RAG的回答可以附上来源,用户更信任,出问题时也方便追责;第三,微调的成本和时间投入更大,在内部工具阶段性价比不高。

这个选型逻辑在大多数企业内部知识问答场景都适用。除非文档高度机密、不能出内网,或者模型回答风格需要极其定制,否则RAG是更稳的起点。

3.2 数据清洗与知识库构建,做了三件关键事

原始数据是wiki导出的html和一堆pdf,处理起来并不干净。我先统一转成纯文本,然后用正则处理残留的HTML标签和乱码。这一步看起来很基础,但做了之后发现至少10%的文档内容原本是格式错乱的,不处理的话,检索时会出现大量无意义字符。

接下来是文档切块。这是RAG效果好坏的关键环节。我的做法是先把每篇文档按章节标题切成大块,再对超过长度限制的块做二次切分。这里有一个需要注意的参数:chunk_size(块大小)和overlap(重叠长度)。我试过几种组合,最后用的是chunk_size=512,overlap=64,按字符数计算。块太大,检索时容易混入无关内容;块太小,语义不完整,模型读起来费劲。

切完块之后,我用嵌入模型给每块文本生成向量,存入向量数据库。这一步我用的是常见的embedding模型,维度是1024。入库前还做了一道过滤:把纯表格、纯图片、空文本删掉。表格内容如果直接转成文本效果很差,我后续专门写了一个表格转Markdown的逻辑,再纳入知识库。

做完这些,知识库大概有1400多个块。数量不算大,但对内部FAQ来说,覆盖面已经基本够了。而且这个流程是脚本化的,以后wiki有更新,重新跑一遍就能同步。

3.3 Prompt模板与检索增强生成(RAG)实现,核心代码拆解

RAG的推理流程可以拆成四步:接收用户问题、向量检索、拼装Prompt、返回答案。我写了一个简化的Python示例,便于理解整个链路:

def rag_answer(question): # 1. 生成问题向量 q_embedding = embedding_model.encode(question) # 2. 从向量数据库检索最相关的top_k块 docs = vector_db.search(q_embedding, top_k=5) # 3. 拼装Prompt context = "\n\n".join([d["text"] for d in docs]) prompt_template = """ 你是一个企业内部运维助手。请根据下面提供的文档内容,回答用户问题。 要求:回答要简洁,不超过200字;如果文档中没有明确依据,请直接说明“知识库中未找到相关信息”,并建议用户联系运维组;不要编造文档中没有的内容。 【文档内容】 {context} 【用户问题】 {question} """ prompt = prompt_template.format(context=context, question=question) # 4. 调用大模型,返回结果 response = llm_call(prompt) return response, docs

这段代码虽然简单,但有几个细节值得展开说。

第一,top_k的选择直接影响答案质量。我最初设成3,结果经常漏掉关键信息;调到5之后好了一些,但调成8后发现模型会把多个不相关段落混在一起,开始编造连接性内容。最后停在5,算是一个平衡点。

第二,Prompt里明确写了“不要编造文档中没有的内容”。这句听起来像废话,但不写的话,大模型在信息不足时会脑补,而且脑补出来的答案还特别像回事。加了这句之后,回答“未知”的情况明显变多,虽然牺牲了一点回答率,但换来的是可信度大幅提升。

第三,我用了一个简单的“引用来源”机制:在返回结果时,把检索到的文档标题一并返回,没有用复杂的引用溯源算法,只是在接口里多加一个source字段。用户点开来源文档,就能自己确认回答是否靠谱。这种小设计对内部工具来说非常加分。

3.4 评估集设计与自动化回归,让每次改动都有底

做完第一版,我没有急着上线,而是先建了一个评估集。我找了100条常见问题,覆盖了网络配置、账号权限、软件安装、报销流程、会议室预约几大类。每一条都人工写好预期要点,然后写一个脚本自动调用RAG服务,把回答和预期做对比。

对比方式不追求完全一致,而是做了两层判断:第一层,回答里是否包含预期中2到3个核心关键词;第二层,是否出现“知识库中未找到”这类兜底描述——如果该答却没答,就是漏答。

这个评估集的用途在后续迭代中体现得非常明显。有一次我调整了切块参数,期望提升检索准确率,但跑完回归发现整体准确率反而降了1个百分点。如果没有评估集,我根本发现不了这个回退。后来我把这套脚本放进项目的CI流程里,每次代码合并前自动跑一遍,相当于给AI项目上了一个保险丝。

做这个踩过一个大坑:评估样本里英文关键词大小写不一致,导致自动对比失败。后来我统一在对比前做小写化处理。这看起来是小事,但提醒我评估逻辑本身也需要被测试。

3.5 用FastAPI和Docker把服务跑起来,顺便解决并发问题

服务化我用FastAPI实现,结构很简单:一个/ask接口接收问题,内部调用RAG逻辑,返回答案和来源文档;一个/health接口做健康检查。

from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class AskRequest(BaseModel): question: str class AskResponse(BaseModel): answer: str sources: list[str] @app.post("/ask", response_model=AskResponse) def ask(req: AskRequest): answer, docs = rag_answer(req.question) return AskResponse(answer=answer, sources=[d["title"] for d in docs])

部署时用Docker镜像,里面装好Python依赖和向量数据库客户端。这里要注意的是,不要把模型文件和向量数据打进同一个镜像里。因为向量数据更新频繁,而模型权重几乎不变,分开管理能大幅减少镜像构建时间。我是把向量数据放在一个共享存储路径,容器启动时挂载进去。

并发问题也同样重要。大模型API的响应时间经常在1到3秒,如果接口不加限制,别人用脚本连续打就会占满所有上游配额。我加了一个简单的信号量控制并发数,设置为5,超过的信号直接返回429提示稍后重试。同时给每个请求设置了超时时间15秒,防止模型API卡住时拖垮整个服务。

上线后我在日志里加了三行:请求文本摘要、响应摘要、耗时毫秒数。别看就这么点信息,后来排查问题全靠它们。有一次某用户连续问同一个问题,响应时间从2秒变成15秒,通过日志发现是向量数据库连接池被耗尽,连接没有正确释放。定位到问题后,我在向量数据库初始化逻辑里加了一个连接复用机制,耗时立刻恢复正常。

4. 工程进阶:从单点调用到Agent协作工作流

4.1 为什么要从单次调用走向多个环节编排

FAQ问答机器人跑通之后,你会发现用户的需求远比“问一答一”复杂。比如有的用户会问:“我想报销差旅费,但不知道发票丢了怎么办?顺便告诉我流程大概需要多久。”这个问题包含了好几个意图:报销流程、发票丢失处理、处理时限。单次检索加Prompt很难同时覆盖三个意图。

这种场景就需要把模型调用编排成一个工作流。业界常说的Agent,本质就是把一个大任务拆成几步,每一步交给合适的模型或工具去执行,最后汇总结果。这不玄乎,就像你处理复杂问题时先查资料、再问同事、最后写邮件一样,Agent只是把整个过程自动化。

从工程角度看,工作流编排带来的好处非常实际:每个节点可以单独测试、单独替换、单独打日志。如果某个环节效果不好,可以只优化那部分,不用推倒重来。

4.2 一个可落地的Agent工作流demo

我基于FAQ机器人做了一个升级版:当用户问题包含多个意图时,先做意图识别,再分别检索,最后汇总回答。整个过程我直接用Python脚本编排,没有引入重量级框架,因为内部工具不需要特别复杂的Agent能力。

简单示意如下:

def agent_flow(question): intents = intent_classifier(question) # ["报销流程", "发票丢失"] sub_answers = [] for intent in intents: docs = search_by_intent(intent, question) sub_answer = generate_answer(intent, docs) sub_answers.append(sub_answer) final_answer = merge_answers(sub_answers) return final_answer

这个流程里有几个关键点。第一,意图识别本身也是一个模型调用,但它只接收一个分类任务,输入输出简单,效果稳定,不会漏掉子问题。第二,每个子意图的检索范围可以收窄。比如意图是“报销流程”时,只检索报销类文档,减少噪声。第三,汇总回答的Prompt要求模型不要重复相同内容,而是把不同子答案按顺序组织成一段通顺的文字。

实测下来,这种“先拆后答”的方式,比单次调用效果提升明显。我专门拿20条多意图问题做过测试,单次调用能完整回答的只有6条,换成Agent工作流后提升到了15条。虽然多花了几次API调用,但在正确率面前,这点成本是值得的。

4.3 多模型协作与质量问题兜底

在做Agent工作流时,我还尝试过让两个不同的模型互相校验:一个模型负责生成答案,另一个模型负责检查答案是否与知识库内容矛盾。这个思路有点像让同事帮你复核一遍文档。

具体做法是,在生成答案后,将答案和检索到的Top5文档片段一起送给“校验模型”,让它判断答案是否有出处、是否与文档矛盾。如果校验不通过,就把答案标记为“低置信度”,在对话里主动提醒用户“答案可能不够准确,建议人工确认”。

这个兜底机制特别好用。因为大模型有时候会一本正经地输出错误信息,单纯靠Prompt约束很难根治。引入第二道校验后,明显减少了“看起来正确但实际内容错误”的输出。

不过多模型协作也有代价:响应时间变长,成本变高。所以我没有让所有请求都走校验,而是只对置信度较低的问题做二次校验。置信度怎么来的?我让生成模型在返回答案的同时,输出一个self_confidence字段,低于阈值就走校验逻辑。这样既控制了成本,又保住了效果。

5. 我在实际操作中踩过的坑:常见问题与排查实录

5.1 Prompt结果飘忽不定,怎么定位

这是我遇到最多的问题。同一套Prompt,上午测试效果很好,下午再跑就变了一个风格。很多人第一反应是“模型抽风了”,其实背后往往有更具体的原因。

我自己的排查顺序是:先确认输入是否变了,再确认模型版本是否变了,然后确认温度参数是否合理,最后再怀疑Prompt本身。有一次我发现回答突然变长了很多,追查下来,原来是上游同事在传参时把temperature从0.1改成了0.7,参数覆盖了默认配置。这类问题在工程里非常常见,模型本身没变,是调用方引入了不确定性。

应对Prompt不稳定,我积累了两个策略。第一,把temperature等参数固定,设置为默认值,并在代码里写死,不要暴露成可配置项。需要调整时走代码评审流程,而不是线上随便改。第二,把Prompt做成版本敏感,日志里记录使用的Prompt版本号,一旦效果异常,能快速定位是哪一版Prompt引入的问题。

5.2 成本失控的几种典型情况

AI项目的成本大头是模型API调用费。我最开始没在意,直到一个月末收到账单,发现费用是预期的3倍。复盘后找到了几个原因:

第一,重试机制写得太激进。模型接口偶尔超时,我加了自动重试3次,结果高峰期大量请求都重试了,费用翻倍。后来我改成只对连接错误重试,对超时不重试,改为返回降级结果。第二,日志里存了大量答案文本,虽然费用不是这里产生的,但数据存储成本涨了。我改成只存长度和摘要。第三,最隐蔽的是长文档重复被切分进多个上下文。RAG检索时,同一个文档的不同片段可能同时被选中,导致上下文里出现大量重复内容,token消耗剧增。我在检索后加了一个去重逻辑,根据来源文档ID过滤重复片段,成本立刻降了15%。

成本控制不是上线后才做的,而是一开始就要埋点统计。我给每个请求记录了token使用量,按天汇总,这样费用异常能及时发现,而不是等月底账单来“惊喜”。

5.3 数据质量引发的“模型错觉”案例

有一次,用户集中反馈某类问题的答案“经常是错的”。我查日志发现,这类问题的知识库文档本身就有冲突:同一份流程,两篇文档给出了不同的截止时间。模型把两个来源都放进了上下文,生成答案时做了错误的时间取舍。

这个案例让我深刻明白一件事:AI工程的前置条件是知识库本身要干净。模型不是数据库,它没有能力判断两篇文档谁的优先级更高。你需要先通过数据治理解决冲突,或者至少在Prompt里明确“当文档内容冲突时,请直接说明存在两种说法,不要自动选一个”。

我后来做了一件事:在知识库里增加了一个字段doc_priority,检索时按优先级排序,冲突时以高优先级文档为准。这个修复比调整模型快多了,也稳多了。所以遇到“模型总说错”的反馈,先别盯着模型看,去翻一下喂给它的资料是不是有问题。

5.4 部署环境里那些想不到的坑

部署阶段我也碰到不少问题。最经典的是Python包版本不兼容。本地跑得好好的,Docker里一启动就报错,排查发现是C++编译器版本不同导致某个依赖装不上。后来我把基础镜像固定成某个版本,并且把requirements.txt里的包全部锁到精确版本号,不再用>=范围写法,原则上是“能锁多死就锁多死”。

还有一次,向量数据库在测试环境正常,生产环境查询速度极慢。查了半天,发现生产环境的向量数据库没有创建索引。这种问题在测试环境通常不会暴露,因为数据量小,全表扫描也快。所以我在部署检查清单里加了一项:确认向量索引已创建、数据量统计正常。

这些坑单独看都很小,但在工程链条上会连环引爆。我的建议是维护一份“部署检查清单”,每次上线前逐项过一遍。这看起来不酷,但特别有效。

6. AI工程后面还可以怎么扩展,以及我的一点个人体会

6.1 把AI测试开发放进日常流程

以前提到测试,大家想到的是后端接口测试和前端UI测试,AI项目里测试的地位经常被边缘化。我在这个项目里尝到了甜头:为RAG服务建了自动评测集之后,每次改Prompt、换模型、调参数,心里都有底。所以我强烈建议做AI工程的同学,把测试开发作为标配。

具体做的时候不复杂。你可以先从“最小回归集”开始,30条高价值样本就够了,维护一个简单的对比脚本,每日跑一遍,输出通过率变化。后面再逐步加样本,加分类维度。我用的是最朴素的Python脚本加Markdown报告,连Web UI都没做,团队一样每天都在用。

6.2 过了这么久,我的真实感受是什么

从我接手第一个AI工程需求到现在,最大的体会是:AI工程没有想象中那么玄,也不需要把模型训练得多么深入才配叫AI工程师。它更像是一种综合能力,把数据处理、Prompt设计、服务开发、评估运维揉在一起,让AI能力在真实业务里站得住。

这个过程中最容易让人抓狂的,反而不是模型效果,而是那些“看不到的工程债”:数据不干净、Prompt不版本化、评估缺失、日志没有、部署不可复现。每一样都像一根针,扎在项目生命周期的某个阶段。如果你正在从零开始做AI工程,我的建议很简单:先把能自动化的环节都自动化,把评估和日志当成一等公民,把每一次改动都记录在案。慢一点没关系,稳了自然就快了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询