$npx -y skills add Supreme-Ultimate/novel-to-script-team --skill comparative-review-skill对比审核技能。对比生成剧本与爆款剧本的节奏、对话、情绪、框架,给出PASS/FAIL判断和改进建议。
| 1 | # 对比审核技能 |
| 2 | |
| 3 | ## 必读 |
| 4 | |
| 5 | 1. `../../references/00-first-principles.md` — 第一性原则(可拍性、留存性、一致性、可验证性) |
| 6 | 2. `../../references/03-script-writing-standard.md` — 剧本写作标准(对话比、视觉标记、网文感、节奏控制) |
| 7 | 3. `../../references/04-review-gates.md` — 审核门槛(PASS/FAIL标准、回改流程) |
| 8 | |
| 9 | ## 功能 |
| 10 | |
| 11 | 对比生成剧本与参考的爆款剧本,从多个维度进行分析,防止AI味,确保剧本质量。 |
| 12 | |
| 13 | ## 对比维度 |
| 14 | |
| 15 | ### 1. 节奏对比 |
| 16 | |
| 17 | **统计指标**: |
| 18 | - 场景数(scene_count) |
| 19 | - 冲突密度(conflict_density)= 冲突次数 / 总字数 |
| 20 | - 平均场景时长(avg_scene_duration) |
| 21 | - 时长方差(duration_variance) |
| 22 | - 情绪强度(emotion_intensity) |
| 23 | |
| 24 | **对比方法**: |
| 25 | ```python |
| 26 | # 统计生成剧本 |
| 27 | generated = analyze_rhythm(generated_script) |
| 28 | |
| 29 | # 统计参考剧本(5个的平均值) |
| 30 | reference = average([analyze_rhythm(ref) for ref in reference_scripts]) |
| 31 | |
| 32 | # 对比 |
| 33 | rhythm_score = compare_metrics(generated, reference) |
| 34 | ``` |
| 35 | |
| 36 | **判断标准**: |
| 37 | - 场景数:±2个场景内为PASS |
| 38 | - 冲突密度:±0.01内为PASS |
| 39 | - 情绪强度:±0.01内为PASS |
| 40 | |
| 41 | ### 2. 对话风格对比 |
| 42 | |
| 43 | **统计指标**: |
| 44 | - 平均句长(avg_sentence_length) |
| 45 | - 对话比(dialogue_ratio)= 对话字数 / 总字数 |
| 46 | - 视觉标记密度(visual_markers_per_100) |
| 47 | - 短句比例(short_sentence_ratio)< 10字符的句子占比 |
| 48 | - 网文感关键词密度(wanwen_keywords_per_100) |
| 49 | |
| 50 | **网文感关键词**: |
| 51 | ```python |
| 52 | wanwen_keywords = [ |
| 53 | '冷笑', '嗤笑', '冷哼', '冷声', '冷冷', |
| 54 | '眼神一冷', '眸光一沉', '嘴角勾起', |
| 55 | '不屑', '轻蔑', '讥讽', '嘲讽', |
| 56 | '霸气', '强势', '凌厉', '锐利' |
| 57 | ] |
| 58 | ``` |
| 59 | |
| 60 | **判断标准**: |
| 61 | - 句长:12±3字符为PASS |
| 62 | - 对话比:70%±10%为PASS |
| 63 | - 视觉标记:3-5个/100字为PASS |
| 64 | |
| 65 | ### 3. 情绪冲击力对比 |
| 66 | |
| 67 | **统计指标**: |
| 68 | - 情绪词汇密度(emotion_word_density) |
| 69 | - 情感极性摆动(emotion_polarity_swing) |
| 70 | - 高潮点数量(climax_count) |
| 71 | - 悬念设置(suspense_count) |
| 72 | |
| 73 | **情绪词汇**: |
| 74 | ```python |
| 75 | emotion_words = { |
| 76 | '愤怒': ['愤怒', '暴怒', '怒火', '气愤', '恼怒'], |
| 77 | '悲伤': ['悲伤', '难过', '伤心', '痛苦', '绝望'], |
| 78 | '惊讶': ['惊讶', '震惊', '惊愕', '愕然', '惊呆'], |
| 79 | '恐惧': ['恐惧', '害怕', '惊恐', '畏惧', '胆寒'], |
| 80 | '喜悦': ['喜悦', '高兴', '欣喜', '愉悦', '兴奋'] |
| 81 | } |
| 82 | ``` |
| 83 | |
| 84 | **判断标准**: |
| 85 | - 情绪词汇:1.5-2.5个/100字为PASS |
| 86 | - 情感摆动:至少2次明显摆动为PASS |
| 87 | - 高潮点:至少1个为PASS |
| 88 | |
| 89 | ### 4. 框架结构对比 |
| 90 | |
| 91 | **结构要素**: |
| 92 | - 开局(hook):前10%是否有强钩子 |
| 93 | - 发展(development):中间60%是否有持续冲突 |
| 94 | - 高潮(climax):是否有明显高潮点 |
| 95 | - 反转(twist):是否有意外反转 |
| 96 | - 结局(ending):是否有强悬念/钩子 |
| 97 | |
| 98 | **判断标准**: |
| 99 | - 5个要素至少满足4个为PASS |
| 100 | |
| 101 | ### 5. 跨集内容重复检查 |
| 102 | |
| 103 | **检查对象**:当前集与前一集的内容对比 |
| 104 | |
| 105 | **检查项**: |
| 106 | - 场景重复:当前集与前一集是否有相同的场景 |
| 107 | - 剧情点重复:当前集与前一集是否有相同的剧情点 |
| 108 | - 对话重复:当前集与前一集是否有相似的对话 |
| 109 | - 事件重复:当前集与前一集是否是同一个事件 |
| 110 | |
| 111 | **判断标准**: |
| 112 | - 发现任何重复内容,必须 FAIL |
| 113 | - 必须指出具体的重复位置 |
| 114 | - 必须要求删除或重写重复内容 |
| 115 | |
| 116 | **示例**: |
| 117 | ```python |
| 118 | # 检查场景重复 |
| 119 | ep01_scenes = extract_scenes(ep01_script) |
| 120 | ep02_scenes = extract_scenes(ep02_script) |
| 121 | duplicate_scenes = find_duplicates(ep01_scenes, ep02_scenes) |
| 122 | |
| 123 | if duplicate_scenes: |
| 124 | feedback.append({ |
| 125 | 'dimension': '跨集内容重复', |
| 126 | 'issue': '发现重复场景', |
| 127 | 'location': f'第{N}集与第{N-1}集', |
| 128 | 'duplicates': duplicate_scenes, |
| 129 | 'suggestion': '删除重复场景,或改为新的场景' |
| 130 | }) |
| 131 | ``` |
| 132 | |
| 133 | ### 6. 事件完整性检查 |
| 134 | |
| 135 | **检查对象**:当前集的事件结构 |
| 136 | |
| 137 | **检查项**: |
| 138 | - 事件完整性:当前集是否是一个完整的事件(有开始、发展、结束) |
| 139 | - 剧情线完整性:当前集是否有未完成的剧情线 |
| 140 | - 逻辑连贯性:当前集与下一集的规划是否有逻辑断层 |
| 141 | |
| 142 | **判断标准**: |
| 143 | - 事件不完整(如只有开始没有结束),必须 FAIL |
| 144 | - 有未完成的剧情线,必须 FAIL |
| 145 | - 与下一集的规划有逻辑断层,必须 FAIL |
| 146 | |
| 147 | **示例**: |
| 148 | ```python |
| 149 | # 检查事件完整性 |
| 150 | event_structure = analyze_event_structure(script) |
| 151 | |
| 152 | if not event_structure['has_beginning']: |
| 153 | feedback.append({ |
| 154 | 'dimension': '事件完整性', |
| 155 | 'issue': '事件缺少开始', |
| 156 | 'suggestion': '添加事件的触发点' |
| 157 | }) |
| 158 | |
| 159 | if not event_structure['has_ending']: |
| 160 | feedback.append({ |
| 161 | 'dimension': '事件完整性', |
| 162 | 'issue': '事件缺少结束', |
| 163 | 'suggestion': '添加事件的结果或转折' |
| 164 | }) |
| 165 | ``` |
| 166 | |
| 167 | ## 执行流程 |
| 168 | |
| 169 | ### Step 1: 加载剧本 |
| 170 | |
| 171 | ```python |
| 172 | # 加载生成剧本 |
| 173 | with open(generated_script_path, 'r') as f: |
| 174 | generated_script = f.read() |
| 175 | |
| 176 | # 加载参考剧本(之前检索的Top 5) |
| 177 | reference_scripts = [] |
| 178 | for ref_path in reference_paths: |
| 179 | with open(ref_path, 'r') as f: |
| 180 | reference_scripts.append(f.read()) |
| 181 | ``` |
| 182 | |
| 183 | ### Step 2: 统计指标 |
| 184 | |
| 185 | ```python |
| 186 | # 生成剧本指标 |
| 187 | gen_rhythm = analyze_rhythm(generated_script) |
| 188 | gen_style = analyze_style(generated_script) |
| 189 | gen_emotion = analyze_emotion(generated_script) |
| 190 | gen_structure = analyze_structure(generated_script) |
| 191 | |
| 192 | # 参考剧本平均指标 |
| 193 | ref_rhythm = average([analyze_rhythm(ref) for ref in reference_scripts]) |
| 194 | ref_style = average([analyze_style(ref) for ref in reference_scripts]) |
| 195 | ref_emotion = average([analyze_emotion(ref) for ref in reference_scripts]) |
| 196 | ref_structure = average([analyze_structure(ref) for ref in reference_scripts]) |
| 197 | ``` |
| 198 | |
| 199 | ### Step 3: 对比分析 |
| 200 | |
| 201 | ```python |
| 202 | feedback = [] |
| 203 | |
| 204 | # 节奏对比 |
| 205 | if abs(gen_rhythm['scene_count'] - ref_rhythm['scene_count']) > 2: |
| 206 | feedback.append({ |
| 207 | 'dimension': '节奏', |
| 208 | 'issue': f"场景数偏{'少' if gen_rhythm['scene_count'] < ref_rhythm['scene_count'] else '多'}", |
| 209 | 'generated': gen_rhythm['scene_count'], |
| 210 | 'reference': ref_rhythm['scene_count'], |
| 211 | 'suggestion': f"建议调整为{ref_rhythm['scene_count']}个场景" |
| 212 | }) |
| 213 | |
| 214 | # 对话风格对比 |
| 215 | if gen_style['dialogue_ratio'] < 0.6: |
| 216 | feedback.append({ |
| 217 | 'dimension': '对话风格', |
| 218 | 'issue': '对话比偏低', |
| 219 | 'generated': f"{gen_style['dialogue_ratio']:.1%}", |
| 220 | 'reference': f"{ref_style['dialogue_ratio']:.1%}", |
| 221 | 'suggestion': '增加对话,减少叙述性文字' |
| 222 | }) |
| 223 | |
| 224 | # 跨集内容重复检查 |
| 225 | if previous_script: |
| 226 | duplicate_scenes = find_duplicate_scenes(generated_script, previous_script) |
| 227 | if duplicate_scenes: |
| 228 | feedback.append({ |
| 229 | 'dimension': '跨集内容重复', |
| 230 | 'issue': '发现重复场景', |
| 231 | 'location': f'第{N}集与第{N-1}集', |
| 232 | 'duplicates': duplicate_scenes, |