本地大模型驱动:从装傻到暴露的AI剧情生成工作流
2026/9/6 13:45:28 网站建设 项目流程

这是一篇关于“反派装傻苟命,伺机搞破坏反被抓个正着”的 CSDN 技术博客。


0. 写在前面:这个标题,其实是一个 AI 项目的工作流

看到“反派装傻苟命,伺机搞破坏反被抓个正着”这个标题,第一反应可能是网文剧情,或者短视频解说文案。但放到技术语境里,它对应的是一个非常典型的AI 长剧情生成 / 多智能体博弈工作流:一个角色(反派)先隐藏意图(装傻苟命),规划行动(伺机搞破坏),最终由于环境反馈和他人观测而暴露(反被抓个正着)。

这类流程过去只能靠人工写剧本,或者用简单的文本续写模型一点一点“挤牙膏”。现在有了开源大模型 + 本地推理框架,完全可以用一套自动化流程把“动机 - 伪装 - 行动 - 暴露”的剧情链跑通,甚至批量生成多条不同结局的剧情线。本文要做的,就是拆解如何用本地模型和脚本,把这个“装傻 - 搞破坏 - 被抓”的叙述逻辑变成可重复执行的 AI 生成任务。

先说几个读者最关心的判断:本地部署需要一张 6G 以上显存的 NVIDIA 显卡(4G 显存能做量化推理但长文本吃力),支持 CPU 跑但速度会明显下降;整个流程以 Python 脚本为主,能拆成 API 服务,也能批量跑多条剧情线;不需要训练模型,直接调用开源大模型做多轮生成和条件判定即可。

1. 核心能力速览

能力项说明
项目类型本地 AI 长剧情生成 + 多智能体行动判定工作流
基础模型开源大语言模型(Qwen / ChatGLM / Llama 等本地部署版本)
显存需求6G 以上较稳;4G 需要量化模型并调低上下文长度;纯 CPU 可跑但慢
启动方式Python 脚本启动 / API 服务启动
主要功能角色动机生成、伪装行为生成、破坏行动规划、暴露结果判定、多结局剧情批量输出
是否支持 API支持,可将生成与判定模块封装为 HTTP 接口
是否支持批量任务支持,可通过配置文件批量跑多条剧情线
输出内容JSON 结构化剧情节点 + Markdown 可读剧情文本
适合场景网文辅助创作、游戏剧情分支生成、AI 剧本测试、多智能体行为模拟

需要说明的是,这套流程不是某一个现成的一键包,而是基于开源模型和脚本组合出来的工作流。好处是每个环节都能替换、能调试、能接自己的数据;代价是需要自己花半小时配置环境。如果你的核心目的只是“用大模型写一段反派装傻又暴露的短篇故事”,那在线版模型也能做,本文的重点是让你在本地把这件事批量化、可复现、可二次开发。

2. 适用场景与使用边界

2.1 适合谁用

网文和短剧编剧。需要批量生成“反派伪装 - 暗中行动 - 突然暴露”这类高冲突桥段时,手动写又慢又容易重复,用脚本让模型批量产出不同风格的版本,人工再做筛选和润色,效率高很多。

游戏剧情策划。分支剧情往往需要同一事件的不同走向,比如反派装傻成功、装傻失败、行动被提前识破、行动暴露后反杀等。这套工作流可以按设定好的条件输出不同分支。

AI 应用开发者。如果你的产品需要“多角色行为模拟”或“角色意图推断”,本文的判定逻辑可以迁移到客服对话、NPC 行为树、内容审核演练等场景。

2.2 不适合什么场景

  • 需要严格符合某本书/某部剧原有人设和文风的商业化精修,不适合全自动输出,建议只用它出草稿。
  • 需要极高推理速度的实时交互场景(比如游戏内实时 NPC 对话),本地小模型勉强能响应,但体验不如云端大模型。
  • 涉及真实人物、真实品牌、真实地点或受版权保护的作品角色,不建议直接用模型生成模仿性内容,容易踩侵权和肖像权问题。

2.3 合规边界提醒

使用 AI 生成剧情内容时,注意三点:不生成违法违规内容,不使用未经授权的真实人脸、真实声音或版权素材,商用前做内容复核。本文所有测试素材均使用虚构角色和通用场景,大家在本地测试时也建议先用原创设定。

