第40集:【实战】搭建一个基于企业知识库的24小时文档问答智能体

章节标题

企业知识库智能体实战指南

核心知识点讲解

企业知识库智能体的架构

一个完整的企业知识库智能体通常包含以下组件:

  1. 文档处理模块:负责文档的加载、分割和预处理
  2. 向量存储模块:负责文档嵌入和向量存储
  3. 检索模块:负责根据用户查询检索相关文档
  4. 生成模块:负责根据检索结果生成回答
  5. 记忆模块:负责管理对话历史和用户偏好
  6. 部署模块:负责智能体的部署和监控

技术选型考虑因素

  1. 文档类型:不同类型的文档(PDF、Word、Excel、Markdown等)需要不同的处理方式
  2. 数据量:数据量大小会影响向量存储的选择
  3. 响应速度:实时性要求会影响架构设计
  4. 准确性:对回答准确性的要求会影响检索策略
  5. 可扩展性:未来数据增长和功能扩展的需求

企业知识库智能体的优势

  1. 24小时服务:全天候响应用户查询,无需人工干预
  2. 一致性:提供一致的信息和回答,避免人为错误
  3. 效率提升:快速检索和处理大量文档,提高信息获取效率
  4. 知识沉淀:将企业知识数字化、结构化,防止知识流失
  5. 成本降低:减少人工客服和知识管理的成本

实用案例分析

案例:企业内部知识库问答系统

场景:某大型企业拥有大量的内部文档,包括员工手册、产品文档、技术文档等,员工经常需要查询这些文档获取信息。

挑战

  • 文档数量庞大,检索困难
  • 文档更新频繁,难以保持知识的时效性
  • 员工查询效率低下,影响工作效率
  • 新员工培训成本高,熟悉企业知识需要时间

解决方案:搭建一个基于企业知识库的智能体,实现自动化的文档问答服务。

预期效果

  • 员工可以通过自然语言查询获取准确的文档信息
  • 智能体能够理解上下文,提供连贯的问答体验
  • 系统能够自动更新知识库,保持信息的时效性
  • 降低新员工培训成本,加快知识获取速度

代码示例

示例1:完整的企业知识库智能体实现

from langchain.document_loaders import PyPDFLoader, DocxLoader, TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
from langchain.memory import ConversationBufferMemory
from langchain.prompts import PromptTemplate
from langchain.chains import ConversationalRetrievalChain
import os
import glob

# 配置
DATA_DIR = "enterprise_knowledge_base"
VECTORSTORE_DIR = "./vectorstore"
EMBEDDING_MODEL = "text-embedding-ada-002"
LLM_MODEL = "gpt-3.5-turbo"

# 1. 文档加载与处理
def load_documents(data_dir):
    """加载目录中的所有文档"""
    documents = []
    
    # 加载PDF文件
    for pdf_file in glob.glob(os.path.join(data_dir, "*.pdf")):
        print(f"加载PDF文件: {pdf_file}")
        loader = PyPDFLoader(pdf_file)
        documents.extend(loader.load())
    
    # 加载Word文件
    for docx_file in glob.glob(os.path.join(data_dir, "*.docx")):
        print(f"加载Word文件: {docx_file}")
        loader = DocxLoader(docx_file)
        documents.extend(loader.load())
    
    # 加载文本文件
    for txt_file in glob.glob(os.path.join(data_dir, "*.txt")):
        print(f"加载文本文件: {txt_file}")
        loader = TextLoader(txt_file)
        documents.extend(loader.load())
    
    # 加载Markdown文件
    for md_file in glob.glob(os.path.join(data_dir, "*.md")):
        print(f"加载Markdown文件: {md_file}")
        loader = TextLoader(md_file)
        documents.extend(loader.load())
    
    print(f"共加载 {len(documents)} 个文档")
    return documents

