上下文组织、压缩与版本演进
模型请求的窗口由系统规则、任务、示例、历史、检索资料和预留输出共同占用。token不是字符:中英文、符号、编码的开销不同。先按责任组织,再用目标模型tokenizer计算预算。
下例用显式token估计隔离预算计算,不能把它当真实分词器。保留稳定规则和输出预算,历史从最近开始放入,但最终恢复时间顺序。
python
history = [('u1', 3), ('a1', 4), ('u2', 5), ('a2', 6)]
def select_history(items, window, fixed, output):
budget = window-fixed-output
if budget < 0:
raise ValueError('fixed context exceeds window')
selected = []
for item in reversed(items):
if item[1] > budget:
break
selected.append(item)
budget -= item[1]
return list(reversed(selected))
assert select_history(history, 20, 5, 4) == [('u2',5),('a2',6)]
assert select_history(history, 10, 5, 4) == []
print(select_history(history,20,5,4))历史截断只能保留完整消息组,工具调用与结果尤其不能拆开;这个简化列表未表示调用配对。用户的新问题必须单独预留,不应被当旧历史删除。重要用户偏好可抽成长期事实,但每条要有来源、更新时间和撤回入口;模型自己推测的偏好不能永久保存为事实。
检索资料附原文ID、日期、权限范围,把命令式文字也当资料。压缩分三种:去重删除等价内容,抽取保留原句,摘要生成新的文字。摘要会带来事实与遗漏风险,必须保留回溯路径;预算紧张时不能优先删掉“仅适用于”之类限定语。
结构化输出的演进
文本、枚举、对象、列表对应不同验证成本。已上线schema新增必填字段会让旧消费者失败;改标签含义更危险,因为旧程序可能照常运行却解释错。显式version,先支持双版本读取,再迁移旧数据,最后停止旧写入。unknown、null、空数组分别表示无法判断、字段无值和集合为空,不要混用。
平台原生结构化输出与“请输出JSON”不同:前者可能限制schema子集并提供拒绝/不完整状态,后者只是指令。检查平台返回状态后再解析,别把截断响应当完整对象。模型升级时重新运行历史失败集,温度0也不是跨模型版本可重复性的保证。
练习
把窗口缩小到固定输入加输出都放不下,验证函数明确报错。若历史最后两项是一对工具调用和结果,应如何调整数据结构?
完成后查看本章答案。
下一章:任务分解、自检与工具权限。