Codex 费用优化:搭 repomix 与 markitdown 把 Token 消耗降到三成
2026/9/24 20:50:33 网站建设 项目流程

上个月我收到 Codex 的账单,第一反应是以为自己被谁刷了卡。排查了一圈,发现既没有死循环,也没有异常的调用,就是正常用了两周,Token 消耗比我预估的高了快一倍。后来我把每次会话的输入输出拉出来对了一遍,才意识到问题根本不在"多问了几个问题",而是上下文的重复装载和输入噪音频频发生。这篇文章要说的两个开源项目,就是专门针对这两类浪费做优化的:一个负责把代码库压缩成一份干净、紧凑的 Prompt,另一个负责把 PDF、Word、Excel 这类文档转成不掺水的 Markdown。两者配合,我实测下来 Token 消耗能压到原来的三成左右。

如果你平时用 Codex 处理仓库级任务,或者经常往里面塞各种文档,这两个工具应该都能帮上忙。为了让你能判断哪个环节最该改,我先不急着上项目,而是把 Codex 的 Token 消耗账目拆开给你看。

1. 先算清楚:Codex 的 Token 究竟花在了哪里

1.1 三笔容易忽略的 Token 开销

Codex 和普通聊天对话不一样。普通对话里,你发一条、模型回一条,Token 消耗基本就是"内容本身的长度"。Codex 是智能体(agent)模式,它会自己分析任务、决定要读哪些文件、执行哪些命令、观察输出、再决定下一步。这意味着同一个会话里,它会反复发送当前累积的上下文。

第一次开销在上下文重发。每执行一步,Codex 都可能把之前的对话历史、文件内容、命令输出重新发一遍,模型才能"记得"前面发生了什么。上下文里有 1 万 token,每走一步就要为这 1 万 token 付一次钱。走 50 步,光是重发就有 50 万 token 的消耗。这一步是乘法效应,步数越多越吓人。

第二次开销是无效输入。很多人喜欢直接把 PDF、Word、PPT 里的内容复制粘贴给 Codex,或者让 Codex 自己打开一个巨大的文件去读。PDF 的排版噪音、Word 里的隐藏标记、Excel 的空行列、代码文件里大段注释和空行,这些东西都会原封不动变成 token。你花的是全额的钱,买来的却是模型理解上的负担。

第三次开销是错误往返。输入越脏、上下文越乱,Codex 的理解就越容易跑偏。跑偏一次,它就会多读几个文件、多试几种方案,甚至把问题改坏了再改回来。每一步都在消耗 token,而且这种消耗是不可预测的,账单爆炸往往就发生在这。

1.2 真正的大头:上下文重复装载

我在排查自己的账单时,最受触动的不是哪一步特别贵,而是"同样的代码被读了多少次"。举个例子,一个中型项目里有个utils.py,大约 800 行。Codex 为了实现一个功能,先后 6 次主动读取了这个文件,每次读取约 6000 token。光这一个文件的重复读取,就占了 36000 token。

更麻烦的是,Codex 在读取文件之后,会把内容留在上下文里。哪怕后面已经不需要utils.py的细节了,只要对话历史没有截断,它就会一直占着位置。就像你租了个大仓库,进了货不清理,仓库越堆越满,租金越来越贵。

所以省 Token 的核心思路,不是"少问问题",而是让每一次输入都更精准。把项目里真正有用的部分提前整理出来,一次性放入上下文;把文档里的排版噪音剥离掉,只留干货。这两件事做好了,Codex 就不需要自己东翻西找,也不需要带着一堆垃圾信息跑完整条流程。

1.3 省钱三板斧的逻辑:输入净化、输出控制、渠道优化

顺着上面的分析,省 Token 无外乎从三个方向下手。

  • 输入净化:把塞进上下文的内容变少、变干净。这是今天两个项目的核心战场。
  • 输出控制:通过限制任务范围、约束回答格式,减少模型多写废话。比如让 Codex 只输出 diff,不要长篇解释。
  • 渠道优化:如果你的 Codex 版本支持自定义模型端点,把它接到更便宜的模型渠道上,同样的问题花更少的钱。这个属于配置层面的优化,不是今天的主角。

输入净化最容易被忽视,因为它需要"前置功夫"——也就是在向 Codex 提问之前,先把材料处理好。多数人习惯直接把原始仓库、原始文档丢给 Codex,等于把处理成本全部变成了 Token 费用。下面这两个开源项目,就是帮你把这道前置功夫自动化。

