EasyDoc:将你的文档变为 AI 友好格式的万能神器

EasyDoc:将你的文档变为 AI 友好格式的万能神器

4.8
0热度

我们正站在一个路口的拐角——内容的「人机分野」正在模糊。在ChatGPT 出现之前,互联网上的内容,基本都是面向人类的,追求的是视觉美感、阅读体验。但这些对AI 模型来说却是噩梦——HTML的层层嵌套、PDF的复杂排版、Word文档的格式标记……在我看来,最终的信息世界将会是面向AI 的世界——内容是为AI 准备的AI Friendly 的结构化数据。All for AI.但现在还不

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

在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.55372.912529.80578.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%"]
      }
    }
  ]
}

注意,这里有几个关键点:

  1. 层级关系:通过parent_id构建文档树,保持了原始文档的逻辑结构
  2. 精确定位coordinates提供了每个元素的准确位置
  3. 语义理解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倍
也可以在网页里直接上传图片:
虽然是排队的异步逻辑,但不到3秒就完成了
(感觉同步都可,不够自信啊!
会有结构树(人类友好)、json(开发者友好)、markdown(AI 友好) 三种格式来给出解析结果:
表格的解析也非常精准,远不是一个ocr 工具,或是 4o 甚至o3 可比的(丢失了空间关系等许多精准信息):
而这是o3 的输出:
这个茅台年报的解析更能看到效果:
图片
这也是说明在一个小而垂的场景下,一个不需要太大尺寸的专用模型,是可以做得比大通用模型要更好且更经济的。

支持的文档格式

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

性能优化建议

基于我少量的一些实测,这里有几点粗略的优化建议:

  1. 选择合适的模式:不是所有文档都需要Premium,合理选择能节省成本
  2. 预处理大文件:超过50MB的文件建议先压缩或分割
  3. 缓存解析结果:相同文档不要重复解析
  4. 使用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既有技术深度,又真正解决实际问题。

实用,且不花哨。

EasyDoc 技术交流群,大佬们都在

写在最后

回到开头的问题——我们正在经历内容的「AI 化」转型

从为人类设计的内容,到为AI 设计的内容,这个过程注定充满挑战。

EasyDoc的出现,让我看到了一种可能:也许我们不需要推倒重来,重新创造一个「AI原生」的内容世界。通过EasyDoc 这样的智能转换工具,我们可以让现有的人类知识平滑过渡到AI 时代。

而EasyDoc 官方的文档,也天然的是AI 友好,也算是做出表率了。

让文档不再是AI 理解世界的障碍——

EasyDoc 这个点,切的很好。




[1]

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 容易链科技

首页 发现
看过 我的