从 0 到 1 搭建企业级多模态 RAG 知识库:一个装修公司的 AI 落地实战
300 人销售团队、15 天岗前培训、知识散落在各个角落------这是一家江西知名装修公司面临的真实困境。本文完整拆解我主导设计的企业级知识库项目,从产品原型到数据库表设计,从多模态文档解析到 GraphRAG 推理链路,把每个技术决策背后的"为什么"讲透。
一、为什么企业知识库是 AI 时代绕不开的"基建"
先看一个具体的场景。
这家装修公司全省有 300 多人的销售团队,学历参差不齐。每个人上岗前都要经历为期 15 天的岗前培训,内容涵盖装修案例、项目手册、客户权益、售后流程等。培训结束后,员工日常工作中还会不断积累新的业务资料、操作经验、问题解决方案和规范流程。
问题出在哪?
- 知识资产零散:文档散落在个人电脑、微信群、邮件附件里,没有统一归档
- 电子化只解决了一半:信息化、云端化让文件"存得下",但没让知识"找得到"
- 传统检索效率极低:手动翻文档,或者关键词检索------搜"客户退单怎么处理",文档里写的是"订单取消流程",关键词对不上,就是搜不到
- 反复问人、反复试错:老员工被问烦,新员工成长慢,15 天培训的成本反复支出
所以这个项目的定位非常清晰:搭建统一的企业知识库,支持语义检索、AI 一键问答,看懂需求就能匹配资料、直接给出解决方案。
它不是锦上添花的功能,而是企业 AI 落地的基础设施。
这里有个关键的产品思维:需求不太清晰时,先用产品原型图把想法"可视化"。
二、产品原型图:把想法变成可沟通的模型
产品原型图是产品的简易可视化模型,用线条、模块展示页面布局、功能与交互逻辑。它的价值在于:提前验证想法、方便团队沟通、及早发现设计缺陷、减少后期返工成本。
常用工具有 Figma、蓝湖、墨刀。值得一提的是,Figma 现在可以结合 MCP(Model Context Protocol),把产品原型图直接转成前端页面,大大缩短从设计到开发的链路。
这个知识库后台管理系统,产品经理画了六张核心图:
图一:整体框架与登录
- 企业共享的知识库后台管理系统
- 登录页
- 顶部 7 个导航,直达文档、问答、知识图谱
图二:首页大盘
这是首页大盘,用可视化一眼看懂全局:
- 折线图盯访问趋势
- 环形图看文档分类占比
- 五大指标配上涨跌箭头
- 底部操作记录,最终谁干了啥一目了然
管理员不用翻数据,开会张口就有数据。核心功能是文档、AI 问答、知识图谱这三块。
这里有个重要的设计原则:文档会做权限管理,只有有权限的文档才可以被检索出来用于生成回答。 这一点后面会展开讲技术实现。
图三:文档管理核心模块
- 左侧:按"我的、公共、部门、归档"分类
- 右侧:列表可搜索、批量上传、新建文件夹
- 每行标注:类型、上传人、解析状态、权限范围
- 两种显示:列表式和卡片式
图四:智能搜索页
输入关键词,非常快的速度检索出搜索结果:
- 关键词高亮
- 按相关度排序
- 每条标出来源、更新时间和可见权限
- 只让搜到有权限的文档,又快又安全
图五:AI 智能问答页
- 左侧:存着历史会话,随时回顾
- 右侧:直接提问,AI 从库里找出答案,流式输出并附带文档引用
- 提供"你可能想要问"主动引导
- 答得快、有出处、还能追问
图六:知识图谱
三、攻克的核心难点:从"单条文档匹配"到 GraphRAG
传统的 RAG 方案是这样的:
javascript
query -> 单条 document 匹配
用 ES/Milvus 做语义/关键词检索,找最相似的文档片段喂给 LLM。但这种方式有些不足:
- 复杂业务问题往往需要跨文档、多跳推理
- 比如"客户在质保期内要求退单,流程怎么走、责任怎么划分"------这需要串联"质保政策""退单流程""责任认定"多个文档
- 单条匹配只能找到"看起来像"的片段,无法构建完整的推理链路
所以项目引入了 GraphRAG :用图数据库(Neo4j)构建知识图谱,通过 LLM 抽取文档实体、关系自动存入图数据库。用户问题会用 LLM 抽取实体、执行多跳检索,把推理链路和 RAG 的结果融合送入 Prompt 上下文,提升复杂业务问题问答的完整性与逻辑性。
四、功能模块拆解
知识库核心功能 = 文档管理 + 问答助手 + 知识图谱。
4.1 文档管理:多模态统一解析
这是整个项目最"重"的部分,也是最能体现工程能力的地方。
文本类文件
支持格式:PDF、DOCX、DOC、XLSX、XLS、PPTX、PPT、TXT、MD、CSV、JSON。
用 langchain/community/document_loaders 就能支持以上格式。同时支持输入网页 URL,系统自动抓取页面正文并导入知识库归档检索。
图片文件(JPG、PNG 等)
上传后做两件事:
- 通过视觉嵌入模型提取图片特征
- 调用大模型 OCR / 图片理解生成图片描述文本
这样就能实现"文字搜图片"和"以图搜图"。
音频文件(MP3、WAV、M4A)
上传自动执行 ASR(Automatic Speech Recognition)语音转文字,将完整转录文本归档,依托文本内容参与检索。
视频文件
用视频理解模型做全维度内容解析:
- 同步提取音频文字
- 提取画面视觉信息
- 整合生成完整文本内容用于检索
- 输出视频多模态向量,实现图文视频跨模态检索
统一解析策略
项目里有一个很聪明的设计:所有格式统一解析为 Markdown 文档。
- 自动提取文档中的图片上传到 MinIO
- 并替换文档中的图片为
.url - 图片基于 OCR 解析、音频基于 ASR、视频基于分片 + 视频理解模型解析成文档
这样做的好处是:下游的检索、问答、图谱抽取都只需要面对一种格式,极大简化了系统复杂度。
4.2 权限管理:检索前筛选
权限管理分两层:
- 功能权限:页面、菜单、按钮三级细粒度权限拦截
- 数据权限:在检索前筛选,用 PSQL 实现
核心逻辑是:依据当前用户角色过滤文档池,不同人员仅查询自身权限范围内的知识资料,实现功能权限与数据权限双重隔离,满足多部门资料分级保密要求。
4.3 问答助手
- 混合检索:Elasticsearch 全文检索 + Milvus 向量语义检索 + 知识图谱
- 流式输出以及源文件引用
- 主动引导用户追问
- 语音输入 TTS
五、技术栈与简历级项目亮点
技术栈
LangChain、LangGraph、DeepAgents、Vercel AI SDK、Nest、Redis、
PostgreSQL、ElasticSearch、Neo4j、MinIO、Docker Compose、
Mem0、LangSmith、LangFuse、WebSocket
项目亮点(8 条)
1. 混合检索 + Reranker 重排
向量 + 关键词(PGVector + ElasticSearch)实现混合检索,用 Reranker 模型重排,实现多路召回,提高检索准确率。
底层理解:向量检索擅长"语义相似",关键词检索擅长"精确匹配"。两路召回后用 RRF(Reciprocal Rank Fusion)融合,再用 Reranker 精排,是当前工业界最稳的 RAG 检索方案。
2. Neo4j 知识图谱 + 多跳推理
利用 Neo4j 构建知识图谱,通过 LLM 抽取文档实体、关系自动存入图数据库。用户问题会用 LLM 抽取实体、执行多跳检索,把推理链路和 RAG 的结果融合送入 Prompt 上下文。
3. 多模态统一解析
支持 PDF、Word、TXT 等图文格式,支持图片、音视频等多媒体文件,统一解析为 Markdown 文档。自动提取图片上传到 MinIO,并替换文档中的图片为 .url。图片基于 OCR 解析、音频基于 ASR、视频基于分片 + 视频理解模型解析成文档。
4. 分层记忆存储
Redis 实现短期记忆存储,Mem0 实现长期记忆分层存储,包括用户级、会话级记忆。
5. 分层权限管控体系
落地页面、菜单、按钮三级细粒度权限拦截;同时联动检索逻辑做数据权限隔离,依据当前用户角色过滤文档池,不同人员仅查询自身权限范围内的知识资料,实现功能权限与数据权限双重隔离。
6. Agentic RAG 架构
基于 LangGraph 实现 Agentic RAG 架构,Agent 自主判别问题复杂度,动态决策调用混合检索、图谱推理等工具,灵活适配多维度复杂业务提问,规避固定检索流程带来的回答局限性。
7. 语音交互
基于 ASR + 流式 TTS 实现语音交互,SSE 实现文字流式输出,WebSocket + 流式 TTS 实现语音的同步流式播放。
8. 全链路观测与评估
本地开发用 LangSmith 调试,线上用 LangFuse 搜集数据,实现全链路观测,记录检索耗时、LLM 调用成本、回答召回来源、模型报错日志等。搭建 RAG 和 Agent 效果量化评估机制,自动跑实验来评估检索效果。
六、数据库设计:PSQL + PGVector 的底层细节
项目涉及多种存储:
- PSQL(带 PGVector 扩展):存储结构化业务数据 + 文档分片向量
- 中间件:ES、Redis、Neo4j 图数据库
所有知识库相关表用 kh_ 前缀(knowledge base)。
6.1 User 表
sql
CREATE TABLE IF NOT EXISTS kh_user {
id BIGINT PRIMARY KEY, -- 用户ID(雪花)
username VARCHAR(50) NOT NULL, -- 登录用户名
password VARCHAR(255) NOT NULL, -- 密码 (bcrypt 哈希)
email VARCHAR(100), -- 邮箱(可选)
email_verified SMALLINT NOT NULL DEFAULT 1, -- 0 未验证 1 已验证
real_name VARCHAR(50), -- 真实姓名(可选)
avatar VARCHAR(500), -- 头像URL(可选)
status SMALLINT NOT NULL DEFAULT 1, -- 0 禁用 1 启用
last_login_at TIMESTAMP, -- 最后登录时间
created_at TIMESTAMP NOT NULL DEFAULT NOW(), -- 创建时间
updated_at TIMESTAMP NOT NULL DEFAULT NOW(), -- 更新时间
deleted BOOLEAN NOT NULL DEFAULT false -- 是否删除 软删除标记
}
CREATE UNIQUE INDEX IF NOT EXISTS uk_kh_user_username ON kh_user(
username) WHERE deleted=false;
代码解析:为什么这么设计?
① ID 用 BIGINT + 雪花算法
INT是 4 字节,最大值约 21 亿BIGINT是 8 字节,最大值约 922 亿
用户量大的系统,INT 很快就用完了。雪花算法生成的是分布式唯一 ID,天然适合分库分表。
② password 用 VARCHAR(255) 存 bcrypt 哈希
bcrypt 哈希固定 60 字符,但留 255 是防御性设计------未来换算法(如 Argon2)不用改表结构。永远不要明文存密码。
③ email_verified 用 SMALLINT 而不是 BOOLEAN
用 SMALLINT 存 0/1,比 BOOLEAN 更灵活,未来可以扩展成 2、3 表示更多状态(比如"验证中""验证失败")。
④ deleted 软删除标记 + 唯一索引的 WHERE 条件
sql
CREATE UNIQUE INDEX ... ON kh_user(username) WHERE deleted=false;
这是部分唯一索引 。意思是:只有 deleted=false 的行才参与唯一性约束。这样用户被软删除后,同一个 username 可以被重新注册,不会因为历史数据冲突。
⑤ created_at / updated_at 默认 NOW()
时间戳由数据库生成,避免应用层时钟不一致的问题。
6.2 角色表:RBAC 模型
RBAC(Role-Based Access Control)基于角色的访问控制,核心是用户 → 角色 → 权限的三层关系。
sql
CREATE TABLE IF NOT EXISTS kh_role (
id BIGINT PRIMARY KEY,
role_name VARCHAR(50) NOT NULL,
role_code VARCHAR(50) NOT NULL UNIQUE,
description VARCHAR(200),
status SMALLINT NOT NULL DEFAULT 1 -- 0 禁用 1 启用
)
CREATE TABLE IF NOT EXISTS kh_user_role (
id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES kh_user(id),
role_id BIGINT NOT NULL REFERENCES kh_role(id),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
UNIQUE (user_id, role_id)
)
CREATE INDEX IF NOT EXISTS idx_kh_user_role_user_id ON kh_user_role(user_id)
代码解析
① 为什么角色表要同时有 role_name 和 role_code?
role_name:给人看的,比如"销售主管"role_code:给程序看的,比如SALES_MANAGER
代码里判断权限用 role_code,不会因为改名而失效。role_code 加 UNIQUE 约束,保证不重复。
② kh_user_role 是典型的中间表
用户和角色是多对多 关系:一个用户可以有多个角色,一个角色可以分配给多个用户。中间表用 UNIQUE (user_id, role_id) 防止重复分配。
③ 外键 REFERENCES + 索引
sql
user_id BIGINT NOT NULL REFERENCES kh_user(id)
外键保证引用完整性------不能给不存在的用户分配角色。
sql
CREATE INDEX ... ON kh_user_role(user_id)
查询"某用户有哪些角色"是最高频的操作,给 user_id 建索引是必须的。注意这里没有给 role_id 单独建索引,因为"某角色下有哪些用户"的查询频率相对低,可以按需再加。
④ 注意笔记里有个笔误
sql
role_id BIGINT NOT NULL REFERENCES hk_role(id),
这里写成了 hk_role,应该是 kh_role。实际建表时要小心这种拼写错误------外键引用错表会在建表时报错。
七、总结:这个项目为什么"能打"
回头看,这个企业级知识库项目的价值在于它同时解决了三个层面的问题:
- 业务层面:把 15 天岗前培训的成本、反复问人的沟通成本,转化为一次性的知识库建设
- 技术层面:多模态统一解析 + 混合检索 + GraphRAG + Agentic RAG,覆盖了当前 RAG 领域最前沿的工程实践
- 工程层面:分层权限、全链路观测、量化评估,让它不是一个 Demo,而是能上生产的系统
如果你正在准备 AI 应用方向的面试,或者要在公司内部落地知识库,这个项目的架构和取舍思路都值得参考。