我们正站在一个路口的拐角——内容的「人机分野」正在模糊。

在ChatGPT 出现之前,互联网上的内容,基本都是面向人类的,追求的是视觉美感、阅读体验。
但这些对AI 模型来说却是噩梦——HTML的层层嵌套、PDF的复杂排版、Word文档的格式标记……

在我看来,最终的信息世界将会是面向AI 的世界——内容是为AI 准备的AI Friendly 的结构化数据。
All for AI.
但现在还不是,我们正处于一个充满尴(机)尬(会)的过渡期。

最近我在做一个Agent项目时,“如何低成本且优雅准确地解析用户上传的花式文档”的问题让我头大了好几天。
试过各种转Markdown的工具,开源的、闭源的用了一圈,要么丢失格式,要么表格变乱码,要么图表直接消失——恨我得只想直接用Claude Code 徒嘴开撸(语音输入)。

我对技术栈选型的顺序大约是:
靠谱的开源 > 付费 > 自己造轮子 > 低劣的开源+自己改
开源的不少,但试了一圈都没有满足我需求的,直到o3 给出了EasyDoc这个工具。
官网在此:
https://www.easylink-ai.com/easy-doc/

而且,这显然不是个三两个vibe coder vibe coding 几小时就搞出来的项目。
快速上手
真•一句prompt,就完成文档解析:
访问https://www.easylink-ai.com/easy-doc/,给出用python 调用EasyDoc 进行文档解析的代码
轻松搞定:
import requests
# 步骤1:上传文档,发起解析任务
url = "https://api.easylink-ai.com/v1/easydoc/parse"
headers = {"api-key": "your-api-key"} # 从 https://platform.easylink-ai.com/api-keys 获取
files = [("files", open("report.pdf", "rb"))]
data = {"mode": "premium"} # lite/pro/premium 三种模式可选
response = requests.post(url, headers=headers, files=files, data=data)
task_id = response.json()["data"]["task_id"]
# 步骤2:获取解析结果
result_url = f"https://api.easylink-ai.com/v1/easydoc/parse/{task_id}"
result = requests.get(result_url, headers=headers).json()
就这么简单。
easydoc 的整个API 设计,也很好地遵循了RESTful 的规范,只有两个端点:
POST /v1/easydoc/parse
- 上传文档GET /v1/easydoc/parse/{task_id}
- 查询结果
核心技术
传统OCR只能识别文字,EasyDoc的视觉语义大模型则在这基础之上,还具备了理解文档结构的能力。
来看它输出的JSON结构:
{
"nodes": [
{
"id": 1,
"text": "2024年度财务报告",
"type": "Title",
"parent_id": -1,
"composing_blocks": [{
"coordinates": [442.55, 372.91, 2529.80, 578.78],
"page_number": 1,
"layout_width": 2977,
"layout_height": 4335
}]
},
{
"id": 2,
"type": "Table",
"parent_id": 1,
"caption": "营收对比表",
"vlm_understanding": {
"description": "该表格显示了2023-2024年各季度营收数据...",
"insights": ["Q4增长显著", "同比增长23%"]
}
}
]
}
注意,这里有几个关键点:
层级关系:通过 parent_id
构建文档树,保持了原始文档的逻辑结构精确定位: coordinates
提供了每个元素的准确位置语义理解: vlm_understanding
不只是提取表格数据,还能理解其含义

