上传文件至 /
This commit is contained in:
208
NovelConfig.py
Normal file
208
NovelConfig.py
Normal file
@@ -0,0 +1,208 @@
|
||||
"""
|
||||
小说生成器配置文件
|
||||
包含各种高级配置选项和预设模板
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, List, Any, Optional
|
||||
|
||||
@dataclass
|
||||
class AdvancedNovelConfig:
|
||||
"""高级小说生成配置"""
|
||||
# 基础配置
|
||||
genre: str
|
||||
target_total_chars: int
|
||||
model: str = "qwen-turbo"
|
||||
temperature: float = 0.8
|
||||
|
||||
# 质量控制
|
||||
enable_logic_check: bool = True
|
||||
max_logic_iterations: int = 3
|
||||
enable_emotion_enhancement: bool = True
|
||||
enable_dialogue_optimization: bool = True
|
||||
|
||||
# 写作风格
|
||||
writing_style: str = "balanced" # balanced, literary, commercial, dramatic
|
||||
narrative_perspective: str = "third" # first, third, mixed
|
||||
tone: str = "neutral" # light, neutral, serious, humorous
|
||||
|
||||
# 内容控制
|
||||
max_characters: int = 8 # 最大角色数量
|
||||
min_dialogue_ratio: float = 0.3 # 对话占比最小值
|
||||
max_description_ratio: float = 0.4 # 描写占比最大值
|
||||
|
||||
# 技术参数
|
||||
segment_size: int = 2000 # 分段处理大小
|
||||
parallel_workers: int = 3 # 并行处理线程数
|
||||
retry_attempts: int = 3 # 重试次数
|
||||
|
||||
|
||||
# 预设配置模板
|
||||
PRESET_CONFIGS = {
|
||||
"精品长篇": AdvancedNovelConfig(
|
||||
genre="都市逆袭",
|
||||
target_total_chars=25000,
|
||||
model="qwen-max",
|
||||
temperature=0.9,
|
||||
enable_logic_check=True,
|
||||
max_logic_iterations=5,
|
||||
writing_style="literary",
|
||||
enable_emotion_enhancement=True,
|
||||
enable_dialogue_optimization=True,
|
||||
max_characters=12,
|
||||
parallel_workers=4
|
||||
)
|
||||
}
|
||||
|
||||
# 写作风格配置
|
||||
WRITING_STYLES = {
|
||||
"balanced": {
|
||||
"description": "平衡风格,适合大众阅读",
|
||||
"dialogue_ratio": 0.35,
|
||||
"description_ratio": 0.30,
|
||||
"action_ratio": 0.35,
|
||||
"complexity": "medium"
|
||||
},
|
||||
|
||||
"literary": {
|
||||
"description": "文学风格,注重深度和内涵",
|
||||
"dialogue_ratio": 0.25,
|
||||
"description_ratio": 0.45,
|
||||
"action_ratio": 0.30,
|
||||
"complexity": "high"
|
||||
},
|
||||
|
||||
"commercial": {
|
||||
"description": "商业风格,节奏快,易读",
|
||||
"dialogue_ratio": 0.45,
|
||||
"description_ratio": 0.25,
|
||||
"action_ratio": 0.30,
|
||||
"complexity": "low"
|
||||
},
|
||||
|
||||
"dramatic": {
|
||||
"description": "戏剧风格,冲突强烈",
|
||||
"dialogue_ratio": 0.50,
|
||||
"description_ratio": 0.20,
|
||||
"action_ratio": 0.30,
|
||||
"complexity": "medium"
|
||||
}
|
||||
}
|
||||
|
||||
# 语调配置
|
||||
TONE_CONFIGS = {
|
||||
"light": {
|
||||
"description": "轻松愉快的语调",
|
||||
"keywords": ["温馨", "轻松", "幽默", "治愈"],
|
||||
"avoid_keywords": ["沉重", "压抑", "悲伤"]
|
||||
},
|
||||
|
||||
"neutral": {
|
||||
"description": "中性平衡的语调",
|
||||
"keywords": ["自然", "真实", "平衡"],
|
||||
"avoid_keywords": ["过于夸张", "过于沉重"]
|
||||
},
|
||||
|
||||
"serious": {
|
||||
"description": "严肃深刻的语调",
|
||||
"keywords": ["深刻", "思考", "内省", "成长"],
|
||||
"avoid_keywords": ["轻浮", "肤浅"]
|
||||
},
|
||||
|
||||
"humorous": {
|
||||
"description": "幽默风趣的语调",
|
||||
"keywords": ["幽默", "风趣", "机智", "轻松"],
|
||||
"avoid_keywords": ["严肃", "沉重", "悲伤"]
|
||||
}
|
||||
}
|
||||
|
||||
# 题材扩展配置
|
||||
EXTENDED_GENRES = {
|
||||
"都市逆袭": {
|
||||
"core": "底层主角通过智慧和机遇逐步崛起,每一步都有合理动机和代价",
|
||||
"typical_characters": ["奋斗主角", "贵人导师", "竞争对手", "支持朋友", "家人"],
|
||||
"common_conflicts": ["阶层差距", "能力质疑", "机遇选择", "道德考验"],
|
||||
"emotional_themes": ["自我证明", "成长蜕变", "责任担当", "情感成熟"]
|
||||
},
|
||||
|
||||
"甜宠先婚后爱": {
|
||||
"core": "两个有血有肉的人从陌生到相知相爱的心理变化过程",
|
||||
"typical_characters": ["独立女主", "温柔男主", "闺蜜", "家人", "工作伙伴"],
|
||||
"common_conflicts": ["误解矛盾", "价值观差异", "外界阻力", "内心恐惧"],
|
||||
"emotional_themes": ["信任建立", "情感觉醒", "相互理解", "共同成长"]
|
||||
},
|
||||
|
||||
"悬疑推理": {
|
||||
"core": "通过逻辑推理和线索收集,逐步揭开真相的智力较量过程",
|
||||
"typical_characters": ["推理主角", "神秘反派", "关键证人", "警方助手", "受害者"],
|
||||
"common_conflicts": ["线索迷雾", "逻辑陷阱", "时间压力", "真相冲击"],
|
||||
"emotional_themes": ["真相追求", "正义坚持", "智慧较量", "人性探索"]
|
||||
},
|
||||
|
||||
"末世生存": {
|
||||
"core": "在绝望环境中求生,展现人性光辉与黑暗的生存史诗",
|
||||
"typical_characters": ["生存主角", "幸存团队", "资源争夺者", "希望守护者", "堕落者"],
|
||||
"common_conflicts": ["资源争夺", "环境威胁", "人性考验", "道德选择"],
|
||||
"emotional_themes": ["生存意志", "人性光辉", "团队协作", "希望重燃"]
|
||||
},
|
||||
|
||||
"玄幻升级": {
|
||||
"core": "在奇幻世界中通过修炼和历练不断突破自我的成长之路",
|
||||
"typical_characters": ["修炼主角", "师父导师", "同门师兄", "强敌对手", "红颜知己"],
|
||||
"common_conflicts": ["境界瓶颈", "强敌挑战", "门派争斗", "天道考验"],
|
||||
"emotional_themes": ["修炼感悟", "师徒情深", "友情考验", "爱情升华"]
|
||||
},
|
||||
|
||||
"校园青春": {
|
||||
"core": "青春期的成长、友情、初恋和自我发现的故事",
|
||||
"typical_characters": ["青涩主角", "初恋对象", "好友团体", "老师", "家长"],
|
||||
"common_conflicts": ["学业压力", "情感困惑", "友情考验", "家庭期待"],
|
||||
"emotional_themes": ["青春迷茫", "初恋美好", "友情珍贵", "成长痛苦"]
|
||||
},
|
||||
|
||||
"职场励志": {
|
||||
"core": "职场新人或转型者在工作中的成长和突破",
|
||||
"typical_characters": ["职场新人", "严厉上司", "竞争同事", "导师前辈", "客户"],
|
||||
"common_conflicts": ["工作挑战", "人际关系", "职业选择", "价值冲突"],
|
||||
"emotional_themes": ["专业成长", "自我价值", "团队合作", "领导力"]
|
||||
},
|
||||
|
||||
"家庭温情": {
|
||||
"core": "家庭成员之间的情感纠葛和最终和解",
|
||||
"typical_characters": ["家庭成员", "长辈", "晚辈", "亲戚", "邻居"],
|
||||
"common_conflicts": ["代沟问题", "价值观差异", "生活压力", "情感隔阂"],
|
||||
"emotional_themes": ["亲情珍贵", "理解包容", "传承责任", "家庭和谐"]
|
||||
}
|
||||
}
|
||||
|
||||
def get_preset_config(preset_name: str) -> Optional[AdvancedNovelConfig]:
|
||||
"""获取预设配置"""
|
||||
return PRESET_CONFIGS.get(preset_name)
|
||||
|
||||
def get_writing_style_info(style: str) -> Dict[str, Any]:
|
||||
"""获取写作风格信息"""
|
||||
return WRITING_STYLES.get(style, WRITING_STYLES["balanced"])
|
||||
|
||||
def get_tone_info(tone: str) -> Dict[str, Any]:
|
||||
"""获取语调信息"""
|
||||
return TONE_CONFIGS.get(tone, TONE_CONFIGS["neutral"])
|
||||
|
||||
def get_genre_info(genre: str) -> Dict[str, Any]:
|
||||
"""获取题材信息"""
|
||||
return EXTENDED_GENRES.get(genre, EXTENDED_GENRES["都市逆袭"])
|
||||
|
||||
def list_available_presets() -> List[str]:
|
||||
"""列出可用的预设配置"""
|
||||
return list(PRESET_CONFIGS.keys())
|
||||
|
||||
def list_available_genres() -> List[str]:
|
||||
"""列出可用的题材"""
|
||||
return list(EXTENDED_GENRES.keys())
|
||||
|
||||
def list_available_styles() -> List[str]:
|
||||
"""列出可用的写作风格"""
|
||||
return list(WRITING_STYLES.keys())
|
||||
|
||||
def list_available_tones() -> List[str]:
|
||||
"""列出可用的语调"""
|
||||
return list(TONE_CONFIGS.keys())
|
||||
386
QualityAssessment.py
Normal file
386
QualityAssessment.py
Normal file
@@ -0,0 +1,386 @@
|
||||
"""
|
||||
小说质量评估模块
|
||||
提供多维度的质量评估和改进建议
|
||||
"""
|
||||
|
||||
import re
|
||||
import json
|
||||
import logging
|
||||
from typing import Dict, List, Tuple, Any
|
||||
from dataclasses import dataclass
|
||||
from collections import Counter
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@dataclass
|
||||
class QualityMetrics:
|
||||
"""质量指标"""
|
||||
# 基础指标
|
||||
total_chars: int
|
||||
effective_chars: int
|
||||
paragraph_count: int
|
||||
sentence_count: int
|
||||
dialogue_count: int
|
||||
|
||||
# 比例指标
|
||||
dialogue_ratio: float
|
||||
description_ratio: float
|
||||
action_ratio: float
|
||||
|
||||
# 复杂度指标
|
||||
avg_sentence_length: float
|
||||
vocabulary_richness: float
|
||||
repetition_rate: float
|
||||
|
||||
# 结构指标
|
||||
scene_transitions: int
|
||||
character_mentions: Dict[str, int]
|
||||
emotion_words: int
|
||||
|
||||
# 质量评分
|
||||
overall_score: float
|
||||
dimension_scores: Dict[str, float]
|
||||
|
||||
|
||||
class NovelQualityAssessor:
|
||||
"""小说质量评估器"""
|
||||
|
||||
def __init__(self):
|
||||
# 情感词汇库
|
||||
self.emotion_words = {
|
||||
"positive": ["开心", "快乐", "兴奋", "满足", "温暖", "感动", "幸福", "甜蜜", "欣慰", "骄傲"],
|
||||
"negative": ["难过", "痛苦", "愤怒", "失望", "恐惧", "焦虑", "绝望", "孤独", "委屈", "后悔"],
|
||||
"complex": ["复杂", "矛盾", "纠结", "挣扎", "无奈", "感慨", "思考", "反思", "领悟", "成长"]
|
||||
}
|
||||
|
||||
# 动作词汇
|
||||
self.action_words = ["走", "跑", "坐", "站", "看", "听", "说", "想", "做", "拿", "放", "开", "关", "推", "拉"]
|
||||
|
||||
# 描写词汇
|
||||
self.description_words = ["美丽", "漂亮", "高大", "宽敞", "明亮", "温暖", "寒冷", "炎热", "安静", "嘈杂"]
|
||||
|
||||
# 对话标记
|
||||
self.dialogue_patterns = [
|
||||
r'[【「"]([^【「"]+)[】」"]', # 【】「」""标记的对话
|
||||
r'"([^"]+)"', # 英文引号
|
||||
r"'([^']+)'", # 中文引号
|
||||
]
|
||||
|
||||
def assess_novel_quality(self, text: str, title: str = "") -> QualityMetrics:
|
||||
"""评估小说质量"""
|
||||
logger.info("开始质量评估...")
|
||||
|
||||
# 基础统计
|
||||
basic_stats = self._calculate_basic_stats(text)
|
||||
|
||||
# 内容分析
|
||||
content_analysis = self._analyze_content(text)
|
||||
|
||||
# 结构分析
|
||||
structure_analysis = self._analyze_structure(text)
|
||||
|
||||
# 语言质量分析
|
||||
language_analysis = self._analyze_language_quality(text)
|
||||
|
||||
# 计算综合评分
|
||||
dimension_scores = {
|
||||
"内容丰富度": content_analysis["richness_score"],
|
||||
"结构合理性": structure_analysis["structure_score"],
|
||||
"语言质量": language_analysis["language_score"],
|
||||
"情感表达": content_analysis["emotion_score"],
|
||||
"对话质量": content_analysis["dialogue_score"]
|
||||
}
|
||||
|
||||
overall_score = sum(dimension_scores.values()) / len(dimension_scores)
|
||||
|
||||
# 构建质量指标对象
|
||||
metrics = QualityMetrics(
|
||||
total_chars=basic_stats["total_chars"],
|
||||
effective_chars=basic_stats["effective_chars"],
|
||||
paragraph_count=basic_stats["paragraph_count"],
|
||||
sentence_count=basic_stats["sentence_count"],
|
||||
dialogue_count=basic_stats["dialogue_count"],
|
||||
|
||||
dialogue_ratio=content_analysis["dialogue_ratio"],
|
||||
description_ratio=content_analysis["description_ratio"],
|
||||
action_ratio=content_analysis["action_ratio"],
|
||||
|
||||
avg_sentence_length=language_analysis["avg_sentence_length"],
|
||||
vocabulary_richness=language_analysis["vocabulary_richness"],
|
||||
repetition_rate=language_analysis["repetition_rate"],
|
||||
|
||||
scene_transitions=structure_analysis["scene_transitions"],
|
||||
character_mentions=structure_analysis["character_mentions"],
|
||||
emotion_words=content_analysis["emotion_words"],
|
||||
|
||||
overall_score=overall_score,
|
||||
dimension_scores=dimension_scores
|
||||
)
|
||||
|
||||
logger.info(f"质量评估完成,综合评分: {overall_score:.1f}")
|
||||
return metrics
|
||||
|
||||
def _calculate_basic_stats(self, text: str) -> Dict[str, Any]:
|
||||
"""计算基础统计信息"""
|
||||
# 总字符数
|
||||
total_chars = len(text)
|
||||
|
||||
# 有效字符数(中文字符+标点+数字)
|
||||
lines = [line.strip() for line in text.split('\n') if line.strip()]
|
||||
combined = ''.join(lines)
|
||||
chinese_chars = re.findall(r'[\u4e00-\u9fa5]', combined)
|
||||
punctuation = re.findall(r'[,。!?;:、""''()【】《》]', combined)
|
||||
numbers = re.findall(r'\d', combined)
|
||||
effective_chars = len(chinese_chars) + len(punctuation) + len(numbers)
|
||||
|
||||
# 段落数
|
||||
paragraphs = [p.strip() for p in text.split('\n\n') if p.strip()]
|
||||
paragraph_count = len(paragraphs)
|
||||
|
||||
# 句子数
|
||||
sentences = re.split(r'[。!?]', text)
|
||||
sentence_count = len([s for s in sentences if s.strip()])
|
||||
|
||||
# 对话数
|
||||
dialogue_count = 0
|
||||
for pattern in self.dialogue_patterns:
|
||||
dialogue_count += len(re.findall(pattern, text))
|
||||
|
||||
return {
|
||||
"total_chars": total_chars,
|
||||
"effective_chars": effective_chars,
|
||||
"paragraph_count": paragraph_count,
|
||||
"sentence_count": sentence_count,
|
||||
"dialogue_count": dialogue_count
|
||||
}
|
||||
|
||||
def _analyze_content(self, text: str) -> Dict[str, Any]:
|
||||
"""分析内容质量"""
|
||||
# 对话比例
|
||||
dialogue_chars = 0
|
||||
for pattern in self.dialogue_patterns:
|
||||
matches = re.findall(pattern, text)
|
||||
dialogue_chars += sum(len(match) for match in matches)
|
||||
|
||||
dialogue_ratio = dialogue_chars / len(text) if text else 0
|
||||
|
||||
# 描写比例(通过描写词汇估算)
|
||||
description_count = 0
|
||||
for word in self.description_words:
|
||||
description_count += text.count(word)
|
||||
description_ratio = min(description_count / 100, 0.5) # 归一化
|
||||
|
||||
# 动作比例
|
||||
action_count = 0
|
||||
for word in self.action_words:
|
||||
action_count += text.count(word)
|
||||
action_ratio = min(action_count / 100, 0.5) # 归一化
|
||||
|
||||
# 情感词汇统计
|
||||
emotion_words = 0
|
||||
for category, words in self.emotion_words.items():
|
||||
for word in words:
|
||||
emotion_words += text.count(word)
|
||||
|
||||
# 评分计算
|
||||
richness_score = min(100, (dialogue_ratio * 30 + description_ratio * 40 + action_ratio * 30) * 100)
|
||||
emotion_score = min(100, emotion_words * 2) # 每个情感词2分
|
||||
dialogue_score = min(100, dialogue_ratio * 200) # 对话比例评分
|
||||
|
||||
return {
|
||||
"dialogue_ratio": dialogue_ratio,
|
||||
"description_ratio": description_ratio,
|
||||
"action_ratio": action_ratio,
|
||||
"emotion_words": emotion_words,
|
||||
"richness_score": richness_score,
|
||||
"emotion_score": emotion_score,
|
||||
"dialogue_score": dialogue_score
|
||||
}
|
||||
|
||||
def _analyze_structure(self, text: str) -> Dict[str, Any]:
|
||||
"""分析结构质量"""
|
||||
# 场景转换(通过时间、地点词汇估算)
|
||||
scene_markers = ["突然", "接着", "然后", "后来", "此时", "这时", "同时", "与此同时", "第二天", "几天后"]
|
||||
scene_transitions = 0
|
||||
for marker in scene_markers:
|
||||
scene_transitions += text.count(marker)
|
||||
|
||||
# 角色提及统计(简单的人名识别)
|
||||
# 这里使用简单的启发式方法,实际应用中可以使用NER
|
||||
potential_names = re.findall(r'[\u4e00-\u9fa5]{2,3}(?=[,。!?:;]|说|想|看|听)', text)
|
||||
character_mentions = Counter(potential_names)
|
||||
|
||||
# 只保留出现频率较高的(可能是角色名)
|
||||
character_mentions = {name: count for name, count in character_mentions.items() if count >= 3}
|
||||
|
||||
# 结构评分
|
||||
structure_score = min(100, scene_transitions * 5 + len(character_mentions) * 10)
|
||||
|
||||
return {
|
||||
"scene_transitions": scene_transitions,
|
||||
"character_mentions": character_mentions,
|
||||
"structure_score": structure_score
|
||||
}
|
||||
|
||||
def _analyze_language_quality(self, text: str) -> Dict[str, Any]:
|
||||
"""分析语言质量"""
|
||||
# 句子平均长度
|
||||
sentences = re.split(r'[。!?]', text)
|
||||
valid_sentences = [s.strip() for s in sentences if s.strip()]
|
||||
avg_sentence_length = sum(len(s) for s in valid_sentences) / len(valid_sentences) if valid_sentences else 0
|
||||
|
||||
# 词汇丰富度(简单估算)
|
||||
words = re.findall(r'[\u4e00-\u9fa5]+', text)
|
||||
unique_words = set(words)
|
||||
vocabulary_richness = len(unique_words) / len(words) if words else 0
|
||||
|
||||
# 重复率(检查重复的短语)
|
||||
phrases = []
|
||||
for i in range(len(text) - 10):
|
||||
phrase = text[i:i+10]
|
||||
if re.match(r'^[\u4e00-\u9fa5,。!?;:、""''()【】《》]+$', phrase):
|
||||
phrases.append(phrase)
|
||||
|
||||
phrase_counts = Counter(phrases)
|
||||
repeated_phrases = sum(1 for count in phrase_counts.values() if count > 1)
|
||||
repetition_rate = repeated_phrases / len(phrases) if phrases else 0
|
||||
|
||||
# 语言质量评分
|
||||
length_score = min(100, max(0, 100 - abs(avg_sentence_length - 20) * 2)) # 理想句长20字
|
||||
richness_score = vocabulary_richness * 100
|
||||
repetition_score = max(0, 100 - repetition_rate * 200)
|
||||
|
||||
language_score = (length_score + richness_score + repetition_score) / 3
|
||||
|
||||
return {
|
||||
"avg_sentence_length": avg_sentence_length,
|
||||
"vocabulary_richness": vocabulary_richness,
|
||||
"repetition_rate": repetition_rate,
|
||||
"language_score": language_score
|
||||
}
|
||||
|
||||
def generate_improvement_suggestions(self, metrics: QualityMetrics) -> List[str]:
|
||||
"""生成改进建议"""
|
||||
suggestions = []
|
||||
|
||||
# 基于各维度评分给出建议
|
||||
if metrics.dimension_scores["内容丰富度"] < 70:
|
||||
suggestions.append("建议增加更多的场景描写和人物内心活动,提升内容丰富度")
|
||||
|
||||
if metrics.dimension_scores["结构合理性"] < 70:
|
||||
suggestions.append("建议优化故事结构,增加场景转换和情节推进")
|
||||
|
||||
if metrics.dimension_scores["语言质量"] < 70:
|
||||
suggestions.append("建议提升语言表达质量,避免重复用词,丰富词汇")
|
||||
|
||||
if metrics.dimension_scores["情感表达"] < 70:
|
||||
suggestions.append("建议增强情感表达,多使用情感词汇和内心独白")
|
||||
|
||||
if metrics.dimension_scores["对话质量"] < 70:
|
||||
suggestions.append("建议增加对话内容,让角色通过对话展现性格")
|
||||
|
||||
# 基于具体指标给出建议
|
||||
if metrics.dialogue_ratio < 0.2:
|
||||
suggestions.append("对话比例偏低,建议增加角色对话来推进情节")
|
||||
|
||||
if metrics.avg_sentence_length > 30:
|
||||
suggestions.append("句子平均长度偏长,建议适当使用短句增加节奏感")
|
||||
|
||||
if metrics.repetition_rate > 0.1:
|
||||
suggestions.append("存在较多重复表达,建议使用同义词替换增加表达多样性")
|
||||
|
||||
if len(metrics.character_mentions) < 3:
|
||||
suggestions.append("角色数量偏少,建议增加配角丰富故事内容")
|
||||
|
||||
return suggestions
|
||||
|
||||
def export_quality_report(self, metrics: QualityMetrics, title: str = "", output_file: str = None) -> str:
|
||||
"""导出质量报告"""
|
||||
report = f"""
|
||||
# 小说质量评估报告
|
||||
|
||||
## 基本信息
|
||||
- 标题: {title or "未命名"}
|
||||
- 总字符数: {metrics.total_chars:,}
|
||||
- 有效字符数: {metrics.effective_chars:,}
|
||||
- 段落数: {metrics.paragraph_count}
|
||||
- 句子数: {metrics.sentence_count}
|
||||
- 对话数: {metrics.dialogue_count}
|
||||
|
||||
## 综合评分: {metrics.overall_score:.1f}/100
|
||||
|
||||
## 各维度评分
|
||||
- 内容丰富度: {metrics.dimension_scores['内容丰富度']:.1f}/100
|
||||
- 结构合理性: {metrics.dimension_scores['结构合理性']:.1f}/100
|
||||
- 语言质量: {metrics.dimension_scores['语言质量']:.1f}/100
|
||||
- 情感表达: {metrics.dimension_scores['情感表达']:.1f}/100
|
||||
- 对话质量: {metrics.dimension_scores['对话质量']:.1f}/100
|
||||
|
||||
## 详细指标
|
||||
- 对话比例: {metrics.dialogue_ratio:.1%}
|
||||
- 描写比例: {metrics.description_ratio:.1%}
|
||||
- 动作比例: {metrics.action_ratio:.1%}
|
||||
- 平均句长: {metrics.avg_sentence_length:.1f}字
|
||||
- 词汇丰富度: {metrics.vocabulary_richness:.1%}
|
||||
- 重复率: {metrics.repetition_rate:.1%}
|
||||
- 场景转换: {metrics.scene_transitions}次
|
||||
- 情感词汇: {metrics.emotion_words}个
|
||||
|
||||
## 角色提及统计
|
||||
"""
|
||||
|
||||
for character, count in metrics.character_mentions.items():
|
||||
report += f"- {character}: {count}次\n"
|
||||
|
||||
# 添加改进建议
|
||||
suggestions = self.generate_improvement_suggestions(metrics)
|
||||
if suggestions:
|
||||
report += "\n## 改进建议\n"
|
||||
for i, suggestion in enumerate(suggestions, 1):
|
||||
report += f"{i}. {suggestion}\n"
|
||||
|
||||
# 保存到文件
|
||||
if output_file:
|
||||
try:
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(report)
|
||||
logger.info(f"质量报告已保存到: {output_file}")
|
||||
except Exception as e:
|
||||
logger.error(f"保存质量报告失败: {str(e)}")
|
||||
|
||||
return report
|
||||
|
||||
|
||||
def assess_novel_quality(text: str, title: str = "") -> QualityMetrics:
|
||||
"""便捷函数:评估小说质量"""
|
||||
assessor = NovelQualityAssessor()
|
||||
return assessor.assess_novel_quality(text, title)
|
||||
|
||||
|
||||
def generate_quality_report(text: str, title: str = "", output_file: str = None) -> str:
|
||||
"""便捷函数:生成质量报告"""
|
||||
assessor = NovelQualityAssessor()
|
||||
metrics = assessor.assess_novel_quality(text, title)
|
||||
return assessor.export_quality_report(metrics, title, output_file)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 测试代码
|
||||
sample_text = """
|
||||
《测试小说》
|
||||
|
||||
李明走进办公室,心情复杂。今天是他入职的第一天,既兴奋又紧张。
|
||||
|
||||
【你好,我是新来的李明。】他对前台小姐说道。
|
||||
|
||||
【欢迎!我是小王,有什么需要帮助的尽管说。】小王热情地回答。
|
||||
|
||||
李明感到一阵温暖,看来这里的同事都很友善。他想起了母亲昨天的话:【要好好工作,不要让我们失望。】
|
||||
|
||||
突然,一个严肃的声音响起:【你就是新来的?跟我来。】
|
||||
"""
|
||||
|
||||
metrics = assess_novel_quality(sample_text, "测试小说")
|
||||
print(f"综合评分: {metrics.overall_score:.1f}")
|
||||
print(f"对话比例: {metrics.dialogue_ratio:.1%}")
|
||||
print(f"平均句长: {metrics.avg_sentence_length:.1f}")
|
||||
4145
ViralNovel.py
Normal file
4145
ViralNovel.py
Normal file
File diff suppressed because it is too large
Load Diff
111
resume_generation.py
Normal file
111
resume_generation.py
Normal file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
恢复中断的小说生成任务
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
def find_unfinished_projects():
|
||||
"""查找未完成的项目"""
|
||||
base_dir = Path(__file__).parent
|
||||
unfinished = []
|
||||
|
||||
for item in base_dir.iterdir():
|
||||
if item.is_dir() and item.name.startswith('n') and item.name[1:].isdigit():
|
||||
progress_file = item / ".generation_progress.json"
|
||||
if progress_file.exists():
|
||||
try:
|
||||
with open(progress_file, 'r', encoding='utf-8') as f:
|
||||
progress = json.load(f)
|
||||
|
||||
if progress.get('stage') != 'complete':
|
||||
unfinished.append({
|
||||
'dir': item.name,
|
||||
'stage': progress.get('stage', 'unknown'),
|
||||
'progress': progress.get('progress_percent', 0),
|
||||
'last_update': progress.get('last_update', 'unknown')
|
||||
})
|
||||
except:
|
||||
continue
|
||||
|
||||
return sorted(unfinished, key=lambda x: x['last_update'], reverse=True)
|
||||
|
||||
def main():
|
||||
print("🔍 查找未完成的小说生成任务...")
|
||||
|
||||
unfinished = find_unfinished_projects()
|
||||
|
||||
if not unfinished:
|
||||
print("✅ 没有找到未完成的任务")
|
||||
print("💡 运行 python ViralNovel.py 开始新的生成")
|
||||
return
|
||||
|
||||
print(f"\n📋 找到 {len(unfinished)} 个未完成的任务:")
|
||||
print("-" * 60)
|
||||
|
||||
for i, proj in enumerate(unfinished, 1):
|
||||
print(f"{i}. 项目: {proj['dir']}")
|
||||
print(f" 阶段: {proj['stage']}")
|
||||
print(f" 进度: {proj['progress']:.1f}%")
|
||||
print(f" 更新: {proj['last_update']}")
|
||||
print()
|
||||
|
||||
if len(unfinished) == 1:
|
||||
choice = input("是否继续这个任务?(y/n): ").strip().lower()
|
||||
if choice == 'y':
|
||||
selected = unfinished[0]
|
||||
else:
|
||||
print("❌ 已取消")
|
||||
return
|
||||
else:
|
||||
try:
|
||||
choice = input(f"选择要继续的任务 (1-{len(unfinished)}): ").strip()
|
||||
idx = int(choice) - 1
|
||||
if 0 <= idx < len(unfinished):
|
||||
selected = unfinished[idx]
|
||||
else:
|
||||
print("❌ 无效选择")
|
||||
return
|
||||
except ValueError:
|
||||
print("❌ 请输入数字")
|
||||
return
|
||||
|
||||
print(f"\n🚀 继续生成任务: {selected['dir']}")
|
||||
print(f"📊 当前进度: {selected['stage']} ({selected['progress']:.1f}%)")
|
||||
print("⏳ 正在恢复...")
|
||||
|
||||
try:
|
||||
# 导入并运行恢复函数
|
||||
sys.path.append(str(Path(__file__).parent))
|
||||
from ViralNovel import resume_generation_from_progress
|
||||
|
||||
result = resume_generation_from_progress(selected['dir'])
|
||||
|
||||
print(f"\n✅ 生成完成!")
|
||||
print(f"📖 标题: {result['title']}")
|
||||
print(f"📁 保存位置: {result['project_dir']}")
|
||||
|
||||
except ImportError:
|
||||
print("❌ 无法导入 ViralNovel 模块")
|
||||
print("💡 请确保 ViralNovel.py 文件存在")
|
||||
|
||||
except Exception as e:
|
||||
error_str = str(e)
|
||||
print(f"\n❌ 恢复失败: {error_str}")
|
||||
|
||||
if "网络连接" in error_str or "超时" in error_str:
|
||||
print("\n🔧 网络问题解决建议:")
|
||||
print("1. 检查网络连接")
|
||||
print("2. 等待几分钟后重试")
|
||||
print("3. 运行: python resume_generation.py")
|
||||
|
||||
elif "rate limit" in error_str.lower():
|
||||
print("\n⏰ API调用频率限制:")
|
||||
print("1. 等待几分钟后重试")
|
||||
print("2. 运行: python resume_generation.py")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user