第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篇》持續更新中 👇
如有疑問或需要定制開發,請留言或私信我,我們將持續為你提供高質量的人工智能內容。