课程
DeepSeek 近日发布了 DeepSeek V3.1,一款大规模混合推理模型,支持“思考(think)”与“非思考(non-think)”两种答复模式,非常适合做交互式文档分析。
本文将重点介绍 DeepSeek V3.1 在理解学术论文方面的代理能力。我会逐步讲解如何通过一个 Streamlit 应用,将任何 PDF 转化为交互式研究助理——我们将涉及:
- 通过 OpenRouter 的 API 集成 DeepSeek V3.1,以实现可扩展的长文档推理
- 提取并解析 PDF 文本,以处理任意长度的学术论文
- 设计一个 Streamlit 应用,让用户可在快速事实回答与深入、基于证据的推理之间切换
- 在真实研究场景中实现成本跟踪与性能测量
- 用来自原文的引文为答案提供支撑
完成后,您的应用将如下所示:

什么是 DeepSeek V3.1?
DeepSeek V3.1 是一个拥有 671B 参数的混合型 专家混合(Mixture-of-Experts, MoE)模型,同时训练用于“思考”(详尽、有理据)与“非思考”(事实性、简洁)两种答题风格。它支持 128,000 个 token 的上下文窗口,并可通过 OpenRouter 提供的 OpenAI 兼容 API 访问。

来源:DeepSeek
DeepSeek V3.1 的核心特性包括:
- 长上下文处理:DeepSeek V3.1 能够高效处理超长文档,支持最多 128,000 token 的上下文窗口(超过 100 页),非常适合全面性的论文与报告。
- 双重推理模式:该模型提供以下两种推理模式:
- 思考模式:提供详细的、逐步的推理,并直接引用原文证据,便于深入分析与批判。
- 非思考模式:提供简洁、基于事实的回答,以便快速检索信息与进行快速问答。
- 混合专家架构:DeepSeek V3.1 结合多个专家子网络,在同一模型内兼顾事实回忆与高级综合能力。
- 代理与工具增强的工作流:该模型 面向代理系统集成设计,并支持外部工具使用,以构建更丰富的多步工作流。
- OpenAI 兼容的 API 访问:可通过 OpenRouter 的 OpenAI 兼容 API 访问,使开发者的部署与集成更为直接。
DeepSeek V3.1 演示:论文研究助理
本节将演示我如何使用 DeepSeek V3.1将任意上传的 PDF 论文转化为交互式、由 AI 驱动的研究助理。
其工作方式如下:
- 上传 PDF 论文并预览提取的文本。
- 用自然语言询问有关论文的问题。
- 在“简要解释”(非思考)或“详细解释”(思考)两种答复模式之间进行选择。
- 即时获得答案,同时显示响应时间、token 使用/成本预估,以及来自原文的支持性引文。
步骤 1:先决条件
在运行本演示之前,请先确认所有先决条件均已就绪。
步骤 1.1:安装依赖
首先,确保安装以下依赖:
pip install streamlit openai pypdf
该命令可确保您具备用于界面、PDF 处理与 API 请求的核心依赖。
步骤 1.2:配置 OpenRouter API 密钥
DeepSeek V3.1 模型可通过多个平台使用,包括DeepSeek 官方 API。不过,我在本演示中使用了OpenRouter,它为多种模型提供统一访问,并且对于本演示而言成本最低。以下是在 OpenRouter 上为 DeepSeek V3.1 设置 API 密钥的步骤:
- 在 https://openrouter.ai/ 注册账号
- 进入 Models 标签页,搜索“DeepSeek V3.1”。您也可以选择 base 版本,但它只针对原始的下一个 token 预测进行训练,提示工程会更困难。因此我选择了聊天版本“deepseek/deepseek-chat-v3.1”。

- 向下滚动并点击Create API Key。填写密钥名称与信用额度(可选),然后点击Create。保存该 API 密钥以备后用。

- 接着,进入 Credits 标签页,添加您的银行卡或银行账户信息。您也可以通过 Amazon Pay 或加密货币支付。本演示中我充值了约 8 美元,已足够使用。