实战案例
我用EasyDoc做了一个简单的文档问答系统(同样vibe coding),效果简单且出奇的好。
核心代码是这样的:
import json
from typing import List, Dict
def process_document_for_rag(file_path: str) -> List[Dict]:
"""将文档处理成适合RAG的语义块"""
# 1. 解析文档
task_id = upload_document(file_path, mode="premium")
result = get_parse_result(task_id)
# 2. 构建语义块
semantic_chunks = []
nodes = result["data"]["results"]["nodes"]
for node in nodes:
# 获取完整的上下文路径
context_path = get_node_path(node["id"], nodes)
chunk = {
"content": node["text"],
"metadata": {
"type": node["type"],
"page": node["composing_blocks"][0]["page_number"],
"path": context_path,
"coordinates": node["composing_blocks"][0]["coordinates"]
}
}
# 特殊处理表格和图表
if node["type"] in ["Table", "Figure"]:
if"caption"in node:
chunk["content"] = f"{node["caption"]}\n{chunk["content"]}"
if"vlm_understanding"in node:
chunk["ai_analysis"] = node["vlm_understanding"]
semantic_chunks.append(chunk)
return semantic_chunks
def get_node_path(node_id: int, all_nodes: List[Dict]) -> str:
"""递归获取节点的完整路径"""
node = next(n for n in all_nodes if n["id"] == node_id)
if node["parent_id"] == -1:
return node.get("text", "Document")
parent_path = get_node_path(node["parent_id"], all_nodes)
returnf"{parent_path} > {node.get("text", node["type"])}"
这样处理方式的优势在于:
每个chunk都带有完整的上下文信息 表格和图表被正确理解,而不是变成乱码 保留了页码和坐标,便于精确引用
三种模式
easydoc 有三种模型可选:

我总结了下差异:
Lite模式(0.02元/页)
基础布局识别 输出扁平化的文本块 适合快速文本提取,如批量处理简历、合同关键信息
Pro模式(0.06元/页)
构建文档层次结构 合并跨页/跨栏内容 输出完整的文档树,适合知识库构建
Premium模式(0.22元/页)
深度图表理解(vlm_understanding字段) 表格结构完整保留 支持Markdown输出 适合技术文档、财报等复杂文档
实测数据:
100页技术文档:Premium模式52秒完成 准确率:结构识别90%(超过GPT-4V的表现) 表格解析速度:比传统方案快12倍






支持的文档格式
SUPPORTED_FORMATS = {
"word": [".dotm", ".docm", ".doc", ".dotx", ".docx", ".dot"],
"excel": [".xltm", ".xlsm", ".xlsx", ".xls", ".xlt"],
"ppt": [".pptx", ".potm", ".ppt", ".pot", ".pps"],
"image": [".tif", ".png", ".jpg", ".bmp"],
"text": [".txt", ".html"],
"pdf": [".pdf"]
}
几乎覆盖了我们日常工作中的所有文档类型。
而像 pot, xlt 之类的格式,我其实之前都不认识……(见识少了)
而easydoc 对各种Word和Excel变体的支持,解决了很多兼容性问题(也是之前让我最头大的地方)。
批量处理
而如果需要处理大量文档,也很容易——
并发开干,即可:
import asyncio
import aiohttp
from concurrent.futures import ThreadPoolExecutor
asyncdef batch_process_documents(file_paths: List[str], max_concurrent=5):
"""批量处理文档,控制并发数"""
semaphore = asyncio.Semaphore(max_concurrent)
asyncdef process_single(session, file_path):
asyncwith semaphore:
# 上传文档
with open(file_path, "rb") as f:
data = aiohttp.FormData()
data.add_field("files", f, filename=file_path)
data.add_field("mode", "pro")
asyncwith session.post(
"https://api.easylink-ai.com/v1/easydoc/parse",
headers={"api-key": "your-key"},
data=data
) as resp:
result = await resp.json()
task_id = result["data"]["task_id"]
# 轮询结果
whileTrue:
asyncwith session.get(
f"https://api.easylink-ai.com/v1/easydoc/parse/{task_id}",
headers={"api-key": "your-key"}
) as resp:
result = await resp.json()
if result["data"]["status"] == "SUCCESS":
return result
elif result["data"]["status"] == "ERROR":
raise Exception(f"Parse failed: {file_path}")
await asyncio.sleep(2)
asyncwith aiohttp.ClientSession() as session:
tasks = [process_single(session, fp) for fp in file_paths]
returnawait asyncio.gather(*tasks)
已集成dify
EasyDoc已经上架Dify插件商城:
可以直接在Dify工作流中使用:
# Dify工作流配置示例
nodes:
-id:doc_parser
type:tools/easydoc
config:
mode:premium
api_key:"{{env.EASYDOC_KEY}}"
-id:embedding
type:embedding/openai
input:"{{doc_parser.output.nodes}}"
-id:vector_store
type:storage/qdrant
input: "{{embedding.output}}"
同时也支持华为云部署——
对于有合规要求的企业来说……
你懂的,是个好消息。
错误处理
实际使用可能会遇到各种问题,这里是常见错误码:
ERROR_CODES = {
"API_UNAUTHORIZED": "检查API密钥是否正确",
"INSUFFICIENT_BALANCE": "账户余额不足,需要充值",
"INVALID_DOCUMENT": "文档格式不支持或已损坏",
"INSUFFICIENT_RESOURCES": "服务器资源不足,稍后重试"
}
def safe_parse_document(file_path: str, retry=3):
"""带重试机制的文档解析"""
for i in range(retry):
try:
return parse_document(file_path)
except Exception as e:
if"INSUFFICIENT_RESOURCES"in str(e) and i < retry>1:
time.sleep(5 * (i + 1)) # 指数退避
continue
elif"INVALID_DOCUMENT"in str(e):
# 尝试修复或转换文档
fixed_path = attempt_fix_document(file_path)
if fixed_path:
return parse_document(fixed_path)
raise
性能优化建议
基于我少量的一些实测,这里有几点粗略的优化建议:
选择合适的模式:不是所有文档都需要Premium,合理选择能节省成本 预处理大文件:超过50MB的文件建议先压缩或分割 缓存解析结果:相同文档不要重复解析 使用webhooks:对于大批量处理,可以请求他们开通webhook通知
安全性和合规
对于企业用户,EasyDoc提供了几个重要的安全保障:
传输加密:全程HTTPS 数据不留存:解析完成后立即删除原文件 私有化部署:支持本地部署(需联系商务)
# 敏感文档处理示例
def process_sensitive_document(file_path: str):
"""处理敏感文档的最佳实践"""
# 1. 本地加密
encrypted_file = encrypt_file(file_path)
# 2. 使用专用API密钥(限制IP)
headers = {
"api-key": os.environ["EASYDOC_SECURE_KEY"],
"X-Client-IP": get_whitelist_ip()
}
# 3. 立即删除本地副本
try:
result = parse_document(encrypted_file, headers=headers)
finally:
secure_delete(encrypted_file)
return result
目前新用户注册送80元体验金,按Premium模式算能处理360多页,足够你用了——如果不够,那恭喜你:这是个好项目,也不差这么点费用了。

