M7:形仪与语音——真形锚点、候选定相、声音档案与克隆授权、ASR 接入
- 形仪域 domains/xingyi:form_anchors(稳定辨识特征/年龄表现/许可禁忌/可变范围——生成内容不可静默覆盖锚点);forms(主仪/化仪/文字形仪,candidate→adopt 定相治理:未定相不进呈现位、主仪唯一、新主仪自动退役旧主仪);voice_profiles(三来源,授权克隆必填用途与传播范围,revoke-grant 撤回立即生效,assert-usable 合成前置校验拒绝撤回/过期) - ASR:元炁 SenseVoice /v1/audio/transcriptions 透传(Whisper 兼容 multipart);YUANQI_BASE_URL 未配置时 503 不降级不伪造——多模态关闭纪律 - 前端形仪工坊(人物详情页):真形锚点编辑(特征逐行解析)/候选登记定相废弃/声音档案建立与授权撤回;头像呈现位改走定相主仪(forms/primary);xingyi api 库 + mock + 组件 4 用例 - 退役:旧 avatar 模块(services/endpoints/avatar、avatar_dir 配置、avatar_url 字段、前端直传组件与测试) - 验收(test_m7_xingyi 三用例):未定相不成为正式形仪(含主仪唯一与旧主仪 retired 断言);克隆授权可撤回(缺用途拒/撤回即拒/过期同理/预设不受约束);关闭全部多模态后文字相伴完整可用(ASR 503 时镜树缘契百工照常——回归) - 四套件:后端 376、前端 203、BFF 4、神识 5 包全绿(2 个预存环境失败不变);迁移 008 净库+±1 干净
This commit is contained in:
1 parent
7e23d6fa84
commit
b419e0afde
30 files changed
+1876
-468
No files matched your search
@@ -0,0 +1,88 @@
|
||||
"""形仪域表模型:真形锚点 / 主仪化仪(候选定相)/ 声音档案。
|
||||
|
||||
设计依据 core-domains.md §5 与 PRD §8:
|
||||
- 真形锚点记录稳定辨识特征、年龄表现、许可、禁忌与可变范围;
|
||||
- 生成内容先为 candidate,用户定相(adopt)后才成为正式主仪或化仪;
|
||||
- 声音三来源(合成预设/原创设计/授权克隆);克隆授权按身份、用途、期限与
|
||||
传播范围治理,可撤回,撤回立即生效。
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import DateTime, ForeignKey, String, Text
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.core.ids import new_id
|
||||
from app.core.time import utc_now
|
||||
from app.db.base import Base
|
||||
|
||||
|
||||
class FormAnchor(Base):
|
||||
"""真形锚点:不可被生成内容静默覆盖的稳定辨识约束。"""
|
||||
|
||||
__tablename__ = "form_anchors"
|
||||
|
||||
id: Mapped[str] = mapped_column(String(80), primary_key=True, default=lambda: new_id("anchor"))
|
||||
character_id: Mapped[str] = mapped_column(
|
||||
String(80), ForeignKey("characters.id"), nullable=False, index=True
|
||||
)
|
||||
# 稳定辨识特征(发色/瞳色/身形/标志性印记等)
|
||||
features_json: Mapped[str] = mapped_column(Text, nullable=False, default="{}")
|
||||
# 年龄表现约束(成人角色恒定成人表现;不得生成未成年敏感形态)
|
||||
age_presentation: Mapped[str] = mapped_column(String(40), nullable=False, default="adult")
|
||||
# 许可与禁忌(允许的画风/场景;禁止的表现)
|
||||
permissions_json: Mapped[str] = mapped_column(Text, nullable=False, default="{}")
|
||||
# 可变范围(服装/表情/姿态可变;核心特征不可变)
|
||||
mutable_scope_json: Mapped[str] = mapped_column(Text, nullable=False, default="{}")
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
|
||||
updated_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=utc_now, onupdate=utc_now
|
||||
)
|
||||
|
||||
|
||||
class Form(Base):
|
||||
"""主仪/化仪:一魂多仪。candidate → adopted(定相)/ discarded;同一时刻仅一主仪。"""
|
||||
|
||||
__tablename__ = "forms"
|
||||
|
||||
id: Mapped[str] = mapped_column(String(80), primary_key=True, default=lambda: new_id("form"))
|
||||
character_id: Mapped[str] = mapped_column(
|
||||
String(80), ForeignKey("characters.id"), nullable=False, index=True
|
||||
)
|
||||
# primary 主仪 / costume 化仪 / text 文字形仪(启镜最小形态)
|
||||
kind: Mapped[str] = mapped_column(String(20), nullable=False, default="costume", index=True)
|
||||
# candidate(候选,未定相不转正)/ adopted / discarded / retired
|
||||
status: Mapped[str] = mapped_column(String(20), nullable=False, default="candidate", index=True)
|
||||
# 来源:image_gen(生成)/ upload(上传)/ live2d(模型导入)/ text
|
||||
source: Mapped[str] = mapped_column(String(20), nullable=False, default="upload")
|
||||
# 文字描述(所有形态必填——文字形仪或图像的文字说明)
|
||||
description: Mapped[str] = mapped_column(Text, nullable=False, default="")
|
||||
# 媒体引用(图片文件路径或 Live2D 模型包引用;文字形仪为空)
|
||||
media_ref: Mapped[str | None] = mapped_column(String(500))
|
||||
# Live2D 动作映射(模型 motions/expressions 索引,JSON)
|
||||
live2d_json: Mapped[str] = mapped_column(Text, nullable=False, default="{}")
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
|
||||
adopted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
|
||||
|
||||
class VoiceProfile(Base):
|
||||
"""声音档案:合成预设 / 原创设计 / 授权克隆。"""
|
||||
|
||||
__tablename__ = "voice_profiles"
|
||||
|
||||
id: Mapped[str] = mapped_column(String(80), primary_key=True, default=lambda: new_id("voice"))
|
||||
character_id: Mapped[str] = mapped_column(
|
||||
String(80), ForeignKey("characters.id"), nullable=False, index=True
|
||||
)
|
||||
# synthesis_preset / original_design / authorized_clone
|
||||
source: Mapped[str] = mapped_column(String(30), nullable=False, default="synthesis_preset")
|
||||
name: Mapped[str] = mapped_column(String(120), nullable=False)
|
||||
# 合成参数(音色/语速/音高;预设名或设计参数)
|
||||
params_json: Mapped[str] = mapped_column(Text, nullable=False, default="{}")
|
||||
# 克隆授权(authorized_clone 必填):身份、用途、期限、传播范围;可撤回
|
||||
grant_purpose: Mapped[str | None] = mapped_column(String(200))
|
||||
grant_expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
grant_distribution: Mapped[str | None] = mapped_column(String(200))
|
||||
grant_revoked_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
is_active: Mapped[bool] = mapped_column(default=True, nullable=False, index=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
|
||||
Reference in new issue
Block a user