2. 项目一:repomix,把整个仓库压成一份喂给 Codex 的精准 Prompt

2.1 它是干什么的,为什么它能省 Token

repomix 是一个把代码仓库打包成单个 AI 友好文件的命令行工具,前身叫 pack。你只需要在项目根目录执行一条命令,它就会遍历整个仓库,剔除掉不需要的文件,生成一个包含文件树和核心代码的紧凑文件,适合直接作为上下文喂给大模型。

这个词你可能在 GitHub 上见过,它是目前社区里把"代码库转 Prompt"这件事做得最完整的工具之一。它能自动读取.gitignore,默认跳过node_modulesdist.git这类几乎不可能对任务有帮助的目录,还能自己估算 token 数。

为什么它能省 Token?因为 Codex 在无人干预的情况下,探索代码库是非常耗 Token 的。它要自己列目录、猜哪个文件有用、逐个打开再排除。如果仓库里有 500 个文件,其中 400 个跟任务无关,Codex 也得先花时间和 Token 确认"这些无关"。而 repomix 是把所有文件压缩成一份带结构的文本,你只需要看一眼 Token 统计,就知道这份材料大概要花多少钱。后面不再需要反复读文件,一次放进上下文就行。

2.2 安装与三分钟上手

安装很简单,Node.js 环境是必需的。

# 用 npx 直接跑,不需要提前安装 npx repomix # 或者全局安装,用起来更顺手 npm install -g repomix

在项目根目录直接运行:

cd /path/to/your-project repomix

默认会在当前目录生成一个repomix-output.txt,里面是所有代码的拼接体。命令行结束时会打印一行统计,类似:

Codebase analysis complete. Total files: 132 Total tokens: 48,320 Total size: 156.3 KB

这一步非常关键。Token 统计直接告诉你这份材料的"重量",如果超过预期,就该考虑加大忽略范围或者换一种打包方式,而不是直接把它塞给 Codex。

你还可以指定输出格式,我用得最多的是 Markdown 和 XML:

# Markdown 格式,适合人类阅读,也很适合放进 Codex 提示词 repomix --style markdown --output-file codebase.md # XML 格式,结构化更强,程序解析更友好 repomix --style xml --output-file codebase.xml

2.3 让输出更省的配置组合:ignore、compress、模板

只看默认行为还不够。repomix 真正比我以前用的粗暴拼接工具强的地方,是它支持精细的包含和忽略规则。

我第一次用它的时候,直接把整个仓库打包,结果一个中型项目出来 20 万 token,根本喂不起。后来调整了策略,用--include--ignore只保留相关部分:

repomix \ --include "src,scripts,docs" \ --ignore "**/*.test.js,**/*.spec.js,docs/archive/**" \ --compress \ --style xml \ --output-file packed.xml

解释一下各参数的含义:

  • --include:只打包srcscriptsdocs三个目录。
  • --ignore:跳过测试文件和历史归档文档。
  • --compress:这是另一个省 Token 利器。它会删除代码里的注释和多余空行,并做一定的压缩处理。对于注释特别多的老项目,这一项能把体积再压掉 30% 左右。
  • --style xml:XML 格式在边界处理上更清晰,Codex 分辨代码块和结构信息更不容易出错。

这些规则也可以固化到配置文件里,一劳永逸。在项目根目录创建repomix.config.json

{ "ignore": { "useGitignore": true, "custom": [ "**/*.min.js", "dist/**", "coverage/**", "docs/archive/**" ] }, "output": { "style": "xml", "filePath": "packed.xml", "showLineNumbers": false }, "tokenCount": { "encoding": "o200k_base" } }

我用o200k_base做编码估算,是因为 OpenAPI 最新的模型大多基于这个编码体系,估算出来的数字更接近真实计费。如果你用的是别的模型,可能需要根据模型去调整,否则会有偏差。

2.4 和 Codex 配合的推荐工作流

工具再好,也要用对流程。我现在处理一个已有的仓库任务时,基本遵循这个套路:

  1. 先用repomix打包一份全量概览,看一下项目规模。
  2. 根据任务范围,决定是喂全量概览,还是用--include只打包相关模块。
  3. 如果仓库里注释多,开启--compress
  4. 把生成的repomix-output.md作为第一条消息的背景信息发给 Codex,并在提示词里明确说明"代码上下文见附件,后续不需要再探索仓库结构"。
  5. 整个会话里只围绕具体任务提问,避免让 Codex 反复读取文件。

