欢迎光临
我们一直在努力

PaperMind 文献检索 Agent 开发记录:从关键词搜索到自动理解下载意图

摘要

在上一阶段的开发中,我主要完成了 PaperMind 历史阅读功能的优化,包括个人历史库、文献综述持久化、快速回忆、用户个人理解编辑等功能。这个阶段解决的是“用户读过什么、以后如何快速回忆”的问题。

但在继续使用平台时,我发现还有一个很明显的问题:用户并不一定已经拥有论文 PDF。很多时候,用户只是知道自己想找某一类文献,比如“softmax 相关论文”“Transformer ”“大模型幻觉检测方向的论文”,但并不知道应该用什么关键词检索,也不知道哪些论文可以下载 PDF。

因此,本次开发的重点转向了“文献获取入口”的智能化。我希望 PaperMind 不只是一个上传 PDF 后才能使用的平台,而是能够帮助用户完成从“提出需求”到“检索论文”“判断是否可下载”“下载到 PDF 库”的完整流程。

本次开发主要完成了文献检索页面的升级:在原有关键词检索的基础上,新增 PDF 下载库、文献下载按钮,并设计了一个轻量级文献检索 Agent。用户可以通过自然语言告诉系统自己想找什么论文,Agent 会自动识别用户意图,调用后端检索工具,返回相关文献;当用户继续说“下载第 3 篇”或“下载所有能下载的论文”时,Agent 可以继续执行下载动作,把论文保存到本地 PDF 库中。

从开发进度上看,本次功能并不是一次性完成的,而是经历了几天连续的小阶段:先完成文献检索结果的展示,再增加 PDF 下载按钮,然后建立 PDF 库,最后补充自然语言对话入口,让用户可以通过对话触发检索和下载动作。这个过程也比较符合真实项目开发:先保证基础链路可用,再逐步加入智能化能力。

一、为什么要做文献检索 Agent

原来的 PaperMind 更偏向于“阅读已有文献”。用户需要先手动准备 PDF,然后上传到平台中,系统才能进行解析、深度阅读、问答、综述生成等操作。

这个流程虽然可以使用,但存在一个前置门槛:用户必须先自己找到论文 PDF。

在真实的论文阅读场景中,这个步骤其实并不轻松。尤其是刚进入一个方向时,用户往往只知道一个大概主题,例如:

我想找 softmax 相关的论文;
我想找 Transformer 的经典论文;
我想找大模型幻觉检测方向的论文;
我需要几篇能下载的综述类文献。

如果平台只能提供一个普通搜索框,那么用户仍然需要自己思考关键词、判断论文是否相关、点开网页查看是否有 PDF,再手动下载保存。这个过程和 PaperMind 的智能阅读定位并不完全匹配。

所以我认为文献检索功能需要进一步升级:

1. 用户可以直接用自然语言表达需求;
2. 系统能够自动提取检索关键词;
3. 系统能够调用检索工具查找论文;
4. 系统能够判断哪些论文可能存在 PDF;
5. 用户可以让系统执行下载动作;
6. 下载后的论文进入统一的 PDF 库;
7. PDF 库中的论文可以继续进入解析和阅读流程。

这样一来,平台就不只是“读论文”,而是逐渐接近一个完整的学术阅读助手。

我个人理解,这个功能的意义不只是“多了一个下载按钮”,而是把平台的使用入口往前移动了一步。以前 PaperMind 的起点是“我已经有 PDF”,现在的起点可以变成“我有一个研究兴趣”。这对于学术阅读平台来说是比较关键的,因为很多用户真正困难的地方不是打开 PDF,而是从大量论文中找到值得读的那几篇。

二、技术选型

在实现之前,我也参考了 CSDN 上一些关于 Agent、工具调用、FastAPI 后端服务和前端交互设计的文章,同时也通过询问 AI 对比了几种实现方式。

最开始可以考虑三种方案。

