从零搭建企业私有知识库:RAG + 大模型实战(附完整代码)

简介: 本文详解如何用RAG技术构建企业私有知识库:支持PDF/TXT/DOCX等文档上传、向量化存储与智能问答,让大模型精准理解业务数据,兼顾数据隐私、领域专业性与实时性,附完整代码与部署方案。

本文详细介绍如何使用 RAG(检索增强生成)技术搭建企业私有知识库系统,支持上传文档、智能问答,让大模型"懂"你的业务数据。

一、为什么企业需要私有知识库?

很多企业在引入大模型后,发现了一个尴尬的问题:通用大模型不懂你的业务

比如你问 大模型 "我们公司去年的营收是多少",它肯定答不上来。这是因为:

  1. 数据隐私:企业核心数据不能上传到第三方 API
  2. 领域知识:通用模型缺乏垂直行业的专业知识
  3. 实时性:无法回答关于你最新产品、政策的实时问题

RAG(Retrieval-Augmented Generation) 正是解决这个问题的最佳方案。
参考阿里云知识库官网文档:https://help.aliyun.com/zh/model-studio/rag-knowledge-base
image.png

二、RAG 是什么?

RAG = 检索(Retrieval) + 增强生成(Augmented Generation)

核心流程:

用户问题 → 检索相关文档 → 将文档作为上下文 → 大模型生成答案

简单来说,就是先把你的文档"喂"给向量数据库,用户提问时先检索相关文档,再让大模型基于这些文档回答。

三、实战:搭建私有知识库问答系统

3.1 技术架构

┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│  文档上传   │ ──▶ │  文本分块    │ ──▶ │  向量嵌入   │
└─────────────┘     └──────────────┘     └─────────────┘
                                              │
                                              ▼
┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│  用户提问   │ ──▶ │  检索相关文档 │ ◀── │  向量数据库 │
└─────────────┘     └──────────────┘     └─────────────┘
                           │
                           ▼
                    ┌──────────────┐
                    │  大模型生成  │
                    └──────────────┘

3.2 环境准备

# Python 3.10+
pip install langchain openai chromadb pypdf python-dotenv streamlit

3.3 完整代码实现

"""
企业私有知识库问答系统
支持 PDF、TXT、DOCX 文档,自动向量化存储
"""

import os
from dotenv import load_dotenv
from langchain.document_loaders import PyPDFLoader, TextLoader, UnstructuredWordDocumentLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA

# 加载环境变量
load_dotenv()

class PrivateKnowledgeBase:
    def __init__(self, persist_directory="./chroma_db"):
        self.persist_directory = persist_directory
        self.embeddings = OpenAIEmbeddings()
        self.vectordb = None
        self.qa_chain = None

        # 初始化 LLM
        self.llm = ChatOpenAI(
            model="gpt-4",
            temperature=0.3,  # 降低随机性,提高准确性
            max_tokens=1000
        )

    def load_documents(self, folder_path):
        """加载文件夹中的所有文档"""
        documents = []

        for root, dirs, files in os.walk(folder_path):
            for file in files:
                file_path = os.path.join(root, file)
                try:
                    if file.endswith('.pdf'):
                        loader = PyPDFLoader(file_path)
                    elif file.endswith('.txt'):
                        loader = TextLoader(file_path)
                    elif file.endswith(('.docx', '.doc')):
                        loader = UnstructuredWordDocumentLoader(file_path)
                    else:
                        continue

                    documents.extend(loader.load())
                    print(f"✅ 已加载: {file}")
                except Exception as e:
                    print(f"❌ 加载失败 {file}: {e}")

        return documents

    def split_documents(self, documents, chunk_size=500, chunk_overlap=50):
        """将文档分割成小块"""
        text_splitter = RecursiveCharacterTextSplitter(
            chunk_size=chunk_size,
            chunk_overlap=chunk_overlap,
            length_function=len
        )
        return text_splitter.split_documents(documents)

    def build_vectorstore(self, chunks):
        """构建向量数据库"""
        print("🔄 正在生成向量嵌入...")
        self.vectordb = Chroma.from_documents(
            documents=chunks,
            embedding=self.embeddings,
            persist_directory=self.persist_directory
        )
        self.vectordb.persist()
        print(f"✅ 向量数据库已保存到: {self.persist_directory}")
        return self.vectordb

    def load_vectorstore(self):
        """加载已有的向量数据库"""
        if os.path.exists(self.persist_directory):
            self.vectordb = Chroma(
                persist_directory=self.persist_directory,
                embedding_function=self.embeddings
            )
            print("✅ 向量数据库加载成功")
            return True
        return False

    def setup_qa_chain(self, top_k=4):
        """设置问答链"""
        if not self.vectordb:
            raise ValueError("请先构建或加载向量数据库")

        retriever = self.vectordb.as_retriever(
            search_kwargs={
   "k": top_k}  # 检索最相关的 4 个文档块
        )

        self.qa_chain = RetrievalQA.from_chain_type(
            llm=self.llm,
            chain_type="stuff",  # 将检索到的文档"塞进"上下文
            retriever=retriever,
            return_source_documents=True
        )
        print("✅ 问答系统已就绪")

    def ask(self, question):
        """向知识库提问"""
        if not self.qa_chain:
            raise ValueError("请先设置问答链")

        result = self.qa_chain({
   "query": question})

        return {
   
            "answer": result["result"],
            "sources": [doc.page_content[:200] + "..." for doc in result["source_documents"]]
        }