用这种办法,Codex 的开销模型会变得非常可预测。它不需要为了找一个小函数而翻遍整个仓库,因为所有小函数都已经在上下文里了,而且是经过精心筛选的。

有一点要提醒:不要为了数据好看就盲目开--compress。压缩会把注释全部删掉,而有些注释本身就是重要的业务逻辑说明。如果这份代码里充满了"为什么要这么写"的注释,压缩之后 Codex 可能完全看不懂这种"非直观的写法",接下来你要为它的错误理解付出远超省下来的 Token。压缩是一笔交易,你得清楚自己在交易什么。

3. 项目二:markitdown,别让文档里的排版噪音烧掉你的预算

3.1 文档输入是 Token 黑洞

很多人忽略一个问题:Codex 的上下文不只是代码,还有需求文档、接口文档、数据分析报告。这类材料往往以 PDF、Word、Excel 的形式存在。

直接把 PDF 内容复制粘贴给 Codex,会发生什么?

首先是页眉页脚。每一页都可能重复出现公司名、文档名、页码,10 页文档就是 10 次重复。然后是分页符和断行。PDF 的文本提取经常在行尾断裂,一段完整的描述被拆得七零八落。还可能有目录、水印、嵌入的图片说明。这些全是 token,但全都没用,甚至有害。Codex 需要花额外的推理能力去理解这个脏数据,能不能看懂还是两说。

我做过一个对比。同样是 10 页的 PDF 需求文档,直接从 PDF 阅读器复制出来的文本约 6800 token,里面有大量页眉、页脚和断裂行;用 markitdown 转成 Markdown 之后,只剩 3100 token,而且标题层级、列表、表格都保留了下来。

花一半的钱,买到一份结构更清晰的材料,这笔账怎么算都划算。

3.2 安装与支持范围

markitdown 是微软开源的工具,GitHub 上目前热度很高。它支持的格式相当全:

  • PDF
  • Word(.docx)
  • Excel(.xlsx)
  • PowerPoint(.pptx)
  • HTML
  • CSV、JSON、XML
  • 图片(可选用 OCR 识别文字)
  • 音频(可选用转录服务转文字)

安装用 pip:

# 安装全部依赖(包括 OCR、音频转录等) pip install "markitdown[all]" # 如果只需要处理常见文档 pip install markitdown

命令行就可以直接用:

markitdown requirements.pdf > requirements.md markitdown 数据说明.xlsx > 数据说明.md markitdown 产品介绍.pptx > 产品介绍.md

我看到不少朋友只会用命令行,其实它的 Python API 也很有用。想批量处理一堆文档的时候,写个小脚本非常轻松:

from markitdown import MarkItDown from pathlib import Path md = MarkItDown() for path in Path("docs").glob("*.pdf"): result = md.convert(str(path)) output_path = Path("output") / (path.stem + ".md") output_path.write_text(result.text_content, encoding="utf-8")

3.3 一个直观的对比试验

我拿一份真实的数据分析需求文档做过试验,下面是处理前后的对比。

对比项PDF 直接复制粘贴markitdown 转换后
Token 估算68003100
包含内容页眉页脚、页码、断裂行、目录噪音标题层级、干净段落、Markdown 表格
Codex 后续纠错往返次数3 次1 次

那次任务是让 Codex 根据需求文档生成数据分析代码。直接粘贴版让 Codex 把"统计周期"理解错了,因为原始 PDF 里那一段文本被分页符切开,后半段跑到了第二页,模型读的时候漏了一半。后面胶着了两轮才修正。转换版一次就答对了,而且生成代码的质量明显更高。

这就是文档类 Token 黑洞的可怕之处:表面上看只是"多花了点输入钱",实际上因为脏数据导致的错误理解,还会带来额外的输出 token 消耗。输入浪费和输出浪费叠加在一起,才是账单爆炸的真正原因。

3.4 markitdown 在 Codex 流里的两个正确用法

用法一:先转格式,再贴内容。任何文档在进入 Codex 上下文之前,先经过 markitdown 转成干净的 Markdown。这个习惯一旦养成,处理文档的 Token 消耗基本能下降一半。文件太大的话,还可以把多个 md 文件合并成一个,再手动删除明显无关的章节。