# 2. 文档分割
def split_documents(documents):
    """分割文档为小块"""
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=1000,
        chunk_overlap=200,
        length_function=len
    )
    
    splits = text_splitter.split_documents(documents)
    print(f"文档分割为 {len(splits)} 个小块")
    return splits

# 3. 创建向量存储
def create_vectorstore(splits):
    """创建向量存储"""
    embeddings = OpenAIEmbeddings(model=EMBEDDING_MODEL)
    
    vectorstore = Chroma.from_documents(
        documents=splits,
        embedding=embeddings,
        persist_directory=VECTORSTORE_DIR
    )
    
    vectorstore.persist()
    print("向量存储创建完成并持久化")
    return vectorstore

# 4. 加载向量存储
def load_vectorstore():
    """加载现有的向量存储"""
    embeddings = OpenAIEmbeddings(model=EMBEDDING_MODEL)
    
    vectorstore = Chroma(
        embedding_function=embeddings,
        persist_directory=VECTORSTORE_DIR
    )
    
    print(f"向量存储加载完成,包含 {vectorstore._collection.count()} 个文档块")
    return vectorstore

# 5. 创建对话链
def create_conversational_chain(vectorstore):
    """创建对话链"""
    llm = OpenAI(model_name=LLM_MODEL, temperature=0.7)
    
    # 创建记忆
    memory = ConversationBufferMemory(
        memory_key="chat_history",
        return_messages=True
    )
    
    # 创建提示模板
    template = """
    你是一个企业知识库智能助手,负责回答员工关于企业文档的问题。
    
    请根据以下上下文和对话历史,回答用户的问题:
    
    上下文:
    {context}
    
    对话历史:
    {chat_history}
    
    用户问题:
    {question}
    
    请确保你的回答:
    1. 基于提供的上下文,不要编造信息
    2. 回答准确、简洁、专业
    3. 如果无法根据上下文回答,请明确说明
    4. 保持一致的语气和风格
    """
    
    prompt = PromptTemplate(
        input_variables=["context", "chat_history", "question"],
        template=template
    )
    
    # 创建对话链
    chain = ConversationalRetrievalChain.from_llm(
        llm=llm,
        retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
        memory=memory,
        combine_docs_chain_kwargs={"prompt": prompt},
        verbose=True
    )
    
    return chain

# 6. 智能体类
class EnterpriseKnowledgeAgent:
    def __init__(self):
        # 尝试加载向量存储,如果不存在则创建
        try:
            self.vectorstore = load_vectorstore()
        except Exception as e:
            print(f"加载向量存储失败,将创建新的向量存储: {e}")
            documents = load_documents(DATA_DIR)
            splits = split_documents(documents)
            self.vectorstore = create_vectorstore(splits)
        
        # 创建对话链
        self.chain = create_conversational_chain(self.vectorstore)
    
    def update_knowledge_base(self):
        """更新知识库"""
        print("开始更新知识库...")
        documents = load_documents(DATA_DIR)
        splits = split_documents(documents)
        self.vectorstore = create_vectorstore(splits)
        self.chain = create_conversational_chain(self.vectorstore)
        print("知识库更新完成")
    
    def answer_question(self, question):
        """回答用户问题"""
        try:
            response = self.chain.run(question)
            return response
        except Exception as e:
            print(f"回答问题时出错: {e}")
            return "抱歉,我在处理您的问题时遇到了错误,请稍后再试。"

# 7. 测试智能体
if __name__ == "__main__":
    # 初始化智能体
    agent = EnterpriseKnowledgeAgent()
    
    # 测试对话
    print("企业知识库智能助手已启动,您可以开始提问。输入'退出'结束对话。")
    
    while True:
        question = input("您的问题: ")
        if question == "退出":
            break
        
        response = agent.answer_question(question)
        print(f"智能助手: {response}")
        print("-" * 80)
« 上一篇 对话中的记忆管理:总结对话与向量检索结合 下一篇 » 工具的哲学:智能体如何选择工具