ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

企业知识库RAG实战:基于腾讯云向量数据库的检索增强生成方案

2026/10/8 11:09:05 拓冰建站 浏览量
企业知识库RAG实战:基于腾讯云向量数据库的检索增强生成方案 1. 为什么企业知识库需要 RAG而不是直接微调大模型很多团队一上来就问我们想把公司几百份产品文档、售后工单、内部规范喂给大模型是不是直接微调一个专属模型就行了我踩过这个坑也见过不少同行在这条路上浪费了两三周时间最后发现效果还不如老老实实做检索增强生成RAG。这里先把结论摆出来对于企业知识库这种内容持续更新、要求答案可溯源、预算有限的场景RAG 是性价比最高、落地最快的方案微调只适合解决说话风格和固定格式输出的问题不适合承载知识本身。1.1 微调和 RAG 到底在解决什么问题要理解这个选择得先搞清楚两者的本质区别。微调Fine-tuning是把知识烧进模型参数里相当于让模型重新上一次学把新知识变成它的肌肉记忆。而 RAG 是把知识放在外部数据库里模型每次回答前先去查资料再基于查到的资料组织语言。这两条路的差异落到企业实际场景里就非常明显了对比维度微调方案RAG 方案知识更新每次更新都要重新训练成本高、周期长改数据库即可分钟级生效答案溯源无法给出出处出了错很难查可返回原文片段和来源文档幻觉控制知识记错时照样一本正经胡说检索不到就明确说不知道初始成本需要标注数据、GPU 算力主要是文档处理和向量化适合场景固定话术、风格迁移、格式约束知识问答、文档检索、客服助手我自己的经验是企业知识库最大的痛点是内容一直在变——产品文档每周更新售后政策每季度调整如果走微调路线你等于给自己挖了个无底洞。而 RAG 的核心优势就是知识库和模型解耦文档变了只更新向量库模型完全不用动。1.2 RAG 的完整链路拆成四步就懂了很多人觉得 RAG 很玄乎其实拆开看就四个环节我用一个生活化的类比帮你记住把 RAG 想象成一个图书馆管理员。文档切分Chunking把厚厚一本书拆成一页页卡片方便快速翻阅。对应到技术里就是把长文档切成一段段文本块。向量化Embedding给每张卡片贴上语义标签让意思相近的卡片能被归到一起。这一步用嵌入模型把文本转成高维向量。检索Retrieval用户提问时管理员根据问题去卡片堆里找出最相关的几张。这一步在向量数据库里做相似度搜索。生成Generation管理员把找到的卡片递给大模型让它基于这些内容组织成一段通顺的回答。整个链路里向量数据库是承上启下的关键。它决定了检索快不快、准不准、能不能扛住企业级的数据量。这也是为什么我这次选腾讯云向量数据库来落地——它把部署、扩缩容、索引优化这些脏活累活都包了我们只需要专注在文档处理和检索策略上。1.3 什么样的企业场景适合这套方案不是所有场景都值得上 RAG。根据我做过几个项目的经验下面这几类需求最适合内部知识问答员工问年假怎么算报销流程是什么系统从制度文档里检索并回答。智能客服客户问产品参数、售后政策系统从产品手册和工单库里找答案。技术文档助手开发者问 API 怎么调、报错怎么解系统从技术文档里检索。合同/法规检索法务问某条款怎么规定系统从合同库里定位原文。反过来说如果你的需求是让模型学会某种特定的说话风格或者输出固定格式的 JSON那微调更合适。判断标准很简单知识是查得到还是学得会。查得到的用 RAG学得会的用微调。2. 动手前的环境准备与腾讯云向量数据库开通环境准备这一步看着简单但我见过太多人卡在依赖版本冲突、SDK 装不上、密钥配错这些低级问题上。这一章我把踩过的坑都摊开讲你照着做能省下至少半天时间。2.1 Python 环境与依赖清单先说 Python 版本。腾讯云向量数据库的 Python SDK 对版本有要求我实测下来Python 3.8 到 3.11 都能跑但推荐 3.10因为它在兼容性和性能之间平衡得最好。如果你还在用 3.7 或者更早的版本建议先升级否则某些依赖会装不上。安装依赖的时候我建议用虚拟环境隔离别直接往全局环境里装。命令如下# 创建虚拟环境 python -m venv rag_env # 激活Linux/Mac source rag_env/bin/activate # 激活Windows rag_env\Scripts\activate # 安装核心依赖 pip install tcvectordb pip install langchain pip install langchain-community pip install sentence-transformers pip install pypdf pip install python-dotenv这里有几个坑要提醒tcvectordb 是腾讯云向量数据库的官方 SDK别装成别的同名包。sentence-transformers 会连带装 torch如果你机器上没有 GPU装的是 CPU 版本下载量比较大耐心等。如果你用 Mac M 系列芯片torch 的安装可能会慢建议提前配好国内镜像源。提示依赖装完后先跑一句python -c import tcvectordb; print(tcvectordb.__version__)验证一下能打印出版本号就说明装好了。2.2 开通腾讯云向量数据库并拿到连接信息登录腾讯云控制台搜索向量数据库进入后创建一个实例。创建时几个关键参数我解释一下为什么这么选地域选离你应用服务器最近的地域能显著降低网络延迟。如果你的应用部署在广州数据库就选广州。规格测试阶段选最小规格就够1 核 2G 能撑住几万条向量。生产环境根据数据量估算一般 10 万条文档块选 2 核 4G 起步。副本数测试选 1 副本生产建议 2 副本以上保证高可用。创建完成后在实例详情页能拿到三个关键信息访问地址Endpoint、用户名、API 密钥。这三个东西千万别硬编码在代码里用.env文件管理# .env 文件 TCVDB_URLhttp://your-instance-endpoint:port TCVDB_USERNAMEroot TCVDB_API_KEYyour-api-key-here然后在代码里用python-dotenv读取import os from dotenv import load_dotenv load_dotenv() url os.getenv(TCVDB_URL) username os.getenv(TCVDB_USERNAME) api_key os.getenv(TCVDB_API_KEY)注意API 密钥泄露等于把数据库大门敞开一定要走环境变量并且把.env加进.gitignore。我见过有人把密钥提交到公开仓库结果被扫到后数据库被清空这个教训太惨痛了。2.3 嵌入模型的选择本地跑还是调 API向量化的质量直接决定检索效果所以嵌入模型的选择很关键。有两条路路线一本地部署嵌入模型。用sentence-transformers加载开源模型比如BAAI/bge-large-zh-v1.5中文效果很好而且完全免费、数据不出内网。缺点是首次加载慢且需要一定的内存。路线二调用云端嵌入 API。腾讯云、各家大模型厂商都提供嵌入接口优点是省事、效果好缺点是要花钱且数据要出网。我的建议是如果数据敏感走本地模型如果追求效果和省事走云端 API。本文为了演示完整链路用本地模型代码里换成 API 调用也很简单。from sentence_transformers import SentenceTransformer # 加载中文嵌入模型 model SentenceTransformer(BAAI/bge-large-zh-v1.5) # 测试一下 texts [企业知识库怎么搭建, RAG 检索增强生成] embeddings model.encode(texts) print(embeddings.shape) # 输出 (2, 1024)注意bge-large-zh-v1.5输出的是 1024 维向量这个维度要和你后面建集合时指定的维度一致否则会报错。这是新手最容易踩的坑之一。3. 从零构建知识库文档处理与向量入库全流程这一章是整篇的核心我会把文档切分、向量化、入库这条链路完整走一遍每一步都解释清楚为什么这么做以及我踩过的坑。3.1 文档加载与清洗脏数据是检索不准的元凶企业文档的来源五花八门PDF、Word、Markdown、网页、数据库导出。第一步是把它们统一加载成纯文本。用 LangChain 的文档加载器能省不少事from langchain_community.document_loaders import PyPDFLoader, TextLoader from langchain_community.document_loaders import UnstructuredMarkdownLoader def load_documents(file_path): if file_path.endswith(.pdf): loader PyPDFLoader(file_path) elif file_path.endswith(.md): loader UnstructuredMarkdownLoader(file_path) elif file_path.endswith(.txt): loader TextLoader(file_path, encodingutf-8) else: raise ValueError(f不支持的文件类型: {file_path}) return loader.load()加载完之后千万别直接切分先做清洗。我见过太多检索效果差的案例根源就是文档里混着页眉页脚、乱码、重复的导航栏文字。清洗要做这几件事去掉连续的空行和多余空格去掉 PDF 转换产生的乱码字符去掉页眉页脚这类重复内容统一全角半角标点import re def clean_text(text): # 去掉多余空白 text re.sub(r\s, , text) # 去掉常见乱码 text re.sub(r[\x00-\x08\x0b-\x0c\x0e-\x1f], , text) # 去掉页码类内容 text re.sub(r第\s*\d\s*页, , text) return text.strip()提示清洗规则要根据你的文档实际情况调整。建议先拿几份典型文档跑一遍人工看看清洗后的效果别一股脑全量处理完才发现问题。3.2 文本切分策略块大小和重叠度怎么定切分是 RAG 里最讲究技巧的一步。切太大检索出来的内容太杂模型抓不住重点切太小语义被割裂检索出来的片段不完整。我的经验参数是块大小chunk_size中文场景建议 300 到 500 字。英文可以到 500 到 800 词。重叠度chunk_overlap设为块大小的 10% 到 20%保证跨块的语义连贯。from langchain.text_splitter import RecursiveCharacterTextSplitter splitter RecursiveCharacterTextSplitter( chunk_size400, chunk_overlap80, separators[\n\n, \n, 。, , , , , , ] ) chunks splitter.split_documents(documents) print(f切分后共 {len(chunks)} 个文本块)这里separators的顺序很关键。它会优先按段落切段落太长再按句子切最后才按字符切。中文一定要把句号、问号这些标点加进去否则会切出半句话。我踩过的一个坑表格和代码块被切碎。如果你的文档里有大量表格建议先把表格单独提取出来转成字段值的文本形式再切分否则检索出来的表格片段根本没法用。3.3 向量化与批量入库性能优化的关键点切分完成后就要把每个文本块转成向量并写入腾讯云向量数据库。先创建集合Collectionfrom tcvectordb import VectorDBClient from tcvectordb.model.collection import Collection from tcvectordb.model.index import Index, FilterIndex, VectorIndex from tcvectordb.model.enum import FieldType, IndexType, MetricType client VectorDBClient(urlurl, usernameusername, keyapi_key) # 定义索引结构 index Index( FilterIndex(nameid, field_typeFieldType.String, index_typeIndexType.PRIMARY_KEY), FilterIndex(nametext, field_typeFieldType.String, index_typeIndexType.FILTER), FilterIndex(namesource, field_typeFieldType.String, index_typeIndexType.FILTER), VectorIndex(namevector, dimension1024, index_typeIndexType.HNSW, metric_typeMetricType.COSINE) ) # 创建集合 db client.create_database(rag_kb) collection db.create_collection(namedocs, shard1, replicas1, indexindex)几个参数解释一下dimension1024必须和嵌入模型输出维度一致bge-large-zh-v1.5就是 1024。index_typeHNSW这是目前主流的近似最近邻索引检索快、召回率高。数据量小的时候也可以用 FLAT精度更高但慢。metric_typeCOSINE余弦相似度适合文本向量。也可以用内积IP或欧氏距离L2。入库的时候一定要批量写别一条条写。我实测过单条写入 1000 个块要几分钟批量写入只要几秒。腾讯云 SDK 支持批量 upsertfrom tcvectordb.model.document import Document def batch_insert(collection, chunks, model, batch_size100): for i in range(0, len(chunks), batch_size): batch chunks[i:ibatch_size] texts [c.page_content for c in batch] vectors model.encode(texts).tolist() docs [] for j, chunk in enumerate(batch): docs.append(Document( idfdoc_{ij}, textchunk.page_content, sourcechunk.metadata.get(source, unknown), vectorvectors[j] )) collection.upsert(documentsdocs) print(f已写入 {ilen(batch)} / {len(chunks)})注意批量大小别设太大100 到 200 比较稳妥。设太大容易触发请求体超限反而报错。4. 检索与生成让大模型答得准、答得稳数据入库只是上半场真正决定用户体验的是检索和生成这两个环节。这一章我讲讲怎么把检索做准以及怎么让大模型基于检索结果稳定输出。4.1 相似度检索的三种策略对比最基础的检索就是拿用户问题去向量库里找最相似的 Top-K 个块。但实际用下来纯向量检索有几个明显短板对专有名词不敏感比如产品型号X200-Pro向量检索可能找不准。对精确匹配无能为力用户问某个具体编号向量检索不如关键词匹配。Top-K 难定K 太小漏信息K 太大引入噪声。所以我一般用混合检索向量检索 关键词检索两路结果融合。腾讯云向量数据库支持标量过滤可以配合关键词做粗筛def search(collection, query, model, top_k5): query_vector model.encode([query])[0].tolist() results collection.search( vectors[query_vector], limittop_k, params{ef: 128} # HNSW 的搜索参数越大越准但越慢 ) return resultsef这个参数值得说一下。它是 HNSW 索引的搜索广度值越大召回率越高但检索越慢。测试阶段可以设 128 到 256生产环境根据延迟要求调。还有一种进阶策略叫重排序Rerank先用向量检索召回 Top-20再用一个专门的重排序模型精排出 Top-5。这样能显著提升相关性。开源的重排序模型有BAAI/bge-reranker-large效果不错。4.2 提示词模板把检索结果喂给大模型的正确姿势检索到相关片段后要把它们和用户问题一起组装成提示词。这里有个关键原则明确告诉模型只基于给定资料回答资料里没有就说不知道。否则模型会自由发挥产生幻觉。PROMPT_TEMPLATE 你是一个企业知识库助手。请严格基于下面提供的资料回答用户问题。 要求 1. 只使用资料中的信息不要编造。 2. 如果资料中没有相关信息直接回答根据现有资料无法回答该问题。 3. 回答要简洁准确必要时引用资料原文。 资料 {context} 用户问题{question} 回答 def build_prompt(query, search_results): context \n\n.join([r[text] for r in search_results]) return PROMPT_TEMPLATE.format(contextcontext, questionquery)这个模板我调过很多版最后发现把不要编造和无法回答这两条写死最有效。很多团队只写请基于资料回答结果模型还是会脑补加上明确的兜底话术后幻觉率明显下降。4.3 调用大模型生成答案并附上引用来源生成环节可以接各家大模型的 API。为了演示我用一个通用的调用方式import requests def generate_answer(prompt, api_key, api_url): headers { Authorization: fBearer {api_key}, Content-Type: application/json } payload { model: your-model-name, messages: [{role: user, content: prompt}], temperature: 0.1 # 知识问答场景温度调低减少随机性 } response requests.post(api_url, headersheaders, jsonpayload) return response.json()[choices][0][message][content]temperature设 0.1 是有讲究的。知识问答要的是稳定、准确不是创意温度越低输出越确定。如果你设成 0.8同一个问题每次答案都不一样用户会觉得系统不靠谱。生成完答案后一定要把引用来源一起返回。这是 RAG 相比微调最大的优势之一def answer_with_citation(query, collection, model, llm_api_key, llm_api_url): results search(collection, query, model, top_k5) prompt build_prompt(query, results) answer generate_answer(prompt, llm_api_key, llm_api_url) sources list(set([r[source] for r in results])) return { answer: answer, sources: sources }用户看到答案下面标着来源产品手册 v2.3.pdf信任度会高很多也方便他们自己去核对原文。5. 上线后才发现的问题检索质量调优与常见坑系统跑通只是第一步真正上线后你会发现一堆问题。这一章我把自己和同行踩过的坑整理出来都是血泪教训。5.1 检索不准的排查链路当用户反馈答非所问时别急着换模型按这个顺序排查第一步看检索结果本身对不对。把用户问题和检索出的 Top-5 块打印出来人工判断相关性。如果检索结果就不对那问题在检索环节跟大模型无关。第二步检查切分是否合理。如果检索出的块是半句话或者跨了多个主题说明切分有问题。调整 chunk_size 和 separators。第三步检查嵌入模型是否匹配。中文场景用英文模型效果肯定差。确认你用的是中文优化的模型。第四步检查是否有脏数据干扰。如果知识库里混着大量无关文档会稀释检索效果。考虑加元数据过滤只检索相关来源。我遇到过一个典型案例用户问退款政策检索出来的全是退货政策。原因是这两个词向量很接近但业务上是两回事。解决办法是在切分时把标题一起带上让每个块都包含所属章节的标题信息检索时就能区分开。5.2 大模型答非所问的三种典型情况检索对了但模型还是答不好通常是这三种情况现象原因解决办法答案太笼统检索块太大信息不聚焦减小 chunk_size提高检索精度答案不完整Top-K 太小漏了关键信息增大 Top-K或加重排序答案自相矛盾检索到冲突信息加时间过滤只取最新版本还有一种情况是模型不遵守提示词明明资料里没有它还是硬答。这时候可以加一个置信度判断步骤先让模型判断资料是否足够回答问题不够就直接返回兜底话术。5.3 性能与成本的平衡技巧企业知识库上线后性能和成本是两个绕不开的话题。几个实用技巧缓存高频问题把常见问题的答案缓存起来命中缓存直接返回省下检索和生成的开销。异步处理文档入库是 IO 密集型任务用异步并发能大幅提速。分级检索先用便宜的向量检索粗筛只对 Top 结果做重排序避免全量重排。控制上下文长度喂给大模型的资料别太多一般 3 到 5 个块就够多了反而干扰且费钱。提示腾讯云向量数据库的计费跟存储量和计算规格相关测试阶段用最小规格上线前根据实际 QPS 和数据量做压测再决定规格别一上来就买大的。6. 关于 RAG 和知识图谱结合的一些实践思考最近RAG 瓶颈和KG 知识库这两个词很热很多人在讨论 RAG 和知识图谱Knowledge Graph怎么结合。我在项目里也做过一些尝试分享几点真实体会。纯 RAG 的瓶颈主要在两个地方一是多跳推理能力弱比如问A 产品的负责人所在的部门今年的预算是多少这种需要跨多个文档推理的问题纯向量检索很难搞定二是关系型问题处理差问哪些产品和 X 属于同一系列向量检索只能找到语义相似的找不到结构化关系。知识图谱的优势正好补上这两块它把实体和关系显式建模支持多跳查询和关系推理。所以现在比较流行的做法是GraphRAG用知识图谱做实体关系检索用向量库做语义检索两者融合。不过我要泼盆冷水知识图谱的构建成本很高需要实体抽取、关系抽取、图谱维护对数据质量要求也高。如果你的场景只是简单的文档问答纯 RAG 完全够用别为了追热点硬上知识图谱。判断标准是你的问题需不需要跨文档推理和关系查询需要才上图谱不需要就别折腾。如果确实要上一个务实的路径是先用纯 RAG 跑起来收集用户真实问题分析哪些问题是纯 RAG 答不好的再针对性地补知识图谱。这样投入产出比最高也不会一上来就被复杂的图谱工程劝退。7. 我在实际落地中总结的几条经验最后分享几条踩坑踩出来的经验都是文档里不会写、但实际项目里特别管用的。第一先小范围验证再全量铺开。别一上来就把公司所有文档都灌进去。先挑一个部门、一类文档做试点跑通链路、调好参数再逐步扩展。我见过团队一次性灌了几十万文档结果检索效果一塌糊涂排查起来无从下手。第二建立评估集。准备 50 到 100 个真实问题和标准答案每次调整参数后跑一遍评估集看准确率变化。没有评估集你调参就是盲人摸象改好改坏全凭感觉。第三日志要记全。用户问了什么、检索到什么、模型答了什么全都要记下来。这些日志是你后续优化的金矿能帮你发现检索盲区和模型幻觉的高发场景。第四别迷信参数多信数据。chunk_size 到底设 300 还是 500Top-K 设 3 还是 5没有标准答案取决于你的文档特点和用户问题分布。用评估集测出来的结果才是真的。第五给用户一个反馈入口。答案旁边放个有用/没用的按钮收集用户反馈。这些真实反馈比任何离线评估都值钱能帮你快速定位问题。这套基于腾讯云向量数据库的 RAG 方案我从环境搭建到上线调优完整走过一遍整体下来最大的感受是RAG 的门槛不在技术而在数据治理和检索调优。把文档清洗干净、切分合理、检索策略调好效果自然就上来了。工具和框架都是现成的真正花时间的是那些琐碎但关键的细节。