背后的团队
我又用o3 挖了一下创始团队的背景,发现它能做到这个水平并不意外。
CEO是金融投资出身,之前是Plug and Play(璞跃是全球几个历史最悠久覆盖最广的科技孵化器之一)中国金融科技业务的合伙人,一直在主导上一代金融行业的数字化转型项目,推动了上一代人工智能技术在金融业务场景的落地。
CTO 也更是技术大牛——百度前T10级别的技术专家,百度知识图谱技术委员会的主席,之前从0-1建立了全球规模最大的中文知识图谱。
这两个人在2023年的时候,基于整个大模型技术(GPT)的兴起,加上两人对行业的共识理解,发现企业大模型落地的过程中,非结构化数据处理是一个巨大的gap。
这也解释了为什么他们选择从数据基础设施这个切入点创业。
一个懂业务懂know how 懂痛点,一个懂技术实现,这种组合让EasyDoc既有技术深度,又真正解决实际问题。
实用,且不花哨。

写在最后
回到开头的问题——我们正在经历内容的「AI 化」转型。
从为人类设计的内容,到为AI 设计的内容,这个过程注定充满挑战。
EasyDoc的出现,让我看到了一种可能:也许我们不需要推倒重来,重新创造一个「AI原生」的内容世界。通过EasyDoc 这样的智能转换工具,我们可以让现有的人类知识平滑过渡到AI 时代。
而EasyDoc 官方的文档,也天然的是AI 友好,也算是做出表率了。
让文档不再是AI 理解世界的障碍——
EasyDoc 这个点,切的很好。
EasyDoc 官网: https://www.easylink-ai.com/easy-doc/
[2]API 文档: https://docs.easylink-ai.com/easydoc
[3]获取 API 密钥: https://platform.easylink-ai.com/api-keys
[4]在线体验入口: https://www.easylink-ai.com/easy-doc/
[5]微信公众号:EasyLink 容易链科技