第一种是只做普通关键词搜索。用户输入关键词,后端调用检索接口,前端展示结果。这种方式实现最简单,但智能化程度不够,用户仍然需要自己判断怎么搜。

第二种是把整个流程完全接入 LangGraph,把“理解意图、检索文献、判断 PDF、执行下载”全部做成图节点。这种方案结构更完整,也更像正式 Agent,但是对当前项目来说改动比较大,而且文献检索功能还在快速迭代阶段,如果一开始就重构成复杂图结构,调试成本会比较高。

第三种是先做轻量级工具调用式 Agent。也就是保留现有 FastAPI 路由结构,在文献检索页面新增一个 AI 对话入口,由 AI 负责理解用户意图,再由后端执行具体工具函数,例如 search、download_one、download_all 等。

最后我选择了第三种方式。

原因是当前阶段我们更需要能演示、能跑通、能体现智能动作,而不是一开始就追求过重的架构。轻量级 Agent 可以很好地满足目前需求:

保留原有检索接口,不破坏已有功能;
新增 AI 意图识别层,体现智能化;
工具调用动作清晰,方便演示;
后续如果需要接入 LangGraph,也可以把这些工具函数封装为图节点;
对前端改动较小,适合快速迭代。

这次开发让我更明确了一点:不是所有 AI 功能都必须一开始就做成复杂 Agent 框架。先把用户路径跑通,再逐步工程化,往往更适合课程项目和原型系统。

从技术进度角度看,这一版属于“轻量 Agent 雏形”:

1. 已经具备自然语言意图识别;
2. 已经能把用户意图映射到后端工具动作;
3. 已经能执行检索和下载;
4. 已经能把下载结果落到本地 PDF 库;
5. 还没有完全接入 LangGraph 图结构;
6. 对动态网页和强反爬网站的 PDF 获取能力仍然有限。

所以它不是最终形态,但已经具备了 Agent 功能最核心的部分:理解用户需求,然后调用工具改变系统状态。

三、整体功能设计

本次文献检索 Agent 主要围绕两个页面展开。

第一个是文献检索页面。用户可以像以前一样输入关键词搜索论文,也可以在新增的 AI 对话框中直接表达需求。

第二个是 PDF 库页面。用户下载的论文会保存到本地 PDF 库中,后续可以从这里继续载入解析流程。

整体流程可以理解为:

用户自然语言输入
AI 判断用户意图
调用文献检索工具
返回论文列表

 用户选择下载
调用 PDF 下载工具
保存到 PDF 库
后续进入文献解析和阅读

在这个流程中,最重要的是让 AI 不只是“回答文本”,而是真的能触发动作。

例如用户输入:

> 帮我找几篇 softmax 相关的论文。

Agent 不应该只回答“softmax 是什么”,而应该识别这是一个检索意图,然后调用检索接口。

用户继续输入:

> 下载第 2 篇。

Agent 也不应该只说“好的,已为你下载”,而应该根据上一轮检索结果找到第 2 篇文献,调用下载接口,并返回真实的下载结果。

这就是本次功能和普通聊天框最大的区别:它具备工具调用动作。

为了让这个流程更容易维护,我把它理解成三层:

自然语言层:理解用户说了什么
工具调度层:决定调用 search / download_one / download_all
工程执行层:真正请求接口、下载文件、写入 PDF 库

这三层不能混在一起。如果完全让 AI 自己“想办法下载”,系统就会变得不可控;如果完全不用 AI,只做按钮和关键词搜索,又体现不出智能化。因此这一版采用的是比较折中的设计:AI 做意图识别,后端工具做确定性执行。

四、后端实现思路

后端主要新增了三类能力。

第一类是文献检索能力。系统根据关键词调用已有检索逻辑,返回论文标题、作者、年份、来源链接、摘要和可能的 PDF 链接。

第二类是 PDF 发现能力。因为很多论文检索结果本身并不会直接给出 PDF 链接,所以后端需要进一步访问论文详情页,尝试从页面中寻找 PDF 下载入口。