用法二:配合 API 调用做自动预处理。如果你是用 Codex CLI 或脚本方式调接口,可以在代码里先调用 markitdown 做转换,再把转换结果拼进 prompt。这样整个流水线就自动化了,不需要每次手动复制粘贴。

我还习惯把转换后的 Markdown 文件提交到仓库里,形成一个docs/md/目录。这样以后任何人要用这些文档,都直接拿转换版本,不用重新踩一遍原始格式的坑,也算一劳永逸。

4. 组合拳:一次真实项目里,两个项目联用省了多少

4.1 场景预设:接手一个历史仓库 + 三份需求文档

前面分开讲了两个项目各自的用法,现在把它们放到一个真实的场景里演示。

假设你要接手的项目情况如下:

  • 一个历史仓库,约 1.2 万行代码,分布在 420 个文件里。
  • 有 3 份需求文档,分别是 PDF 格式的《功能规格说明书》、Word 格式的《接口文档》、Excel 格式的《数据字典》。
  • 任务:基于这些文档,让 Codex 在仓库里实现一个新的查询接口。

如果按老办法,直接让 Codex 自己去探索,流程可能是这样的:

  1. Codex 先列目录,读 README、读配置、读源码,一段一段探索。
  2. 它分不清哪些文件跟新接口有关,会把大量无关文件也读一遍。
  3. 读到 PDF 需求文档时,又因为格式噪音产生理解偏差,来回试错。

整个流程下来,300k 到 400k Token 是很正常的数字,取决于模型在仓库里迷路多久。

用两个工具联动,流程完全变了。

4.2 操作顺序与 Token 估算

第一步,用 repomix 打包代码部分。但要控制范围,不要把仓库全部打包:

repomix \ --ignore "**/*.test.js,db/migrations/**,docs/old/**" \ --compress \ --style markdown \ --output-file codebase.md

去掉迁移脚本和测试文件之后,420 个文件压到 290 个,打包结果约 64k token。这一步做完,Codex 就不再需要自己去探索仓库了。

第二步,用 markitdown 转三份文档:

markitdown 功能规格说明书.pdf > spec.md markitdown 接口文档.docx > api.md markitdown 数据字典.xlsx > data_dict.md cat spec.md api.md data_dict.md > docs_combined.md

三份文档合并后约 8.5k token。加上代码包 64k,总共约 72.5k token。这里面还包含我第一条消息里的任务描述,我习惯再留一点余量,按 80k 算。

第三步,把两份材料一起放进 Codex 的第一条消息,并给它明确指令:代码上下文和文档上下文都在上面,直接基于这些内容实现功能,不要去仓库里找其他文件,不要重复读取。

最终单次任务的 Token 消耗大约在 85k 到 100k 之间,几乎腰斩再腰斩,而且整个过程中 Codex 迷路的概率大大降低。我用一套差不多的办法跑了几天,基本上把原来"让 Codex 自由探索"的三分之一到四分之一用量,做到了同样甚至更好的结果。

4.3 如果还想更省:模型路由的思路

输入精简到一定程度之后,还想继续省钱,就要看模型渠道侧了。如果你的 Codex 版本支持自定义模型端点,把它接到成本更低的模型渠道上,Token 单价会直接降下来。这一点社区里已经有很多朋友在实践,也有很多 Codex 接入其他模型的教程。

这块涉及的内容比较杂,而且不同版本的 Codex 配置方式变动蛮大,我就先不展开了。如果你感兴趣,可以自己去搜关键词"Codex 自定义端点",核心思路就是通过环境变量或配置文件,把 Codex 的请求指向你希望调用的模型 API 地址。要注意的是,不同模型对工具调用的支持程度不一样,跨模型使用之前最好先做一轮小规模验证。

5. 配套的心得与踩坑记录

5.1 repomix 输出过大的切割技巧

打包出来的文件如果太大,不要急着喂给 Codex。先看命令行打印的 Token 统计,超过目标就调整策略。

一种办法是缩小范围,只打包任务相关的模块。比如任务是"修复登录模块的 bug",那就--include "src/auth,src/utils",把无关的支付、订单代码全部丢在外面。

