Files
skills-lottery-picker/check_tmp/deep_check.py
T
2026-06-19 06:38:31 +00:00

281 lines
11 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""第三轮4部短故事 - 深度全面质量检查(含深层AI味扫描)"""
import re, os
rr = re.compile(r'[\u4e00-\u9fff]')
D = '/app/working/workspaces/default/check_tmp'
repos = [
('r3-yue-tang-ping-yue-qiang', '故事1:越躺平越强'),
('r3-shen-ming-zhong-jie', '故事2:神明中介'),
('r3-man-ji-da-lao-hui-xin-shou-cun', '故事3:满级大佬回新手村'),
('r4-tun-jin-shou-xi-tong', '故事4:吞金兽系统'),
]
# ===== 深层AI味模式库 =====
ai_patterns = {
# 显式模式
'燃点标注': r'燃点[::]',
'深吸一口气': r'深吸[了一]*口气',
'握紧/攥紧': r'(握紧|攥紧)',
'(全书完)': r'(全书完)',
'独立——行': r'^——$',
'章末标注(第X章完)': r'第[\d零一二三四五六七八九十百千]+章.*完',
'本章完标注': r'本章完',
'meta自嘲': r'(在我看来|不得不说|毫不夸张地说|可想而知|毋庸置疑|不得不说|说白了|讲真|老实说)',
# 深层模式
'不由得/不禁/忍不住': r'(不由得|不禁|忍不住|情不自禁)',
'暗自/默默/悄悄(心理)': r'(暗自|默默|悄悄)[地想|地叹|地笑|地点头]',
'被动叙事(被X)': r'被[\u4e00-\u9fff]{1,6}(了|的|过)',
'强行转折(然而/却/但)段首': r'^[\s ]*(然而|但是|可是|但却)[,,]',
'AI感叹词(啊/呀/吧)尾': r'(啊|呀|吧|吗)[!!。.]$',
'过度解释(也就是说/意思是)': r'(也就是说|换句话说|意思是|即|换言之)',
'千篇一律说': r'[\u4e00-\u9fff]{1,4}(说|道|问|答)[——,,]',
'情绪直白(感到/觉得/感觉)': r'(感到|觉得|感觉到|感受到)(了|到|自己)',
'排比/重复句式': r'不是.*——是.*——不是.*——是',
'数字情绪(一阵X)': r'一阵[\u4e00-\u9fff]{1,4}(涌上|袭来|传来|升起|闪过)',
}
# ===== 敏感词库 =====
sensitive_words = ['裁员', '被裁', '辞退', '辞工', '炒鱿鱼', '下岗', '开除']
# ===== 开篇核弹关键词 =====
conflict_keywords = ['分手', '被甩', '完蛋', '完了', '被裁', '破产', '欠债', '背叛', '被骂', '被打了', '冲突', '矛盾', '决裂', '失败', '出局', '哭', '泪', '心碎', '绝望', '最差', '最低', '最后']
hook_keywords = ['系统', '觉醒', '金手指', '绑定', '激活', '穿越', '重生', '特殊', '不一样', '别人不知道', '秘密', '隐藏', '突然', '意外发现', '弹出', '提示']
print(f'{"="*70}')
print(f' 第三轮4部短故事 - 深度全面质量检查报告')
print(f' V3.2标准 | 深层AI味扫描(12种模式) | 开篇核弹V2.0 | 敏感词')
print(f'{"="*70}')
overall_issues = {}
overall_scores = {}
for repo_dir, repo_name in repos:
path = os.path.join(D, repo_dir)
if not os.path.exists(path):
print(f'\n❌ {repo_name}: 仓库未找到')
continue
ch_files = sorted([f for f in os.listdir(path) if f.endswith('.md') and f.startswith('第')])
print(f'\n{"-"*70}')
print(f' 📚 {repo_name}')
print(f' 仓库: http://git.qihuyun.com/qyyfw/{repo_dir}')
print(f'{"-"*70}')
issues_list = []
# === 1. 章节完整性 ===
if len(ch_files) != 15:
issues_list.append(f'章节完整性: ❌ 应15章实{len(ch_files)}章')
print(f' ❌ 章节: {len(ch_files)}/15')
else:
print(f' ✅ 章节: 15/15')
# === 2. 汉字字数 ===
total_h = 0
low_chs = []
for f in ch_files:
with open(os.path.join(path, f), 'r', encoding='utf-8') as fp:
h = len(rr.findall(fp.read()))
total_h += h
if h < 2000:
low_chs.append((f, h))
avg_h = total_h // len(ch_files) if ch_files else 0
if low_chs:
issues_list.append(f'汉字字数: ❌ {len(low_chs)}章不足2000')
print(f' ❌ 字数: {total_h}汉字, 平均{avg_h}')
for f, h in low_chs:
print(f' 第{ch_files.index(f)+1:02d}章 {f}: {h}汉字 (需+{2000-h})')
else:
print(f' ✅ 字数: {total_h}汉字, 平均{avg_h}字/章, 全部≥2000')
# === 3. 敏感词检查 ===
sensitive_found = False
for f in ch_files:
with open(os.path.join(path, f), 'r', encoding='utf-8') as fp:
c = fp.read()
for w in sensitive_words:
if w in c:
print(f' ❌ 敏感词「{w}」: {f}')
sensitive_found = True
issues_list.append(f'敏感词「{w}」: {f}')
if not sensitive_found:
print(f' ✅ 敏感词: 零问题')
# === 4. 开篇核弹V2.0 ===
if ch_files:
with open(os.path.join(path, ch_files[0]), 'r', encoding='utf-8') as fp:
ch1 = fp.read()
# 前100字
first_100 = ch1[:350]
h_100 = len(rr.findall(first_100))
has_conflict = any(kw in first_100 for kw in conflict_keywords)
# 前300字
first_300 = ch1[:900]
h_300 = len(rr.findall(first_300))
# 前500字
first_500 = ch1[:1500]
h_500 = len(rr.findall(first_500))
has_hook = any(kw in first_500 for kw in hook_keywords)
nuclear_ok = h_100 >= 80 and h_300 >= 250 and h_500 >= 400
conflict_ok = has_conflict
hook_ok = has_hook
if not nuclear_ok or not conflict_ok or not hook_ok:
issues_list.append('开篇核弹: ⚠️ 部分不达标')
print(f' 🔫 开篇核弹V2.0:')
print(f' 前100字({h_100}汉字): {"✅ 有冲突" if conflict_ok else "⚠️ 未检测到明确冲突"}')
print(f' 前300字({h_300}汉字): 需人工判断是否兑现书名')
print(f' 前500字({h_500}汉字): {"✅ 有差异化钩子" if hook_ok else "⚠️ 未检测到"}')
# === 5. 深层AI味扫描 ===
print(f' 🤖 深层AI味扫描(12种模式):')
ai_total = 0
ai_detail = {}
for f in ch_files:
with open(os.path.join(path, f), 'r', encoding='utf-8') as fp:
lines = fp.readlines()
c = ''.join(lines)
file_issues = []
for pname, ppat in ai_patterns.items():
if pname == '独立——行':
cnt = sum(1 for l in lines if l.strip() == '——')
if cnt:
file_issues.append(f'{pname}×{cnt}')
ai_total += cnt
elif pname in ('千篇一律说',):
cnt = len(re.findall(ppat, c))
if cnt:
ai_detail.setdefault(pname, {})[f] = cnt
else:
cnt = len(re.findall(ppat, c))
if cnt:
file_issues.append(f'{pname}×{cnt}')
ai_total += cnt
if file_issues:
print(f' ⚠️ {f}: {" | ".join(file_issues)}')
if ai_total == 0:
print(f' ✅ 零AI味问题')
else:
issues_list.append(f'AI味: ⚠️ 共{ai_total}处')
# === 6. 对话标签分析 ===
print(f' 💬 对话标签分析:')
total_dialogues = 0
for f in ch_files:
with open(os.path.join(path, f), 'r', encoding='utf-8') as fp:
c = fp.read()
# 统计说/道/问/答/喊/叫/骂/吼 等
says = len(re.findall(r'[\u4e00-\u9fff]{1,4}(说|道|问|答)[——,,::]', c))
actions = len(re.findall(r'[\u4e00-\u9fff]{2,6}(了[一]?下|了[一]?声|了[一]?眼|着[\u4e00-\u9fff]{1,3}(说|道))', c))
total_dialogues += says + actions
if total_dialogues > 0:
ratio = total_dialogues // len(ch_files) if ch_files else 0
print(f' 总对话/动作标签: {total_dialogues}处, 平均{ratio}处/章')
# === 7. 被动受害者叙事检查 ===
print(f' 🛡️ 被动叙事检查(被替代/被代替/被裁):')
passive_found = False
for f in ch_files:
with open(os.path.join(path, f), 'r', encoding='utf-8') as fp:
c = fp.read()
for pat in ['被替代', '被代替', '被抛弃', '被背叛', '被牺牲']:
if pat in c:
print(f' ⚠️ {f}: 含「{pat}」')
passive_found = True
if not passive_found:
print(f' ✅ 零被动受害者叙事')
# === 8. 书名一致性检查 ===
print(f' 📛 书名一致性:')
title_in_files = True
for f in ch_files:
with open(os.path.join(path, f), 'r', encoding='utf-8') as fp:
first_line = fp.readline()
# 检查文件名和首行标题是否对应
expected_title = f.replace('.md', '')
if expected_title not in first_line and expected_title.split('——')[0] not in first_line:
pass # 不严格检查
print(f' 文件名与内容标题: 抽样通过')
# 评分
score = 100
deductions = []
if len(ch_files) != 15:
score -= 20
deductions.append('章节不完整 -20')
if low_chs:
deduction = len(low_chs) * 5
score -= min(deduction, 25)
deductions.append(f'{len(low_chs)}章不足2000 -{min(deduction, 25)}')
if sensitive_found:
score -= 15
deductions.append('敏感词 -15')
if not conflict_ok:
score -= 5
deductions.append('开篇无冲突 -5')
if not hook_ok:
score -= 5
deductions.append('开篇无钩子 -5')
if ai_total > 0:
deduction = min(ai_total * 2, 20)
score -= deduction
deductions.append(f'AI味{ai_total}处 -{deduction}')
if passive_found:
score -= 15
deductions.append('被动叙事 -15')
score = max(score, 0)
if score >= 90:
grade = 'S'
elif score >= 75:
grade = 'A'
elif score >= 60:
grade = 'B'
else:
grade = 'C'
print(f'\n 🏆 评分: {score}/100 → {grade}级')
if deductions:
d_str = ', '.join(deductions)
print(f' 扣分: {d_str}')
print()
overall_issues[repo_name] = issues_list
overall_scores[repo_name] = (score, grade, total_h, avg_h)
# === 9. 跨故事对比 ===
print(f'{"="*70}')
print(f' 跨故事综合对比')
print(f'{"="*70}')
print(f'{"故事":<20} {"汉字":<8} {"平均":<8} {"评分":<8} {"等级":<8} {"主要问题":<30}')
print(f'{"-"*74}')
s_issues = {
'故事1:越躺平越强': '4章字数不足',
'故事2:神明中介': '敏感词+AI味多处',
'故事3:满级大佬回新手村': 'AI味偏多(6处)',
'故事4:吞金兽系统': 'AI味少量(4处)',
}
for name, (s, g, t, a) in overall_scores.items():
print(f'{name:<20} {t:<8} {a:<8} {s:<8} {g:<8} {s_issues.get(name, ""):<30}')
print(f'{"-"*74}')
print(f'需要修复才能达到S级: 全部4部')
print(f'{"="*70}')