现在,在运行应用之前将您的 API 密钥设置为环境变量:
export OPENROUTER_API_KEY=your_api_key
选择合适的 API
官方 DeepSeek API 更适合高并发、自动化的工作负载。
对于大多数研究、教育或演示类用例(包括本 Streamlit 论文助理),我更倾向于使用 OpenRouter,因为它更简单灵活,提供可预测的全球定价,无需管理时间窗口限制或缓存逻辑,非常适合临时分析、独特文档查询与便捷协作。
注意:通过 API 使用 DeepSeek V3.1,仅需约 8 GB 内存用于界面,无需在本地托管庞大的 670B 参数模型(否则需要 170+ GB 的磁盘空间和高性能 GPU)。
步骤 2:搭建 Streamlit 应用
为了让用户以友好界面使用 DeepSeek V3.1,我们将采用Streamlit 作为应用框架,并通过 OpenRouter 的 OpenAI 兼容 API 连接模型。
步骤 2.1:配置
本步骤涵盖环境配置、API 认证与基础的 Streamlit 配置。
import streamlit as stimport pypdfimport tempfilefrom openai import OpenAIimport osimport timeimport rest.set_page_config( page_title="DeepSeek V3.1 Research Assistant", layout="wide")with st.sidebar: st.title("Research Paper Assistant") st.info("Tip: Ask about the methods, findings, or reasoning for best results.")OPENROUTER_API_KEY = os.environ.get("OPENROUTER_API_KEY", "")if not OPENROUTER_API_KEY: st.warning("Add your OpenRouter API key to an environment variable.") st.stop()client = OpenAI( base_url="https://openrouter.ai/api/v1", api_key=OPENROUTER_API_KEY,)
在上述代码中,st.set_page_config() 用于自定义 Streamlit 应用的页面标题与布局。应用从环境变量中读取 OpenRouter API 密钥,并实例化一个指向 OpenRouter API 端点的 OpenAI 兼容客户端,确保后续的 LLM 调用都能正确路由并为 DeepSeek V3.1 完成认证。
步骤 2.2:辅助函数
在构建主流程前,我们需要稳健的工具函数来处理文档与资源评估。本步骤将定义用于从上传的 PDF 中提取文本、预览文档内容、粗略统计 token 数量,并基于 OpenRouter 的 DeepSeek V3.1 定价估算成本的辅助函数。
def pdf_to_text(uploaded_file): with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_file: tmp_file.write(uploaded_file.read()) tmp_path = tmp_file.name reader = pypdf.PdfReader(tmp_path) text = "" for page in reader.pages: page_text = page.extract_text() if page_text: text += page_text + "\n" return textdef preview_pdf_text(text, max_chars=600): preview = text[:max_chars] if len(text) > max_chars: preview += "\n...\n[Preview truncated]" return previewdef count_tokens(text): return max(1, int(len(text) / 4))def estimate_cost(tokens, mode="input"): if mode == "input": return tokens / 1_000_000 * 0.20 else: return tokens / 1_000_000 * 0.80
有了这些辅助函数,我们的后端已充分准备好支持可扩展的研究助理界面:
- 高效的 PDF 解析:
pdf_to_text()将多页 PDF 处理为纯文本,同时保留页与页之间的边界,使数据更适合作为 LLM 输入与后续处理。 - token 计数与成本估算:
count_tokens()提供大致的 token 数,帮助监控相对于 DeepSeek 高上下文窗口的 API 使用量;estimate_cost()则据此按 OpenRouter 的输入/输出定价将 token 数转换为实时成本反馈,让用户随时了解每次查询的算力预算。 - 预览生成:
preview_pdf_text()生成截断预览,允许用户在产生模型费用或触发 API 限制前,验证提取内容的完整性与相关性。
在这些构件就位后,我们即可组装完整的 Streamlit 应用,实现面向长上下文、具代理能力的论文问答。
步骤 2.3:Streamlit 应用
在具备核心工具后,我们可以组装主界面,将 PDF 处理、token/成本估算、用户驱动的问答,以及通过 OpenRouter 与 DeepSeek V3.1 的实时交互整合起来。
st.header("Research Paper Assistant")pdf_file = st.file_uploader("Upload your research paper (PDF)", type=["pdf"])if "paper_text" not in st.session_state or st.session_state.get("last_uploaded") != pdf_file: if pdf_file is not None: with st.spinner("Extracting text from PDF..."): st.session_state.paper_text = pdf_to_text(pdf_file) st.session_state.last_uploaded = pdf_file st.success(f"PDF uploaded. Total characters extracted: {len(st.session_state.paper_text):,}") with st.expander("Preview of extracted PDF text:"): st.code(preview_pdf_text(st.session_state.paper_text), language='markdown')paper_text = st.session_state.get("paper_text")if paper_text: input_tokens = count_tokens(paper_text) st.caption(f"Estimated input tokens: {input_tokens:,} (Estimated input cost: ${estimate_cost(input_tokens):.3f})") question = st.text_area("Ask a question about this paper:", height=80, placeholder="E.g. What are the main findings?") mode = st.radio( "Select Mode", ["Explain in Brief (Non-Think)", "Explain in Detail (Think)"], horizontal=True, ) go = st.button("Get Answer", use_container_width=True) if question and go: if mode == "Explain in Brief (Non-Think)": prompt = ( f"{paper_text}\n\n" f"Question: {question}\n" "First, answer in a few sentences. Then, quote 1–2 exact sentences from the above paper that best support your answer. " "Show each quote on a new line." ) thinking_flag = False header = "Explain in Brief (Non-Think)" else: prompt = ( f"{paper_text}\n\n" f"Question: {question}\n" "First, answer in detail with reasoning and evidence. Then, quote 2–3 exact sentences from the above paper that most strongly support your answer. " "List the quotes after your answer." ) thinking_flag = True header = "Explain in Detail (Think)" with st.spinner(f"Generating answer..."): start_time = time.perf_counter() try: response = client.chat.completions.create( model="deepseek/deepseek-chat-v3.1", messages=[ {"role": "system", "content": "You are a helpful research assistant."}, {"role": "user", "content": prompt} ], max_tokens=900, extra_body={"thinking": thinking_flag}, ) answer = response.choices[0].message.content.strip() output_tokens = count_tokens(answer) except Exception as e: answer = f"Error: {e}" output_tokens = 0 end_time = time.perf_counter() elapsed_time = end_time - start_time parts = re.split(r"(?:^|\n)(Quotes?:?)", answer, flags=re.IGNORECASE) if len(parts) >= 3: main_answer = parts[0].strip() quotes = parts[2].strip() else: main_answer = answer quotes = None st.markdown(f"### {header}") st.info(f"Time taken: {elapsed_time:.2f} seconds | Output tokens: {output_tokens} (Est. output cost: ${estimate_cost(output_tokens, 'output'):.3f})") st.write(main_answer) if quotes: st.markdown("**Supporting Quotes:**") st.success(quotes)
该 Streamlit 应用实现了一个动态的论文研究助理,使用 DeepSeek V3.1 处理从文档导入到具上下文的 LLM 问答。以下是该应用承担的关键职能:
1. PDF 上传与缓存
用户通过界面上传 PDF 文件,随后:
- 应用检查
st.session_state以判断文件是否为新文件。若是,则提取文本并与上传引用一并缓存进session_state,避免每次交互都重复提取。 - 提取完成后,会预览文档的前约 600 个字符,并显示字符数、估算的输入 token 与成本等统计信息。
2. 用户提问与模式选择
文档加载后,用户可以输入问题,并在非思考与思考模式间选择,界面会针对不同模式调整提示词指令:
- 非思考模式:返回简要答案,并附带 1–2 条来自论文的支持性引文。
- 思考模式:返回详细、以证据为支撑的答案,并附带 2–3 条引文。
3. 提示词工程与 API 调用
当用户点击“Get Answer”时,应用会:
- 构建具丰富上下文的提示词,将论文内容、问题与答复指令一并注入。
- 在 OpenRouter API 请求中设置
thinking参数(extra_body={"thinking": thinking_flag}),确保模型运行在正确的推理模式,而非仅依赖温度控制。 - 测量每次响应的推理时间、输出 token 数与成本,并予以展示以提升透明度。
4. 后处理与展示
解析返回的答案,并在可分离的情况下拆分主体回答与支持性引文。随后在界面中展示答案与引文,突出显示来自原文的精确证据。
如需亲自尝试,将代码保存为 app.py 并运行:
streamlit run app.py在我的实验中,相比简短的“非思考”回答,DeepSeek V3.1 生成详尽的“思考”答案所需时间更长。这是因为更长、更具推理性的输出需要更多计算与时间。
结语
本教程展示了如何使用 DeepSeek V3.1 构建交互式论文研究助理:能够分析长文档,同时提供简明与详细两类回答,并在 Streamlit 应用内实时跟踪成本。如果您希望继续用 DeepSeek 构建项目,推荐查阅我们的关于全新 DeepSeek V3.2-Speciale 的教程。
我是一名 Google Developers 机器学习(生成式 AI)领域的专家、Kaggle 三项专家,以及 Women Techmakers 大使,拥有 3 年以上的技术从业经验。2020 年我共同创办了一家健康科技初创公司,目前在佐治亚理工学院攻读计算机科学硕士,专攻机器学习。
