ARTICLE DETAIL

资讯详情

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

从零搭建AI工程:模型到稳定服务的完整实践路径

从零搭建AI工程:模型到稳定服务的完整实践路径 如果有人问我AI工程怎么从零开始我的回答可能会让一些人意外——先别急着写模型代码。过去几年我见过太多类似的场景代码在本地笔记本里跑得飞起一到服务器就频频报错demo演示时效果惊艳一接真实流量就各种超时模型换了一个又一个回头发现连日志都没法查。我自己也踩过同样的坑所以才有了这篇记录。它不是什么权威教程而是我把AI工程这条链路从零重新捋了一遍之后留下的真实经验、踩过的坑、以及最终沉淀出来的工具链和流程。我理解中的ai-engineering-from-scratch核心不是从零训练一个大模型——对绝大多数团队来说这既不现实也没必要——而是从零建立把模型变成稳定服务的能力。转换、向量化、推理、部署、评测、监控每一个环节都要亲手搭一遍才算真正入了AI工程的门。这篇文章会按我实际走过的路径拆解适合那些已经能调用模型API、但还没独立交付过一个AI服务的人。1. 为什么绕了一圈我决定把AI工程从零重学1.1 从跑通脚本到交付系统之间隔着一整条生产线我最早接触AI工程的方式和很多人一样拿着模型API写提示词在Jupyter Notebook里调试跑通一个文档问答demo就直接复制到业务代码里。当时觉得AI工程不过如此——模型帮我干活我负责把结果拼进界面就行。真正被打脸是一次内部工具的部署。本地测试响应很快但接到公司服务器后几个并发请求直接把进程拖垮了原因我排查了很久忘了做请求队列也没有设置超时和重试GPU显存被多线程重复加载的模型占满。那一刻我才意识到本地能跑的脚本和线上能跑的AI服务隔着整整一条生产线。那条生产线包括数据的获取与清洗、模型的选择与加载策略、推理服务的并发控制、接口的容错处理、评测集的构造、以及上线后靠什么判断系统有没问题。任何一个环节缺失都会在真实场景里用故障和事故告诉你。1.2 算法能力和工程能力是两种不同的能力算法岗和AI工程岗经常被混为一谈但实际工作方式差异很大。算法岗的核心目标是提升模型在某个指标上的表现比如准确率、召回率AKA让模型更聪明AI工程的核心目标是让模型在真实环境里稳定、可控、可维护地工作AKA让模型靠得住。换句话说前者关心单点效果后者关心系统可靠性。举个例子一个模型在评测集上准确率提高了5%但如果它的推理耗时长了一倍调用方不愿意等那这5%毫无意义。又比如你花了很多精力微调模型结果上线后遇到一类新的输入格式就乱输出没有评测集和监控机制帮你发现用户只会觉得这AI怎么变傻了。所以我重学AI工程时反复提醒自己不要只用一个demo来证明能做要用一整套工程手段来证明能稳定用。这个思维转变是整个过程的出发点。1.3 我给这次重学定的三个目标为了不让自己再次沉没在追新模型、换新框架的节奏里开始时我就定了三个非常具体的目标独立搭建一条可运行的RAG问答链路从文档处理、向量化、检索到生成全部自己写出来不依赖一键式框架把这条链路部署成带API的服务支持并发访问、超时控制、基础监控建立一套小但可用的评测办法至少能用客观规则判断模型变了之后是变好还是变坏。这三个目标都不涉及从零训练模型但每一条单拎出来都需要动手解决大量实际问题。事实证明走完这一圈之后再看各种新框架、新技术就不会慌了——因为底层的工程逻辑我已经摸过一遍。2. 先分清四层再动手我梳理的AI工程能力地图有几个朋友问我AI工程到底要学什么直接上LangChain行不行我的看法是框架可以帮你提速但不能帮你建立判断力。如果一开始就把所有逻辑交给框架出了问题你连从哪里排查都不知道。所以我先把AI工程拆成四层每一层都明确它解决什么问题。2.1 数据工程层所有项目的地基这一层看着最不起眼却决定项目上限。AI系统的输入数据质量直接决定输出效果。我吃过最大的亏就是把脏数据直接拿去切分入库结果检索出来的片段残缺、噪声大再怎么优化提示词都没用。数据工程层核心要做四件事采集确定数据源、拉取方式、增量更新机制清洗去重、去广告噪声、去掉乱码和表格错位之类的问题结构化把原始文档转成适合后续处理的格式比如按标题层级整理切分与标注决定文本块大小、重叠策略需要标注的任务还得设计标注规范。这一层不需要多高深的技术但一定要亲自动手做一遍。我建议每个人从自己的真实数据开始哪怕只是几十篇文章也要走完原始文档到可检索片段的全过程。2.2 模型工程层不只是会调用模型工程层在我这里包含三块内容模型选型、推理优化、微调。模型选型的核心是弄清楚约束条件部署成本、响应延迟、上下文长度、中文能力、显存占用。不是越大的模型越好而是在你的硬件和延迟预算内挑效果最好的。实测下来很多业务里7B左右量级的开源模型配合好的检索和提示词效果已经够用。推理优化这块至少要知道量化把模型权重精度降低比如从FP16压到INT8或INT4、批处理同时处理多个请求、缓存重复问句直接返回这三板斧。它们直接影响吞吐和成本。微调我放到最后学因为它是用更多数据让模型更适配场景的手段前提是你已经有一套能评价核心能力的流程。否则微调完了也不知道是变好还是变坏。2.3 应用编排层模型怎么被业务使用这一层回答的问题是业务怎么调用模型能力。包括提示词管理、上下文组装、工具调用Function Calling、Agent流程控制、以及RAG的检索与生成组装。我特别想强调提示词管理的重要性。很多人把提示词直接写在业务代码里改一版要发一版。我在实践里会把提示词做成模板文件或配置项甚至可以带版本号方便对比效果。不要小看这个动作等到你试过十几种提示词写法后就知道没有版本管理根本分不清哪个改动带来了提升。2.4 部署与可观测层真正的分水岭如果说前面三层是把模型用起来那部署与可观测层就是让系统靠谱地活着。这一层包括服务化把模型封装成API处理好并发、超时、重试容器化用Docker统一环境避免在我机器上是好的评测构造评测集量化模型效果变化监控日志、指标、错误追踪出了问题能快速定位安全输入输出侧的敏感信息过滤、权限控制。实话说很多人学AI工程会卡在这一层。因为前面三层里你改改代码就能看到模型输出成就感来得直接而部署和监控的反馈很慢看起来像是在做非AI的杂活。但我可以负责任地说这一层才决定了你到底是会写AI脚本还是会做AI工程。3. 工具链选型实录哪些留下、哪些放弃聊完能力地图分享一下我实际用下来的工具链。我选工具的标准很简单维护成本低、社区活跃、文档清晰。功能炫酷但不稳定的我一律不用因为AI项目本来就容易出问题我不想再叠加一层工具的不确定性。3.1 Python环境pyenv uv告别依赖地狱早期我吃够了Python依赖冲突的苦A项目需要torch 2.xB项目却锁定在1.x装个包把系统级Python环境搞崩重装系统那种。后来我切换到pyenv管理Python版本加uv管理依赖和虚拟环境基本告别了这类问题。uv目前是我最推荐的工具它比pip快一个量级依赖解析也很智能。我的标准操作流程是# 安装 uv虚拟环境会自动创建 uv init ai-engineering-from-scratch cd ai-engineering-from-scratch # 添加依赖 uv add fastapi uvicorn chromadb sentence-transformers uv add --group dev pytest # 跑脚本时会自动识别虚拟环境 uv run python main.py3.2 模型推理方案Transformers、vLLM、Ollama怎么分工模型推理这块我按场景分了三档场景工具原因本地调试、小数据量测试HuggingFace Transformers灵活、调试方便、和模型社区生态无缝衔接线上高并发推理服务vLLM吞吐量高、支持连续批处理显存管理做得好快速做原型、个人电脑轻量跑Ollama安装简单、模型管理方便但控制粒度较粗需要注意不要让工具绑架场景。比如直接把pipeline塞进在线API里没有批处理和流式控制几个并发就把显存打爆反之给一个小工具接上vLLM又属于杀鸡用牛刀白白增加部署复杂度。3.3 应用层FastAPI自研pipelineLangChain用在哪我见过一些初学者把LangChain当作AI工程的全部说实话这个框架确实封装了很多东西——RAG、Agent、Tool调用都有现成实现上手很快。但我在实践中发现框架封装的越多越容易让你绕过中间的关键细节。所以我的做法是核心链路自己写LangChain只做局部接入。比如我需要一个稳定的问答服务时会直接用FastAPI搭API用SentenceTransformers做embedding用向量库做检索再用模型做生成。每一步的输入输出都在我控制之内出了问题我能精准定位。而LangChain的组件我更多在需要快速验证某个工具调用流程是否可行时使用比如让模型决定是否要调用搜索工具、下次该问什么。这种探索性场景它价值很高。3.4 向量库、部署与监控的取舍向量数据库我经历了一个从轻到重的过程。最初用Chroma起步因为它部署简单上海量数据前完全够用。后来数据规模上来、查询并发变高我才迁到Milvus。我建议你也这样先跑通再迁移不要一开始就上重系统。部署我统一用Docker。一个典型项目至少会有三个容器API服务、向量库、模型服务如果模型单独部署的话。我习惯用docker compose做本地编排线上再用统一的容器平台管理。记得给每个容器配好健康检查不然编排系统会以为服务还活着一直往里发流量。监控这块我先保证最基础的三件事日志有结构化字段时间、请求ID、输入长度、输出token数、耗时、错误码指标有请求量和P95延迟报警至少要能推送到群聊。一开始就上全链路追踪、大盘体系反而容易劝退。4. 从零跑通一个RAG问答系统一天内的实操记录接下来是全文最实操的部分。我会把自己跑通一个最小可用的RAG问答系统的完整过程记录下来包含目录结构、关键代码、以及我调试中遇到的具体问题。这套流程第一次做可能需要一整天甚至更久但做过一遍之后你对AI工程的手感会有本质提升。4.1 需求与数据准备需求定得很小给一份内部知识库文档做问答系统用户问报销流程是什么系统从文档中找到对应片段用模型组织成口语化回答。数据准备阶段我先做了两件事把文档转成统一格式我用的是Markdown格式因为它的标题层级天然适合切分清洗噪声原文里有一些广告块、重复段落我用脚本按规则删除再人工抽查20%的文本。这一步想提醒大家切分不是靠猜一个固定长度。先看你的文档结构决定切分策略。我的经验是优先按标题层级切分如果某个标题下内容太长再按最大token数二次切分同时让相邻片段有少量重叠防止关键信息正好被切断。4.2 切分、向量化、检索重排我用的是最朴素的实现方式不引入太重的组件。切分逻辑大致这样def split_markdown_by_heading(md_content, max_tokens512, overlap_tokens64): # 1. 按标题层级把文档切成大的章节块 # 2. 对超过 max_tokens 的块再按段落切并保留 overlap # 3. 返回 [(title, chunk_text, token_count), ...]向量化我选了中文场景下比较稳的BAAI/bge-small-zh-v1.5。小模型向量维度和效果够用即可不需要一上来就上最大号的embedding模型否则检索快感没有存储成本和耗时先翻倍。初步检索用topk8然后在结果里加了一道重排用BAAI/bge-reranker-base对候选片段做相关性打分最后保留前三名。加了重排之后回答的命中率提升非常明显原因很简单向量检索负责找得到重排负责找得准。不过重排会增加约几十毫秒延迟所以是否需要得看你的实时性要求。4.3 生成环节提示词与上下文设计生成环节我用Qwen系列中的7B指令模型做本地推理。这里关键有两点上下文窗口管理和提示词模板版本化。上下文管理的意思是不能把检索出来的所有片段一股脑塞进模型。要预估token数按相关性排序截断确保总长度不超过模型上下文限制并且给回答留足输出空间。我常用的做法是max_context_tokens 4096 max_output_tokens 768 # 拼装 system user 提示词时按比例预留输出 token提示词方面我早期踩过很多坑只给检索片段不给原文结构模型经常编造来源没有回答不出来就直说的约束模型就会硬答。最终沉淀一个模板靠系统提示词明确角色、引用规则和边界你是一个严谨的知识库问答助手。请仅基于下面提供的资料回答问题。 如果资料中没有答案直接说知识库中未找到相关信息不要编造。 回答时先给出结论再补充依据。4.4 本地跑通与问题调试把上述模块串一个main.py用FastAPI暴露接口后我开始测试。第一个问题出在并发模型推理是同步占用的两个请求同时进来直接排队一个卡住全部卡住。解决办法是把模型推理放到独立线程池并在API层加超时控制。第二个问题更隐蔽切分片段之间有重复内容导致回答啰嗦。因为重叠切分有些片段一半以上的内容重复检索结果把同一个意思说了三遍。后来我在构造返回片段时做了简单相似度去重问题才缓解。第三个问题是资源消耗。本地推理跑在CPU或低配GPU上速度感人。我临时把模型量化到INT8回答延迟才降到可用范围。这也让我确认了上线前必须做推理优化否则可能连测试用户都等得失去耐心。5. 上生产前的最后十米并发、评测、监控、成本demo跑通只能代表路能走通离系统能交付还有一段距离。这一节讲讲我上生产前处理的最重要的四件事。5.1 并发和资源先解决显存和超时模型服务上线第一个要解决的问题就是资源调度。我在vLLM上部署模型后遇到两个典型瓶颈显存管理模型加载进显存后即使空闲也占用大量显存。vLLM的连续批处理能把多个请求同时喂给模型吞吐显著提升超时与队列一旦并发超过处理能力请求会堆积。我在API网关层设置了最大排队数和单请求超时时间超出的直接返回繁忙避免雪崩。这里有个形而上但很有用的经验AI系统的容量规划先从最稀有的资源算起。对GPU推理服务稀有资源是显存和推理卡片的计算能力对RAG链路稀有资源往往是大模型生成速度。先算清楚瓶颈在哪个环节再谈水平扩容否则只是盲目加机器。5.2 评测怎么定义能用模型类项目的最大难题是效果说不清楚。我在没有评测体系之前常常陷入好像变好了一点又好像某类问题变严重了的模糊状态。后来我下决心建了一个最小的评测集构造了100条问答对覆盖常见问题和刁钻问题每条标注了期望的答案来源来自哪份文档以及一个简单打分标准每次修改提示词、调模型、改切分策略都拿评测集跑一遍输出对比报告。我建议你也可以从这一步开始不要追求大而全的评测平台先用JSON文件维护一个几十到一百条的测试集配合脚本统计几个关键指标精确命中率、无答案拒绝率、平均回答长度。有了这个底子你后面做的优化才不再是盲人摸象。5.3 日志与监控出了问题能查AI服务的日志比普通服务要更细致因为同样的输入模型每次输出都可能不同。我后来统一了日志格式每一条请求都会记录{ request_id: req_123, timestamp: 2025-01-15T10:00:00Z, query: 报销流程是什么, retrieved_ids: [doc_1#section_3, doc_2#section_1], prompt_tokens: 1200, completion_tokens: 156, latency_ms: 2840, error: null }有了这些日志你才能回答三个关键问题回答慢不慢慢在检索还是生成用户有没有触发无答案拒绝如果延迟一直在涨多半是检索库里数据量大了索引没优化或者是并发峰值到了如果用户频繁触发未找到那问题大概率出在切分或者检索策略上。5.4 成本控制缓存、批处理、模型分层AI工程的成本大头在推理。我的省钱三板斧缓存重复请求完全相同的用户问题在有效期内直接返回上一次结果用Redis存就行。实际业务里热点问题重复率能到20%。模型分层不是所有请求都需要最强的模型。简单问答、闲聊、格式化任务用更小的模型处理复杂推理、长文档分析才调用能力更强的模型。这么一套分层成本能降一大截。批量测试而非逐条调用评测集跑批处理模式一口气发多个请求吞吐远高于循环里一次一次等结果。6. 这半年我悟出的几条经验6.1 三个我亲手踩进去的坑第一个坑是切分策略照搬别人。网上教程喜欢给一个固定token数比如512说什么大部分场景够用。但我的文档里有些表格被拦腰截断有些段落标题和内容被拆到不同块里检索效果惨不忍睹。现在我的第一反应永远是看数据长什么样再定切分规则。第二个坑是忽视重排这层。第一次部署RAG时只有向量检索用户问的问题稍微换了个说法检索回来的片段相关性就不行。加了重排之后同一批候选结果里能命中正确答案的概率提升了不止一点。但代价是多了几十毫秒得自己权衡。第三个坑是上线不设限这条。这里不是指接口限流而是模型回答没有不适用的边界。用户问隐私、问情绪化问题、问知识库里根本没有的事模型能一本正经地编答案。后来我在提示词里加死规则没有资料就拒绝在输出侧也做了兜底检测遇到高编造风险的回答宁可拒绝也不给错误信息。6.2 对新手的两条建议一条是关于学习路径的。如果你也像我一样从零开始我推荐的顺序是先会写提示词并理解token代价再跑通一条RAG链路这能让你接触全部组件接着把服务部署成API最后才考虑微调或接Agent框架。别一上来就沉迷微调大模型那是另一座山。另一条是把能跑和可控分开看。AI项目最容易让人误判进度的就是demo能跑。真正可控的标准是模型换了你知道吗效果变了你能量化吗出了问题你能半小时内定位到是哪一环吗这三点做不到系统离可交付还很远。6.3 下一步计划走完这一圈我给自己安排的下一阶段方向是两条线并进一条线把评测体系扩得更大覆盖多语言、多文档类型并把评测流程接到代码提交流程里每次改动自动触发另一条线开始涉足Agent编排让模型能真实地调用工具、做多步推理。最后说点实在的AI工程迭代很快但底层的工程基本功变化很慢。如果有一件事是贯穿始终的那就是稳定地交付一个让用户信任的AI服务——这句话说起来容易亲手做一遍才知道分量。
返回列表