第三类是 PDF 下载与保存能力。找到可下载 PDF 后,系统会把文件保存到本地 PDF 库,并记录基本信息,方便前端展示和后续解析。

为了让 Agent 可以调用这些动作,后端将用户意图抽象成几种类型:

action = "search"        检索论文
action = "download_one"  下载某一篇
action = "download_all"  下载所有可下载论文
action = "clarify"       需求不清晰,需要追问

这里并没有让 AI 直接操作文件系统,而是让 AI 只负责判断“用户想做什么”,真正的下载、保存、校验都由后端确定性代码完成。

实际实现时,后端可以把 AI 返回的结构控制成 JSON,方便程序继续处理:

{
"action": "search",
"query": "softmax neural network paper",
"index": None
}

如果用户说“下载第 2 篇”,则可以解析成:

{
"action": "download_one",
"query": None,
"index": 2
}

这里代码不需要很多,但思路很关键:让 AI 输出结构化结果,而不是输出一大段自然语言。结构化结果更适合被程序消费,也方便后续接入 LangGraph 或任务队列。

一个简化后的工具调度逻辑可以写成这样:

if intent["action"] == "search":
papers = search_papers(intent["query"])
elif intent["action"] == "download_one":
result = download_paper(last_results[intent["index"] – 1])
elif intent["action"] == "download_all":
result = download_all_available(last_results)
else:
result = {"message": "请补充你想检索的主题或要下载的序号"}

这段代码体现了本次功能最核心的思路:AI 不是替代后端逻辑,而是把用户语言转换成后端能够执行的动作。

我认为这个设计非常重要。

AI 适合处理自然语言理解,比如用户说“帮我找几篇 softmax 的文献”,AI 可以提取出关键词 softmax;用户说“下载刚才检索出来的所有能下载的”,AI 可以判断这是 download_all。

但是 AI 不应该直接决定文件保存路径,也不应该绕过后端校验直接写文件。真正涉及数据保存和系统状态变化的操作,必须由后端代码控制。

这也是我对agent的一个理解:AI 负责理解意图,代码负责执行动作。

五、PDF 下载为什么比想象中复杂

一开始我以为 PDF 下载会很简单:检索结果里有 PDF 链接,就显示下载按钮;没有 PDF 链接,就显示无 PDF。

但实际测试时发现,很多文献明明点开网页可以下载 PDF,可是检索结果中却没有直接提供 PDF 地址。

原因主要有几个。

第一,有些网站把 PDF 链接藏在详情页中。检索接口只返回论文页面地址,真正的 PDF 按钮需要进入页面后才能发现。

第二,不同网站的 PDF 按钮命名不统一。有的叫 PDF,有的叫 Download,有的叫 Full Text,有的甚至是法语或其他语言。

第三,有些 PDF 地址不是以 `.pdf` 结尾,而是通过动态链接返回 PDF 文件。

第四,有些网页有反爬、JS 渲染或权限限制,后端普通请求无法像浏览器一样完整访问页面。

因此本次实现没有只判断链接是否以 .pdf 结尾,而是加入了更通用的发现逻辑:

1. 先检查检索结果是否自带 PDF 链接;
2. 如果没有,则访问论文详情页;
3. 在详情页中查找 PDF、Download、Full Text 等相关链接;
4. 对候选链接发送请求;
5. 根据响应头或文件开头判断是否是真正 PDF;
6. 如果确认是 PDF,再允许下载。

必要的代码思想可以简化成下面这样:

def is_pdf_response(response):
content_type = response.headers.get("content-type", "").lower()
return "application/pdf" in content_type or response.content.startswith(b"%PDF")

这段代码说明了一个问题:判断 PDF 不能只看 URL 后缀。有些下载链接可能是 `/download?id=123`,它并不以 `.pdf` 结尾,但返回内容确实是 PDF 文件。所以更可靠的方式是检查响应头和文件内容。

保存到 PDF 库时,也需要做文件名清洗,避免论文标题里出现不适合作为文件名的字符:

