# MaxKB 技术架构与实现原理 MaxKB 是本次四平台横评里**部署最轻、API 自动化最顺**的一个。它定位是"开箱即用的企业内部知识库",单容器跑满所有依赖。本文拆解它的技术栈、架构、数据流和模型集成方式——所有结论均来自对其运行实例(容器进程、PostgreSQL 表结构、Django 序列化器源码、API 行为)的一手观察。 ## 一、技术栈 | 层 | 选型 | 说明 | |---|---|---| | 后端框架 | **Python / Django**(DRF 风格的 REST) | API 在 `/admin/api/...`,序列化器在 `apps/dataset/serializers/` | | 部分高性能组件 | **Go** | 向量库适配、部分 IO 密集任务用 Go 实现 | | 关系库 + 向量库 | **PostgreSQL + pgvector**(同一实例) | `document` / `paragraph` / `embedding` 三张核心表,embedding 列是 `vector` 类型 | | 缓存 / 队列 | **Redis + Celery** | 异步 embedding、文档同步走 celery | | 前端 | Vue | 单页应用,随容器发布 | | 部署 | **单容器**(4.6GB 镜像) | postgres + redis 全部内嵌,一条 `docker run` 起服务 | **"单容器"是 MaxKB 最重要的架构决策**——把 postgres、redis、后端、前端全打到一个镜像里。代价是镜像偏大、不适合超大规模横向扩展;收益是**部署心智负担最低**(一条命令、3 分钟可用、不依赖外部编排)。对中小团队内部知识库这个目标场景,这个取舍很合理。 ## 二、核心数据模型(PostgreSQL) MaxKB 的知识库数据落在三张表上(实测 `psql -U root -d maxkb` 查到): ``` document (id, name, knowledge_id, status, status_meta, ...) paragraph (id, document_id, content, status, status_meta, ...) embedding (paragraph_id, knowledge_id, embedding:vector, search_vector:tsvector) ``` - `document` 通过 `knowledge_id` 关联到知识库(不是 `dataset_id`,命名容易踩坑)。 - `paragraph` 是切片后的段落,一个 document 切出多个 paragraph。 - `embedding` 是独立的表,存 pgvector 向量 **和** 一个 `search_vector`(tsvector,用于全文检索)——MaxKB 走的是**混合检索**(向量 + 全文),不是纯向量。 `document.status` 是个有意思的字段:它用多位字符编码状态,实测看到 `nnn0` / `nnn1` / `nnn2` 等值,末位 `2` 表示 embedding 成功。`paragraph.status` 同理。 ## 三、数据流:从 PDF 到可检索 MaxKB 的灌库是**两步式**(`split` → `batch_create`),关键点是**它不自动切片**——你要么用它 split 的结果,要么自己切好。 ``` [PDF/txt 文件] │ POST /knowledge//document/split (multipart file) ▼ [split 端点: 调 PdfSplitHandle / 文本解析, 返回 [{name, content:[{title,content}], source_file_id}]] │ 注意: PDF 走 split_model.parse() 兜底分支, 输出 {title,content} dict 列表 ▼ [PUT /knowledge//document/batch_create body=[{name, paragraphs, source_file_id}]] │ DocumentInstanceSerializer 校验, paragraphs 必须是 [{content:str}] 格式 ▼ [batch_save: @post(post_embedding) 装饰器 → 事务提交后触发 celery 异步 embedding] │ 对每个 document 调 Operate.refresh() → 走 celery → 向量化 ▼ [paragraph 表写入 + embedding 表生成 pgvector 向量 + search_vector 生成 tsvector] ``` 实测中踩过一个坑:`batch_create` 的 `paragraphs` 字段,传字符串列表会 500、传错结构会"创建文档但 chunk_num=None(0 chunk)"。正确姿势是用 `split` 端点返回的 `content` 列表原样传回。这个"split 出来什么、batch_create 吃什么"的对偶设计,需要读源码(`apps/knowledge/serializers/document.py` 的 `ParagraphInstanceSerializer`)才能确认。 ## 四、模型集成:OpenAI 兼容接 Ollama MaxKB 的模型管理是最直白的——走 **OpenAI 兼容协议**,几条 POST 就能把 Ollama 接上: ``` POST /admin/api/workspace/default/model { "name": "qwen2.5-14b", "provider": "model_openai_provider", "model_type": "LLM", "api_base": "http://:11434/v1", "api_key": "ollama", ... } ``` embedding 模型同理(`model_type` 换成 embedding)。配置完直接可用于灌库(向量化)和对话。 这也是 MaxKB "API 自动化最顺"的根源——**没有 aiproxy 这样的中间层、没有插件市场、没有 mongo 模型注册表**,模型就是一张 `model` 表里的记录,CRUD 即可。对比 FastGPT 的三层模型系统、Dify 的插件市场,MaxKB 的简单在这一项上是真的省心。 ## 五、检索:hit_test 与混合检索 检索端点是 `POST /workspace/default/knowledge//hit_test`,参数有个**必须注意的坑**: ``` { "query_text": "...", # 查询文本 "top_number": 5, # top-K "similarity": 0.6, # 相似度阈值 —— 必填, 不能为 null, 不能用 0.0(会返回空) "search_mode": "embedding" # 检索模式 —— 必填, 漏了会 500 } ``` 实测漏 `search_mode` 或把 `similarity` 设 0.0,都会得到 0 结果或 500——这是最容易让初学者以为"MaxKB 检索坏了"的坑,其实只是参数。 `search_mode` 支持 `embedding`(向量)/ `blend`(混合)等。混合检索同时用 `embedding` 表的 pgvector 向量和 `search_vector` 的 tsvector,做向量召回 + BM25 全文召回的融合。对中文/英文混合、有专有名词的语料,blend 通常比纯 embedding 稳。 ## 六、为什么 MaxKB 在横评里表现"均衡" 回到横评结论,MaxKB 在四个数据集上:TechQA 90%、CUAD 84%、CMRC 92.5%、DocVQA 0%。它的特点是**没有明显短板也没有极端长板**(除了易用性和资源占用): - 检索走 pgvector 混合检索,稳但不是最快(0.59s)。 - 建库 528s(646 篇)——中规中矩,比 Dify(1307s)快、比 RAGFlow(70s)慢。 - **不做 OCR**——DocVQA 上 0 chunks,和 FastGPT 一样。这是它"均衡但不全场景"的边界。 - 单容器架构让它的资源占用最低(RAM ~最少、镜像最小),适合资源受限的私有化场景。 ## 七、API 自动化友好度总结 MaxKB 是四家里**唯一能"半天纯 API 跑通全流程"**的: - 登录:`POST /user/login`,token 放 `Authorization: Bearer`。 - 配模型:几条 POST(OpenAI 兼容)。 - 灌库:`split` → `batch_create`。 - 检索:`hit_test`(注意 `search_mode` + `similarity` 参数)。 - 对话:`/chat/api//chat/completions`(注意用 app 的 secret_key 而非 admin token)。 没有反爬码、没有 CSRF 双提交、没有插件市场、没有 aiproxy 中间层。对要做自动化集成、CI/CD 灌库、多知识库批量管理的场景,MaxKB 的摩擦度最低。 ## 八、扩展性与边界 MaxKB 的单容器架构在**横向扩展**上是弱项——pgvector 单实例的向量规模上限、单容器的并发能力,都比不上 RAGFlow(ES/Infinity 分布式)或 Dify(多服务可独立扩)。但对"几千到几万篇文档、内部几十到几百人用"的目标场景,MaxKB 的单容器足够,且运维成本最低。 如果你想深入它的某个组件(比如混合检索的融合策略、celery embedding 的并发控制、或 Go 写的向量适配层),可以继续拆。本文聚焦在"理解 MaxKB 为什么在横评里表现如此"所需的架构层面的最小完整图景。