Files
hunjing/backend/app/schemas/character.py
T
chenxin 7e23d6fa84 M6:缘契、人格与世界——契约版本链、铸魂分灵、河图境界与三界分流
- 缘契域 domains/yuanqi:covenants(当前版)+ covenant_events(不可变历史);提议—问心—铭契—撤回全链;边界变更立即生效;多维关系并存,服务层拒绝 affinity/好感度单一键;浪漫维度成人资格标记位
- 道体铸魂与分灵 domains/jingsheng/soul.py:soul_forgings 确认流(锚点变更 pending→confirmed 应用并签发新魂籍版本,确认前人物锚点不变);分灵创建新人物(继承资料与谱系 lineage 链、不继承原身份,魂籍从 v1 起)
- 河图域 domains/hetu:persistent_worlds 境界 + world_entities/world_relations 境界作用域重建 + 世谱挂接;境界正史视图(scope=persistent_world 归真集合);canonize 后置推进正史计数
- 三界分流:reality→息壤提取(不变);persistent_world→境界实录+正史推进;simulation→只记试演实录;factual_records 增 scope 列——境界/幻境实录与真界本相隔离
- 正影打通:引文 target_type=memory 时被引记忆 superseded → 返回 successor_memory_id 提示,不静默替换
- 前端:人物详情页缘契面板(提议维度选择/铭契/撤回/事件史)+ 世界页重建(境界目录/实体/正史概览)+ covenants/worlds api 库
- 退役:旧 personality/drive/evolution/world 模块、服务、端点、仓储、schema、前端五页与组件样式;迁移 007 退役九张旧表与 characters.current_personality_version_id
- 验收(test_m6_domains 六用例):多维无单一好感度/铭契版本链/事件不可抹除/撤回立即生效/边界即时/铸魂确认流+魂籍版本/分灵谱系/境界正史不进真界(实录 scope 隔离+真界候选=0)/引文正影后继
- 四套件:后端 379、前端 199、BFF 4、神识 5 包全绿(2 个预存环境失败不变);迁移 007 净库+±1 干净
2026-08-27 20:10:11 +08:00

136 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""人物 API schema。"""
from typing import Any
from pydantic import BaseModel, ConfigDict, Field
class CharacterResponse(BaseModel):
model_config = ConfigDict(
json_schema_extra={
"examples": [
{
"id": "character_ec83d55746c54e47ab6f98d683032626",
"name": "default",
"display_name": "魂镜默认人物",
"status": "active",
"language": "zh-CN",
"profile": {"bio": "本地 MVP 默认人物。"},
"model_policy": {"default_model_hint": "deepseek-v4-flash"},
"privacy_level": "normal",
"owner_scope": "local-user",
"is_system_template": False,
"source_template_id": "character_template_default",
"created_at": "2026-06-19T09:00:00.000000Z",
"updated_at": "2026-06-19T09:00:00.000000Z",
}
]
}
)
id: str = Field(description="人物 ID,前缀为 character_。")
name: str = Field(description="人物内部名称。")
display_name: str | None = Field(description="人物显示名称。")
status: str = Field(description="人物状态,取值见契约字典 character.status。")
language: str = Field(description="人物默认语言。")
profile: dict[str, Any] = Field(description="人物档案 JSON。")
model_policy: dict[str, Any] = Field(description="人物模型策略。")
privacy_level: str = Field(description="隐私等级:normal / sensitive / local_only。")
owner_scope: str = Field(description="归属范围;当前本地 MVP 为 local-user。")
is_system_template: bool = Field(description="是否系统人物模板;active API 通常返回 false。")
source_template_id: str | None = Field(
description="来源系统模板人物 ID;非模板复制人物通常有值。"
)
avatar_url: str | None = Field(
default=None, description="角色头像 URL。无头像时为 null。"
)
created_at: str = Field(description="创建时间,UTC ISO 8601 字符串。")
updated_at: str = Field(description="更新时间,UTC ISO 8601 字符串。")
class CharacterSummaryResponse(BaseModel):
"""人物列表项(api-spec §6 列出人物)。"""
id: str = Field(description="人物 ID,前缀为 character_。")
name: str = Field(description="人物内部名称。")
display_name: str | None = Field(description="人物显示名称。")
status: str = Field(description="人物状态,取值见契约字典 character.status。")
memory_count: int = Field(default=0, description="人物关联的未删除记忆数量。")
personality_version: int = Field(default=0, description="当前人格版本号;尚未形成人格时为 0。")
activated_at: str | None = Field(
default=None, description="最近激活时间,UTC ISO 8601 字符串。"
)
class CreateCharacterRequest(BaseModel):
name: str = Field(min_length=1, description="人物内部名称,必填。")
display_name: str | None = Field(default=None, description="可选显示昵称。")
template_key: str | None = Field(
default=None,
description="系统模板 key;传此值则从模板创建(继承档案/模型策略,status=active)。",
)
profile: dict[str, Any] | None = Field(
default=None,
description="人物档案,可含 birthday/height/weight/background/speaking_style。",
)
model_policy: dict[str, Any] | None = Field(
default=None,
description="模型策略,可含 default_chat_model_hint / memory_extraction_model_hint 等。",
)
class UpdateProfileRequest(BaseModel):
"""更新人物档案(api-spec §6 PATCH /characters/{id}/profile)。手动编辑视为用户确认。"""
display_name: str | None = Field(default=None, description="可选显示昵称。")
birthday: str | None = Field(default=None)
height: str | None = Field(default=None)
weight: str | None = Field(default=None)
description: str | None = Field(default=None, description="一句话简介。")
background: str | None = Field(default=None)
speaking_style: str | None = Field(default=None, description="表达风格。")
temperament: str | None = Field(default=None, description="性情气质。")
hobbies: list[str] | None = Field(default=None, description="兴趣爱好列表。")
values: list[str] | None = Field(default=None, description="价值观列表。")
class UpdateModelPolicyRequest(BaseModel):
"""更新人物模型策略(api-spec §6 PATCH /characters/{id}/model-policy)。"""
default_chat_model_hint: str | None = Field(default=None)
memory_extraction_model_hint: str | None = Field(default=None)
personality_analysis_model_hint: str | None = Field(default=None)
embedding_model_hint: str | None = Field(default=None)
privacy_level: str | None = Field(default=None)
class ActivateCharacterResponse(BaseModel):
"""激活人物响应(api-spec §6 POST /characters/{id}/activate)。"""
active_character_id: str = Field(description="当前激活人物 ID。")
status: str = Field(description="激活后状态,恒为 active。")
class CharacterTemplateSummaryResponse(BaseModel):
"""系统模板列表项(GET /character-templates)。"""
key: str = Field(description="模板唯一标识(template_key)。")
name: str = Field(description="模板人物内部名称。")
display_name: str | None = Field(description="模板人物显示昵称。")
description: str | None = Field(description="档案中的一句话描述(profile.description)。")
temperament: str | None = Field(description="档案中的性情气质(profile.temperament)。")
speaking_style: str | None = Field(description="档案中的说话风格(profile.speaking_style)。")
language: str = Field(description="默认语言。")
class ImportCardResponse(BaseModel):
"""角色卡导入结果。"""
character_id: str = Field(description="新建人物 ID。")
name: str = Field(description="人物名称。")
display_name: str | None = Field(default=None, description="显示名(V3 nickname 优先)。")
lorebook_id: str | None = Field(
default=None, description="导入的世谱 ID(character_book);无则为 null。"
)
entry_count: int = Field(default=0, description="世谱条目数。")