另一种办法是把一个大包拆成多个小文件,分批喂。比如先给 Codex 一个整体概览(文件树 + 核心入口文件),等它提出具体问题,再把对应模块的完整代码追加进去。这种做法能把单次请求的上下文控制住,避免一次性投入过多 Token 却用不上。

我踩过的坑是:一开始图省事,全量打包一个超大仓库,结果 repomix 生成了 18 万 token 的文件,我硬塞给 Codex。任务进行到一半,Codex 开始遗忘早期内容,回答质量明显下降,反而要重开会话。后来才明白,省 Token 不等于不花 Token,而是把每一个 Token 都花在刀刃上。合理分片,让 Codex 在每一个会话里只看它真正需要的内容,比一次性给全量高效得多。

5.2 扫描版 PDF 与乱码文档要小心

markitdown 对普通 PDF 的转换效果很好,但有一个明显的软肋:扫描版 PDF。这类文件本质是图片,没有文本层。markitdown 拿到这种 PDF,读不出任何文字,转出来要么是空白,要么只有 OCR 出来的零星乱码。

解决办法是先用 OCR 工具把扫描件识别成文本,再用 markitdown 或者手动整理成干净文本。常见的开源方案有 PaddleOCR 等,识别中文效果也比较可靠。但 OCR 本身有误识别率,越专业的术语越容易出错。处理完之后,稍作人工校对,再喂给 Codex。

另外,Excel 转出来的 Markdown 表格可能非常长,尤其是有几十个 Sheet 的工作簿。建议在转换之前,先把真正需要的 Sheet 单独拆出来,或者写脚本按 Sheet 名筛选,只保留核心内容。否则一个数据字典转出 5000 行表格,它也变成一个巨大的 Token 负担,反而违背了省 Token 的初衷。

5.3 压缩是技术,更是取舍:不能省的 Token 别省

这是我最想强调的一点。很多朋友用repomix --compress之后,看到 Token 数刷一下降下来,非常兴奋。但压缩不是免费的。

代码里的大段注释往往是业务规则的最佳说明,尤其是那些"为什么不用方案 A 而用方案 B"的注释。这些内容被删掉以后,Codex 可能会基于代码表象得出一个完全相反的结论,然后给出一个技术上正确、业务上错误的方案。你省下了输入 Token,却要为多轮纠错付出更多的输出 Token 和宝贵时间。

同理,某些看似冗余的上下文,比如项目的整体架构说明、模块之间的依赖关系,对 Codex 理解任务至关重要。这种 Token 属于"基建投入",该花就花。我现在的原则是:无关内容坚决不喂,相关内容压缩可以,但核心逻辑和业务说明一条不动。

5.4 把省 Token 变成日常工作流的最后建议

最后分享几个我从实践中养成的习惯,也算给这篇文章收个尾。

第一,把 repomix 和 markitdown 固化成固定的前置步骤,而不是想起来才用。我给自己的工作目录写了一个简单的打包脚本,一条命令完成"代码打包 + 文档转换 + Token 统计",每次开新任务前先跑一遍,心里大概有数,知道这次任务要花多少预算。

第二,在提示词里明确告诉 Codex"上下文已经齐了,不需要再探索仓库"。这句话真的能省很多 Token,因为它直接切断了 Codex 因为不确定而启动的主动探索行为。

第三,如果被 Codex 的登录态问题困扰过,比如 token 失效、验证流程卡住,直接用 API Key 方式运行 Codex CLI 会省心很多。我自己的使用体验是 API Key 方式的会话状态更可控,配合自定义模型端点也更灵活。这可能涉及不同人的使用习惯,你可以自己试试看哪种方式顺手。

第四,也是最重要的:省 Token 不是目的,让 Codex 更快地给出高质量结果是目的。所有压缩、忽略、切割的动作,都应该围绕"帮助 Codex 更好理解任务"来设计。如果一个操作让 Codex 的理解变差了,不管它省了多少 Token,都不值得做。

这两个开源项目给我带来的最大改变,不是账单数字变小了,而是我对 Codex 的每一次使用都变得有掌控感。我知道喂进去的是什么、花了多少、预期的产出是什么,而不是月底看账单的时候一脸茫然。如果你也在被 Codex 的 Token 消耗困扰,建议从 repomix 和 markitdown 开始,先跑通一个只涉及单模块和单文档的任务,再慢慢扩展到整个仓库级工作流。这套方法不会让你的 Codex 变聪明,但会让你花出去的每一分钱都更值。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询