想象你是一位话剧导演,要给一群“天才但健忘的演员”排一出多幕剧。这些演员演技一流,却有两个怪癖:一是必须把完整台词摆在眼前才记得住;二是分不清谁在说话——如果剧本上只在每行写台词而不标角色名,它们就会把“服务员,来碗面”和“好的,马上到”念成同一个人说的。 所以剧作家发明了“标准剧本格式”:每句台词前标好角色名,用括号区分导演旁白与道具提示,用分界线隔开一幕幕。大模型就是这样的演员,而对话格式——ChatML、Vicuna——就是它们认的“剧本方言”。这篇文章我们拆开这本“剧本”,看它到底怎么写,模型才能几十轮对话不串戏、不丢人设,你也能真正理解“格式为什么决定智商”。
掌握对话格式设计,是 AI 应用工程师让大模型“听懂人话”的必修课。它直接决定微调效果、上下文利用率和线上对话质量,也是从“调接口”走向“设计系统”的关键一步。
可视化演示
展示K-Means聚类算法的迭代过程,数据点分配与质心更新实时动画呈现。
本节配有交互动效(进入视口后自动加载,约 3KB)。
K-Means聚类迭代 彩色点为各簇数据点 大光点为聚类质心 J = Σ||x_i − μ_c||² 每步将点分配到最近质心并更新质心位置
对话格式概览
想象你是一位话剧导演,手下有位“只认剧本”的天才演员——大模型。它记性很差,每次对话都得把完整台词递到眼前;它又很轴,如果剧本只写台词不标人名,它就会把所有话当成同一个角色在自言自语。所以你需要一套“谁在什么时候说什么”的排版规范,这套规范就是对话格式。
对话格式(Chat Template)是模型微调与在线推理之间的一层契约。ChatML、Vicuna、Alpaca 都是这份契约的具体版本。它们干的事完全相同:把“系统消息、用户问题、助手答复”三类内容翻译成模型在训练时见过的纯文本排列。任何一次多轮对话,本质上都是这个结构的反复叠加:先给导演旁白,再给一问一答,循环往复。
一次完整对话可以抽象成“导演旁白 + N 轮一问一答 + 用户的最新追问”。模型在微调时已经把这种排列“背”进了参数里,推理时你按什么顺序拼,它就按什么顺序理解。顺序一旦错乱——比如把助手的答复放在用户问题之前——模型就会“精神分裂”,答非所问。
1. 系统前置:$[\text{system}]$ 是导演旁白,即系统提示词,永远放在整份剧本最前面。
2. 轮次求和:把 n 轮“一问一答”按时间顺序首尾相接,每一轮都由用户问题加助手答复组成。
3. 拼接操作:$\oplus$ 表示字符串拼接,顺序永久保留,模型靠它判断先后与因果。
4. 最新追问:$[\text{user}_{n+1}]$ 是用户刚发的问题,也是模型需要续写的起点。
所以说,给大模型编排对话,跟给演员排剧本一个道理:不讲究文采,讲究“死规矩”。谁先说、谁后说、用什么符号隔开,规矩定死了,无论多少轮都不会串戏。
特殊Token设计
翻开任何一份话剧剧本,你都会发现台词之外的“特殊标注”:角色名前用力括号框住、舞台提示用小括号括起、幕与幕之间画横线分隔。演员知道这些符号“不念出来,只负责指挥我怎么演”。对话格式里的特殊 token,就是这种“不发音的结构暗号”。
特殊 token(special token)在词表中拥有独立编号,不参与普通分词。ChatML 的 <|im_start|> 与 <|im_end|>、Llama 家族的 <s> 与 </s>、GPT-2 的 <|endoftext|> 都属于这一类。它们对用户不可见,但对模型来说却是明确的“结构指令”:看见 <|im_start|>,就知道一条新消息要开始了。
一条消息的原子结构可以写成“起始标记 + 角色 + 正文 + 结束标记”。设计特殊 token 有一条铁律:绝不能让它们与训练语料里的普通文本重复。否则模型分不清眼前是个“字”还是个“标记”,舞台暗号就会被当成台词念出来,整场戏瞬间垮掉。
\text{Msg} = \langle \texttt{im\_start} \rangle \ \text{role} \ \textbackslash n \ \text{content} \ \langle \texttt{im\_end} \rangle
1. 起始标记:$\langle \texttt{im\_start} \rangle$ 是消息的“开场白”,宣布一条消息开始。
2. 角色字段:$\text{role}$ 声明发言人身份,取值通常是 system、user 或 assistant。
3. 换行分隔:$\textbackslash n$ 是把“角色名”与“正文”隔开的换行符,防止两者粘连。
\textbackslash n
4. 内容与结束:$\text{content}$ 是消息正文,$\langle \texttt{im\_end} \rangle$ 是本条消息的“谢幕”标志。
特殊 token 就像剧本暗号:观众(用户)完全无感,演员(模型)一眼就懂。暗号设计得顺,戏就顺;设计得蹩脚,排练再久也白搭。
ChatML格式
ChatML 是 OpenAI 贡献的一套“标准化剧作模板”。它的性格很轴:每一句台词都必须按“【开始】角色名 换行 台词【结束】”的固定章节排版,谁来都不例外。正因为这种轴,它成为今天大模型对话格式中最流行的一种方言。
ChatML 定义了三种角色:system 是导演旁白,user 是提问的观众,assistant 是负责接话的演员。每条消息都由 <|im_start|> 开头、<|im_end|> 收尾,角色名与正文之间用换行分隔。系统消息永远放在最前面,用来设定语气、知识边界和行为准则。
ChatML 最大的优点是边界清晰。模型能精确知道每条消息从哪里开始、到哪里结束、是谁说的。多轮对话就是把这些消息一条条按顺序拼下去,最后在末尾放一个“assistant 开场标记”,相当于递话筒:轮到演员开口了。因为它严谨、可扩展,主流开源模型大多支持或兼容这套方言。
S = \bigoplus_{k=1}^{m} \Big( \langle \texttt{im\_start} \rangle \ r_k \ \textbackslash n \ M_k \ \langle \texttt{im\_end} \rangle \Big), \quad r_k \in \{\text{system}, \text{user}, \text{assistant}\}
1. 消息序列:$\bigoplus_{k=1}^{m}$ 把 m 条消息严格按顺序拼接成完整文本,先后次序绝不可乱。
2. 角色枚举:$r_k$ 只能取三种身份之一,保证每条消息都有明确的发言人。
3. 消息单元:$M_k$ 是第 k 条消息的正文,被起始标记和结束标记严密包裹。
\langle \texttt{im\_start} \rangle \ r_k \ \textbackslash n \ M_k \ \langle \texttt{im\_end} \rangle
4. 整体交付:最终得到的 $S$ 就是直接喂给模型的请求文本,末尾还要补一个 assistant 开场标记。
用 ChatML 写对话,像用统一软件排版剧本:场记、角色、台词分区明确。哪怕排上一百轮,导演、观众、演员也永远不会串位。
Vicuna格式
另一家剧团却流行一种“极简主义”剧本:不搞括号、不用暗号,只在台词前写个名字——"USER:"、"ASSISTANT:"。像古罗马戏剧里演员胸前挂的铭牌,简单粗暴,一眼看懂。这就是 Vicuna 格式的风格。
Vicuna 格式源自 UC Berkeley 的 Vicuna 模型微调实践,继承了 Llama 家族的文本习惯。它的单轮模板形如 USER: 问题 ASSISTANT: 回答,多轮对话时把每一轮首尾相接、层层累积,像在剧本末尾不断附加新的对白。
Vicuna 没有独立的 system 标记,导演旁白只能写成一句固定前缀文本,例如“A chat between a curious user and an artificial intelligence assistant.“。它的局限很明显:角色只有两个,扩展性弱;但胜在格式紧凑、token 开销小。注意,模型在微调时是”背“着这套格式训练的,推理时换别的方言,它马上就”失灵”。
1. 初始前缀:$S_0 = \text{SYSTEM: } P$ 是固定写在开头的“剧情简介”,通常由模板写死。
2. 递推拼接:$S_n = S_{n-1} \oplus \dots$ 每轮新问答都追加在上一轮的尾部,历史永远保留。
3. 角色铭牌:$\text{USER: } Q_n$ 与 $\text{ASSISTANT: } A_n$ 分别是提问与回答的前缀标识。
4. 续写锚点:预测时在最后补一个 ASSISTANT: 前缀,让模型从这个位置接着写回答。
Vicuna 的剧本省纸、好懂,但只有两个角色位。哪天你想加个系统提示,就得硬塞进前台,稍不留神,演员就念错词了。
上下文窗口管理
舞台就这么大,剧本架只能摆下六页纸。戏越排越长,导演必须做取舍:是保开场的重要提示,还是保最后一幕的高潮?现实中,大模型的“舞台”就是上下文窗口,而取舍就是窗口管理。
上下文窗口(context window)是模型一次能“看”的 token 上限。多轮对话不断追加,历史占用的 token 就不断膨胀。如果不加管理,留给模型回答的空间被挤没,它就会话说到一半“断片”——生成的文字被硬生生截断,这是线上对话最典型的翻车现场。
业界常用的策略有三种:第一,裁剪最旧的历史,优先保住系统消息和最新一问;第二,把已讲过的对话压缩成一段摘要,再放回上下文,相当于“剧情回顾”;第三,滑动窗口,永远只保留最近 N 轮。核心的预算思维是:历史总 token 必须压进“总窗口减去系统消息、再减去生成空间”的剩余预算里。
1. 预算计算:$B = W - T_{\text{sys}} - T_{\text{gen}}$,总窗口先扣掉系统消息和要生成的输出空间。
2. 历史占用:$\ell(Q_i) + \ell(A_i)$ 是第 i 轮用户问题和助手回答加起来的 token 数。
3. 求和约束:把 n 轮历史全部累加,$T_{\text{hist}}$ 必须小于等于 $B$,否则必须裁剪压缩。
4. 裁剪优先级:超限时优先丢最旧轮次,系统消息和用户最新一问优先级最高。
上下文管理本质是舞台调度:好导演永远保证最后一幕有足够的演出空间,哪怕忍痛删掉前面的铺垫。
格式兼容适配
你的剧团要出门巡演了,可外地剧院演员只认另一种剧本风格。你只好请人做“剧本翻译”——把 ChatML 的章法翻成 Vicuna 的铭牌式,翻得忠不忠实,直接决定演出成败。大模型世界里的“剧本翻译”,就是格式转换。
模型与格式是强绑定的:微调时喂了什么格式,推理时就必须喂什么格式。开源模型会在 Transformers 框架里通过 chat_template 字段声明自己的“方言”,框架再按方言渲染请求。如果你无视这个字段、自创格式,再强的模型也会表现失常。
如果手头积累的数据是 Vicuna 格式,而目标模型却是用 ChatML 微调的,就需要写格式转换器:把一对 USER:/ASSISTANT: 问答解析出来,重写成两条带角色标记的 ChatML 消息。转换的关键是语义不变——谁说的话不能串位,每条消息的角色标记必须一一对应。
\mathcal{T}_{V \to C}: \text{USER: } Q \ \text{ASSISTANT: } A \ \longmapsto \ \langle \texttt{im\_start} \rangle \text{user} \ \textbackslash n \ Q \ \langle \texttt{im\_end} \rangle \ \langle \texttt{im\_start} \rangle \text{assistant} \ \textbackslash n \ A \ \langle \texttt{im\_end} \rangle
1. 转换算子:$\mathcal{T}_{V \to C}$ 是一个完成方言翻译的函数,输入输出都是文本。
2. 输入句对:$\text{USER: } Q \ \text{ASSISTANT: } A$ 是 Vicuna 里的一轮问答。
3. 输出消息:映射结果展开成 ChatML 的 user 与 assistant 两条独立消息。
\langle \texttt{im\_start} \rangle \text{user} \ \textbackslash n \ Q \ \langle \texttt{im\_end} \rangle
4. 语义不变:角色和内容完整保留,变的只是“排版方言”,问答逻辑不受影响。
格式转换是“翻译剧本”而不是“改编剧情”。台词、角色一字不串,换个方言版照样满堂彩。
工程落地实践
正式彩排前,导演会做三件琐事:统一剧本模板、核对道具数量、反复走台。工程上让对话格式落地,也是同一套“笨功夫”——把看似简单的事情做到无死角。
实际项目里最常见的坑是“手拼字符串”:今天加个空格、明天少个换行,模型表现时好时坏,还查不出原因。正规做法是把格式封装成模板函数,所有入口统一调用,杜绝散装拼接。这就是我们在 Python 演示里要做的事。
落地还要盯住三件事:第一,用 tokenizer 或启发式公式估算 token 数,给裁剪提供依据;第二,调试时把真正发给模型的文本打印出来,亲眼检查角色标记和换行有没有变形;第三,max_tokens 要预留充足,否则长回答会被拦腰截断。加上裁剪保底,一套对话链路的稳定性立刻上一个台阶。
1. 中文计数:$c(s)$ 统计这段文本里的中文字符数,中文是 token 消耗的大头。
2. 长度计数:$L(s)$ 统计文本的字符总长度,覆盖英文、数字、标点。
3. 加权求和:$\alpha \cdot c(s) + \beta \cdot L(s)$ 把两类字符按不同权重折算成 token 数。
4. 向上取整:$\lceil \cdot \rceil$ 确保估算不偏低,为裁剪决策留出安全余量。
一场成功的演出,靠的不是演员临场发挥,而是彩排时那本印得规范、检查过一百遍的剧本。对话格式工程化,就是把这本剧本固定成流程,让每一次请求都稳稳当当地照本宣科。
AI 应用场景
智能客服多轮售后
阶段:推理部署 / 对话管理
解决的问题:传统客服走“菜单树”脚本,用户换个说法就卡死,面对“那改地址呢”这类依赖上一轮的指代更是无从处理。AI 用 ChatML 把每一轮追问拼进上下文,模型自动理解“那”指代的是上一轮说的订单。
具体案例:某电商售后机器人接入大模型后,系统消息固定为“你是一位耐心的客服,只能依据订单库信息回答”。用户先问“手机怎么还没发货”,再追问“那能改地址吗”,两轮消息按 ChatML 拼接后,模型正确识别出改的是“手机订单”,并继续索要新地址。当轮次超过 8 轮时,裁剪逻辑自动丢弃最早的 2 轮,保住系统人设。
微调数据统一格式管线
阶段:数据工程 / 监督微调
解决的问题:网上爬来的对话数据格式混乱,有的带前缀、有的带结尾符,直接喂给模型会让它把“格式噪音”也背进参数里。统一转成 ChatML 再训练,模型才能学到稳定的角色边界。
具体案例:团队收集 10 万条客服对话,写转换器把各种方言统一成“system + 多轮 user/assistant”形制,超长样本按“保开头、保末尾追问、裁中间”的原则截断。微调完成后,推理端强制使用同一套 ChatML 模板,线上评测得分回升 12%。
开源模型对话兼容适配
阶段:模型部署 / 推理平台建设
解决的问题:开源模型各有各的“剧本方言”(Vicuna、ChatML、Qwen 系),产品切换模型时提示词全部重写,维护成本极高。推理平台需要一层“翻译官”。
具体案例:推理平台在路由层维护统一的内部消息结构,出站前按目标模型的 chat_template 渲染。从 Vicuna 微调的小模型切换到 ChatML 微调的大模型,只改一行配置,对话历史自动完成格式转换,上层业务零改动。
Python 演示
# -*- coding: utf-8 -*-"""对话格式构建器:ChatML / Vicuna 与上下文裁剪示例""" def estimate_tokens(text): """启发式估算 token 数:中文约 1.5 token/字,英文约 0.3 token/字符。""" cn = sum(1 for ch in text if "\u4e00" <= ch <= "\u9fff") other = len(text) - cn return int(cn * 1.5 + other * 0.3) + 1 class ChatMLFormatter: """ChatML 格式:<|im_start|>role\\ncontent<|im_end|>""" def __init__(self, system_prompt=""): self.system_prompt = system_prompt def build(self, messages): parts = [] if self.system_prompt: parts.append("<|im_start|>system\n" + self.system_prompt + "<|im_end|>") for role, content in messages: parts.append("<|im_start|>%s\n%s<|im_end|>" % (role, content)) parts.append("<|im_start|>assistant\n") return "\n".join(parts) class VicunaFormatter: """Vicuna 格式:SYSTEM / USER / ASSISTANT 前缀""" def __init__(self, system_prompt="A chat between a curious user and an artificial intelligence assistant."): self.system_prompt = system_prompt def build(self, messages): parts = ["SYSTEM: " + self.system_prompt] for role, content in messages: if role == "user": parts.append("USER: " + content) else: parts.append("ASSISTANT: " + content + "</s>") parts.append("ASSISTANT:") return "\n".join(parts) def trim_history(formatter, messages, max_tokens=2048, protect_system=True): """从最旧开始裁剪历史,尽量保留系统消息与最新一问。""" keep = list(messages) while estimate_tokens(formatter.build(keep)) > max_tokens and len(keep) > 1: if protect_system and keep[0][0] == "system": keep = keep[:1] + keep[2:] else: keep = keep[1:] return keep def main(): chatml = ChatMLFormatter("你是一位耐心的手机客服。") chat = [ ("user", "我想查一下话费"), ("assistant", "好的,请稍等。本月话费 128 元。"), ("user", "那流量还剩多少"), ("assistant", "本月剩余 20G 流量。"), ("user", "能帮我改成 50G 的套餐吗"), ("assistant", "可以的,马上为您办理。"), ] text = chatml.build(chat) print("ChatML 输出:\n" + text) print("预估 token:", estimate_tokens(text)) kept = trim_history(chatml, chat, max_tokens=120) print("\n裁剪后剩余轮次:", [(r, c[:8]) for r, c in kept]) vicuna = VicunaFormatter() text2 = vicuna.build(chat) print("\nVicuna 输出:\n" + text2) print("预估 token:", estimate_tokens(text2)) if __name__ == "__main__": main()
parts.append("<|im_start|>%s\n%s<|im_end|>" % (role, content))ChatML 消息单元的拼装核心,角色、换行、正文、结束暗号一个都不能少。parts.append("<|im_start|>assistant\n")在对话末尾补一个“assistant 开场标记”,相当于把话筒递给模型让它接着写。if role == "user": parts.append("USER: " + content)Vicuna 只认两个角色,靠前缀字样的不同区分谁在说话。parts.append("ASSISTANT: " + content + "</s>")Vicuna 的助手回复以</s>收尾,标记这句话说完了。cn = sum(1 for ch in text if "\u4e00" <= ch <= "\u9fff")用 Unicode 区间筛出中文字符,为启发式 token 估算提供输入。while estimate_tokens(formatter.build(keep)) > max_tokens and len(keep) > 1:只要预估超预算且还有得裁,就继续循环,保证至少留下最后一问。keep = keep[:1] + keep[2:]系统消息在首位时保护它,优先丢掉的是一条最老的历史轮次,而不是系统人设。text = chatml.build(chat)调用统一的模板函数生成最终请求文本,避免散装手工拼接。
常见误区
误区“我试过 ChatML,多加个空格少个换行也没什么大区别嘛,模型照样正常回复。格式这种东西,意思到了就行。”
正解格式差一点,短期看模型“硬撑”也能答,但长对话中角色边界会逐渐模糊。比如 <|im_start|> 后面忘了换行,模型可能把角色名当成正文;更致命的是,微调时喂的格式与推理时不一致,模型会直接“神经错乱”。剧本上的逗号位置错了,演员不会按你脑补的句子念。
为何常见:大模型容错性强,小错误不会立刻暴露,让人误以为格式无关紧要,直到线上出问题才后悔。
误区“我在提示词里手写 `<|im_start|>user`,模型不也能正常回复吗?说明它就是个普通字符串。”
正解特殊 token 在词表中是独立编号,不参与普通分词。如果你手写 <|im_start|> 而分词器没识别它,它会被切成几个普通字符——模型看到的是“字”,不是“标记”。就像你把舞台暗号抄在台词里念出来,演员只会当它是句废话。
为何常见:人眼看来 <|im_start|> 就是一行字符,容易忽略“分词”这一层隐形加工的存在。
误区“模型支持 128K 上下文,那我历史对话全塞进去,信息越全回答越准,不是天经地义吗?”
正解塞满有两个问题:一是没有留给生成的空间,模型回答到一半就被截断;二是历史过长时,模型对早期信息的注意力显著衰减,早期内容变成“被记住的噪音”。正确做法是预留 max_tokens,并适时裁剪、摘要或滑动窗口。
为何常见:厂商宣传大窗口,用户误以为“全用上”等于“用得好”,忽略了注意力机制的天生局限。
误区“反正都是表达'用户说 + 助手说',我上一轮用 ChatML,下一轮换 Vicuna,模型应该能理解吧?”
正解模型在微调时把特定格式“背”进了参数。推理时混用格式,等于给背熟 ChatML 剧本的演员递 Vicuna 台本:开头还能应付,多轮之后角色标识对不上,必然串戏。微调与推理必须使用同一种方言。
为何常见:两种格式看起来都在表达同样的语义,人眼分不出致命差异,但模型只认它被训练时的那一种排版。
误区“系统消息不是对话内容,它是独立配置,模型会一直记得,不会被上下文长度影响。”
正解系统消息也是普通 token,同样占用上下文。裁剪逻辑若实现不当,它可能和早期历史一起被丢掉;一旦系统消息被裁,模型的“人设”约束当场消失。所以重要约束要么放在受保护的位置,要么每隔几轮在 user 消息里重申一遍。
为何常见:人们把系统消息当作“对话之外的配置”,忘了它最终也是被拼接进同一段文本、同吃一份 token 预算。
面试题
Q1. ChatML 中用于标记一条消息开始的是哪个特殊 token?
- A.标记消息开始的
<|im_start|>← 正确答案 - B.标记消息结束的
<|im_end|> - C.Llama 家族的序列起始符
<s> - D.Llama 家族的序列结束符
</s>
答案:A。<|im_start|> 是 ChatML 的开场暗号,宣布一条消息开始;<|im_end|> 是谢幕暗号。<s> 与 </s> 属于 Llama 家族,不是 ChatML 定义的角色标记。认准“start 对应开始,end 对应结束”即可。
Q2. Vicuna 格式中助手回复的前缀标记是什么?
- A.用户消息前固定的前缀标识 USER:
- B.助手回复前固定的前缀标识 ASSISTANT:← 正确答案
- C.ChatML 中助手角色的书写格式规范
- D.系统开场白里固定的引导前缀文本
答案:B。Vicuna 的极简方言只用 USER: 和 ASSISTANT: 两个铭牌区分角色,答案自然是 B。A 说的是用户消息前缀,C 是 ChatML 的写法,D 是 SYSTEM 前缀,均不符合“助手回复前缀”的题干。
Q3. 多轮对话拼接后总 token 数超过上下文窗口时,最合理的处理方式是?
- A.直接截断用户最新提出的问题
- B.裁剪最旧历史并保留最新提问← 正确答案
- C.无限调高生成上限 max_tokens
- D.干脆放弃系统消息这部分内容
答案:B。最新的用户提问是模型要回答的对象,绝不能丢;最旧的历史对当前回答的贡献最小,应当先裁。系统消息通常也应保护而不是第一个放弃,所以 D 不对。C 中 max_tokens 由模型窗口硬性限制,不能无限调高。
Q4. 对话格式中的特殊 token 通常承担哪些作用?
- A.标记每一条消息的起始位置← 正确答案
- B.标识不同发言人的角色身份← 正确答案
- C.压缩历史对话的 token 长度
- D.为模型显示可见的普通提示
答案:AB。特殊 token 的职责是搭建结构——开场、收尾、标识角色,所以 A、B 正确。压缩历史是摘要策略干的事,与 token 本身无关;特殊 token 对用户不可见,也不是“普通提示”,C、D 错误。
Q5. ChatML 中 <|im_end|> 的主要作用是什么?
- A.表示整段多轮对话全部结束
- B.表示当前这一条消息的结束← 正确答案
- C.用来切换下一个发言人的角色
- D.让模型立即停止生成全部输出
答案:B。<|im_end|> 是“散场”标记,但它只结束当前这一条消息,不是整个对话;对话末尾模型停不停,取决于专门的停止符或推理参数。它也不负责切换角色,切换角色靠下一条消息的开场标记。
Q6. 一个只用 Vicuna 格式微调的模型,推理时改用 ChatML 格式会发生什么?
- A.模型完全不会受到任何影响
- B.只是生成速度略有下降而已
- C.角色边界混乱导致质量下降← 正确答案
- D.程序一定会直接报错崩溃掉
答案:C。模型在微调时把 Vicuna 的排列习惯“背”进了参数,换 ChatML 等于给背熟一种剧本的演员递另一种台本,多轮后角色边界必然模糊、质量下降。这是语义层面的退化,不一定会崩溃报错,所以 D 过于绝对。
Q7. 上下文窗口管理中,常用的历史压缩策略有哪些?
- A.裁剪最早的几轮历史对话← 正确答案
- B.把历史内容压缩成一段摘要← 正确答案
- C.滑动窗口只保留最近几轮← 正确答案
- D.无限扩大窗口直到完全够用
答案:ABC。裁剪最旧、摘要化、滑动窗口是三大主流手段,A、B、C 都对。D 不可行,窗口大小由模型结构决定,工程上无法“无限扩大”。预算思维是核心:历史必须让位于最新的问答。
Q8. 极端裁剪场景:历史上所有轮次和系统消息都被裁掉,只保留最后一条 user 消息,以下哪种说法正确?
- A.模型彻底失忆导致回答必然失败
- B.会当成第一轮但立刻分不清角色
- C.末尾的助手开场标记仍能驱动回复← 正确答案
- D.模型会自动恢复被裁剪掉的历史
答案:C。只要消息仍按模板拼装,末尾保留 <|im_start|>assistant\n,模型就知道“该我接话”了并继续生成。裁剪会丢失人设和事实,但格式本身仍在指挥模型扮演助手。D 是幻觉,模型不会自动恢复已裁剪内容。
Q9. 设计一套新的对话格式时,需要重点考虑哪些因素?
- A.与预训练和微调格式保持一致← 正确答案
- B.角色边界表达足够清晰明确← 正确答案
- C.特殊 token 不与正文内容冲突← 正确答案
- D.模板越长越能体现专业水平
答案:ABC。格式必须与模型“背过”的方言一致,角色边界要清楚,特殊 token 要与普通文本区分开,A、B、C 都是关键设计原则。D 恰恰相反——冗长模板浪费 token、降低鲁棒性,简洁明确才是好格式。
Q10. 工程上常用的 token 估算近似方法是什么?
- A.中文字符按 1.5、英文按 0.3 估算← 正确答案
- B.中文字符按 0.3、英文按 1.5 估算
- C.所有字符一律按 1.0 估算
- D.所有字符一律按 0.5 估算
答案:A。中文信息密度高,通常每字消耗更多 token,约 1.5;英文、数字等密度低,约每个字符 0.3。B 把权重写反了,C、D 一刀切忽略了中英文的差异,都会导致预算估算严重失准。