摘要
公开的 WeKnora 文章大致分三类:NAS/Compose 启动清单、产品功能宣传向介绍、以及偏源码的局部拆解。本文按工程落地需要,把三条线拧在一起:
- 它是什么、进程怎么拆(架构与数据流)
- 检索链路为何这样设计(分块 → 混合检索 → 事件管线 → 生成)
- 怎么部署、怎么选形态(Compose / Lite / Helm)、和谁比、何时用
版本锚点:v0.8.0(官网页脚与 README 徽章一致)。仓库 Tencent/WeKnora,MIT。
1. 定位:不是「又一个聊天套壳」
WeKnora(维娜拉) 是腾讯开源的企业级知识管理 / RAG 框架,背景硬在两点:
- 官网与文档挂在
weknora.weixin.qq.com,是微信对话开放平台技术栈的开源形态(WXG 系,而非实验室 demo)。 - 同时提供 REST API、MCP Server、CLI、IM 渠道、嵌入 Widget,面向「可私有化、可集成」,而不是只做一个网页聊天窗。
README 给的三合一能力:
| 形态 | 解决什么 |
|---|---|
| RAG 快速问答 | 带引用的日常查文档 |
| ReAct Agent 智能推理 | 跨文档对比、多轮工具、联网、数据分析 |
| Wiki 模式 | Agent 把原始资料蒸馏成互链 Markdown + 图谱,可回滚 |
再叠加:多源同步(飞书 / Notion / 语雀 / GitLab / IMA / RSS…)、多租户 RBAC、技能沙箱、跨会话记忆、Langfuse 追踪。
结论先说:它是「知识中台」体量,不是单文件桌面玩具;默认 Docker 形态对内存不友好,但默认不需要单独向量库。
2. 架构:三进程 + 两基础设施 + 可选插件
2.1 核心服务
浏览器
│
▼
frontend (Nginx + Vue3) :${FRONTEND_PORT:-80}
│ 反代 /api
▼
app (Go / Gin) :8080
│ gRPC :50051(仅 compose 网内) │ SQL + BM25 + 向量
▼ ▼
docreader (Python 解析) postgres (ParadeDB pg17)
│ ▲
│ 共享卷传图片 │
└──────────────────────────── redis (Asynq + SSE 流)
| 服务 | 镜像/技术 | 职责 |
|---|---|---|
app | Go 1.26 + Gin | REST、RAG 管线、Agent 引擎、异步 worker、IM/Embed |
frontend | Vue3 + Nginx | 控制台;Nginx 反代 /api |
docreader | Python gRPC | 版式/OCR/Office/网页等解析(LibreOffice、Playwright 等,吃内存) |
postgres | ParadeDB | 业务数据 + BM25 + pgvector(RETRIEVE_DRIVER=postgres 默认) |
redis | Redis 7 | Asynq 队列、SSE 断线续传、设置 Pub/Sub、并发闸门 |
工程含义:
- 默认部署不引入独立向量库——ParadeDB 同时承担稀疏与稠密检索,减少组件。
docreader默认不映射宿主机端口,只暴露在 compose 网络。- 可选能力全部走 Compose profile(neo4j / minio / qdrant / milvus / searxng / langfuse / mcp / full…),避免一上来
--profile full把机器拖垮。
2.2 部署形态选型
| 形态 | 存储 / 队列 | 适用 |
|---|---|---|
| Docker Compose 标准 | ParadeDB + Redis | 团队/服务器,默认推荐 |
开发编排 docker-compose.dev.yml | 基础设施进容器,app/前端在宿主机热更新 | 改 Go/前端代码 |
| Lite 单二进制 | SQLite + sqlite-vec + 内存队列,无 Redis | 个人、低配、离线 |
| Helm | Chart 内置 PG/Redis | K8s ≥ 1.25 |
| 桌面(Wails) | 同 Lite 运行时 | Release 尚未附安装包 |
Homebrew weknora-lite | 同 Lite | macOS/Linux 命令行 |
硬件(官方建议):标准 Compose 4 核 / 8GB 起步;启用 Milvus、Langfuse 等再加内存。磁盘按 Postgres 卷 + data-files 文件卷预留。
2.3 源码分层(读文档时有用)
cmd/server入口;internal/分层(handler → application/service → repository)。- 检索:
RetrieveEngineRepository→ 组合引擎 → 注册表(RETRIEVE_DRIVER+ DB 内VectorStore实例)。 - 问答:事件驱动插件管线
chat_pipeline(见 §3.4),不是单函数黑盒。 - Agent:
AgentEngine跨轮无状态,历史每轮从 DB 重建;事件经EventBus→ StreamManager → SSE。
3. 特性深挖(比「功能列表」多一层)
3.1 文档入库:异步管线
上传/URL/Markdown 一律走异步:
parse(docreader) → chunk(Go chunker) → embedding/BM25 索引
→ 可选:问题生成 / 图谱抽取 / Wiki 富化
状态:pending → processing → finalizing → completed
要点:
- 解析在 Python docreader(生态:LibreOffice、OCR、Playwright…);
- 分块与索引在 Go,与业务同事务边界更清晰;
- 大文件受
MAX_FILE_SIZE_MB(默认 50)、处理超时(默认 2h)约束; - 批量 reparse、按上传
process_config覆盖解析/分块/多模态开关。
3.2 分块:自适应三级 + 父子
默认起点:chunk_size=512、overlap=80(约 15%)、strategy=auto。
auto 不是玄学,是「画像 → 尝试链 → 校验回退」:
| Tier | 策略 | 适用 |
|---|---|---|
| 1 | 标题感知(Markdown/书签层级 + 面包屑 ContextHeader) | 技术文档、导出规范的结构稿 |
| 2 | 启发式边界(换页、编号章节、全大写行、分隔线…) | OCR PDF、纯文本手册 |
| 3 | 递归 legacy(\n\n → \n → 。 + 受保护区间) | 一切兜底 |
受保护、绝不从中间切开:代码围栏、公式 $$、表格结构、图片/链接引用等;大表还有表头前置,避免后半表丢列名。
父子分块(推荐长文档):
parent ≈ 4096 字符(只入库,通常不进向量)
child ≈ 384 字符(真正被 embedding / 检索)
检索命中 child → 回答时展开 parent 上下文
调参直觉(官网表):
| 现象 | 动作 |
|---|---|
| 答案碎、缺上下文 | 调大 chunk_size 或开父子 |
| 命中的块跑题 | 调小 chunk_size,主题更集中 |
| FAQ / 参数表 | overlap=0,防相邻条目串味 |
| 长叙事 | overlap 150–200,可叠父子 |
预览:POST /api/v1/chunker/preview(不写库、不 embedding)。改配置后必须 reparse 才作用于存量文档。
3.3 检索:多引擎 + 统一 RRF
引擎矩阵(RETRIEVE_DRIVER 可逗号多驱动):
| 引擎 | 向量 | 关键词 | 典型场景 |
|---|---|---|---|
| postgres(默认) | pgvector halfvec + HNSW | ParadeDB BM25 | 默认;业务同库 |
| sqlite | sqlite-vec | FTS5 bigram | Lite / 桌面 |
| ES v8 / OpenSearch | 有 | BM25 | 已有搜索栈 |
| ES v7 | 仅关键词 | BM25 | 存量,需再配向量引擎 |
| Qdrant / Milvus / Weaviate | 原生 | 各异 | 独立扩容向量 |
| Doris / 腾讯云 VectorDB | 有 | 有 | 数仓或云托管 |
无论底层是否「原生混合」,上层混合始终是加权 RRF:
score = w_v / (k + rank_v) + w_k / (k + rank_k)
向量与关键词各自检索 → 按 rank 融合,对分数量纲免疫;跨引擎时向量分归一化到 [0,1],BM25 分不硬压。
一次典型检索还会叠加:
- 查询改写 + 意图(
kb_search/ 闲聊 / 网页…) - 查询扩展(召回不足时本地变体,中文走 jieba)
- 可选图谱实体并行(Neo4j GraphRAG)
- Rerank + 复合分
0.6·模型 + 0.3·检索 + 0.1·来源 - MMR 去冗(λ≈0.7)
- 父子展开、FAQ 填充、邻居短块扩展、历史引用注入
FILTER_TOP_K稳定排序截断- 组装上下文 → 流式生成 + 引用别名(
cN/dN不进模型明文)
这条链解释了:为什么首次「没引用」要先查 parse 是否 completed、embedding 是否换过、阈值是否过高——问题常在入库或检索配置,不在「模型不会说话」。
3.4 RAG 管线:事件插件,而不是一坨 if
问答是 事件驱动插件责任链,例如 RAG 流可动态拼成:
LOAD_HISTORY? → QUERY_UNDERSTAND → CHUNK_SEARCH_PARALLEL
→ CHUNK_RERANK → WEB_FETCH? → CHUNK_MERGE → FILTER_TOP_K
→ DATA_ANALYSIS? → INTO_CHAT_MESSAGE → CHAT_COMPLETION_STREAM
- 结果不直接写 HTTP,而是 EventBus → StreamManager(memory/redis)→ SSE 100ms 拉取。
- 因此:刷新页面可
continue-stream重放;多副本可共享 Redis 流;stop与生成解耦。 - 引用在流关闭前以
references事件先推,前端角标与「召回面板」不依赖最后一帧。
对集成方:自建面板时优先消费标准 SSE response_type(answer / thinking / references / complete…),不要假设一次性 JSON。
3.5 Agent:两种模式 + 工具面
| 模式 | 行为 |
|---|---|
quick-answer | 经典 RAG:检索→拼上下文→一次生成(不进 ReAct) |
smart-reasoning | ReAct:Think/Act/Observe,多轮工具 |
内置 Agent 示例:快速问答、智能推理(高 max_iterations)、数据分析(DuckDB SQL)、Wiki 问答/修订。
工具面(节选):knowledge_search、grep_chunks、图谱查询、web_search/web_fetch、data_analysis、沙箱 shell_exec/文件工具、search_memory、Wiki 读写、动态 MCP。
安全相关(与部署直接相关):
- MCP 危险工具可 HITL 审批(默认可等 10 分钟量级)+ 会话内 OAuth;
- 技能在 Docker / E2B / Cube 沙箱执行;
local宿主机后端已移除; - Docker 沙箱默认关:开启 ≈ 挂
docker.sock≈ 宿主机 root 级,务必威胁建模后再开; - 工具注册 first-wins,防 MCP 同名劫持内置工具。
3.6 Wiki、记忆、评估(常被一笔带过的三块)
Wiki 模式:入库侧 Agent 蒸馏互链 Markdown + Neo4j 图谱;页面有版本、行级 diff、回滚;检索侧 Wiki chunk 可加权(×1.3 量级)。这是相对 Dify/RAGFlow 更「产品完整」的差异点。
跨会话记忆:profile / preference / fact / task / interest;默认关,按空间与调用者隔离;Agent 可关 memory_enabled。
评估(Evaluation)——和「只靠手感调 RAG」对立:
- 数据集:Parquet(queries / corpus / answers / qrels / qas);
- 指标:检索 Precision / Recall / NDCG@3 / NDCG@10 / MRR / MAP;生成 BLEU-1/2/4、ROUGE-1/2/L;
- API:
POST /api/v1/evaluation创建(Admin),GET ...?task_id=轮询;结果在内存,重启丢; - 做法:固定数据集,一次只改一个变量(分块、阈值、模型、rerank)。
3.7 平台能力速览
| 能力 | 要点 |
|---|---|
| 多租户 | 空间 RBAC:Owner/Admin/Contributor/Viewer;按 KB 归属;审计默认可保留 90 天 |
| 认证 | JWT / X-API-Key(能力级 + KB 白名单)/ OIDC;注册可 invite_only |
| 模型 | LLM/Embedding/Rerank/VLM/ASR 分类;Ollama 或任意 OpenAI 兼容;LiteLLM(0.8) |
| 可观测 | Langfuse 为唯一追踪后端;解析时间线;任务队列面板 |
| 客户端 | Web、CLI(agent-first JSON)、Go SDK、Chrome 插件、小程序、DSH 插件 |
4. Docker 部署(标准路径)
4.1 启动
git clone https://github.com/Tencent/WeKnora.git
cd WeKnora
cp .env.example .env
# 必填:DB_USER / DB_PASSWORD / DB_NAME
# REDIS_PASSWORD / JWT_SECRET / SYSTEM_AES_KEY(32 字节)
docker compose pull
docker compose up -d
# 等价封装(.env 兜底、Ollama 检查、沙箱镜像预拉取):
# make start-all
docker compose ps
curl http://localhost:8080/health # {"status":"ok"}
SYSTEM_AES_KEY 必须 32 字节:租户 API Key、模型密钥、数据源凭据等落盘 AES 加密;丢了密钥 = 密文不可恢复。禁止把 .env 提交进 Git。
4.2 端口与冲突
| 用途 | 变量/端口 | 默认 |
|---|---|---|
| Web UI | FRONTEND_PORT | 80(占用则改此变量) |
| 后端 API | APP_PORT | 8080 |
| Langfuse(profile) | — | 3000 |
| docreader | 不映射宿主 | — |
若机器 80 已被其它反代占用:只改
FRONTEND_PORT=8081等,再docker compose up -d;不要为了腾 80 去动本机 Docker 里无关的其它 nginx(例如若你另有业务栈在 80/443,明确避开)。
4.3 可选 profile
docker compose --profile neo4j up -d # GraphRAG
docker compose --profile minio up -d # STORAGe_TYPE=minio
docker compose --profile langfuse up -d # 链路追踪
docker compose --profile full pull && docker compose --profile full up -d
searxng 默认只绑 127.0.0.1;对外开放必须设 SEARXNG_SECRET 并加固。自建时把 127.0.0.1 加入 SSRF_WHITELIST,否则后端出站白名单会拦。
4.4 升级 / 停止
# .env 中 WEKNORA_VERSION=目标版 或 latest
docker compose pull && docker compose up -d # 必须先 pull,否则吃旧镜像
docker compose down # 保留卷
# docker compose down -v # 删数据,慎用
4.5 Lite 单二进制
cp .env.lite.example .env.lite # SYSTEM_AES_KEY / JWT_SECRET
make run-lite
# 或 make package-lite
Lite:DB_DRIVER=sqlite + FTS5/sqlite-vec,队列 memory,前端内嵌;仍可连本地 docreader。适合先验证产品形态再决定是否上完整 Compose。
4.6 首次问答最短闭环
- 打开
http://localhost→ 注册(无默认账号;密码 8–32 且含字母数字)。 - 建知识库 → 向导配 LLM + Embedding(至少各一;可选 Rerank/VLM/ASR)。
- 容器内连宿主机 Ollama:
http://host.docker.internal:11434(Linux 依赖host-gateway)。 - 上传文档,等
completed。 - 对话页选库提问,点引用展开原文。
- 向导务必点「测试」;换 Embedding 模型必须重建索引。
API 路径与向导一一对应:注册/登录 → POST /knowledge-bases → POST /initialization/initialize/:kbId → 上传 → POST /knowledge-chat/:session_id(SSE)或 knowledge-search(只要检索)。服务端集成优先 API Key(X-API-Key),不要把 JWT 当长期凭据。
5. 和 Dify / RAGFlow / FastGPT 怎么比
没有统一官方 benchmark,下表是能力定位(非跑分):
| 维度 | WeKnora | Dify | RAGFlow | FastGPT |
|---|---|---|---|---|
| 主后端 | Go | Python | Python | Node/TS |
| 文档解析深度 | docreader + OCR + 父子 + 自适应 | 中 | 深(DeepDoc) | 中 |
| 工作流编排 | ReAct + 插件管线(偏 Agent) | 强(可视化 workflow) | 中 | 中 |
| Wiki 自维护 | 有(版本/图谱) | 无 | 无 | 无 |
| IM 渠道 | 企微/飞书/钉钉等 10+ | 部分 | 部分 | 部分 |
| 默认向量依赖 | ParadeDB 同库,可零外置 | 多种 | 多种 | 多种 |
| 多租户 RBAC | 四级 + 审计 | 有 | 部分 | 有 |
| 评估 | 内置检索/生成指标 API | 有(产品化) | 有 | 有 |
选型一句话:
- 要 可视化工作流编排、应用市场式搭建 → 优先 Dify。
- 要 解析/表格/扫描件极限质量 → RAGFlow 一类更「摄入痴迷」。
- 要 私有化 + IM + Wiki 沉淀 + 接近企业知识中台 → WeKnora 差异化最明显。
- 要 极轻个人库 → Lite,或继续用「笔记 + 薄 RAG 工具」(见本站
rag-as-agent-tool思路)。 - 已深度绑定 Dify 工作流 → 迁移成本在编排模型,不在再装一个容器。
6. 接进 DeepSeek Harness(只读知识面)
官方插件 @wxg-prc-cpg/dsh-weknora(文档写明验证 dsh 0.1.0-rc.8 + WeKnora 0.8.0):
dsh plugin --profile web add @wxg-prc-cpg/dsh-weknora
export WEKNORA_BASE_URL=https://weknora.example.com
export WEKNORA_API_KEY='<api-key>' # retrieve;ask 另需 chat
export WEKNORA_KNOWLEDGE_BASE_IDS=kb-123,kb-456
export WEKNORA_RESOURCE_URLS=public
dsh web
四个只读工具:
| 工具 | 用途 |
|---|---|
weknora_search | 混合检索片段(带 knowledge_id) |
weknora_read_document | 按文档拼回正文、翻页 |
weknora_ask | 服务端 RAG/Agent 成稿 + 引用 |
weknora_list_knowledge_bases | 列库,便于 Agent 自缩范围 |
与本站 DeepSeek Harness 插件化笔记一致:Harness 不负责检索,知识落在外部,用插件只读挂载——编码 Agent 与知识库权限面分离。
7. 安全与运维清单(生产必读)
- 网络:官方明确建议内网/反代后部署,避免裸公网;定期升级。
- 密钥:
JWT_SECRET、SYSTEM_AES_KEY、DB/Redis 口令只进环境注入;轮换 AES 主密钥前评估密文兼容。 - 沙箱:Docker 沙箱默认关;开
WEKNORA_SANDBOX_DOCKER_ENABLED=true+docker.sock等于交出宿主机控制权;Cube/E2B 用网络策略(默认可改「默认拒绝出站 + allow_out」)。 - 注册与权限:
DISABLE_REGISTRATION=true或系统设置invite_only;首个系统管理员用WEKNORA_BOOTSTRAP_SYSTEM_ADMIN_EMAIL(邮箱需先注册)。 - 文件上传:
MAX_FILE_SIZE_MB、技能包MAX_SKILL_BUNDLE_SIZE_MB(默认至 256 MiB)与 Nginxclient_max_body_size对齐。 - 审计与日志:空间审计默认可保留 90 天;Langfuse 侧注意勿把密钥打进 trace 属性。
- 评估结果内存态:不要把内存中的 evaluation 当历史存档;重要结论应外部落盘。
8. 排错表
| 现象 | 检查顺序 |
|---|---|
compose 解析失败缺 .env | cp .env.example .env(app 使用 env_file) |
上传卡 processing | docker logs WeKnora-docreader;文件大小/超时;磁盘 |
| Ollama 探测失败 | OLLAMA_BASE_URL=host.docker.internal:11434;Linux host-gateway |
| 无引用 / 召回空 | completed?→ embedding 与建库一致?→ 降 vector_threshold → 查 rerank |
| 注册页消失 | GET /auth/config 的 registration_mode(可能已是 invite_only) |
| API Key 403 | capabilities 是否含 retrieve/chat/评估;KB 白名单 |
| UI 版本与 release 不符 | 只 up -d 没 pull |
| 80 被占用 | 改 FRONTEND_PORT,勿抢机器上其它业务的 80/443 |
| 分块改了没效果 | 未 reparse;或预览与入库父子策略不一致(新版本已对齐) |
| 评估指标恒 0 | 结果 ID 是否对上 dataset pid;corpus 是否同步索引完成 |
9. 实验路径建议(按投入排序)
| 阶段 | 做什么 | 退出条件 |
|---|---|---|
| T0 半天 | Lite 或最小 Compose + 远程 API 模型,传 3~5 份文档 | 引用可点开 |
| T1 一天 | 调 chunk/父子、开 rerank,固定 20 个真实问题手感对比 | 稳定命中意图 |
| T2 | 起 Parquet 评估,锁数据集改单变量 | 有 Precision/NDCG 数字 |
| T3 | 需要时:neo4j / langfuse profile;DSH 只读接入编码 Agent | 编码流可检索且不写库 |
| T4 | IM 或 Embed Widget;关公开注册;备份卷与 AES 密钥管理 | 可对外小流量 |
不必一步 full:默认核心跑通 → 按缺口开 profile,比一次拉齐所有服务更省运维。
10. 结论
WeKnora v0.8.0 的专业价值不在「又接了几个 LLM 厂商」,而在把企业知识库的脏活做成了可替换组件:
- 摄入:独立 docreader + 自适应/父子分块 + 异步队列;
- 检索:多引擎 + 统一 RRF + rerank/MMR/引用别名;
- 交互:事件化 RAG 管线 + 可断点 SSE;
- 演进:Wiki / 记忆 / 评估 / 沙箱 / 多租户,而不是停在 demo 问答。
部署主线始终是三步:Compose 起服务 → 配 LLM+Embedding → 文档到 completed 再提问。
是否值得长期占用一台 8GB 机器,取决于你要的是「能问答」,还是「能沉淀、能评估、能接进现有 IM 与编码工作流」——后者才是它相对轻量脚手架的分水岭。
参考
官方
- 仓库:github.com/Tencent/WeKnora · CHANGELOG / LICENSE (MIT)
- 站点与文档:weknora.weixin.qq.com
- 文档专题:安装部署、快速上手、总体架构、分块机制、检索引擎、RAG Pipeline、评估能力、技能与沙箱、DeepSeek Harness 插件
社区写法(本文对照过的类型)
- 部署向:腾讯云开发者社区《轻松部署全攻略》等 NAS/Compose 清单文
- 功能向:CSDN/知乎「保姆级」介绍(偏场景与截图)
- 拆解向:掘金《开源知识库项目 WeKnora 技术拆解》(异步向量化、Asynq、多租户)
- 对比向:博客园等对 Dify/RAGFlow/FastGPT 的能力矩阵讨论
版本说明:行文以 v0.8.0 文档与 README 为准;升级前以仓库 CHANGELOG.md 为准。本文不构成安全审计;公网暴露前请按 §7 自行加固。