Просмотр исходного кода

移除未接入自动化流程的 feedback_collector.py

该脚本设计为手动 CLI 反馈收集工具,但未在 evolve.sh 或任何自动化
环节中被调用,评分逻辑已由 quality_tuner.py 覆盖。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
nonvioce 5 месяцев назад
Родитель
Сommit
0c2a05260e
2 измененных файлов с 2 добавлено и 198 удалено
  1. 2 7
      README.md
  2. 0 191
      scripts/feedback_collector.py

+ 2 - 7
README.md

@@ -174,7 +174,7 @@ novel-skill/
 │   ├── prompt_evolver.py  # 提示词遗传进化
 │   ├── prompt_evolver.py  # 提示词遗传进化
 │   ├── quality_tuner.py   # 质量阈值自适应
 │   ├── quality_tuner.py   # 质量阈值自适应
 │   ├── pattern_mine.py    # 写作模式挖掘
 │   ├── pattern_mine.py    # 写作模式挖掘
-│   ├── feedback_collector.py  # 多维反馈收集
+
 │   ├── event_store.py     # 事件溯源引擎
 │   ├── event_store.py     # 事件溯源引擎
 │   ├── seed_extractor.py  # 内置15题材种子提取
 │   ├── seed_extractor.py  # 内置15题材种子提取
 │   └── utils.py           # 共享工具
 │   └── utils.py           # 共享工具
@@ -389,11 +389,6 @@ python3 scripts/quality_tuner.py show                             # 当前阈值
 python3 scripts/quality_tuner.py analyze --project /path/to/novel # 分析
 python3 scripts/quality_tuner.py analyze --project /path/to/novel # 分析
 python3 scripts/quality_tuner.py tune --project /path/to/novel    # 分析并应用
 python3 scripts/quality_tuner.py tune --project /path/to/novel    # 分析并应用
 
 
-# === 反馈收集 ===
-python3 scripts/feedback_collector.py collect \
-    --project /path/to/novel --chapter 35 \
-    --scores '{"P1":88,"P2":76,"P3":70,"P4":82,"P5":91}'
-python3 scripts/feedback_collector.py state   # 查看会话状态
 
 
 # === 事件溯源 ===
 # === 事件溯源 ===
 python3 scripts/event_store.py compile --genre other    # 编译 population
 python3 scripts/event_store.py compile --genre other    # 编译 population
@@ -419,7 +414,7 @@ python3 scripts/pattern_mine.py mine --project /path/to/novel
 | `scripts/prompt_evolver.py` | 岛屿模型 + 遗传算法 + 早停 + 灭绝 |
 | `scripts/prompt_evolver.py` | 岛屿模型 + 遗传算法 + 早停 + 灭绝 |
 | `scripts/seed_extractor.py` | 内置15题材配置 → 5岛种子提取 |
 | `scripts/seed_extractor.py` | 内置15题材配置 → 5岛种子提取 |
 | `scripts/event_store.py` | 事件溯源引擎(编译/写入/列出事件) |
 | `scripts/event_store.py` | 事件溯源引擎(编译/写入/列出事件) |
-| `scripts/feedback_collector.py` | 多维反馈收集 + 事件写入 |
+
 | `scripts/quality_tuner.py` | 质量阈值自适应调优 |
 | `scripts/quality_tuner.py` | 质量阈值自适应调优 |
 | `scripts/pattern_mine.py` | MAP-Elites 写作模式挖掘 |
 | `scripts/pattern_mine.py` | MAP-Elites 写作模式挖掘 |
 | `scripts/utils.py` | 共享工具(路径解析/题材映射/持久化)|
 | `scripts/utils.py` | 共享工具(路径解析/题材映射/持久化)|

+ 0 - 191
scripts/feedback_collector.py

