《AI大模型应知应会100篇》第65篇:基于大模型的文档问答系统实现

第65篇:基于大模型的文档问答系统实现

📚 摘要:本文详解如何构建一个基于大语言模型(LLM)的文档问答系统,支持用户上传 PDF 或 Word 文档,并根据其内容进行智能问答。从文档解析、向量化、存储到检索与生成回答,手把手带你搭建完整流程。文末提供实战代码与部署指南,适合 AI 初中级开发者学习和参考。


在这里插入图片描述

一、系统架构设计概览

构建一个完整的文档问答系统,通常包括以下几个核心模块:

用户上传文档 → 文档解析 → 文本预处理 → 向量化 → 存储到向量数据库
→ 用户提问 → 检索相关段落 → 结合 LLM 生成答案 → 返回结果

我们将其拆解为五个主要步骤:

  1. 文档解析:将 PDF/Word 转换为纯文本;
  2. 文本分割与向量化:使用 LangChain 分割文本并用嵌入模型编码;
  3. 向量存储与检索:使用 Pinecone 存储向量并执行相似度搜索;
  4. 问答生成引擎:结合检索结果,调用大模型生成自然语言答案;
  5. 前后端整合:使用 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、多语言识别、错题记录;
  • 扩展:支持视频字幕提取 + 知识图谱构建。

七、总结与扩展建议

当前系统优势:

  • 支持多种文档格式上传;
  • 基于语义检索 + 大模型生成,答案更准确;
  • 易于部署,前后端分离,便于扩展。

可扩展方向:

  1. 多文档交叉检索:允许多个文档同时参与检索,提升准确性;
  2. 多语言支持:使用 multilingual transformers 增加中文/日文/韩文等支持;
  3. OCR 集成:对扫描 PDF 使用 Tesseract OCR 提取文字;
  4. 知识图谱构建:将文档结构化为实体关系图,增强推理能力;
  5. 私有化部署:使用本地大模型(如 Qwen、ChatGLM)替代 OpenAI;
  6. 性能优化:使用 FAISS 替代 Pinecone 实现本地向量检索。

📌 附录:推荐工具与资源

功能推荐工具
文档解析PyPDF2, python-docx
文本分割LangChain
向量化OpenAI Embeddings, Sentence Transformers
向量数据库Pinecone, Milvus, FAISS
大模型问答OpenAI GPT, HuggingFace Transformers
后端框架FastAPI
前端界面Streamlit, React

📌 结语:本文从零开始讲解了如何构建一个完整的文档问答系统,涵盖数据处理、向量化、检索与生成等多个环节,并提供了实战代码与部署方案。希望你能通过本篇文章掌握这一关键技术,打造属于自己的智能问答助手!

如果你喜欢这篇文章,欢迎点赞、收藏、转发,也欢迎关注我的专栏《AI大模型应知应会100篇》持续更新中 👇


如有疑问或需要定制开发,请留言或私信我,我们将持续为你提供高质量的人工智能内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/81269.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RTK哪个品牌好?2025年RTK主流品牌深度解析

在测绘领域,RTK 技术的发展日新月异,选择一款性能卓越、稳定可靠的 RTK 设备至关重要。2025 年,市场上涌现出众多优秀品牌,本文将深入解析几大主流品牌的核心竞争力。 华测导航(CHCNAV):技术创…

SpringCloud微服务开发与实战

本节内容带你认识什么是微服务的特点,微服务的拆分,会使用Nacos实现服务治理,会使用OpenFeign实现远程调用(通过黑马商城来带你了解实际开发中微服务项目) 前言:从谷歌搜索指数来看,国内从自201…

pgsql14自动创建表分区

最近有pgsql的分区表功能需求,没想到都2025年了,pgsql和mysql还是没有自身支持自动创建分区表的功能 现在pgsql数据库层面还是只能用老三样的办法来处理这个问题,每个方法各有优劣 1. 触发器 这是最传统的方法,通过创建一个触发…

math toolkit for real-time development读书笔记一三角函数快速计算(1)

一、基础知识 根据高中知识我们知道,很多函数都可以用泰勒级数展开。正余弦泰勒级数展开如下: 将其进一步抽象为公式可知: 正弦和余弦的泰勒级数具有高度结构化的模式,可拆解为以下核心特征: 1. 符号交替特性 正弦级…

uni-app 中适配 App 平台

文章目录 前言✅ 1. App 使用的 Runtime 架构:**WebView 原生容器(plus runtime)**📌 技术栈核心: ✅ 2. WebView Native 的通信机制详解(JSBridge)📤 Web → Native 调用&#xf…

SpringBoot基础(静态资源导入)

