第65篇:基于大模型的文档问答系统实现
📚 摘要:本文详解如何构建一个基于大语言模型(LLM)的文档问答系统,支持用户上传 PDF 或 Word 文档,并根据其内容进行智能问答。从文档解析、向量化、存储到检索与生成回答,手把手带你搭建完整流程。文末提供实战代码与部署指南,适合 AI 初中级开发者学习和参考。
一、系统架构设计概览
构建一个完整的文档问答系统,通常包括以下几个核心模块:
用户上传文档 → 文档解析 → 文本预处理 → 向量化 → 存储到向量数据库
→ 用户提问 → 检索相关段落 → 结合 LLM 生成答案 → 返回结果
我们将其拆解为五个主要步骤:
- 文档解析:将 PDF/Word 转换为纯文本;
- 文本分割与向量化:使用 LangChain 分割文本并用嵌入模型编码;
- 向量存储与检索:使用 Pinecone 存储向量并执行相似度搜索;
- 问答生成引擎:结合检索结果,调用大模型生成自然语言答案;
- 前后端整合:使用 FastAPI 构建后端接口 + Streamlit 实现前端交互。
二、文档预处理与向量化【实战部分】
1. 安装依赖
pip install PyPDF2 python-docx langchain openai sentence-transformers pinecone-client fastapi uvicorn streamlit
2. 解析 PDF 和 Word 文件
import PyPDF2
from docx import Documentdef read_pdf(file_path):with open(file_path, 'rb') as f:reader = PyPDF2.PdfReader(f)text = ''for page in reader.pages:text += page.extract_text()return textdef read_docx(file_path):doc = Document(file_path)full_text = [p.text for p in doc.paragraphs]return '\n'.join(full_text)
3. 使用 LangChain 进行文本分割
from langchain.text_splitter import RecursiveCharacterTextSplittertext_splitter = RecursiveCharacterTextSplitter(chunk_size=1000,chunk_overlap=100
)chunks = text_splitter.split_text(document_text) # document_text 是上一步读取的文本
4. 使用 OpenAI 或 Sentence Transformers 生成嵌入
✅ OpenAI 嵌入方式(需 API Key)
from langchain.embeddings.openai import OpenAIEmbeddingsembeddings = OpenAIEmbeddings(openai_api_key="YOUR_OPENAI_API_KEY")
vectorized_chunks = embeddings.embed_documents(chunks)
✅ 本地 Sentence Transformer 嵌入方式(无需网络)
from sentence_transformers import SentenceTransformermodel = SentenceTransformer('all-MiniLM-L6-v2')
vectorized_chunks = model.encode(chunks)
三、向量存储与检索【实战部分】
我们以 Pinecone 为例来展示向量存储和检索过程。
1. 初始化 Pinecone
pip install pinecone-client
import pineconepinecone.init(api_key="YOUR_PINECONE_API_KEY", environment="us-west1-gcp")
index_name = "document-qa-index"if index_name not in pinecone.list_indexes():pinecone.create_index(name=index_name, dimension=1536) # OpenAI 默认维度index = pinecone.Index(index_name)
2. 将向量写入 Pinecone
from uuid import uuid4vectors = [(str(uuid4()), vector, {"text": chunk}) for chunk, vector in zip(chunks, vectorized_chunks)]
index.upsert(vectors=vectors)
3. 执行语义检索(Top-K)
query = "什么是量子计算?"
query_vector = embeddings.embed_query(query) # 如果是 OpenAI 嵌入
# query_vector = model.encode([query])[0] # 如果是 Sentence Transformerresult = index.query(queries=[query_vector], top_k=3, include_metadata=True)
print(result)
输出示例:
{"matches": [{"id": "abc123","score": 0.89,"metadata": {"text": "量子计算是一种利用量子比特进行信息处理的技术..."}},...]
}
四、问答生成引擎【实战部分】
1. 使用 LangChain + OpenAI 生成答案
from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplatellm = ChatOpenAI(model_name='gpt-3.5-turbo', openai_api_key="YOUR_OPENAI_API_KEY")prompt_template = """
你是一个基于以下上下文回答问题的助手。
请根据提供的上下文信息,给出简洁准确的回答。Context: {context}Question: {question}Answer:
"""prompt = PromptTemplate.from_template(prompt_template)# 整理检索结果中的 context
context = "\n".join([match['metadata']['text'] for match in result['matches']])
final_prompt = prompt.format(context=context, question=query)answer = llm.predict(final_prompt)
print(answer)
2. 多轮对话记忆机制(可选)
from langchain.memory import ConversationBufferMemorymemory = ConversationBufferMemory(memory_key="chat_history", input_key="question")
conversation = ConversationalRetrievalChain.from_llm(llm, retriever=vectorstore.as_retriever(), memory=memory)response = conversation({"question": "量子比特是什么?"})
print(response["answer"])
五、前后端整合与部署
1. 使用 FastAPI 构建后端服务
# app.py
from fastapi import FastAPI, UploadFile, File
from pydantic import BaseModel
import osapp = FastAPI()@app.post("/upload")
async def upload_file(file: UploadFile = File(...)):file_location = f"uploads/{file.filename}"with open(file_location, "wb+") as file_object:file_object.write(file.file.read())# 解析文档 + 向量化 + 存入 Pinecone 的逻辑return {"filename": file.filename, "status": "processed"}class QuestionRequest(BaseModel):question: str@app.post("/ask")
async def answer_question(req: QuestionRequest):# 调用检索 + 生成答案逻辑return {"answer": generated_answer}
启动服务:
uvicorn app:app --reload
访问 http://localhost:8000/docs
查看 API 接口文档。
2. 使用 Streamlit 构建前端界面
# frontend.py
import streamlit as st
import requestsst.title("文档问答系统")uploaded_file = st.file_uploader("上传 PDF 或 Word 文件", type=["pdf", "docx"])
if uploaded_file:files = {"file": uploaded_file.getvalue()}res = requests.post("http://localhost:8000/upload", files=files)st.success(res.json()["filename"] + " 已上传并处理完成!")question = st.text_input("请输入你的问题:")
if question:payload = {"question": question}res = requests.post("http://localhost:8000/ask", json=payload)st.write("回答:", res.json()["answer"])
运行前端:
streamlit run frontend.py
六、实战案例研究
案例一:企业内部知识库问答系统
- 场景:员工上传公司制度、产品手册等文档,快速查找政策或技术细节;
- 技术点:多文档上传、交叉检索、权限控制;
- 扩展:集成 Slack / 钉钉机器人自动推送答案。
案例二:教育领域课程资料问答平台
- 场景:学生上传讲义、笔记,提出课程相关问题,系统自动生成解答;
- 技术点:OCR 支持扫描版 PDF、多语言识别、错题记录;
- 扩展:支持视频字幕提取 + 知识图谱构建。
七、总结与扩展建议
当前系统优势:
- 支持多种文档格式上传;
- 基于语义检索 + 大模型生成,答案更准确;
- 易于部署,前后端分离,便于扩展。
可扩展方向:
- 多文档交叉检索:允许多个文档同时参与检索,提升准确性;
- 多语言支持:使用 multilingual transformers 增加中文/日文/韩文等支持;
- OCR 集成:对扫描 PDF 使用 Tesseract OCR 提取文字;
- 知识图谱构建:将文档结构化为实体关系图,增强推理能力;
- 私有化部署:使用本地大模型(如 Qwen、ChatGLM)替代 OpenAI;
- 性能优化:使用 FAISS 替代 Pinecone 实现本地向量检索。
📌 附录:推荐工具与资源
功能 | 推荐工具 |
---|---|
文档解析 | PyPDF2, python-docx |
文本分割 | LangChain |
向量化 | OpenAI Embeddings, Sentence Transformers |
向量数据库 | Pinecone, Milvus, FAISS |
大模型问答 | OpenAI GPT, HuggingFace Transformers |
后端框架 | FastAPI |
前端界面 | Streamlit, React |
📌 结语:本文从零开始讲解了如何构建一个完整的文档问答系统,涵盖数据处理、向量化、检索与生成等多个环节,并提供了实战代码与部署方案。希望你能通过本篇文章掌握这一关键技术,打造属于自己的智能问答助手!
如果你喜欢这篇文章,欢迎点赞、收藏、转发,也欢迎关注我的专栏《AI大模型应知应会100篇》持续更新中 👇
如有疑问或需要定制开发,请留言或私信我,我们将持续为你提供高质量的人工智能内容。