ARTICLE DETAIL

资讯详情

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

从零搭建AI工程能力:推理引擎、上下文管理与缓存评测实战

从零搭建AI工程能力:推理引擎、上下文管理与缓存评测实战 1. 从零搭建AI工程能力为什么我劝你别一上来就调包这两年AI应用开发的门槛肉眼可见地在降低随便拉个框架、调个API就能跑出一个能对话的Demo。但我带过的新人里十个有八个在遇到模型输出不稳定推理延迟飙高上下文一长就崩这类问题时完全不知道从哪下手。根子就在于——大家跳过了从零理解AI工程这一步直接站在了工具链的最顶层。ai-engineering-from-scratch这个方向说白了就是把AI应用从能跑到跑得稳、跑得省、跑得可维护这条路上那些被框架封装掉的底层环节自己动手重新走一遍。它适合三类人一是刚转行做AI应用、只会调API的开发者二是想搞清楚推理服务内部到底发生了什么的后端工程师三是需要给团队搭建AI基础设施、但不想被某个框架绑死的技术负责人。我自己走过这条路也踩过不少坑。这篇文章不讲虚的就把我从零搭一套AI工程能力时真正需要理解的几个核心模块——推理引擎、上下文管理、缓存策略、评测体系——拆开揉碎讲一遍。每个环节我都会说清楚为什么这么设计参数怎么算实际会遇到什么问题你照着做能少走至少半年的弯路。2. 整体设计思路为什么从零比调包更值钱2.1 先搞清楚AI工程到底在工程什么很多人把AI工程等同于写Prompt或者调模型API这是最大的误解。一个能上生产的AI应用本质上是一个带概率输出的分布式系统它和传统后端系统最大的区别在于输入输出都是不确定的而且计算成本极高。这就带来三个传统工程里不存在的核心问题不确定性管理同样的输入模型可能给出不同输出。你得设计重试、校验、降级策略。成本控制每次推理都是真金白银。Token消耗、GPU占用、并发排队每一项都要精打细算。质量评测传统系统测的是对不对AI系统测的是好不好而好是个连续谱需要一套评测体系来量化。ai-engineering-from-scratch的核心思路就是把这三个问题当成一等公民来对待而不是等出了问题再打补丁。我见过太多项目前期Demo跑得飞快一上量就各种崩就是因为这三个问题从来没被认真设计过。2.2 分层架构把模型当成一个可替换的零件从零搭建时我建议采用清晰的分层架构而不是把所有逻辑塞在一个文件里。我的分层是这样的层级职责关键设计点接入层请求路由、鉴权、限流与模型无关可独立扩展编排层Prompt组装、上下文管理、工具调用业务逻辑核心最需要测试推理层模型调用、批处理、重试可替换支持多模型路由缓存层语义缓存、结果缓存成本控制的关键评测层离线评测、在线监控质量保障的闭环这么分层的最大好处是模型是可以随时换的。今天用A模型明天B模型降价了想换你只需要改推理层的适配器编排层和评测层完全不用动。我见过把模型调用散落在各处的项目换个模型要改几十个文件那才叫痛苦。2.3 技术选型别被最新最强绑架选型这块我的原则很朴素优先选你能读懂源码的、社区活跃的、能本地跑起来的。具体来说推理引擎如果只是调云端API那选型意义不大但如果要自部署我建议从支持连续批处理continuous batching的引擎入手这是吞吐量的分水岭。向量检索小规模百万级以下用内存索引就够别一上来就上分布式向量库运维成本远大于收益。编排框架能用代码写清楚的就别用框架框架的抽象泄漏在调试时是灾难。我个人的做法是先用纯代码实现等模式稳定了再考虑抽象。提示选型时一定要问自己一个问题——如果这个组件明天停止维护我迁移的成本有多大 答案超过一周的就要慎重。3. 核心模块拆解推理、上下文、缓存、评测3.1 推理引擎吞吐量和延迟的平衡术推理层是整个系统的心脏。从零理解它你需要搞明白两个核心指标首Token延迟TTFT和每Token输出时间TPOT。用户感知到的快主要取决于TTFT而整体吞吐量取决于批处理效率。连续批处理continuous batching是绕不开的概念。传统批处理要等一个批次里所有请求都生成完才能处理下一批而连续批处理允许新请求随时插入、完成的请求随时退出。实测下来在并发场景下吞吐量能提升3到8倍具体取决于请求长度的分布。如果你要自部署关键参数是max_batch_size和max_num_seqs。这两个值不是越大越好max_batch_size过大单次前向计算显存占用飙升容易OOM过小则GPU利用率上不去成本浪费。我的经验算法是先用显存容量反推最大批大小再根据P99延迟要求往下调。比如一张24G显存的卡跑7B模型FP16约14G权重留给KV Cache的显存大概8G按每个序列平均2K上下文估算能同时容纳的序列数大概在30到50之间。这个数就是你的max_num_seqs上限实际设置时留20%余量。3.2 上下文管理长对话不崩的关键上下文一长就崩是新手最常遇到的问题。根子在于KV Cache随上下文线性增长而显存是有限的。从零做上下文管理核心是三件事第一滑动窗口加摘要。不要傻乎乎地把所有历史都塞进去。我的做法是保留最近N轮完整对话更早的用模型压缩成一段摘要。N的取值看任务客服场景5到8轮足够代码助手可能要保留完整文件上下文。第二Token预算分配。给系统提示、历史对话、检索内容、用户输入各分配一个预算上限超了就按优先级裁剪。这个预算要动态调整比如检索内容相关度高时多给检索、少给历史。第三位置编码的处理。很多模型对超出训练长度的上下文外推能力很差硬塞长文本会导致中间遗忘。如果必须处理超长文本要么用支持长上下文的模型要么做分段处理再聚合。注意上下文不是越长越好。实测中把无关历史塞进去反而会降低输出质量因为模型注意力被稀释了。宁可精准检索不要暴力堆砌。3.3 缓存策略省钱的命脉AI应用的成本大头在推理而推理成本的大头在重复计算。缓存做得好成本能降一半以上。缓存分三层精确缓存输入完全一致时直接返回。实现简单用哈希做key就行。命中率在客服、FAQ类场景能到30%以上。语义缓存输入语义相似时复用结果。需要向量检索加相似度阈值。这里有个坑——阈值设太高命中率低设太低会返回不相关答案。我的经验是先用0.92起步根据badcase调整。前缀缓存相同系统提示和前缀的请求复用KV Cache。这个在自部署场景收益巨大尤其是系统提示很长的时候。主流推理引擎都支持开启后TTFT能降50%以上。缓存类型实现复杂度典型命中率主要收益精确缓存低20%-40%成本、延迟语义缓存中15%-35%成本、延迟前缀缓存低引擎支持60%首Token延迟3.4 评测体系没有评测就没有迭代这是最容易被忽略、但最重要的一环。没有评测你改一个Prompt、换一个模型根本不知道是变好了还是变坏了。从零搭评测我建议分两步走离线评测准备一个覆盖核心场景的测试集每个case标注期望输出或评分标准。每次改动跑一遍看指标变化。指标不要只看准确率还要看格式合规率、拒答率、平均长度等。在线监控生产环境采样人工抽检加自动指标。重点关注用户反馈点赞点踩、重试率、异常输出率。这些信号比离线指标更真实。评测集的建设是个持续过程。我的做法是每次发现一个badcase就把它加进评测集。半年下来评测集就成了项目的护城河。4. 实操落地从零到一搭建的完整流程4.1 环境准备与最小可运行版本第一步不是搭架构而是跑通一个最小闭环。我的建议是先写一个纯Python脚本实现读输入→组装Prompt→调模型→输出结果这条链路不引入任何框架。# 最小推理闭环示例 import time def generate(prompt, model_client, max_retries3): for attempt in range(max_retries): try: start time.time() response model_client.chat(prompt) latency time.time() - start # 记录关键指标 log_metrics(ttftresponse.ttft, latencylatency, tokensresponse.usage) return response.text except RateLimitError: time.sleep(2 ** attempt) # 指数退避 except Exception as e: if attempt max_retries - 1: raise return None这个脚本虽然简单但包含了三个关键设计重试机制、指标记录、异常分类处理。很多人的Demo里这三样都没有一上生产就抓瞎。环境准备上我建议用虚拟环境隔离依赖把模型客户端、向量库、评测工具分开管理。配置文件用YAML或环境变量别硬编码密钥和模型名。4.2 编排层的实现要点编排层是业务逻辑的核心也是最需要测试的地方。我的实现原则是把Prompt组装做成纯函数输入是结构化的上下文对象输出是最终的Prompt字符串。这样测试起来非常方便给定输入就能断言输出。上下文对象我一般设计成这样的结构class Context: system_prompt: str history: list[Message] # 历史对话 retrieved: list[Document] # 检索到的文档 user_input: str budget: TokenBudget # 各部分的token预算组装时按预算裁剪优先级是系统提示 用户输入 检索内容 历史对话。裁剪历史时从最旧的开始丢但保留第一轮通常包含关键设定。工具调用function calling也在这层处理。我的经验是工具描述要写得像给新人看的文档参数说明清楚、给例子、说明什么时候用。工具数量控制在10个以内太多模型会选错。4.3 缓存层的落地细节缓存层落地时key的设计是关键。精确缓存的key不能只用用户输入还要包含模型名、温度参数、系统提示版本。否则改了系统提示缓存还返回旧结果那就出大事了。语义缓存的实现我建议用两阶段先用向量检索找候选再用一个轻量模型或规则判断是否真的等价。纯靠向量相似度会有误判尤其是帮我查A和帮我查B这种向量可能很近但答案完全不同。前缀缓存的开启取决于推理引擎。自部署时记得把系统提示放在最前面且保持稳定这样前缀命中率才高。如果系统提示里带了时间戳之类的动态内容前缀缓存就废了。提示缓存一定要有失效机制。模型更新、知识库更新时要能批量清理相关缓存。我一般给缓存加个版本号版本变了自动失效。4.4 评测流程的自动化评测要自动化才有意义。我的做法是写一个评测脚本输入是评测集文件输出是各项指标的报表。每次代码合并前跑一遍指标下降就阻断合并。评测集格式我一般用JSONL每行一个case{id: case_001, input: ..., expected: ..., tags: [faq, chinese]}评分方式分两种有标准答案的用精确匹配或相似度没有标准答案的用模型打分LLM-as-judge但要固定打分模型和Prompt保证可比性。评测指标我重点关注这几个准确率、格式合规率、平均延迟、平均Token消耗。前两个看质量后两个看成本。四个指标一起看才能判断一次改动是提质增效还是拆东墙补西墙。5. 常见问题与排查技巧实录5.1 输出不稳定怎么办这是最高频的问题。排查思路按顺序来先看温度参数。温度大于0.7时输出波动大是正常的业务需要稳定就调到0.1到0.3。再看Prompt是否有歧义。同一个问题换个说法答案就变说明Prompt约束不够。加上明确的输出格式要求和边界条件。最后看模型本身。有些模型在特定任务上就是不稳定换模型或加few-shot示例。我的经验是80%的不稳定其实是Prompt问题不是模型问题。与其频繁换模型不如把Prompt打磨到位。5.2 延迟突然飙高怎么排查延迟问题要分段定位。我在代码里会给每个阶段打点检索耗时、Prompt组装耗时、模型推理耗时、后处理耗时。哪段涨了一眼就能看出来。常见原因和对策现象可能原因对策TTFT高但TPOT正常排队严重或前缀缓存失效扩容、检查前缀稳定性TPOT高输出太长或批处理效率低限制max_tokens、调批参数检索耗时高索引未加载或数据量涨了检查索引、加缓存整体都高下游依赖慢加超时、降级策略5.3 成本失控怎么止血成本失控通常有三个来源重复推理、超长上下文、无效重试。止血顺序先上精确缓存这是最快见效的。再检查上下文预算把不必要的历史和检索内容砍掉。最后看重试逻辑是不是失败后无脑重试导致成本翻倍。重试一定要有次数上限和退避策略。我踩过的一个坑是流式输出中途失败后重试导致用户看到重复内容。后来改成流式失败不重试直接返回错误让用户重发反而体验更好。5.4 评测指标好看但线上效果差这是典型的评测集和真实分布不一致。评测集是你自己造的真实用户的问题千奇百怪。解决办法是持续从线上采样把真实case补充进评测集。另外评测时要注意数据泄漏——如果评测集里的问题和训练数据或Prompt示例高度相似指标会虚高。我的做法是维护两个评测集一个是核心集覆盖必须做对的场景指标要求严格一个是探索集收集线上真实case指标作为参考。两个集一起看才能既保底线又看趋势。6. 我在这条路上踩过的几个坑第一个坑是过早抽象。一开始就想搞一套通用框架结果业务还没跑通框架先把自己绕进去了。后来我改成先写三遍重复代码再抽象反而清晰很多。第二个坑是忽视可观测性。早期只记了个总延迟出问题完全不知道哪慢。后来给每个环节都加了打点排查效率提升十倍不止。AI系统的可观测性比传统系统更重要因为不确定性更高。第三个坑是评测集造假。为了让指标好看专挑简单case放进评测集结果线上被真实用户教做人。评测集必须诚实宁可难看不要虚假繁荣。最后一个体会是AI工程的核心竞争力不在模型而在工程。模型大家都能用但谁能把不确定性管好、把成本控住、把质量评准谁就能做出真正能上生产的东西。这条路没有捷径但每一步都算数。
返回列表