AI科研idea生成:从模糊兴趣到可判定问题的四步流水线

发布时间:2026/10/25 2:20:11
AI科研idea生成:从模糊兴趣到可判定问题的四步流水线

博一上学期最难熬的时刻,往往不是实验跑不出结果,而是组会上导师问“你最近在想什么问题”,你只能把上周读过的三篇论文的方法复述一遍,然后补一句“我再去看看”。这个场景说明的问题,比“读得不够多”更严重:你没有自己的问题,只有别人的答案。

这两年在科研圈里,用 AI 帮忙找 idea 已经从“偷偷试”变成“公开讨论”。但大多数人用完之后的真实感受是:生成得很快,能用得很少。你让它想创新点,它给你的多半是“将 A 方法与 B 场景结合”,读起来像综述的最后一段,正确、平滑、毫无信息增量。于是很多人得出一个结论:AI 根本不会产生 idea。

我的判断正好相反,但需要加一个限定:AI 现在的水平,不足以替你产生好 idea,但它能把从模糊兴趣到可判定问题的这段路,压缩到你以前不敢想的速度。真正被它改变的是验证成本,而不是灵感本身。过去你需要两周读文献才能确认“这个想法是不是已经有人做了”,现在可能半天就能得到一个初步判断。

这意味着 idea 生产的分工需要重排。以前你把 80% 的时间花在信息搬运和文献确认上,20% 花在真正的思考上;现在反过来了,搬运和确认的成本被压到极低,剩下的时间能不能产生好问题,取决于你自己有没有可用的真实素材。

这篇内容不聊提示词玄学,也不吹某个模型多神。我会把“用 AI 产生好 idea”拆成一条可复用的流水线:先说清楚 AI 该站在哪一环,再讲三种最常见的失败模式,然后给出四步方法、可以直接复制改用的提示词模板、两段能跑起来的 Python 脚本,最后补上验证判据、排错清单和数据安全边界。如果你正在读研、准备开题,或者带学生做课题,这套流程可以直接拿去用。

1. 先说结论:AI 在 idea 生产链里的正确位置

要判断 AI 有没有用,得先把“产生 idea”这件事拆开。它不是一个动作,而是一条链,链上每一环的能力要求完全不同。

环节具体做什么AI 的当前能力人不可替代的部分
问题感知发现某个现象不对劲、某个指标异常、某个流程别扭弱你在现场、在数据里、在实验台前的直接经验
假设生成把模糊的疑惑转成可检验的猜想强判断哪个猜想值得花半年
快速证伪检索是否已有工作、找最可能被反驳的点强判断反驳是否致命
表达与落地写成问题陈述、实验设计、图表结构中讲清楚为什么这个问题重要

看这张表能得出一个很实用的结论:AI 在第二环和第三环是碾压式的,在第一环几乎帮不上忙,在第四环只能做个粗糙的初稿机。

而绝大多数人踩的坑是:他们把第一环也外包给了 AI。打开对话框输入“帮我在这几个方向里找找有什么可做的”,然后期待一个惊喜。这不是 AI 不行,是你让它做了它天然做不到的事。模型的训练目标是拟合人类已有的文本分布,它最擅长的插值和归纳,最不擅长的是“从没有文本记录的地方发现问题”。

反过来看,如果你手上有真实素材——一组复现不出来的实验结果、一次组会上被质疑的点、一个工业界朋友抱怨的具体麻烦——把这些东西喂给 AI,它的输出质量会立刻不一样。因为它不再是凭空插值,而是在一个有约束的空间里做组合。

所以本文的核心方法可以浓缩成一句话:好 idea 的数量,取决于你喂给模型什么,而不是你问模型什么。后面所有的提示词和脚本,都是在为这句话服务。

2. 为什么大多数人用 AI 想不出好 idea:三种典型失败模式

在给方法之前,先把失败案例摊开看。这三种模式几乎覆盖了我在各种讨论里见到的大部分情况,认出来之后改起来很快。

2.1 把 AI 当搜索引擎:问“这个方向有什么新进展”

典型提问是这样的:“图神经网络最近有什么值得做的方向?”模型的回答通常是:效率优化、可解释性、跨域迁移、与大模型结合。四平八稳,看起来挺全,但你读完什么也没得到。