@@ -1,191 +0,0 @@
-#!/usr/bin/env python3
-"""
-feedback_collector.py — 结构化反馈收集器
-反馈数据写入 evolution/session_state.json 和项目数据库。
-"""
-
-import sys, os, re, json
-from pathlib import Path
-from datetime import datetime
-from collections import Counter
-from typing import Any
-
-sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
-from utils import (
-    find_project_root, get_evolution_dir,
-    load_evolution, save_evolution, load_project_db, save_project_db,
-    log_evolution_event,
-)
-
-
-def collect_chapter_feedback(project: Path, chapter_num: int,
-                              scores: dict[str, int],
-                              prompt_used: str = "",
-                              issues: list[str] | None = None,
-                              notes: str = "") -> dict:
-    db = load_project_db(project)
-    entry = {
-        "timestamp": datetime.now().isoformat(),
-        "chapter": chapter_num,
-        "scores": scores,
-        "composite": sum(scores.values()) / len(scores) if scores else 0,
-        "prompt_used_hash": hash(prompt_used) % 100000 if prompt_used else None,
-        "prompt_used": prompt_used[:200] if prompt_used else "",
-        "issues": issues or [],
-        "notes": notes,
-    }
-    db.setdefault("feedback", []).append(entry)
-    db.setdefault("meta", {}).setdefault("quality_scores", {})[str(chapter_num)] = entry["composite"]
-    save_project_db(project, db)
-
-    # 更新会话状态
-    state = load_evolution("session_state.json") or {}
-    state.setdefault("recent_chapters", []).append({
-        "chapter": chapter_num,
-        "composite": entry["composite"],
-        "timestamp": entry["timestamp"],
-    })
-    # 只保留最近 20 章
-    state["recent_chapters"] = state["recent_chapters"][-20:]
-    state["total_feedback_count"] = state.get("total_feedback_count", 0) + 1
-    save_evolution("session_state.json", state)
-
-    # 写入事件日志(Event Sourcing — git 共享无冲突)
-    if prompt_used:
-        _write_feedback_event(project, chapter_num, scores, prompt_used)
-
-    log_evolution_event(project, "章节反馈收集", {
-        "章节": chapter_num,
-        "综合评分": f"{entry['composite']:.0f}",
-        "各维评分": ", ".join(f"{k}:{v}" for k, v in scores.items()),
-        "问题数": len(issues or []),
-    })
-    return entry
-
-
-def _write_feedback_event(project: Path, chapter_num: int,
-                          scores: dict[str, int],
-                          prompt_used: str) -> None:
-    """将反馈写入事件日志(追加写入,天然无 git 冲突)。
-
-    不再直接修改 population.json —— 改为写入不可变事件文件。
-    population.json 通过 `evolve.sh --compile` 从事件编译生成。
-    """
-    from hashlib import md5 as _md5
-    from utils import (find_project_genre, map_genre_to_inkos_id,
-                       load_genre_evolution)
-    from event_store import write_events
-
-    genre_name = find_project_genre(project)
-    genre_id = map_genre_to_inkos_id(genre_name)
-
-    # 匹配变体:从当前编译后的 population 中查找
-    pop = load_genre_evolution(genre_id, "prompts/population.json")
-    prompt_hash = _md5(prompt_used.encode()).hexdigest()[:12]
-    prompt_key = prompt_used[:40] if len(prompt_used) > 40 else prompt_used
-
-    matched_island = "writing"
-    matched_id = prompt_hash
-
-    if pop:
-        for cat, pop_data in pop.items():
-            for variant in pop_data.get("variants", []):
-                tmpl = variant.get("template", "")
-                if (variant.get("id") == prompt_hash
-                        or (prompt_key and prompt_key in tmpl)
-                        or (prompt_used and len(tmpl) >= 40 and tmpl[:40] in prompt_used)):
-                    matched_island = cat
-                    matched_id = variant.get("id", prompt_hash)
-                    break
-            else:
-                continue
-            break
-
-    event = {
-        "type": "feedback",
-        "chapter": chapter_num,
-        "island": matched_island,
-        "variant_id": matched_id,
-        "variant_template": prompt_used,  # 携带模板文本,编译时可重建缺失变体
-        "scores": {k.upper(): v for k, v in scores.items()},
-    }
-    write_events(genre_id, [event])
-
-
-def parse_user_feedback(text: str) -> dict:
-    feedback = {"sentiment": "neutral", "mentioned_dimensions": [],
-                "mentioned_chapters": [], "action_items": []}
-
-    pos_words = ["好", "不错", "很好", "精彩", "满意", "perfect", "great"]
-    neg_words = ["差", "不好", "弱", "无聊", "平淡", "不行", "重写", "废弃"]
-    pos_count = sum(1 for w in pos_words if w in text)
-    neg_count = sum(1 for w in neg_words if w in text)
-    if pos_count > neg_count:
-        feedback["sentiment"] = "positive"
-    elif neg_count > pos_count:
-        feedback["sentiment"] = "negative"
-
-    dim_keywords = {
-        "结构": ["结构", "节奏", "场景", "布局"],
-        "角色": ["角色", "人物", "主角", "配角", "人设"],
-        "原创性": ["套路", "新鲜", "创新", "模板"],
-        "对话": ["对话", "对白", "台词"],
-        "文本": ["文字", "措辞", "句式", "描写"],
-        "钩子": ["钩子", "悬念", "伏笔", "期待"],
-        "爽点": ["爽点", "高潮", "打脸", "爽感"],
-        "情感": ["情感", "情绪", "心理"],
-    }
-    for dim, keywords in dim_keywords.items():
-        if any(kw in text for kw in keywords):
-            feedback["mentioned_dimensions"].append(dim)
-
-    chapter_refs = re.findall(r"第(\d+)章", text)
-    feedback["mentioned_chapters"] = [int(c) for c in chapter_refs]
-
-    for m in re.finditer(r"(?:需要|应该|必须|要)\s*(.+?)(?:[。!,,.]|$)", text):
-        feedback["action_items"].append({"type": "required", "content": m.group(1).strip()})
-
-    return feedback
-
-
-if __name__ == "__main__":
-    import argparse
-    parser = argparse.ArgumentParser(description="反馈收集器")
-    parser.add_argument("action", choices=["collect", "parse", "state"])
-    parser.add_argument("--project", "-p", default=".")
-    parser.add_argument("--chapter", "-c", type=int)
-    parser.add_argument("--scores", "-s", type=str, default="{}")
-    parser.add_argument("--prompt", type=str, default="")
-    parser.add_argument("--issues", "-i", nargs="*", default=[])
-    parser.add_argument("--notes", "-n", type=str, default="")
-    parser.add_argument("--text", "-t", type=str, default="")
-    args = parser.parse_args()
-
-    if args.action == "collect":
-        root = find_project_root(Path(args.project).resolve())
-        if not root:
-            print("错误: 未找到小说项目根目录")
-            sys.exit(1)
-        if not args.chapter:
-            print("错误: 需要 --chapter")
-            sys.exit(1)
-        try:
-            scores = json.loads(args.scores)
-        except json.JSONDecodeError:
-            print("错误: --scores 需要 JSON 格式")
-            sys.exit(1)
-        result = collect_chapter_feedback(root, args.chapter, scores,
-                                          prompt_used=args.prompt,
-                                          issues=args.issues, notes=args.notes)
-        print(f"✓ 章节 {args.chapter} 反馈已收集 (综合: {result['composite']:.0f})")
-
-    elif args.action == "parse":
-        if not args.text:
-            print("错误: 需要 --text")
-            sys.exit(1)
-        result = parse_user_feedback(args.text)
-        print(json.dumps(result, ensure_ascii=False, indent=2))
-
-    elif args.action == "state":
-        state = load_evolution("session_state.json") or {}
-        print(json.dumps(state, ensure_ascii=False, indent=2))