1. 从“能跑通”到“能讲清”:大模型调用背后的认知断层
我见过太多简历上写着“熟悉大模型应用开发”的人,面试时让他们讲讲一次完整的推理请求到底经历了什么,能说清楚的人不到三成。大多数人能熟练地写出client.chat.completions.create(...),能对着文档把参数一个个填进去,但一旦问“temperature 和 top_p 同时设置时到底谁说了算”“为什么同样的 prompt 两次返回结果差异巨大”“流式输出在服务端到底是怎么拼出来的”,就开始含糊其辞。
这不是个别现象,而是整个行业快速膨胀期的典型症状。大模型 API 的封装做得太好了,好到把底下所有复杂性都藏了起来。你调用一个函数,传进去一段文字,几秒钟后拿到一段回复,整个过程像魔法一样。但工程不是魔法,工程是把魔法拆解成可理解、可控制、可优化的模块。会调 API 的人很多,因为门槛确实低;懂原理的人极少,因为愿意往下钻的人少。
这篇手记想做的事情很具体:把一次大模型 API 调用从你按下回车到拿到结果之间发生的所有关键环节,一层层剥开。不是讲论文里的 Transformer 架构,也不是讲怎么训练模型,而是讲推理服务这条链路上,一个应用开发者必须理解的工程原理。理解这些之后,你写出来的代码质量、排查问题的速度、优化成本的能力,会和只会调 API 的人拉开明显差距。
适合读这篇内容的人:已经用过大模型 API 做过至少一个完整项目,但总觉得“知其然不知其所以然”的开发者;正在做 AI 应用架构设计,需要判断哪些环节可以优化、哪些参数不能乱动的技术负责人;以及那些面试时被追问“为什么”就卡壳、想补上这块认知短板的人。
2. 一次推理请求的完整生命周期:从你的代码到模型的输出
2.1 请求发出之前:Tokenization 决定了你真正发送了什么
很多人以为发给模型的就是自己写的那段文字。不是的。你写的文字在离开你的进程之前,已经被切成了 token。这个过程叫 tokenization,是大模型推理链路里第一个被严重低估的环节。
Token 不是字,不是词,也不是字节。它是介于字符和单词之间的一种子词单元。英文里 “unbelievable” 可能被切成 “un”“believ”“able” 三个 token;中文里 “人工智能” 可能是两个 token,也可能是一个,取决于模型用的分词器。不同模型家族用的分词方案不一样,同一个句子在不同模型里 token 数量可能差出百分之二三十。
这件事为什么重要?因为计费按 token 算,上下文窗口按 token 算,推理速度也按 token 算。你觉得自己只写了五百字,实际可能是一千二百个 token。你觉得自己离上下文上限还有距离,实际可能已经快撑满了。我见过一个团队做长文档摘要,本地测试时用英文文档跑得好好的,上线换成中文文档后频繁触发长度截断,排查了半天才发现是中文 token 密度和英文差异太大,同样的字数中文消耗的 token 多得多。
更隐蔽的是,tokenization 还会影响模型对内容的理解。有些特殊字符、罕见符号、混合语言片段,在分词时会被切得支离破碎,模型看到的和你以为它看到的完全不是一回事。比如你在 prompt 里写了一个复杂的 JSON 结构,里面嵌套了好几层,如果分词器把某些键名切成了奇怪的片段,模型解析起来就容易出错。这不是模型笨,是你喂给它的东西在第一步就已经变形了。
实操建议:在正式接入之前,先用对应模型的分词工具跑一遍你的典型输入,看看实际 token 数是多少,看看有没有被切得很奇怪的片段。这个习惯能帮你避开很多莫名其妙的“模型不听话”问题。
2.2 请求到达服务端之后:批处理与调度的隐形等待
你的 HTTP 请求到达推理服务端之后,并不会立刻被送进模型。服务端要做的事情比你想象的多。
首先是请求排队。推理服务通常不是来一个请求就立刻处理一个,而是攒一批一起处理,这叫批处理(batching)。批处理能大幅提升 GPU 利用率,因为 GPU 最擅长的就是并行计算。但代价是,如果你的请求恰好在一个批次刚满之后到达,就得等下一批攒够。这个等待时间可能很短,也可能很长,取决于当前服务的负载情况。
然后是显存分配。模型权重是常驻显存的,但每次推理还需要额外的显存来存放中间计算结果。如果当前显存不够,服务端要么等,要么把请求排到后面。这就是为什么高峰期 API 响应会变慢——不是模型变慢了,是排队和资源调度变慢了。
还有一个容易被忽略的环节:请求预处理。服务端收到你的请求后,要解析 JSON、校验参数、拼接对话模板、应用系统提示词、处理特殊 token 等等。这些操作本身不慢,但在高并发场景下会累积成可观的延迟。
理解这一层的意义在于:当你发现 API 响应时间波动很大时,不要第一反应就是“模型不稳定”。先看看是不是服务端负载问题,是不是你的请求恰好撞上了高峰期。很多所谓的“性能问题”,其实是调度问题。
2.3 模型真正开始计算:自回归生成与 KV Cache
终于到了模型计算这一步。大模型生成文本的方式是自回归的:一次生成一个 token,然后把新生成的 token 追加到输入后面,再生成下一个,如此循环。
这意味着生成一百个 token 的回复,模型要跑一百次前向计算。每次计算都要处理之前所有的 token。如果每次都从头算,计算量会随长度平方增长,根本跑不动。所以有了 KV Cache 这个关键技术。
KV Cache 的思路是:把之前计算过的注意力键值对缓存起来,生成新 token 时只计算新 token 的注意力,然后和缓存拼接。这样每次前向计算只需要处理一个新 token,计算量从平方级降到了线性级。
但 KV Cache 是有代价的。它占显存,而且占得不少。上下文越长,KV Cache 越大。这就是为什么长上下文推理又慢又贵——不只是输入 token 多,还因为 KV Cache 把显存吃掉了,能同时处理的请求数就少了。
还有一个细节:KV Cache 在流式输出时特别关键。你看到文字一个个蹦出来,背后就是模型每生成一个 token 就立刻返回一个,同时把新的 KV 对追加到缓存里。如果服务端不支持 KV Cache 复用,流式输出的延迟会高得没法用。
2.4 采样策略:为什么同样的输入会有不同的输出
模型计算出来的是一组概率分布,表示下一个 token 可能是什么。从这组概率到最终选出的那个 token,中间隔着一个采样策略。
最常见的采样参数是 temperature 和 top_p。Temperature 控制概率分布的平滑程度:温度越低,高概率 token 的优势越大,输出越确定;温度越高,低概率 token 也有机会被选中,输出越多样。Top_p 则是另一种思路:只从累积概率达到 p 的那部分 token 里采样,把长尾直接砍掉。
这两个参数同时设置时,通常是先应用 temperature 调整分布,再应用 top_p 截断。但具体实现顺序不同框架可能有差异,这就是为什么有时候你调了参数感觉“没生效”——可能被另一个参数覆盖了。
还有一个容易被忽略的参数是 top_k,它直接限制只从概率最高的 k 个 token 里选。Top_k 和 top_p 的区别在于:top_k 是固定数量,top_p 是动态数量。有些场景下 top_k 更稳定,有些场景下 top_p 更灵活。
理解采样策略的意义在于:你能解释为什么同一个 prompt 两次调用结果不一样,能根据场景选择合适的参数组合,而不是盲目地把 temperature 设成 0 就以为能获得确定性输出。实际上 temperature 设成 0 也不保证完全确定,因为底层还有浮点数精度、并行计算顺序等不确定因素。
3. 参数背后的工程含义:那些文档里不会写清楚的取舍
3.1 Temperature 与 Top_p 的配合逻辑:不是调了就有用
很多开发者对 temperature 的理解停留在“越高越有创意,越低越稳定”。这个理解不算错,但太粗糙了。Temperature 的本质是调整 logits 的缩放系数:温度 T 会把原始 logits 除以 T,然后做 softmax。T 小于 1 时,分布变得更尖锐,高概率 token 更高概率被选中;T 大于 1 时,分布变得更平坦,低概率 token 也有机会。
但 temperature 有一个问题:它是对所有 token 一视同仁地缩放。如果模型本身对某个位置非常确定,温度再高也很难让它选别的;如果模型本身很犹豫,温度稍微一调输出就天差地别。这就是为什么单纯调 temperature 有时候感觉“不跟手”。
Top_p 解决的是另一个问题:它直接砍掉长尾。不管 temperature 怎么调,top_p 只从累积概率达到 p 的 token 集合里采样。这意味着那些概率极低的奇怪 token 永远不会被选中,输出质量更稳定。
实际使用中,我的经验是:需要确定性输出时,temperature 设 0 到 0.3,top_p 设 0.1 到 0.5;需要多样性时,temperature 设 0.7 到 1.0,top_p 设 0.9 到 0.95。两个参数不要同时往极端调,否则要么输出太死板,要么输出太离谱。
还有一个坑:有些 API 文档说 temperature 和 top_p 二选一调整,但实际实现里两个都生效。如果你只调了一个发现效果不对,试试把另一个也调一下。
3.2 流式输出的实现原理:SSE 与 chunk 拼接
流式输出是大模型应用里用户体验的关键。没有流式输出,用户要盯着空白屏幕等好几秒;有了流式输出,文字一个个蹦出来,感觉快得多。
流式输出的底层通常是 Server-Sent Events(SSE)。服务端和客户端建立一个长连接,服务端每生成一个 token 就通过这个连接推送给客户端。客户端收到后立刻渲染,同时继续等待下一个。
但这里有几个工程细节容易出问题。第一,SSE 推送的不是完整的 token,而是 chunk。一个 chunk 可能包含一个 token,也可能包含多个 token,还可能把一个 token 拆成多个 chunk。客户端需要自己拼接这些 chunk,拼错了就会出现乱码或断字。
第二,流式输出的结束标志不是连接关闭,而是一个特殊的结束 chunk。如果你只监听连接关闭事件,可能会在最后一个 chunk 还没处理完时就认为结束了。
第三,流式输出和错误处理要配合好。如果生成到一半出错了,服务端可能直接断开连接,客户端需要能识别这种情况并给出合理提示,而不是一直转圈。
我踩过的一个坑:早期做流式输出时,没有处理 chunk 边界,结果中文输出经常出现半个字的情况。后来在客户端加了一个缓冲区,确保每次渲染的都是完整的字符,问题才解决。
3.3 上下文窗口管理:截断、摘要与滑动窗口
上下文窗口是有限的,但对话可以无限长。这两者之间的矛盾,是所有对话类应用都要面对的问题。
最简单的策略是截断:超过窗口就丢掉最早的消息。但这样会丢失重要信息,用户会发现机器人“失忆”了。稍微好一点的是滑动窗口:保留最近 N 轮对话,更早的丢掉。但这样还是会丢信息,只是丢得慢一点。
更聪明的做法是摘要:把早期对话压缩成一段摘要,放在系统提示词里。这样既保留了关键信息,又节省了 token。但摘要本身也要消耗 token 来生成,而且摘要质量不稳定,可能把重要细节漏掉。
还有一种做法是检索:把历史对话存到向量数据库里,每次根据当前问题检索相关片段拼进上下文。这样理论上可以支持无限长的对话历史,但检索本身有延迟,而且检索不准时会引入无关信息。
实际项目中,我通常组合使用这几种策略:最近几轮对话保留原文,更早的做摘要,再早的存起来按需检索。具体比例根据场景调整,客服场景可能更依赖检索,创作场景可能更依赖摘要。
3.4 系统提示词的真实作用:不是“设定人设”那么简单
系统提示词(system prompt)经常被当成“给模型设定人设”的工具。这没错,但它的作用远不止于此。
系统提示词是模型在生成每个 token 时都会看到的上下文的一部分。它会影响模型对整个对话的理解,影响模型选择什么样的语气、什么样的知识、什么样的推理路径。一个好的系统提示词,能显著提升输出质量;一个差的系统提示词,能让模型表现下降一个档次。
我见过很多团队把系统提示词写得很随意,几句话就完事。然后抱怨模型“不听话”。实际上,系统提示词需要精心设计:要明确任务边界,要给出输出格式要求,要说明什么该做什么不该做,要提供必要的背景知识。这些内容不是“人设”,是“工作说明书”。
还有一个细节:系统提示词的位置和格式会影响效果。有些模型对系统提示词的遵循度更高,有些模型会把系统提示词和用户消息混在一起理解。了解你用的模型对系统提示词的处理方式,能帮你写出更有效的提示词。
4. 成本与性能的平衡:从 token 计费到推理加速
4.1 Token 计费的隐藏成本:输入输出不对称
大模型 API 的计费通常是输入 token 和输出 token 分开算的,而且输出 token 往往比输入 token 贵。这个差价反映的是推理成本的不对称:输入 token 可以并行处理,输出 token 必须串行生成。
这意味着什么?意味着你的成本大头可能在输出上。一个应用如果输出很长,即使输入很短,成本也可能很高。反过来,如果你能把输出压缩得简洁一些,成本会明显下降。
但压缩输出不能牺牲质量。我的经验是:在系统提示词里明确要求“简洁回答”“不要重复问题”“不要解释显而易见的事情”,能省下不少输出 token。另外,对于结构化输出(比如 JSON),让模型直接输出目标格式,而不是先输出一段解释再输出 JSON,也能省 token。
还有一个容易被忽略的成本:重试。如果模型输出不符合要求,你需要重新调用,这就产生了额外成本。减少重试的关键是提高首次调用成功率:把要求写清楚,把格式定明确,把边界条件说明白。
4.2 批处理与并发:什么时候该等,什么时候该冲
批处理能省钱,因为很多 API 对批处理请求有折扣。但批处理意味着等待,不适合实时交互场景。
并发能提速,但并发太高会触发限流,反而更慢。而且并发请求之间可能互相影响,比如共享的 KV Cache 被挤占。
我的经验是:实时交互场景用低并发加流式输出,保证响应速度;离线处理场景用批处理加高并发,追求吞吐量。两者不要混在一起,否则两头不讨好。
还有一个技巧:对于可以预测的请求,提前发起。比如用户打开对话界面时,你可以先发一个空的或者极短的请求预热连接,等用户真正输入时延迟会低一些。
4.3 缓存策略:哪些请求可以复用,哪些不能
大模型推理的缓存分好几个层次。最底层是 KV Cache,服务端自动管理,开发者一般不用操心。上一层是语义缓存:如果两个请求的语义相同或高度相似,可以复用之前的输出。
语义缓存的实现方式通常是:把请求向量化,在缓存里找相似度超过阈值的记录,如果找到就直接返回缓存结果。这样能省下推理成本,但风险是缓存结果可能不完全适用当前请求。
我一般只在特定场景用语义缓存:FAQ 类问答、固定格式的转换任务、对实时性要求不高的场景。对于需要结合上下文、需要个性化输出的场景,语义缓存容易出问题。
还有一个简单的缓存:对完全相同的请求直接返回缓存结果。这个没有语义相似度的风险,但命中率低,只适合重复请求多的场景。
4.4 模型选择:不是越大越好,也不是越小越省
模型选择是成本与性能平衡的核心决策。大模型能力强但贵且慢,小模型便宜快但能力有限。怎么选?
我的框架是:先看任务复杂度。简单的分类、抽取、格式转换,小模型足够;复杂的推理、创作、多轮对话,大模型更稳。再看延迟要求。实时交互场景,小模型或中等模型更合适;离线处理场景,可以用大模型慢慢跑。最后看预算。预算充足就上大模型,预算紧张就小模型加精心设计的提示词。
还有一个策略是模型级联:先用小模型处理,如果小模型置信度低或者输出不符合要求,再升级到大模型。这样大部分请求用小模型处理,只有少数难题用大模型,整体成本可控。
但级联会增加系统复杂度,而且小模型的判断不一定准。我一般只在请求量大、成本压力大的场景用级联,小规模应用直接用中等模型更省心。
5. 排查与调试:当 API 返回的结果不符合预期时
5.1 从日志开始:记录什么才有用
排查大模型问题时,日志是第一手资料。但很多团队的日志记录得太少,出问题了根本不知道当时发生了什么。
我建议至少记录这些信息:完整的请求参数(包括所有采样参数)、完整的输入 token 序列(或者至少是 token 数量)、完整的输出、响应时间、使用的模型版本。如果涉及多轮对话,还要记录对话历史。
但记录完整输入输出有隐私风险,所以要做好脱敏。我的做法是:生产环境记录 token 数量和哈希值,不记录原文;调试环境记录完整内容,但设置访问权限和自动清理。
还有一个技巧:给每个请求打上唯一标识,这样可以在日志里追踪一个请求的完整生命周期,从客户端发出到服务端处理到返回结果。
5.2 常见异常的分类与定位
大模型 API 的异常大致分几类:网络类(超时、连接断开)、服务端类(限流、内部错误)、模型类(输出不符合预期)、参数类(参数不合法或冲突)。
网络类异常通常重试就能解决,但要注意重试策略:指数退避比固定间隔好,加随机抖动比不加好。服务端类异常要看具体错误码,限流就降速,内部错误就重试。模型类异常最麻烦,因为不是“错误”,只是“不符合预期”,需要仔细分析输入输出。参数类异常最好排查,看文档对照就行。
我遇到最多的是模型类异常,表现五花八门:输出格式不对、内容跑偏、重复啰嗦、突然截断。这类问题往往不是单一原因,而是提示词、参数、上下文共同作用的结果。排查时需要控制变量:先固定参数,调整提示词;再固定提示词,调整参数。一步步缩小范围。
5.3 提示词调试的工程化方法
提示词调试不能靠感觉,要有工程化的方法。
第一步是建立评估集:收集一批典型输入和期望输出,作为调试的基准。没有评估集,你改提示词就是盲人摸象,改好了一个 case 可能弄坏了另外三个。
第二步是自动化评估:写脚本批量跑评估集,自动对比输出和期望,给出通过率。这样每次改提示词都能快速看到效果。
第三步是版本管理:提示词也要像代码一样版本管理,每次修改记录改了什么、为什么改、效果如何。这样出问题了可以回滚,也可以追溯哪个改动导致了效果下降。
我见过很多团队提示词改来改去,最后不知道哪个版本效果好,就是因为没有版本管理。这个习惯建立起来之后,提示词优化的效率会高很多。
5.4 性能问题的排查路径
性能问题通常表现为响应慢或吞吐低。排查路径可以从外到内:先看网络延迟,再看服务端排队时间,再看模型推理时间,最后看输出处理时间。
网络延迟用 ping 或 traceroute 排查。服务端排队时间看 API 返回的响应头或者日志。模型推理时间看首 token 延迟和总生成时间。输出处理时间看客户端渲染和拼接逻辑。
一个常见误区是只盯着模型推理时间,忽略了其他环节。实际上在高并发场景下,排队和网络往往是大头。我遇到过一次性能问题,排查了半天发现是客户端拼接 chunk 的逻辑太低效,每个 chunk 都触发一次重渲染,导致 CPU 跑满。改成批量渲染后,问题立刻消失。
6. 从原理到实践:几个能立刻用上的优化技巧
6.1 减少 token 消耗的五个具体做法
第一个做法是精简系统提示词。系统提示词在每个请求里都会重复发送,如果写得太长,累积成本很可观。把不必要的解释、示例、重复说明删掉,只保留核心指令。
第二个做法是压缩历史对话。多轮对话里,早期轮次如果和当前问题无关,可以摘要或者直接丢弃。不要把所有历史都塞进上下文。
第三个做法是控制输出长度。在提示词里明确要求简洁,设置 max_tokens 上限,避免模型长篇大论。
第四个做法是复用前缀。如果多个请求共享相同的前缀(比如相同的系统提示词和少量示例),可以利用前缀缓存来减少重复计算。有些 API 支持显式的前缀缓存,有些是自动的。
第五个做法是选择合适的模型。不是所有任务都需要大模型,小模型能做的就用小模型,省下的钱可以用在真正需要大模型的地方。
6.2 提升输出稳定性的参数组合
输出不稳定通常表现为:同样的输入,有时候输出好,有时候输出差。提升稳定性的关键是降低采样随机性。
我的推荐组合是:temperature 设 0.1 到 0.3,top_p 设 0.1 到 0.3,同时设置 frequency_penalty 和 presence_penalty 为 0 或很小的值。这样输出基本确定,但又不至于完全死板。
如果还是不稳定,检查一下是不是上下文里有冲突信息。模型在矛盾信息面前容易摇摆,清理掉矛盾信息往往比调参数更有效。
还有一个技巧:在系统提示词里明确要求“直接回答,不要犹豫,不要输出多个版本”。这能减少模型输出“一方面……另一方面……”这种摇摆内容。
6.3 流式输出的正确实现方式
流式输出的实现要注意几个点。第一,正确处理 chunk 边界,确保每次渲染的都是完整字符。第二,正确处理结束标志,不要依赖连接关闭。第三,正确处理错误,生成中途出错要有合理提示。第四,正确处理背压,如果客户端渲染慢,要能暂停接收,避免内存堆积。
我的实现通常是在客户端加一个缓冲区,收到 chunk 先存起来,然后按字符边界切分,完整的字符立刻渲染,不完整的留在缓冲区等下一个 chunk。结束标志收到后,把缓冲区剩余内容渲染完,然后关闭连接。
错误处理方面,我会在流式连接上监听错误事件,一旦出错就停止渲染,显示错误提示,并记录日志。不要试图在流式过程中重试,因为已经渲染的内容没法撤回,重试会导致内容重复。
6.4 成本监控与告警的搭建
成本监控不是等到账单出来才看,要实时监控。我的做法是:每次 API 调用都记录 token 消耗和估算成本,汇总到监控系统,设置日预算和月预算告警。
告警阈值要合理:太低会频繁误报,太高就失去意义。我一般设三个级别:日预算的 50% 提醒,80% 警告,100% 严重告警。严重告警时自动降级到小模型或者暂停非关键请求。
还有一个细节:区分不同业务线的成本。如果多个功能共用同一个 API key,成本混在一起很难归因。给每个业务线单独的 key 或者单独的标签,能帮你快速定位成本异常的来源。
监控数据还可以用来优化:看看哪些请求消耗 token 最多,哪些功能成本最高,然后针对性地优化。很多时候,优化一个高频低价值的功能,比优化一个低频高价值的功能更能省钱。
7. 一些踩过的坑和想明白的事
7.1 关于“模型不稳定”的误解
早期我总觉得模型“不稳定”,同样的输入输出时好时坏。后来想明白了:模型本身是确定的,给定相同的输入和参数,输出应该相同(忽略浮点误差)。不稳定的是我的输入——我以为是相同的输入,实际上 tokenization 后可能不同,上下文可能不同,服务端状态可能不同。
想明白这件事之后,我不再抱怨模型,而是仔细检查自己的输入。把输入固定下来,把参数固定下来,把上下文固定下来,输出自然就稳定了。如果还不稳定,那就是服务端的问题,不是模型的问题。
7.2 关于“提示词工程”的边界
提示词工程有用,但边界比很多人想象的要窄。它能引导模型的行为,但不能让模型做它能力之外的事。你没法通过提示词让一个小模型拥有大模型的推理能力,也没法通过提示词让模型知道它训练数据里没有的知识。
提示词工程的核心是“对齐”:让模型的输出和你的期望对齐。对齐的前提是模型有能力产生你期望的输出。如果模型没这个能力,再好的提示词也没用。
所以我的做法是:先选对模型,再写提示词。模型选错了,提示词写得再好也是事倍功半。
7.3 关于“成本优化”的优先级
成本优化有很多手段:换小模型、压缩输入、控制输出、缓存、批处理。但优先级很重要。我的优先级是:先优化高频高成本的请求,再优化低频高成本的请求,最后优化高频低成本的请求。低频低成本的请求直接忽略,优化它们的时间成本比省下的钱还多。
还有一个原则:不要为了省钱牺牲质量。如果优化导致输出质量下降,用户流失的成本远大于省下的 API 费用。质量优先,成本其次。
7.4 关于“原理学习”的投入产出比
学原理要花时间,但回报是长期的。理解原理之后,你排查问题更快,优化更有方向,和团队沟通更顺畅。而且原理是通用的,换个模型、换个 API、换个框架,原理还是那些原理。
我的建议是:不要一开始就啃论文,从工程实践中的问题出发,遇到不懂的再往下钻。比如你发现流式输出有延迟,就去查 KV Cache 的原理;你发现成本高,就去查 tokenization 和计费的逻辑。这样学起来有目标,记得也牢。
8. 写给想从“会调”到“懂原理”的开发者
从会调到懂原理,中间隔着的不是智商,是愿不愿意多问几个为什么。每次调用 API 的时候,多想想这个请求到底发生了什么,这个参数到底影响了什么,这个结果到底是怎么产生的。想多了,原理自然就通了。
我自己的路径是:先跑通,再拆解,再优化。跑通是第一步,但不要停在第一步。拆解是把黑盒打开,看看里面有什么。优化是在理解的基础上,让系统跑得更好、更省、更稳。
这个过程没有捷径,但有方法。方法就是:遇到问题不要绕过去,追到底。追到底的过程中,你会遇到很多不懂的概念,一个个搞懂,认知就上来了。
大模型应用开发这个领域,变化很快,但底层原理变化很慢。把原理搞扎实,上层怎么变你都能跟上。只会调 API 的人,换个 API 就要重新学;懂原理的人,换个 API 只是换个调用方式。
这个系列我会继续写下去,下一篇想聊聊多轮对话的状态管理,那是另一个被严重低估的工程问题。如果你也在做类似的事情,欢迎交流。