novel-reader
Novel Reader - 智能长文本小说阅读器
使用 Python 安全、可靠地读取长文本小说,解决 LLM 上下文窗口有限的问题。完美支持 UTF-8 编码的中文小说。自动过滤无关内容,实时抽取详细的角色、道具、场景信息。
核心功能
- 多格式支持:如果输入文件是 PDF、DOC、DOCX 格式,先使用 doc-to-txt skill 转换为 TXT 纯文本格式,然后读取转换后的 TXT 文件
- 按字符位置读取:使用 Python 按字符位置精确读取,不会出现乱码
- 分段读取:每次读取最多 3000 字符,默认值为 3000 字符,避免超出工具输出限制。严禁跳读,必须连续逐段读取
- 灵活定位:可从任意位置开始读取
- 编码安全:原生支持 UTF-8 编码,正确处理中文字符
- 智能内容过滤:通过大模型自动识别并跳过小说中与正文无关的内容(上架感言、作者感谢、访谈、广告等)
- 实时资产抽取:每读取一段内容,立即识别并记录小说中的角色、道具、场景的详细信息
- 大纲记录:记录每段内容的摘要,形成完整大纲
- 进度追踪:记录当前阅读位置、已读字数等进度信息
- 上下文管理:充分利用 Agent 的上下文 compact 机制,在上下文快用完时自动压缩
重要要求
严禁跳读
- 必须连续逐段读取:每次读取 3000 字符后,下一次必须从当前结束位置继续读取(即 start = 上次的 start + 3000)
- 禁止跳读:绝对不允许跳过中间内容直接跳到后面的位置
- 绝对禁止 for 循环读取:严禁使用 for 循环批量读取文件(如
for i in $(seq ...)),因为 Agent 工具会对输出进行压缩,for 循环会导致内容被截断,当你看到 (some characters truncated) 表示内容已经被截断,你只能手动重新一段一段读取。 - 禁止一个命令多次调用 python 脚本:每个工具只能输出 3000 字,超出的内容会被截断,一次 tool call 最多只能调用一次 python 命令!
- 提升效率:因为要读取超长文本,你可以连续调用读取工具脚本(但不能用 for 循环),中间不思考也不说话。
- 更新循环:每读取 10 个小说片段(每次 3000 字符,共 30000 字符),就更新一次大纲、进度、资产文件,继续下一个循环。
- 禁止预设任务:禁止使用 TODO 列表,Task 列表相关工具!
使用方法
核心命令
python3 read_novel.py <小说文件路径> [--start <起始位置>]
参数说明
| 参数 | 说明 | 示例 |
|---|---|---|
<小说文件路径> |
小说文件的路径(必填),支持 TXT、PDF、DOC、DOCX 格式。如果是 PDF/DOC/DOCX 格式,先使用 doc-to-txt skill 转换为 TXT | test-files/novel.txt 或 test-files/novel.pdf |
--info |
获取小说信息(总字符数、总行数、非空行数) | --info |
--start |
起始位置(字符索引,从 0 开始,默认:0,可选) | --start 10000 |
示例
获取小说信息:
python3 read_novel.py ./novel.txt --info
读取小说从头开始的 3000 个字符(使用默认参数):
python3 read_novel.py ./novel.txt --start 0
读取小说从第 3000 个字符开始的 3000 个字符(仅指定 start):
python3 read_novel.py ./novel.txt --start 3000
查看帮助:
python3 read_novel.py --help
工作流
完整工作流分为三个阶段:文件格式处理 → 初始化 → 循环读取 → 完成总结
前置步骤:文件格式处理
- 检查输入文件格式
- 如果是 PDF、DOC、DOCX 格式,先使用 doc-to-txt skill 转换为 TXT 纯文本格式
- 转换完成后,使用转换后的 TXT 文件进行后续操作
阶段一:初始化(仅需一次)
步骤 1:获取小说信息
python3 read_novel.py novel.txt --info
输出示例:
总字符数: 5512508
总行数: 158108
非空行数: 79053
步骤 2:检查读取进度
- 检查是否存在
读取进度.txt文件 - 如果存在:读取当前位置,从该位置继续(断点续读)
- 如果不存在:从位置 0 开始全新读取
阶段二:循环读取(核心阶段)
每个循环读取 10 个片段(共 30000 字符),分为两个子阶段:
子阶段 A:批量读取(连续执行,中间不分析)
连续调用 10 次读取命令,每次读取 3000 字符:
- 第 1 次:
--start <当前位置> - 第 2 次:
--start <当前位置+3000> - ...
- 第 10 次:
--start <当前位置+27000>
示例(从 0 开始的第一个循环):
读取片段 1:--start 0
读取片段 2:--start 3000
...
读取片段 10:--start 27000
示例(从 60000 开始的第三个循环):
读取片段 21:--start 60000
读取片段 22:--start 63000
...
读取片段 30:--start 87000
⚠️ 关键规则:10 次读取必须连续执行,中间不分析、不总结、不更新文件
子阶段 B:分析更新(读完 10 个片段后执行)
- 分析这 10 个片段的内容
- 更新
大纲.txt:添加这 10 个片段的章节摘要 - 更新
读取进度.txt:记录当前位置(如 30000) - 创建或更新资产文件:提取新出现的角色、道具、场景
子阶段 C:判断是否继续
- 计算已读进度(已读字数/总字数)
- 如果未达到用户要求(如"读 5%"):回到子阶段 A,继续下一批 10 个片段
- 如果已达到用户要求:进入阶段三
阶段三:完成总结
- 输出最终读取进度
- 总结已抽取的资产统计(角色数、道具数、场景数)
执行顺序示例
假设用户要求读取小说前 5%,小说文件是 novel.pdf:
前置步骤:文件格式处理
- 检查文件格式:.pdf
- 使用 doc-to-txt skill 将 novel.pdf 转换为 novel.txt
- 后续步骤使用 novel.txt 文件
步骤 1:初始化
- 获取小说信息 → 总字数 5512508
- 检查
读取进度.txt→ 不存在,从位置 0 开始
步骤 2:循环读取
循环 1(片段 1-10,0-30000 字符):
- 批量读取:连续执行
--start 0到--start 27000 - 分析更新:更新大纲、进度(30000)、资产
- 检查进度:30000/5512508 = 0.54%,未达到 5%,继续
循环 2(片段 11-20,30000-60000 字符):
- 批量读取:连续执行
--start 30000到--start 57000 - 分析更新:更新大纲、进度(60000)、资产
- 检查进度:60000/5512508 = 1.09%,未达到 5%,继续
循环 3(片段 21-30,60000-90000 字符):
- 批量读取:连续执行
--start 60000到--start 87000 - 分析更新:更新大纲、进度(90000)、资产
- 检查进度:90000/5512508 = 1.63%,未达到 5%,继续
... 继续循环 ...
循环 10(片段 91-100,270000-300000 字符):
- 批量读取:连续执行
--start 270000到--start 297000 - 分析更新:更新大纲、进度(300000)、资产
- 检查进度:300000/5512508 = 5.44%,已达到 5%,停止
步骤 3:完成总结
- 输出最终进度:5.44%
- 统计资产:角色 X 个,道具 Y 个,场景 Z 个
关键规则
| 规则 | 说明 |
|---|---|
| 严禁边读边分析 | 每读完一个片段就分析更新是错误的做法 |
| 必须批量读取 | 10 个片段全部读完后再统一分析更新 |
| 支持断点续读 | 通过读取进度.txt 实现中断后继续 |
| 进度计算 | 每次循环读取 30000 字符(10 × 3000) |
资产抽取
智能内容过滤
通过执行 Python 脚本读取小说内容后,让大模型读懂内容,自动识别并忽略与小说正文无关的内容,只保留小说的正文章节内容进行分析和资产抽取。不使用任何规则或正则表达式进行过滤,完全依赖大模型的理解能力。
实时资产抽取
每读取一段内容(不超过 3000 字符),立即从中识别并抽取新出现的资产(角色、道具、场景),并实时更新对应的文件。不要等到全部读完再更新。大模型会充分利用上下文 compact 机制,在快用完上下文时自动压缩。
抽取元素
从每段读取的内容中,识别并抽取以下三类资产,尽可能收集详细信息:
-
角色 - 小说中出现的人物,包括:
- 基本信息:姓名、年龄、性别、身份、角色定位(主角/配角/反派/男二/女二等)
- 外貌特征:容貌、身高、体型、着装
- 性格特点:口头禅、习惯性动作、行为模式
- 背景关系:家庭、朋友、敌人、师承
- 能力修为:实力等级、特殊能力、武器装备
- 出场情节:首次出场、重要事件
-
道具 - 小说中出现的物品、法宝、武器等,包括:
- 基本信息:名称、类型、来源
- 外观特征:形状、颜色、材质、大小
- 功能特性:特殊能力、使用方法、效果
- 历史背景:来历、前任主人、重要事件
- 相关角色:拥有者、使用者、争夺者
-
场景 - 小说中出现的地点、环境、场所等,包括:
- 基本信息:名称、类型、地理位置
- 环境特征:地形、气候、建筑风格、氛围
- 功能用途:居住、修炼、交易、战斗
- 相关势力:所属势力、管理者、常驻人物
- 重要事件:发生过的关键情节
目录结构
在小说文件所在目录下创建以下结构:
小说名或项目名/
├── 大纲.txt
├── 读取进度.txt
├── 角色/
│ ├── <角色名1>.txt
│ ├── <角色名2>.txt
│ └── ...
├── 道具/
│ ├── <道具名1>.txt
│ ├── <道具名2>.txt
│ └── ...
└── 场景/
├── <场景名1>.txt
├── <场景名2>.txt
└── ...
文件内容格式
大纲.txt
1. <第一段内容的摘要>
2. <第二段内容的摘要>
...
说明:
- 按小说内容的逻辑分段添加摘要,不按固定字数分段
- 大模型根据内容自然决定何时添加新的摘要条目
- 每条摘要用序号标识,按阅读顺序排列
- 只记录小说正文内容的摘要,跳过无关内容
- 跳过小说中与正文无关的内容,如上架感言、作者感谢、访谈、广告等
读取进度.txt
当前位置: <字符索引>
已读字数: <数字>
总字数: <数字>
进度: <百分比>%
角色文件(角色/<角色名>.txt)
每个角色文件包含该角色的详细描述,参考格式如下:
<角色名称>
【基本信息】
姓名:
年龄:
性别:
身份:
角色定位:
【外貌特征】
容貌:
身高:
体型:
着装:
【性格特点】
性格:
口头禅:
习惯性动作:
行为模式:
【背景关系】
家庭:
朋友:
敌人:
师承:
【能力修为】
实力等级:
特殊能力:
武器装备:
【出场情节】
首次出场:
道具文件(道具/<道具名>.txt)
每个道具文件包含该道具的详细描述,参考格式如下:
<道具名称>
【基本信息】
名称:
类型:
来源:
【外观特征】
形状:
颜色:
材质:
大小:
【功能特性】
特殊能力:
使用方法:
效果:
【历史背景】
来历:
重要事件:
【相关角色】
拥有者:
使用者:
争夺者:
场景文件(场景/<场景名>.txt)
每个场景文件包含该场景的详细描述,参考格式如下:
<场景名称>
【基本信息】
名称:
类型:
地理位置:
【环境特征】
地形:
气候:
建筑风格:
氛围:
【功能用途】
居住:
修炼:
交易:
战斗:
【相关势力】
所属势力:
管理者:
常驻人物:
【重要事件】
发生过的关键情节:
抽取规则
- 去重:如果资产文件已存在,只需追加新的信息,不要重复创建
- 准确性:确保抽取的资产名称准确,避免错别字
- 完整性:尽可能记录资产的所有相关信息,使用上述详细格式
- 自然语言:使用自然语言描述,让大模型理解抽取需求
- 内容过滤:在抽取资产前,先过滤掉无关内容,只从正文中抽取
- 实时更新:每读取一段内容(不超过 3000 字符),立即识别并抽取新出现的资产,不要等全部读完再更新
- 不使用规则/正则:完全通过执行 Python 脚本获取内容,让大模型自己理解和分析,不使用任何规则或正则表达式进行匹配
- 重要性筛选:只记录重要的资产,不重要的角色、场景、道具可以忽略跳过。判断标准包括:
- 角色:对剧情有推动作用的主要角色、关键配角、重要反派等;路人、龙套、一次性出现的次要角色可忽略
- 道具:对剧情有关键作用的法宝、武器、重要物品;普通物品、一次性道具可忽略
- 场景:故事发生的主要地点、重要场所;临时场景、一笔带过的地点可忽略
技巧提示
- 获取文件总字符数:
python3 -c "
with open('test-files/novel.txt', 'r', encoding='utf-8', errors='replace') as f:
print(len(f.read()))
"
-
读取分段:每次读取最多 3000 字符,默认值为 3000 字符,避免超出工具输出限制
-
上下文管理:大模型通常有 128k 上下文窗口,Agent 会在快用完上下文时自动压缩,请合理利用
为什么用 Python?
- ✅ 编码安全:原生支持 UTF-8,不会出现乱码
- ✅ 按字符读取:不是按字节,正确处理中文字符(每个中文字符算 1 个)
- ✅ 跨平台:Windows/Mac/Linux 都一样
- ✅ 系统预装:几乎所有现代系统都预装了 Python 3
- ✅ 语法简单:一个模式搞定所有场景