乐于分享
好东西不私藏

如果你想把文档直接灌进 SurrealDB,这个仓库把最麻烦的一层封装掉了

如果你想把文档直接灌进 SurrealDB,这个仓库把最麻烦的一层封装掉了

很多 RAG 教程都停在“提取文本、切块、做 embedding”这一步,真正到了工程落地,最麻烦的往往不是模型,而是数据库那一层:表怎么建、索引怎么配、chunk 怎么关联原文、重复内容怎么去重、全文检索和向量检索怎么一起跑。

但如果你正在用 SurrealDB 做知识库、文档搜索或者混合检索,这个仓库

kreuzberg-dev/kreuzberg-surrealdb[1]

非常值得看。


一、它解决的是 RAG 工程里最容易被低估的一层

今天大家聊 RAG,讨论最多的通常是:

  • 用什么模型做 embedding
  • chunk size 该设多少
  • 检索是 BM25 还是向量召回
  • rerank 要不要上

但只要你真的把系统做起来,就会发现还有一层更脏、更杂、也更影响稳定性的工作:

  • 文档抽取后怎么落表
  • 文档和 chunk 怎么组织
  • 检索字段怎么索引
  • 同一份内容重复导入怎么办
  • 向量维度错了怎么兜底
  • 原文元数据怎么跟 chunk 关联起来

kreuzberg-surrealdb 做的事情,本质上就是把这层工作系统化。

它不是在重复造文档抽取轮子,也不是在重新发明向量数据库,而是在 Kreuzberg + SurrealDB 之间补上了一层真正能落地的 ingest connector。

从官方 README 的一句话描述看,它的定位非常直接:

Extract, chunk, and embed documents from 88+ formats directly into SurrealDB.

这个表述的重点不在“88+ formats”,而在 directly into SurrealDB它想解决的不是“文档能不能抽出来”,而是“抽出来之后,能不能直接变成一个可搜索、可迭代、可持续入库的数据库结构”。


二、最聪明的设计,不是 embedding,而是把产品分成了两层

这个仓库最实用的一点,是它没有把所有场景都塞进一个超级类里。

相反,它把使用方式拆成了两个层级:

  • DocumentConnector
  • DocumentPipeline

这两个名字看起来只是 API 设计,但背后其实对应了两类完全不同的落地路径。

1. DocumentConnector:适合先把全文检索跑起来

如果你的需求是:

  • 先把文档抽出来
  • 先落进数据库
  • 先用 BM25 做关键词搜索
  • 先不要碰 chunking 和 embedding

那么 DocumentConnector 就够了。

它存的是完整文档,不做 chunk,不做 embedding,速度快,结构简单,也更适合项目初期验证。

这类设计的好处是,它允许团队先把“文档入库 + 全文检索”这条链路跑通,而不是一上来就把整个语义检索系统全堆上去。

2. DocumentPipeline:适合真正进入语义检索和混合检索

如果你的需求已经进入下一阶段,例如:

  • 需要 chunk 级别检索
  • 需要本地 embedding
  • 需要 BM25 + 向量混合检索
  • 需要 chunk 和原文记录之间的结构关联

那就切到 DocumentPipeline

它会把文档切成 chunk,把 embedding 算出来,把 chunk 表和 document 表一起组织好,再配上 BM25 和 HNSW 索引。

这意味着它不是简单地把“切块后的文本数组”塞进数据库,而是在数据库层面认真设计了文档和 chunk 的关系。

这个分层非常重要,因为它降低了接入门槛。

很多项目失败,不是因为技术做不到,而是因为第一版就想一步到位。kreuzberg-surrealdb 在这里的思路很现实:先给你一条轻量路径,再给你一条完整路径。


三、它真正帮你省掉的,是数据库侧的那些脏活

如果只看 README,很多人会觉得这就是一个“把文档写入 SurrealDB 的小工具”。但仔细看功能列表,会发现它真正包掉的是几件特别烦的事。

1. 自动建 schema,不需要你自己从零写