原因很简单:这类问题问的是分布的中心,而中心区域是所有综述都写过的内容。模型给你的是统计意义上的高频答案,而高频答案在科研里恰恰是最没有价值的那部分。

改法是把“有什么”换成“如果”。不要问“有什么新进展”,要问“如果过平滑问题的本质是层间信息混淆,那么有哪些现有方法其实是在隐式地做解耦?这些方法在什么条件下会失效?”前者求清单,后者求推理。求清单得到的是百科,求推理得到的才是可能被验证的猜想。

这也是我在实践中感受最深的一点:提问里带一个明确的假设,输出质量立刻上一个台阶。因为假设本身给了模型一个搜索方向,它不用再在整片分布里漫游。

2.2 把 AI 当许愿池:一句“帮我想个创新点”

这类提问的问题在于完全没有约束。没有约束的情况下,模型只能给你“缝合式创新”:把两个热门词拼在一起,比如“用对比学习解决冷启动”,听起来像个题目,实际上没有任何可检验的内容。

更麻烦的是,这类输出会让你产生一种“我好像有想法了”的错觉。你把它记在笔记里,两周后再看,会发现它连一个能跑的实验都设计不出来。

有效的约束至少包括四类:数据条件(你有什么数据、多大规模、标注质量如何)、算力条件(单卡还是多卡、能跑多久)、时间条件(三个月能做完什么)、评价条件(什么结果算成功、什么结果算失败)。把这四类写进提示词,模型的输出会立刻从“综述段”变成“方案段”。

我在帮人改提示词时经常用一个检验方法:把 AI 的输出拿给同组的人看,如果对方第一反应是“这个我知道”,说明约束不够;如果对方第一反应是“这个怎么做”,说明约束到位了。

2.3 没有判据:分不清“新”和“好”

这是最隐性的问题。“新”是一个相对概念,只要换个数据集、换个指标,任何工作都能说自己新。“好”是完全不同的东西,它至少包含三个维度:有人在乎(问题本身有价值)、可证伪(能设计出否定的实验)、做得完(在你的资源条件下可完成)。

大部分 AI 生成的 idea 只满足第一个维度的一部分,也就是“看起来没被人做过”。但它们既不可证伪,也做不完。

解决办法是提前把判据写出来,让模型在生成的同时自我打分。这一点在后面的示例二里会具体实现:不是让模型自由发挥,而是让它先发散、再被“审稿人”攻击、最后按固定维度打分。判据前置,是从“生成一堆”到“筛出几个”的关键一步。

3. 核心方法:约束、发散、证伪、收敛四步

把上面三种失败模式反过来,就得到一条四步流水线。这条流水线的好处是每一步都有明确的输入输出,可以单独优化,也可以单独替换模型。

步骤目标AI 参与方式你的动作
约束把研究方向翻译成可判定陈述追问、补全、检查可测量性提供真实素材和边界条件
发散扩大候选空间,逼出非常规组合多角色并行、类比迁移注入分布外的异常和抱怨
证伪用最低成本杀掉站不住的想法扮演严苛审稿人判断反驳是否致命
收敛从候选里挑出值得投入的按维度打分、整理台账设置冷却期,两周后回看

3.1 约束:把“我想做 X”变成“如果 Y,那么 Z”

约束这一步的目标只有一个:让你的问题具备可测量性。判断标准很朴素,如果你的问题陈述里出现了“提升”“优化”“探索”“增强”这类动词,而后面没有跟一个具体的可观测指标,那它就还不是一个研究问题。

一个合格的陈述长这样:“在标注率低于 5% 的节点分类任务上,如果把邻接矩阵的谱范数作为正则项加入训练目标,那么在多数类与少数类的准确率差距上,应该比现有方法缩小至少 3 个百分点。”这里面有对象、有干预、有指标、有阈值,也就有了证伪的可能。

这一步最适合让 AI 来做,因为它是纯逻辑检查,不需要领域直觉。你可以把自己的模糊想法丢给它,让它逐条检查:这个陈述里的因变量是什么?能不能测?如果测出来不符合预期,算不算这个想法错了?

3.2 发散:真正有效的不是多问几次,而是换视角

很多人理解的“发散”就是同一个问题多生成几遍。效果很差,因为同一个角色、同一个上下文,输出的方差主要来自采样温度,内容本质上是同质的。