# ==================== 使用示例 ====================

if __name__ == "__main__":
    # 初始化知识库
    kb = PrivateKnowledgeBase(persist_directory="./company_knowledge")

    # 方式一:从文档构建(首次使用)
    print("\n📂 开始构建知识库...")
    docs = kb.load_documents("./documents")  # 放入你的文档目录
    chunks = kb.split_documents(docs)
    kb.build_vectorstore(chunks)
    kb.setup_qa_chain()

    # 方式二:直接加载已有知识库
    # kb.load_vectorstore()
    # kb.setup_qa_chain()

    # 开始问答
    print("\n💬 知识库问答系统已启动,输入 'exit' 退出\n")

    while True:
        question = input("请输入问题: ")
        if question.lower() == "exit":
            break

        result = kb.ask(question)
        print(f"\n📖 回答:\n{result['answer']}\n")
        print(f"📌 参考来源 ({len(result['sources'])} 条):")
        for i, src in enumerate(result['sources'], 1):
            print(f"  {i}. {src}\n")

3.4 添加更多数据源

除了本地文档,还可以接入:

# 接入网站内容
from langchain.document_loaders import UnstructuredURLLoader

urls = ["https://your-company.com/about.html"]
loader = UnstructuredURLLoader(urls=urls)
web_docs = loader.load()

# 接入 Notion
from langchain.document_loaders import NotionLoader

loader = NotionLoader(notion_url="https://notion.so/...")
notion_docs = loader.load()

四、使用国产大模型(节省成本)

如果觉得 OpenAI API 太贵,可以用国内模型替代:

from langchain.chat_models import Tongyi

# 阿里通义千问
llm = Tongyi(temperature=0.3)

# 或者使用本地部署的 Ollama
from langchain.llms import Ollama
llm = Ollama(model="llama3")

五、效果优化技巧

5.1 文档分块策略

# 针对不同类型内容使用不同策略

# 技术文档:较小分块,保持代码完整性
tech_splitter = RecursiveCharacterTextSplitter(
    chunk_size=300,
    separators=["\n\n", "\n", "```\n", "```", " "]
)

# 政策文档:较大分块,保持段落完整
policy_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    separators=["\n\n\n", "\n\n", "\n", "。", "!", "?"]
)

5.2 混合检索

# 结合关键词搜索和向量搜索
from langchain.retrievers import EnsembleRetriever

# 向量检索
vector_retriever = vectordb.as_retriever(search_kwargs={
   "k": 5})

# 关键词检索
bm25_retriever = BM25Retriever.from_documents(chunks)

# 混合检索
ensemble_retriever = EnsembleRetriever(
    retrievers=[vector_retriever, bm25_retriever],
    weights=[0.7, 0.3]
)

5.3 重排序(Rerank)

使用 Coherence Rerank 可以进一步提升检索质量:

from cohere import Client as CohereClient

cohere_client = CohereClient()

def rerank_documents(query, documents, top_n=3):
    results = cohere_client.rerank(
        query=query,
        documents=documents,
        top_n=top_n
    )
    return [results[i].document for i in range(len(results))]

六、部署上线

6.1 使用 Streamlit 快速搭建界面

import streamlit as st

st.title("🏢 企业私有知识库")

if "qa_chain" not in st.session_state:
    st.session_state.kb = PrivateKnowledgeBase()
    if st.session_state.kb.load_vectorstore():
        st.session_state.kb.setup_qa_chain()

question = st.text_input("请输入您的问题:")

if question:
    with st.spinner("正在思考..."):
        result = st.session_state.kb.ask(question)
    st.success(result["answer"])

    with st.expander("查看参考来源"):
        for i, src in enumerate(result["sources"], 1):
            st.text(f"{i}. {src}")

6.2 一键启动

streamlit run app.py --server.port 8501

现在你可以通过浏览器访问 http://localhost:8501 使用知识库了。

七、常见问题

