FlawedFictions 对应论文《Finding Flawed Fictions: Evaluating Complex Reasoning in Language Models via Plot Hole Detection》,核心目标不是再做一个常规阅读理解 benchmark,而是把“发现故事中的情节漏洞”转化为一个可控、可评测、可扩展的语言模型深层推理任务。论文提出了 FlawedFictionsMaker,用于在人类原始故事中自动注入 continuity error,并构建了 FlawedFictions 与 FlawedFictionsLong 两个评测集。论文结论很明确:即便是前沿大模型,在这类叙事一致性任务上也并不强,故事一旦变长,性能会明显恶化;增加 reasoning budget 也不保证稳定收益。从当前仓库实现看,这个项目更接近“论文实验运行器”而不是完整产品。它已经实现了论文 benchmark 的核心使用路径:加载数据集、调用不同 LLM、按 prompt 模板执行 continuity error 检测、输出分类与定位指标;但它并没有完整公开 FlawedFictionsMaker 的数据构造流水线。结合本地技术报告、阅读笔记和测试脚本,本报告的结论是:FlawedFictions 在研究选题上很有价值,在工程实现上足够复现实验,但距离稳定、可长期维护的评测框架还有明显差距。
1. 调研对象与资料范围
本次调研综合使用了以下资料:
- 仓库内部资料:
~\FlawedFictions\docs\technical_report_zh.md~\FlawedFictions\docs\paper_note.md~\FlawedFictions\test_file_issue_detector.py~\FlawedFictions\data\测试脚本输出.json
- 论文原文:
需要特别说明两点:
- 论文 arXiv 页面显示当前最新版本为 v3,发布日期 2025-12-18。
- 当前仓库主要覆盖 benchmark 运行与评测代码,不是论文完整数据构建系统的全量公开实现。
2. 论文试图解决什么问题
这篇论文抓住了一个非常具体、但又非常有代表性的问题:现有主流语言模型 benchmark 能否真正测到“深层叙事理解”。
作者认为,很多流行 benchmark 更偏向于:
- 表层问答
- 多跳知识调用
- 明确规则下的推理
- 短文本理解
但故事理解并不只是“知道发生了什么”,还包括:
- 跟踪人物、地点、物品和状态
- 维护故事世界内部规则
- 理解角色动机、信念和行为约束
- 识别前后设定是否被后文推翻
- 在长上下文中保持稳定的世界模型
因此,论文提出:把 plot hole detection 当作语言模型深层语言理解与推理能力的代理任务。
3. 论文如何定义 Plot Hole
论文没有把所有 plot hole 类型混成一个宽泛概念,而是有意识地聚焦到 continuity error。这类错误可以概括为:
故事前文已经建立为真的设定,在后文被直接或隐含地推翻。
论文同时指出,plot hole 还可以包括:
- out-of-character behavior
- factual errors
- impossible events
- unresolved storylines
但 continuity error 最适合形式化、可控生成和自动评估,因此被选作主任务。
这个选择非常关键,因为它让“情节漏洞检测”从文学评论问题,收缩成一个可以做 benchmark 的推理问题:模型不仅要看懂文本,还要维持一个跨句、跨段、跨事件的叙事状态表示。
4. FlawedFictionsMaker:论文的核心方法贡献
论文最重要的创新,其实不只是 benchmark 本身,而是数据构造算法 FlawedFictionsMaker。
它的基本思想不是凭空写一个有 bug 的故事,而是:
- 从原始无漏洞故事中,抽取前半段已建立的事实。
- 选中其中一个事实,构造 counterfactual 版本。
- 用 counterfactual 设定重写后半段故事。
- 把“原始前文”和“改写后的后文”拼接在一起。
- 让前后文在关键事实层面形成冲突,从而得到 continuity error。
论文正文给出了一个 5 阶段主流程:
- Three Act Structure Extraction
- Proposition Extraction and Scoring
- Counterfactual Story Generation
- Re-building Story / Patching
- Filtering
之后再加第 6 步:
- Human Verification
这里有两个特别值得注意的研究设计点。
第一,作者只从第一幕抽取 proposition,再在后续部分引入矛盾,这样可以确保错误具备“先建立、后推翻”的时间结构。
第二,过滤步骤不是简单的规则筛选,而是使用 LLM 作为 judge 做辅助质量控制,并用 self-consistency 机制保留至少 5 次判断中有 4 次认为存在 continuity error 的样本。最后再加人工验证,确保 benchmark 质量。
这套设计的优点是:
- 避免纯人工构造数据集的人力成本
- 避免纯自动生成导致的大量低质样本
- 相比现成公开故事漏洞文本,更不容易被训练污染
- 生成逻辑具有可扩展性
5. Benchmark 设计与任务形式
论文最终构建了两个核心数据集:
5.1 FlawedFictions
- 样本数:414
- 平均长度:731.81 词
- 中位数:754 词
- 最大长度:1236 词
5.2 FlawedFictionsLong
- 样本数:200
- 平均长度:2703.09 词
- 中位数:2575 词
- 最大长度:3999 词
这两个数据集分别代表:
- 常规短篇叙事的一致性检测
- 长上下文叙事的一致性检测
任务形式分成两层:
5.3 分类任务
输入一个故事,判断是否存在 continuity error。
5.4 双向定位任务
如果存在 continuity error,模型还要指出两类句子:
- 哪些句子引入了错误
- 哪些更早的句子被这些错误所矛盾
这意味着 FlawedFictions 不是简单 yes/no 分类,而是:
分类 + 证据定位
这也是它比很多浅层 benchmark 更有区分度的原因。
6. 评测指标设计
论文与仓库代码都采用两层指标。
6.1 分类指标
- Accuracy
- Precision
- Recall
- F1
6.2 定位指标
CEEval-PosCEEval-Full
可以把这两类指标理解为:
- 分类指标回答“模型有没有意识到故事有问题”
- 定位指标回答“模型知不知道问题具体出在哪里”
从研究价值上看,后者更接近真实叙事理解能力。
7. 论文的主要实验结论
7.1 前沿模型并不轻松
论文在 FlawedFictions 上的代表性结果显示:
- Claude 3.5 Sonnet:Accuracy 0.76,CEEval-Full 0.67
- Claude 3.5 Sonnet + Verifier:Accuracy 0.74,CEEval-Full 0.68
- Claude 3.7 Sonnet with Extended Thinking:Accuracy 0.73,CEEval-Full 0.66
- o1(Low / Medium):CEEval-Full 0.65
- Human:Accuracy 0.76,CEEval-Full 0.68
这组结果说明:
- 最强模型大致接近人类,但并没有稳定超越
- 即使是高端 reasoning model,也没有展现压倒性优势
- verifier 结构有一定帮助,但不是质变
7.2 长文本会显著拉低性能
FlawedFictionsLong 的结果更说明问题。表现较好的模型也只有:
- GPT-4-turbo CoT:CEEval-Full 0.53
- o1 Medium:CEEval-Full 0.53
- GPT-4-turbo:CEEval-Full 0.52
- Claude 3.5 Sonnet + Verifier:CEEval-Full 0.50
和短文本结果相比,整体明显下滑。这说明模型在长叙事上的持续状态跟踪仍然不稳。
7.3 reasoning budget 不是稳定增益
论文明确指出,增加 reasoning effort 并不保证变强,某些模型甚至会退化。这一点很重要,因为它反驳了一个常见直觉:
只要让模型“多想一会”,复杂叙事推理自然会更好。
在这个任务上,事实并非如此。
7.4 Few-shot 和 CoT 不是普适解
论文结果显示:
- CoT 对部分模型有帮助
- few-shot 往往不稳定,甚至可能变差
- 不同模型对 prompting 策略的反应差异很大
这说明任务难点并不只是 prompt engineering,而是模型内部叙事状态表示本身就不够可靠。
8. 论文对实际生成任务的一个重要发现
论文不只是用 benchmark 给模型排名,还把它反过来用于质检 LLM 生成故事。
作者测试了两个任务:
- story summarization
- contemporary adaptation
结果非常值得关注:
- 在 summarization 中,最低 continuity error rate 也从 0.31 升到 0.45,约 50% 增长
- 在 contemporary adaptation 中,最佳情况也从 0.14 升到 0.27,接近 100% 增长
- 最差情况下,GPT-4o-mini 从 0.14 升到 0.53,增长 278%
这组结果的现实意义很强:
- 摘要并不天然安全,摘要会丢掉使后续情节成立的关键中间事实
- 改编尤其危险,因为模型会迁移背景,但经常忘记同步迁移世界规则和可置信性约束
因此,FlawedFictions 不只是一个“科研 benchmark”,也可以反向作为生成式系统的叙事一致性质检工具。
9. 当前仓库实现了什么
结合仓库资料,当前代码主要是 benchmark 运行层,而不是完整数据构造层。
已经实现的核心能力包括:
- 从 Hugging Face 加载
kahuja/flawed-fictions - 使用不同模型进行 continuity error 检测
- 支持基础 prompt、CoT prompt、few-shot prompt
- 统一封装 OpenAI / Azure OpenAI / Claude 调用
- 解析模型输出中的 explanation、error lines、contradicted lines、decision
- 计算分类指标和定位指标
- 将结果输出为 JSON 与 CSV
- 支持缓存,避免重复 API 调用
换句话说,当前仓库更像:
FlawedFictions benchmark runner
而不是:
FlawedFictionsMaker + benchmark construction framework
10. 当前仓库没有完整公开什么
从论文方法对照代码,缺失或未完整公开的部分主要是:
- 三幕切分流水线
- proposition 抽取与打分
- counterfactual 事实生成
- 后续故事重写 / patching
- 自动过滤与 4/5 self-consistency 过滤
- 人工验证工作流
- summarization / adaptation 的实验脚本
这意味着:
- 当前仓库足够用于“跑 benchmark”
- 但不足以完整复现“如何从零造出这个 benchmark”
11. 本地测试脚本与测试输出的意义
test_file_issue_detector.py 不是 benchmark 主入口,而是一个单文件故事检测脚本。它会:
- 读取指定故事文件
- 初始化 LLM 客户端
- 调用
check_conterror_story - 输出结构化 JSON
从 data\测试脚本输出.json 看,这次测试样本的结果是:
has_issue = falsesummary = "No continuity error found"
解释文本认为该故事在世界规则、角色设定、时间线和关键事件上保持了一致性,因此没有发现 continuity error。
这说明两件事:
- 仓库不仅能跑 benchmark,也能用于单篇故事的局部检测。
- 这类单文件脚本更像 smoke test 或演示入口,不能替代系统性 benchmark 评估。
12. 从工程角度看当前实现的主要问题
结合本地技术报告与测试脚本,可以把主要问题分为几类。
12.1 输出解析过于脆弱
仓库当前依赖 XML 风格标签和字符串切分来解析模型输出。这种方式的优点是实现简单,但缺点非常明显:
- 模型一旦多输出前后缀文本,容易误解析
- 标签缺失、闭合错误、嵌套变化都可能导致失败
decision的判断规则比较脆弱
在零信任工程视角下,这一层不够稳。
12.2 路径依赖 os.getcwd()
如果用户不是在仓库根目录下运行,prompt、cache、output 路径都可能错位。这类问题在实验脚本中很常见,但对于长期维护的项目来说是不必要的风险。
12.3 CLI 布尔参数定义不规范
本地技术报告指出,某些布尔参数使用 type=bool,这在 argparse 中是常见坑点,更稳妥的写法应是 store_true / store_false。
12.4 定位匹配策略偏弱
定位阶段并不是真正的 fuzzy matching,更像标准化后的子串包含。这会带来:
- 模型轻微改写句子后匹配失败
- 短片段误匹配多个句子
- 定位指标受实现细节影响较大
12.5 评测表字段污染 bug
本地技术报告已经指出,construct_eval_dataset() 中 ground_truth_expl 会被预测解释覆盖。这是标准的数据污染问题,会让导出结果失真。
12.6 外部依赖说明不足
仓库依赖:
- Hugging Face 数据集可访问性
- API Key
- NLTK 资源
但这些前置条件没有完全工程化封装,也没有全部在运行前做严谨检查。
12.7 测试脚本暴露出安全与配置反模式
test_file_issue_detector.py 里直接写入了:
OPENAI_API_KEYOPENAI_BASE_URL
这对一次性本地验证也许方便,但从工程实践上看属于明显反模式:
- 密钥不应硬编码进脚本
- provider 配置不应耦合在测试文件里
- 可复用脚本应优先走环境变量或配置文件
这一点虽然不影响论文结论,但会影响项目后续可维护性和安全性。
13. 这个项目的研究价值在哪里
如果从研究角度评价,FlawedFictions 的价值很高,主要体现在四点。
13.1 任务选得准
它不测浅层问答,而测故事一致性。这比很多常规 benchmark 更接近“语言模型是否真的理解复杂文本”。
13.2 自动构造思路很强
FlawedFictionsMaker 通过“原故事 + counterfactual 重写 + patching + 过滤 + 人工验证”的方式,把一个原本高度主观的问题压缩成可批量生产、可质控的数据构造流程。
13.3 指标设计不止于分类
加入双向定位后,benchmark 不只是测“猜对没”,而是在一定程度上测“有没有找到真正的证据链”。
13.4 可以反向用于生成系统质检
论文已经证明,这个 benchmark 思想可以扩展到:
- 摘要质检
- 改编质检
- 长篇创作一致性检查
- 叙事型 agent 输出审校
14. 这个项目的局限性在哪里
即便论文很强,它也有明确边界。
14.1 continuity error 不能覆盖全部 plot hole
它覆盖的是最容易形式化的一类,不代表所有叙事漏洞都被涵盖。
14.2 benchmark 仍有构造分布偏差
即使有人工过滤,正样本仍来自特定生成流水线,因此模型可能部分适应“这种风格的错误”,而不是掌握更一般的叙事一致性判断。
14.3 长文本集的人类验证均匀性略弱
论文对长文本的人工验证流程不如主 benchmark 那么均匀,这会影响一部分解释力度。
14.4 当前代码仓库仍是研究原型
现有实现更适合复现实验和做对照,不适合直接作为生产级评测服务部署。
15. 对后续工作的建议
如果目标是继续做研究,建议优先沿以下方向扩展:
- 扩展 continuity error 以外的 plot hole 子类型
- 强化长文本、多角色、多线叙事场景
- 增强定位任务的句级对齐和证据评分
- 将 benchmark 反向接入 story generation / editing / summarization 质检闭环
如果目标是把仓库做成更可靠的工程工具,建议优先处理:
- 替换脆弱的字符串解析器
- 修复
ground_truth_expl覆盖问题 - 清理硬编码 API key / base URL
- 规范命令行参数与路径解析
- 显式检查 NLTK 与外部依赖
- 增加最小 smoke test 和结构化测试
16. 总结
FlawedFictions 的真正价值,不在于“又做了一个新分数榜”,而在于它把 故事一致性 变成了一个结构化、可扩展、可实证评估的 LLM 推理问题。论文证明了两件很重要的事:
- 前沿模型并不真正擅长稳定的深层叙事推理。
- 语言模型在生成、摘要和改编故事时,很容易引入新的 plot hole。
而当前仓库则说明,这一研究方向已经落到了一个可运行的实验框架上:它足够支撑 benchmark 复现和局部故事检测,但尚未达到成熟工程系统的标准。
如果把它定位为:
面向 narrative reasoning 的研究型 benchmark 与实验运行器
那么它是成功的。
如果把它定位为:
稳定、可扩展、低风险的生产级故事一致性检测平台
那么它还需要一轮明确的工程加固。
参考资料
- Kabir Ahuja, Melanie Sclar, Yulia Tsvetkov. Finding Flawed Fictions: Evaluating Complex Reasoning in Language Models via Plot Hole Detection, arXiv:2504.11900, latest version v3 published on 2025-12-18.
- DOI: 10.48550/arXiv.2504.11900
- 本地技术说明:
D:\github-project\FlawedFictions\docs\technical_report_zh.md - 本地论文笔记:
D:\github-project\FlawedFictions\docs\paper_note.md - 本地测试脚本:
D:\github-project\FlawedFictions\test_file_issue_detector.py - 本地测试输出:
D:\github-project\FlawedFictions\data\测试脚本输出.json