跳到正文

devlog/token-math/how-much-context-to-send-and-the-cost-of-pasting-whole-files-62.md

别急着粘贴整份文件:在终端量出上下文的真实成本

先拿一次超时重试排查做实验

排查请求超时,我最容易做的事是把整个客户端文件贴给模型。省了挑代码的时间,却把导入、类型声明和无关接口一起送了过去。文件越长,问题也越容易埋在背景里。这次用同一个问题发两次请求:一次带整份文件,一次只带相关代码,直接看接口返回的用量。

下面使用 Bash、curl、jq,以及项目里真实存在的文件。实验会产生两次调用费用;先选一个不含密钥、客户数据和生产日志的源码文件。

把密钥、模型和实验目录准备好

我用 Fluxo 接这次实验:一个密钥和 https://api.fluxorelay.com 这个基础地址,可以访问 Claude、GPT、Gemini、DeepSeek、Kimi、GLM、Qwen、Grok 等系列。它也适配 Claude Code、Codex、Gemini CLI 和 OpenAI SDK;这里直接用 HTTP,方便保存原始用量。

先输入密钥,关闭终端输入回显,再创建独立的临时目录:

read -r -s -p 'Fluxo API Key:' FLUXO_API_KEY; printf '\n'; export FLUXO_API_KEY

export FLUXO_BASE_URL='https://api.fluxorelay.com'; WORK_DIR=$(mktemp -d) — 查询接口实际返回的模型标识。可以选择 Claude Sonnet 5.5;展示名称与请求标识未必相同,不要凭名称猜 ID。

curl --fail-with-body -sS "$FLUXO_BASE_URL/v1/models" -H "Authorization: Bearer $FLUXO_API_KEY" | jq '.data[] | {id, name}'

read -r -p '粘贴要使用的模型 ID:' FLUXO_MODEL

从整份文件缩到一个完整调用链

进入项目根目录,输入超时处理所在的文件路径。先搜索关键字,再选择相关函数的起始行。

read -r -p '源码文件路径:' SOURCE_FILE

cp -- "$SOURCE_FILE" "$WORK_DIR/full.txt" — rg -n 'timeout|retry|AbortController' -- "$SOURCE_FILE"

read -r -p '相关代码起始行号:' START; END=$((START + 79)); sed -n "${START},${END}p" "$SOURCE_FILE" > "$WORK_DIR/slice.txt"

cat "$WORK_DIR/slice.txt" — 八十行只是起点。确认片段包含函数入口、超时取消、异常处理和重试出口;如果函数被截断,就调整范围。依赖外部配置时,补上对应定义。缺失关键条件的短提示,通常只会换来一次追问。

用相同问题发送两份上下文

固定模型、问题和输出上限,只改变代码内容。下面生成两个请求文件,JSON 转义交给 jq,避免源码里的引号破坏请求。

QUESTION='检查以下代码:请求超时后,重试是否可能重复提交?请引用代码说明;缺少定义时明确指出,不要猜测。'

for variant in full slice; do jq -n --arg model "$FLUXO_MODEL" --arg question "$QUESTION" --rawfile context "$WORK_DIR/$variant.txt" '{model:$model,messages:[{role:"user",content:($question + "\n\n" + $context)}],max_tokens:800,stream:false}' > "$WORK_DIR/$variant.request.json"; done

for variant in full slice; do curl --fail-with-body -sS "$FLUXO_BASE_URL/v1/chat/completions" -H "Authorization: Bearer $FLUXO_API_KEY" -H 'Content-Type: application/json' --data-binary "@$WORK_DIR/$variant.request.json" -o "$WORK_DIR/$variant.response.json" || break; done

读取 usage,别把字符数当账单

提取两次结果,先确认没有接口错误,再比较输入用量与回答质量。

for variant in full slice; do jq --arg variant "$variant" '{variant:$variant,error:.error,usage:.usage,answer:.choices[0].message.content}' "$WORK_DIR/$variant.response.json"; done

在兼容响应中,prompt_tokens 通常表示输入 token,completion_tokens 表示输出 token;缓存明细要看实际返回字段。不要把缺失字段解释成零,也不要把文本字节数换算成精确 token。中文、标识符和代码标点的切分都可能不同。

这两次请求只能做一次现场对照。输出长度会波动,缓存状态也可能不同,因此总 token 更少不必然意味着账单按同比例下降。

把缓存命中和上下文质量一起算进去

Fluxo 按实际 token 计费,缓存读取和写入也计费,没有月费。核算时按对应模型的计费说明,分别计算普通输入、缓存读取、缓存写入和输出;先确认各字段是否包含在输入总量里,避免重复相加。没有具体费率,就先报告用量差异,不编一个节省金额。

日常我按这三个条件决定是否继续补代码:

  • 模型已经定位到具体分支,并且证据完整时,我就停止追加背景文件。
  • 模型指出缺少配置或调用方时,我只补充对应定义和实际参数。
  • 问题涉及跨模块状态或初始化顺序时,我扩大上下文并保留文件路径。

稳定的项目约定可以放在前面,变化的报错和代码放在后面,但是否命中缓存仍以接口和账单为准。整份文件适合需要完整结构的问题;局部排查则先给一条完整调用链。

想用自己的项目跑这组对照,可以创建一个 Fluxo 账户。它也提供邀请分成:受邀用户付费后,邀请人可获得相应分成。

缓冲区里的下一篇

一分钟注册,赠送额度足够把文中提到的模型都试一遍。 注册 →