feat(prompt): 攻击提示词按运动拓扑分四支 - #320
Conversation
attack.md 拆成 sweep/thrust/project/lunge × side/front 八节,去掉 crescent / broad side 这类形状先验 —— 它们等于断言角色手握一件有宽面的长条物,喂法杖 / 空手 / 四足角色时模型会凭空补出那件东西(1024XEngineer#195 只清了装备名词,没清形状先验)。 build_attack_prompt 新增 archetype(默认 THRUST,SWEEP 是唯一要求持有长条物的 一支),ActionSpec 加同名字段并对非攻击动作拒收;母版姿态同步分四支。 构图约束抽到 _framing 由代码统一追加到五个动作,只写正向计数句。 Refs 1024XEngineer#310
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
| # attack 同样进不了那张表:它还要按运动拓扑选提示词分支。archetype 缺省时不在这里 | ||
| # 兜一个默认值 —— 缺省只由 build_attack_prompt 定义一次,写两处会各自漂移。 | ||
| if action.action is ActionType.ATTACK: | ||
| if action.archetype is None: |
There was a problem hiding this comment.
[P1] 把 archetype 贯通到生产请求模型
生产入口 CharacterActionGenerateRequest、CharacterActionInput 和 ActionTaskExecutor._produce_action 都没有 archetype 字段或转发逻辑,所以所有 API 提交的 attack 最终都会走这里的 None 分支并固定使用默认 THRUST;客户端即使提交 archetype: "sweep"/"project"/"lunge",Pydantic 请求模型也会把这个未知字段忽略。请将该枚举从请求层贯通到 ActionSpec(并对非 attack 拒收),否则新增的三个非默认拓扑在实际产品路径中不可达。
| # attack 按运动拓扑取母版姿态:四支的起手姿态互不兼容(横挥蓄力母版跑不出直刺), | ||
| # 而"母版姿态决定动作"对 attack 最狠 —— 见本模块开头。这里不放行空值: | ||
| # 四支都必须有自己的蓄力姿态,缺一支就该炸,不能退回中性站立。 | ||
| ATTACK_MASTER_POSES = { |
There was a problem hiding this comment.
[P1] 让拓扑专用母版姿态进入生成路径
这张新映射目前只被测试导入,生产代码没有任何消费者;VideoFrameStrategy.derive 仍直接使用同一份调用方 master,并且只按动作字符串调用 prepare_master(master, "attack"),完全不知道所选 archetype。于是即使直接构造 ActionSpec(archetype=LUNGE/PROJECT/...),运行时也只是换了视频提示词,不会使用这里声明的互不兼容的起手姿态,正好违背本 PR 所述“母版姿态决定动作”的核心约束。请在母版生成/选择链路中按 archetype 消费该映射,或把对应姿态随动作规格明确传入。
Refs #310
问题
attack.md里三处措辞合起来断言了角色的身体构造和手里拿的东西:the leading arm—— 断言有手臂,且发力主语是手臂downward crescent arc—— 断言挥动轨迹是弧线broad side facing the viewer—— 断言手里那件东西有"宽面"三条合起来 = "双足 + 有手臂 + 手握一件有宽面的长条物"。喂法杖 / 空手 / 四足角色时,
图文矛盾会被模型自己调和掉,凭空补出那件宽面长条物。#195 那次修复只清了装备名词
(the weapon / the sword),没清装备形状先验,所以同一个坑从名词层退到了形状层。
改法
按身体怎么发力分四支运动拓扑,而不是按手里拿什么分:
sweepthrustprojectlungeattack.md拆成<拓扑>.<朝向>八节,master_poses.md的 attack 节同步拆成四节。母版姿态必须跟着拆:四支的起手姿态互不兼容 —— 拿横挥蓄力母版跑直刺,模型会先把收在
腰际的那侧重新抡起来再做。所以
ATTACK_MASTER_POSES不放行空值,缺一支就炸,不退回中性站立。
build_attack_prompt加archetype关键字参数,默认 THRUST:四支里只有 SWEEP要求手里有一件有宽面的长条物,拿它当默认等于对每个未知角色继续断言持械。
ActionSpec.archetype是可选字段,非攻击动作带它会被 validator 拒收(它只被攻击提示词消费,传了不生效,静默忽略比报错更坏)。缺省值只在
build_attack_prompt定义一处,ActionSpec侧留None,避免同一个缺省两处各写一份后各自漂移。顺带把构图约束抽进
prompt/_framing.py,由代码统一追加到 walk / jump / idle / attack /custom 五个动作,不再抄进每份 md —— 同一条约束抄 N 份会各自漂移。只写正向计数句
("恰好一个角色在画面里"),不写否定句:该 i2v 接口没有 negative_prompt,否定句里的名词
会被 latch 进画面。
怎么验证的
新增
backend/tests/test_attack_archetypes.py(57 个用例),按结构性质断言而不是背文案:拓扑×朝向组合都解析到真正文,两两互不相同the leading armActionSpec对非攻击动作拒收 archetype;派生层真的把 archetype 传下去了本地闸门(backend/):
没跑任何付费生成,断言都是纯文本结构检查。
范围
只含后端。
_framing.py会被后续几个动作相关 PR 共用,但本 PR 自带完整实现,可独立合入。