静态资源导入 在WebMvcAutoConfiguration自动配置类中 有一个添加资源的方法: public void addResourceHandlers(ResourceHandlerRegistry registry) { //如果静态资源已经被自定义了,则直接生效if (!this.resourceProperties.isAddMappings()) {logg…

基于OpenCV的人脸识别:LBPH算法

文章目录 引言一、概述二、代码实现1. 代码整体结构2. 导入库解析3. 训练数据准备4. 标签系统5. 待识别图像加载6. LBPH识别器创建7. 模型训练8. 预测执行9. 结果输出 三、 LBPH算法原理解析四、关键点解析五、改进方向总结 引言 人脸识别是计算机视觉领域的一个重要应用&…

ElasticSearch重启之后shard未分配问题的解决

以下是Elasticsearch重启后分片未分配问题的完整解决方案,结合典型故障场景与最新实践: 一、快速诊断定位 ‌检查集群状态 GET /_cluster/health?pretty # status为red/yellow时需关注unassigned_shards字段值 ‌ 2.查看未分配分片详情 …

CSS- 3.1 盒子模型-块级元素、行内元素、行内块级元素和display属性

本系列可作为前端学习系列的笔记,代码的运行环境是在HBuilder中,小编会将代码复制下来,大家复制下来就可以练习了,方便大家学习。 HTML系列文章 已经收录在前端专栏,有需要的宝宝们可以点击前端专栏查看! 点…

Git/GitLab日常使用的命令指南来了!

在 GitLab 中拉取并合并代码的常见流程是通过 Git 命令来完成的。以下是一个标准的 Git 工作流,适用于从远程仓库(如 GitLab)拉取代码、切换分支、合并更新等操作。 🌐 一、基础命令:拉取最新代码 # 拉取远程仓库的所…

HTML 表格与div深度解析区别及常见误区

一、HTML<div>元素详解 <div>是HTML中最基本的块级容器元素&#xff0c;本身没有语义&#xff0c;主要用于组织和布局页面内容。以下是其核心用法&#xff1a; 1. 基础结构与特性 <div><!-内部可包含任意HTML元素 --><h2>标题</h2><p…

mybatisPlus 新增时 其他字段的值和 id 保持一致实现方法

MyBatis-Plus 实现 sp_id_path 与 id 同步的方案 要实现新增时 sp_id_path 自动与 id 保持一致&#xff0c;需要在实体类和插入逻辑中做相应处理。MyBatis-Plus 提供了几种方式来实现这一需求&#xff1a; 方案一&#xff1a;使用 MyBatis-Plus 的自动填充功能 这是最优雅的…

兰亭妙微设计:为生命科技赋予人性化的交互语言

在医疗科技日新月异的今天&#xff0c;卓越的硬件性能唯有匹配恰如其分的交互语言&#xff0c;方能真正发挥价值。作为专注于医疗UI/UX设计的专业团队&#xff0c;兰亭妙微设计&#xff08;www.lanlanwork.com&#xff09;始终相信&#xff1a;每一处像素的排布&#xff0c;都应…

Tcping详细使用教程

Tcping详细使用教程 下载地址 https://download.elifulkerson.com/files/tcping/0.39/在windows环境下安装tcping 在以上的下载地中找到exe可执行文件&#xff0c;其中tcping.exe适用于32位Windows系统&#xff0c;tcping64.exe适用于64位Windows操作系统。 其实tcping是个…

springCloud/Alibaba常用中间件之Seata分布式事务

文章目录 SpringCloud Alibaba:依赖版本补充Seata处理分布式事务(AT模式)AT模式介绍核心组件介绍AT的工作流程&#xff1a;两阶段提交&#xff08;**2PC**&#xff09; Seata-AT模式使用Seata(2.0.0)下载、配置和启动Seata案例实战前置代码添加全局注解 GlobalTransactional Sp…

COMSOL随机参数化表面流体流动模拟

基于粗糙度表面的裂隙流研究对于理解地下水的流动、污染物传输以及与之相关的地质灾害&#xff08;如滑坡&#xff09;等方面具有重要意义。本研究通过蒙特卡洛方法生成随机表面形貌&#xff0c;并利用COMSOL Multiphysics对随机参数化表面的微尺度流体流动进行模拟。 参数化…

初识——QT

QT安装方法 一、项目创建流程 创建项目 入口&#xff1a;通过Qt Creator的欢迎页面或菜单栏&#xff08;文件→新建项目&#xff09;创建新项目。 项目类型&#xff1a;选择「Qt Widgets Application」。 路径要求&#xff1a;项目路径需为纯英文且不含特殊字符。 构建系统…

7-15 计算圆周率

π​131​352!​3573!​⋯357⋯(2n1)n!​⋯ 输入格式&#xff1a; 输入在一行中给出小于1的阈值。 输出格式&#xff1a; 在一行中输出满足阈值条件的近似圆周率&#xff0c;输出到小数点后6位。 输入样例&#xff1a; 0.01输出样例&#xff1a; 3.132157 我的代码 #i…

【图片识别工具】批量单据识别批量重命名,批量OCR识别图片文字并重命名,批量改名工具的使用步骤和注意事项

一、适用场景 ​​财务与发票管理​​&#xff1a;企业需处理大量电子发票或扫描件&#xff0c;通过OCR识别发票代码、金额等关键信息&#xff0c;自动重命名为发票号_金额.pdf格式&#xff0c;便于归档与税务审计。 ​​物流单据处理​​&#xff1a;物流公司需从运单中提取单…

Modbus TCP转Profinet网关:数字化工厂异构网络融合的核心枢纽

在现代工业生产中&#xff0c;随着智能制造和工业互联网的不断发展&#xff0c;数字化工厂成为了制造业升级的重要方向。数字化工厂的核心在于实现设备、数据和人的互联互通&#xff0c;而这其中&#xff0c;通信协议扮演着至关重要的角色。今天&#xff0c;我们就来探讨开疆智…