3. 本地部署环境准备

整个流程依赖一个本地可调用的大语言模型推理环境。先列通用检查清单,再看具体操作。

3.1 硬件与系统要求

  • 操作系统:Windows 10/11、Ubuntu 20.04 及以上、macOS(Apple Silicon 可跑部分模型)
  • GPU:NVIDIA 显卡建议 6G 以上显存;A 卡和核显不建议折腾
  • CPU:能跑就行,生成速度会慢一些
  • 内存:16G 以上比较稳
  • 磁盘空间:模型文件加依赖至少预留 20G,量化模型可压到 8G 左右

3.2 软件依赖

  • Python 3.10 或 3.11(3.12 部分依赖可能还不兼容,建议先查各框架支持情况)
  • CUDA 11.8 / 12.1 对应版本的 PyTorch
  • 一个可以本地加载的量化大模型,例如 Qwen2.5-7B-Instruct-GPTQ-Int4、ChatGLM3-6B 或 Llama-3-8B-Instruct 的 GGUF 版本
  • 模型加载框架:Transformers + Accelerate,或 LlamaCpp / Ollama(更省事)

检查 Python 和显卡驱动:

python --version nvidia-smi

如果nvidia-smi能显示显卡信息和驱动版本,说明驱动正常。PyTorch 是否识别 GPU,用下面命令验证:

import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else "CPU only")

如果cuda.is_available()返回False,先确认装的是对应 CUDA 版本的 PyTorch,而不是 CPU 版本。

3.3 用 Ollama 做基础推理(推荐先跑通)

不想折腾 Transformers 依赖的话,可以直接用 Ollama 管理本地模型。先安装 Ollama,然后拉取一个中文能力不错的模型:

ollama pull qwen2.5:7b ollama run qwen2.5:7b

能正常对话,说明本地基础推理环境已经通了。接下来所有脚本都只需要调用 Ollama 的 HTTP 接口,不需要自己处理模型加载细节,非常省事。如果追求更低的显存占用,也可以换更小的模型,比如qwen2.5:3bgemma2:2b,但生成质量和长文本能力会下降。

4. 安装部署与启动方式

先创建项目目录,建议结构如下:

antihero_workflow/ ├── config.yaml # 全局配置:模型、剧情参数、页面 ├── scripts/ │ ├── generate.py # 主线剧情生成脚本 │ ├── judge.py # 暴露判定脚本 │ └── batch_run.py # 批量任务运行器 ├── inputs/ │ └── characters.json # 角色设定和初始剧情/场景 ├── outputs/ │ ├── json/ # 结构化输出 │ └── markdown/ # 可读剧情文本 └── requirements.txt

4.1 安装 Python 依赖

如果直接用 Ollama,Python 依赖很少,主要是 PyYAML 和 Requests:

pip install pyyaml requests

如果你想直接用 Transformers 加载模型,再补这些:

pip install transformers accelerate torch

4.2 编写配置文件

config.yaml里写清楚模型地址、生成参数和测试场景:

model: backend: "ollama" # ollama 或 transformers base_url: "http://127.0.0.1:11434" model_name: "qwen2.5:7b" temperature: 0.8 max_tokens: 2048 task: genre: "古风权谋" # 不知道怎么写可以先给风格词 language: "中文" output_dir: "outputs" judge: max_rounds: 3 # 最多做几轮行动/观测判定 time_out: 30 # 单次请求超时时间

4.3 准备角色与初始场景

inputs/characters.json里定义角色和目标:

{ "world_setting": "大周王朝末年,朝堂党争剧烈,江湖势力暗流涌动。", "antihero": { "name": "沈无咎", "identity": "被废黜的镇北侯世子,表面装疯卖傻,暗中收集各派罪证。", "superficial_goal": "只想安稳做个富贵闲人。", "real_goal": "查出当年家族覆灭真相,让幕后黑手付出代价。", "personality": "表面怯懦懒散,实则心思缜密,护短但不滥杀。" }, "observer": { "name": "长公主", "identity": "当朝摄政长公主,疑心极重,掌控京城情报网。", "attitude_to_antihero": "怀疑沈无咎是装傻,但没有直接证据。" }, "trigger_event": "长公主府夜宴,沈无咎被人当众试探,言语间露出破绽。" }