setup_schema() 会生成:

  • 文档表
  • chunk 表
  • BM25 索引
  • HNSW 向量索引
  • analyzer

对于想把 SurrealDB 用作文档检索底座的团队来说,这一步非常关键。

因为很多 PoC 卡住,并不是抽取和 embedding 不会做,而是数据库 schema 和 index 设计迟迟定不下来。这个仓库把默认结构先给出来,相当于帮你把“第一版可工作的数据库设计”也一起交付了。

2. 去重是按内容做的,不是按文件名做的

它用 SHA-256 内容哈希 做 deterministic record ID。这意味着:

  • 同一份文件重复导入,不会重复插入
  • 同样内容、不同路径,也不会被当成两份文档
  • 增量 ingestion 会更稳定

这在知识库场景里特别重要,因为现实里的文档源经常是混乱的:重命名、复制、重新上传、目录迁移都很常见。

如果没有内容级去重,数据库很快就会长满重复记录。

3. chunk 和 document 是 record link,不是松散文本

README 里有一个很值得注意的设计:chunk 不是孤立记录,它通过 SurrealDB 的 record link 指向父 document。

这件事的好处是:

  • chunk 可以直接带出父文档字段
  • 搜索结果可以回溯原始来源
  • 可以按 document 做 sibling chunk 导航
  • 质量分数、source、metadata 等文档级信息都能自然带下来

这比很多“只存 chunk 文本和向量”的方案更扎实,因为检索系统最终一定要回到来源和上下文。

4. embedding 控制做得很务实

它没有强行绑死某一个 embedding 模型,而是给了几种层次分明的选择:

  • "fast"
  • "balanced"
  • "quality"
  • "multilingual"

也支持通过 Kreuzberg 的 EmbeddingModelType 接自定义 ONNX 模型。

这类设计的价值,不是“看起来高级”,而是方便团队逐步迭代:

  • 先用默认 preset 快速跑通
  • 再按效果和成本换模型
  • 最后如果有内部模型,再替换掉默认实现

对早期团队和中型团队来说,这种过渡路径通常比“理论上无限灵活”更有价值。


四、它最适合的,不是泛数据库场景,而是 SurrealDB 的文档检索工作流

这个仓库并不是一个“通用向量数据库连接器”。它非常明显地是围绕 SurrealDB 的能力特征 来设计的。

这一点体现在三个地方。

1. BM25、向量检索、RRF 融合都直接按 SurrealDB 思路来

README 里给出的查询示例不是抽象 API,而是直接写 SurQL:

  • BM25:search::score(1)
  • 向量检索:vector::distance::knn()
  • 混合检索:search::rrf()

这说明它不是想把 SurrealDB 屏蔽掉,而是希望你继续使用 SurrealDB 的原生查询能力,只是把 ingest 和 schema 这层先帮你搭好。

这类设计适合对数据库有掌控欲的团队。你不会被限制在一个黑盒 SDK 里,依然可以自己写 SurQL、调索引参数、做特定过滤。

2. quality score 和 metadata 是一等信息

每条文档记录都可以存:

  • quality_score
  • title
  • authors
  • created_at
  • metadata
  • detected_languages
  • keywords

这意味着它并不是只为了“把文本塞进向量库”,而是默认你会关心抽取质量、文档来源和后续治理。

如果你做的是企业知识库、文档搜索或者合规检索,这些字段会比“是不是有 embedding”更重要。

3. chunking 是数据库设计的一部分,而不是预处理副产物

DocumentPipeline 会保留 chunk 的:

  • chunk_index
  • word_count
  • page_number
  • char_start
  • char_end
  • first_page
  • last_page

这让 chunk 不只是检索单元,也可以是回显、定位、溯源和高亮展示的单元。

换句话说,这不是一个“抽完文本顺便存一下 chunk”的仓库,而是把 chunk 当成数据库中的一级实体认真建模了。


五、这个仓库为什么值得看,哪怕它还很早期

说实话,这不是一个已经成熟到可以闭眼上生产的大项目。