真正有效的发散是换视角。我在实践中会固定用四类角色:综述型研究者(擅长把散落工作归成路线)、工程实现者(只关心能不能跑起来)、严苛审稿人(先问“这和已有工作的差别在哪”)、隔壁方向的外来者(会把自己领域的工具类比过来)。

第四个角色往往最有价值。跨领域类比是产生非显然想法的常用路径,但前提是必须同时说明类比在哪里失效,否则就会变成“把 A 套到 B 上”的空话。

另一个提高发散质量的手段是分布外注入。你可以往上下文里塞一些模型训练数据里不可能有的东西:你自己实验里的异常曲线、组会上老师的一句质疑、实习时业务方的一句抱怨。这些东西是独属于你的信息,模型无法从公开文本里学到,因此它围绕这些素材做的组合,天然就带有一定的独特性。

3.3 证伪:先假设它是错的,再找证据

这一步是整个流程里投入产出比最高的,也是最容易被跳过的。人的天性是喜欢自己的想法,一旦有了一个听起来不错的点子,就会不自觉地去寻找支持它的证据。AI 可以帮你对抗这个倾向。

具体做法是让模型扮演一个不客气的审稿人,专门做三件事:找出这个想法最像哪一类已有工作、指出最可能被反驳的那一句话、判断如果只能做一个最小实验应该先做哪个。

其中第二件事最关键。“最可能被反驳的那一句话”往往就是你这个想法的真正弱点所在。如果这句话你能答上来,想法就站得住;答不上来,早点放弃比做到一半放弃成本低得多。

需要提醒的是,模型找的“已有工作”经常是模糊的、甚至是编造的。所以这一步的正确用法是把它当线索而不是当结论:它说“这很像某某思路”,你就去检索这个思路的关键词,用真实的文献去核实。

3.4 收敛:打分和冷却

收敛要有明确规则,否则你会陷入“每个都还行”的状态。我的做法是固定五个维度打分,每个维度 1 到 5 分:新颖性(和已知工作的差别有多大)、可行性(现有资源能否完成)、验证成本(最快多久能拿到第一个信号)、数据可得性(数据是否真的能拿到)、价值密度(如果结论成立,谁会关心)。

五个维度里,我会给“验证成本”和“数据可得性”更高的权重。原因很现实:博一阶段最稀缺的不是聪明想法,而是能快速拿到反馈的机会。一个中等新颖但两周能出结果的想法,价值远高于一个非常新颖但要半年才知道行不行的想法。

另外一个被低估的动作是冷却期。把候选 idea 写进台账,两周之后再回来看。很多当时觉得惊艳的想法,两周后你会觉得索然无味。这个过滤机制非常有效,因为它筛掉的不是想法本身,而是你当时的情绪。

4. 环境准备:搭一套最小可用的 AI 科研工作台

不需要复杂的基础设施,一套能在笔记本上跑起来的最小工作台就够用了。版本号请以你实际项目里的为准,本文重点演示通用思路,不绑定具体版本。

4.1 硬件与模型

硬件方面,一台能跑浏览器和 Python 的普通笔记本就够了。只有当你需要本地部署模型或者做嵌入计算时,才需要考虑显卡。

模型方面,建议准备两类:一类是通用对话模型,用来做推理、改写、评审;另一类是长上下文模型,用来一次性读进多篇论文。如果你的单位提供了内部的模型接口,优先用内部接口,数据合规上更省心。

4.2 目录结构与依赖

科研场景最怕文件散落。建议从一开始就固定目录结构,把“原始文献”“笔记”“给模型的输入”分开放:

# 在项目根目录执行 mkdir -p papers notes exports tools configs touch notes/idea_ledger.md
  • papers/:存放 PDF 原文,只读,不改名。
  • notes/:想法台账、组会记录、异常现象记录。
  • exports/:准备喂给模型的脱敏副本,和原始文献物理隔离。
  • tools/:检索、发散、评审的脚本。
  • configs/:接口配置,绝不提交到公开仓库。

依赖安装只需要两步,先建虚拟环境再装包:

python -m venv .venv source .venv/bin/activate # Windows 用 .venv\Scripts\activate pip install -U openai pypdf