safe_title = re.sub(r'[\\\\/:*?"<>|]+', "_", title).strip()
filename = f"{safe_title[:80]}.pdf"

这类代码虽然很小,但属于真实工程里必须处理的细节。如果不处理,用户下载一篇标题带特殊字符的论文时,就可能在 Windows 文件系统下保存失败。

这种方式比简单字符串判断更可靠,也更符合真实网站环境。

但是它仍然不是万能的。如果网站必须通过浏览器 JS 渲染、登录权限、验证码或强反爬机制才能下载 PDF,那么普通后端请求仍然可能失败。这个问题不是代码写错,而是下载环境本身有限制。

我个人对这部分的理解是:文献下载不是单纯的“拿一个链接”,而是一个网页解析、资源发现、文件校验和异常处理组合起来的过程。用户看到的是一个下载按钮,但背后其实有很多不确定因素。

六、前端交互设计

前端这次主要做了两个变化。

第一个是在文献检索结果旁边增加下载按钮。如果系统判断某篇论文存在可下载 PDF,用户可以直接点击下载,论文会保存到 PDF 库中。

第二个是在文献检索页增加 AI 对话框。用户可以不输入关键词,而是直接告诉系统需求。

例如:我想找几篇关于 Transformer 的经典论文。

系统会自动识别为检索任务,并在页面中展示结果。

如果用户继续输入:

下载第 1 篇。

系统会基于当前检索结果执行下载,而不是重新检索。

这种交互让页面从“搜索工具”变成了“带动作能力的文献助手”。

前端调用后端 Agent 接口时,逻辑可以非常简单:

前端不需要自己判断用户到底是要搜索还是下载,而是把当前上下文一起交给后端。后端根据用户输入和当前检索结果,决定下一步动作。

同时,为了避免用户误解,我认为前端必须清楚展示每一步状态:

 正在理解需求;
正在检索文献;
找到多少篇结果;
哪些文献可能可以下载;
下载成功还是失败;
失败原因是什么;
下载后的文件在哪里查看。

尤其是下载失败时,不能只显示“失败”,而应该告诉用户可能原因,比如链接不可访问、不是 PDF、网站限制、远程服务器超时等。

这也是我觉得前端设计里比较重要的一点:Agent 的过程不能完全黑盒化。用户需要知道系统正在做什么,否则一旦失败,就会觉得“AI 不靠谱”。如果能把“检索中、发现 PDF、正在下载、下载失败原因”展示出来,用户对系统的容错感会更高。

七、开发过程中遇到的问题

这次开发中最明显的问题是:用户对“能不能下载”的判断和系统对“能不能下载”的判断并不完全一样。

用户在浏览器中点开网页,看到右侧有 PDF 按钮,就会认为“这篇论文可以下载”。但是后端程序访问页面时,可能拿不到同样的内容。

这背后其实涉及两个环境差异:

浏览器访问网页时,可以加载 JS、图片、Cookie、跳转和动态按钮;

后端请求网页时,通常只能拿到静态 HTML,遇到 JS 渲染页面就可能看不到按钮。

所以我一开始问“为什么明明网页有 PDF,系统还显示无 PDF”时,其实暴露的是一个真实工程问题:浏览器看到的页面,不一定等于后端请求拿到的页面。

针对这个问题,后续可以继续优化,例如:

1. 引入浏览器自动化工具访问详情页;
2. 对常见学术网站增加适配规则;
3. 保存失败页面用于调试;
4. 对 PDF 链接发现过程增加日志;
5. 对无法下载的情况给出更明确提示。

但在当前阶段,我们先完成了通用 PDF 发现和下载能力,让大部分静态可访问 PDF 能够进入 PDF 库。

本次功能的技术进度可以总结为:

模块当前进度后续优化
普通关键词检索 已完成 可继续优化排序和摘要展示
AI 意图识别 已完成基础版 后续可接入更严格的结构化输出
下载单篇论文 已完成 可增强失败重试
下载所有可下载论文 已完成基础版 可增加任务队列和进度条
PDF 库 已完成基础展示 可增加分类、删除、载入解析
PDF 链接发现 已完成通用静态解析 可加入浏览器自动化
LangGraph 接入 暂未接入 后续可把工具封装为图节点