Q: 检索不到相关内容?

  • 检查文档是否正确加载
  • 尝试调整 chunk_size(太小或太大都不行)
  • 增加检索数量 top_k

Q: 回答不准确?

  • 在 prompt 中添加角色设定:"你是一个专业的XXX顾问..."
  • 降低 temperature 参数
  • 检查参考文档的相关性

Q: 响应太慢?

  • 使用流式输出 stream=True
  • 考虑使用本地部署的 Embedding 模型
  • 启用缓存机制

总结

通过本文,你学会了:

  1. ✅ RAG 的基本原理
  2. ✅ 使用 LangChain + Chroma 构建向量知识库
  3. ✅ 实现文档问答系统
  4. ✅ 优化检索和生成效果
  5. ✅ 快速部署上线
相关文章
|
11天前
|
人工智能 自然语言处理 前端开发
从传统RAG到AgentRAG:Java企业AI应用的范式升
AgentRAG是向量空间AI实验室提出的新型智能体范式,融合ReAct推理、企业知识库与Java系统Skill工具集,突破传统RAG单轮问答局限,实现意图理解、任务规划、多轮执行与系统协同,助力企业AI从“被动应答”迈向“主动办事”。
114 0
|
11天前
|
存储 自然语言处理 算法
大模型应用:基于千问大模型 + 图算法:可追溯知识图谱问答系统构建.83
本文介绍“图算法+大模型”双引擎智能问答方案:用PageRank、最短路径等图算法处理关系推理与知识验证,由千问大模型负责自然语言理解与生成,实现可信、可溯源、强推理的高可靠问答,破解幻觉、推理弱、不可溯三大难题。
214 7
|
11天前
|
人工智能 Java API
【SpringAIAlibaba新手村系列】(17)百炼 RAG 知识库应用
本章基于 Spring AI Alibaba 落地百炼 RAG,完成 DashScopeApi、ChatModel、ChatClient 配置,并通过检索器与 DocumentRetrievalAdvisor 组装检索增强问答链路,实现可运行的知识库问答接口。
226 1
|
11天前
|
人工智能 JSON Java
Spring AI 整合火山引擎豆包向量库:我踩过的 10 个致命坑与终极解决方案
本文详述Spring AI 1.1.2整合火山引擎豆包向量模型的实战踩坑全过程,涵盖10大典型问题(如404、空指针、API Key中文、模型ID混淆等),提供根因分析与可直接复用的解决方案,并附完整多模态向量化、内存向量库及问答系统代码。
371 1
|
2月前
|
存储 人工智能 API
给大模型配个“外接硬盘”!RAG架构全解析:企业级知识库搭建的终极指南
AI博主详解RAG技术:为大模型“接外挂”,破解幻觉难题。拆解T5-RAG、FiD、RAR三大流派原理与实战,手把手教搭专属知识库助手,附低代码落地方案。(239字)
232 1
|
5天前
|
缓存 人工智能 自然语言处理
我对比了8个Claude API中转站,踩了不少坑,总结给你
本文是个人开发者耗时1周实测的8大Claude中转平台横向评测,聚焦Claude Code真实体验:以加权均价(¥/M token)、内部汇率、缓存支持、模型真实性及稳定性为核心指标。
2157 11
|
人工智能 JavaScript Java
【SpringAIAlibaba新手村系列】(1)初识 Spring AI Alibaba 框架
本文介绍了SpringAIAlibaba框架的基本概念和使用方法。作为Spring官方AI框架的阿里云实现版本,它简化了Java开发者调用AI模型的过程。文章详细讲解了核心概念如ChatModel、ChatClient,以及阿里云百炼平台的功能。通过HelloWorld项目示例,展示了如何配置APIKey、编写控制层代码,实现普通调用和流式输出两种AI交互方式。重点阐述了SpringAI与SpringAIAlibaba的关系,以及自动配置机制的工作原理,帮助开发者快速上手这一框架。
1900 4
|
2月前
|
数据采集 存储 自然语言处理
向量数据库实战——零基础搭建专属RAG知识库
本文手把手教你零代码搭建向量数据库,构建个人大模型知识库:5步完成数据清洗、入库、检索配置与测试,无需编程/本地GPU,10分钟上手RAG核心环节,解决大模型“记不住专属知识”难题。(239字)
|
10天前
|
人工智能 弹性计算 安全
Hermes Agent是什么?怎么部署?超详细实操教程
Hermes Agent 是 Nous Research 于2026年2月开源的自进化AI智能体,支持跨会话持久记忆、自动提炼可复用技能、多平台接入与200+模型切换,真正实现“越用越懂你”。MIT协议,部署灵活,隐私可控。
2294 5

热门文章

最新文章

下一篇
开通oss服务