OpenContracts:把一堆文档变成可编程的引用图谱
The open document intelligence platform for builders and hackers - DMS for the agentic world
秒懂
- 它是什么?
- 它把解析、嵌入、抽取、标注和引用关系解析串成一条可插拔的流水线,对外只暴露一套 GraphQL/REST 接口,外加一个 MCP server 供 agent 调用。判断是:适合已经有一批结构化程度低、但引用关系密集的文档、并且愿意自己维护一套 Celery 加向量库基础设施的团队。
- 适合谁用?
- 如果你的文档集合里,价值主要藏在文书之间的相互引用上(判例、法规、披露文件、合规文件),并且团队有能力自己跑 Postgres、Celery 和向量库,OpenContracts 值得先做一次概念验证。反过来,如果你要的只是把 PDF 转成可搜索文本,或者团队没有 Python 与容器运维能力,这个项目的复杂度会成为负担,用更薄的解析加检索方案更划算。
- 能商用吗?
- 可以。MIT 是宽松许可证:你可以使用、修改并销售基于它的软件,只需保留版权和许可证声明。
- 还在维护吗?
- 在维护。仓库在最近一天内有新的提交。
- 用什么语言写的?
- 主要是 Python(依据 GitHub 的语言统计)。
以上回答依据项目的 GitHub 数据(最近同步于 2026年9月15日)和我们的分析,不构成法律意见。
开源项目深度解析
它要解决的不是搜索,而是引用关系
多数文档工具的终点是全文检索:把文件切块、嵌入、返回相似段落。OpenContracts 的落点不同。README 描述的核心产物是一张引用图谱:把每份文书里出现的法定引用识别出来、解析到具体条款,然后画成边。演示里 36 份 SEC 文件被连到 Delaware General Corporation Law、Securities Act 以及它们引用的 SEC 规则,粒度到「条款」而不是「文件」。
这个差别决定了它的用户画像。适合它的是法律、合规、监管披露这类场景,文档本身的价值不在单篇内容,而在于谁引用了谁、哪条法条被反复援引、哪些被引用对象自己的库里还没有。README 明确提到,库里尚未收录的法律不会被丢掉,而是作为 backlog 自动跟踪,直到你把它 ingest 进来。这是一个很具体的产品判断:图谱允许存在空洞,空洞本身是可查询的状态。
不适合的场景同样清楚。如果你面对的是发票、工单、合同之外的普通业务文档,引用关系稀疏甚至不存在,那么这套图谱机制大部分时间处于空转,你付出的是解析、嵌入、Celery 编排的运维成本,换回来的却只是一个比全文检索重得多的检索层。
三种界面共用一张图
README 用一句话概括了架构:同一张图,三个界面。GraphQL 加 REST 接口给应用调用,Model Context Protocol server 给 agent 调用,React UI 给人用。文档强调 UI 里能做的每一件事,API 和 MCP server 上同样可达。
这个设计带来的实际后果是,你不需要为了接入自己的系统去改前端或写爬虫。MCP 部分列出了具体的端点和工具名:端点是 /mcp/ 用于匿名访问公开 corpus,/mcp/me/ 用于认证访问;发现入口是 /llms.txt 和 /.well-known/mcp.json;工具包括 search_corpus、list_documents、get_document_text、list_annotations、list_relationships、list_threads、create_thread_message。注意最后两个工具涉及 thread,也就是对话线程,说明 MCP 这一层不只是只读检索,还允许 agent 写入自己的注释,前提是被授权。
Python 侧的 agent 接口在 README 里给了两行示例:agents.for_document(123, corpus=45) 拿到一个文档级或 corpus 级 agent,然后 agent.stream(...) 流式返回内容。文档也提到可以走 Pydantic 模型拿回类型化对象。这个双通道设计(流式文本给聊天,类型化对象给程序)在文档里是明确写出来的,不是推测。
fieldset:用自然语言列定义一张表
结构化抽取是这个项目里最容易理解、也最容易低估的部分。机制是这样:你定义一个 fieldset,它是一组列,每一列本质上是一条自然语言查询。把这个 fieldset 跑在整个 corpus 上,抽取任务会分散到 Celery worker 上执行,结果落到一个类似电子表格的网格里,可以一次处理上百份文档。每个单元格都有人工 approve 或 reject 的操作。
这个设计把「抽取规则」和「抽取执行」解耦了。你不写正则,也不训练模型,你写问题。代价是抽取质量直接取决于底层 LLM 和文档解析质量,而解析质量又取决于文件格式。README 没有给出任何准确率数字,也没有说明当某一列在文档中找不到答案时返回什么(空值、拒答、还是幻觉填充),这一点在选型时必须自己验证。
人工 approve/reject 的存在说明作者清楚自动抽取不可全信。这是一个诚实的取舍:与其追求全自动,不如把人工确认做进流程。但如果你的文档量是几十万份,逐单元格审核本身就是瓶颈,这套流程的吞吐上限不在 Celery,而在审核人手。
可插拔流水线与它的真实边界
解析、嵌入、缩略图生成被描述为可替换组件。README 的说法是,你可以为特定格式注册自定义 parser、embedder 或 thumbnailer,下游的搜索、标注、agent 都无需改动继续工作。文档指向 docs/pipelines/pipeline_overview.md。
这个承诺的强度取决于接口设计。文档只说明了「可替换」这一层,没有给出组件接口的具体签名、失败重试语义,也没有说明当自定义 parser 输出不符合预期结构时下游会怎样表现。这是评估时最该打开文件看一眼的地方,而不是相信概述。
另外要注意 pipeline 与 Celery 的耦合。抽取是 fan out 到 worker 的,意味着这套系统的运行成本不只是 API 服务,还包括一个常驻的 worker 集群和一个向量数据库。对个人开发者而言,本地跑通演示和在生产环境稳定运行,中间隔着的运维工作量不小。
怎么把它跑起来
仓库本身没有在 README 片段里给出完整的安装命令,这一点必须说清楚:本文没有实际安装或运行过这个项目,下面的入口全部来自 README 与文档路径的引用。
从材料能确认的接入点有几个。demo 实例在 https://contracts.opensource.legal,README 明确说两个演示片段都是在本地安装上跑的原版产品,没有自定义代码,这意味着本地部署路径是存在的,只是具体命令要去看仓库文档。MCP 侧,匿名访问打 /mcp/,认证访问打 /mcp/me/,客户端发现可以读 /llms.txt 和 /.well-known/mcp.json。Python 侧,agent 通过 agents.for_document(document_id, corpus=corpus_id) 创建。
配置层面,材料里出现的可调项是 fieldset(列定义)和 pipeline 组件注册(parser、embedder、thumbnailer)。README 没有列出环境变量名、数据库连接串或 Celery broker 的具体键名,所以任何声称「设置某个环境变量即可」的说法都属于编造。要落地,第一步应该是读 docs/pipelines/pipeline_overview.md 和 docs/mcp/,确认部署形态。
和「解析加检索」路线的实际差别
最常见的替代做法是拿一个文档解析库加一个向量库,自己拼一条 RAG 链路。两者的差别不在功能多少,而在状态放在哪里。
自建 RAG 链路里,文档是原料,切块和向量是派生物,引用关系通常不建模,或者只作为 chunk 的元数据附带。OpenContracts 把引用关系提升为一等公民:它是一条边,可以被列举(list_relationships)、可以被追溯(某个法条被谁引用)、可以有悬空状态(尚未 ingest 的法律作为 backlog)。这带来一个自建方案很难低成本复制的性质:图谱可以在文档不完整的情况下仍然自洽,你知道自己缺什么。
代价是灵活性下降。自建链路里你可以随时换切块策略、换重排模型、加一层自定义过滤,改动范围自己控制。OpenContracts 把这些收进 pipeline 组件接口,你能替换组件,但要在它定义的契约内替换。如果你的需求恰好落在契约之外,绕开框架的成本可能高于一开始就自建。
判断标准可以简化成一句:你的文档之间的引用关系,是不是你真正要查询的对象。是,就用它;不是,自建更轻。
许可、维护与升级成本
许可证是 MIT,仓库未归档,最近一次推送时间是 2026-09-10,最近版本是 v3.1.0(2026-09-08),上一个重要版本 v3.0.0 的副标题是 Corpus Intelligence, Authority Linking & Deep Research。从版本节奏看,v3.0.0 在 2026-08-10,v3.1.0 在 2026-09-08,间隔约一个月。
MIT 的含义是你可以自托管、修改、闭源分发,义务很轻。但要注意两点,这里不构成法律意见:一是项目自身代码的许可,不等于你通过它调用的底层模型、解析库或向量库的许可,这些需要分别核对;二是如果你的 corpus 里包含第三方版权文档,图谱化处理不改变原始文档的版权状态。
升级成本方面,v3.0.0 到 v3.1.0 是小版本,但从 v2 线跨到 v3.0.0 这种带副标题的大版本,通常意味着数据模型或接口层面的变动。材料里没有提供迁移指南或 breaking change 清单,所以任何关于升级平滑度的判断都缺乏依据。稳妥的做法是在升级前读完对应版本的 release notes,并确认你的自定义 pipeline 组件是否仍符合新接口。
维护成本的大头不在代码,而在运行:Celery worker 集群、向量库、数据库,以及抽取结果的人工审核队列。这些是持续支出,不会因为项目是 MIT 而消失。
编辑结论
如果你的文档集合里,价值主要藏在文书之间的相互引用上(判例、法规、披露文件、合规文件),并且团队有能力自己跑 Postgres、Celery 和向量库,OpenContracts 值得先做一次概念验证。反过来,如果你要的只是把 PDF 转成可搜索文本,或者团队没有 Python 与容器运维能力,这个项目的复杂度会成为负担,用更薄的解析加检索方案更划算。动手前先确认三件事:仓库里 docs/pipelines/pipeline_overview.md 描述的组件替换边界是否覆盖你的文件格式;fieldset 抽取在你真实文档量级下 Celery 队列的吞吐表现;以及 MCP 的 /mcp/ 匿名端点与 /mcp/me/ 认证端点的权限划分是否满足你的数据隔离要求。
社区笔记