
本文定位AI 应用性能 / 成本治理 / 高可用设计示例环境Java 21、Spring Boot 3.3、Redis、PostgreSQL、OpenTelemetry。模型价格会变化文章只讨论测量与治理方法不绑定某个供应商价格。摘要AI Demo 上线后最容易失控的两个指标是成本和延迟。Prompt 变长、检索片段增多、工具重复调用、失败重试和长历史对话都会让一次请求消耗更多 Token模型响应慢、Rerank 排队、数据库连接池耗尽又会把用户体验拖垮。本文先建立成本与延迟的测量模型再讨论上下文裁剪、缓存、批处理、流式输出、模型路由、限流、超时、熔断和降级。重点是说明优化顺序先测出钱花在哪里再决定哪些内容值得缓存或压缩避免为了追求一个理论上的低延迟而牺牲正确性和安全性。一、成本模型一次 RAG 请求成本可以拆成总成本 Embedding成本 关键词/向量检索成本 Rerank成本 模型输入Token成本 模型输出Token成本 重试成本 工具和基础设施成本很多团队只看模型输出 Token忽略了输入上下文。RAG 把 10 个大 Chunk 塞进 Prompt 后输入成本和延迟可能远高于回答本身。每次请求至少记录输入 Token、输出 Token、检索条数、Rerank 次数、重试次数和最终模型。二、延迟分解网关排队问题改写Embedding关键词/向量检索Rerank模型首Token模型完成输出校验用户感知的流式体验主要受首 Token 延迟影响但系统总耗时还包括完整输出和后处理。监控 P50、P95、P99以及首 Token、每 Token 间隔和完成时间不能只看平均响应时间。三、上下文裁剪比换模型更先做上下文应经过“过滤—排序—去重—压缩—限长”流程过滤无权限、过期和低相关文档。按 Rerank 分数、版本和来源排序。对重复或高度相似 Chunk 去重。对长文本只保留与问题相关的句子但保留引用定位。设置输入 Token 硬上限。publicListEvidencetrimContext(ListEvidenceevidence,intmaxChars){SetStringseennewHashSet();ListEvidenceresultnewArrayList();intused0;for(Evidenceitem:evidence){Stringfingerprintnormalize(item.content());if(!seen.add(fingerprint))continue;if(useditem.content().length()maxChars)break;result.add(item);useditem.content().length();}returnList.copyOf(result);}裁剪不能只按字符串长度截断。切掉条款的例外条件会导致答案错误因此最好按句子、列表项或语义单元裁剪并保留文档标题、版本和页码。四、缓存设计缓存适合稳定、重复和可安全复用的数据Embedding 结果、公开文档的检索结果、相同问题的最终答案。用户权限和知识库版本必须进入缓存键。embedding:{model}:{textHash} retrieve:{tenant}:{permissionHash}:{kbVersion}:{queryHash} answer:{tenant}:{permissionHash}:{promptVersion}:{model}:{queryHash}最终答案缓存需要注意两个问题一是用户权限可能发生变化二是文档更新后旧答案可能失效。缓存 TTL 不能代替版本失效发布新知识库版本时要主动失效相关键。对高风险问题可以只缓存检索结果不缓存最终答案。五、流式输出和取消流式输出能降低用户感知等待但不能解决模型总耗时。客户端断开后服务端需要取消模型请求和工具任务否则会出现用户看不到结果但后台仍持续消耗成本。publicFluxStringstream(PublisherAiEventevents,CancellationTokentoken){returnFlux.from(events).takeUntil(event-token.isCancelled()).map(AiEvent::safeText).doOnCancel(()-{token.cancel();audit.record(client_cancelled);});}对于有副作用的工具取消请求不一定等于取消业务动作。必须区分“停止生成文本”和“停止已经提交的业务执行”后者需要状态机和补偿策略。六、模型路由与备用模型可以按任务复杂度选择模型简单分类和查询使用低成本模型复杂总结或多步推理使用更强模型。路由规则必须可解释并记录实际命中模型。publicModelRouteroute(RequestProfileprofile){if(profile.requiresTool()profile.risk()RiskLevel.HIGH){returnModelRoute.of(quality-model,Duration.ofSeconds(30));}if(profile.inputTokens()600profile.intent()Intent.CLASSIFY){returnModelRoute.of(fast-model,Duration.ofSeconds(8));}returnModelRoute.of(balanced-model,Duration.ofSeconds(15));}备用模型切换需要注意上下文和工具兼容性。若备用模型不支持某种工具调用格式不能在超时后无条件切换。高风险场景宁可降级为“展示证据并转人工”也不要为了成功率让不兼容模型执行动作。七、限流、超时和熔断限流至少分为用户、租户、接口和模型供应商四层。对 Token 而不是只对请求数限流因为一个超长请求可能消耗几十个普通请求的资源。publicvoidcheckQuota(AuthContextauth,UsageEstimateestimate){QuotaquotaquotaService.current(auth.tenantId());if(quota.remainingTokens()estimate.inputTokens()){thrownewQuotaExceededException(超过租户Token额度);}rateLimiter.acquire(auth.tenantId(),estimate.weight());}超时要分阶段设置Embedding、检索、Rerank、模型首 Token、模型完成和工具调用分别配置。一个总超时不能替代阶段超时否则某个下游卡住后很难定位。熔断发生后降级逻辑不能让模型凭空回答。可以选择关键词检索、返回已确认的缓存结果、提交异步任务或转人工。八、重试会放大成本只对明确的临时错误重试并设置最大次数和指数退避。重试请求要带相同幂等键特别是涉及工具调用时。每次重试增加的 Token 和供应商费用都要进入成本统计。错误是否通常重试说明认证失败否修复配置或权限参数校验失败否修改输入429 限流有条件按 Retry-After 退避网络超时有条件限次、幂等供应商 5xx有条件备用模型或降级引用校验失败最多一次第二次失败转人工无限重试既可能制造账单也可能造成工具重复执行。九、成本报表按天、租户、应用、模型、工作流和用户群统计请求数、输入输出 Token、平均成本、P95 延迟、失败率、重试率和人工转接率。成本报表要能回答“钱花在什么场景、哪个版本、哪个租户、哪类问题”。高成本请求要保存原因标签例如上下文过长、工具轮次过多、重复提问、超时重试或模型路由错误。没有原因标签成本优化只能靠猜。十、上线检查是否记录输入输出 Token 和每阶段耗时。缓存键是否包含租户、权限和知识库版本。客户端断开后是否取消可取消的后台请求。工具调用是否使用幂等键。是否按阶段设置超时和限流。备用模型是否支持相同的输出和工具协议。熔断后是否有安全降级而非无依据回答。是否有租户级成本预算和告警。十一、一次可复现的性能实验建议建立三个固定场景短问题、长上下文问题和需要工具调用的问题。每个场景分别用 1、5、20、50 并发运行预热后重复多轮记录首 Token、完整耗时、输入输出 Token、错误率、重试次数和峰值显存或连接数。不要只跑一次因为网络抖动和供应商排队会影响结果。实验报告中至少包含代码提交号、模型与 Prompt 版本、知识库版本、缓存状态、测试机器、并发、样本数量和统计方式。P95 应说明是对所有请求统计还是只统计成功请求失败请求不能被简单剔除否则结果会过于乐观。还可以做一个“上下文裁剪前后”的对照保持模型和问题集不变只改变证据条数与去重策略再比较引用准确率、输入 Token 和延迟。如果质量没有下降而成本明显降低才说明裁剪真正有效。十二、预算与配额成本治理最好有租户级预算、应用级预算和单请求硬上限。预算接近阈值时可以降低非关键场景的模型级别或暂停批量任务高风险业务则应转人工而不是悄悄降低质量。所有预算拒绝和降级都要对用户给出明确提示并在审计中记录。十三、总结性能和成本优化的第一步是测量不是换模型。先把 Token、检索候选、Rerank、模型首 Token、完成时间、重试和工具轮次记录下来再针对最昂贵、最慢或最容易失败的阶段优化。一个成熟的 AI 系统应该在“质量、成本、延迟、可靠性”之间做明确取舍普通问题追求快和便宜高风险问题追求可验证和可追责所有降级都必须保留安全边界。读者讨论如果你的 AI 应用费用突然上升建议先按“输入 Token、重试次数、上下文条数、工具轮次”四项拆账通常很快能定位主因。