先说明一下:标题提到的GPT-3.5/ChatGPT在本文写作时(2022年1月)尚未正式发布,目前OpenAI最新的是GPT-3系列(Davinci、Curie等)和Codex。本文基于GPT-3 API的实际使用经验,分享大语言模型API的性能优化技巧。这些技巧也适用于未来的GPT-3.5和ChatGPT API,原理是相通的。

大语言模型API(比如GPT-3)功能强大,但有一个痛点:慢。一个复杂的请求可能要等十几秒甚至几十秒,用户体验很差。而且API按token收费,调用成本也不低。

我做过几个基于GPT-3的应用,从一开始的"慢到想放弃",到后来的"秒级响应",踩了不少坑,也总结了一些优化经验。今天分享这些性能优化技巧,包括Prompt优化、参数调优、缓存、流式输出、并发控制、成本控制等。帮你把API调用从慢优化到快,同时省钱。

一、性能优化的核心思路

在讲具体技巧之前,先说说性能优化的核心思路。

GPT API的响应时间,主要由两部分组成:

  1. 首token延迟(TTFT):从发出请求到收到第一个token的时间
  2. 生成速度:每个后续token的生成时间,一般是几十毫秒一个token

总响应时间 = TTFT + 生成token数 × 每个token时间

所以优化方向就是:

  • 减少TTFT(让模型更快开始输出)
  • 减少生成的token数(让输出更短)
  • 提高生成速度(用更快的模型、流式输出)
  • 避免重复调用(缓存、预生成)

成本方面,API按输入+输出的token总数收费,所以减少token数也能省钱。

二、Prompt优化

Prompt是影响性能和成本的关键因素。Prompt越长,输入token越多,TTFT越长,费用越高。

1. 精简Prompt

很多人写Prompt喜欢写很长,加很多背景说明、示例、规则。但其实很多内容是多余的。精简Prompt,只保留必要的信息,能显著减少输入token。

比如,原来的Prompt:

你是一个有10年经验的资深前端工程师,精通Vue、React、JavaScript、CSS、HTML等各种前端技术。
请回答以下问题,要求:
1. 回答要准确
2. 回答要简洁
3. 用中文回答
4. 分点说明
5. ...(一堆规则)

问题:...

精简后:

你是资深前端工程师,请简洁回答以下问题(中文,分点说明):
问题:...

效果差不多,但token数少了很多。

2. 用更短的示例

如果用Few-shot(给示例),示例要尽量短。不要给太长的示例,每个示例尽量控制在几十token以内。

如果示例很长,可以考虑用Embedding做检索,只取最相关的几个示例,而不是把所有示例都放进去。

3. 明确输出格式和长度

在Prompt里明确要求输出长度,比如"不超过100字""用3点说明""只返回JSON"。这样模型不会输出多余的内容,减少输出token。

比如做摘要,明确说"用50字总结",比说"总结一下"输出短很多。

4. 用结构化输出

要求模型输出JSON、XML等结构化格式,方便解析,也能减少多余的文字。比如:

请以JSON格式返回,包含name和age两个字段,不要输出其他内容。

这样模型不会输出"好的,以下是JSON:"之类的多余文字。

三、参数调优

API的参数也会影响性能和效果。

1. 选择合适的模型

OpenAI有多个模型,性能和速度差别很大:

  • Davinci:最强,但最慢最贵
  • Curie:中等,速度和能力均衡
  • Babbage:较快,能力一般
  • Ada:最快最便宜,适合简单任务

不是所有任务都需要Davinci。简单的分类、提取、格式转换,用Curie甚至Ada就够了,速度快好几倍,价格便宜很多。

建议:先从最便宜的模型开始试,效果不够再升级。很多任务Curie的效果和Davinci差不多,但快很多。

2. max_tokens设置合理

max_tokens限制输出的最大长度。设置太大,模型可能输出多余内容,也会增加响应时间。设置太小,可能输出被截断。

根据任务需要设置合理的maxtokens。比如做分类,输出一个标签,maxtokens设10就够了。做摘要,设200-500。不要默认设2048,浪费时间和钱。

3. temperature和top_p

temperature控制随机性。temperature低(0-0.3),输出更确定,可能更快(因为模型不用"纠结"选哪个token)。temperature高,输出更多样,但可能更慢。

对于确定性任务(分类、提取、格式化),用低temperature。对于创意任务(写文章、头脑风暴),用高temperature。

top_p类似,用默认的1就行,一般不用调。

4. stop序列

用stop参数指定停止序列,模型遇到这些序列就停止输出。比如输出JSON后,模型可能继续输出解释,用stop=["\n\n"]或者stop=["```"]可以让它及时停止,减少多余输出。

四、缓存策略

缓存是性能优化最有效的手段之一。相同的请求,不要重复调用API。

1. 完全相同的请求缓存

如果用户的请求完全相同(比如常见问题),直接返回缓存的结果,不用调用API。用Redis或者本地缓存,key是Prompt的hash,value是API返回结果。

缓存时间根据任务设置,事实性内容可以缓存久一点,时效性内容缓存短一点。

2. 相似请求缓存

对于相似的请求,可以用Embedding计算相似度,如果相似度超过阈值,返回缓存的结果(或者基于缓存结果做微调)。这样能减少很多重复调用。

比如客服场景,用户问的问题经常是重复的,用相似度匹配,大部分问题都能命中缓存。

3. 预生成

对于可以预见的请求,提前生成好结果缓存起来。比如产品介绍、常见问题解答,提前用API生成好,用户请求时直接返回,零延迟。

