《Python + Streamlit + DeepSeek API 实现一个本地文档问答助手》

发布时间:2026/8/29 9:11:10

《Python + Streamlit + DeepSeek API 实现一个本地文档问答助手》
Python Streamlit DeepSeek API 实现一个本地文档问答助手本文会从 0 到 1 实现一个可以运行的大模型文档问答小项目上传 PDF 或 TXT 文档输入问题后程序会先从文档中检索相关片段再调用大模型生成回答。摘要很多大模型应用并不是从零训练模型而是把已有模型接入到具体业务流程中。本文以“本地文档问答助手”为例使用 Python、Streamlit、DeepSeek API、pypdf 和 scikit-learn 实现一个入门版 RAG 应用。项目完成后可以实现上传 PDF / TXT 文档自动读取文档内容将长文本切分成多个片段根据用户问题检索相关内容调用 DeepSeek 大模型生成回答展示答案和参考片段本文尽量不依赖复杂框架先把完整流程跑通适合用来理解大模型应用开发中的 RAG 基本思路。目录一、项目效果二、技术选型三、项目原理四、环境准备五、项目目录六、完整代码七、运行项目八、核心代码解析九、常见问题十、后续优化方向十一、总结一、项目效果运行后会得到一个本地 Web 页面页面中包含两个主要输入区域文档上传区域支持上传 PDF 或 TXT问题输入区域输入想从文档中查询的问题使用流程如下上传文档 ↓ 输入问题 ↓ 点击“生成回答” ↓ 系统检索文档片段 ↓ 大模型基于检索内容生成回答 ↓ 页面展示回答和参考片段例如上传一份技术文档后可以提问这份文档主要讲了什么也可以提问文档中提到了哪些关键步骤相比普通聊天机器人这个项目的重点在于模型回答时会参考用户上传的文档内容而不是完全依赖模型自身知识。二、技术选型本项目使用的技术如下技术作用Python核心开发语言Streamlit快速搭建 Web 页面DeepSeek API调用大模型生成回答OpenAI SDK使用兼容 OpenAI 格式的接口调用 DeepSeekpypdf读取 PDF 文本scikit-learn使用 TF-IDF 和余弦相似度做文本检索这里没有直接使用 LangChain、LlamaIndex 或向量数据库主要是为了先用较少代码理解 RAG 的核心流程。后续可以在这个版本基础上继续升级。三、项目原理这个项目可以看作一个简化版 RAG也就是检索增强生成。普通大模型问答流程是用户问题 → 大模型 → 回答本文实现的流程是用户问题 → 检索文档相关片段 → 大模型基于片段回答 → 展示答案完整流程可以拆成 5 步1. 读取上传文档 2. 将文档切分成多个文本片段 3. 计算用户问题和文本片段的相似度 4. 取出最相关的几个片段 5. 将片段和问题一起交给大模型生成回答这里的“检索”使用 TF-IDF cosine similarity 实现。它不是最强的语义检索方案但非常适合入门因为代码简单、依赖少、方便理解。四、环境准备建议使用 Python 3.10 或以上版本。1. 创建项目目录mkdirdocument_qa_democddocument_qa_demo2. 创建虚拟环境python-mvenv .venvWindows PowerShell 激活虚拟环境.venv\Scripts\Activate.ps1macOS / Linux 激活虚拟环境source.venv/bin/activate3. 安装依赖pipinstallstreamlit openai scikit-learn pypdf也可以新建requirements.txtstreamlit openai scikit-learn pypdf然后执行pipinstall-rrequirements.txt4. 配置 DeepSeek API KeyDeepSeek API 兼容 OpenAI SDK调用时需要配置base_url和 API Key。Windows PowerShell 临时设置$env:DEEPSEEK_API_KEY你的 API KeymacOS / Linux 临时设置exportDEEPSEEK_API_KEY你的 API Key如果使用 Streamlit 的 secrets也可以创建文件.streamlit/secrets.toml写入DEEPSEEK_API_KEY 你的 API Key注意不要把自己的 API Key 上传到 GitHub也不要直接写进公开文章的代码里。五、项目目录最终目录结构如下document_qa_demo ├── app.py ├── requirements.txt └── .streamlit └── secrets.toml其中app.py项目主程序requirements.txt依赖列表.streamlit/secrets.toml本地密钥配置可选六、完整代码新建app.py写入下面代码importosfromioimportBytesIOimportstreamlitasstfromopenaiimportOpenAIfrompypdfimportPdfReaderfromsklearn.feature_extraction.textimportTfidfVectorizerfromsklearn.metrics.pairwiseimportcosine_similarity MODEL_NAMEdeepseek-v4-flashdefget_api_key():ifDEEPSEEK_API_KEYinst.secrets:returnst.secrets[DEEPSEEK_API_KEY]returnos.getenv(DEEPSEEK_API_KEY)defread_pdf(uploaded_file):readerPdfReader(BytesIO(uploaded_file.getvalue()))text_list[]forpageinreader.pages:page_textpage.extract_text()ifpage_text:text_list.append(page_text)return\n.join(text_list)defread_txt(uploaded_file):returnuploaded_file.getvalue().decode(utf-8,errorsignore)defsplit_text(text,chunk_size700,overlap120):chunks[]start0whilestartlen(text):endstartchunk_size chunktext[start:end].strip()iflen(chunk)80:chunks.append(chunk)startend-overlapreturnchunksdefretrieve_chunks(question,chunks,top_k4):ifnotchunks:return[]vectorizerTfidfVectorizer(analyzerchar,ngram_range(2,4))doc_vectorsvectorizer.fit_transform(chunks)question_vectorvectorizer.transform([question])scorescosine_similarity(question_vector,doc_vectors)[0]ranked_indexesscores.argsort()[::-1][:top_k]results[]forindexinranked_indexes:results.append({content:chunks[index],score:float(scores[index])})returnresultsdefask_llm(api_key,question,retrieved_chunks):context\n\n.join([f资料片段{index1}\n{item[content]}forindex,iteminenumerate(retrieved_chunks)])clientOpenAI(api_keyapi_key,base_urlhttps://api.deepseek.com)responseclient.chat.completions.create(modelMODEL_NAME,messages[{role:system,content:(你是一个严谨的文档问答助手。请只根据用户提供的资料回答问题。如果资料中没有相关信息请明确说明无法从当前资料中确定。)},{role:user,content:f 请根据下面的资料回答用户问题。 【资料】{context}【用户问题】{question}【回答要求】 1. 先直接回答问题 2. 不要编造资料中没有的信息 3. 如果资料不足请明确说明 4. 最后简单说明依据来自哪些资料片段 }],streamFalse)returnresponse.choices[0].message.content st.set_page_config(page_title本地文档问答助手,layoutwide)st.title(本地文档问答助手)st.caption(上传 PDF 或 TXT 文档输入问题后系统会检索相关片段并调用大模型生成回答。)api_keyget_api_key()ifnotapi_key:st.warning(请先设置 DEEPSEEK_API_KEY。可以使用环境变量也可以使用 .streamlit/secrets.toml。)st.stop()withst.sidebar:st.header(参数设置)chunk_sizest.slider(文本片段长度,min_value300,max_value1500,value700,step100)overlapst.slider(片段重叠长度,min_value0,max_value300,value120,step20)top_kst.slider(检索片段数量,min_value1,max_value8,value4,step1)uploaded_filest.file_uploader(上传文档,type[pdf,txt])questionst.text_input(请输入你的问题,placeholder例如这份文档的核心内容是什么)ifuploaded_file:st.info(f当前文件{uploaded_file.name})ifuploaded_fileandquestion:ifst.button(生成回答,typeprimary):withst.spinner(正在读取文档...):ifuploaded_file.name.lower().endswith(.pdf):textread_pdf(uploaded_file)else:textread_txt(uploaded_file)ifnottext.strip():st.error(没有读取到有效文本。可能是扫描版 PDF或者文档内容为空。)st.stop()withst.spinner(正在切分文本并检索相关内容...):chunkssplit_text(text,chunk_sizechunk_size,overlapoverlap)retrieved_chunksretrieve_chunks(question,chunks,top_ktop_k)ifnotretrieved_chunks:st.error(没有检索到可用文本片段。)st.stop()withst.spinner(正在调用大模型生成回答...):answerask_llm(api_key,question,retrieved_chunks)st.subheader(回答)st.write(answer)st.subheader(参考片段)forindex,iteminenumerate(retrieved_chunks,start1):withst.expander(f参考片段{index}相似度{item[score]:.4f}):st.write(item[content])else:st.write(请先上传文档并输入问题。)七、运行项目在项目目录下执行streamlit run app.py如果命令不可用可以使用python-mstreamlit run app.py正常情况下浏览器会自动打开本地页面地址通常是http://localhost:8501如果页面没有自动打开也可以手动复制终端里的地址到浏览器访问。八、核心代码解析1. 使用 Streamlit 上传文件uploaded_filest.file_uploader(上传文档,type[pdf,txt])这里限制上传类型为 PDF 和 TXT。Streamlit 会把上传的文件包装成一个类似文件对象的UploadedFile后续可以直接读取内容。2. 读取 PDF 文本readerPdfReader(BytesIO(uploaded_file.getvalue()))pypdf可以读取普通 PDF 中的文本。如果 PDF 是扫描图片可能提取不到文字这种情况需要额外接入 OCR。3. 文本切分chunkssplit_text(text,chunk_sizechunk_size,overlapoverlap)长文档不能直接全部塞给大模型所以需要切成多个片段。这里设置了两个参数chunk_size每个片段的大致长度overlap相邻片段之间的重叠长度保留重叠的原因是避免一句话或一个段落被切断后丢失上下文。4. 检索相关片段scorescosine_similarity(question_vector,doc_vectors)[0]这里使用 TF-IDF 将文本转换成特征向量再用余弦相似度计算问题和文档片段的相关程度。相似度越高说明该片段越可能和问题相关。本文为了适配中文使用了字符级 n-gramanalyzerchar,ngram_range(2,4)这样即使没有分词工具也能完成一个基础检索效果。5. 调用 DeepSeek APIclientOpenAI(api_keyapi_key,base_urlhttps://api.deepseek.com)DeepSeek API 兼容 OpenAI SDK所以可以通过OpenAI客户端调用。本文使用的模型是MODEL_NAMEdeepseek-v4-flash生成回答时将检索到的资料片段和用户问题一起发送给模型responseclient.chat.completions.create(modelMODEL_NAME,messages[...],streamFalse)这样模型就会优先根据上传文档中的内容进行回答。九、常见问题1. 为什么上传 PDF 后没有内容可能原因是 PDF 是扫描版也就是每一页本质上是图片而不是可复制的文字。pypdf只能提取文本型 PDF。扫描版 PDF 需要使用 OCR 工具识别文字。2. 为什么回答看起来不够准确可能有几个原因文档切分太短导致上下文不完整文档切分太长导致检索不精确TF-IDF 更偏关键词匹配不是真正的语义向量检索问题表述和文档内容差异较大可以尝试调整侧边栏中的文本片段长度、片段重叠长度和检索片段数量。3. TF-IDF 和真正的向量检索有什么区别TF-IDF 更像关键词检索适合入门和小规模 Demo。真正的 RAG 项目通常会使用 Embedding 模型把文本转换成语义向量然后存入 FAISS、Chroma、Milvus 或 pgvector 等向量数据库中。简单理解TF-IDF更关注字词是否相似 Embedding更关注语义是否相似例如“如何申请报销”和“费用报销流程是什么”字面上不完全一样但语义接近。Embedding 检索通常更容易识别这种相似关系。4. API Key 应该怎么保存不要直接写在代码里建议使用环境变量.streamlit/secrets.toml部署平台提供的密钥管理功能如果代码要上传 GitHub记得把.streamlit/secrets.toml加入.gitignore。十、后续优化方向当前项目是入门版本可以继续从以下方向优化使用 Embedding 模型替代 TF-IDF提高语义检索效果。使用 FAISS 或 Chroma 存储向量支持更大的文档库。支持多文件上传实现个人知识库。记录历史对话让用户可以连续追问。增加页码引用让答案能追溯到 PDF 的具体页面。增加 FastAPI 后端将前端和后端分离。增加 Dockerfile方便部署和演示。接入 OCR支持扫描版 PDF。如果继续升级可以把项目路线设计成版本 1TF-IDF Streamlit 单文件 Demo 版本 2Embedding FAISS 语义检索 版本 3多文档知识库 历史对话 版本 4FastAPI 后端 前端页面 版本 5Docker 部署 项目上线这样既能逐步理解技术原理也能把项目迭代过程记录下来。十一、总结本文实现了一个可以本地运行的大模型文档问答助手核心流程包括文档上传 → 文本读取 → 文本切分 → 相关片段检索 → 大模型生成回答 → 展示参考片段这个项目虽然不复杂但已经覆盖了大模型应用开发中的几个关键点Prompt 设计API 调用文档处理文本检索RAG 基本流程Web 页面展示对于入门大模型应用开发来说先完成这样一个能运行、能演示、能继续扩展的小项目比一开始直接堆复杂框架更容易理解核心逻辑。参考资料DeepSeek API 文档https://api-docs.deepseek.com/Streamlit 运行应用文档https://docs.streamlit.io/develop/concepts/architecture/run-your-appStreamlit 文件上传组件文档https://docs.streamlit.io/develop/api-reference/widgets/st.file_uploaderscikit-learn TfidfVectorizer 文档https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.htmlscikit-learn cosine_similarity 文档https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.cosine_similarity.htmlpypdf 文档https://pypdf.readthedocs.io/

相关新闻

TD3 vs SAC vs DDPG:3 种连续控制算法在 5 个 MuJoCo 任务上的性能对比

TD3 vs SAC vs DDPG:3 种连续控制算法在 5 个 MuJoCo 任务上的性能对比

2026/8/29 9:08:58

TD3 vs SAC vs DDPG:5大MuJoCo任务中的算法性能深度评测在强化学习领域,连续控制问题一直是极具挑战性的研究方向。面对高维连续动作空间,如何选择适合的算法成为工程师和研究者的核心关切。本文将基于5个标准MuJoCo环境(HalfChee…

通信与接口协议面试七、RS232

通信与接口协议面试七、RS232

2026/8/27 1:06:20

串口通信接口,全双工, 3 线一根信号线接收、一根信号线发送、一根地线。1.特性1.一对一通信。 2.最大传输速率:速率低,约15M20Kbps 3.最大传输距离:最大50米,实际15米 4.缺点:单端传输受共模干扰…

「 简记往来」第二十二篇:冷启动——0用户的第一个月是怎么过来的

「 简记往来」第二十二篇:冷启动——0用户的第一个月是怎么过来的

2026/8/27 16:35:21

一、上线第一天,只有3个人用 简记往来上线第一天,用户数:3人。 我、我老婆、一个朋友。 不是“理想很丰满,现实很骨感”——这就是现实。没有流量、没有用户、没有评论,你做了半年的产品,就像扔进大海里…

nPM3104 PMIC深度解析:小电池产品电源设计的关键

nPM3104 PMIC深度解析:小电池产品电源设计的关键

2026/8/29 9:10:05

做低功耗物联网产品这几年,我最大的体会是:很多时候产品翻车,不是死在无线链路,而是死在电源。Nordic Semiconductor 这次发布的 nPM3104 Power Management IC,来得正是时候。它面向小型电池产品,核心卖点就…

2026 年 AI 漫剧工具横评:知漫剧批量制作能力解析

2026 年 AI 漫剧工具横评:知漫剧批量制作能力解析

2026/8/29 9:10:05

引言 2026 年 AI 漫剧赛道持续升温,但市面上真正能做到批量量产的工具不多。知漫剧(zz.jiaxunai.cn)价格实惠,小白一键就能生成,平台有全流程教学,角色、声音、场景一致性一站解决。 这篇文章从技术视角横…

短视频剧情号批量出片思路:知漫剧实操经验分享

短视频剧情号批量出片思路:知漫剧实操经验分享

2026/8/29 9:10:05

引言 做短视频剧情号,最难的不是创意,而是稳定更新。一天出一条不难,难的是每天出一条,连续出三个月。知漫剧(zz.jiaxunai.cn)价格实惠,小白一键就能生成,平台有全流程教学&#xf…

AI短剧制作成本与效率评估:知漫剧自动化方案与外包团队的技术路径对比

AI短剧制作成本与效率评估:知漫剧自动化方案与外包团队的技术路径对比

2026/8/29 9:10:05

引言 做短剧,传统方案是找外包团队,但成本高、周期长、沟通效率低。AI 自动化工具的出现改变了这个局面。知漫剧(zz.jiaxunai.cn)价格实惠,小白一键就能生成,平台有全流程教学,角色、声音、场景…

Dify 零代码快速教程:30分钟搭出你的智能邮件管家

Dify 零代码快速教程:30分钟搭出你的智能邮件管家

2026/8/29 9:10:05

Dify 零代码快速教程:30分钟搭出你的智能邮件管家 【免费下载链接】dify Build Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to…

深度学习入门避坑:GPU显存不够时这4个技巧帮我跑通了7B模型

深度学习入门避坑:GPU显存不够时这4个技巧帮我跑通了7B模型

2026/8/29 9:00:05

深度学习入门避坑:GPU显存不够时这4个技巧帮我跑通了7B模型 最近组里接到一个需求,要把一个开源的7B参数语言模型微调后用于内部知识库问答。作为后端转AI的新手,我兴致勃勃地拉下模型权重,想在单张RTX 3090(24GB)上先跑通预训练推理。结果,AutoModel.from_pretrained执行到一…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/27 11:10:02

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/27 7:25:23

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/28 7:34:42

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

四款热门降AI工具测评:研究生和本科生怎么选?

四款热门降AI工具测评:研究生和本科生怎么选?

2026/8/29 0:09:39

马上要交论文了,最近真的被论文ai率折磨的够呛。 明明查重都没问题了,但是ai率就是居高不下,崩溃了,明明都是我自己写的,天杀的,明明都是我亲生的啊 改来改去,终于给我搞出一套完美的降ai方案…

论文降AI率免费攻略:自查、提示词与工具推荐

论文降AI率免费攻略:自查、提示词与工具推荐

2026/8/29 0:09:39

马上要交论文了,最近真的被论文ai率折磨的够呛。 明明查重都没问题了,但是ai率就是居高不下,崩溃了,明明都是我自己写的,天杀的,明明都是我亲生的啊 改来改去,终于给我搞出一套完美的降ai方案…

北京GEO优化服务商推荐:预算型企业如何选北京GEO优化服务商?

北京GEO优化服务商推荐:预算型企业如何选北京GEO优化服务商?

2026/8/29 0:09:39

前言:预算有限的企业更关心投入能否形成可持续的品牌资产。评估北京GEO优化服务商时,不能只比较单篇内容或单月报价,还要看是否能够把问题词、官网、信源和监测串成完整链路。本期重点放在预算配置、试点范围和交付边界,帮助企业先…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/28 7:35:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/28 7:34:51

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/28 7:34:35

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…