接口密钥不要写死在代码里,用环境变量。新建一个.env.example作为模板,真正的.env加进.gitignore:

# 文件路径:.env.example LLM_API_KEY=your-key-here LLM_BASE_URL=https://your-endpoint/v1 LLM_MODEL=your-model-name

4.3 一条必须提前说清楚的红线

在把任何材料交给模型之前,先做一次分类:哪些是已经公开发表的,哪些是未发表数据、实验结果、合作方提供的资料、涉及个人隐私的信息。

公开发表的论文,可以放心处理。未发表的数据、合作方的商业信息、涉及人的隐私数据,一律不要上传到公网接口。如果确实需要用模型处理,走单位内部的合规接口,或者先在本地做脱敏,把能标识来源的字段全部去掉。

这条线不是形式主义。科研数据泄露的后果,往往不是“被抄袭”那么简单,而是直接违反数据使用协议,影响整个课题组的后续合作。

5. 示例一:用结构化提示词把模糊兴趣改成可判定问题

这是四步法里“约束”那一步的具体实现。它的作用是把你脑子里那团模糊的东西,逼成一个能被检验的句子。

5.1 提示词模板

下面这个模板可以直接复制,把方括号里的内容替换掉就行。注意它不是“让模型想 idea”,而是“让模型帮你把话说清楚”,目标完全不同。

# 角色 你是一位在【研究方向】深耕多年的研究者,熟悉该方向主流期刊和会议的审稿标准, 说话克制,不做没有依据的预测。 # 任务 把我下面这段模糊的研究兴趣,改写成 3 个“可判定”的研究问题陈述。 # 约束 1. 每个陈述必须包含四要素:研究对象 + 干预或变量 + 可观测指标 + 判定条件。 2. 禁止使用“提升”“优化”“探索”“赋能”“增强”这类无法测量的动词, 除非后面紧跟一个具体的、可量化的指标。 3. 不得编造具体数据、文献标题、作者姓名或发表年份。 4. 如果你认为我的输入缺少关键信息,请先列出 3 个你必须追问的问题,再给草稿。 5. 如果某个陈述你自己也觉得站不住,直接标注【弱】并说明原因。 # 输出格式 不要寒暄,按以下结构输出: 【问题陈述 1】 - 一句话陈述: - 自变量: - 因变量(可观测指标): - 证伪条件(出现什么结果说明这个想法是错的): - 最小验证实验(数据、算力、预计周期): - 风险标注:【强】或【弱】+ 原因 【问题陈述 2】 (同上) 【问题陈述 3】 (同上) 【必须追问的问题】 1. 2. 3. # 输入 【在这里粘贴你的一句话兴趣,例如:我想看看图神经网络在小样本节点分类上还能不能改】

这个模板里有几个设计值得单独说。第一,要求输出“证伪条件”,这是把伪问题筛掉的利器,因为伪问题往往写不出证伪条件。第二,要求标注【弱】,等于给了模型一个诚实的出口,它会因此少说一些场面话。第三,要求先追问再给草稿,这一条能显著减少“基于错误前提生成的漂亮废话”。

5.2 一次典型的输入输出

假设你的输入是“我想看看图神经网络在小样本节点分类上还能不能改进”,一个好的输出应该长这样:

【问题陈述 1】

  • 一句话陈述:在每类仅 3 个标注节点的设置下,若在训练目标中加入邻接矩阵谱范数的上界约束,则少数类的 F1 相比基线应提升不少于 2 个百分点。
  • 自变量:正则项系数 λ,取值范围 {0, 0.01, 0.05, 0.1}。
  • 因变量:少数类 F1、整体准确率、训练稳定性(5 次随机种子的标准差)。
  • 证伪条件:λ 从 0 增加到 0.1 时,少数类 F1 变化小于 1 个百分点,或整体准确率下降超过 3 个百分点。
  • 最小验证实验:3 个公开小样本数据集,单卡即可,预计 3 到 5 天。
  • 风险标注:【强】,因为干预明确、指标清晰、失败也有解释空间。

对比一下原始输入和这个输出,差别不在于想法变高级了,而在于它变得可以动手了。这就是“约束”这一步的全部价值。

5.3 这一步最容易做错的地方

