
如果只看标题I wont read LLM authored fiction是一句很带情绪的表态。但放到技术语境里它真正的问题其实是大语言模型到底能不能写出“值得被读完”的长篇虚构作品短篇、营销文案、爽文开头现阶段的 LLM 都能生成得像模像样一旦拉到几十万字的长篇角色会忘记人设时间线会对不上前文埋的伏笔后文直接失踪。这不是一个纯粹的审美问题而是技术问题。这篇文章不打算跟你争论“AI 写作有没有灵魂”而是从工程角度拆解为什么 LLM 写不长、写不乱那么难如果一定想让 LLM 参与长篇虚构写作应该怎么设计系统本地部署需要什么条件怎么验证生成质量怎么把小说生成管线做成接口和批量任务整篇文章会围绕这几个问题展开最后给出一套可以直接借鉴的工程化思路。适合的读者也很明确正在做 LLM 长文本应用、LLM Agent、内容生成工具或者单纯好奇“LLM 写小说到底哪里不行”的开发者。看完你会得到一套可以落地的验证方法而不是一句“AI 写不了小说”的结论。1. 核心能力速览在展开技术细节之前先把这条讨论线的关键信息整理成一张表。注意这个话题不是某个具体开源项目而是一类 LLM 长文本生成课题所以表格里的内容更多是工程分析和通用能力而不是某个仓库的功能清单。能力项说明话题类型LLM 长文本生成、虚构叙事质量、写作 Agent核心问题上下文窗口限制、角色一致性、时间线一致性、风格一致性、创意重复可落地方向设定生成、章节大纲、正文初稿、一致性校验、批量分支续写典型硬件参考本地推理建议 8G 显存以上起步实际以模型版本和量化精度为准常见开源模型Qwen、Llama、DeepSeek 等长文本模型系列版本需按项目测试启动方式本地推理框架Ollama、vLLM 等或云端 API按实际方案选择是否支持 API可以封装成 HTTP 服务需要自行实现或使用推理框架自带接口是否支持批量任务可以通过任务队列和脚本批量生成章节、分支结局、候选片段自动化程度中建议保留人工编辑闭环不适合直接端到端输出长篇成品主要风险AI 生成内容标注、训练数据版权、虚构内容误导、数据隐私从这张表可以看出来LLM 写小说这件事并不是“能不能生成文字”的问题而是“能不能在几十万字尺度上维持结构”的问题。后面所有技术方案都是围绕这个目标展开的。2. “不读 LLM 小说”的争议点到底在哪“I wont read LLM authored fiction”这句话在开发者社区里能引发讨论本质上是因为它触及了三个层次的问题成本、质量和风险。这三个层次混在一起就会变成一场说不清结论的争论。先把它们拆开。2.1 成本问题阅读时间是不可逆的读小说是一件高成本的事。一个长篇通常需要几十个小时用户投入的不仅是时间还有情绪和注意力。如果一个故事读到一半出现逻辑崩塌、角色性格飘移、伏笔无法回收读者会产生很强的挫败感。这种体验损失比“看一段 AI 生成的营销文案”要严重得多因为后者只有三十秒的成本。所以很多人反对“读 LLM 小说”反对的不是技术本身而是反对在长阅读场景中承担这种质量风险。短文本生成可以容错长篇小说不能。2.2 质量问题长文本一致性是硬伤从技术角度看这才是关键。LLM 在生成短段落时表现很好是因为它的训练目标就是预测下一个 token局部语义连贯。但长篇小说要求的是角色的动机、能力、性格在多个场景中保持一致时间和空间线不出现冲突设定、物品、人际关系能跨章节复用伏笔在几十章之后能被回收文风在长时间生成中不发生漂移。这些要求远远超过“下一个 token 预测”的能力范围。LLM 没有真实的记忆也没有一个全局的“故事状态”概念。它的每一次生成都只依赖当前上下文和参数推断。上下文一旦截断、摘要、或者被其他信息稀释前面埋下的细节就可能丢失。2.3 风险问题版权与可信度还有一层是版权和标注问题。训练数据中可能包含受版权保护的小说内容模型生成出来的文本可能存在语义上的近似。如果把它用于商业发布需要人工复核和来源验证。同时AI 生成内容在很多平台上有明确标注要求这一点在实际产品里不能忽略。所以把“I wont read LLM authored fiction”当作一个技术问题来看核心就变成了能否通过工程手段缓解长文本生成的一致性问题让 LLM 从“能写”变成“能写完”。3. LLM 长篇叙事写不长的四个技术瓶颈3.1 上下文窗口与信息稀释现在的开源模型普遍支持 8K、32K、128K 甚至更长的上下文窗口。但上下文长不代表模型能充分利用。大量研究表明模型对长上下文的中间部分关注度会下降也就是“lost in the middle”现象。对小说而言前文的设定、人物关系、事件细节恰恰属于容易丢失的中间信息。因此简单地把整本小说塞进上下文然后让模型继续写不是正确做法。上下文越长显存占用越高推理速度越慢而信息利用效率反而可能下降。这是第一道门槛。3.2 KV Cache 显存开销长上下文推理时KV Cache 的增长是平方级的内存压力。比如一个 7B 模型在 4K 上下文中可能只占 6G 显存但拉到 32K 以上显存占用会明显上升。对于 8G 显存的消费级显卡长文本生成很容易触碰 OOM。这就是为什么很多长文本应用实际采用的是“分段生成 外部记忆”而不是单次长上下文生成。分段生成时每一段控制在模型擅长的长度内再用外部状态文件把关键信息保存下来。3.3 角色与设定一致性角色一致性是最容易被察觉的问题。第一章里 A 角色是个沉默寡言的人到第十章突然话痨B 角色的眼睛颜色在第三章是蓝色到第十五章变成棕色。模型没有主动去维护一个角色档案每个 token 的生成都只是概率选择。要解决这个问题不能靠模型自觉得靠系统设计。把角色档案、物品清单、地点状态、时间线单独保存每章生成时显式注入关键信息生成后再做一致性校验。3.4 文风漂移与叙事节奏文风漂移比角色一致性更隐蔽。前文是冷峻的短句风格后文突然变成绵长的心理描写前文节奏快、冲突密集后文突然大段写景。模型本身没有“风格锚点”只能依赖上下文中的风格样本。如果上下文里恰好混入了大量不同类型的内容风格就会漂移。4. 工程化方案Agent 外部状态管理如果要把 LLM 长篇写作做成一个可用的系统推荐的做法是多模块 Agent 管线 外部状态管理。这个方法不是让一个模型一口气写完一整本小说而是把写作拆成几个子任务每个子任务由不同的提示词、模型调用或 Agent 节点完成中间用结构化数据JSON / Markdown / 数据库传递状态。4.1 管线模块划分一个典型的虚构写作管线可以拆成六个模块模块输入输出世界观设定一句话选题地理、魔法/科技规则、势力、历史事件角色卡生成世界观设定每个角色的目标、性格、能力、秘密剧情大纲设定 角色卡分卷情节、章节梗概、伏笔计划章节正文生成大纲 角色卡 前情摘要章节正文一致性校验章节正文 设定 时间线冲突列表修订重写正文 冲突列表修订后的正文每个模块之间通过 JSON 文件或数据库传递数据。这样做的好处是模型每次只生成一个相对聚焦的子任务输出质量更稳定某个环节出错只需要重跑该环节不用整个管线重来工程上更容易扩展比如后续想加视频脚本、互动小说、游戏支线只需要替换或新增模块。4.2 用一个状态文件维护故事核心信息这里给出一个简化版的 Python 伪代码框架演示“外部状态管理”的核心思路。实际使用时你需要根据项目结构调整数据结构并在关键位置换成真正的 LLM 调用。import json from typing import Dict, Any import requests # 状态文件示例存一个故事的核心记忆 def load_state(path: str) - Dict[str, Any]: with open(path, r, encodingutf-8) as f: return json.load(f) def save_state(state: Dict[str, Any], path: str) - None: with open(path, w, encodingutf-8) as f: json.dump(state, f, ensure_asciiFalse, indent2) def build_chapter_prompt(state: Dict[str, Any], chapter_outline: str) - str: # 把设定、角色、时间线、前情摘要压缩成提示词 characters json.dumps(state[characters], ensure_asciiFalse) timeline json.dumps(state[timeline], ensure_asciiFalse) summary state.get(recent_summary, ) prompt f你是小说写作助手请基于以下状态信息生成章节正文。 【核心设定】 {state.get(world, )} 【角色档案】 {characters} 【当前时间线】 {timeline} 【前情摘要】 {summary} 【本章大纲】 {chapter_outline} 要求 1. 保持角色性格和能力一致。 2. 不引入设定之外的新超能力。 3. 埋下本章需要的伏笔。 return prompt def call_llm(prompt: str, api_url: str, max_tokens: int 2000) - str: # 通用调用模板实际请求体以你部署的推理服务为准 payload { model: your-model-name, prompt: prompt, max_tokens: max_tokens, temperature: 0.8, } response requests.post(api_url, jsonpayload, timeout120) response.raise_for_status() return response.json()这个框架想表达的核心思想是不要在提示词里堆整本小说原文而是把“状态信息”提炼成结构化片段再拼到提示词里。角色档案、时间线、前情摘要都是状态文件的一部分。随着章节推进状态文件不断更新。4.3 用摘要维护长期记忆长篇小说不可能永远把全文塞进上下文。比较通用的做法是每生成 N 章就对前面的内容做一轮摘要。摘要内容不是简单的“第 1 章讲了什么”而是要保留已出场角色及其当前状态已发生的关键事件尚未回收的伏笔当前时间线和地点主要冲突和人物关系变化。这份摘要会替换掉原文作为后续章节生成的“前情提要”。这样做的代价是细节丢失但换取的是上下文可控。如果某些细节特别重要可以单独存成“伏笔表”或“事件表”专门在提示词中保留。5. 本地部署环境准备如果你想把这套方案接到本地开源模型上需要先准备环境。下面是一份通用检查清单实际版本以你的模型和系统为准。5.1 操作系统与工具链项目建议操作系统Windows 11 / Ubuntu 20.04 / macOS均可Linux 推理体验通常更好Python3.10 以上建议使用虚拟环境推理框架Ollama、LM Studio、vLLM、llama.cpp任选一种模型格式GGUF 或 Hugging Face 格式按框架选择显卡驱动NVIDIA 用户建议更新到较新驱动CUDA 与框架版本匹配即可磁盘空间7B 量化模型约 4G 到 6G13B 约 8G 到 12G20B 以上需要更多5.2 显存与推理规模本地部署长文本生成时显存是一个无法回避的约束。模型规模显存参考适合场景7B 量化6G 起短章节生成、摘要模块13B 量化10G 起更高质量的正文生成30B 及以上24G 起长上下文、复杂世界观不同模型量化精度如 FP16、BF16、INT8、INT4对显存占用影响很大实际需要以本机测试为准。如果你的显卡只有 8G 显存优先考虑 7B 或 13B 的量化版本并把生成长度控制在 1000 token 以内。5.3 依赖安装示例假设你选择使用 Python 调用本地推理服务可以这样组织项目依赖pip install requests tqdm pydantic如果你使用 vLLM 或 Ollama它们有各自的安装方式建议按官方文档操作。这里不建议把所有依赖都写进一个万能脚本最好根据项目推进逐步安装。6. 功能测试与效果验证验证 LLM 长篇叙事质量不能只靠“读起来顺不顺”。在工程里我们需要可量化的测试方法和判断标准。6.1 小规模测试三章连续生成先做一个小规模测试。目标不是马上写完整本书而是验证系统的状态管理是否有效。测试步骤如下编写一份简单的世界观设定100 字左右。创建两个测试角色每个角色有 3 个能力、1 个秘密、1 个目标。让系统生成第一章大纲再生成第一章正文。把第一章的关键事实更新到状态文件中。让系统基于新状态生成第二章重复这个过程。在第三章结尾检查角色能力、秘密、目标是否发生了改变。判断成功的标准是在没有任何人工修正的情况下三章中的角色能力、秘密、目标、时间线保持全部一致。失败时排查什么先看状态文件是否更新再看提示词中是否真的把关键状态注入进去最后检查模型输出是否偏离了提示词约束。6.2 用评审模型做一致性检查比较实用的做法是让另一个独立的 LLM 调用担任评审。评审模型不负责写正文只负责读章节摘要和状态文件找出冲突。这样可以形成“写作模型 评审模型”的双模型结构。def review_consistency(chapter_text: str, state: Dict[str, Any]) - str: review_prompt f 请阅读以下章节和状态档案找出所有不一致之处。 【章节正文】 {chapter_text} 【状态档案】 {json.dumps(state, ensure_asciiFalse)} 请输出 1. 角色能力冲突列表 2. 时间线冲突列表 3. 设定冲突列表 4. 伏笔遗漏列表 如果没有冲突直接输出无。 # 调用另一个 LLM return call_llm(review_prompt, api_urlhttp://127.0.0.1:8000/v1/completions)6.3 长文本压力测试三章一致还不够还需要做长文本压力测试。具体做法是连续生成 20 章每章 500 词测试以下指标测试项测试方法参考标准角色一致性检查角色卡中的所有特征是否始终生效全部匹配时间线一致性统计章节中的时间推进是否有冲突无冲突伏笔回收率统计前 10 章埋下的伏笔是否在后文被回收或提及不低于 60%文风漂移让评审模型比较前 5 章和后 5 章的用词与句式分布风格差异不明显重复度统计高频短语和事件模式重复情况无大面积重复这些指标不需要一开始全部做先跑通前三项再逐步增加。7. 接口 API 与批量任务当系统验证通过后下一步就是把小说生成管线封装成 HTTP 接口方便其他工具调用或者批量生成候选内容。7.1 封装一个小说生成 API下面给出一个极简的 FastAPI 服务示例。注意这个示例只演示接口结构模型调用部分需要你替换成实际部署的推理服务地址。from fastapi import FastAPI, HTTPException from pydantic import BaseModel import json import requests app FastAPI() class ChapterRequest(BaseModel): state_path: str chapter_outline: str class ChapterResponse(BaseModel): chapter_text: str updated_state_path: str app.post(/api/generate_chapter, response_modelChapterResponse) def generate_chapter(req: ChapterRequest): # 1. 加载状态 with open(req.state_path, r, encodingutf-8) as f: state json.load(f) # 2. 组装提示词 prompt build_chapter_prompt(state, req.chapter_outline) # 3. 调用你的推理服务 try: response requests.post( http://127.0.0.1:8000/v1/completions, json{prompt: prompt, max_tokens: 2000}, timeout120, ) response.raise_for_status() chapter_text response.json()[choices][0][text] except Exception as e: raise HTTPException(status_code500, detailstr(e)) # 4. 更新状态文件简化处理实际需要抽取关键信息后写入 updated_path req.state_path.replace(.json, _updated.json) with open(updated_path, w, encodingutf-8) as f: json.dump(state, f, ensure_asciiFalse, indent2) return ChapterResponse( chapter_textchapter_text, updated_state_pathupdated_path, )这个服务的启动方式假设你已经安装了 FastAPI 和 uvicornuvicorn api_server:app --host 127.0.0.1 --port 7860启动后可以用下面这个 curl 请求测试接口curl -X POST http://127.0.0.1:7860/api/generate_chapter \ -H Content-Type: application/json \ -d { state_path: ./state/story_001.json, chapter_outline: 主角在集市发现一个神秘的包裹 }需要注意上面的/v1/completions请求体格式只是一个通用模板不同推理框架的参数名可能不同。实际调用请以你部署的服务文档为准。7.2 批量生成能力批量任务的目的是在给定同一份世界观设定和角色卡的前提下生成多个不同的剧情走向供创作者挑选。一个比较简单的做法是写一个批量脚本用进程池并发调用接口。from concurrent.futures import ThreadPoolExecutor, as_completed import requests API_URL http://127.0.0.1:7860/api/generate_chapter OUTLINES [ 主角选择救下受伤的陌生人, 主角放弃救人独自前往遗迹, 主角将陌生人交给教会换取情报, 主角与陌生人结盟寻找共同目标, 主角暗中跟踪陌生人发现更大阴谋, ] def generate_one(outline: str, idx: int): payload { state_path: f./state/story_{idx}.json, chapter_outline: outline, } response requests.post(API_URL, jsonpayload, timeout180) response.raise_for_status() return idx, response.json()[chapter_text] with ThreadPoolExecutor(max_workers3) as executor: futures [ executor.submit(generate_one, outline, idx) for idx, outline in enumerate(OUTLINES) ] for future in as_completed(futures): idx, text future.result() with open(f./outputs/chapter_{idx}.txt, w, encodingutf-8) as f: f.write(text)批量任务的关键点有两个一是任务必须可重试单个任务失败不能影响整个批次二是输出结果必须能对应回输入的任务元数据方便创作者定位。8. 资源占用与性能观察本地运行长文本生成时资源占用是很多人最关心的问题。这里给出一套通用的观察方法。8.1 如何观察显存占用如果你使用 NVIDIA 显卡在 Windows 上可以用任务管理器或nvidia-smi。在 Linux 上最直接的方式是watch -n 1 nvidia-smi这样每秒刷新一次显存占用、功率、温度等信息。当你发起一次长文本生成任务时重点观察生成过程中显存的峰值而不是只看空闲时的占用。8.2 哪些因素会影响显存与速度因素影响上下文长度越长KV Cache 占用越大显存压力越高生成长度 max_tokens越长单次任务耗时越长显存峰值可能更高并发数ThreadPoolExecutor 中的并发数越多显存叠加越明显量化精度INT4 占显存最少FP16/BF16 质量更好但占用更高批大小单次请求多个样本会成倍增加显存占用降低显存占用的常见手段包括使用更小尺寸的量化模型、缩小上下文长度、用摘要替代原文、降低并发数、把不用的后端进程关掉。8.3 速度与稳定性的取舍本地推理速度通常以 token/s 为单位。消费级显卡跑 7B 量化模型的生成速度大约在 10 到 30 token/s 之间具体取决于显卡、模型、量化格式和上下文长度。如果你需要快速生成大量候选章节就要在模型尺寸、上下文长度和并发数之间做平衡。更稳妥的做法是先把所有参数调成一个能稳定运行的最小配置比如“7B 量化 4K 上下文 单并发”跑通全流程后再逐步增加上下文和并发观察显存峰值和推理速度找到边界。9. 常见问题与排查方法问题现象可能原因排查方式解决方案启动后页面打不开端口被占用或服务未启动检查日志和端口监听更换端口或重启服务生成内容重复严重temperature 设置过低或提示词约束不足查看参数配置适当提高 temperature在提示词中强调避免重复角色前后矛盾状态文件未更新检查每次生成后的状态文件写入逻辑增加关键信息抽取与状态更新步骤显存不足 OOM上下文过长或并发过高用 nvidia-smi 观察显存峰值缩短上下文、降低并发、使用更小的量化模型推理速度极慢模型过大或电脑无 GPU 加速查看主要耗时阶段换小模型、增加 GPU 或使用云端 APIAPI 调用失败接口路径或请求参数不匹配先用 curl 测试接口按推理服务文档调整请求体批量任务中途卡住单任务无超时或线程阻塞查看日志中的卡住任务设置超时、加入失败重试与单任务日志输出质量不稳定模型随机采样导致重复运行对比固定随机种子、人工复核或在管线中加入评审模型排查问题有一个通用顺序先看日志再看状态文件最后看请求参数。不要一上来就换模型很多问题出在调用逻辑而不是模型本身。10. 最佳实践与合规提醒10.1 人机协作代替全自动生成目前阶段让 LLM 独立完成一部长篇小说并达到出版水准难度很大。更现实的路线是LLM 负责生成设定、大纲、初稿和候选片段人类负责方向决策、风格把关、伏笔管理和最终修订。这样可以兼顾效率与质量。10.2 设定与状态分离不要把世界观、角色、时间线混在正文提示词里。将它们单独存储为结构化文件每章生成时显式注入。这样做的好处是角色修改只需要改状态文件不需要重写前面的章节生成下一章时也不会遗忘关键设定。10.3 明确标注 AI 生成内容如果你把 LLM 生成的内容发布到公开平台需要在显著位置标注 AI 参与生成。不同平台对 AI 生成内容的标注要求不同发布前务必确认平台规则。10.4 版权与授权使用开源模型时注意检查模型 License不同模型对商用和衍生发布有不同限制。如果你使用真实人物、真实品牌、受版权保护的虚构人物必须获得相关授权。涉及数据隐私的内容不要上传到公有云推理服务如果对隐私有要求优先选择本地部署。10.5 质量管理闭环每次生成后保留一份“状态文件快照 章节正文 评审报告”。出了问题可以回滚到任意章节。不要直接在原文件上反复覆盖否则很难定位是哪一章引入的冲突。11. 总结与下一步回到开头那个问题为什么很多人不愿意读 LLM 写的小说原因不是模型不会写句子而是模型在长尺度的结构控制上还不可靠。但这不意味着这个方向没有价值。通过 Agent 管线拆分、外部状态管理、摘要记忆、评审模型和批量任务设计我们可以把 LLM 从“只能写片段”逐渐推进到“能够辅助完成长篇创作”。如果你现在想做一次验证我建议按照这个顺序开始先用一个 7B 左右的本地模型或云端 API搭一个最小管线只做“设定 角色卡 三章生成 一致性检查”。跑通后把状态文件升级成更完整的时间线和伏笔表。再加评审模型把人工复核成本降下来。最后再考虑封装 API、做批量任务。最容易踩的坑有两个一是贪大一开始就想生成几十万字结果上下文失控二是忽略状态文件更新角色档案只在第一版生效后面全靠模型自己记。这两点都靠工程手段解决而不是靠换一个更大的模型。后续你可以尝试的方向包括互动小说里的分支管理、游戏 NPC 对话与背景故事生成、多语言环境下的文化一致性、长篇内容的自动摘要与检索增强生成。所有这些方向的底层能力本质上都是同一个东西让 LLM 在一个长期生成任务中稳定地记住自己说过什么。