1. 引言:从信息检索到智能问答的演进
在企业数字化转型的浪潮中,知识管理始终是一个核心命题。传统的文档管理系统依赖关键词匹配,用户需要精确记忆文档中的术语才能找到所需内容,这种方式在面对海量异构文档时显得力不从心。随着大语言模型(Large Language Model, LLM)技术的成熟,一种名为 RAG(Retrieval-Augmented Generation,检索增强生成)的技术范式逐渐成为解决这一问题的主流方案。
RAG 的核心思想并不复杂:将用户的自然语言问题转化为向量表示,在预先构建的文档向量索引中检索出语义相关的内容片段,再将这些片段作为上下文提供给大语言模型,由模型生成最终的回答。这种方式既保留了大模型强大的语言理解和生成能力,又通过检索机制引入了外部知识,有效缓解了模型"幻觉"问题,使回答更加准确可靠。
然而,从理论到工程落地之间存在着巨大的鸿沟。一个生产级别的 RAG 系统需要解决诸多技术挑战:如何高效解析 PDF、Word、图片等多种格式的文档?如何处理文档中的表格、图表等复杂结构?如何设计检索策略以平衡召回率和精确度?如何支持多租户隔离和权限管理?这些问题的答案,正是 WeKnora 框架所要提供的。
WeKnora是腾讯开源的企业级文档理解与语义检索框架,其名称寓意"We Know RAG"——我们深谙 RAG 之道。该框架采用模块化架构设计,将文档解析、向量索引、智能检索、大模型生成等环节解耦,使得各组件可以独立演进和替换。无论是接入不同的向量数据库,还是切换底层的大语言模型,都可以通过配置完成,无需修改核心代码。
2. 技术架构总览
2.1 分层架构设计
WeKnora 采用经典的分层架构,从上到下依次为表现层、业务逻辑层、数据访问层和基础设施层。这种设计使得系统具备良好的可维护性和可扩展性,各层之间通过明确定义的接口进行通信,降低了模块间的耦合度。
从架构图中可以看出,WeKnora 的设计遵循了"关注点分离"原则。表现层负责与用户交互,提供 Web 界面、API 接口和 MCP 协议支持;业务逻辑层封装了知识库管理、文档处理、会话管理和智能推理等核心功能;数据访问层抽象了不同类型的存储后端,包括向量数据库、关系型数据库、图数据库和对象存储;基础设施层则提供了文档解析、向量生成、大模型调用等底层能力。
2.2 项目目录结构
理解一个开源项目的最佳方式是从其目录结构入手。WeKnora 的代码组织清晰,各模块职责分明:
WeKnora/ ├── cmd/# 应用程序入口点│ ├── server/# 主服务器启动入口│ └── download/# 模型下载工具├── internal/# 核心业务逻辑(Go 语言实现)│ ├── agent/# ReACT Agent 智能推理引擎│ ├── handler/# HTTP 请求处理器│ ├── models/# LLM 和 Embedding 模型管理│ ├── searchutil/# 检索工具和文本处理│ ├── types/# 数据类型和接口定义│ ├── router/# API 路由配置│ ├── middleware/# HTTP 中间件│ ├── database/# 数据库连接管理│ └── container/# 依赖注入容器├── docreader/# 文档解析服务(Python + gRPC)│ ├── parser/# 多格式文档解析器│ ├── splitter/# 文本分块处理│ ├── ocr/# 光学字符识别模块│ └── proto/# gRPC 协议定义├── frontend/# Web 前端(Vue 3 + TypeScript)│ ├── src/components/# Vue 组件库│ ├── src/views/# 页面视图│ ├── src/api/# API 调用封装│ └── src/stores/# Pinia 状态管理├── mcp-server/# MCP 协议服务器(Python)├── config/# 配置文件模板├── migrations/# 数据库迁移脚本├── docker/# Docker 镜像构建文件├── helm/# Kubernetes Helm 部署配置└── scripts/# 启动和运维脚本这种目录结构体现了几个重要的设计决策。首先,后端核心逻辑使用 Go 语言编写,放置在internal目录下,这是 Go 语言的惯例,表示这些包不对外暴露。其次,文档解析服务独立为docreader模块,使用 Python 实现并通过 gRPC 与主服务通信,这样做的好处是可以充分利用 Python 生态中丰富的文档处理库。最后,前端采用现代化的 Vue 3 技术栈,与后端完全解耦,便于独立开发和部署。
3. 核心模块深度剖析
3.1 文档解析服务(DocReader)
文档解析是 RAG 系统的第一道关卡,其质量直接决定了后续检索和生成的效果。WeKnora 的 DocReader 服务采用 Python 实现,通过 gRPC 协议与 Go 后端通信,支持多种文档格式的结构化解析。
支持的文档格式:
| 格式类型 | 文件扩展名 | 解析能力 |
|---|---|---|
| PDF 文档 | 文本提取、表格识别、图片抽取 | |
| Word 文档 | .docx, .doc | 段落解析、样式保留、嵌入图片处理 |
| Markdown | .md | 结构化解析、代码块识别 |
| 纯文本 | .txt | 直接读取 |
| 表格文件 | .xlsx, .csv | 行列解析、表头识别 |
| 图片文件 | .png, .jpg | OCR 文字识别、图像描述生成 |
DocReader 服务通过 gRPC 协议对外提供接口,其核心协议定义如下:
// docreader/proto/docreader.proto service DocReader { // 从本地文件读取文档 rpc ReadFromFile(ReadFromFileRequest) returns (ReadResponse); // 从 URL 读取文档 rpc ReadFromURL(ReadFromURLRequest) returns (ReadResponse); } message ReadConfig { int32 chunk_size = 1; // 分块大小,默认 500 字符 int32 chunk_overlap = 2; // 分块重叠,默认 50 字符 repeated string separators = 3; // 自定义分隔符 bool enable_ocr = 4; // 是否启用 OCR string ocr_backend = 5; // OCR 后端:paddle/api/no_ocr } message Chunk { string id = 1; // 分块唯一标识 string content = 2; // 分块文本内容 int32 page_number = 3; // 所在页码 string metadata = 4; // 元数据 JSON } message ReadResponse { repeated Chunk chunks = 1; // 文档分块列表 repeated Image images = 2; // 提取的图片列表 string metadata = 3; // 文档级元数据 }这个协议设计体现了几个关键考量。chunk_size和chunk_overlap参数控制文本分块策略,合理的分块大小对检索效果至关重要——过大会导致检索精度下降,过小则可能丢失上下文语义。enable_ocr参数允许按需启用 OCR 功能,对于纯文本 PDF 可以关闭以提升处理速度。
3.2 向量检索引擎
向量检索是 RAG 系统的核心环节。WeKnora 设计了一套灵活的检索引擎抽象,支持多种向量数据库后端,并提供混合检索策略。
检索引擎接口定义:
// internal/types/interfaces/retrieve_engine.gotypeRetrieveEngineinterface{// 返回引擎类型标识EngineType()types.RetrieverEngineType// 执行检索操作Retrieve(ctx context.Context,params types.RetrieveParams)([]*types.RetrieveResult,error)// 返回支持的检索类型Support()[]types.RetrieverType}typeRetrieveEngineRepositoryinterface{// 保存单个索引Save(ctx context.Context,indexInfo*types.IndexInfo,paramsmap[string]any)error// 批量保存索引BatchSave(ctx context.Context,indexInfoList[]*types.IndexInfo,paramsmap[string]any)error// 按分块 ID 删除索引DeleteByChunkIDList(ctx context.Context,indexIDList[]string,dimensionint,knowledgeTypestring)error// 复制索引(用于知识库克隆)CopyIndices(ctx context.Context,sourceKBID,targetKBIDstring,dimensionint)error}这套接口设计遵循了"依赖倒置"原则,业务逻辑层依赖抽象接口而非具体实现,使得切换向量数据库变得简单。
支持的向量数据库:
| 数据库 | 驱动标识 | 适用场景 | 特点 |
|---|---|---|---|
| PostgreSQL + pgvector | postgres | 中小规模部署 | 轻量级,与业务数据库统一 |
| Elasticsearch 7/8 | elasticsearch_v7/v8 | 大规模生产环境 | 分布式,支持全文检索 |
| Qdrant | qdrant | 专业向量检索场景 | 高性能,丰富的过滤能力 |
WeKnora 实现了三种检索策略的混合使用: