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:
@@ -293,6 +293,7 @@ async def generate_characters(
|
||||
gateway=gateway,
|
||||
user_id=STUB_OWNER_ID,
|
||||
project_id=project_id,
|
||||
role_mix=body.role_mix,
|
||||
)
|
||||
await session.commit()
|
||||
log.info(
|
||||
|
||||
@@ -12,7 +12,7 @@ snake_case;前端经 OpenAPI 生成 TS 类型消费。改字段 → 前端必
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
|
||||
from ww_api.schemas.rules import RuleView
|
||||
|
||||
@@ -47,11 +47,40 @@ class WorldGenPreviewResponse(BaseModel):
|
||||
|
||||
|
||||
class CharacterGenerateRequest(BaseModel):
|
||||
"""POST /projects/:id/characters/generate:据需求生成角色卡(预览,群像防雷同)。"""
|
||||
"""POST /projects/:id/characters/generate:据需求生成角色卡(预览,群像防雷同)。
|
||||
|
||||
`role_mix`(⑦ 群像按定位配比)与 `count` 的关系:`role_mix` 在场时 `count` 取各值之和
|
||||
(忽略客户端显式 count),每项数量须 ≥ 1、总和须 ≤ `MAX_GENERATE_COUNT`;缺省则退回
|
||||
单一 `role` + `count` 语义。
|
||||
"""
|
||||
|
||||
brief: str = Field(min_length=1, description="角色生成需求")
|
||||
count: int = Field(default=1, ge=1, le=MAX_GENERATE_COUNT, description="生成数量")
|
||||
count: int = Field(
|
||||
default=1,
|
||||
ge=1,
|
||||
le=MAX_GENERATE_COUNT,
|
||||
description="生成数量(role_mix 在场时取各值之和)",
|
||||
)
|
||||
role: str | None = Field(default=None, description="角色定位(主角/CP/对手/导师/工具人 等)")
|
||||
role_mix: dict[str, int] | None = Field(
|
||||
default=None,
|
||||
description="按定位配比生成 {定位: 数量};在场时 count=各值之和(每项≥1、总和≤12)",
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _reconcile_role_mix(self) -> CharacterGenerateRequest:
|
||||
"""配比在场时校验并把 count 定为各值之和(构造期归一化,非外部对象变更)。"""
|
||||
if self.role_mix is None:
|
||||
return self
|
||||
if not self.role_mix:
|
||||
raise ValueError("role_mix 不能为空对象")
|
||||
if any(n < 1 for n in self.role_mix.values()):
|
||||
raise ValueError("role_mix 每个定位的数量须 ≥ 1")
|
||||
total = sum(self.role_mix.values())
|
||||
if total > MAX_GENERATE_COUNT:
|
||||
raise ValueError(f"role_mix 数量总和须 ≤ {MAX_GENERATE_COUNT}")
|
||||
self.count = total
|
||||
return self
|
||||
|
||||
|
||||
class CharacterRelationView(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user