这个 JSON 就是后续所有生成任务的“种子”。可以准备多个不同角色文件,跑批量任务时轮换使用。

4.4 启动模型服务

如果选择 Ollama,只需要确保服务在运行,默认端口 11434:

ollama serve

另开一个终端验证模型服务是否可调用:

curl http://127.0.0.1:11434/api/generate -d '{ "model": "qwen2.5:7b", "prompt": "说一句话", "stream": false }'

如果返回了 JSON 格式的响应,说明基础服务已经就绪。后面所有 Python 脚本都走这个 HTTP 接口。

如果直接用 Transformers,就不需要启动 Ollama,但脚本里要配置好pipeline的初始化部分。从省心和显存占用角度,更建议先用 Ollama,后面再按需迁移。

5. 功能测试与效果验证

核心目标:让模型按照“装傻 - 搞破坏 - 暴露”的节奏生成剧情。脚本逻辑可以设计成三段式。

5.1 第一段:动机与伪装生成

任务提示词里要明确告诉模型:现在要生成的是“反派表面行为”,不是“内心想法”。这一步测试模型是否理解“装傻”和“真实动机”之间的反差。

generate.py中定义单次生成函数:

import json import requests import yaml with open("config.yaml", "r", encoding="utf-8") as f: config = yaml.safe_load(f) API_URL = config["model"]["base_url"] + "/api/generate" def call_model(prompt, system_prompt=""): payload = { "model": config["model"]["model_name"], "prompt": prompt, "system": system_prompt, "stream": False, "options": { "temperature": config["model"]["temperature"], "num_predict": config["model"]["max_tokens"] } } resp = requests.post(API_URL, json=payload, timeout=60) return resp.json().get("response", "") def generate_pretense(character_json): with open(character_json, "r", encoding="utf-8") as f: data = json.load(f) prompt = f""" 请根据以下设定,生成一段反派角色的“伪装面”剧情。 世界观:{data['world_setting']} 角色:{data['antihero']['name']},{data['antihero']['identity']} 表面目标:{data['antihero']['superficial_goal']} 真实目标:{data['antihero']['real_goal']} 触发事件:{data['trigger_event']} 要求: 1. 剧情中不能直接透露反派内心想法。 2. 反派言语行为必须符合“装傻”设定,但要留有细思极恐的伏笔。 3. 只输出剧情内容,不要输出分析和说明。 """ return call_model(prompt)

执行后,把输出存到outputs/json/pretense.json,同时把可读版本写到outputs/markdown/pretense.md

运行方式:

python scripts/generate.py --task pretense --input inputs/characters.json

预期结果:模型输出一段晚宴场景的叙述,沈无咎在对话中装傻充愣,但若有若无地提到了一个只有幕后黑手才知道的细节。判断成功标准不是“文笔多好”,而是“表面言行与真实动机之间有没有张力”。

如果输出太平铺直叙,可以尝试调高温度到 0.9,或换一个模型。如果输出直接揭露了内心想法,说明提示词里的“不要直接透露内心想法”约束不够强,需要在 system prompt 里重复强调。

5.2 第二段:破坏行为规划与行动生成

这一步让模型在“伪装”基础上,推进到实际破坏行动。剧情上要体现“伺机”两个字——不是无脑搞破坏,而是选择时机和方式。

继续写generate.py里的第二个函数:

def generate_sabotage(character_json, pretense_text): with open(character_json, "r", encoding="utf-8") as f: data = json.load(f) prompt = f""" 以下是反派在触发事件中的“伪装”剧情: {pretense_text} 现在请基于以上信息,在保持反派表面人设不变的前提下,生成一段破坏行动前的“机会评估”和“行动准备”剧情。 要求: 1. 反派需要暗中收集情报或安排棋子,不能亲自下场暴露身份。 2. 行动必须被某种“合理借口”包装,比如醉酒误入、走错院子、关心朋友。 3. 不写内心独白,只写可见行为。 4. 输出内容要有一定留白,让读者能猜到动机但不能直接坐实。 """ return call_model(prompt)

