Python中LangChain进行文档检索和问答:企业应用实战案例

云信安装大师
90
AI 质量分
2 5 月, 2025
2 分钟阅读
0 阅读

Python中LangChain进行文档检索和问答:企业应用实战案例

引言

在企业环境中,如何快速从大量文档中获取精准信息是一个常见挑战。本文将介绍如何使用Python的LangChain框架构建一个企业级文档检索和问答系统,帮助员工快速获取知识库中的信息。

准备工作

环境要求

  • Python 3.8+
  • pip包管理工具
  • 推荐使用Jupyter Notebook或VS Code作为开发环境

安装依赖

代码片段
pip install langchain openai chromadb tiktoken python-dotenv pypdf

获取OpenAI API Key

  1. 访问OpenAI官网
  2. 创建账号并获取API Key
  3. 在项目根目录创建.env文件保存密钥:
代码片段
OPENAI_API_KEY=你的API密钥

实战步骤

1. 初始化环境与加载文档

代码片段
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from dotenv import load_dotenv
import os

# 加载环境变量
load_dotenv()

# 加载PDF文档(以企业员工手册为例)
loader = PyPDFLoader("employee_handbook.pdf")
pages = loader.load()

# 将文档分割成小块(chunks)
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200,
    length_function=len
)
docs = text_splitter.split_documents(pages)

print(f"原始文档页数: {len(pages)}")
print(f"分割后的文档块数: {len(docs)}")

原理说明
RecursiveCharacterTextSplitter会将文本按字符递归分割,保持语义连贯性
chunk_size=1000表示每个块约1000个字符
chunk_overlap=200确保块之间有200字符重叠,避免信息割裂

2. 创建向量数据库

代码片段
# 初始化OpenAI的嵌入模型
embeddings = OpenAIEmbeddings()

# 创建并持久化向量存储(这里使用ChromaDB)
persist_directory = 'db'
vectordb = Chroma.from_documents(
    documents=docs,
    embedding=embeddings,
    persist_directory=persist_directory
)
vectordb.persist()

print("向量数据库创建完成,已持久化到本地")

企业实践建议
1. 对于大型企业文档库,考虑使用专业向量数据库如Pinecone或Weaviate
2. ChromaDB适合中小规模数据(10万条以内),无需额外服务即可运行

3. 构建问答链

代码片段
from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI

# 初始化LLM(这里使用gpt-3.5-turbo)
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

# 创建检索式问答链
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=vectordb.as_retriever(search_kwargs={"k": 3}),
    return_source_documents=True
)

参数解释
temperature=0使输出更确定性,适合企业场景
search_kwargs={"k":3}表示检索最相关的3个文档块作为上下文

4. 测试问答系统

代码片段
query = "公司年假政策是怎样的?"
result = qa_chain({"query": query})

print(f"问题: {query}")
print(f"回答: {result['result']}")
print("\n参考来源:")
for doc in result['source_documents']:
    print(f"- {doc.metadata['source']} (第{doc.metadata['page']+1}页)")

示例输出

代码片段
问题: 公司年假政策是怎样的?
回答: 根据公司政策,全职员工工作满一年后享有15天带薪年假...

参考来源:
- employee_handbook.pdf (第23页)
- employee_handbook.pdf (第24页)

高级优化技巧

1. 添加历史对话上下文

代码片段
from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory(
    memory_key="chat_history",
    return_messages=True,
    output_key='answer'
)

qa_chain_with_memory = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=vectordb.as_retriever(),
    memory=memory,
    return_source_documents=True,
)

2. PDF预处理优化方案

代码片段
def preprocess_pdf(file_path):
    """处理PDF中的特殊格式"""
    loader = PyPDFLoader(file_path)

    # LangChain内置的PDF处理器有时会保留换行符导致问题
    for page in loader.load():
        page.page_content = page.page_content.replace('\n', ' ')
        # Add more preprocessing as needed

    return pages

# Usage:
pages = preprocess_pdf("employee_handbook.pdf")

常见问题解决

  1. 报错”Rate limit reached”

    • OpenAI API有调用频率限制(3,000 RPM/60,000 TPM)
    • Solution:
      代码片段
      from tenacity import retry, stop_after_attempt, wait_exponential
      
      @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
      def safe_query(qa_chain, question):
          return qa_chain({"query": question})<br>
      
  2. 中文支持不佳

    • Solution:
      代码片段
      text_splitter = RecursiveCharacterTextSplitter(
          separators=["\n\n", "\n", "。", "!", "?", ";"], #中文标点分割符  
          chunk_size=500, #中文可适当减小chunk大小  
          chunk_overlap=100  
      )<br>
      

部署建议

对于企业生产环境,建议:

  1. 安全层:在API前添加认证层(Auth0/Keycloak)
  2. 监控:记录所有问答日志用于后续分析优化
  3. 缓存机制:对常见问题答案进行缓存减少API调用

完整部署示例(Docker版):

代码片段
FROM python:3.9-slim

WORKDIR /app 
COPY . .

RUN pip install -r requirements.txt 

ENV OPENAI_API_KEY=${OPENAI_API_KEY}
EXPOSE 8000 

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

总结

本文通过完整案例展示了如何利用LangChain构建企业级文档问答系统:

1️⃣ PDF文档加载与智能分块处理
2️⃣ ChromaDB向量数据库的创建与管理
3️⃣ GPT模型与检索链的集成方法
4️⃣生产环境部署的实用建议

通过这个方案,企业可以快速将静态文档转化为智能知识库,显著提升信息检索效率。

原创 高质量