别急着粘贴整份文件:在终端量出上下文的真实成本
先拿一次超时重试排查做实验
排查请求超时,我最容易做的事是把整个客户端文件贴给模型。省了挑代码的时间,却把导入、类型声明和无关接口一起送了过去。文件越长,问题也越容易埋在背景里。这次用同一个问题发两次请求:一次带整份文件,一次只带相关代码,直接看接口返回的用量。
下面使用 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 账户。它也提供邀请分成:受邀用户付费后,邀请人可获得相应分成。