Skip to content

cubenlp/PoetrySite

Repository files navigation

Poet Role Evolution(诗人角色进化)

这是一个独立实验 project:不再把“单首词”当作进化个体,而是让“诗人角色(带记忆)”在多轮写作-评审-更新中持续进化。

整体流程(每一轮 round)

固定一个 cipai + title,循环 N 轮:

  1. 写作:诗人根据当前记忆生成 k 个候选词作(默认 k=3)。
  2. 评审:对每个候选同时打三类分:
    • LLM 评审(两种模式):
      • absolute:对每首给信息量 informativeness + 艺术性 aesthetic(1–10)+ 理由
      • relative(默认):同轮 k 个候选做相对排序(rank),再映射回 1–10(缓解打分饱和)
    • 格律信号:结构匹配(True/False)+ 平仄匹配率 tonal_score(0–1)
    • 押韵信号:按词牌韵位的一致性评分 rhyme_score(0–1)
    • 用典信号(可选):allusion_count(严格 form 词表匹配命中数量)+ 命中列表
  3. 择优:先算 fitness = info_component + aes_component + tonal_score + rhyme_score,再按 selection_score 选本轮最佳候选:
    • selection_score = fitness + allusion_weight * ac_factor + rhyme_weight * rhyme_score
    • ac_factor = -distance(allusion_count, [2,3])(命中 2~3 时为 0,偏离越大越负)
    • absolute/relative:都使用 judge 给出的 1~10 分,component = score / 10
    • relative 中的 rank 仅保留为同轮排序信息,不直接参与 fitness
  4. 更新记忆:把评审理由 + 格律问题,转成“可执行写作规则”的 JSON patch,更新诗人记忆。
  5. 落盘:每轮保存候选、分数、选中项、记忆快照,便于回放和分析。

关键模块(代码位置)

  • 写作代理:src/poet_role_evolve/agent.py
  • 评审器:src/poet_role_evolve/judge.py
  • 记忆 schema + patch 应用:src/poet_role_evolve/memory.py
  • 主流程编排(数据流核心):src/poet_role_evolve/runner.py
  • LLM 访问层(含 Mock):src/poet_role_evolve/llm_provider.py
  • KG 典故检索(可选):src/poet_role_evolve/kg/
  • 用典统计(严格 form 匹配):src/poet_role_evolve/allusion_match.py
  • 词牌/平仄校验(自包含拷贝并调整 import):src/poet_role_evolve/cipai_utils.pysrc/poet_role_evolve/poem.pysrc/poet_role_evolve/xinyun/
  • CLI 入口:scripts/run.py

数据流与产出(results 结构)

