1. 为什么你的文档喂给 AI 后 Tokens 总是爆表
如果你正在做 RAG 知识库、AI 文档问答,或者只是想把一份 PDF 丢给大模型做总结,大概率遇到过这种情况:一份 20 页的 PDF,直接上传给模型,Tokens 消耗直接冲到几万,账单肉眼可见地涨。更麻烦的是,模型读完之后回答质量还不稳定,表格错位、标题层级丢失、页眉页脚混进正文,这些都是原始文档格式带来的“噪音”。
MarkItDown 是微软开源的一个文档转 Markdown 工具,专门解决这个“格式鸿沟”问题。它能处理 PDF、Word、Excel、PPT、图片、音频等 20 多种格式,把它们统一转成结构清晰的 Markdown。Markdown 本身就是大语言模型最“爱吃”的格式——标题、列表、表格、链接都能保留,同时去掉了大量排版冗余信息。实测下来,同一份文档先转 Markdown 再喂给模型,Tokens 消耗能降到直接上传原始文件的一半甚至更低。
这篇文章聚焦两件事:一是用 Python 调用 MarkItDown 完成文档转换,二是通过 MCP 协议把 MarkItDown 挂载到你的 AI 工具链里,让模型自己调用转换能力。我会给出可复制的配置片段、Python 示例代码,以及一套 Tokens 对比验证步骤,你可以跟着在本地复现效果。适合正在搭建 RAG 管道、做 AI 文档处理、或者单纯想省 Token 成本的开发者。
2. TaoToken 前置准备:让 MarkItDown 的 AI 能力跑起来
MarkItDown 本身是一个纯本地的转换工具,大部分格式转换不需要联网。但有两个场景会用到外部模型能力:一是图片 OCR 和图片描述,二是音频转录。这两个功能需要配置一个兼容 OpenAI 接口的客户端。我这边用的是 TaoToken 提供的 API 服务,它兼容 OpenAI SDK 的调用方式,配置起来比较直接。
你需要先拿到一个 API Key。访问 https://taotoken.net/api-keys 创建一个密钥,然后确认你要用的模型 ID。TaoToken 的 API 端点地址是 https://taotoken.net/api ,这个地址在后面的 Python 代码和 MCP 配置里都会用到。
这里要区分一下:MarkItDown 的 MCP 服务器本身不依赖外部 API,它只是把转换能力暴露成工具。但如果你想让 MarkItDown 在转换图片时生成描述文字,或者在转换音频时做语音转文字,就需要在初始化 MarkItDown 实例时传入 llm_client 和 llm_model 参数。这个 llm_client 可以指向 TaoToken 的 API 端点。
另外,如果你打算长期做编码类任务或者 Agent 开发,可以了解一下 Coding Plan,它适合需要频繁调用模型能力的场景。如果只是想验证模型对话效果,可以直接用模型对话页面测试。接入文档在 https://taotoken.net/doc 可以查到详细的参数说明。
环境方面,MarkItDown 需要 Python 3.10 或更高版本。你可以先用python --version确认一下。如果版本不够,建议用 pyenv 或者 conda 建一个独立环境,避免和系统 Python 冲突。安装 MarkItDown 的时候,推荐直接装全量依赖:
pip install 'markitdown[all]'如果你只需要处理 PDF 和 Word,可以按需安装:
pip install 'markitdown[pdf,docx]'装完之后用markitdown --version验证一下,能返回版本号就说明安装成功了。MCP 服务器包会随全量安装一起装好,后面配置 MCP 的时候直接调用markitdown-mcp命令就行。
3. 可复制配置:MCP 服务与 Python 调用完整片段
这一节给出两套可复制的配置:一套是 MCP 服务器的 JSON 配置,另一套是 Python 调用 MarkItDown 的完整示例。你可以根据自己的工具链选择使用。
先看 MCP 配置。MarkItDown 原生支持 MCP 协议,启动方式有两种:STDIO 模式和 HTTP 模式。STDIO 模式适合本地集成,HTTP 模式适合远程访问。下面是一个标准的 MCP 客户端配置片段,你可以把它加到你的 MCP 配置文件里(比如mcp.json或claude_desktop_config.json):
{ "mcpServers": { "markitdown": { "command": "markitdown-mcp", "args": [], "env": { "MARKITDOWN_LLM_API_BASE": "https://taotoken.net/api", "MARKITDOWN_LLM_API_KEY": "你的_TaoToken_API_Key", "MARKITDOWN_LLM_MODEL": "你的模型ID" } } } }这里三个环境变量分别对应 Base URL、API Key 和 Model ID。如果你不需要图片描述或音频转录功能,可以省略 env 部分,只保留 command 和 args。配置保存后重启你的 MCP 客户端,MarkItDown 的转换工具就会出现在工具列表里。
如果你用的是 HTTP 模式,启动命令是:
markitdown-mcp --http --host 127.0.0.1 --port 3001然后在 MCP 客户端里配置对应的 URL 端点即可。HTTP 模式适合多个客户端共享同一个转换服务,但要注意端口不要和本地其他服务冲突。
接下来是 Python 调用示例。基础用法很简单:
from markitdown import MarkItDown md = MarkItDown() result = md.convert("document.pdf") print(result.text_content)如果你要启用图片描述功能,需要传入 llm_client 和 llm_model:
from markitdown import MarkItDown from openai import OpenAI client = OpenAI( api_key="你的_TaoToken_API_Key", base_url="https://taotoken.net/api" ) md = MarkItDown( llm_client=client, llm_model="你的模型ID" ) result = md.convert("example.jpg") print(result.text_content)批量处理的时候,可以这样写:
import os from pathlib import Path from markitdown import MarkItDown md = MarkItDown() doc_dir = Path("./documents") for pdf_file in doc_dir.glob("*.pdf"): result = md.convert(str(pdf_file)) output_file = pdf_file.with_suffix(".md") with open(output_file, "w", encoding="utf-8") as f: f.write(result.text_content) print(f"转换完成: {pdf_file} -> {output_file}")处理大文件的时候,建议用流式方式,避免一次性把整个文件读进内存:
with open("large_document.pdf", "rb") as f: result = md.convert_stream(f, file_extension=".pdf") print(result.text_content)这套配置跑通之后,你就可以在 MCP 客户端里直接说“帮我把这个 PDF 转成 Markdown”,模型会自动调用 MarkItDown 工具完成转换。Python 脚本则适合集成到你的数据处理管道里,做批量转换和后续的向量化入库。
4. 验证请求与 Tokens 对比:确认消耗真的减半
配置好之后,你需要一套可复现的验证步骤来确认 Tokens 消耗确实降下来了。我试过的方法是这样的:准备一份 20 页左右的 PDF 文档,分别用两种方式喂给模型,对比 Tokens 消耗。
第一种方式:直接把 PDF 文件上传给模型,让它做总结。第二种方式:先用 MarkItDown 转成 Markdown,再把 Markdown 文本喂给模型做同样的总结任务。两次任务使用相同的模型和相同的提示词。
具体操作步骤:
第一步,用 MarkItDown 转换文档:
markitdown 年度报告.pdf -o 年度报告.md第二步,查看转换后的 Markdown 文件大小和字符数:
wc -c 年度报告.md wc -l 年度报告.md第三步,把 Markdown 内容通过 API 发给模型,记录返回的 usage 字段里的 prompt_tokens 和 completion_tokens。TaoToken 的 API 兼容 OpenAI 格式,你可以直接用 curl 或者 Python 脚本调用:
from openai import OpenAI client = OpenAI( api_key="你的_TaoToken_API_Key", base_url="https://taotoken.net/api" ) with open("年度报告.md", "r", encoding="utf-8") as f: content = f.read() response = client.chat.completions.create( model="你的模型ID", messages=[ {"role": "user", "content": f"请总结以下文档:\n\n{content}"} ] ) print(response.usage)第四步,对比两次的 prompt_tokens。直接上传 PDF 的时候,很多平台会把 PDF 解析成文本再计算 Tokens,解析过程中会保留大量排版信息,导致 Tokens 偏高。而 Markdown 版本去掉了这些冗余,只保留结构化文本,Tokens 通常会降到一半左右。
这里有个细节要注意:MarkItDown 转换后的 Markdown 里,表格会保留为 Markdown 表格格式,标题层级用 # 表示,列表用 - 表示。这些结构对模型理解文档很有帮助,同时不会像原始 PDF 那样引入大量空白字符和排版标记。如果你转换的是扫描版 PDF,MarkItDown 会调用 OCR 能力,这时候 Tokens 消耗主要在 OCR 环节,转换后的 Markdown 本身仍然很精简。
验证的时候建议多试几份不同类型的文档:纯文本 PDF、带表格的 Excel、带图片的 Word。不同类型的文档,Tokens 节省比例会有差异,但整体趋势是一致的——Markdown 版本明显更省。
5. 常见报错排查:401、local proxy failed 与 OAuth 问题
配置过程中最容易遇到的几个报错,我整理了一下排查思路。
401 错误:通常出现在调用 TaoToken API 的时候。先检查 API Key 是否正确,确认没有多余的空格或换行。然后确认 Base URL 是不是https://taotoken.net/api,注意末尾不要加/v1或者其他路径。如果用的是环境变量,检查变量名是否拼写正确。另外,有些 MCP 客户端不会自动加载 shell 的环境变量,你需要在配置文件里显式写进去。
local proxy failed:这个报错一般出现在 MCP 服务器启动的时候。先确认markitdown-mcp命令在 PATH 里可用,可以用which markitdown-mcp查一下路径。如果找不到,说明 MCP 服务器包没装好,重新执行pip install 'markitdown[all]'。如果命令存在但启动失败,检查端口是否被占用,HTTP 模式下换个端口试试。
reading choices 报错:这个通常和模型返回格式有关。如果你在 MarkItDown 里配置了 llm_client 做图片描述,但模型返回的内容不符合预期,就会报这个错。排查方法是先用模型对话页面单独测试一下模型是否能正常返回,确认 API Key 和模型 ID 没问题。如果模型本身正常,检查 MarkItDown 的版本是否是最新的,旧版本对某些返回格式的兼容性可能不够好。
OAuth 相关报错:如果你用的是需要 OAuth 认证的 MCP 客户端,配置 MarkItDown 的时候可能会遇到认证失败。这种情况下,先确认客户端的 OAuth 配置是否正确,然后检查 MarkItDown MCP 服务器是否支持当前的认证方式。大部分情况下,STDIO 模式不需要 OAuth,直接用 command 启动就行。
转换后内容为空:如果 MarkItDown 转换出来的 Markdown 是空的,先确认源文件是否加密或者有权限限制。有些 PDF 加了密码保护,MarkItDown 无法直接读取。另外,扫描版 PDF 如果没有配置 OCR,也可能输出空内容。这时候需要启用 Azure Document Intelligence 或者配置 llm_client 做图片描述。
排查的时候建议打开 verbose 模式,能看到更详细的日志:
markitdown document.pdf --verboseMCP 服务器也支持 verbose 参数,启动的时候加上就能看到请求和响应的详细过程。
6. 把 MarkItDown 接入你的 AI 工作流
MarkItDown 最大的价值在于它把文档转换这件事标准化了。不管你面对的是 PDF、Word、Excel 还是图片,输出都是统一的 Markdown 格式。这意味着你的下游处理逻辑不需要为每种格式写不同的解析代码,RAG 管道的分块策略也可以统一按 Markdown 的标题层级来做。
如果你正在用 Claude Code 或者类似的编码 Agent,可以把 MarkItDown 的 MCP 服务器挂上去,让 Agent 在需要读文档的时候自动调用转换工具。配置方式就是前面给的 JSON 片段,把 Base URL、API Key 和 Model ID 三件套填好就行。这样 Agent 在处理项目文档、需求说明、技术方案的时候,可以直接读取原始文件并转换成 Markdown 再分析,不需要你手动预处理。
对于批量文档处理场景,建议把 MarkItDown 集成到你的数据管道里。比如用 Python 脚本遍历文档目录,批量转换成 Markdown,然后送入向量数据库。转换过程中可以加上异常处理和日志记录,方便排查个别文件的转换问题。
如果你需要长期跑编码类任务或者 Agent 工作流,Coding Plan 可能更适合你的使用节奏。如果只是偶尔做文档转换和模型调用,按量使用 API 就够了。接入文档里有详细的参数说明和示例代码,遇到问题可以先查文档再排查。
最后提醒一点:MCP 服务器可以读写文件和执行命令,在添加第三方 MCP 服务器之前,确认来源可信。MarkItDown 是微软开源的项目,代码透明,但如果你用的是其他第三方 MCP 服务器,建议先审查一下它的权限范围。