这一步产出的是“破坏计划 + 伪装动作”的复合剧情。运行:

python scripts/generate.py --task sabotage --input inputs/characters.json

预期结果:沈无咎在宴席上以醉酒为借口离席,暗中摸到了长公主用于存放密信的书房附近,但表面上只是“找地方醒酒”。这里重点检查剧情逻辑是否合理——反派行动是否利用了前文铺垫的伪装人设。

5.3 第三段:暴露与被抓判定

“反被抓个正着”是整条剧情链的高潮,也是最有技术含量的部分。不能简单让模型写“他暴露了”,而是要让模型基于前面生成的伪装剧情、行动剧情和观测者视角,做出一个“暴露程度判定”。

judge.py

def judge_exposure(character_json, pretense_text, sabotage_text): with open(character_json, "r", encoding="utf-8") as f: data = json.load(f) observer = data["observer"] prompt = f""" 你是{observer['name']},{observer['identity']}。你一直在怀疑{data['antihero']['name']}是否真的装傻。 你看到了以下事件: 1. 伪装阶段: {pretense_text} 2. 行动阶段: {sabotage_text} 请以旁观者的视角分析: 1. 你是否发现了破绽?请列出至少两个可疑点。 2. 你是否有确定的证据?如果有,是什么? 3. 你决定怎么做?是直接抓捕、暗中监视,还是设局试探? 输出格式: 暴露等级:高/中/低 可疑点:... 证据判定:... 行动决定:... """ result = call_model(prompt) return result

然后写一个汇总脚本,把三段剧情串起来并输出完整故事:

python scripts/judge.py --input inputs/characters.json

5.4 完整测试用例:从“装傻”到“被抓”

做一次端到端测试时,建议直接把三段剧情放进一个长提示词里,让模型一次性生成完整故事,对比分段生成和整体生成的差异。

输入示例:

{ "world_setting": "现代都市商战,百年集团内部权力更迭。", "antihero": { "name": "程见微", "identity": "被踢出董事会的原副总裁,假装沉迷钓鱼,暗中收集集团财务造假证据。", "real_goal": "让现任董事长身败名裂。" }, "trigger_event": "集团年会,程见微被邀请上台发言,有董事故意问起离职真相。" }

整体生成 prompt 模板:

请根据以下角色设定,生成一个完整短篇故事,要求包含三个阶段: 第一阶段:反派装傻苟命,伪装人设立住。 第二阶段:反派伺机搞破坏,行动周密但留下细微破绽。 第三阶段:反派被某个敏锐角色当场抓住破绽,剧情反转。 设定:...

预期输出:结构完整、三个阶段清晰、暴露方式不再是“突然智商下降”,而是因为一个细节漏洞被抓。判断成功的标准是“暴露环节是否由前文伏笔支撑”,而不是模型强行给反派降智。

失败常见原因:

  • 模型把“装傻”理解成“真傻”,导致后续行动逻辑崩坏。解决办法:在 prompt 中增加“表面行为与真实意图高度不一致”的明确示例。
  • 暴露环节太突兀,没有前文线索。解决办法:在 judge 阶段要求模型从之前的剧情里提取“可疑点”,而不是自由发挥。
  • 输出过长导致截断。解决办法:降低max_tokens到 1536,或者分两次生成再拼接。
  • 中文人名和复杂关系容易混乱。解决办法:在 prompt 里重复强调角色名称,并减少次要角色数量。

6. 接口 API 与批量任务

单次生成只是第一步。真正有价值的是把“装傻 - 搞破坏 - 被抓”做成一个可批量执行的流水线。

6.1 封装 API 服务

用 Python + Flask 或 FastAPI 把生成流程包成一个 HTTP 接口,这样其他客户端(前端页面、游戏服务器、内容管理后台)都能调用。

安装 Flask:

pip install flask

写一个最小 API 服务api_server.py

