ARTICLE / 工具
400MB的AI会话日志怎么读:只看尾部40MB,0.06秒拿到任务结论
400MB 的 AI 会话日志怎么读:只看尾部 40MB,0.06 秒拿到任务结论
一个跑了一整天的 AI 编码代理,会话日志能滚到多大?我手上这个真实文件是 382.9MB——Codex CLI 的 rollout-*.jsonl 会话日志,追加写,首行时间戳是当天 0 点刚过(UTC 16:03:00,即北京时间 00:03),一路记到一个长跑任务收尾。里面的内容绝大多数是过程流量:工具调用的原始输入输出、推理过程、token 计数,真正有信息量的结论——任务什么时候完成、最终答复是什么、用户最初要求了什么——稀疏地散在其中。
问题很具体:想快速回答"这个任务跑完了吗、结论是什么",把 400MB 全量载入必然爆上下文,整文件解析也慢。这篇讲一个直接有效的做法:seek 到文件末尾开一个 40MB 窗口,只解析尾部。在一个 382.9MB 的真实文件上,这个方法 0.06 秒命中了 task_complete 记录,拿到了完整结论字段。
先理解 jsonl 追加写的结构,方法才能成立
rollout 日志是逐行 JSON(jsonl),按时间顺序追加。一天内多轮任务写进同一个文件时,中间几百 MB 都是工具调用流,而结论性事件——本例实测确认的是 task_complete(任务完成,携带 last_agent_message、全程耗时等字段)——要么在文件头部(任务目标,user_message 类事件),要么在每轮任务收尾处。顺带一提,我第一版猜的 final_answer 类型在这份日志里并不存在,猜结构不如先统计。
方法成立的前提就这一条:追加写 + 结论靠后。凡是满足这个前提的 jsonl(AI 会话日志、任务执行流水、爬虫去重记录),都可以套用。
40 行代码的核心:seek、丢半行、按真实结构过滤
实现只需要标准库。第一步 os.path.getsize 探大小,决定窗口(40MB 足够覆盖数轮完整任务收尾);第二步 f.seek(size - WINDOW) 后先 readline() 丢弃第一个半截行——seek 点几乎必然落在某行中间,不丢这一行,json.loads 会一直抛异常;第三步逐行解析,按记录类型过滤。
我在 382.9MB 真实文件上跑通了完整流程。关键实测数据:尾部 40MB 窗口共 175 行 JSON 记录,命中 1 条 task_complete 事件,耗时 0.06 秒。这条记录带出了任务全程指标——duration_ms=11027450(全程约 184 分钟)、time_to_first_token_ms=353506,以及 agent 的收尾消息原文。
这里有个实测换来的教训:过滤条件必须对着真实结构写,不能对着想象写。我第一版脚本按顶层字段的 type == 'task_complete' 过滤,命中 0 条。把尾部 2MB 的记录类型统计出来才发现,Codex 日志的真实结构是 type: "event_msg" 包着 payload.type: "task_complete"——完成事件是 event_msg 的子类型,顶层只有 event_msg / response_item / token_usage_record / turn_context 四种。改成读 payload.type 后立即命中。写日志分析器之前,先花十秒钟统计一下文件的类型分布,比按记忆猜结构可靠得多。
尾部没有完成事件,不等于出错了
一个容易误判的边界:长跑产线任务的尾部 40MB 可能全是中间工具流,task_complete 在更早位置。统计尾部 2MB 的类型分布,实测得到 item_completed 45 条、token_count 18 条、reasoning 17 条、custom_tool_call 及其输出各 14 条,另有 task_complete 和 task_started 各 1 条——过程流量占绝对多数,结论事件稀疏。如果某个窗口里连一条结论事件都没有,正确动作是扩大窗口重试(40MB→60MB),或者先看尾部 10MB 有无锚点再决定要不要全量扫,>1GB 的文件可以按窗口二分定位。把"尾部没搜到"当成"任务失败"是错误的——它只说明结论不在这个窗口里。
另一个实用细节:任何大文本分析产物先重定向到 scratch 文件落盘,再分段读取查看。几百 KB 的提取结果直接打到终端,输出必被截断,落盘后想怎么看都行。
这个方法的适用边界
三个前提缺一不可:文件是追加写的 jsonl;你要找的结论性事件靠后;单行记录可以独立解析(半截行丢弃不影响后续)。反过来,如果需要全文件统计(比如全天 token 消耗汇总),尾部窗口就不够了,得全量流式扫描——但那也是逐行流式读,不是整文件载入内存。
对经常和 AI 代理会话日志打交道的人,这 40 行脚本值得存一个模板:探大小、定窗口、丢半行、按真实 payload 结构过滤、产物落盘。下次面对 400MB 甚至几个 GB 的日志,先 seek 到尾部,0.06 秒就能知道任务跑成什么样了。
(实验数据来自本机真实 Codex 会话日志的尾部提取实测,提取脚本与输出已随文存档;文中任务耗时等指标为该次记录的原始字段值。)
本文面向授权安全研究与防御建设,未经授权对任何系统实施文中技术属违法行为。