截至 2026 年 3 月 31 日,它目前只有:

  • PyPI 版本 0.1.1
  • Development Status :: 4 - Beta
  • 很新的仓库历史
  • 没有单独的 GitHub Releases 页

这说明它还很早。

但也正因为它早,它的设计意图反而更清楚。

从 CHANGELOG.md 看,0.1.0 就已经把核心路径定下来了:

  • DocumentConnector
  • DocumentPipeline
  • ingestion 方法全集
  • 内容哈希去重
  • 本地 embedding preset
  • async context manager 生命周期

而 0.1.1 并没有大改架构,而是跟随 Kreuzberg 升级,把更好的 PDF / DOCX 抽取和更多文件格式继承进来。

这说明它当前的推进重点不是频繁换方向,而是在补稳底层能力。

对于关注 SurrealDB + 文档检索的人来说,这类项目的价值不在“有多大社区”,而在于:

它把一个非常具体、也非常真实的工程空档补上了。


六、它适合谁,不适合谁

如果你满足下面这些条件,这个仓库会非常值得试:

  • 你已经在用 SurrealDB,或者确定要用 SurrealDB
  • 你要处理 PDF、DOCX、扫描件、Office 文档等真实文档
  • 你不想自己从零设计 document / chunk schema
  • 你希望同时拥有 BM25、向量检索和混合检索能力
  • 你希望 ingestion 可以做增量更新和内容去重

但如果你的情况是下面这样,它可能还不是最优先的选择:

  • 你根本不用 SurrealDB
  • 你只想做一个最小 demo
  • 你不需要文档级和 chunk 级的关系建模
  • 你希望拿到一个现成托管平台,而不是 Python 连接器

说得更直接一点:

kreuzberg-surrealdb 不是“文档搜索平台”,它更像是 SurrealDB 文档入库层如果你刚好缺的就是这一层,它会非常顺手;如果你缺的是更上层的应用框架,那它就不是答案本身。


七、结语

kreuzberg-surrealdb 最值得看的地方,不是它把 embedding 接进了 SurrealDB。

真正值得看的,是它承认了一件很多 RAG 项目都会遇到的现实:

真正麻烦的部分,不是把文档抽出来,也不是把向量算出来,而是把文档、chunk、索引、去重、检索模式和数据库结构稳定地拼成一条长期可维护的链路。

这个仓库做的,就是那条链路里最容易被忽略、但又最容易把项目拖慢的一层。

如果你正在做 SurrealDB 上的文档检索、企业知识库、混合搜索或者 AI 检索底座,这个仓库值得尽早关注。它也许还很新,但它补的位置很对。


参考资料

  • GitHub 仓库:https://github.com/kreuzberg-dev/kreuzberg-surrealdb[1]
  • README:https://github.com/kreuzberg-dev/kreuzberg-surrealdb/blob/main/README.md[2]
  • CHANGELOG:https://github.com/kreuzberg-dev/kreuzberg-surrealdb/blob/main/CHANGELOG.md[3]
  • PyPI:https://pypi.org/project/kreuzberg-surrealdb/[4]
  • pyproject.toml:https://github.com/kreuzberg-dev/kreuzberg-surrealdb/blob/main/pyproject.toml[5]
  • 示例目录说明:https://github.com/kreuzberg-dev/kreuzberg-surrealdb/blob/main/examples/README.md[6]

References

[1] https://github.com/kreuzberg-dev/kreuzberg-surrealdb

[2] https://github.com/kreuzberg-dev/kreuzberg-surrealdb/blob/main/README.md

[3] https://github.com/kreuzberg-dev/kreuzberg-surrealdb/blob/main/CHANGELOG.md

[4] https://pypi.org/project/kreuzberg-surrealdb/

[5] https://github.com/kreuzberg-dev/kreuzberg-surrealdb/blob/main/pyproject.toml

[6] https://github.com/kreuzberg-dev/kreuzberg-surrealdb/blob/main/examples/README.md