最常见的错误是输入太抽象。“我想做多模态”“我对大模型的可解释性感兴趣”,这类输入无论模板多好,输出都会是空话。因为模型没有素材,只能拿通用知识填空。

第二个错误是不接受追问。模板里让模型先问三个问题,很多人直接跳过,继续要答案。这等于放弃了最有价值的一轮对话,因为那三个问题往往正好指出了你思考里的空白。

第三个错误是把输出直接当成结论用。它只是草稿,里面每一句关于“已有工作”的描述都需要你自己去核实。

6. 示例二:多角色发散 + 对抗评审的可运行脚本

手工复制粘贴也能做,但效率低。这一节给一个能跑的脚本,把“发散”和“证伪”两步自动化:四个角色并行生成候选,每个候选再被审稿人角色攻击一遍,最后按分数排序输出。

6.1 完整代码

# 文件路径:tools/idea_loop.py """多角色发散 + 对抗评审:一次跑出若干候选,再筛掉缝合式想法。""" import json import os from concurrent.futures import ThreadPoolExecutor from openai import OpenAI client = OpenAI( api_key=os.environ["LLM_API_KEY"], base_url=os.environ.get("LLM_BASE_URL", "https://api.openai.com/v1"), ) MODEL = os.environ["LLM_MODEL"] ROLES = { "surveyor": "你是该方向的综述型研究者,擅长把散落的工作归成几条技术路线," "说话克制,不做没有依据的预测。", "builder": "你是工程实现者,只关心方法能不能在有限算力和有限数据下跑起来," "会主动指出实现上的死穴。", "reviewer2": "你是以严苛著称的审稿人,习惯先问“这和已有工作的差别到底在哪”," "并直接给出最可能被拒的理由。", "outsider": "你是隔壁方向的研究者,会把自己领域成熟的工具类比过来," "但必须说明这个类比在哪里会失效。", } def chat(system: str, user: str, temperature: float = 0.8) -> str: resp = client.chat.completions.create( model=MODEL, temperature=temperature, messages=[ {"role": "system", "content": system}, {"role": "user", "content": user}, ], ) return resp.choices[0].message.content.strip() def diverge(brief: str, role: str) -> dict: user = f"""# 研究背景与约束 {brief} # 你的任务 以你的视角提出 2 个候选研究方向。每个方向必须写清楚: 1. 一句话主张,格式为“如果……那么……” 2. 它和已有工作最可能的重叠点在哪里 3. 最小验证实验需要什么数据、多少算力、大概多久 4. 如果结论为负,这个负结果本身有没有价值 不要写客套话,不要编造文献标题和作者。""" return {"role": role, "text": chat(ROLES[role], user)} def critique(brief: str, candidate: str) -> str: user = f"""# 研究背景 {brief} # 候选方向 {candidate} # 任务 请以审稿人视角回答三件事: 1. 这个方向最像哪一类已有工作,描述思路即可,不要编造具体论文标题和作者 2. 最可能被反驳的一句话是什么 3. 如果只能做一个最小实验,你会先做哪个,为什么 最后给出 1 到 10 的分数,并单独一行输出 SCORE=<数字>。""" return chat(ROLES["reviewer2"], user, temperature=0.3) def parse_score(text: str) -> float: for line in text.splitlines(): if line.strip().upper().startswith("SCORE="): try: return float(line.split("=", 1)[1].strip()) except ValueError: return 0.0 return 0.0 def main() -> None: brief = os.environ.get( "BRIEF", "方向:图神经网络在稀疏标签场景下的过平滑问题。" "数据:3 个公开引文数据集,单卡 24G。时间:3 个月。", ) with ThreadPoolExecutor(max_workers=len(ROLES)) as pool: drafts = list(pool.map(lambda r: diverge(brief, r), ROLES)) results = [] for draft in drafts: review = critique(brief, draft["text"]) results.append({**draft, "review": review, "score": parse_score(review)}) results.sort(key=lambda x: x["score"], reverse=True) with open("idea_candidates.json", "w", encoding="utf-8") as f: json.dump(results, f, ensure_ascii=False, indent=2) for item in results: print(f"[{item['score']:.1f}] 角色={item['role']}") print(item["text"][:200].replace("\n", " ")) print("-" * 60) if __name__ == "__main__": main()

6.2 运行方式

