
神话 IP 游戏化设计的第一步不是急着讨论原画风格也不是到处找内部消息而是先把原著拆成结构化素材。以《钟馗斩鬼传》这类古本小说为例游戏化解读要回答的问题非常具体钟馗在不同章节里到底和谁战斗、使用了什么手段、场景在哪里、哪些角色轮流出场。这些问题如果只靠人工通读效率低且容易漏如果直接在网上搜二手结论又容易把版本和情节混在一起。更可靠的做法是写一套文本处理工具把原著原文变成可查询的人物表、地点表、事件表和关系图。这套流程就是本文要分享的内容从原始文本开始经过清洗、切分、分词、实体抽取、关系统计、事件识别最终输出 JSON 和知识图谱再让策划人员基于结构化数据做任务设计和关卡拆解。1. 为什么游戏化解读要先做结构化拆解小说文本是线性的而游戏内容是高度模块化的。打开一本章回体小说读到的是第一回、第二回这样按顺序推进的叙事但关卡设计、任务编排、角色养成需要的却是另一套索引钟馗在第几回遇见了谁战斗发生在哪个地点某段对话属于主线还是支线某个妖怪是单场 BOSS 还是反复登场的势力代表。这些信息藏在文字流里如果不提前抽取出来策划在写剧情、配战斗、做任务时只能反复翻原著而且每个人翻到的重点可能不一致。1.1 游戏化解读的本质是把叙事转成系统数据游戏化解读不是把小说内容复制到策划文档里而是要把一段线性叙事转换成可被战斗、任务、关卡、角色系统消费的数据。举个例子原著的某一回可能写“钟馗来到一处山岭遇到小妖拦路随后一场大战最终把妖收服”。如果只在文档里摘抄这句话研发团队依然不知道要准备几张地图、几个敌人、几个演出环节。但如果把这句话拆成结构化数据地点山岭角色钟馗、小妖事件类型战斗结果收服那么关卡策划可以直接把这条记录映射为“一张野外地图 一场普通战斗 收服后触发的剧情”。文本的价值在这里才真正被游戏系统消费掉。这也是为什么需要先做结构化拆解而不是直接写剧情摘要。1.2 手工阅读和结构化拆解的差异手工阅读适合理解氛围、语言风格和人物性格但不适合支撑大规模系统设计。下面用一张表对比两者的主要差异对比维度人工通读结构化拆解角色出场追踪需要边读边记容易漏程序自动统计结果稳定地点出现频率凭印象判断可按次数、章节分布排序战斗事件提取依赖阅读者主观判断按触发词和上下文规则抽取关系网络很难整体把握生成人物共现图直观展示多人协作每个人理解可能不同结果有统一 schema可校对成本第一次阅读成本高需要脚本开发和词表维护成本从这张表能看出来结构化拆解最大的价值不是取代人工阅读而是把“印象”转成“可讨论、可校验、可版本化”的材料。人工阅读仍然重要但应该用在审核结果、补充语感、判断规则错误上。1.3 这套流程适合谁这套流程适合三类读者。第一类是游戏策划尤其是做世界观、剧情、关卡设计的策划可以通过结构化数据快速建立原著素材库。第二类是独立游戏开发者没有专门文案团队时可以用脚本自动整理文本降低通读成本。第三类是对自然语言处理感兴趣的开发者可以把它当作中文文本抽取入门练习使用正则、分词、共现统计和简单规则不需要一开始就上大模型。核心前提只有一个具备最基础的 Python 环境并且愿意维护一份人物词表和地点词表。词表质量决定了抽取结果的上限后面会专门说明。2. 环境准备与数据准备在写任何代码之前先把 Python 环境和原始文本准备好。这一步不复杂但非常容易出问题尤其是编码和文件路径。建议按下面的顺序操作。2.1 Python 环境与依赖推荐使用 Python 3.10 以上版本。如果你的机器上已经有别的 Python 项目最好创建独立的虚拟环境避免依赖冲突。创建虚拟环境并安装依赖python -m venv venv source venv/bin/activateWindows 环境使用venv\Scripts\activate依赖清单写入requirements.txtjieba0.42.1 pandas2.2.2 networkx3.3 pyecharts2.0.5 openpyxl3.1.5安装pip install -r requirements.txt各依赖的作用如下依赖用途jieba中文分词和自定义词典加载pandas生成事件 Excel 表格networkx构建关系图和导出 GEXF 文件pyecharts生成可视化 HTML 关系图openpyxlpandas 写 Excel 的底层依赖需要注意版本号不是固定不变的。实际安装时如果遇到依赖冲突可以去掉版本号重新安装优先保证本机环境能跑通。2.2 原文数据从哪来《钟馗斩鬼传》是古本小说不同整理本的校订、回目、用词会有差异。不要随便从一个未知网页复制全文否则可能遇到乱码、缺章、带广告噪声等问题。推荐的做法是先手头确认一份你拥有授权或明确允许使用的整理文本保存为data/raw/zhongkui.txt编码统一使用 UTF-8。如果文件是从其他编码转过来的优先另存为utf-8-sig这样 Python 读取时可以自动跳过 BOM 头。读取原始文本前先做一次简单的完整性检查from pathlib import Path raw_text Path(data/raw/zhongkui.txt).read_text(encodingutf-8-sig) print(字符数:, len(raw_text)) print(raw_text[:300])如果输出开头是乱码说明文件编码不是 UTF-8需要先转换。如果文件里面包含大量 web 页面残留的“下一页”“返回目录”等内容也要在清洗阶段处理。注意原始文本一旦确认无误立刻备份一份到data/raw/zhongkui_backup_日期.txt。清洗脚本绝不能原地覆盖原始文件否则后面调整规则时没有基线可对。2.3 项目目录结构为了方便跑多个脚本先把目录结构固定下来。推荐这样组织text-mining-zhongkui/ ├── data/ │ ├── raw/ │ │ └── zhongkui.txt │ └── cleaned/ ├── config/ │ ├── characters.txt │ └── places.txt ├── scripts/ │ ├── 01_clean.py │ ├── 02_segment.py │ ├── 03_entities.py │ └── 04_export.py ├── output/ │ ├── result.json │ ├── events.xlsx │ └── relations.gexf └── requirements.txtdata/cleaned放清洗后的章节文本config放人物词表和地点词表output放最终结果。这样脚本、数据、配置互相隔离后面调试时不用翻乱文件。3. 清洗原文与章节切分清洗的目标是去掉噪声保留正文。章回体小说最常见的噪声包括空白字符、全角空格、回目标题前的解说、出版者注释、页面页脚等。这一阶段不需要做语义理解只需要让文本干净到能被切分。3.1 去除空白和多余空行第一步先把连续空白字符压缩成单个空格并把连续三个以上的换行压缩为两个换行。这样不会影响后续按句号切句还能让中间结果更易读。import re def remove_noise(text): text re.sub(r[ \t\u3000], , text) text re.sub(r\n{3,}, \n\n, text) return text.strip()这里把全角空格\u3000也替换掉了。原始整理文本如果是从 PDF 转出来的全角空格经常出现不处理会影响统计。3.2 按回目切分章节章回体小说的回目标题通常写成“第一回”“第二回”“第十回”等。用正则可以根据这些标记切分章节。RE_CHAPTER re.compile(r第[0-9一二三四五六七八九十百千零两][回章卷]) def split_chapters(text): parts RE_CHAPTER.split(text) titles RE_CHAPTER.findall(text) chapters [] for index, (title, body) in enumerate( zip(titles, parts[1:]), start1 ): content body.strip() if not content: continue chapters.append({ id: index, title: title.strip(), content: content, }) return chaptersRE_CHAPTER.split会按回目把文本切开findall会拿回匹配到的标题。注意parts[0]通常是回目前面的引子或出版说明这里直接丢弃。如果原始文本存在“楔子”“引首”等独立段落需要单独处理不能混进第一回。切分后把结果保存到data/cleaned/chapters.jsonimport json from pathlib import Path chapters split_chapters(remove_noise(raw_text)) Path(data/cleaned/chapters.json).write_text( json.dumps(chapters, ensure_asciiFalse, indent2), encodingutf-8, ) print(章节数:, len(chapters))检查点这里的章节数应该和你手里的目录一致。如果少了多半是回目标题写法特殊比如“第一回”中间有空格需要先看一批标题。3.3 按句子切分关系抽取和事件抽取都需要以句子为单位。中文没有天然的单词边界但有句号、问号、感叹号、分号等结束标记。用正则切分句子SENT_SPLIT re.compile(r(?[。])) def split_sentences(chapters): for chapter in chapters: content chapter[content] sentences [ s.strip() for s in SENT_SPLIT.split(content) if s.strip() ] chapter[sentences] sentences chapter.pop(content, None) return chapters这里使用了正则中的(?...)后行断言意思是只在句末标点之后切分不丢弃标点。这样每一句话仍然保留原来的句号或问号便于后续打印原始证据。保存句子版本的章节数据chapters split_sentences(chapters) Path(data/cleaned/sentences.json).write_text( json.dumps(chapters, ensure_asciiFalse, indent2), encodingutf-8, )到这里原始文本已经变成“章节 句子”的结构化中间数据。后续所有的命名实体、关系、事件抽取都建在这份数据上。3.4 清洗阶段最容易被忽略的坑第一个坑是回目标题不统一。有的版本写“卷一”有的写“第一回”有的写“第一回 钟馗降生”。如果只有一套正则很容易漏掉部分章节。建议先运行RE_CHAPTER.findall(raw_text[:10000])看看实际出现了哪些格式再决定要不要扩展正则。第二个坑是书中的诗词、赞语夹杂在正文里。诗词对关系抽取没有帮助但不会影响正确性可以选择保留。如果诗句过长导致句子切分异常可以增加按逗号切句的规则不过这会增加噪声需要权衡。第三个坑是重复段落。一些整理本会在每回开头重复上一回末尾的一句话或者回末有“下回分解”。这些内容不影响章节计数但会影响事件统计的权重。如果发现某句话被统计了两次要先回到原始文本确认是不是重复段落。4. 构建人物和地点词库命名实体识别是文本抽取的核心。传统中文 NLP 可以依靠训练好的模型但古本小说有大量生僻词、异体字和人名别名直接用通用模型效果并不好。更稳妥的方式是维护一份自定义词表配合 jieba 分词使用。4.1 词库格式与维护方式在config目录下维护两个文本文件config/characters.txt示例# 人物词表一行一个支持注释 钟馗 判官 阎君 小鬼 大鬼config/places.txt示例# 地点词表一行一个 森罗殿 奈何桥 凌霄殿注意上面的词表只是演示格式不代表《钟馗斩鬼传》里一定出现了这些词。实际项目里需要根据你手头版本的原文回目、人物表和地名表来补充。词表宁多勿少因为后面会用实体是否出现在句子中来判断多一个词不会破坏结果少了就会漏实体。4.2 加载词表并注册到 jiebaimport jieba from pathlib import Path def load_words(path): words [] with open(path, encodingutf-8) as f: for line in f: line line.strip() if not line or line.startswith(#): continue words.append(line) return words characters load_words(config/characters.txt) places load_words(config/places.txt) for word in characters places: jieba.add_word(word, freq20000, tagn)freq20000表示把这个词在词典中的词频调高让 jieba 尽量把它当成一个完整词。tagn表示名词。如果某个词还是被切开可以额外使用jieba.suggest_freq(word, True)for word in characters places: jieba.suggest_freq(word, True)tuneTrue会调整默认词频强制让这个词更容易被识别。使用时要观察是否影响了正常句子切分如果出现误切可以把freq调低或者去掉。4.3 在句子中定位实体有了词表后最简单的实体定位方式就是字符串匹配def find_entities(sentence, entity_list): found [] for entity in entity_list: if entity in sentence: found.append(entity) return found这个办法虽然简单但非常稳定。它不依赖模型推理也不会把“钟馗”识别成“时钟”之类的现代词。缺点是如果实体别名太多比如“钟馗”又被称作“钟进士”“钟公”词表里必须同时收录否则会漏。为了减少重复计算在读入句子后先做一次实体定位all_sentences [] for chapter in chapters: for sentence in chapter[sentences]: all_sentences.append({ chapter_id: chapter[id], sentence: sentence, entities: find_entities(sentence, characters places), })这样后面统计关系时不需要反复find直接遍历entities列表即可。4.4 词表迭代的节奏第一次运行后统计实体出现的句子数按频率排序from collections import Counter entity_counter Counter() for item in all_sentences: for ent in item[entities]: entity_counter[ent] 1 for ent, count in entity_counter.most_common(50): print(ent, count)高频词里的非人物、非地点词说明词表需要清理。漏掉的实体则体现在“很多句子没有实体”上。可以把没有命中的句子打印出来看原文里到底用了什么称谓再决定是否加入词表。词表迭代通常要做三轮以上第一轮保证高频实体不丢第二轮处理别名第三轮处理生僻地点。5. 抽取角色关系与降妖事件实体抽取完成后下一步是根据实体之间的共现关系推测角色关系再根据触发词抽取出战斗、收服等事件。这一阶段是规则抽取的核心也是噪声最多的环节。5.1 用共现指标生成角色关系假设同一句话里出现的两个实体存在某种关系这叫共现关系。虽然它不一定是真实关系比如“钟馗”和“判官”可能只是同时出现在一场朝会里并不代表他们有直接互动但共现频率高通常说明两个角色在同一场景中反复出现值得策划关注。from collections import Counter def extract_relations(all_sentences): pair_counter Counter() for item in all_sentences: entities list(dict.fromkeys(item[entities])) if len(entities) 2: continue for i in range(len(entities)): for j in range(i 1, len(entities)): pair tuple(sorted([entities[i], entities[j]])) pair_counter[pair] 1 relations [ { source: source, target: target, weight: weight, sentence_count: weight, } for (source, target), weight in pair_counter.most_common() ] return relations这里用dict.fromkeys去掉同一句中的重复实体。如果一句话里“钟馗”出现了三次只算一次否则会虚高权重。共现频率高只能说明两个角色常同时出现要形成真正的“敌对关系”“上下级关系”还需要结合事件抽取结果人工标注。5.2 基于触发词的事件抽取降妖战斗类事件可以用触发词识别。比如“斩、杀、捉、斗、收、拿”这些词通常出现在战斗或收服场景中。设定一个触发词表TRIGGERS { 斩: combat, 杀: combat, 斗: combat, 捉: capture, 收: capture, 拿: capture, }事件抽取规则先找到触发词的位置再找最近的两个实体一个在触发词左边作为主语一个在右边作为宾语。def extract_events(all_sentences, entities, triggers): events [] for item in all_sentences: sentence item[sentence] for trigger, etype in triggers.items(): tpos sentence.find(trigger) if tpos 0: continue subject None object_ None for ent in entities: pos sentence.find(ent) if pos 0: continue if pos tpos: if subject is None or abs(pos - tpos) abs( sentence.find(subject) - tpos ): subject ent elif pos tpos: if object_ is None or abs(pos - tpos) abs( sentence.find(object_) - tpos ): object_ ent if subject and object_: events.append({ chapter_id: item[chapter_id], type: etype, trigger: trigger, subject: subject, object: object_, sentence: sentence.strip(), }) return events这个规则能处理“钟馗斩妖”“钟馗把小妖捉住”这类主谓宾相对正常的句子。但它无法处理被动句比如“小妖被钟馗斩杀”因为“小妖”出现在触发词左边会被错误识别成主语。所以事件抽取结果一定要经过人工校验。5.3 输出统一 JSON把实体、关系、事件放在同一个 JSON 文件里方便策划和程序共用import json from datetime import datetime def export_result(characters, places, relations, events): result { project: zhongkui-game-design, extracted_at: datetime.now().isoformat(timespecseconds), entities: { characters: characters, places: places, }, relations: relations, events: events, } Path(output/result.json).write_text( json.dumps(result, ensure_asciiFalse, indent2), encodingutf-8, )这份 JSON 的 schema 不复杂但已经足够支撑策划工作。事件表里带有chapter_id可以直接定位回原文关系表里带有共现权重可以排序后优先关注高频关系。注意共现不等于关系所有自动抽取出来的关系都必须经过人工抽检。抽检比例建议不低于 20%。6. 知识图谱可视化与策划应用单纯看 JSON 表格不够直观。把关系数据渲染成图策划一眼就能看出核心角色、次级角色和孤立角色。常用方案是 NetworkX 导出 GEXF再用 Gephi 做深度分析或者直接生成 pyecharts 的 HTML 图方便在浏览器里查看。6.1 用 NetworkX 生成关系图文件import networkx as nx def build_graph(relations): G nx.Graph() for rel in relations: G.add_edge( rel[source], rel[target], weightrel[weight], ) nx.write_gexf(G, output/relations.gexf) return GGEXF 是 Gephi 支持的图格式。导出后可以用 Gephi 打开调整布局、颜色、节点大小。节点大小可以映射为度数边粗细映射为共现次数。这样能快速看出谁是最核心的角色。6.2 用 pyecharts 生成浏览器关系图如果不想额外安装 Gephi直接用 pyecharts 生成 HTML 更方便。from pyecharts import options as opts from pyecharts.charts import Graph nodes [ {name: 钟馗, symbolSize: 60}, {name: 小鬼, symbolSize: 30}, ] links [ {source: 钟馗, target: 小鬼}, ] graph ( Graph() .add( , nodesnodes, linkslinks, repulsion1000, edge_length100, ) .set_global_opts(title_optsopts.TitleOpts(title钟馗斩鬼传角色共现关系)) ) graph.render(output/graph.html)repulsion控制节点之间的斥力值越大节点越分散edge_length控制边的长度值越大图越疏松。真实数据中节点数量多建议先用repulsion2000、edge_length150起步再根据效果调整。6.3 从事件表反推关卡和任务草稿拿到了结构化事件策划可以通过一个映射规则把它变成任务设计初稿。以下是示例映射方式事件字段关卡设计用途chapter_id定位到具体章节便于查原文subject任务发起者或玩家扮演角色object关卡 BOSS 或交互对象trigger战斗方式关键词type决定玩法类型战斗或捕获sentence原始剧情文本直接作为文案素材比如一个事件记录是{ chapter_id: 3, type: combat, trigger: 斩, subject: 钟馗, object: 小妖, sentence: 钟馗挥剑斩向小妖。 }任务设计师可以把它改写成任务地点第 3 回对应场景敌人小妖目标击败小妖触发条件进入该场景后自动触发演出旁白钟馗挥剑斩向小妖这是结构化数据进入游戏设计的最小闭环。实际项目中还要补充地图资源、AI 行为、奖励掉落、剧情演出等字段不能只依赖文本抽取结果。7. 运行验证与结果检查自动抽取的每一类结果都要能验证。验证不是只确认脚本跑完没有报错而是确认结果符合原著预期。7.1 完整运行流程按顺序运行下面几个脚本python scripts/01_clean.py python scripts/02_segment.py python scripts/03_entities.py python scripts/04_export.py如果中间某一步失败先看错误信息再回到对应阶段排查。比如01_clean.py报错大概率是文件路径或编码问题03_entities.py报错大概率是词表文件格式问题。7.2 结果检查清单手动检查时按下面的顺序过一遍章节数是否等于目录回目数。每个章节的句子数是否正常是否有章节为空。实体列表里是否全是人物或地点没有混入无关高频词。共现关系表中最高频的几对角色是否符合原著印象。事件表中随机抽取 5 条事件回到原文确认主语、宾语是否正确。生成的关系图是否有孤立节点孤立节点如果是人物说明其他句子里的称谓没进词表。快速统计命令import json from pathlib import Path data json.loads(Path(output/result.json).read_text(encodingutf-8)) print(章节数:, max(event[chapter_id] for event in data[events])) print(事件数:, len(data[events])) print(关系数:, len(data[relations]))这里用max(event[chapter_id])来估计章节数只适合事件覆盖了每一章的情况。如果某些章节没有事件就用保存章节时的列表长度来校验。7.3 人工抽检事件准确率事件抽取的准确率可以用一个最简单的方式评估随机抽 100 条事件人工判断主语、宾语、触发词是否准确然后计算准确率。如果准确率低于 80%建议先优化触发词表和词表再考虑引入更复杂模型。抽检时把事件输出成 Excel方便多人核对import pandas as pd df pd.DataFrame(data[events]) df.to_excel(output/events.xlsx, indexFalse)Excel 里每一行就是一条候选事件策划和主文案可以直接在表里标记“正确/错误/需修改”。这是把自动化结果推进到人工审核流程的好办法。8. 常见问题与排错路径8.1 读取文件时报 UnicodeDecodeError现象执行read_text(encodingutf-8-sig)时抛出错误。常见原因文件实际上是 GBK、GB2312 或 ANSI 编码。检查方式from pathlib import Path raw Path(data/raw/zhongkui.txt).read_bytes() print(raw[:10])看前几个字节可以判断是否有 BOM但无法直接判断编码。更稳妥的办法是用编辑器打开文件看右下角编码。解决方案把文件另存为 UTF-8或者用gb18030读取raw_text Path(data/raw/zhongkui.txt).read_text(encodinggb18030)预防建议所有原始文本统一转成utf-8-sig保存并在项目文档里写清楚编码要求。8.2 章节切分后数量不对现象打印章节数时发现比目录少。常见原因回目写法不统一比如“第一回”和“第一回钟馗降生”混用某些章节标题被错误换行。检查方式print(re.findall(r第[^回]{1,10}回, raw_text[:5000]))查看实际出现的标题格式。解决方案调整正则加入\s*处理空格或者使用更宽泛的匹配规则。RE_CHAPTER re.compile(r\s*第[0-9一二三四五六七八九十百千零两]\s*[回章卷]\s*)预防建议在切分前先输出目录中的所有匹配结果确认每一个标题都覆盖到。8.3 jieba 把人物名切成多个词现象实体匹配时找不到“钟馗”或者被切成了“钟”“馗”。常见原因词典里没有这个词或者词频太低。检查方式print(jieba.lcut(钟馗提剑进入森罗殿))如果输出[钟, 馗, 提剑, ...]说明词没有被正确识别。解决方案jieba.add_word(钟馗, freq20000, tagn) jieba.suggest_freq(钟馗, True)预防建议人物词表、地点词表单独维护每次增补词后重新跑完整流程并把结果 diff 出来审查。8.4 关系抽取噪声过大现象事件表里出现大量不相关的角色关系比如“钟馗”和“阎君”在十句话里共现但实际只是普通朝会场景。常见原因共现窗口太大同一句话里只要出现两个实体就认为有关系。解决方案把共现窗口从整句缩小到相邻短语或者加入中间动词过滤。比如只保留两个实体之间距离不超过 6 个字的共现。def extract_relations_with_window(all_sentences, entities, window6): pair_counter Counter() for item in all_sentences: sentence item[sentence] positions [] for ent in entities: pos sentence.find(ent) if pos 0: positions.append((pos, ent)) positions.sort() for i in range(len(positions)): for j in range(i 1, len(positions)): if positions[j][0] - positions[i][0] window: pair tuple(sorted([positions[i][1], positions[j][1]])) pair_counter[pair] 1 return pair_counter预防建议先用全句共现拿到候选再用窗口过滤最后人工抽检。不要一上来就追求高精度避免漏掉真实关系。8.5 pyecharts 生成的 HTML 图为空白现象浏览器打开graph.html后只有标题没有图。常见原因pyecharts 在渲染时使用了外部 CDN 加载依赖库网络不通或资源被拦截。检查方式打开 HTML 源码看是否引入了echarts.min.js外链。解决方案换用 NetworkX Matplotlib 生成静态图片或者把 echarts 库下载到本地静态目录。import matplotlib.pyplot as plt import networkx as nx G build_graph(data[relations]) plt.figure(figsize(12, 8)) nx.draw(G, with_labelsTrue, node_size500, font_size10) plt.savefig(output/graph.png, dpi150)预防建议如果交付给策划时浏览器环境不受控优先使用静态图片或 Gephi而不是 HTML。8.6 原始文本版本混乱导致结果不一致现象两个同事用不同的整理本跑出来的人物表和事件表差异很大。常见原因文本来源不同回目、用词、人物别名不一致。解决方案在result.json中增加source_version字段记录文本版本、来源、整理日期。每一次分析结果都要绑定版本号。预防建议把原始文本纳入 Git 版本管理但要注意文本授权。如果文本不允许公开分发只保存在本地仓库并设置好权限。9. 生产环境扩展与最佳实践这套规则抽取流程适合项目起步和原型验证。如果要做更大规模的游戏 IP 文本拆解还需要从三方面扩展算法、存储和流程。9.1 从规则到模型规则抽取最大优势是可控、可解释、不需要标注数据。但缺点也很明显遇到被动句、省略主语、代词指代时准确率会下降。生产环境可以考虑引入命名实体识别和关系抽取模型。方案优点缺点适合场景正则 词表简单可控容易维护依赖词表被动句识别差小规模文本、原型验证通用 NER 模型识别新词能力强古文本表现不稳定快速跑通候选实体微调 NER 模型领域效果好需要标注数据固定 IP 的长期拆解大模型 Prompt 抽取规则表达灵活成本高、结果不稳定批量候选抽取仍需人工审核如果选择模型路线建议先用规则抽取生成一批候选数据人工校对后作为训练集。这样能把已有结果复用起来而不是从零标注。9.2 存储与版本管理result.json适合小项目但多人协作时会遇到覆盖冲突。建议把实体、关系、事件分别存入 SQLite 或 PostgreSQL并增加版本字段。CREATE TABLE events ( id INTEGER PRIMARY KEY AUTOINCREMENT, source_version TEXT NOT NULL, chapter_id INTEGER NOT NULL, event_type TEXT NOT NULL, subject TEXT NOT NULL, object TEXT NOT NULL, trigger_word TEXT, sentence TEXT, verified INTEGER DEFAULT 0, created_at TEXT );verified字段用于标记人工审核状态。每次自动抽取完先插入一批verified0的新数据策划审核后改成1。这样既能保留自动结果也能沉淀人工知识。9.3 可持续的游戏化解读流程游戏化解读不是一次性的活动。随着版本更新、新剧情加入、角色扩充需要反复跑管线和人工审核。推荐形成这样一个闭环原始文本入库并打版本号。自动清洗、切分、分词、实体识别。事件和关系抽取输出待审核表。策划与文案人工审核标记正确或修改。审核后的数据进入设计库供任务和关卡系统使用。新增文本后重复 1-5 步。每轮迭代都要保留上一次的词表、触发词表和审核记录否则模型或规则的改动会让历史结果不可比。9.4 可复用清单把上面所有实践经验浓缩成一张清单在项目开始前过一遍原始文本备份禁止清洗脚本覆盖原文件。统一编码为utf-8-sig并在项目文档中说明。人物词表和地点词表独立存放使用配置化管理。先确认回目标题格式再写切分正则。每次增补词表后重新跑全流程并对比结果。共现关系和事件抽取结果必须人工抽检。结果文件中记录抽取时间、文本版本和词表版本。用 Excel 待审核表驱动策划人工审核。生产环境使用数据库存储事件和关系不直接暴露 JSON。规则抽取的结果可以作为训练集不能直接当作最终标注数据。9.5 最后提醒做神话 IP 游戏化解读时最容易犯的错误是迷信“情报”和“爆料”用二手结论替代原文分析。原文文本才是唯一可靠的素材来源。即使你手上只有一份 txt 文件也能通过本文介绍的流程把它拆成角色、地点、关系、事件四类结构化数据再去支撑后续的任务设计。对于一个以文本叙事为核心的 IP 项目先跑通这套文本拆解流程比一开始就讨论单张原画或单个系统设计更有实际价值。