4. 缓存注意事项

  • 缓存要设置过期时间,避免内容过时
  • 缓存的key要包含所有影响输出的参数(模型、temperature、max_tokens等)
  • 注意隐私,不要缓存敏感信息

五、流式输出

流式输出(stream=true)是提升用户体验的重要手段。

不用流式输出时,用户要等整个响应生成完才能看到内容,可能要等十几秒。用流式输出,API会一个token一个token地返回,用户能看到内容逐字出现,感觉上快很多。

虽然总时间没变,但用户感知的等待时间大大缩短。就像看视频,边下边播比下完再看体验好很多。

实现流式输出:

  • 调用API时设置stream=true
  • API返回Server-Sent Events(SSE)格式
  • 前端用EventSource或者fetch读取流,逐字显示

几乎所有的GPT应用都应该用流式输出,尤其是长文本生成场景。

六、并发和异步

1. 异步调用

如果一个任务需要多次调用API,而且这些调用之间没有依赖,用异步并发调用,而不是串行。

比如要总结10篇文章,串行调用要10次的时间,并发调用只要1次的时间(受限于API的速率限制)。

用Python的asyncio + aiohttp,或者JavaScript的Promise.all,都能实现并发。

2. 注意速率限制

OpenAI API有速率限制( RPM:每分钟请求数,TPM:每分钟token数)。并发太高会被限流,返回429错误。

要做限流控制:

  • 用令牌桶或者滑动窗口算法控制请求速率
  • 遇到429错误,用指数退避重试
  • 如果需要更高的速率限制,可以申请提升,或者用多个API key轮询

3. 批处理

如果有大量离线任务(比如批量处理数据),可以用批处理。把多个请求合并,或者用异步队列慢慢处理,不影响用户体验。

OpenAI也提供了批量处理的功能(目前在beta阶段),适合非实时的大批量任务,价格更便宜。

七、架构优化

除了API本身的优化,应用架构也很重要。

1. 前后端分离

前端不要直接调用OpenAI API(会暴露API key),通过后端代理。后端可以做缓存、限流、日志、错误处理。

2. 队列削峰

如果请求量波动大,用消息队列削峰。用户请求先入队,后台worker慢慢处理,处理完再通知用户。避免高峰期API被打爆。

3. 降级策略

API可能会超时、报错、限流。要有降级策略:

  • 超时:返回缓存的结果,或者提示用户稍后再试
  • 报错:重试几次,还是失败就降级到简单的规则处理
  • 限流:排队等待,或者用备用模型

不要让API故障导致整个应用不可用。

4. 监控和日志

记录每次API调用的参数、响应时间、token数、费用。监控响应时间和错误率,发现性能问题及时优化。

可以用Prometheus+Grafana做监控,或者用第三方的LLM监控工具(比如Helicone、Portkey)。

八、成本优化

性能优化的同时,也要关注成本。GPT API不便宜,优化好了能省很多钱。

1. 用便宜的模型

前面说过,不是所有任务都需要Davinci。用Curie或Ada,价格是Davinci的1/10甚至1/100。

2. 减少token

  • 精简Prompt
  • 限制输出长度
  • 用缓存避免重复调用
  • 用Embedding检索相关示例,而不是把所有示例都放Prompt里

3. 批量处理

批量处理任务可以用更便宜的批量API,或者在流量低谷时处理,不影响实时响应。

4. 成本监控

设置预算告警,超过预算及时通知。分析每个功能的API成本,优化成本高的功能。

九、实际案例分享

分享一个我做过的优化案例。

场景: 一个智能客服系统,用户提问,用GPT-3生成回答。

优化前:

  • 用Davinci模型,Prompt很长(500+ token,包含所有知识库和示例)
  • max_tokens设500,不用流式输出
  • 没有缓存,每次都调用API
  • 平均响应时间15秒,用户经常等不及
  • 每月API费用很高

优化后:

  1. 用Embedding做知识库检索,Prompt只放最相关的3条,输入token降到200
  2. 模型换成Curie,效果差不多,速度快3倍
  3. max_tokens设200,明确要求简洁回答
  4. 加了Redis缓存,常见问题直接返回,缓存命中率60%
  5. 用流式输出,用户看到逐字回答
  6. 加了降级和重试,API故障时返回预设答案

结果:

  • 平均响应时间降到3秒(缓存命中时<100ms)
  • API费用降低70%
  • 用户满意度大幅提升

这个案例说明,综合运用多种优化手段,能带来质的提升。

十、写在最后

大语言模型API的性能优化,是一个系统工程。从Prompt到参数,从缓存到架构,每个环节都有优化空间。

总结最重要的几点:

  1. 精简Prompt,减少token
  2. 选合适的模型,不要盲目用最强的
  3. 用缓存,避免重复调用
  4. 用流式输出,提升用户体验
  5. 并发异步,提高吞吐量
  6. 做好降级和监控,保证稳定性
  7. 关注成本,用最少的钱办最多的事

2022年了,大语言模型还在快速发展,未来的模型会更快、更便宜、更强大。但优化的思路是相通的,掌握了这些方法,不管用什么模型都能做好性能优化。

希望这篇文章能帮你把GPT应用从慢优化到快,同时省钱。如果你有其他优化技巧,欢迎在评论区交流。

最后,提醒一句:AI应用的核心是用户体验,性能是体验的基础。不要只看模型能力,忽略了响应速度。再聪明的回答,让用户等30秒,体验也是差的。

祝大家都能做出又快又好的AI应用。