export LLM_API_KEY="your-key-here" export LLM_BASE_URL="https://your-endpoint/v1" export LLM_MODEL="your-model-name" python tools/idea_loop.py

跑完之后会在当前目录生成idea_candidates.json,同时在终端按分数从高到低打印摘要。预期看到的形态是:四个角色各出一段,每段包含两条主张,后面跟着审稿人意见和一个分数。分数通常在 3 到 7 之间波动,拿到 8 分以上的很少,这很正常。

6.3 关键设计说明

第一,为什么用四类角色而不是四个不同温度。温度影响的是措辞的随机性,角色影响的是注意力的分配。综述型角色会主动归类,工程型角色会主动挑实现问题,这两类输出的差异是结构性的,不是随机性的。

第二,为什么把评审的 temperature 调到 0.3。评审需要稳定和一致,同一个候选跑两次得到完全相反的评价是没有意义的。生成要热,评审要冷,这个搭配在实际使用中效果明显。

第三,为什么每轮跑完都不直接采纳。因为SCORE只是模型的判断,它和真实价值的相关性有限。这个脚本的作用是排序和淘汰,不是决策。真正该做的是从 top 3 里挑一个,做进一步的人工核查。

第四,为什么要多跑几轮。因为采样有随机性,同一组输入跑三次,交集部分往往是最稳的想法。如果三次里只有一次出现的想法,通常可以直接放弃。

7. 示例三:本地文献检索增强,让 AI 的说法有据可依

上一节留下的最大隐患是幻觉。模型会一本正经地说“这很像某某工作提出的某某方法”,而你根本查不到。解决这个问题靠的不是更强的提示词,而是把真实文献塞进上下文。

7.1 为什么不直接上向量数据库

向量检索当然更好,但对于起步阶段,一个纯 Python、零额外依赖的关键词打分方案更实用。理由是:它能让你先看清自己的文献库到底有没有料。很多时候你以为“模型在胡说”,实际是你的库里根本没有相关文档。

下面这个脚本实现的是切片加 BM25 风格打分的极简检索,跑起来不需要任何外部服务。

# 文件路径:tools/lit_search.py """极简文献检索:切片 + 关键词打分,先跑通再升级成向量检索。""" import math import re from collections import Counter from dataclasses import dataclass, field from pathlib import Path TOKEN_RE = re.compile(r"[a-zA-Z][a-zA-Z\-]{1,}|[\u4e00-\u9fa5]{2,}") def tokenize(text: str): return [t.lower() for t in TOKEN_RE.findall(text)] def load_text(path: Path) -> str: suffix = path.suffix.lower() if suffix in {".txt", ".md"}: return path.read_text(encoding="utf-8", errors="ignore") if suffix == ".pdf": try: from pypdf import PdfReader except ImportError as exc: raise SystemExit("请先 pip install pypdf,或把 PDF 转成 txt") from exc reader = PdfReader(str(path)) return "\n".join((page.extract_text() or "") for page in reader.pages) return "" def split_chunks(text: str, size: int = 600, overlap: int = 120): text = re.sub(r"\s+", " ", text).strip() chunks, start = [], 0 while start < len(text): piece = text[start:start + size] if len(piece) > 80: chunks.append(piece) start += size - overlap return chunks @dataclass class Chunk: doc: str idx: int text: str tf: Counter = field(default_factory=Counter) class MiniIndex: def __init__(self): self.chunks = [] self.df = Counter() def add_document(self, path: Path) -> None: for i, piece in enumerate(split_chunks(load_text(path))): chunk = Chunk(doc=path.name, idx=i, text=piece) chunk.tf = Counter(tokenize(piece)) self.chunks.append(chunk) for term in set(chunk.tf): self.df[term] += 1 def search(self, query: str, top_k: int = 5): q_terms = tokenize(query) n = max(len(self.chunks), 1) scored = [] for chunk in self.chunks: score = 0.0 for term in q_terms: tf = chunk.tf.get(term, 0) if tf == 0: continue idf = math.log((n + 1) / (self.df[term] + 0.5)) score += (tf / (tf + 1.2)) * idf if score > 0: scored.append((score, chunk)) scored.sort(key=lambda x: x[0], reverse=True) return scored[:top_k] def build_prompt(query: str, hits) -> str: blocks = [ f"[来源 {chunk.doc} 第 {chunk.idx} 段 | 相关度 {score:.2f}]\n{chunk.text}" for score, chunk in hits ] context = "\n\n".join(blocks) if blocks else "(没有检索到相关段落)" return ( "下面是我本地文献库中与问题最相关的段落。请只依据这些段落回答," "凡是段落中没有的内容,直接写“素材不足”,不要补充你自己的知识。\n\n" f"# 问题\n{query}\n\n# 素材\n{context}\n\n" "# 输出\n" "1. 这些段落共同支持的结论,附来源段落编号\n" "2. 段落之间互相矛盾的地方\n" "3. 素材不足以回答、需要我补哪些主题的文献" ) if __name__ == "__main__": index = MiniIndex() corpus = Path("papers") for file in sorted(corpus.glob("*")): if file.suffix.lower() in {".pdf", ".txt", ".md"}: index.add_document(file) print(f"已索引 {len(index.chunks)} 个段落") hits = index.search("图神经网络 过平滑 缓解 方法", top_k=5) for score, chunk in hits: print(f"{score:.3f} {chunk.doc}#{chunk.idx} {chunk.text[:60]}...") Path("prompt.md").write_text( build_prompt("图神经网络过平滑有哪些缓解思路", hits), encoding="utf-8", )