from flask import Flask, request, jsonify import json from scripts.generate import generate_pretense, generate_sabotage from scripts.judge import judge_exposure app = Flask(__name__) @app.route("/api/story", methods=["POST"]) def create_story(): data = request.get_json() character_file = data.get("character_file", "inputs/characters.json") with open(character_file, "r", encoding="utf-8") as f: character = json.load(f) pretense = generate_pretense(character_file) sabotage = generate_sabotage(character_file, pretense) exposure = judge_exposure(character_file, pretense, sabotage) return jsonify({ "pretense": pretense, "sabotage": sabotage, "exposure": exposure }) if __name__ == "__main__": app.run(host="127.0.0.1", port=8000, debug=False)

启动服务:

python api_server.py

curl 调用:

curl -X POST http://127.0.0.1:8000/api/story \ -H "Content-Type: application/json" \ -d '{"character_file": "inputs/characters.json"}'

6.2 Python 调用示例

import requests url = "http://127.0.0.1:8000/api/story" payload = { "character_file": "inputs/characters.json" } response = requests.post(url, json=payload, timeout=300) print(response.json()["exposure"])

判断服务是否成功的标准:

  • POST 请求返回 200 状态码。
  • 返回 JSON 包含三段剧情字段。
  • 剧情内容没有明显逻辑断裂。

如果超时,先检查模型侧是否卡住;如果返回 500,看服务端日志里的异常堆栈。

6.3 批量任务设计

批量任务的核心是准备多个角色文件,然后循环调用生成函数,把输出写到独立文件。

创建batch_run.py

import json import os import glob from scripts.generate import generate_pretense, generate_sabotage from scripts.judge import judge_exposure def run_batch(input_dir="inputs/batch", output_dir="outputs/batch"): os.makedirs(output_dir, exist_ok=True) os.makedirs(f"{output_dir}/json", exist_ok=True) os.makedirs(f"{output_dir}/markdown", exist_ok=True) files = glob.glob(f"{input_dir}/*.json") results = [] for i, file in enumerate(files): try: print(f"[{i + 1}/{len(files)}] 处理 {file}") pretense = generate_pretense(file) sabotage = generate_sabotage(file, pretense) exposure = judge_exposure(file, pretense, sabotage) item = { "input": file, "pretense": pretense, "sabotage": sabotage, "exposure": exposure } results.append(item) base_name = os.path.basename(file).replace(".json", "") with open(f"{output_dir}/json/{base_name}.json", "w", encoding="utf-8") as f: json.dump(item, f, ensure_ascii=False, indent=2) except Exception as e: print(f"失败: {file}, 原因: {e}") # 记录失败,不中断整个批次 with open(f"{output_dir}/error.log", "a", encoding="utf-8") as f: f.write(f"{file}: {str(e)}\n") return results if __name__ == "__main__": run_batch()

批量运行:

python scripts/batch_run.py

批量任务设计要点:

  • 每个角色文件一个任务,任务之间无状态依赖,天然支持并发。想加速可以用concurrent.futures.ThreadPoolExecutor或直接上 Celery。
  • 必须保留失败重试机制。模型接口偶发超时或返回空内容是常态,建议对单个任务重试 2 到 3 次。
  • 输出文件按输入文件名命名,方便对账。
  • 每次批量跑完检查error.log,把失败任务单独重新跑。

7. 资源占用与性能观察

7.1 显存占用怎么观察

用 Ollama 加载 Qwen2.5 7B 量化版时,启动后观察:

nvidia-smi

重点看进程对应的显存占用。7B 量化模型一般会吃掉 5G 到 8G,具体取决于量化位数和上下文长度。如果你的显卡是 4G 显存,建议换 3B 或 2B 模型,否则生成长文本大概率 OOM。

如果切换到 Transformers 直接加载,可以用torch.cuda.memory_summary()查看更细的显存分配,但日常观察nvidia-smi已经够用了。

7.2 CPU 推理与 GPU 推理差异

同样一段剧情生成,GPU 推理可能只要几十秒,CPU 推理可能要几分钟甚至更久。如果你的设备只有 CPU,建议把max_tokens缩短到 1024,把num_ctx(上下文窗口)降低到 4096,否则一次生成能等得怀疑人生。

Ollama 里设置上下文窗口:

ollama run qwen2.5:7b --num-ctx 4096

