1. 接大模型 API 前先把这几个坑想明白大模型 API 接入这件事看起来就是拿个 Key、拼个请求、解析个 JSON 返回三行代码跑通 Demo 的事。但我见过太多项目Demo 阶段顺风顺水一上生产环境就各种翻车429 限流把服务打挂、Key 泄露被人刷爆额度、缓存策略没设计好导致重复计费、上下文长度超限直接报错、错误码看不懂排查半天。这些问题不是会不会遇到而是什么时候遇到。我自己从最早接 OpenAI 到现在对接过智谱、DeepSeek、通义、Kimi 等一堆国内外模型服务踩过的坑基本能凑齐一本错题集。这篇文章不讲大模型原理也不讲怎么调 Prompt就聚焦一件事当你准备把大模型 API 接入到真实业务系统时有哪些坑必须提前知道以及怎么绕过去。适合正在做 AI 应用开发的后端、全栈、独立开发者也适合技术负责人做方案评审时对照检查。核心关键词就几个大模型 API、429 限流、Key 管理、缓存策略、上下文长度。下面按我实际踩坑的顺序一个一个拆开讲。2. 坑一429 限流不是偶尔抽风是架构问题2.1 429 到底在说什么429 Too Many Requests这个状态码字面意思是请求太多了。但很多人第一次遇到时的反应是我明明没发几个请求啊这里有个认知差429 的判定维度不只是 QPS还包括 TPM每分钟 Token 数、RPM每分钟请求数、并发连接数甚至是日累计额度。不同厂商的限流策略差异很大。有的按账号维度限有的按 Key 维度限有的按模型维度限。你同一个账号下开了三个 Key 给三个服务用可能三个服务加起来触发的是同一个账号的总限额。我遇到过最坑的一次是测试环境用同一个 Key 跑压测把生产环境的额度一起打满了线上直接 429 雪崩。提示接入前第一件事去翻厂商的限流文档把 RPM、TPM、并发数三个指标抄下来写进你的容量规划表。别等出事再查。2.2 重试策略写不对等于火上浇油看到 429 就无脑重试是最常见的错误。你想想服务端已经在说你请求太多了你还立刻再发一次这不是添乱吗更糟的是有些 SDK 默认带自动重试指数退避没配好瞬间打出重试风暴。正确的做法是指数退避 抖动Jitter。基础等待时间从 1 秒开始每次翻倍加上一个随机抖动避免多个客户端同时重试。伪代码大概是这样import random import time def call_with_retry(func, max_retries5): for attempt in range(max_retries): try: return func() except RateLimitError: if attempt max_retries - 1: raise base 2 ** attempt jitter random.uniform(0, base * 0.5) time.sleep(base jitter)关键点在于jitter。如果十个客户端都在第 1 秒、第 2 秒、第 4 秒同时重试那服务端看到的还是脉冲式流量。加了随机抖动重试请求就被打散了。2.3 限流要从架构层面解决重试只是兜底真正的解法是在客户端做主动限流。我常用的方案是令牌桶Token Bucket本地维护一个桶按厂商给的 RPM 上限往里放令牌每次请求前先取令牌取不到就排队等待。这样从源头就不会超发。如果你用的是多实例部署本地令牌桶就不够了得用 Redis 做分布式限流。用 Redis 的INCREXPIRE实现一个滑动窗口计数器或者直接用 Redis 的 Lua 脚本做原子操作。这块代码网上一搜一大把核心是保证计数和判断是原子的。还有一个容易被忽略的点区分可重试和不可重试的错误。429 可以重试但 400参数错误、401认证失败、403权限不足重试一万次也没用只会浪费额度。我见过有人把所有非 200 都塞进重试队列结果一个 Key 失效的请求被重试了几百次日志刷屏还烧钱。3. 坑二Key 管理混乱迟早出大事3.1 Key 硬编码是原罪api_key sk-xxxxxxxx直接写在代码里然后提交到 Git 仓库——这是新手最常犯的错也是后果最严重的。公开仓库里的 Key 会被爬虫在几分钟内扫到然后你的额度就被薅光了。我有个朋友的项目就因为这事一晚上被刷掉几百块。正确的做法是环境变量 密钥管理服务。本地开发用.env文件并且把.env加进.gitignore。生产环境用云厂商的密钥管理服务比如 AWS Secrets Manager、阿里云 KMS或者至少用容器编排平台的 Secret 机制。代码里只读环境变量永远不出现明文 Key。import os api_key os.environ.get(LLM_API_KEY) if not api_key: raise RuntimeError(LLM_API_KEY not set)3.2 一个 Key 打天下风险集中很多团队图省事所有服务共用一个 Key。这有几个问题一是限流额度共享一个服务跑批把额度打满其他服务全挂二是出问题无法定位是哪个服务干的三是 Key 一旦泄露影响面是全部业务。我的建议是按服务、按环境拆分 Key。生产环境一个、测试环境一个、每个独立服务各一个。这样既能独立限流又能通过 Key 快速定位问题来源。如果厂商支持再给每个 Key 设置独立的额度上限和告警阈值。3.3 Key 轮换和失效处理Key 不是设一次就完事。定期轮换比如每 90 天是安全基线。但轮换时要注意新旧 Key 要有重叠期不能一刀切。我见过有人直接删旧 Key 建新 Key结果正在运行的服务瞬间全部 401。更麻烦的是 Key 失效的检测。如果 Key 被厂商封了或者过期了你的服务会一直报 401。这时候需要一个健康检查机制定时用最小成本的请求比如一个 1 token 的调用探测 Key 是否有效失效了立刻告警。注意有些厂商的免费额度 Key 和付费 Key 是分开的免费 Key 限流更严。别拿免费 Key 去跑生产流量429 会让你怀疑人生。3.4 关于统一 Key 通道的思考市面上有些方案号称能统一 Key 通道把多个厂商的 Key 聚合成一个入口。这确实能简化调用但也有代价多了一层中间商延迟增加、故障点增加、计费不透明。我的看法是如果只是个人项目图方便可以用但企业级应用最好直连厂商 API把 Key 管理做成自己可控的基础设施。毕竟你的业务数据经过第三方通道合规和隐私都是问题。4. 坑三缓存没设计好钱白花还慢4.1 大模型调用为什么需要缓存大模型 API 是按 Token 计费的而且响应延迟通常在秒级。如果你的业务里有大量重复或相似的请求不缓存就是纯烧钱。最典型的场景是用户问同样的问题、系统做批量分类、RAG 检索到相同的上下文。缓存能解决两个问题省钱和提速。命中缓存的请求直接返回既不计费也不等待。我做过一个统计某客服问答场景下Top 100 的高频问题占了总请求量的 40% 以上这部分全缓存下来成本直接砍掉近一半。4.2 缓存 Key 怎么设计缓存的核心是 Key 的设计。大模型请求的缓存 Key 不能只用用户输入因为同样的输入在不同参数下结果不同。完整的 Key 应该包含模型名 温度参数 系统提示词 用户输入 其他影响输出的参数。import hashlib import json def build_cache_key(model, messages, temperature, max_tokens): payload { model: model, messages: messages, temperature: temperature, max_tokens: max_tokens, } raw json.dumps(payload, sort_keysTrue, ensure_asciiFalse) return llm: hashlib.sha256(raw.encode()).hexdigest()注意sort_keysTrue保证字典序列化顺序一致否则同样的内容会生成不同的 Key。还有ensure_asciiFalse中文内容不要转义减少 Key 长度。4.3 温度参数决定能不能缓存这里有个关键判断temperature 大于 0 的请求严格来说不应该缓存。因为同样的输入模型每次输出都可能不同。如果你缓存了 temperature0.7 的结果用户第二次问同样的问题得到一模一样的回答体验会很怪。所以缓存策略要分场景temperature0 的场景分类、抽取、翻译放心缓存结果确定。temperature0 的场景创作、对话谨慎缓存或者只缓存很短时间或者干脆不缓存。我一般的做法是给缓存加一个开关按业务场景配置。分类任务缓存 24 小时对话任务缓存 5 分钟或者不缓存。4.4 缓存的坑失效和穿透缓存失效策略要提前想清楚。大模型输出不像数据库记录会更新它基本是一次生成永久有效除非模型升级。所以 TTL 可以设得比较长。但要注意模型版本变化厂商悄悄升级了模型你的缓存还是旧模型的输出可能就不准了。所以缓存 Key 里最好带上模型版本号。缓存穿透是另一个问题如果大量请求的 Key 都不存在每个都打到 API缓存就形同虚设。这种情况要么做布隆过滤器预判要么对空结果也做短期缓存。提示别用 Redis 存大模型的完整响应如果响应很长。一个响应几千 token存几万条 Redis 内存就爆了。可以考虑只缓存高频短响应长响应走对象存储。5. 坑四上下文长度不是越大越好5.1 上下文超限的报错长什么样不同厂商的报错不一样但核心都是token 数超了。有的返回 400 加一句maximum context length exceeded有的直接截断不报错更坑你都不知道内容被砍了。我遇到过最迷惑的是返回一个空字符串排查半天才发现是上下文超了。上下文长度包括输入 输出。很多人只算输入忘了给输出留空间。比如模型上限 8K你输入塞了 7900 token输出最多只能生成 100 token稍微长一点的回答就被截断了。5.2 Token 怎么估算精确计算要用厂商的 tokenizer但不同模型的分词方式不同同一个文本在不同模型下的 token 数可能差 20% 以上。工程上一般用估算英文约 4 个字符 1 token中文约 1.5 到 2 个字符 1 token。def estimate_tokens(text): # 粗略估算中文按 1.5 字符/token英文按 4 字符/token chinese_chars sum(1 for c in text if \u4e00 c \u9fff) other_chars len(text) - chinese_chars return int(chinese_chars / 1.5 other_chars / 4)这个估算误差在 10% 到 20%做容量规划够用但做精确截断就不行。如果业务对精度要求高还是得引入对应模型的 tokenizer 库。5.3 长上下文的成本陷阱现在很多模型支持 128K 甚至更长的上下文看起来很美好但有两个坑第一是成本。Token 计费是按量算的你塞 100K token 进去费用是 1K token 的 100 倍。而且很多厂商对超长上下文有额外溢价。我见过有人把整个知识库塞进上下文做 RAG一次请求几毛钱量一大账单就失控了。第二是效果。长上下文不等于模型能有效利用所有信息。业界有个说法叫lost in the middle模型对上下文开头和结尾的信息记得牢中间部分容易忽略。所以塞得越多不一定答得越准。我的建议是能用 RAG 检索就不要硬塞上下文。把相关知识检索出来只放最相关的几段既省钱又准。上下文长度控制在模型上限的 60% 到 70%给输出留足空间。5.4 上下文截断策略如果输入实在超了得有截断策略。常见的有从头截断保留最新的对话丢掉最早的。适合多轮对话。从中间截断保留开头系统提示和结尾最新问题丢掉中间。适合长文档问答。摘要压缩把早期对话用模型总结成一段话替换原始内容。成本高但效果好。我一般用第二种因为系统提示词通常在开头丢了会改变模型行为。6. 坑五错误处理决定你的服务能不能扛住6.1 大模型 API 的错误分类大模型 API 的错误码比普通 REST API 复杂因为多了模型层面的问题。我把它分成几类错误类型典型状态码是否可重试处理策略限流429是指数退避重试认证失败401否检查 Key告警权限不足403否检查账号权限参数错误400否检查请求体上下文超限400否截断后重试服务端错误500/502/503是退避重试超时-是重试或降级内容审核拦截400否记录并返回用户这张表建议直接抄进你的错误处理代码里。核心原则可重试的错误才重试不可重试的错误快速失败并告警。6.2 超时设置的门道大模型响应慢是常态尤其是长文本生成。超时设太短正常请求被误杀设太长故障时请求堆积。我的经验值是连接超时 10 秒读取超时按预期输出长度动态设置。短回答 30 秒长文本生成 120 秒甚至更长。流式响应streaming能缓解超时问题因为数据是边生成边返回的只要第一个 token 及时到达后续可以慢慢等。如果你的场景允许尽量用流式。6.3 降级方案必须有大模型服务不是 100% 可用的。厂商会维护、会故障、会限流。你的系统必须有降级方案多厂商备份主用一家备用一家主挂了切备用。但要注意不同厂商的 API 格式不同得做适配层。缓存兜底API 挂了返回缓存的历史结果。规则兜底实在不行返回预设的模板回答。我见过一个线上事故某应用强依赖单一模型 API厂商故障两小时整个应用不可用。如果有降级方案至少能保证核心功能可用。6.4 日志和监控大模型调用的日志要记全请求 ID、模型名、输入 token 数、输出 token 数、耗时、状态码、错误信息。这些数据是排查问题和成本分析的基础。监控要盯几个指标成功率、P95 延迟、429 比例、Token 消耗速率、成本。429 比例突然升高说明限流了Token 消耗异常可能是被刷了或者有 bug 导致重复调用。提示给成本设告警阈值。我见过有人测试代码写错循环调用 API一晚上烧了几千块。有告警至少能及时发现。7. 一些实操中的零碎经验7.1 关于免费额度和免费 API网上有很多免费大模型 API的分享我的建议是个人学习可以用生产环境别碰。免费额度通常限流极严、稳定性没保障、随时可能停服。而且很多所谓免费 API来源不明把业务数据发过去有隐私风险。如果预算有限可以关注厂商的免费额度政策很多厂商对新用户有赠送额度对特定模型有免费调用。但要把这些当成临时补贴不能作为长期方案。7.2 关于 SDK 选择官方 SDK 通常最稳但不同厂商的 SDK 风格差异大切换成本高。如果项目要对接多家建议用 OpenAI 兼容格式的 SDK现在大部分厂商都支持 OpenAI 兼容接口或者自己封装一层适配层。这样换厂商时只改配置不改业务代码。7.3 关于并发控制大模型 API 的并发能力有限别用高并发去压。我一般用信号量Semaphore控制并发数或者用队列串行化。Python 里asyncio.Semaphore就很好用import asyncio sem asyncio.Semaphore(5) # 最多 5 个并发 async def call_llm(prompt): async with sem: return await client.chat(prompt)并发数设多少取决于厂商的限流和你的业务容忍度。一般从 3 到 5 开始试观察 429 比例再调整。7.4 关于 Prompt 缓存有些厂商支持 Prompt 缓存比如把系统提示词缓存起来重复使用不计费或打折。如果你的系统提示词很长且固定一定要用这个功能能省不少钱。接入前问清楚厂商是否支持怎么开启。7.5 关于数据安全发给大模型的数据等于交给了第三方。敏感数据用户隐私、商业机密要么脱敏后再发要么用私有化部署的模型。企业级应用尤其要注意这点合规部门会盯着。8. 常见问题速查Q429 一直重试还是失败怎么办A检查是不是账号级限流多个服务共用 Key 会互相影响。降低并发拉长重试间隔必要时申请提额。QKey 明明是对的为什么报 401A检查 Key 有没有多余空格、有没有过期、账号有没有欠费、请求头格式对不对。有些厂商要求Bearer前缀有些不要。Q缓存命中率很低怎么办A检查缓存 Key 设计是不是把随机参数如时间戳、请求 ID也放进去了。温度参数大于 0 的请求本身就不适合缓存。Q上下文超限但不想截断怎么办A用 RAG 检索最相关的内容或者用摘要压缩历史对话。实在不行换支持更长上下文的模型。Q响应太慢怎么优化A用流式响应让用户先看到部分结果。或者用更小的模型处理简单任务大模型只处理复杂任务。Q怎么估算成本A统计平均输入输出 token 数乘以单价再乘以预估调用量。记得把重试和失败的调用也算进去。9. 最后几句掏心窝的话接大模型 API 这件事技术门槛不高但工程细节特别多。我见过太多项目在 Demo 阶段惊艳上线后因为限流、Key 泄露、缓存设计不当这些问题翻车。这些坑的共同点是它们都不是模型能力问题而是工程问题。我的建议是在写第一行业务代码之前先把限流、Key 管理、缓存、错误处理这四件事的框架搭好。哪怕先用最简单的实现也比事后补救强。因为这些问题一旦在生产环境爆发排查成本远高于提前设计。还有一点别迷信任何一家厂商。大模型服务这个领域变化太快今天最好的明天可能就落后了。把适配层做好保持切换能力才是长期主义。我自己现在的做法是所有大模型调用都走一层自研的网关统一处理限流、重试、缓存、日志、降级。业务代码只调网关不直接碰厂商 API。这样换厂商、加厂商、调策略都只改网关一处。这套东西搭起来花了两天但后面省的心力值回票价。
阅读完成 · 觉得有帮助?