【AI应用--白话大模型(篇三)】《理解大模型之搞懂 Token 计算与词表原理,剖析大模型多轮对话记忆瓶颈,吃透提示词与 ChatTemplate 聊天模板》 一.Token1.定义Token词元是⼤语⾔模型LLM理解和处理⽂本的最⼩基本单位。“我爱⼤模型开发”了解的⼈获得信息的断句是我/爱/⼤模型/开发依次送⼊到我们的⼤脑中去理解同样我们将信息输⼊到⽂本时也是按照切分后输⼊到模型中的。因此这⼀个⼀个的输⼊就叫token例如上例中“我”是⼀个token“爱”是第⼆个token“⼤模型”和“开发”都是token。这个断句的过程在⼈⼯智能领域叫做分词tokenization。当然对于没有背景知识的⼈上例的断句也可能是我/爱/⼤/模型/开发对于⼩孩来说断句是我/爱/⼤/模/型/开/发。不同的⼈断句的⽅式不同与此相同市⾯上的⼤模型⼚商切词也会有细微的差别不同切词的⽅式同⼀句话切出来的token是不⼀样的。⼤语⾔模型不看完整的句⼦⽽是把句⼦拆成⼀个个Token来“理解”和“⽣成”。2.常见形态Token的常见的形态⼀个完整的单词 Hello 可能是 1 个Token。单词的⼀部分 unbelievable 可能会被拆成 un believe able 3个Token。标点符号逗号、句号、感叹号通常各占 1 个Token。中⽂情况中⽂⾥⼀个汉字通常占 1 到 2 个Token视具体词汇频率⽽定⽽不是⼀个字对应⼀个Token。3.估算⼯具下⾯地址是chatgpt的Token估算⼯具https://platform.openai.com/tokenizer开源多模型 Tokenizer ⽹⻚版 同样提供了分词查看能⼒https://tiktokenizer.vercel.app/4.为什么需要 Token?1.数字化让机器能听懂计算机本质上只能处理数字和数学运算⽆法直接理解⼈类的⽂本。通过将⽂本切分为 Token 并转换为向量AI 才能在神经⽹络中进⾏矩阵运算从⽽捕捉词语之间的语义关系第⼀步切分编号数字化输⼊——解决“怎么拆”的问题⽂本不能⼀整坨丢给计算机必须先拆成最⼩计算单元Token并给每个Token分配⼀个整数ID。⽐如 unhappiness 切成⼦词[un, happi, ness] 分别对应ID [432, 891, 256] 。 此时计算机拿到了纯数字 [432, 891, 256] 但注意数字891并不⽐432“更⼤”或“更开⼼”它只是个冰冷的代号。如果直接拿这些ID做加减法432891毫⽆意义。第⼆步离散的ID⽆法表达语义必须把每个ID映射成⼀串⾼维浮点数向量。这些向量在训练中不断调整语义越近向量在空间⾥离得越近。模型为 happy 分配向量 [0.8, 0.9, -0.1,...] 为 glad 分配向量 [0.79, 0.88, -0.09, ...] 两者距离很近都表⽰开⼼。⽽ un 的向量带有“否定”⽅向当它和 happy 组合时合成向量会把空间坐标推向sad 所在的⽅向。2. 解决“词汇爆炸”问题a. 如果按“字⺟”为单位粒度太细,词表很⼩英⽂ unhappiness 会被拆成 11 个字符u n h a p p i n e s s 每个字符⼏乎没有独⽴语义⽐如 u 和 n 拼在⼀起才能表达“否定”模型需要花⼤量计算去学习相邻字符的组合规律。⽽且对于⻓⽂本序列会变得极⻓计算量按平⽅增⻓效率极低。b. 如果按“单词”为单位粒度太粗,词表会爆炸。如果模型把所有可能出现的英⽂单词都放进词表词表会⼤到⽆法训练英语有⼏⼗万单词还有派⽣词如 unhappiness 、unhappily 等。遇到未登录词如新造词 cryptocurrency 模型只能当成“未知”⽽⽆法理解语义表达能⼒受限5.输⼊token和输出tokena.输⼊token你发送给模型的提⽰词所消耗的 token 数量。包含内容⽤⼾输⼊的⽂本。如果开启了联⽹搜索搜索引擎返回的相关内容也会被计⼊输⼊ token。b.输出token模型⽣成回答所消耗的 token 数量包含模型返回的完整回复⽂本。6.为什么输出token贵可以从 模型 价格 | DeepSeek API Docs和 chatgpt的价格https://developers.openai.com/api/docs/pricing致命伤⼀算⼒闲置利⽤率极低输⼊Prefill把 1000 个 Token 打包成⼀个⼤矩阵GPU 的 Tensor Core 满载运⾏利⽤率接近 100%。虽然算得多但 0.1 秒就⼲完了占⽤硬件的时间极短。输出Decode每次只算 1 个 Token 的 Q但为了算这 1 个 Q得把缓存⾥ 1000 个 K 搬出来做点积。GPU 的计算单元闲置了 95% 的时间全在等“搬数据”。虽然每次算得极少但⽣成1000 个输出 Token 需要串⾏跑 1000 步总共耗时可能是输⼊阶段的 10 倍以上。类⽐输⼊像满载的货⻋⾛⾼速费油但跑得快输出像市区堵⻋⾛⾛停停不费油但耗时极⻓。出租⻋公司云⼚商按“打表时间”收费堵⻋当然更贵。致命伤⼆显存带宽被榨⼲硬件瓶颈我们前⾯讲过输出阶段瓶颈从“计算速度”变成了“显存搬运速度Memory Bound”。输⼊消耗的是计算单元算⼒这是 GPU 的强项。输出消耗的是显存带宽HBM 带宽。为了算⼀个新 Token要把缓存⾥⼏千个 K 向量从显存“搬”到缓存⾥。显存带宽是 GPU 最稀缺、最贵的资源之⼀⽐如 H100 带宽 3.35TB/s。输出阶段疯狂搬运海量数据直接把带宽打满导致其他运算都得排队。致命伤三KV Cache 占⽤的显存内存成本输⼊算完就释放显存不占地⽅。输出每⽣成⼀个新 Token就得把这个 Token 的 K 和 V 永久追加进显存直到整段对话结束。⽣成 1000 个 Token就要占 1000 份显存空间。对于云⼚商来说显存 钱。⼀块 A100 只有 80GB 显存如果⼀个⽤⼾⽣成⻓⽂本占了 40GB那这张卡上能同时跑的⽤⼾数就急剧减少。输出 Token 不仅让你慢还占着茅坑显存不让别的⽤⼾拉屎。就像你要盖房⼦都需要1000块砖处理输⼊相当于你有1000个⼯⼈每⼈同时搬⼀块砖⼀次性搞定1轮完成。⽣成输出相当于你只有1个⼯⼈因为下⼀个词必须依赖上⼀个词他得来回搬1000趟。⽽且更惨的是随着⽣成的Token越多⽐如搬了500块后他每次路过材料堆时还得清点⼀下前⾯已经搬过的所有砖KV Cache越来越⼤每⾛⼀步负担都⽐上⼀步重⼀点点。二.Vocabulary词表1.定义词表是模型预定义的⼀个映射字典。它包含了模型“认识”的所有词元Token。每个词元都有⼀个唯⼀的数字 ID索引。当输⼊⽂本时分词器Tokenizer会查阅词表将句⼦切割成词表中存在的⽚段并转换为 ID列表输⼊模型模型输出的 ID 再通过词表映射回⽂本。在⼤型语⾔模型LLM的架构中Vocabulary词表是模型理解⼈类语⾔的“字典”。它定义了模型能“看⻅”和“写出”的所有基本单位。2.常⻅的词表⼤⼩3.作⽤由于⼤语⾔模型LLM本质上是数学函数输⼊数字输出数字⽆法直接处理原始⽂本因此词表就是连接“⼈类语⾔”和“模型数字世界”的桥梁。4.⽣成词范围不能⽣成不在词表Vocabulary⾥的“Token”但可以组合出不在词表⾥的“词Word”。⽐如 3个token un believe able 组词出来 unbelieveable 理论上⽣成的所有的内容都必须来⾃token。如果真遇到了token没办法表⽰的单字符⽐如某些Emoji 表情就会触发字节级回退。虽然模型可以拼凑出任何字符串但它⽆法创造出词表索引之外的新编号。 如果模型的词表⼤⼩是50,257GPT-2 的标准它永远不可能输出编号为 50,258 的 Token。对于词表⾥有的词模型输出1 个 Token 即可对于词表⾥没有的“新词”模型可能需要输出 5-10 个 Token。这也是为什么处理某些冷⻔专业术语或罕⻅语⾔时LLM 的推理速度会变慢且更贵。5.什么是字节级回退了解字节级回退”Byte-fallback是现代⼤模型分词器如 Llama、ChatGLM 等普遍采⽤的 BPE 分词器能够做到“100%不漏掉任何字符”零 unk 标记的幕后功⾂。为了让你的知识闭环更完整我们可以⽤⼀个更具体的硬核拆解来看看它在底层到底是怎么运作的假设我们要让⼤模型处理 这个表情⽽词表⾥恰好没有它1. UTF-8 编码编码 的 UTF-8 编码由 4 个字节组成 0xF0 0x9F 0x98 0x8A 。2. 传统 Tokenizer 的绝路传统分词器⼀看词表⾥没有 就会直接抛出⼀个未知字符标记——[UNK] Unknown。模型看到 [UNK] 就是两眼⼀抹⿊根本不知道这后⾯代表的是愤怒、悲伤还是微笑。3. Byte-fallback 的拯救触发回退机制把这 4 个字节拆开0xF0 $\rightarrow$ 映射到词表⾥的专⽤ Token byte_0xF00x9F $\rightarrow$ 映射到词表⾥的专⽤ Token byte_0x9F0x98 $\rightarrow$ 映射到词表⾥的专⽤ Token byte_0x980x8A $\rightarrow$ 映射到词表⾥的专⽤ Token byte_0x8A最后这个表情就被切成了 4 个独⽴的字节 Token 送⼊模型。为什么说这是⼀个“极其精妙”的设计在 Byte-fallback 出现之前为了不让模型遇到⽣僻字就变“瞎⼦”早期的 GPT-2 采⽤了纯字节级BPEByte-level BPE。也就是说它的词表⼲脆完全由最基础的 256 个字节组合⽽成。但纯字节级有⼀个致命缺点效率太低。英⽂单词 apple 就要占 5 个 Token中⽂ 苹果 在 UTF-8下有 6 个字节要占 6 个 Token。这会导致⼤模型的上下⽂窗⼝Context Window迅速被吃满。⽽Byte-fallback字节级回退则是两者的完美结合Best of Both Worlds正常情况下 词表⾥有⾼频的“苹果”、“apple”、“Hello”那就直接⽤⼤ Token保证效率。极端情况下 遇到冷⻔字、⽕星⽂、罕⻅ Emoji不报错、不丢弃⽽是降级回退到字节模式保证鲁棒性。三.多轮对话简单说模型的如何记住我说过的话1.失忆的⼤模型我们先问下DeepSeek告诉他我们的名字然后再打开个新的会话他其实并不知道我们是谁因为⼤模型是没有记忆的就只是进⾏简单的概率预测。在这里我们会发现它不记得我们叫什么了好像失忆了一样。(这里我是开启了新的对话2.概念从技术本质上讲LLM 本⾝是⽆状态的Stateless。这意味着模型处理每⼀条指令时默认并不知道你之前说过什么。LLM⼤语⾔模型的多轮对话是指模型在与⽤⼾交互时能够“记住”之前的对话内容并以此为基础理解和⽣成后续回复的能⼒。简单来说它让 AI 不再是“⼀问⼀答、互不关联”的复读机⽽是⼀个能承接上下⽂、具备短期记忆的对话者。我们来看个例⼦感受下什么是多轮对话我们第⼀次问DeepSeek我叫⼩明我今年6岁了你叫什么DeepSeek回复如下:我们第⼆轮接着问我叫什么我明年⼏岁了可以看到他竟然知道我叫⼩明明年⼏岁了也知道这种能⼒就是多轮对话带来的。3.⼯作机制从技术实现⻆度看多轮对话的核⼼在于上下⽂管理。⽬前的LLM本质上是“⽆状态”的——它们每次处理请求时并不天然记住之前的内容。因此所谓的“多轮对话”其实是由应⽤层客⼾端或服务端来模拟和维护的。实现多轮对话的常⻅⽅式是将历史对话记录History/Context连同当前的新问题⼀起重新打包发送给模型。我们来看个例⼦理解下4.为什么需要多轮对话1.上下⽂依赖对话的语境Context是理解代词“它”、“那个”和隐喻的关键。没有多轮对话模型就⽆法建⽴“记忆”每次互动都是断裂的。你⻰是什么 AI:在中国⽂化中⻰是祥瑞的象征代表权⼒、尊贵、⼒量和好运。它常与⾬⽔、江河相关被视为 能够呼⻛唤⾬的神兽。皇帝⾃称“真⻰天⼦”⻰也是中华⺠族的精神图腾之⼀。 你它的头像什么 AI:“⻰有九似”的说法头似驼⻆似⿅眼似兔⽿似⽜项似蛇腹似蜃鳞似鲤⽖似鹰掌似 ⻁。2. 复杂问题逐渐搞清晰⼈类的意图往往具有模糊性。⽤⼾往往不会在第⼀时间提供所有必要信息⽽是倾向于遵循“最省⼒原则”通过多轮互动逐步探索和完善⾃⼰的需求。举例说明想象⼀下看医⽣的场景。你不会⼀进⻔就说“我头痛持续三天是胀痛没有发烧请开 药”。更⾃然的对话是 你“医⽣我头痛。” AI医⽣“这种头痛持续多久了” 你“⼤概三天了。” AI医⽣“是哪种性质的痛胀痛还是刺痛” 你“是胀痛。” 通过这种多轮问答AI才能像真⼈医⽣⼀样构建出完整的“病情图像”最终给出精准的建议。3.纠错与对⻬ (Feedback Loop) 模型可能会在第⼀轮出现幻觉或逻辑错误。多轮对话给了⽤⼾“指正”的机会让模型在当前会话内通过反馈进⾏即时调整。第1轮⽤⼾提问 ⽤⼾请问鲁迅的《狂⼈⽇记》最早发表在哪本杂志上 第2轮AI出现错误 AI您好鲁迅的《狂⼈⽇记》最早发表在《新潮》杂志上。 第3轮⽤⼾纠正 ⽤⼾不对应该是《新⻘年》吧1918年5⽉第4卷第5号。 第4轮AI承认错误并纠正 AI⾮常抱歉您说得对。我刚才记错了。《狂⼈⽇记》最早确实是发表在1918年5⽉的《新⻘年》第 4卷第5号上⽽不是《新潮》。感谢您的指正我会注意核实此类⽂学史信息。5.多轮对话常⻅问题和解决思路上下⽂管理与记忆的瓶颈问题核⼼限制⼤模型如DeepSeek系列本质上是“⽆状态”的其“记忆”完全依赖于输⼊⽂本即上下⽂窗⼝。这个窗⼝有固定的⻓度上限例如32K tokens⼀旦对话历史超出限制最早的信息就会被“遗忘”或截断。⽐如在⼀个⻓对话中⽤⼾最初提到“我对花⽣过敏”但在后续询问蛋糕推荐时由于对话轮次过多这条关键信息可能已被移出上下⽂窗⼝导致模型推荐了含有花⽣的蛋糕配⽅。⽤⼾我对花⽣过敏以后推荐⻝物时请避开花⽣。 助⼿明⽩了我会记住您对花⽣过敏。之后涉及⻝品的建议都会避开花⽣及相关制品。 ⽤⼾最近想学做⾯包有什么适合新⼿的配⽅吗 助⼿当然。推荐基础⽩⾯包⾼筋⾯粉、⽔、酵⺟、盐、糖、⻩油。没有花⽣成分请放⼼。 ⽤⼾谢谢。那烤箱温度怎么控制 助⼿⼀般⽩⾯包⽤180-190℃烤25-30分钟。建议买个烤箱温度计更准确。 ⽤⼾我家的烤箱是30升的需要调整时间吗 助⼿30升属于中⼩型受热可能更快建议先设25分钟观察上⾊情况。 ⽤⼾好的。还想问⼀下戚⻛蛋糕总是塌陷怎么办 助⼿常⻅原因蛋⽩打发不⾜、翻拌消泡、或出炉没震热⽓倒扣。建议蛋⽩打到⼲性发泡翻拌⼿法 轻快。 ⽤⼾原来如此。那有没有适合下午茶的蛋糕配⽅简单⼀点的。 助⼿推荐花⽣酱玛芬蛋糕低筋⾯粉、花⽣酱、鸡蛋、⽜奶、糖、泡打粉。⾮常⾹浓做法简单。注 意花⽣过敏者不宜⻝⽤。 ⽤⼾我⼀开始就说了我对花⽣过敏你怎么还推荐含花⽣的配⽅a.解决思路选择性记忆⽽⾮全记住b.解决技术1. 对话摘要超过⻓度后让模型把旧对话压缩成简短摘要。⽐如对话过程中助⼿在第10轮后检测到⻓度接近上限 “我们的对话已经较⻓。为了不丢失您之前说的‘花⽣过敏’等重要信息我将把前⾯的内容压缩成如下 摘要之后基于这个摘要继续回答您的问题—— 摘要⽤⼾对花⽣过敏。⽤⼾是烘焙新⼿已尝试⽩⾯包烤箱为30升。⽤⼾询问过戚⻛蛋糕塌陷的原 因正在寻找简单的下午茶蛋糕配⽅不能含花⽣。建议的沟通流程可以参考下⾯的过程2. 滑动窗⼝只保留最近N轮对话这个⽐较简单模型就只认⼏条消息超过了我就当没有3. RAG技术后⾯我们会详细介绍把历史存⼊向量数据库按需检索相关⽚段⽽⾮全量输⼊。核⼼思路是超过上下⽂的时候把之前相关的内容添加到下⼀次沟通。三者对比技术一句话总结核心逻辑对话摘要压缩旧内容成摘要带着走记住总结丢掉细节滑动窗口只留最近N轮远的直接扔只记最近不管以前RAG全部存起来按需查相关片段全记住用的时候翻档案记忆强度滑动窗口最健忘 对话摘要中等 RAG记得最全推理效率与成本问题每轮对话都要重新处理整个历史Token消耗和延迟随轮次线性增⻓成本会快速上升。⽐如⼀个20轮的客服对话每次提问模型都要重新“阅读”全部20轮内容即使⼤部分是闲聊。a.解决思路减少重复计算b.解决技术1. 提⽰词缓存机制KV Cache缓存已计算的历史的计算结果每轮只算新内容⼏乎所有⽣产级服务都⽤。[“今”“天”“天”“⽓”] ⽣成第 1 个字“真”把前⾯4个token的计算信息存⼊缓存区。 ⽣成第 2 个字“不”从缓存中取出之前的5个计算结果和新算出的拼接在⼀起。 ⽣成第 3 个字“错” 从缓存中取出之前的6个计算结果和新算出的拼接在⼀起。2. 上下⽂剪枝移除历史中对当前⽣成⽆⽤的Token。剪枝前:[1] ⼩明: 帮我推荐⼏本好看的科幻⼩说要短篇的。 [2] AI: 《你⼀⽣的故事》《呼吸》《献给阿尔吉侬的花束》都不错〜 [3] ⼩明: 谢谢对了你吃午饭了吗 [4] AI: 我不吃饭不过你可以去⻝堂看看今天有啥好吃的 [5] ⼩明: 好吧。我现在要写物理作业是关于“动量守恒”的。 [6] AI: 好的动量守恒的关键是系统不受外⼒或合外⼒为零。你有具体题⽬吗 [7] ⼩明: 有⼀题是“两个⼩球碰撞⼀个静⽌⼀个运动碰后速度怎么算” [8] AI: 弹性碰撞的话可以⽤公式 v1 (m1-m2)/(m1m2) * v1 ...剪枝后:[5] ⼩明: 好吧。我现在要写物理作业是关于“动量守恒”的。 [6] AI: 好的动量守恒的关键是系统不受外⼒或合外⼒为零。你有具体题⽬吗 [7] ⼩明: 有⼀题是“两个⼩球碰撞⼀个静⽌⼀个运动碰后速度怎么算” [8] AI: 弹性碰撞的话可以⽤公式 v1 (m1-m2)/(m1m2) * v1 ...模型能⼒局限问题上下⽂遗忘当上下⽂较⻓时模型很可能忘记前⾯设定的变量、上下⽂或约束导致后续步骤不⼀致。例如第⼀轮设定“请始终⽤中⽂回答”过了20轮你随⼝问“Whats the weather?”模型可能直接切到英⽂。中间遗忘现象模型更容易记住和利⽤位于上下⽂开头和结尾的信息⽽中间部分的内容常被忽略。在⼤海捞针测试中当关键信息藏在⼤量⽆关信息中间时模型很难找到它。论⽂地址https://arxiv.org/pdf/2307.03172a.解决思路增强模型优化交互b.解决技术1. 训练更⻓窗⼝的模型如百万Token级别,从根上解决:例如DeepSeekGemini的token上下⽂已经到了百万token。2. 显式状态跟踪要求模型维护⼀个“状态信息”记录关键信息。原理不让LLM“记住”状态⽽是由系统维护状态LLM只负责更新。实现⽅式系统维护⼀个独⽴的状态存储变量、数据库、缓存每轮对话时将“当前状态 ⽤⼾输⼊”⼀起发给LLMLLM输出“状态更新指令”系统据此修改状态⽣成回答时系统将“当前状态”作为上下⽂的⼀部分提供给LLM系统维护的状态始终独⽴存储 - ⽬的地野⽣动物园 - 出发时间周⽇早上⼋点 - 参与⼈员妈妈、孩⼦、⼩明 - 交通⼯具开⻋ - 带什么多带⽔和零⻝ 第7轮时系统将上述状态注⼊LLM的上下⽂ “当前计划状态如下[状态详情] ⽤⼾问咱们⼏点出发来着 请基于状态回答问题。” LLM回答 “根据当前计划出发时间是周⽇早上⼋点。”四.提示词1.⽤户提⽰词想让⼤模型⼲什么事情⽤⼾提⽰词 User Prompt就是您⽤户直接发给模型的那句话、问题或指令。它是模型开始⼯作的起点。⽐如下⾯问模型的“北京的天⽓怎么样”。2.系统提示词如何⼀次性给模型设置好⼈设不⽤每次设置a.概念系统提⽰词System Prompt是在与⼤语⾔模型对话开始时预先设定的顶层指令。它定义了模型在整个对话中的⾝份、⾏为边界、回复⻛格和遵循的规则。从技术架构上看系统提⽰词位于对话的最前端由开发者/应⽤⽅来设置贯穿整个对话⽬的是控制模型⾏为边界。我们通过交互逻辑来看下b.为什么需要系统提示词1. 定义⻆⾊与⾏为边界系统提示词为 AI 设定了明确的⾝份和职责范围。⻆⾊塑造它可以告诉 AI “你是⼀位乐于助⼈的客服专家”或“你是⼀个严谨的代码审查员”从⽽让 AI 的回答⻛格与特定场景匹配。划定边界它能清晰地界定 AI 能做什么、不能做什么。例如⼀个技术⽀持助⼿的系统提⽰词会规定它只回答产品相关问题对于超出范围的问题则礼貌地拒绝或引导⽤⼾。2.稳定模型⾏为⼤模型本质上是概率模型每次回答都有随机性。系统提⽰词相当于“锚点”让模型在不同会话中保持⼀致的⻛格和边界。3. 确保安全与合规这是系统提⽰词最核⼼的功能之⼀。开发者通过它来内置“安全护栏”防⽌ AI ⽣成有害、偏⻅或不合规的内容。⻛险规避它会明确禁⽌ AI ⽣成涉及暴⼒、仇恨⾔论或⾮法活动的建议⼒求让 AI 的输出“有益且⽆害”。合规性在某些应⽤中系统提示词会强制 AI 遵守特定的法律或伦理规范例如不泄露⽤⼾隐私信息。4. 弥补知识短板与提供上下⽂知识更新AI 的知识有截⽌⽇期。通过系统提⽰词开发者可以⼿动“热修复”⼀些关键事实。例如直接写明“DeepSeek V4是最新的模型”以弥补模型训练数据截⽌后发⽣的重要事件。案例ClaudeAnthropic公司推出的旗舰级⼤语⾔模型AI助⼿的品牌名称类似于 OpenAI 的ChatGPT、Google 的 Gemini。Opus 系列和Sonnet 系列的模型在代码开发领域是处于领先地位。Claude 是为数不多的公开系统提⽰词的⼤模型下⾯代码块是Claude Opus 4.6的系统提⽰词可以看到系统提⽰词给了很多设定1. 产品信息确认明确⾃⼰⾝份2. 安全和拒绝机制⽐如⼉童保护、恶意代码、危险物质3. 法律和财务建议不提供4. 公正与政治话题处理政治意⻅的处理⽅式5. 语⽓要求温暖具体地址App unavailable in region | Claude by Anthropic五.聊天模板Chat Template1.Chat Template是什么我们可以把 ChatTemplate 理解为⼤语⾔模型LLM进⾏标准化对话的“格式蓝图”。它的核⼼价值在于解决兼容性问题不同的 LLM 在训练时使⽤的对话格式各不相同 ChatTemplate 确保了输⼊给模型的对话格式与它训练时的格式⼀致从⽽显著提升模型表现的稳定性并因此成为 LLM 应⽤开发中⼀个重要的标准化组件。简单来说原始对话数据是System Prompt定义⻆⾊如“你是⼀个AI助⼿”。User Prompt⽤⼾的问题。什么是AIAssistant Response模型需要填写的回答。(AI 是....)[ {role: system, content: 你是⼀个AI助⼿}, {role: user, content: 什么是AI}, {role: assistant, content: AI是...} ]经过 Chat Template 处理后会变成类似|im_start|system 你是⼀个AI助⼿|im_end| |im_start|user 什么是AI|im_end| |im_start|assistant AI是....|im_end|如果没有 ChatTemplate您直接拿原始的 JSON 列表喂给模型模型会把它当成普通⽂本去理解⽆法区分“系统指令”和“⽤⼾历史提问”回答就会完全跑偏。2.常⻅的模型模板三种主流大模型的对话模板Chat Template格式对比Qwen通义千问角色格式system系统提示im_startsystem\n{系统提示}\im_end\nbr/user用户im_startuser\nHello!\im_end\nbr/assistant助手im_startassistant\nHi! How can I help?\im_end地址https://huggingface.co/Qwen/Qwen3.6-27B/blob/main/chat_template.jinjaLlama 3角色格式文本开始标记begin_of_textsystem系统提示start_header_idsystemend_header_id\n\n{系统提示}eot_iduser用户start_header_iduserend_header_id\n\nHello!eot_idassistant助手start_header_idassistantend_header_id\n\n地址https://www.llama.com/docs/model-cards-and-prompt-formats/meta-llama-3/Gemma角色格式文本开始标记bosturn 1 - systemturnsystem\n你是一个安全专家。turnturn 2 - userturnuser\n如何检测代码中的内存泄露turnturn 3 - modelturnmodel\n检测内存泄露通常有以下几种方法...turn地址https://huggingface.co/google/gemma-4-31B-it/tree/main对比总结模型系统提示标记用户标记助手标记特殊分隔符Qwenim_startsystemim_startuserim_startassistantim_endLlama 3start_header_idsystemstart_header_iduserstart_header_idassistanteot_idGemmaturnsystemturnuserturnmodelturnbos通俗理解这些格式本质上都是把对话“翻译”成模型能看懂的语言相当于给对话加上“角色标签”Qwen用im_start和im_end包住每一轮对话Llama 3用start_header_id标记说话人eot_id表示该轮结束Gemma用turn来切分每一轮对话轮次实际开发中你不需要手写这些格式直接用tokenizer.apply_chat_template()会自动生成但这些格式在调试 prompt、看日志、手动构造输入时很有用。3.为什么需要Chat Template1. 通⽤性更加友好假如你⼿动拼接脑⼦⾥想的是def build_prompt(messages): prompt # 初始化空字符串用于拼接最终提示词 for msg in messages: # 遍历每条对话消息 if msg[role] user: # 如果角色是用户 prompt f|im_start|user\n{msg[content]}|im_end|\n # 拼接成|im_start|user\n用户说的话|im_end|\n elif msg[role] assistant: # 如果角色是助手 prompt f|im_start|assistant\n{msg[content]}|im_end|\n # 拼接成|im_start|assistant\n助手说的话|im_end|\n return prompt # 返回拼接好的完整提示词这段代码有什么问题代码本⾝能完美运⾏也能处理 1 条或 100 条消息。但是“Qwen 模型⽤ |im_start| ”这个关键知识被硬⽣⽣地写死在了 Python 代码的 if 条件⾥。如果明天换成了 Llama 模型你必须修改这段 Python 代码把⾥⾯的字符串全换成|start_header_id| 。如果同时维护 10 个模型你的 Python ⽂件⾥就会有⼀⼤堆 if model_name llama的脏逻辑。⽽ Jinja 的做法是把“怎么拼”的规则从 Python 代码⾥抽出来单独存成⼀个⽂本⽂件模板{% for message in messages %} {% if message.role user %}|im_start|user\n{{ message.content }} |im_end|\n {% elif message.role assistant %}|im_start|assistant\n{{ message.content }}|im_end|\n {% endif %} {% endfor %}这样做的好处是什么现在你的 Python 代码⾥只剩下⼀个通⽤的渲染调⽤如template.render(messagesmessages) 完全不需要知道具体的标签名字。换 Llama 模型时你不⽤改 Python 代码只需要把模板⽂件⾥的 |im_start| 全局替换成|start_header_id| 即可。模型作者发布新模型时直接附带这个模板⽂件你的 Python 代码⼀⾏都不⽤动。2. 能根据“有没有某样东西”做决定除了条数不确定模版还得处理“有没有”的问题。⽐如如果⽤⼾传了“⼯具调⽤tools”参数就在系统提⽰词⾥塞⼀⼤段 JSON 说明如果没传就只发普通的系统提⽰词。普通拼接做不到“动态删减⼤段⽂字”只能提前全写死。⽽ Jinja ⽀持 {% if tools %} 条件判断有就插⼊没有就跳过⾮常灵活。3. 能防⽌⽤⼾输⼊“捣乱”⽤⼾可能在聊天内容⾥打上 {{ 或 {% 这类符号。如果你⽤ Python 直接拼接字符串程序很可能误以为这是变量⽽报错。Jinja 默认会把⽤⼾输⼊的内容当成纯⽂本进⾏安全转义确保⽤⼾乱写特殊符号也不会破坏整个提⽰词的格式。聊天模板底层⼀般使⽤Jinja模板引擎来编写和解析感兴趣的同学可以进⼀步研究下Pallets补充Jinja 把“对话格式怎么拼”这件事从 Python 代码里剥离出来变成可替换的配置文件让一套代码能适配所有模型。