01 · 定位与演进
它到底是什么
一个「知识框架」,而不只是「RAG 引擎」——三大能力围绕同一份知识库生长。
WeKnora(中文名「维娜拉」)是腾讯开源的企业级 LLM 知识管理框架,脱胎于微信对话开放平台的工程技术。2025 年 9 月 8 日以 v0.1.0 开源,一年迭代到 v0.8.0,已从「文档理解与检索框架」长成覆盖入库 → 检索 → 推理 → 沉淀全链路的知识平台。名字里的三大能力:
| 能力 | 一句话 | 适用 |
|---|---|---|
| RAG 快速问答 | 事件驱动的检索管线:改写 → 并行检索 → 重排 → 融合 → 带引用生成 | 日常事实型查询,秒级返回 |
| ReAct Agent 智能推理 | 自主编排知识检索、MCP 工具、技能沙箱与联网搜索的多步推理循环 | 跨文档分析、联网调研、文件产出 |
| Wiki 模式 | Agent 从原始文档自治生成相互链接的 Markdown 页面与知识图谱,支持人工编辑、版本历史与一键回滚 | 把文档库沉淀成可浏览的知识结构 |
一年演进:从检索框架到知识平台
| 版本 | 时间 | 里程碑 |
|---|---|---|
| v0.1.0 | 2025-09 | 开源首发:文档解析 + 向量检索 + Web 问答 |
| v0.2–0.3 | 2025 下半年 | ReAct Agent、MCP 工具、FAQ 知识库、父子分块;企微/飞书/Slack/钉钉/Telegram 等 IM 集成潮;Agent Skills + 沙盒执行雏形 |
| v0.4–0.5 | 2026 上半年 | Chrome 插件、Notion 连接器;Wiki 模式正式版(自治生成页面 + 知识图谱);自适应三层分块 |
| v0.6–0.7 | 2026 年中 | 空间 RBAC 四级角色、权限范围 API Key、运行时任务队列面板、多实例存储后端;官方文档站(VitePress,约 360 个 API 端点);分块编辑与版本历史;知识库文件夹树 |
| v0.8.0 | 2026-09-03 | 技能沙箱运行时(会话级 Docker / E2B / Cube)、空间技能目录(ClawHub / SkillHub / git / zip)、跨会话长期记忆、Go 进程内 anydoc Office 解析、LiteLLM、DeepSeek Harness 插件 |
值得注意的是它的「全家桶」倾向:模型厂商 20+(OpenAI、Claude、DeepSeek、Qwen、智谱、混元、Gemini、Ollama、LiteLLM 等)、向量库 9 种、对象存储 8 种、IM 渠道 10 种、数据源连接器(飞书知识库/云盘、GitLab、腾讯 IMA、Notion、语雀、钉钉、RSS……),再加网站嵌入 Widget、Chrome 插件、微信小程序与 CLI。组件全部可替换、可私有化部署,数据不出内网。
02 · 总体架构
三进程核心 + 一库两用
默认部署只有 5 个容器;向量检索不装独立向量库——PostgreSQL 一个库同时管业务数据、BM25 和 pgvector。
25+ 格式解析微服务
默认无需独立向量库
Pub/Sub · 限流 · 并发闸门
Docker(默认关)/ E2B / Cube
图 1 · 总体拓扑:实线为默认核心链路,虚线框为可选组件(app 亦可直连 compose 外的 Elasticsearch、OpenSearch、腾讯云 VectorDB 等)
几个有信息量的架构决策
- ParadeDB 一库两用。默认 postgres 镜像是 ParadeDB 发行版(pg17),自带 BM25 全文检索(
paradedb.score+|||操作符)与 pgvector 向量能力,单机部署不引入额外向量库;需要扩容时再用RETRIEVE_DRIVER切换 Qdrant / Milvus / Weaviate / Doris / ES / OpenSearch / 腾讯云 VectorDB / SQLite。 - Redis 承担五种角色。Asynq 异步任务队列、SSE 流断线续传的 Stream Manager(跨实例)、system_settings 发布订阅、Embed 渠道限流、分布式 per-model 并发信号量。不配 Redis(Lite 模式)时 Asynq 退化为进程内同步执行。
- app ↔ docreader 走 gRPC(TLS + Token 可选),大扫描件用流式
ReadStream规避 gRPC 消息上限,解析出的图片经共享卷docreader-tmp传递、由 Go 侧统一落存储。 - 四种部署形态:标准 Docker Compose(profile 按需叠加);Lite 模式(SQLite + sqlite-vec + 进程内队列,单二进制内嵌前端);桌面版(Wails v2);Kubernetes Helm Chart 与裸机 systemd。
技术栈速览
| 层 | 选型 |
|---|---|
| 后端 | Go 1.26 · Gin · GORM · uber/dig 依赖注入 · golang-migrate 自动迁移 · viper 配置 |
| 异步任务 | hibiken/asynq(Redis),6 个 worker 池,失败重试 + 死信巡检 |
| 文档解析 | Python + grpcio 微服务 docreader;Go 进程内 anydoc(cgo 链接 Rust 库) |
| 前端 | Vue 3 + TypeScript + Vite 7 + TDesign + Pinia;Marked / KaTeX / Mermaid / highlight.js |
| 认证 | JWT Bearer / X-API-Key / OIDC(JWKS 验签)三态 |
| 可观测 | OpenTelemetry → Langfuse(唯一追踪后端),LLM 调用级 trace |
| AI 接入 | 20+ 模型厂商;mark3labs/mcp-go 外接 MCP 工具(含 OAuth2) |
03 · 文档入库
一条带自愈的异步管道
HTTP 层只落库与入队,所有耗时工作由 Asynq Worker 池消费;原子计数器收敛终态,后台巡检回收僵尸任务。
创建 Knowledge 记录
产物统一为 Markdown + 图片
面包屑入 ContextHeader
写入向量库 + BM25
生成 image_ocr / image_caption 子块
expectedSubtasks 原子计数
计数归零自动升级
图 2 · 入库管线:核心五阶段(解析→分块→索引→多模态→后处理)+ 富化扇出
解析:七个引擎,统一产物
支持的格式覆盖 PDF / Word / TXT / Markdown / HTML / EPUB / MHTML / 图片 / CSV / Excel / PPT / JSON / XMind 及音频(ASR 转写)。解析引擎按文件类型路由,产物统一为 Markdown 文本 + 图片字节,图片持久化由 Go 侧负责:
| 引擎 | 说明 |
|---|---|
| builtin(gRPC) | Python docreader 服务:PDF(含 OCR)/ DOCX / Excel / EPUB / 网页抓取等 25+ 解析器,可插拔 markitdown(微软)与 opendataloader(PDF 版面分析) |
| anydoc(进程内) | v0.8 新增:Go 进程经 cgo 链接 Rust 库,Office 文档不出进程即可解析,嵌入图按原文档位置插回 Markdown |
| simple(Go 原生) | md / txt / csv / json / 图片 / 音频直接处理,无外部依赖 |
| 云引擎 | WeKnora Cloud 托管解析、MinerU、PaddleOCR-VL(本地/云)——扫描件与复杂版面的增强选项 |
分块:自适应三 Tier + 校验器回退链
这是 WeKnora 工程上最讲究的部分。分块在 Go 侧完成,默认 512 字符、重叠 80,策略为 auto 时先对文档做单遍画像(标题密度、编号小节、换页符、语言检测等),再组装尝试链:
- Tier 1 标题分块:Markdown 结构规整时,按主标题层级切段,标题面包屑存入与正文分离的
ContextHeader——只进 embedding,不污染原文,向量携带章节语境而原文偏移不变。 - Tier 2 启发式边界:面向 OCR 出的 PDF / 纯文本手册,按换页符、编号小节(
1.2.3、第一章、Chapter 3)、全大写标题、分隔线、页脚等 7 类正则找边界,贪心装箱。 - Tier 3 递归分块:经典分隔符递归(
\n\n→\n→。),公式 / 代码块 / 表格 / 图片链接是受保护区绝不从中间切;重叠取语义后缀(段→行→句边界)而非定长切片。 - Validator 把关:每层结果要过五条拒绝规则(大文档只出 1 块、碎块过多、全部远小于目标、超 2 倍预算……),不过就降级下一层。
POST /api/v1/chunker/preview可在改参数前试切并返回每层被拒原因。 - 表格表头追踪:大表被切碎后,每片自动前置表头行,列名上下文不丢。
状态机与自愈:别小看这部分
富化阶段用 pending_subtasks_count 原子递减收敛终态,短缺时补偿递减防止永久卡在 finalizing;递减动作用 context.WithoutCancel 脱离上下文执行,避免 worker 优雅退出丢计数。后台每 5 分钟一轮 Housekeeping,按「updated_at 粗筛 → span 心跳复核 → 队列内检查」三重判据,把 worker 崩溃 / Redis 丢任务留下的僵尸回收为 failed,用户可一键 reparse 重来。索引失败还有补偿回滚:删掉已写 chunks 并清向量索引,不留半成品。
这张安全网是为万级文档批量入库设计的——v0.5.2 专门为 Wiki 入库补了任务队列 + 死信队列,长跑型任务的可靠性在这里是显式设计目标,而不是「碰运气」。
04 · 检索与问答
事件驱动插件管线
每个阶段是一个插件,管线按请求特征动态组装;结果经 append-only 事件流推给 SSE,断线可从零重放。
(闲聊/问候直接跳过检索)
召回不足→本地查询扩展
(可选)
(可选)
MMR 多样性→Wiki 加权 ×1.3
(重排之后才花这个钱)
父子块回捞/邻居扩展
references 先于答案推送
图 3 · RAG 管线(quick-answer 模式):检索无结果时走兜底策略(固定文案或模型自由回答),不直接报错
混合检索:两路单模 + 上层 RRF
不管底层引擎自身是否支持混合检索,WeKnora 都坚持向量、关键词各自独立检索,在上层做加权 RRF 融合——引擎只需提供两类单模能力,融合逻辑全局统一:
- 过召回:实际取
matchCount = max(topK×5, 50) × 库数(上限 500),给后面的重排和融合留冗余; - 跨库硬约束:一次多库检索的所有知识库必须共享同一 embedding 模型身份,否则拒绝——避免跨向量空间的分数不可比;查询向量按模型身份分组只算一次;
- 跨引擎分数归一化:多存储扇出结果混合时,把 Milvus 的 [-1,1] cosine 等各引擎值域统一映射到 [0,1];BM25 分数故意不归一化(值域无上界,压缩会坍缩长尾),因为 RRF 基于 rank 天然免疫尺度差异;
- FAQ 迭代扩召回:FAQ 库结果不足时 TopK 从 3 倍起最多 5 轮翻倍重检索,并支持「负例问题」过滤——这条 FAQ 不要用来答某类问题。
重排:一段值得抄的打分逻辑
- 重排前先清洗 passage:剥离 Markdown 语法噪声,但代码块与公式只脱围栏、保留正文(整块删除会把纯代码候选清成空串而丢分);再拼入图片 Caption/OCR 与预生成问题做增强;
- 全低于阈值但 top1 ≥ 0.15 时保留 top1 兜底;阈值 > 0.3 且无结果时自动降级(×0.7)重试一次;Rerank API 挂了回退原始检索结果继续跑;
- MMR 多样性选择(λ=0.7)压制冗余;Wiki 页面(LLM 预综合过的知识)在重排后乘 1.3 加权——预综合内容优先于原始碎片;
- 合并阶段八步流水:历史引用注入(Jaccard 过滤、打 0.6 折)、父子块上下文回捞、相邻块拼接、FAQ 答案回填、短块邻居扩展(不足 350 字符拉邻居到 850)、二次去重。
引用机制:模型永远看不到真实 UUID
这是全项目最「工程师味」的设计。为了让引用可验证又不怕模型篡改,每次回答维护一个请求级注册表,把真实 ID 替换成低熵别名:知识块 c1 c2…、网页 w1…、文档 d1…、知识库 b1…。system prompt 追加引用协议,要求模型用 <ref id="c3"/> 内联引用;输出流经 StreamExpander 实时展开成公开标签,未知别名 fail-closed 直接删除。同理,minio://、cos:// 这类高熵存储句柄被替换为 res://0001 再进模型上下文,防止模型复述时篡改 URL——解码时带 Flush 处理跨 chunk 分裂的标签。
SSE:断线续传是第一公民
生成不直接写 HTTP:每请求独立 EventBus → 订阅者把事件追加进 StreamManager(内存或 Redis,append-only,按 offset 拉取)→ HTTP 层 100ms 轮询推 SSE。生成 goroutine 与连接完全解耦,所以刷新页面、网络闪断都不中断生成,GET /continue-stream/:id 从 offset 0 重放全部事件再续推;「停止」走双通道(SSE 内检测 + 独立 watcher),客户端已断开也能取消。引用列表作为独立 references 事件先于答案推送,保证连接关闭前客户端已拿到引用。
05 · Agent 引擎
无状态引擎上的 ReAct 循环
引擎跨轮无状态,历史每轮从 DB 重建;终止条件穷举了七种退出路径,连「连续两轮说一模一样的话」都有专门的卡死检测。
对话框里的「智能推理」模式进 Agent 引擎(quick-answer 模式走经典 RAG 管线,不进引擎)。每轮迭代四阶段:
工具集
| 类别 | 工具 | 备注 |
|---|---|---|
| 知识库 | search_knowledge(hybrid / semantic / keyword 三模式)、read_document(分页 + 块内正则)、list_documents | v0.8 后整合旧工具,兼容别名自动映射 |
| Wiki ×10 | wiki_search / wiki_read_page / wiki_write_page 等只读 + 写操作 | 维基问答用只读集,维基修订用全集 |
| 联网 | web_search / web_fetch | 11 种搜索后端,DuckDuckGo / SearXNG 可自托管 |
| 数据分析 | data_schema / data_analysis | CSV/Excel 载入 DuckDB,LLM 生成 SQL 执行 |
| 沙箱技能 | shell_exec、read_file(skill://…)、文件读写编辑 | 会话级沙箱内执行,产物落 /workspace/output |
| MCP | mcp_{service}_{tool} 动态注册 | 危险工具走人工审批卡片(10 分钟等待),会话内可完成 OAuth 授权 |
内置 Agent 与类型预设
| 内置 Agent | 模式 / 预设 | 要点 |
|---|---|---|
| 快速问答 | quick-answer | 经典 RAG,FAQ 优先(直接回答阈值 0.9),不进引擎 |
| 智能推理 | smart-reasoning / rag-qa | max_iterations 50,检索四件套 + 图谱 + 联网 |
| 数据分析师 | smart-reasoning / data-analysis | temperature 0.3,仅 DuckDB 工具,限定 csv/xlsx |
| 维基问答 | smart-reasoning / wiki-qa | 只读 wiki 工具 + wiki_flag_issue 报障 |
| 维基修订 | 内部 Agent(列表不可见) | 9 个 wiki 写工具,跨轮保留检索历史 |
类型预设(rag-qa / wiki-qa / hybrid / data-analysis)只在编辑器里预填表单,用户可任意覆盖。多轮强制开启,历史按上下文窗口加载;达到最大迭代上限时不是报错,而是把全部工具结果作为 user 消息喂给 LLM 合成最终答案;用户点停止时若已有工具结果,也会「抢救性合成」——任何退出路径都尽量给出可用答案。
06 · 三个方向性能力
技能沙箱 · Wiki 模式 · 长期记忆
v0.5–v0.8 的三次「加点」,把知识库从「能查」推向「能干活、能沉淀、能记住你」。
技能沙箱:Agent Skills 的平台化实现
技能 = SKILL.md 说明 + 脚本 + 模板,从 ClawHub / SkillHub / git 仓库 / zip 安装为空间级资源(不是丢在进程旁边的文件);执行走会话级常驻沙箱,一个会话一个实例,三后端共享一套 RemoteSandboxClient 协议:
- Docker(单机自托管,走 Engine API;默认关闭——挂载
docker.sock等于给 app 宿主机 root,需管理员显式开启,容器内以 uid 1000 执行); - E2B / Cube(云或自托管控制面,支持网络策略:默认拒绝出站 + IP/CIDR/域名放行清单、L7 规则);
- 环境变量四级解析:个人技能值 > 个人沙箱值 > 空间技能值,秘密值只注入不回显;产物写
/workspace/output被系统收集为消息附件,沙箱重建不丢交付物。
Wiki 模式:Agent 自治的知识沉淀
知识库开启 Wiki 索引策略后,入库管道会在富化阶段调用 LLM 从文档中提取人物、产品、概念等条目,生成相互链接、带来源引用的 Markdown 页面(6 种类型:summary / entity / concept / index / synthesis / comparison,后两种仅 Agent 可创建),外加可视化知识图谱。关键是它把「生成内容」当文档系统而不是一次性输出对待:
- 每次覆盖前旧版本先整份快照,历史支持行级 diff 与一键回滚(回滚本身也产生新版本,可再回滚);
- 版本来源四类(pipeline / agent / user / revert),保留策略软上限 50 版(只清理自动生成)、硬上限 200 版;
- 服务重启后自动恢复持久化的待处理 Wiki 任务,万级文档靠任务队列 + 独立 lane 吞吐。
跨会话长期记忆:确认制的个人信息库
记忆按「空间 × 调用者身份」隔离(IM 用户、嵌入访客各自独立),分五类:profile / preference / fact / task / interest。自动抽取产生的推断条目先 pending、用户确认后才生效;反复讨论的主题可「提升」为长期关注;反复引用的文档形成偏好、反向影响检索排序(但永不扩展知识库权限)。常驻记忆(资料/偏好)每轮随提示注入,情景事实按当前问题词法 + 可选语义召回,Agent 也可主动 search_memory。注意这是 v0.8 新做的独立体系,不是早年被移除的 Neo4j 会话记忆复活。
07 · 平台工程面
把它当企业软件看
RBAC、审计、密钥加密、SSRF 防护、任务队列治理——这些「不性感」的部分决定它能不能进生产。
| 维度 | 要点 |
|---|---|
| 多租户与权限 | 空间 RBAC 四级角色(Owner / Admin / Contributor / Viewer)+ 资源归属 + 每空间审计日志;invite-only 准入;跨空间共享 Agent 强制只读、检索 scope 切到属主租户 |
| API 集成 | 权限范围 API Key:能力级授权 + 按知识库限制 + 节流的 last_used 追踪;平台级 Key 管控制面(空间管理、系统设置、队列治理) |
| 安全 | API Key 与 MCP/数据源凭据 AES-256-GCM 静态加密 + 平滑轮换;app↔docreader gRPC TLS + Token;防 SSRF 的 HTTP 客户端(URL 导入、数据源、重定向链三重校验防 TOCTOU);OIDC JWKS 验签;密钥响应脱敏 |
| 可观测 | Langfuse 全链路:ReAct 循环、Token 消耗、工具调用、解析管线逐阶段时间线(Span 树);系统级任务队列面板(队列深度、按模型并发、失败重试) |
| 任务治理 | 分阶段独立 Worker 池(core 8 / 后处理 2 / 富化 12 / 维护 4 + Wiki 独立池),按模型后台并发治理;版本升级自动数据库迁移(90+ 个迁移文件) |
| 存储编排 | 每空间多实例存储后端:不同知识库绑定不同存储(local / MinIO / COS / TOS / S3(IAM Role)/ OSS / KS3 / OBS),resource:// 引用层支持无感迁移 |
接入面全景
数据源连接器支持飞书知识库 / 飞书云盘 / Lark / GitLab / 腾讯 IMA / Notion / 语雀 / 钉钉文档 / RSS 自动同步(增量 + 全量)。对 AI 编码工作流有个有趣的落点:官方 DeepSeek Harness 插件把 WeKnora 变成编码 Agent 的外挂知识库——weknora_search 返回带 knowledge_id 的原文片段,可翻页读回全文。
08 · 上手路径
五分钟跑起来
默认 profile 只起 5 个核心容器,本地 Ollama 模型也能直接接。
git clone https://github.com/Tencent/WeKnora.git
cd WeKnora
cp .env.example .env # 按需编辑(模型 Key、端口等,文件内有注释)
docker compose pull # 拉取最新镜像(升级时必做,见下方坑)
docker compose up -d
# Web UI → http://localhost · 后端 API → http://localhost:8080
可选服务按 profile 叠加:--profile neo4j(GraphRAG)、minio(对象存储)、langfuse(链路追踪)、searxng(自托管搜索)、full(全部)。改代码走快速开发模式:make dev-start(基础设施)→ make dev-app(后端 Air 热重载)→ make dev-frontend(前端 Vite 热重载),不用重建镜像。
--profile neo4j 开图谱后重解析,看 GraphRAG 与 Wiki 图谱;⑤ 用 PyPI 的 tencent-weknora-mcp 把知识库挂进 Claude / 其他 MCP 客户端;⑥ 跑一遍 Langfuse trace,看每轮 Token 花在哪。
09 · 点评与踩坑清单
读完全部架构文档之后的判断
以下为学习笔记的个人判断与源码事实摘录,供决策参考。
亮点:工程深度在「管线两端」
- 入库端的状态机 + 自愈(原子计数收敛、housekeeping 三重判据、索引失败补偿回滚)和检索端的打分细节(RRF 上层统一、跨引擎归一化、重排清洗 + 阈值降级 + top1 兜底、MMR、引用别名)是同类开源项目里少见的完成度——大部分「RAG 框架」只做到把向量库查出来拼 prompt。
- 引用别名机制(模型看不到真实 ID / URL,输出 fail-closed 展开)同时解决了幻觉引用与注入两个问题,值得任何做带引用问答的团队抄。
- 企业特性是原生的而不是后补的:RBAC / 审计 / 权限范围 API Key / 多存储后端 / 任务队列面板在架构文档里与检索特性同级展开。
- 中文场景适配细:jieba 查询扩展、中文按字分词的 Jaccard、FTS5 bigram、Doris chinese parser、中文正则(第一章/第3节)。
权衡
- 功能面极宽(20+ 模型厂商 × 9 向量库 × 10 IM × 9 数据源),配置面随之膨胀——官方环境变量约 150 个,小团队未必都用得上,建议从默认 profile 起步按需开。
- 重量级能力(Wiki、图谱、问题生成、自动标签)都按 LLM 调用计费,批量入库前先在小批量上估算用量;Langfuse 面板能看到每类任务的真实开销。
坑与注意(源码 / CHANGELOG 实录)
- 沙箱 Docker 后端默认关闭,且挂 docker.sock ≈ 宿主机 root。单机体验可以显式开启(
WEKNORA_SANDBOX_DOCKER_ENABLED=true),生产建议远端 daemon + TLS 或 E2B/Cube;旧的 Local 宿主机进程后端已在 v0.8 移除。 - 升级必须
docker compose pull:只up -d会复用本地缓存镜像,Web UI 显示版本与实际 release 不一致。 - 官方明确建议内网部署,勿直接暴露公网(生产环境配防火墙,保持更新)。
- ES v7 驱动只做关键词引擎(能力声明不含 vector),要向量得配 v8 / OpenSearch 或与其他驱动组合
RETRIEVE_DRIVER=postgres,elasticsearch_v7。 - 跨库检索必须同 embedding 模型;改分块配置后已有文档要 reparse 才生效;overlap > chunk_size/2 会被钳到一半。
- Lite 模式的取舍:SQLite + 进程内任务执行,重启可能丢队列任务(Wiki 有持久化待处理表兜底恢复),只适合桌面 / 开发 / 微型部署。
- Postgres 向量索引的隐藏要求:HNSW 建在
halfvec(dim)表达式上,查询的 ORDER BY 必须与索引表达式逐字一致才走索引——自己改 SQL 时容易踩。
10 · 参考
链接与阅读路径
- github.com/Tencent/WeKnora — 主仓库(MIT;本页基于 v0.8.0 / main 分支,2026-09-20 阅读)
website-docs/— 官方产品文档站源码(VitePress,六大板块约 50 篇):02-architecture 四篇(总体架构 / Go 后端设计 / 文档入库 / RAG 管线)是理解全项目信息密度最高的材料CHANGELOG.md— 版本演进实录,每条带 issue 号,可按图索骥读源码docs/sandbox-protocol.md、docs/QA.md— 沙箱协议与常见问题排查
本页为个人学习笔记,与腾讯官方无关;引用事实均出自上述仓库的 README、CHANGELOG 与 website-docs,判断性内容已单独标注。