7.2 运行与验证

python tools/lit_search.py cat prompt.md

预期输出分三部分:索引到的段落数量、五条命中结果(带文件名、段落号和分数)、以及生成好的prompt.md。

怎么判断成功?看命中结果里有没有你认识的、确实相关的段落。如果全是无关段落,说明两个可能:切片的粒度不对,或者你的查询词和文献用词不一致。前者调size和overlap,后者换成文献里真实出现的术语再试。

prompt.md可以直接粘进对话框,也可以让脚本继续调接口。它最有价值的地方是最后那三条输出要求——“共同支持的结论”“互相矛盾的地方”“还缺哪些文献”。第三条尤其有用,它相当于让模型帮你做了一次文献缺口分析。

7.3 升级路径

跑通之后可以按需升级:换成向量检索解决同义词问题,加 rerank 解决排序问题,加元数据过滤解决“只在我关心的年份和会议里检索”的问题。但顺序不要反,先把关键词版跑到能用,再谈升级。很多人的问题是直接上向量库,结果调了两周还没搞清楚效果差在哪一环。

8. 结果验证:怎么判断一个 AI 给的 idea 值不值得做

生成容易,判断难。这一节给两个可直接用的筛选工具。

8.1 五维评分表

维度判断问题低分特征高分特征
新颖性和已知工作的实质差别在哪只换了数据集或指标改变了问题设定或假设
可行性现有代码和算力能否支撑需要重建整条流水线在现有代码上加模块即可
验证成本最快多久能拿到第一个信号一个月以上一周到两周
数据可得性数据是不是真的拿得到依赖未公开数据公开数据集或实验室已有数据
价值密度结论成立时谁会在乎只有自己关心同行会引用,或业务方会用

建议给“验证成本”和“数据可得性”加一倍权重。这两个维度不高的想法,再新也容易拖成烂尾。

8.2 三问过滤法

任何候选想法,先问三个问题,答不上来就进冷却区:

  1. 如果这个结论成立,会推翻什么?答不出来说明它可能只是个增量改进。
  2. 如果这个结论不成立,我能不能写出一篇有价值的负结果?答不出来说明这个实验设计的风险太高。
  3. 三个月后我能拿出什么?如果答案是“更完整的文献综述”,说明这个想法还没到可以动手的程度。

8.3 想法台账模板

所有候选都进台账,不要只记活下来的。被否掉的想法本身也是资产,因为你会反复想到它们。

<!-- 文件路径:notes/idea_ledger.md --> ## 2025-XX-XX 候选 03 - 一句话主张:如果……那么…… - 来源:哪次讨论 / 哪条异常现象 / 哪个角色的输出 - 最小验证实验:数据、算力、周期 - 证伪条件: - 五维评分:新颖 4 / 可行 3 / 成本 5 / 数据 4 / 价值 4 - 当前状态:待验证 / 冷却中 / 已否决 / 进行中 - 否决原因(如果否决): - 下次回看日期:

