犀牛鸟 2026 研究笔记 estelledc.github.io

Ch36: AnythingLLM 源码走读——Collector 与适配器

Part 9 · 前置:Ch19 AnythingLLM 精读 · 后续:Ch37 五平台对照实验

结论先行:AnythingLLM 大师读 server/(Express 业务)+ collector/(解析向量化独立进程)+ server/utils/vectorDbProviders/(向量适配器)。代码量小于 WeKnora,适合 一天读完架构——学 减法设计适配器模式。与 WeKnora 对比:AnythingLLM 故意不做 BM25/图谱/Rerank;WeKnora 十库 VectorStore 接口 与 AnythingLLM 十一 Provider 文件同构,见 Ch30


一、日常类比

AnythingLLM 像 随身瑞士军刀:一个 Electron 壳、本地 SQLite、默认 LanceDB——开箱即用,换「刀片」(向量库/LLM)只换卡槽不拆整机。WeKnora 像 专业工具箱:BM25、图谱、Rerank 都有,更重但企业检索更稳。大师学 AnythingLLM 的 接口边界零配置默认,不必复制其检索深度。


二、Commit / 版本 Pin 说明

建议
仓库 Mintplex-Labs/anything-llm
分支 master + clone 日 2026-06 commit
运行 yarn setup → Desktop 或 server/ + frontend/ 分离 dev
git clone https://github.com/Mintplex-Labs/anything-llm.git
cd anything-llm && git rev-parse HEAD > ~/anythingllm-pin.txt
cd server && yarn && yarn dev

Pin 与 Ch37 元数据「AnythingLLM commit」列一致。


三、目录地图

server/
  endpoints/              # REST:workspace, document, chat
  utils/vectorDbProviders/  # LanceDB, Chroma, Qdrant... 各一文件
  utils/chats/            # 默认 RAG vs @agent 分支
  models/                 # Sequelize + SQLite
collector/
  processSingleFile/      # 解析 → chunk → embed(独立 Node 进程)
  utils/extensions/       # 格式扩展
frontend/                 # React SPA
document-storage/         # 原始文件
对比项 AnythingLLM WeKnora
向量抽象 BaseVectorDb + 子类文件 VectorStore interface + driver
隔离单位 Workspace ID metadata kb_id / tenant filter
检索 纯向量 similarSearch BM25 + 向量 + PMI + RRF

四、一条具体调用链(上传文档 → 向量检索 → 回答)

server/endpoints/api/document/index.js           # POST 上传
  → server/utils/files/multer.js                 # 存 document-storage/
  → server/utils/collectorApi/index.js           # HTTP 调 collector 进程
  → collector/processSingleFile/index.js         # processFile()
  → collector/utils/extensions/PDFLoader/...     # 按扩展名解析
  → collector/utils/textSplitter/index.js        # chunk
  → collector/utils/embedder/index.js            # 调 embedding API
  → server/utils/vectorDbProviders/lance/index.js  # addDocument(chunks)
       # metadata.workspaceId = 当前 Workspace
--- 用户提问 ---
  → server/endpoints/api/workspaceThread/chat.js
  → server/utils/chats/stream.js                 # 默认 RAG 路径
  → server/utils/vectorDbProviders/lance/index.js  # similarSearch(query, k, {workspaceId})
  → server/utils/AiProviders/openAi/index.js       # LLM 生成

输入 @agent 时分支到 server/utils/agents/——「默认 RAG / 按需 Agent」渐进复杂度。


五、grep 起手式

cd anything-llm
rg -n "class LanceDb|BaseVectorDb" server/utils/vectorDbProviders/
rg -n "workspaceId|workspace_id" server/ collector/
rg -n "processFile|processSingleFile" collector/
rg -n "@agent|agentHandler" server/utils/
rg -l "similaritySearch|similarSearch" server/utils/vectorDbProviders/

WeKnora 对照:

# 在 WeKnora 仓库
rg -n "type VectorStore interface" --glob '*.go'
rg -n "kb_id|KnowledgeBaseID" internal/ -g '*vector*'

六、适配器模式:与 WeKnora 同构点

// AnythingLLM 概念 — server/utils/vectorDbProviders/base.js
class BaseVectorDb {
  async connect() {}
  async addDocument(chunks) {}
  async similaritySearch(query, k, filter) {}
}
// WeKnora — internal/.../vectorstore 同职能
type VectorStore interface {
    Upsert(ctx, vectors) error
    Search(ctx, query, topK, filter) ([]Hit, error)
}

差异:AnythingLLM 新库 = 新 JS 文件;WeKnora = 新 Go driver。共性:业务层不 import 具体 SDK。见 Ch30case-1633


七、动手练习(45–60 分钟)

时段 任务
0–15 min 起 server+collector,建 Workspace A/B
15–30 min 各上传 weknora-arch.md,确认 B 搜不到 A 的 chunk
30–45 min lance/index.jssimilarSearch filter 构造
45–60 min 对比 Ch302 个故意不做的 RAG 能力及理由

章末自检


延伸阅读