7.3 影响生成速度的因素

  • 输入 token 长度:三段剧情拼接会让 prompt 越来越长,后续生成速度和首字延迟都会上升。
  • 输出 token 长度:剧情设置越长,单次请求越久。
  • 模型大小:7B 模型比 3B 慢大约一倍。
  • batch size:如果自己实现并发,要注意显存峰值会随并发数上升。

7.4 降低资源占用的方案

  • 用更小的量化模型,比如 4bit GGUF。
  • 把三段式生成拆成独立请求,而不是一个超长请求。
  • 每轮生成后清理一下上下文,避免模型在同一会话里积累太多对话历史。
  • 批量任务串行跑,不要同时开太多并发;真要并发,控制到 2 路以内。
  • 如果显存不够且不追求速度,把 Ollama 的num_gpu设置成负数,表示模型层全部跑 CPU。

8. 常见问题与排查方法

问题现象可能原因排查方式解决方案
启动后请求一直转圈,没有输出模型服务未启动,或端口不对curl http://127.0.0.1:11434检查先启动模型服务,确认配置文件里的 base_url 正确
输出只有半句话就停了max_tokens设置太小查看返回内容长度调大max_tokens,或把剧情拆成两段生成再拼接
显存不足(CUDA out of memory)模型过大或上下文过长nvidia-smi查看显存占用换成 3B 量化模型、调小上下文窗口、减少 batch 并发
模型回答内容严重偏离“装傻”设定prompt 约束不足查看生成内容增加格式约束和负面示例,比如“不要直接写内心想法”
批量任务跑到一半卡住单次生成超时无重试查看日志,找到卡住的输入文件对单次调用加重试机制,超时时间设 60 秒以上
中文输出夹杂英文或特殊符号模型能力限制或提示词不清晰查看生成原文在提示词末尾加“只输出中文内容”
第一次调用很慢,后续正常模型加载到显存需要时间等待数十秒正常现象,预热后提速
API 返回 500 错误Python 脚本异常或读取文件路径不对查看 Flask 日志检查角色 JSON 文件格式,确保 UTF-8 编码

9. 最佳实践与使用建议

  • 第一次跑通时,先不追求剧情质量,只验证“三段式流程能不能输出不报错”。输入尽量简短,把max_tokens调到 1024 以内,等流程稳定后再加长。
  • 保留一套最小可运行配置。把测试通过的config.yaml和角色文件单独存一个目录,不要覆盖,后续再优化时随时能回滚。
  • 模型文件、输入素材、输出结果分开目录管理。批量跑完几十个文件后,你会发现清晰的目录结构是排查问题的关键。
  • 批量任务必须加日志和失败重试。模型输出天然有随机性,失败重试不是可选项,是必选项。
  • 接口服务如果跑在公网或局域网,要限制访问范围。只监听127.0.0.1或者用防火墙限制 IP 段,不要默认0.0.0.0裸奔。
  • 如果后续要商用剧情内容,建议对生成结果做一次人工复核。AI 生成的内容可能在细节逻辑、版权相似度、价值观表达上有问题,不能直接交付。
  • 当需要生成大量剧情分支时,先小批量测试 5 到 10 条,确认风格稳定后再跑全量,避免一次性跑完几百条后发现全部不达标。

10. 总结与下一步

这套“反派装傻苟命,伺机搞破坏反被抓个正着”的工作流,本质上是一个本地大模型驱动的剧情生成与判定流水线。值得先验证的功能是:三段式生成能否在本地模型上稳定跑通,暴露判定是否能让剧情逻辑闭环,而不是靠模型随机发挥。

最值得先做的事情是跑通generate.pyjudge.py的完整链路,用一个简单的角色文件测试 3 到 5 次,观察输出文件里的 JSON 结构是否完整。最容易踩的坑是提示词约束不够,导致反派直接暴露内心独白、装傻变真傻,建议把负面示例直接写进 prompt。

后续可以扩展的方向有三块:一是把判定模块升级成多轮博弈,让反派在暴露后继续撒谎圆场,而不是立刻被抓死;二是接入检索增强,让角色行为和设定的世界观保持一致;三是把批量任务接上消息队列,做成一个真正的异步内容生成服务。如果目标是出短剧脚本或网文片段,还可以在此基础上接视频分镜生成工具。建议收藏备用,先从一条完整剧情线跑起来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询