
记得年初接了一个让我连续失眠好几天的需求业务方拿着一个模糊的想法找到我说我们要做一个AI应用把企业内部的文档都接进来让员工直接提问就能拿到答案。听起来很简单但真正动手做的时候才发现所谓AI工程最难的部分根本不在AI本身而在AI外围那一圈看不见的工程细节。从架构设计到数据准备从评测体系到上线部署每一步都在教做人。这个项目从零开始到最终交付、稳定跑在生产环境前后大概花了两个月时间。我把整个过程完整复盘了一遍脑子里冒出来的第一个念头就是市面上讲Prompt技巧、讲模型原理的内容一抓一大把但真正讲怎么从零把一个AI项目做成一个能上线、能维护、能迭代的工程产品的内容太少了。所以我想把这次从零构建AI工程化项目的完整路径写下来给那些正准备在自己的项目里落地AI能力、或者刚刚接到类似需求的朋友一个清晰的地图。这篇文章会覆盖我从需求拆解、技术选型、工程骨架搭建、模型接入、RAG检索链路实现、评测体系设计到最后部署上线的完整过程。不会太多扯理论更多是踩过坑之后的经验总结。1. 需求边界界定从做个AI到定义MVP——先想清楚这道题到底在解什么很多AI项目死掉不是死在技术难点上而是死在第一步——需求压根没想清楚。业务方说我要一个AI这句话跟我要一辆车一样模糊你得帮他搞清楚是一辆代步轿车还是一辆货车拉几个人跑什么路况预算多少。AI项目的需求定义就是不断把模糊愿望翻译成可执行工程约束的过程。1.1 拆解业务诉求用户要的不是大模型而是一个能用的流程我那会儿接到的原始需求是让员工直接提问就能拿到答案。听上去很AI但我做的第一件事反而是反AI的我拉着业务方坐下来一个细节一个细节地问。你是想让员工查企业内部的制度文件还是让新人快速上手项目历史还是让客服快速找到产品知识这些场景落到系统上完全是不同的技术路线。最后我们把需求收敛成了这样一句话在内部知识库范围内让员工用自然语言提问系统返回带有来源引用的准确答案且答案必须基于知识库内容不能胡编。这句话定义了三个关键约束范围约束答案必须来自知识库这决定了我们后续必须走检索增强RAG路线而不是纯靠模型脑补。正确性约束回答要准确这意味着我们需要设计一套评估机制去度量准确。可追溯约束答案要有出处这决定了检索链路必须在返回结果里带上来源文档和片段位置。这一轮拆解的作用立竿见影——我在技术方案文档里写的每一行都开始有据可依。后来我养成了一个习惯凡是接AI项目先跟业务方对齐范围正确性可追溯这三个词各自意味着什么比先冲去选模型重要一百倍。1.2 技术选型的取舍逻辑先定边界条件再谈工具好坏需求定完之后才轮到技术选型。很多新手上来就纠结我要用LangChain还是直接写代码用哪个模型。我的经验是选型不要从哪个工具火出发而是从边界条件倒推。我当时的边界条件是这些部署环境在私有云上数据不能出内网这意味着大模型的API调用要经过专门的安全通道或者干脆部署开源模型。知识库文档以Word、PDF、Markdown为主总量在几百份后续可能涨到几千份这个量级不需要上分布式向量库。团队里会维护这个项目的人就我和另一位后端同事技术栈是Python。要控制成本但优先级排在稳定性和效果之后。基于这些条件我做的核心选择是模型层采用API优先的架构先接商用模型的合规接口跑通全链路同时把模型层封装成统一接口后续可以随时替换成私有化部署的开源模型。框架层不用任何重型的AI编排框架只用轻量的提示词管理工具。原因是我们的链路并不复杂——检索、拼装、调用、解析这些直接用代码写反而更清晰出问题也好排查。框架带来了抽象但抽象是有调试成本的。向量库选了PostgreSQL的pgvector扩展。理由很实际我们原本就有PostgreSQL实例加一个扩展就能用还能复用现有的备份、权限体系。为一个几百份文档的项目单独引入一套向量数据库运维负担不划算。应用层FastAPI提供API服务因为异步支持好文档自动生成团队熟悉。1.3 设计上的隐形警示不要把自由度留给未来我还做了一件当时看起来有点过度设计的事——把模型接入做成了插件化接口。每个模型一个适配器统一输入输出格式。当时业务方说就用一个模型别搞复杂了但我的经验是在AI领域唯一不变的就是模型会换。今天你觉得某个模型好用三个月后可能出了新的、更便宜、效果更好的或者原厂商调整了价格和策略。如果你把代码写死在某个模型的API细节上换模型的时候就是一次大重构。这套接口设计后来真的派上了用场——上线一个多月后因为成本和效果的综合考虑我们把底座模型换了一版只改了适配器配置就完成了切换业务完全无感。这件事让我更加坚定了一个原则在AI工程化里不稳定是常态所以架构里一定要给变化留位置。2. 从零搭建工程骨架项目结构、环境隔离与依赖管理技术路线定了之后就是动手搭骨架。这个阶段最容易被小看但恰恰是后期迭代快不快、排查顺不顺的分水岭。我见过太多AI项目代码全堆在一个main.py里依赖装在全局环境里数据文件散落在各处。这种项目只要跑两周就会变成谁也不敢碰的定时炸弹。2.1 项目目录按职责划分而不是按流程划分我最终采用的目录结构是这样的你可以直接参考ai-engineering-demo/ ├── app/ │ ├── main.py # FastAPI入口 │ ├── config.py # 全局配置 │ ├── api/ # 路由层 │ │ ├── v1/ │ │ │ ├── endpoints/ │ │ │ └── deps.py │ ├── core/ # 核心领域逻辑 │ │ ├── reader.py # 文档解析 │ │ ├── splitter.py # 切片策略 │ │ ├── retriever.py # 召回逻辑 │ │ ├── generator.py # 生成逻辑 │ │ └── models.py # 数据模型 │ ├── llm/ # 模型适配层 │ │ ├── base.py # 模型接口抽象 │ │ ├── openai_adapter.py │ │ └── local_adapter.py │ ├── services/ # 业务编排层 │ │ ├── qa_service.py │ │ └── ingest_service.py │ └── schemas/ # API请求/响应结构 ├── data/ │ ├── raw_docs/ # 原始文档 │ └── processed/ # 解析处理后的中间产物 ├── tests/ │ ├── unit/ # 单元测试 │ ├── eval/ # 评测集与评测脚本 │ └── integration/ # 集成测试 ├── scripts/ │ └── ingest.py # 知识库入库脚本 ├── pyproject.toml └── README.md这个结构的核心逻辑是按职责分层路由层只管接收请求和返回响应services层负责串起整个问答流程core层放核心技术逻辑llm层隔离模型细节。这样一来任何一个环节要改我只需要知道改哪个目录不需要通读全项目。2.2 环境依赖用锁文件锁死一切变量依赖管理这关我吃过很多亏。Python项目只要经历一次在我电脑上能跑啊你就知道依赖管理有多重要。最开始我用的是常规的requirements.txt但很快发现一个问题requirements.txt里写的版本范围太宽松比如你写numpy1.24三个月后同事一装依赖装到了最新的1.26一些微妙的API变动导致代码跑不起来排查半天才发现是numpy版本问题。这个项目我直接换成了uv来管理。uv的特点是快而且通过uv lock生成的锁文件会把所有依赖的精确版本固定下来——包括传递依赖。这意味着任何人在任何时间clone项目执行一条命令就能装出和我开发时完全一样的环境。对AI项目来说这尤其重要因为像transformers、torch这种库版本一变行为就变。除了Python依赖我还在项目根目录放了一个.env.example文件把所有需要配置的环境变量列出来并附上说明。真正跑的时候用.env提供实际值.env不进版本库。变量包括模型API的key、数据库连接串、向量维度配置等。2.3 配置管理的细节把一切可变项从代码里抽出来配置管理的核心原则是凡是可能变化的参数都不许硬编码在代码里。我吃了这个亏之后才立的规矩——早期写原型时向量检索的top_k值直接写死在retriever.py里后来调优的时候每次都要改代码、重启服务。后来我把所有可调参数都挪到了配置文件里用pydantic-settings加载。我的配置文件长这样from pydantic_settings import BaseSettings class Settings(BaseSettings): model_name: str gpt-4o embedding_model: str text-embedding-3-small top_k: int 5 chunk_size: int 800 chunk_overlap: int 100 vector_dim: int 1536 db_url: str api_key: str temperature: float 0.3 class Config: env_file .env env_file_encoding utf-8 settings Settings()这句话背后的逻辑很简单AI应用是一个参数密度极高的系统。切片的粒度、召回的数量、温度系数、条数限制每一个参数都在影响最终的体验和成本。你要在运行时快速调参实验就必须把参数从代码中解放出来。这个习惯在后续的评测调优阶段给我省了非常多的效率成本。3. 模型接入层选型、Prompt工程与给模型减负基础架子搭好之后先后做的事是模型选型与Prompt工程。这个环节看起来是纯调用API的工作实际上很多失败的项目就是死在这里——要么模型选型不对要么Prompts里的问题根本没写好。3.1 模型选型的核心约束效果、成本、延迟三者的平衡模型选型没有绝对的好坏只有适不适合。我当时在两个方案之间纠结一是直接商用模型效果最好、成本可控二是私有化部署开源模型数据安全等级最高、但人力和算力成本很高。最终我选了先商用、后私有化的策略原因是项目初期还在验证阶段量级也小商用模型按量付费的成本完全可以接受。但这笔账怎么算的要给大家交代清楚商用模型成本估算假设每天500个问题每个问题的上下文大约3000个token每天花费大约是0.5到1美元一个月就是15到30美元。这个成本对内部项目来说可以忽略不计。私有化部署成本估算需要GPU服务器月成本在几百美元以上还需要人来维护模型服务、处理OOM、升级版本。在小规模场景下这些成本远高于商用API。所以我的结论是小规模内部项目用商用API的性价比远高于私有化部署。只有当你的调用量到了每天数万次级别私有化部署的单位成本优势才开始体现出来。而且通过适配器模式我在代码层已经留好了后路——将来量大了随时可以切换。3.2 Prompt工程让模型理解它只是个问答引擎不是维基百科模型基座定了接下来是Prompt工程。很多人以为Prompt工程是用魔法让模型回答得更好但实际做下来你会发现Prompt工程的核心是约束角色的行为边界而不是提要求。我设计的系统提示词核心部分是你是一个企业内部知识库问答助手。你的任务是基于提供的文档片段回答用户的问题。 规则 1. 只基于提供的文档内容回答禁止使用你自己的知识补充。 2. 如果文档内容不足以回答用户问题必须直接回复知识库中没有找到相关内容并建议用户重新措辞或咨询相关部门。 3. 回答时优先引用文档中的原话保持表述与文档一致。 4. 回答控制在200字以内给出明确结论然后用条目列出关键依据。你可能会问这套提示词有什么特别的特别之处在于每一句都在减负——它明确告诉模型什么不该做。禁止使用你自己的知识补充这条是最重要的它把幻觉风险从源头压制住了。因为RAG链路的价值就在于答案有据可查如果模型自作聪明拿自己的知识补一段用户的信任感瞬间崩塌。我还做了两个版本的回答风格测试详细模式和简洁模式。最终内部员工反馈是简洁模式更好用所以我把系统提示词里的回答控制在200字以内保留了下来但调整了策略——默认简洁用户追问时才展开。这个交互设计也让API调用成本下降了约30%因为平均输出token数减少了。3.3 用JSON Mode保证输出结构让模型输出能解析的内容纯文本回答对用户展示够了但对系统来说我们要的不只是能看的答案还有结构化的元数据这句话读的是哪个文档、哪个段落、置信度多少。这样才能支撑前端展示引用来源。解决方案是把输出格式定成JSON{ answer: 请假超过3天需要提前在OA系统提交审批并附上相关证明材料。, source_documents: [ { title: 员工请假管理制度.docx, page: 3, score: 0.87, snippet: ... } ] }具体实现上我在系统提示词里给出了这个JSON的schema描述并让模型严格按JSON输出。这一步极其关键如果模型偶尔输出了一串多带带文本我们还要写解析逻辑去兼容那才是噩梦的开始。后来我换成了一种更稳的做法在调用接口时显式开启JSON模式同时仍然在提示词里附上schema。两重保障之下解析错误率从偶尔出现直接降到了零。4. RAG检索链路搭建文档切片、向量召回与问答组装到这一步终于进入整个项目最核心的部分——RAG链路。RAG检索增强生成的思想一句话可以概括先让系统在知识库里找到和问题相关的片段再把片段喂给模型生成答案。但找得准这三个字展开来足以让你折腾一个月。4.1 文档解析与切片设计题目的上限在起点就被定死了RAG的效果上限其实在文档切片这一步就已经决定了。模型再聪明也回答不了它压根没有见到的内容。如果切片把一份文档中本属于同一问题的上下文切散了或者把多份不同主题的内容误合到一个片段里后面的检索和生成就都会受影响。我处理的第一步是文档解析。我们内部的知识库是Word、PDF、Markdown混合的企业级文档的噩梦在于——很多PDF本质上是一张图片直接解析出来只有一堆乱码。我当时的处理方案是Word和Markdown用解析库直接取出正文。文本型PDF用PyMuPDF直接取文本。扫描版PDF先用OCR识别再转文本。识别完的文本还有一层清洗去掉页眉页脚、去掉多余的换行和空格、统一编码格式。这些活儿看似不起眼但它直接决定了你后面所有环节输入的干净程度。第二步是切片策略设计这是RAG工程最讲究的环节。我测试了三种切片方案固定宽度切片每512字符切一块实现最简单但经常在句子中间切断导致语义残废。按段落固定宽度混合优先按段落切段落太长的再按句子边界二次切分。效果比纯固定宽度好很多但实现麻烦。按语义切分依靠模型判断语义边界效果最好但成本高、耗时长。我最终采用的是第二种方案——按段落切段落太长时在句子边界处切分同时设置80个字符的overlap。overlap的作用是让切片之间保留重叠区域防止某个关键句恰好落在上一个片段的结尾、下一个片段的中段导致信息丢失。我还加了两个优化措施一是在切片过程中添加上下文的锚点比如把文档标题作为前缀加到每个切片里这样检索时如果命中了某个切片模型就知道它出自哪份文档的哪个部分二是把切片长度和拼接策略做成可配置的方便后续调参。这里我想特别强调切片参数一定要做成可配置因为你一开始设定的最佳参数随着文档类型变化几乎必然会过时。4.2 Embedding、向量库与召回让找到相关片段变得更精准切片做完之后每个切片都是一小段文本。我们要让用户的问题能找到它们就得把这些文本转换成向量然后做相似度检索。Embedding模型的选择上我做了个简单测试拿20个典型问题跑了一下top-5召回率对比了三种Embedding方案——OpenAI的text-embedding-3-small、开源的bge-large-zh、本地的m3e-base。结果让我有点意外在中文企业文档场景下开源bge系列与商用模型的差距并没有想象中那么大但商用方案的稳定性和速率更省心。最终我选择了商用Embedding模型因为它不需要额外的部署运维而且官方的批量接口处理速度快。向量库用pgvector的思路前面提到过。建表和索引的SQL大概是这样CREATE EXTENSION IF NOT EXISTS vector; CREATE TABLE doc_chunks ( id BIGSERIAL PRIMARY KEY, doc_id VARCHAR(128) NOT NULL, title VARCHAR(512), chunk_index INT NOT NULL, content TEXT NOT NULL, source_page INT, embedding VECTOR(1536) ); CREATE INDEX idx_doc_chunks_embedding ON doc_chunks USING hnsw (embedding vector_cosine_ops);HNSW索引是pgvector支持的近似最近邻索引在大几千量级的数据下查询速度都在几十毫秒以内完全够用。这个方案的好处是你的知识库数据和业务数据在同一个数据库里备份、权限、监控都是现成的不需要额外运维一套新系统。召回策略我做了两层第一层是向量召回把用户问题转成向量在pgvector里按余弦相似度取top-20。第二层是重排Rerank)向量检索的结果里有些文本可能关键词对上了但实际意思不相关。我引进了一个轻量级的重排模型对top-20结果做精细打分再取top-5作为最终上下文。这个召回多取、重排精取的策略是在实际测试中得来的经验如果只向量召回top-5一旦前几瞄准有噪声整个答案就拉垮了如果全部塞给模型又会超出上下文限制。两级方案既保证了召回率又控制了送入模型的token量整体效果有明显提升。4.3 问答链路组装把检索和生成拼成一个完整的服务模块都准备好了之后最后拼装问答链路。我做的服务流程大概是这样的接收用户问题进行必要的标准化处理去重空格、统一大小写、识别是否包含多个人名/日期等实体。调Embedding接口把问题向量化。在pgvector中做向量召回取回top-20切片。用重排模型评精排序得到top-5切片。如果涉及的多份文档内容存在明显差异或相互矛盾会额外标记出来提醒模型注意。把切片内容按文档1、文档2……的顺序拼成上下文连同系统提示词和问题一起发送给模型。解析模型返回的JSON经过总长度、来源字段校验后发给前端。有个细节值得说一下我在把切片内容拼给模型时会在每个切片前加上文档标题的标记。这是受了锚点思路的启发——让模型在生成引用的时候知道它引用的是哪一份文档。否则模型只能答出内容却没有办法给出准确的来源。这个细节直接解决了引用来源准确性的问题。还有一个常被忽视的地方对话历史的问题。一开始我做了多轮对话支持把历史消息也喂给模型。结果发现历史消息经常抢走最新问题的注意力而且文档切换不及时会导致前后文矛盾。后来我改了策略默认每次提问都基于用户当前的问题独立检索多轮对话只保留最近一轮的上下文。实测下来流畅度接受准确率反倒因为上下文干扰变少而提高了。经验是没有硬性需求不要无脑做多轮记忆成本高且易翻车。5. 评测体系先定义好再谈迭代——没有评估的AI项目都是耍流氓做AI应用最痛苦的地方在于它不是一个写完了就完了的东西。模型输出的随机性、文档内容的变化、用户提问方式的多样性导致同一个系统今天的表现和明天可能完全不同。如果没有一套评测机制你就会陷入改了不知道变好了还是变坏了的泥潭。5.1 建一个黄金评测集给好和坏立下标准我在项目进入开发后半段时花了两天时间专门做评测集。方法很简单从真实业务中收集了80个问题覆盖了六大类典型场景——制度查询、操作流程、历史决策、数据统计口径、系统故障处理、开放域试探就是那些不该被回答的问题。每个问题我都手工标注了理想答案的要点和应该引用的来源文档。最终评测集分成了三个子集召回定位集40个问题测试检索链路能不能找到正确的文档片段。回答正确集30个问题测试整个生成链路能不能给出正确结论。安全拒答集10个问题测试系统会不会在知识库没有答案时胡编一个。这三类必须分开因为一条链路的问题可能出在检索段也可能出在生成段。分开评测才能快速定位故障环节。我写了一个评测脚本自动跑完所有问题把结果输出成表格——答对了、答错了、拒答正确、错误引用、引用缺失等状态一目了然。每次改动Prompt或切片策略就把评测集重跑一遍。5.2 让准确率变得可以度量评测的核心是定义清楚评价指标。我没有用特别复杂的自动指标而是采用了机器初筛人工复核的混合模式自动初筛检查回答是否包含预期答案中的关键实体词检查引用的来源是否落在标注的正确文档范围内检查系统是否错误拒答了应回答的问题。这些规则写起来很快能过滤掉约60%的基础错误。人工复核剩下无法自动判断的就人工看一遍。80个问题人工复核一次大约需要40分钟。这个时间花得值因为每次调优后都要跑而40分钟能换来你对系统状态的确切认知。另外我还引入了一个简单但很有用的指标——答案与切片的句法对齐度把模型回答里的句子与对应引用切片做相似度计算阈值设0.35低于这个值的句子视为无据生成。这能相对有效地抓出幻觉的苗头虽然不完美但已经能自动暴露很多问题。这套评测体系让我避免了无数次盲人摸象。有一次我把切片长度从800改到600评测跑下来发现召回定位集的通过率从87%掉到了78%原因是有几份制度文档的关键条款被切散了。如果只看一两个示例上的表现根本发现不了这种回归。5.3 建立回归防守线每次改动都必须过关卡另外一个重要习惯是把评测脚本挂进CI。遇到一个重大改动时统一先跑单元测试再跑评测集评分低于设定阈值就直接阻止合并。这个关卡看起来简单但它能在你连续调了三小时Prompt之后阻止你把一个感觉有明显改进但实际退化的版本合进主干。评测门槛的具体数值是参考第一次全量评测跑出来的基线设置的。当时基线是召回通过率85%、正确率82%、拒答完成率90%。我设置了两个关卡一个是不得低于基线另一个是改动目标指标提升不低于2个百分点才允许替换旧方案。AI项目迭代最怕的不是没变化而是改了之后你不知道是变好了还是变差了。评测关卡就是那杆尺。6. 部署上线与服务化从笔记本到生产环境最后一道坎开发和评测都在本地完成后真正的考验才刚开始——部署上线。AI应用部署和平常的后端服务部署有很多不同它依赖模型API、embedding API的可用性有更复杂的配置管理响应时间更长客户端需要适配模型输出不稳定还要有兜底方案。6.1 API服务化把AI能力包成一个干净的接口我用FastAPI写API层最大的心得是接口设计要面向调用方的方便而不是面向模型的方便。我对外暴露的接口长这样POST /api/v1/qa { question: 请假超过3天需要怎么操作 } Response 200: { answer: 根据《员工请假管理制度》请假超过3天需要提前在OA系统提交申请并附相关证明材料。, sources: [ { title: 员工请假管理制度.docx, page: 3, score: 0.87, snippet: 请假时间超过3天的需提前在OA系统提交申请附相关证明材料报部门负责人审批。 } ], conversation_id: uuid }这个接口设计的关键点请求只有question字段调用方不需要理解任何AI概念把系统当成一个普通搜索接口用。响应包含sources数组前端可以直接渲染引用来源而不是让用户只能相信一个黑盒回答。conversation_id留着做后续的追踪和日志关联排查问题时能按会话维度拉出完整的请求链路。另外我单独做了一批异步任务型接口比如重新入库一份文档批量刷新向量数据这类操作用异步任务队列来处理避免阻塞主服务。对于问答这种实时接口我用同步超时加上客户端轮询的方式保证可靠。6.2 性能、缓存与成本优化让AI服务能够跑得稳也跑得起AI服务上线后最容易出问题的不是功能不可用而是响应太慢和成本失控。我在性能方面做了三件事网关层设置合理的超时机制模型调用设置30秒超时这是为了给模型官方接口足够的冷却时间。API网关设置15秒超时这是为了让前端不至于等太久配合前端loading提示。如果模型超时则返回一个AI服务繁忙的错误提示并附上业务方提供的兜底可直接联系的人员联系方式不至于让用户傻等。Embedding和常见问题的结果缓存向量化是相对贵的操作我们对高频问题比如加班怎么算年假有几天这类热门问题做了语义缓存——先用Embedding把问题向量化然后在Redis里查有没有语义相近的历史问题直接返回缓存答案。实测热点问题响应时间从3-5秒降到了150毫秒左右。缓存策略做了关键词语义向量双通道关键词一样就直接命中关键词不同但向量距离近的返回时附一个以下为相近问题的结果可能不完整的提示避免用户拿到答非所问的结果。Token用量统计与预算控制我写了一个简单的Token计数中间件每次请求都记录输入输出Token数并按部门打上标签。月底看账单的时候哪些部门用得多、哪些问题占了大部分成本一目了然。一旦发现某类问题长期高频出现就直接把它做成FAQ静态页用户还没走到问答环节就找到答案了也直接砍掉了这部分成本。6.3 CI/CD与线上监控让加了新文档也成为一次部署事件AI项目的CI/CD有个独特特征模型参数变了算一次发布知识库文档变了也算一次发布。两者的变更都可能引起线上行为变化所以都要纳入版本控制。我的Git工作流大概是这样的代码改动走正常的feature分支合并。知识库文档变更走单独的一个流程文档更新后推到最新的解析结果然后在CI里自动跑一遍“摄入流程”解析、清洗、切片、向量化、入库同时跑小规模回归测试大概10个代表性问题保证新增文档没让原有的回答质量明显下降。模型版本升级也走一次正式的发布流程在CI里加上模型对比测试旧模型跑一遍评测集新模型跑一遍对比指标没有下降才自动切换。线上监控主要盯三个指标响应P95延迟超过5秒就需要排查是模型API变慢还是数据库慢。错误率调用模型失败、超时、JSON解析失败都算。我设了1%的告警阈值。无引用回答的比例如果回答的sources为空或引用与答案的相关度不高说明这个回答大概率不可信要重点检查。日志系统里我会把人机问答对和评分都留底。每个回答都会让用户点有帮助/没帮助超过两周的反馈数据加起来就能告诉你系统该往哪个方向调优。这种做法对AI产品来说几乎是刚需——因为模型输出的质量感受非常主观你需要持续地、有规模地收集真实世界的反馈。写在最后AI工程难的不是AI是工程回看这个项目的全过程我最大的体会是AI工程这个词的重心其实落在工程两个字上。模型只是整个链路里最亮眼的一个环节而真正决定项目成败的是你有没有把需求拆干净、有没有把数据处理好、有没有把评测体系立起来、有没有把部署运维想周全。如果你正准备从零开始做一个AI项目我最想给你的建议就三条。第一抠需求的时间永远别省先和业务方把做什么、不做什么、什么叫做得好三句话对齐后面就不容易返工。第二把一个最小的闭环先跑通哪怕暂时不能用最好的模型、没有全部文档也别在项目初期就追求大而全。第三尽早建评测而不是等上线了被用户骂了再补因为到那会儿你已经分不清是哪里坏了。这个项目上线之后我其实每天还在收到反馈、每周还在做微调。但正因有了这套从零搭起来的框架每次迭代都有章可循。AI领域变化这么快今天的最优方案明天可能就过时了——但你已经搭好了一个能快速切换、持续验证的底座这本身就是最有价值的部分。