这个表格也说明了我对当前功能定位的理解:它已经可以用于演示和基础使用,但还不是最终版本。它解决了“有没有 Agent 动作”的问题,下一步才是解决“Agent 是否足够稳定、是否足够工程化”的问题。

 八、本次 Vibecoding 的提示词整理

1. 项目理解与功能评估提示词

你是一名熟悉 FastAPI、Vue、学术论文检索系统和 AI Agent 工具调用的全栈开发专家。

请先阅读当前 PaperMind 项目,重点分析:

1. 文献检索功能的前后端实现;
2. 论文搜索接口的数据来源和返回字段;
3. 前端文献检索页面的展示逻辑;
4. 当前是否已有 PDF 下载、保存和解析入口;
5. 哪些功能可以复用,哪些需要新增。

在没有理解现有项目结构前,不要直接重构。请先给出功能评估和实现计划。

 2. PDF 库与下载按钮开发提示词

请为当前项目新增一个 PDF 库功能。

要求:

1. 在本地项目中建立统一 PDF 保存目录;
2. 为每篇检索出来的文献增加下载按钮;
3. 点击下载后,后端尝试获取 PDF 文件并保存到 PDF 库;
4. 下载成功后返回文件名、保存路径和论文基本信息;
5. 下载失败时返回明确原因;
6. 前端新增 PDF 库页面,可以展示已下载论文;
7. PDF 库中的论文后续可以进入文献解析流程;
8. 不要影响原有文献检索和阅读功能。

3. 文献检索 Agent 开发提示词

你是一名 AI Agent 应用开发专家,同时熟悉学术搜索、工具调用和后端接口设计。

请在文献检索页面新增一个 AI 对话入口,使用户可以用自然语言表达文献需求。

功能要求:

1. 用户输入自然语言,例如“帮我找几篇 softmax 相关论文”;
2. AI 自动识别检索关键词和用户意图;
3. 如果是检索意图,调用后端文献检索工具;
4. 如果用户说“下载第几篇”,则调用下载工具;
5. 如果用户说“下载所有能下载的”,则批量下载当前检索结果中可下载的论文;
6. 如果需求不明确,则向用户追问;
7. AI 只负责意图识别,不直接操作文件;
8. 所有下载、保存、校验逻辑必须由后端确定性代码完成。

4. PDF 链接发现优化提示词

当前系统不能只根据检索结果中是否存在 PDF 字段判断能否下载。

请优化 PDF 发现逻辑:

1. 如果检索结果自带 PDF 链接,优先使用;
2. 如果没有 PDF 链接,则访问论文详情页;
3. 从详情页中识别 PDF、Download、Full Text 等相关链接;
4. 对候选链接进行验证;
5. 通过 Content-Type 或文件头判断是否是真正 PDF;
6. 不要只依赖 `.pdf` 后缀;
7. 对无法访问、非 PDF、超时、权限限制等情况返回明确错误信息;
8. 保持逻辑尽量通用,不要只针对某一个固定网站硬编码。

5. 工程边界提示词

请注意,本功能当前先采用轻量级工具调用式 Agent 实现,不强制接入 LangGraph。

设计原则:

1. AI 负责理解用户自然语言意图;
2. 后端工具函数负责执行检索和下载;
3. 前端负责展示状态和结果;
4. 文件保存必须由后端控制;
5. 失败原因必须明确返回;

以上只是和ai交互的部分提示词,ai使用的是codex 中的chatgpt5.5

效果展示如下:

我们对ai发起对话,点击下载就可以成功下载到本地存储的PDF库,并在本地PDF库中可以加入解析

赞(0)
未经允许不得转载:171主机测评 » PaperMind 文献检索 Agent 开发记录:从关键词搜索到自动理解下载意图
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址