feat(web): 角色群像按定位配比生成(role_mix 缩减版)
- 契约: CharacterGenerateRequest 加 role_mix{定位:数量},model_validator 归一
count=各值之和(每项≥1、总和≤12),缺省退回单一 role+count
- @llm: build_character_gen_context/run_character_gen 加 role_mix 参并注入配比块
(确定性、无时间戳,守 assemble 纯函数);router 穿参
- character-gen.md 加"按配比严格分配 role"纪律 + regen prompt_hashes 金标准
- 前端: sanitizeRoleMix/roleMixTotal + buildCharacterGenerateRequest 第4参 +
useCharacterGen 穿参 + RoleMixEditor + CharacterGenerator 单一/配比双模
This commit is contained in:
@@ -181,6 +181,39 @@ def test_build_character_gen_context_injects_existing_and_generated() -> None:
|
||||
assert "苏黎" in ctx # 本批已生成卡
|
||||
|
||||
|
||||
def test_build_character_gen_context_injects_role_mix() -> None:
|
||||
# ⑦ 群像按定位配比:role_mix 各定位 + 数量都进上下文,指示模型按配比分配
|
||||
ctx = build_character_gen_context(
|
||||
brief="给我一组群像",
|
||||
count=6,
|
||||
role=None,
|
||||
world_context="",
|
||||
existing_chars=[],
|
||||
generated_so_far=[],
|
||||
role_mix={"主角": 1, "对手": 2, "配角": 3},
|
||||
)
|
||||
|
||||
assert "配比" in ctx # 配比块标识
|
||||
assert "主角" in ctx and "对手" in ctx and "配角" in ctx
|
||||
assert "1" in ctx and "2" in ctx and "3" in ctx
|
||||
|
||||
|
||||
def test_build_character_gen_context_role_mix_overrides_single_role() -> None:
|
||||
# role_mix 在场时用配比块,不再输出单一「角色定位:role」行
|
||||
ctx = build_character_gen_context(
|
||||
brief="群像",
|
||||
count=3,
|
||||
role="主角", # 应被 role_mix 覆盖
|
||||
world_context="",
|
||||
existing_chars=[],
|
||||
generated_so_far=[],
|
||||
role_mix={"对手": 3},
|
||||
)
|
||||
|
||||
assert "角色定位:主角" not in ctx
|
||||
assert "对手" in ctx
|
||||
|
||||
|
||||
def test_build_character_gen_context_handles_empty_anti_dup() -> None:
|
||||
# 首次单生成:无已有/已生成时仍产出可用上下文(不崩)
|
||||
ctx = build_character_gen_context(
|
||||
@@ -243,6 +276,29 @@ async def test_run_character_gen_injects_anti_dup_into_request() -> None:
|
||||
assert "九转炼气" in req.input # 世界观约束注入
|
||||
|
||||
|
||||
async def test_run_character_gen_injects_role_mix_into_request() -> None:
|
||||
# ⑦ role_mix 穿参:run → build_character_gen_context → 请求 input 含各定位
|
||||
gateway = FakeRunGateway(_CARDS)
|
||||
|
||||
await run_character_gen(
|
||||
character_gen_spec,
|
||||
brief="群像",
|
||||
count=5,
|
||||
role=None,
|
||||
world_context="",
|
||||
existing_chars=[],
|
||||
generated_so_far=[],
|
||||
gateway=gateway,
|
||||
user_id=USER,
|
||||
project_id=PROJECT,
|
||||
role_mix={"主角": 2, "配角": 3},
|
||||
)
|
||||
|
||||
req = gateway.last_request
|
||||
assert req is not None
|
||||
assert "配角" in req.input # 配比定位注入
|
||||
|
||||
|
||||
async def test_run_character_gen_raises_when_gateway_fails() -> None:
|
||||
gateway = FailingRunGateway(RuntimeError("provider down"))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user