Skip to content

消息、内容、上下文与能力矩阵 ​

先分开三种身份 ​

业务请求标识一次用户目标,模型调用标识一次生成,工具调用标识一次执行意图。重试生成时业务 ID 不变、调用 ID 改变;同一业务可能产生多次工具调用。将它们都叫 session_id,会在重试时无法判断是新动作还是重放。

模型请求包含指令、用户内容、历史和可选工具。角色是 API 契约,不是文字中写“system:”即可升级权限。检索网页和工具返回均属于不可信数据,即使其中包含命令,也不能冒充开发者指令。

内容块用显式 type 区分文本、图像、文件和工具结果。不同平台的同名字段并不保证等价:Claude 顶层 system、Gemini parts、Responses input items 都需映射;无法表达的能力应拒绝或走显式扩展,不应静默丢弃图片。

第一个可运行实验:按完整轮次裁剪 ​

使用 Python 3.12,保存 context.py,运行 python context.py,无第三方依赖。这里 token 数是已知教学输入,不是用字符数冒充真实 tokenizer。

python
def choose(turns,window,reserved_output,fixed_input):
    remaining=window-reserved_output-fixed_input
    if remaining<0:raise ValueError('fixed context exceeds budget')
    picked=[]
    for turn in reversed(turns):
        if turn['tokens']>remaining:break
        picked.append(turn)
        remaining-=turn['tokens']
    return list(reversed(picked))
turns=[{'id':'a','tokens':20},{'id':'b','tokens':30},{'id':'c','tokens':40}]
assert [t['id'] for t in choose(turns,100,20,20)]==['c']
assert [t['id'] for t in choose(turns,130,20,20)]==['a','b','c']
print('context budget passed')

固定指令占 20、预留输出占 20,100 的窗口只余 60。最新轮 c 占 40 后,只余 20,不能再放 b,因此保留连续后缀 c。这里故意不跳过 b 去捡更早的 a,因为旧结论可能依赖被删掉的中间轮。真实系统还要把一次工具请求及结果视为不可分割单元。

摘要与缓存解决不同问题 ​

摘要减少输入,代价是丢失细节。保存摘要的来源 ID、时间和未解决问题,关键数字仍从原始材料读取。缓存复用计算,不缩小逻辑上下文。稳定指令与工具定义尽量放在稳定前缀,动态时间戳和本轮问题放在后面;命中须看平台计量,不以“第二次快了”判断。

真实预算用平台 tokenizer 或 count_tokens 接口,并留工具描述、系统内容与多模态开销余量。不同模型有不同上下文与输出上限;某些推理模型的输出预算还包含非可见推理开销,不能只数最终文本。

能力矩阵应记录“已验证的组合”:模型、API 版本、文本/图像、原生 schema、工具、流式、缓存、区域和认证入口。仅记录供应商名无法判断某个模型是否支持工具与结构化输出同时使用。模型退役、SDK 升级与区域策略变化都应触发矩阵重验。

具体首次联网调用见 Responses 请求、Claude 消息 和 Gemini 输入。

练习 ​

把窗口改为 120,输出预留 20、固定输入 20。预期保留哪些轮?再令固定输入为 110,要求明确报错,不返回空历史掩盖预算失败。

先记录自己的输出与解释,再核对本章答案。

用心记录每一步成长