台账的价值在于回看。三个月后你会发现,真正做出来的往往是当初评分中等但验证成本最低的那个,而不是当初最惊艳的那个。

9. 常见问题与排查

使用过程中遇到的问题高度集中,下面这张表覆盖了大部分情况。

问题现象可能原因排查方式解决方案
输出全是“A 与 B 结合”提示词没有约束条件检查是否写清数据、算力、时间、评价标准补齐四类约束再重跑
每次输出都差不多单一角色、单一上下文对比不同角色输出的差异换角色,或注入你自己的异常现象
提到的文献查不到模型幻觉逐条检索核实改为检索增强,只让模型基于给定段落回答
分数虚高但内容很空评审提示词太宽松看评审是否给出具体反驳句要求“必须指出最可能被反驳的一句话”
上下文超长报错一次性塞入太多论文看错误信息里的 token 限制改成切片检索,只放 top-k 段落
话题越跑越偏输入里混入了多个目标回看自己的输入一次只留一个核心问题
脚本报 KeyError环境变量没生效打印os.environ检查重新export或在.env里配好再加载

除了表格里的,还有两个值得单独说明的问题。

第一个是“回答太像综述”。这不是模型的问题,是它没有具体材料时只能复述通用知识。解决办法只有一个:把你的真实数据、真实异常、真实困惑写进输入。哪怕只有三行,效果也完全不同。

第二个是“用久了产生依赖”。这个风险比想象中更实际。有效的对抗方式是保留一块完全不用 AI 的时间,比如每周有半天只读书和写笔记,不打开任何对话框。你自己的判断力是需要维护的,长期外包会让它退化。

10. 最佳实践与工程建议

最后这一节讲那些不写进教材、但会影响你半年后能不能拿出东西的细节。

固定记录提示词版本。同一个模板改一个字,输出风格可能差很多。建议把用过的提示词按日期存进configs/prompts/,用完觉得好就留着,不好就标注原因。三个月后回头看这批记录,比看任何教程都有用,因为那是你自己的实验数据。

把模型名和日期写进笔记。模型更新很快,同一段提示词在不同版本上表现不同。台账里记一句“生成于某模型某日期”,将来回溯时能省很多猜测。

发散和评审用不同的温度。生成阶段温度调高一点,追求多样性;评审阶段温度调低,追求一致性。这个搭配在脚本里已经体现,手工操作时也建议照做。

每轮候选数量控制在 8 个以内。生成太多反而筛不动。人的注意力有限,超过十个候选,你会开始凭直觉随便挑,等于放弃了筛选。

先做能证伪的实验,不要做能证明的实验。这是整套方法里最重要的一条。AI 很擅长帮你设计出一堆支持性实验,但真正让你少走弯路的是那个能快速把想法否掉的实验。每次拿到候选,第一件事就是想“我做什么能在三天内知道它是错的”。

数据和代码的边界要提前划清。未发表数据、合作方资料、涉及个人信息的数据,不上公网接口;需要处理时走内部合规通道或本地脱敏。这一条没有例外,也不要抱侥幸心理。

和组会结合使用。把 AI 生成的候选挑两个带到组会上,主动说“这是机器生成的,我觉得第二个可能是错的,因为……”。这种用法有两个好处:一是导师会直接指出你判断里的偏差,二是你会被迫形成自己的立场。

每周留一个固定时段复盘。半小时就够,翻一遍台账,把冷却期满的想法重新过一遍,把状态从“待验证”更新成“冷却中”或“已否决”。这个动作看起来琐碎,但它决定了你三个月后手里是有一堆散点,还是有一条主线。

不要让 AI 替你写问题陈述的最终版本。它可以给你草稿、挑逻辑漏洞、检查指标是否可测,但最后那一句话必须是你自己写的。因为那句话代表你对问题的理解深度,理解不到位,后面的实验设计一定歪。

如果要把这套流程浓缩成一句可执行的话,我会这么说:把 AI 当成一个随叫随到、不知疲倦、但完全没有问题意识的合作者。它负责在你给定的边界里快速生成和快速否定,你负责告诉它边界在哪、以及什么样的否定是致命的。博一这一年真正值钱的不是读了多少篇论文,而是你手里有没有几个自己反复琢磨过、被质疑过、并且能在两三周内看到第一个信号的问题。