SyFI TraceLab
数据助手
正在读取公开 SYFI 数据池
覆盖 Claude 和 Codex 的 357,161 个智能体步骤,可公开分享。
答案会在沙箱中运行真实 DuckDB/Python,并展示代码
全部图表
会话
一段连续的工作记录,通常包含多个请求或问题。
请求
从一次用户输入到智能体最终响应的完整过程。
智能体步骤
请求内部的一次模型调用。
用户触发步骤
由用户输入启动的智能体步骤。
工具触发步骤
由工具结果启动的智能体步骤。
问题

在单个编码会话内,总输入长度(前缀 + 追加)从一个智能体步骤到下一个是如何变化的——当它缩小时,那是计数抖动还是一次真正的上下文压缩?

表格

All steps

MetricClaudeCodex
Steps137,629210,221
Positive (growth) %99.60%96.56%
Negative (reduction) %0.39%3.43%
  Micro %0.06%1.08%
  Ordinary %0.09%1.73%
  Major reduction %0.24%0.62%
Avg positive growth1,7191,838

User-initiated steps

MetricClaudeCodex
Steps16,92717,033
Positive (growth) %98.21%68.63%
Negative (reduction) %1.71%31.32%
  Micro %0.37%12.47%
  Ordinary %0.57%18.09%
  Major reduction %0.77%0.76%
Avg positive growth1,5272,742

Tool-initiated steps

MetricClaudeCodex
Steps120,702193,188
Positive (growth) %99.79%99.03%
Negative (reduction) %0.21%0.97%
  Micro %0.02%0.07%
  Ordinary %0.03%0.29%
  Major reduction %0.16%0.61%
Avg positive growth1,7461,783
表 1按步骤触发来源划分的同会话上下文变化:每一步相对会话中上一步的总输入长度(前缀 + 追加 token)变化,分为增长和缩减区间。

上下文几乎总是逐步骤增长(论文的 tab:context_growth_and_compaction)。在所有步骤中,窗口在 99.60% 的 Claude 步骤和 96.56% 的 Codex 步骤上增长——新的用户输入、工具结果以及输出全都叠加到先前的上下文之上——每个增长的步骤增加约 ~1.7k–1.8k 个 token。缩减很罕见,且呈现提供商特性:对 Claude 而言,负值只占极小的 0.39%,且偏向 major(0.24%,真正的压缩),而 Codex 减少的频率约高出 ~9×(3.43%),且大多落在无害的 micro/ordinary 区间。这一分布还按触发器集中:Codex 的缩减堆积在用户触发步骤上(其中 31.3% 的步骤缩小,对比工具触发的 0.97%),而两个提供商的工具触发步骤都有约 99% 的时间在增长。

参考
实验概览

trace 中的每一行是一个智能体步骤。本实验按顺序遍历一个会话的各个步骤,记录每个步骤的总输入长度prefix_tokens + newly_append_tokens)变化——正的 delta 表示窗口在增长,负的 delta 表示在缩小——并把每一次下降归入三个桶之一。

方法与假设:

  • 一个步骤的总输入prefix_tokens + newly_append_tokens(缓存的前缀加上新追加的输入)。每个步骤的指标是该数量相对于同一会话中上一个被看到的步骤的有符号 delta。
  • 配对。 只有当当前步骤的第一个 timing event 是一个可见的输入事件——即一个 user_message 或一个 tool_result(该步骤的触发器)——且该会话此前已被看到过时,才会发出一个增长事件。previous 步骤是按 trace 顺序为该会话最后观察到的任意步骤,与其触发器无关。会话内的步骤按 ingestion 顺序排序(round_pk = 文件顺序),即迁移到 DuckDB 之前的扫描所用的同一行顺序定序。
  • 缩减桶(阈值来自 artifacts/utils/growth.py,可在 CLI 覆盖):
    • micro-reduction —— 下降 ≤ 1024 个 token(计数抖动);
    • major-reduction —— 下降 ≥ 50000 个 token(一次真正的上下文压缩);
    • ordinary reduction —— 介于两者之间的任何情况。
  • 报告的触发器。 Summary 行按三种方式切分——allusertool_result——依据当前步骤的触发器,并按 scope(merged 加上每个提供商)切分。
  • trace_facts overview summary 共用增长 helper(build_growth_statsreduction_bucket、CSV writer)。
代码结构

这是一个**混合式(hybrid)**实验:trace DuckDB 负责单遍 ingest,而 Python 负责按会话的定序与增长分桶。

  • iter_growth_events_from_db(con) —— 唯一的数据加载代码。两条按 ingestion 顺序的查询(步骤标量 ORDER BY round_pk,以及每个步骤在 event_index = 1 处的第一个 timing event,用于取触发器类型和时间戳),在 Python 中借助一个 last_by_session map 遍历,为每个合格的步骤发出一个增长事件——精确复现旧的逐行 JSONL 扫描。
  • _epoch_us_to_iso(...) —— 时间戳以整数 epoch-microseconds 拉取(native/wasm 一致),并重建为规范的 …Z ISO 字符串,因此时间戳列与迁移到 DuckDB 之前的输出逐比特一致。
  • build_growth_stats(...) / reduction_bucket(...) / write_summary_csv(...) / write_events_csv(...) —— artifacts/utils/growth.py 中未改动的共享 helper。
  • write_filtered_events_csv(...) —— 稳定排序后的 reduction / micro-reduction 下钻。

数据层位于 artifacts/utils/trace_db.py(参见 artifacts/utils/DB_SCHEMA.md)。

运行方式
# default merged trace (materialized to a temp DuckDB cache on first use)
uv run python artifacts/session/total_input_growth/analyze.py

# a specific trace
uv run python artifacts/session/total_input_growth/analyze.py -i trace/sample.jsonl

# a prebuilt DB (run_all.py's build-db step passes this), into a chosen dir
uv run python artifacts/session/total_input_growth/analyze.py --db /tmp/trace.duckdb -o /tmp/out

旋钮:--micro-reduction-max-tokens / --major-reduction-min-tokens 重新调校缩减桶, --no-drilldowns 只写 summary,--limit-events 在稳定排序后对每个下钻设上限, 而 --summary-csv / --events-csv / --reductions-csv / --micro-csv 覆盖各自的路径。

输出
  • total_input_growth_summary.csv —— 按 (scope, trigger) 的增长/缩减桶计数及 delta 统计。
  • total_input_growth.md —— 论文 float tab:context_growth_and_compaction 的 GFM 镜像 (Claude vs Codex,按步骤触发器),渲染在网页详情页上。
  • total_input_growth_events.csv —— 每一个同会话的增长事件,按 trace 顺序。
  • total_input_reductions.csv —— 仅 negative-delta 事件(全部三个缩减桶)。
  • total_input_micro_reductions.csv —— 仅 micro-reduction 事件。

无图。

SyFI TraceLab · 实验详情