输入:

  • 词牌模板数据:data/cipai2info.json(本 project 内自包含)
  • .env:API Key / Base URL(默认读取 CHATANY_API_KEY / CHATANY_BASE_URL,也兼容 OPENAI_API_KEY / OPENAI_BASE_URL
  • (可选)KG 典故检索:NEO4J_URI/NEO4J_USER/NEO4J_PASSWORD

输出(每次运行一个独立目录):

  • results/poet_role_evolve/<run_id>/config.json:完整参数与模型名
  • results/poet_role_evolve/<run_id>/kg_allusions.json:本次 run 的关键词与 Top-K 典故池(KG 不可用则为 error + 空列表)
  • results/poet_role_evolve/<run_id>/intention.jsonprompt v2 的创作意图(若启用)
  • results/poet_role_evolve/<run_id>/memory_init.json:初始记忆
  • results/poet_role_evolve/<run_id>/rounds.jsonl:每轮所有候选 + 分数 + 选中项
  • results/poet_role_evolve/<run_id>/memory_snapshots.jsonl:每轮 patch + patch_raw + 更新后的记忆
  • results/poet_role_evolve/<run_id>/best.json:全程 top5 候选(先按历史 selection_score 取 top5,再做一次 relative rank 复评,并按 overall_score 做最终排序;保留 top1 兼容字段)

快速开始

cd poet_role_evolve
pip install -r requirements.txt
cp config.example.yaml config.yaml
cp .env.example .env  # 填写 key/base_url(推荐把 key 放 env,不要写进 config.yaml)

如需启用 KG 典故检索(可选),在 .env 里补齐 NEO4J_URI/NEO4J_USER/NEO4J_PASSWORD,并在 config.yaml 中设置 kg.enabled: true

Prompt 方案(v1 / v2)

config.yaml 可切换:

prompts:
  profile: v2          # v1 | v2
  intention:
    enabled: true
    seed: ""
    max_chars: 600

last_round_poem:
  enabled: false       # true 时:把上一轮入选作品全文 + 结构/平仄/押韵评估写入记忆并注入下一轮写作 prompt

rhyme_memory:
  enabled: false       # true 时:在长期记忆中注入“同韵/换韵策略 + 韵脚一致性约束”

memory_settings:
  max_inspirations: 20
  max_revision_checks: 20
  max_avoid_patterns: 20
  max_rhyme_lessons: 20
  max_good_phrases: 10
  max_bad_cases: 10
  • v1:保留原始写作 prompt(向后兼容)。
  • v2:加入“硬约束优先 + intention + 词牌分型冷启动记忆”。

v2 中,intention 默认在每次 run 冷启动时生成一次并落盘,不参与每轮 patch 更新;在写作 prompt 中以中文“意图要点”呈现(非 JSON,不含用典/意象策略这类硬约束项)。 若 rhyme_memory.enabled: true,会根据词牌规则生成“押韵要点”,并写入 intention.jsonrhyme_guidance 及初始记忆。 memory_settings 的 canonical 容量键也已切到新 schema;旧的 max_principles / max_checklist 等名称目前仍可读取,但只作为兼容别名。

API/供应商配置怎么理解(推荐心智模型)

你可以把配置理解成两层:

  1. 供应商(vendor/provider):一套 base_url + api_key(可能是 OpenAI 官方,也可能是任何 OpenAI-compatible 代理/平台)。
  2. 模型 ID(model):该供应商下你要调用的具体模型名(例如 deepseek-v3.2 / gpt-5.1 / kimi-k2 等)。

本项目在 config.yaml 里用:

  • providers.<name> 定义供应商(base_url / api_key)
  • llm.<role>.provider_ref 选择用哪个供应商
  • llm.<role>.model 选择用该供应商下的哪个模型 ID

示例(一个供应商):

providers:
  vendor_a:
    provider: openai
    api_key_env: CHATANY_API_KEY
    base_url_env: CHATANY_BASE_URL

llm:
  poet:   { provider_ref: vendor_a, model: deepseek-v3.2 }
  judge:  { provider_ref: vendor_a, model: gpt-5.1 }
  memory: { provider_ref: vendor_a, model: gpt-5.1 }

示例(两个供应商:写作走 A,评审走 B):

providers:
  vendor_a: { provider: openai, api_key_env: A_KEY, base_url_env: A_URL }
  vendor_b: { provider: openai, api_key_env: B_KEY, base_url_env: B_URL }

llm:
  poet:   { provider_ref: vendor_a, model: deepseek-v3.2 }
  judge:  { provider_ref: vendor_b, model: gemini-3-pro-preview }
  memory: { provider_ref: vendor_a, model: gpt-5.1 }

多评审(3 个 judge 取平均)

如果你想用 3 个不同评审模型来降低偏差,可以在 llm 里配置 judges 列表:

llm:
  judge:
    provider_ref: vendor_a   # 作为 judges 的默认供应商(可选)
  judges:
    - { model: gemini-3-pro-preview }
    - { model: kimi-k2-0905-preview }
    - { model: doubao-seed-1-6-251015 }

运行时每个 candidate 会被这三个 judge 各评一次,最后 informativeness/aesthetic 取平均(只对成功解析的 judge 求平均;若全失败则为 0)。

评审模式:absolute vs relative(推荐 relative)

run.judge_mode 中选择:

  • absolute:每首单独打 1–10 分(旧行为)
  • relative(默认):同轮 k 个候选做 rank,再线性映射回 1–10(rank=1→10,rank=k→1),更不容易出现“全是 9/10”饱和。

当相对排序输出无法解析/不满足全排列约束时,会自动回退到 absolute 逐个打分,保证流程不中断。

KG 典故池与用典统计(可选)

  • kg.enabled: true 时,会用 title 作为关键词,从 Neo4j 聚合 Top-K 典故条目(典故名 + 1–2 个常见 form + 出处古籍(若有)),写入初始记忆并注入写作 prompt。
  • 每个候选会统计 allusion_count:对“典故 form 词表”做严格子串匹配(便于自动统计与人工核验),并输出命中 forms 列表。
  • allusion_count 不参与 fitness,但会通过 ac_factor 影响 selection_score(更偏好 2~3 的用典密度)。
  • prompt 展示层可在 memory_settings 控制条目数量,尤其是 prompt_allusion_forms_per_item(每个典故展示几个 form)。

运行(真实 API):

cd poet_role_evolve
python scripts/run.py --config config.yaml

批量运行 ACL 实验(读取 data/acl_experiment/experiment_config_8x6.json,输出到 results/acl_exp):

cd poet_role_evolve
python scripts/run_acl_experiment.py --config config.yaml --out-dir results/acl_exp

干跑(不调用 API,用于快速验证流程):

cd poet_role_evolve
python scripts/run.py --config config.yaml --mock

测试:

cd poet_role_evolve
python -m pytest -q

关键实现约定(便于你改实验)

  • 记忆更新使用 patch:LLM 只输出严格 JSON patch;代码确定性应用(去重/裁剪/版本号+1)。
  • 记忆编辑器是上一轮提炼器:输入是整轮 candidates 证据 JSON,专门提炼 good_phrases / inspirations / bad_cases / avoid_patterns / rhyme_lessons / revision_checks
  • patch 失败不让流程中断:解析失败会用 fallback patch(确定性规则)继续跑,并在 memory_snapshots.jsonl 记录错误。
  • prompt profile 可切换run 期间统一使用 config.prompts.profile 指定的写作/记忆更新模板。
  • v2 意图建模可回退:intention JSON 解析失败时自动回退默认意图,并在 intention.json 标记 source/error。
  • 记忆支持增删:patch 可对 inspirations / revision_checks / avoid_patterns / rhyme_lessons / good_phrases / bad_cases 做 add/remove。
  • 好句与反例都单句化add_good_phrases / add_bad_cases 若传多行文本会被拒收,避免整首作品写入长期记忆。
  • 短期信息会被拦截:标题、创作意图、上一轮作品、评分/rank/候选编号等运行时信息不会进入长期记忆。
  • 押韵诊断可解释:Judge 除 rhyme_score 外,还会输出 rhyme_feedback 与结构化 rhyme_diagnostics,供筛选、落盘与记忆提炼复用。
  • Runner 中创建 CiPoem 时默认 auto_split_que=False:避免模型输出行分割与模板阕结构不一致时抛异常;格律检查仍以 default_auditor 的模板匹配为准。
  • 相对排序评审输出为严格 JSON;解析失败会回退到绝对分评审,保证流程不中断。

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors