py-aidol 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aidol/models/__init__.py +2 -1
- aidol/models/aidol.py +4 -2
- aidol/models/aidol_lead.py +22 -0
- aidol/models/companion.py +20 -2
- aidol/repositories/__init__.py +2 -0
- aidol/repositories/aidol.py +2 -0
- aidol/repositories/aidol_lead.py +52 -0
- aidol/repositories/companion.py +38 -5
- aidol/schemas/__init__.py +12 -0
- aidol/schemas/aidol.py +10 -6
- aidol/schemas/aidol_lead.py +38 -0
- aidol/schemas/companion.py +122 -5
- {py_aidol-0.1.0.dist-info → py_aidol-0.2.0.dist-info}/METADATA +1 -1
- py_aidol-0.2.0.dist-info/RECORD +24 -0
- py_aidol-0.1.0.dist-info/RECORD +0 -21
- {py_aidol-0.1.0.dist-info → py_aidol-0.2.0.dist-info}/WHEEL +0 -0
aidol/models/__init__.py
CHANGED
aidol/models/aidol.py
CHANGED
|
@@ -18,7 +18,9 @@ class DBAIdol(BaseModel):
|
|
|
18
18
|
__tablename__ = "aidols"
|
|
19
19
|
|
|
20
20
|
# id, created_at, updated_at inherited from BaseModel
|
|
21
|
-
name: Mapped[str] = mapped_column(String, nullable=
|
|
21
|
+
name: Mapped[str | None] = mapped_column(String, nullable=True)
|
|
22
22
|
concept: Mapped[str | None] = mapped_column(String, nullable=True)
|
|
23
|
-
profile_image_url: Mapped[str] = mapped_column(String, nullable=
|
|
23
|
+
profile_image_url: Mapped[str | None] = mapped_column(String, nullable=True)
|
|
24
24
|
claim_token: Mapped[str | None] = mapped_column(String(36), nullable=True)
|
|
25
|
+
email: Mapped[str | None] = mapped_column(String, nullable=True)
|
|
26
|
+
greeting: Mapped[str | None] = mapped_column(String, nullable=True)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AIdol Leads database model
|
|
3
|
+
|
|
4
|
+
Uses aioia_core.models.BaseModel which provides:
|
|
5
|
+
- id: Mapped[str] (primary key, UUID default)
|
|
6
|
+
- created_at: Mapped[datetime]
|
|
7
|
+
- updated_at: Mapped[datetime]
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from aioia_core.models import BaseModel
|
|
11
|
+
from sqlalchemy import String
|
|
12
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DBAIdolLead(BaseModel):
|
|
16
|
+
"""AIdol Lead (viewer email) database model"""
|
|
17
|
+
|
|
18
|
+
__tablename__ = "aidol_leads"
|
|
19
|
+
|
|
20
|
+
# id, created_at, updated_at inherited from BaseModel
|
|
21
|
+
aidol_id: Mapped[str] = mapped_column(String, nullable=False)
|
|
22
|
+
email: Mapped[str] = mapped_column(String, nullable=False)
|
aidol/models/companion.py
CHANGED
|
@@ -8,7 +8,7 @@ Uses aioia_core.models.BaseModel which provides:
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
from aioia_core.models import BaseModel
|
|
11
|
-
from sqlalchemy import ForeignKey, Index, String, Text
|
|
11
|
+
from sqlalchemy import ForeignKey, Index, Integer, String, Text
|
|
12
12
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
13
13
|
|
|
14
14
|
|
|
@@ -19,9 +19,27 @@ class DBCompanion(BaseModel):
|
|
|
19
19
|
|
|
20
20
|
# id, created_at, updated_at inherited from BaseModel
|
|
21
21
|
aidol_id: Mapped[str | None] = mapped_column(ForeignKey("aidols.id"), nullable=True)
|
|
22
|
-
name: Mapped[str] = mapped_column(String, nullable=
|
|
22
|
+
name: Mapped[str | None] = mapped_column(String, nullable=True)
|
|
23
|
+
gender: Mapped[str | None] = mapped_column(String, nullable=True)
|
|
24
|
+
grade: Mapped[str | None] = mapped_column(String, nullable=True)
|
|
23
25
|
biography: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
24
26
|
profile_picture_url: Mapped[str | None] = mapped_column(String, nullable=True)
|
|
25
27
|
system_prompt: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
26
28
|
|
|
29
|
+
# MBTI scores (1-10 scale)
|
|
30
|
+
mbti_energy: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
31
|
+
mbti_perception: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
32
|
+
mbti_judgment: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
33
|
+
mbti_lifestyle: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
34
|
+
|
|
35
|
+
# Stats (0-100 scale)
|
|
36
|
+
vocal: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
37
|
+
dance: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
38
|
+
rap: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
39
|
+
visual: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
40
|
+
stamina: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
41
|
+
charm: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
42
|
+
|
|
43
|
+
position: Mapped[str | None] = mapped_column(String, nullable=True)
|
|
44
|
+
|
|
27
45
|
__table_args__ = (Index("ix_companions_aidol_id", "aidol_id"),)
|
aidol/repositories/__init__.py
CHANGED
|
@@ -3,9 +3,11 @@ AIdol repositories
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from aidol.repositories.aidol import AIdolRepository
|
|
6
|
+
from aidol.repositories.aidol_lead import AIdolLeadRepository
|
|
6
7
|
from aidol.repositories.companion import CompanionRepository
|
|
7
8
|
|
|
8
9
|
__all__ = [
|
|
9
10
|
"AIdolRepository",
|
|
11
|
+
"AIdolLeadRepository",
|
|
10
12
|
"CompanionRepository",
|
|
11
13
|
]
|
aidol/repositories/aidol.py
CHANGED
|
@@ -25,6 +25,8 @@ def _convert_db_aidol_to_model(db_aidol: DBAIdol) -> AIdol:
|
|
|
25
25
|
return AIdol(
|
|
26
26
|
id=db_aidol.id,
|
|
27
27
|
name=db_aidol.name,
|
|
28
|
+
email=db_aidol.email,
|
|
29
|
+
greeting=db_aidol.greeting,
|
|
28
30
|
concept=db_aidol.concept,
|
|
29
31
|
profile_image_url=db_aidol.profile_image_url,
|
|
30
32
|
claim_token=db_aidol.claim_token,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AIdol Lead repository
|
|
3
|
+
|
|
4
|
+
Implements BaseRepository pattern for BaseCrudRouter compatibility.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from datetime import timezone
|
|
8
|
+
|
|
9
|
+
from aioia_core.repositories import BaseRepository
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
from sqlalchemy.orm import Session
|
|
12
|
+
|
|
13
|
+
from aidol.models import DBAIdolLead
|
|
14
|
+
from aidol.schemas import AIdolLead, AIdolLeadCreate
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class _AIdolLeadUpdate(BaseModel):
|
|
18
|
+
"""Placeholder for update schema (not used)."""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _convert_db_aidol_lead_to_model(db_lead: DBAIdolLead) -> AIdolLead:
|
|
22
|
+
"""Convert DB AIdolLead to Pydantic model."""
|
|
23
|
+
return AIdolLead(
|
|
24
|
+
id=db_lead.id,
|
|
25
|
+
aidol_id=db_lead.aidol_id,
|
|
26
|
+
email=db_lead.email,
|
|
27
|
+
created_at=db_lead.created_at.replace(tzinfo=timezone.utc),
|
|
28
|
+
updated_at=db_lead.updated_at.replace(tzinfo=timezone.utc),
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _convert_aidol_lead_create_to_db(schema: AIdolLeadCreate) -> dict:
|
|
33
|
+
"""Convert AIdolLeadCreate schema to DB model data dict."""
|
|
34
|
+
return schema.model_dump(exclude_unset=True)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class AIdolLeadRepository(
|
|
38
|
+
BaseRepository[AIdolLead, DBAIdolLead, AIdolLeadCreate, _AIdolLeadUpdate]
|
|
39
|
+
):
|
|
40
|
+
"""
|
|
41
|
+
Database-backed AIdolLead repository.
|
|
42
|
+
|
|
43
|
+
Extends BaseRepository for CRUD operations compatible with BaseCrudRouter.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(self, db_session: Session):
|
|
47
|
+
super().__init__(
|
|
48
|
+
db_session=db_session,
|
|
49
|
+
db_model=DBAIdolLead,
|
|
50
|
+
convert_to_model=_convert_db_aidol_lead_to_model,
|
|
51
|
+
convert_to_db_model=_convert_aidol_lead_create_to_db,
|
|
52
|
+
)
|
aidol/repositories/companion.py
CHANGED
|
@@ -10,7 +10,15 @@ from aioia_core.repositories import BaseRepository
|
|
|
10
10
|
from sqlalchemy.orm import Session
|
|
11
11
|
|
|
12
12
|
from aidol.models import DBCompanion
|
|
13
|
-
from aidol.schemas import
|
|
13
|
+
from aidol.schemas import (
|
|
14
|
+
Companion,
|
|
15
|
+
CompanionCreate,
|
|
16
|
+
CompanionStats,
|
|
17
|
+
CompanionUpdate,
|
|
18
|
+
Gender,
|
|
19
|
+
Grade,
|
|
20
|
+
Position,
|
|
21
|
+
)
|
|
14
22
|
|
|
15
23
|
|
|
16
24
|
def _convert_db_companion_to_model(db_companion: DBCompanion) -> Companion:
|
|
@@ -23,20 +31,45 @@ def _convert_db_companion_to_model(db_companion: DBCompanion) -> Companion:
|
|
|
23
31
|
id=db_companion.id,
|
|
24
32
|
aidol_id=db_companion.aidol_id,
|
|
25
33
|
name=db_companion.name,
|
|
34
|
+
gender=Gender(db_companion.gender) if db_companion.gender else None,
|
|
35
|
+
grade=Grade(db_companion.grade) if db_companion.grade else None,
|
|
26
36
|
biography=db_companion.biography,
|
|
27
37
|
profile_picture_url=db_companion.profile_picture_url,
|
|
38
|
+
position=Position(db_companion.position) if db_companion.position else None,
|
|
28
39
|
system_prompt=db_companion.system_prompt,
|
|
40
|
+
mbti_energy=db_companion.mbti_energy,
|
|
41
|
+
mbti_perception=db_companion.mbti_perception,
|
|
42
|
+
mbti_judgment=db_companion.mbti_judgment,
|
|
43
|
+
mbti_lifestyle=db_companion.mbti_lifestyle,
|
|
44
|
+
stats=CompanionStats(
|
|
45
|
+
vocal=db_companion.vocal or 0,
|
|
46
|
+
dance=db_companion.dance or 0,
|
|
47
|
+
rap=db_companion.rap or 0,
|
|
48
|
+
visual=db_companion.visual or 0,
|
|
49
|
+
stamina=db_companion.stamina or 0,
|
|
50
|
+
charm=db_companion.charm or 0,
|
|
51
|
+
),
|
|
29
52
|
created_at=db_companion.created_at.replace(tzinfo=timezone.utc),
|
|
30
53
|
updated_at=db_companion.updated_at.replace(tzinfo=timezone.utc),
|
|
31
54
|
)
|
|
32
55
|
|
|
33
56
|
|
|
34
|
-
def
|
|
35
|
-
|
|
57
|
+
def _convert_companion_schema_to_db(
|
|
58
|
+
schema: CompanionCreate | CompanionUpdate,
|
|
59
|
+
) -> dict:
|
|
60
|
+
"""Convert CompanionCreate/Update schema to DB model data dict.
|
|
36
61
|
|
|
62
|
+
Decomposes nested stats object into individual DB columns.
|
|
37
63
|
Includes system_prompt for AI configuration.
|
|
38
64
|
"""
|
|
39
|
-
|
|
65
|
+
data = schema.model_dump(exclude_unset=True, exclude={"stats"})
|
|
66
|
+
|
|
67
|
+
# Decompose stats into individual columns
|
|
68
|
+
if schema.stats is not None:
|
|
69
|
+
stats_dict = schema.stats.model_dump()
|
|
70
|
+
data.update(stats_dict)
|
|
71
|
+
|
|
72
|
+
return data
|
|
40
73
|
|
|
41
74
|
|
|
42
75
|
class CompanionRepository(
|
|
@@ -53,5 +86,5 @@ class CompanionRepository(
|
|
|
53
86
|
db_session=db_session,
|
|
54
87
|
db_model=DBCompanion,
|
|
55
88
|
convert_to_model=_convert_db_companion_to_model,
|
|
56
|
-
convert_to_db_model=
|
|
89
|
+
convert_to_db_model=_convert_companion_schema_to_db,
|
|
57
90
|
)
|
aidol/schemas/__init__.py
CHANGED
|
@@ -12,12 +12,17 @@ from aidol.schemas.aidol import (
|
|
|
12
12
|
ImageGenerationRequest,
|
|
13
13
|
ImageGenerationResponse,
|
|
14
14
|
)
|
|
15
|
+
from aidol.schemas.aidol_lead import AIdolLead, AIdolLeadBase, AIdolLeadCreate
|
|
15
16
|
from aidol.schemas.companion import (
|
|
16
17
|
Companion,
|
|
17
18
|
CompanionBase,
|
|
18
19
|
CompanionCreate,
|
|
19
20
|
CompanionPublic,
|
|
21
|
+
CompanionStats,
|
|
20
22
|
CompanionUpdate,
|
|
23
|
+
Gender,
|
|
24
|
+
Grade,
|
|
25
|
+
Position,
|
|
21
26
|
)
|
|
22
27
|
|
|
23
28
|
__all__ = [
|
|
@@ -29,9 +34,16 @@ __all__ = [
|
|
|
29
34
|
"ImageGenerationData",
|
|
30
35
|
"ImageGenerationRequest",
|
|
31
36
|
"ImageGenerationResponse",
|
|
37
|
+
"AIdolLead",
|
|
38
|
+
"AIdolLeadBase",
|
|
39
|
+
"AIdolLeadCreate",
|
|
32
40
|
"Companion",
|
|
33
41
|
"CompanionBase",
|
|
34
42
|
"CompanionCreate",
|
|
35
43
|
"CompanionPublic",
|
|
44
|
+
"CompanionStats",
|
|
36
45
|
"CompanionUpdate",
|
|
46
|
+
"Gender",
|
|
47
|
+
"Grade",
|
|
48
|
+
"Position",
|
|
37
49
|
]
|
aidol/schemas/aidol.py
CHANGED
|
@@ -24,20 +24,22 @@ class AIdolBase(BaseModel):
|
|
|
24
24
|
|
|
25
25
|
model_config = ConfigDict(populate_by_name=True, alias_generator=camelize)
|
|
26
26
|
|
|
27
|
-
name: str = Field(
|
|
27
|
+
name: str | None = Field(default=None, description="AIdol group name")
|
|
28
|
+
email: str | None = Field(default=None, description="Creator email")
|
|
29
|
+
greeting: str | None = Field(default=None, description="Greeting message")
|
|
28
30
|
concept: str | None = Field(default=None, description="Group concept or theme")
|
|
29
|
-
profile_image_url: str = Field(
|
|
31
|
+
profile_image_url: str | None = Field(default=None, description="Profile image URL")
|
|
30
32
|
|
|
31
33
|
|
|
32
34
|
class AIdolCreate(AIdolBase):
|
|
33
35
|
"""Schema for creating an AIdol group (no id).
|
|
34
36
|
|
|
35
|
-
claim_token is
|
|
37
|
+
claim_token is required for ownership verification.
|
|
36
38
|
"""
|
|
37
39
|
|
|
38
|
-
claim_token: str
|
|
39
|
-
|
|
40
|
-
description="
|
|
40
|
+
claim_token: str = Field(
|
|
41
|
+
...,
|
|
42
|
+
description="Client-generated UUID for ownership verification",
|
|
41
43
|
)
|
|
42
44
|
|
|
43
45
|
|
|
@@ -47,6 +49,8 @@ class AIdolUpdate(BaseModel):
|
|
|
47
49
|
model_config = ConfigDict(populate_by_name=True, alias_generator=camelize)
|
|
48
50
|
|
|
49
51
|
name: str | None = Field(default=None, description="AIdol group name")
|
|
52
|
+
email: str | None = Field(default=None, description="Creator email")
|
|
53
|
+
greeting: str | None = Field(default=None, description="Greeting message")
|
|
50
54
|
concept: str | None = Field(default=None, description="Group concept or theme")
|
|
51
55
|
profile_image_url: str | None = Field(default=None, description="Profile image URL")
|
|
52
56
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AIdol Lead (viewer email) schemas
|
|
3
|
+
|
|
4
|
+
Schema hierarchy:
|
|
5
|
+
- AIdolLeadBase: Common fields
|
|
6
|
+
- AIdolLeadCreate: For creating a lead (no id)
|
|
7
|
+
- AIdolLead: Response with all fields
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
|
|
12
|
+
from humps import camelize
|
|
13
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AIdolLeadBase(BaseModel):
|
|
17
|
+
"""Base AIdol Lead model with common fields."""
|
|
18
|
+
|
|
19
|
+
model_config = ConfigDict(populate_by_name=True, alias_generator=camelize)
|
|
20
|
+
|
|
21
|
+
aidol_id: str = Field(..., description="AIdol group ID")
|
|
22
|
+
email: str = Field(..., description="Viewer email")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class AIdolLeadCreate(AIdolLeadBase):
|
|
26
|
+
"""Schema for creating an AIdol lead (no id)."""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AIdolLead(AIdolLeadBase):
|
|
30
|
+
"""AIdol Lead response schema with id and timestamps."""
|
|
31
|
+
|
|
32
|
+
model_config = ConfigDict(
|
|
33
|
+
populate_by_name=True, from_attributes=True, alias_generator=camelize
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
id: str = Field(..., description="Lead ID")
|
|
37
|
+
created_at: datetime = Field(..., description="Creation timestamp")
|
|
38
|
+
updated_at: datetime = Field(..., description="Last update timestamp")
|
aidol/schemas/companion.py
CHANGED
|
@@ -2,18 +2,77 @@
|
|
|
2
2
|
Companion (member) schemas
|
|
3
3
|
|
|
4
4
|
Schema hierarchy:
|
|
5
|
+
- CompanionStats: Nested stats object for request/response
|
|
5
6
|
- CompanionBase: Mutable fields (used in Create/Update)
|
|
6
7
|
- CompanionCreate: Base + system_prompt (mutable, but sensitive)
|
|
7
|
-
- CompanionUpdate:
|
|
8
|
+
- CompanionUpdate: All fields optional for partial updates
|
|
8
9
|
- Companion: Response with all fields including system_prompt (internal use)
|
|
9
10
|
- CompanionPublic: Response without sensitive fields (API use)
|
|
10
11
|
"""
|
|
11
12
|
|
|
12
13
|
from datetime import datetime
|
|
14
|
+
from enum import Enum
|
|
13
15
|
|
|
14
16
|
from humps import camelize
|
|
15
17
|
from pydantic import BaseModel, ConfigDict, Field
|
|
16
18
|
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
# Enums
|
|
21
|
+
# ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Gender(str, Enum):
|
|
25
|
+
"""Gender options for companions."""
|
|
26
|
+
|
|
27
|
+
MALE = "male"
|
|
28
|
+
FEMALE = "female"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Grade(str, Enum):
|
|
32
|
+
"""Grade levels for companions."""
|
|
33
|
+
|
|
34
|
+
A = "A"
|
|
35
|
+
B = "B"
|
|
36
|
+
C = "C"
|
|
37
|
+
F = "F"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Position(str, Enum):
|
|
41
|
+
"""Position roles in the group."""
|
|
42
|
+
|
|
43
|
+
LEADER = "leader"
|
|
44
|
+
MAIN_VOCAL = "mainVocal"
|
|
45
|
+
SUB_VOCAL = "subVocal"
|
|
46
|
+
MAIN_DANCER = "mainDancer"
|
|
47
|
+
SUB_DANCER = "subDancer"
|
|
48
|
+
MAIN_RAPPER = "mainRapper"
|
|
49
|
+
SUB_RAPPER = "subRapper"
|
|
50
|
+
VISUAL = "visual"
|
|
51
|
+
MAKNAE = "maknae"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# ---------------------------------------------------------------------------
|
|
55
|
+
# Nested Objects
|
|
56
|
+
# ---------------------------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class CompanionStats(BaseModel):
|
|
60
|
+
"""Nested stats object for API request/response."""
|
|
61
|
+
|
|
62
|
+
model_config = ConfigDict(populate_by_name=True, alias_generator=camelize)
|
|
63
|
+
|
|
64
|
+
vocal: int = Field(default=0, ge=0, le=100, description="Vocal skill")
|
|
65
|
+
dance: int = Field(default=0, ge=0, le=100, description="Dance skill")
|
|
66
|
+
rap: int = Field(default=0, ge=0, le=100, description="Rap skill")
|
|
67
|
+
visual: int = Field(default=0, ge=0, le=100, description="Visual score")
|
|
68
|
+
stamina: int = Field(default=0, ge=0, le=100, description="Stamina")
|
|
69
|
+
charm: int = Field(default=0, ge=0, le=100, description="Charm score")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# ---------------------------------------------------------------------------
|
|
73
|
+
# Request Schemas
|
|
74
|
+
# ---------------------------------------------------------------------------
|
|
75
|
+
|
|
17
76
|
|
|
18
77
|
class CompanionBase(BaseModel):
|
|
19
78
|
"""Base companion model with common mutable fields.
|
|
@@ -25,11 +84,31 @@ class CompanionBase(BaseModel):
|
|
|
25
84
|
model_config = ConfigDict(populate_by_name=True, alias_generator=camelize)
|
|
26
85
|
|
|
27
86
|
aidol_id: str | None = Field(default=None, description="AIdol group ID")
|
|
28
|
-
name: str = Field(
|
|
87
|
+
name: str | None = Field(default=None, description="Companion name")
|
|
88
|
+
gender: Gender | None = Field(default=None, description="Gender")
|
|
89
|
+
grade: Grade | None = Field(default=None, description="Grade level")
|
|
29
90
|
biography: str | None = Field(default=None, description="Companion biography")
|
|
30
91
|
profile_picture_url: str | None = Field(
|
|
31
92
|
default=None, description="Profile picture URL"
|
|
32
93
|
)
|
|
94
|
+
position: Position | None = Field(default=None, description="Position in group")
|
|
95
|
+
|
|
96
|
+
# MBTI scores (1-10)
|
|
97
|
+
mbti_energy: int | None = Field(default=None, ge=1, le=10, description="E↔I (1-10)")
|
|
98
|
+
mbti_perception: int | None = Field(
|
|
99
|
+
default=None, ge=1, le=10, description="S↔N (1-10)"
|
|
100
|
+
)
|
|
101
|
+
mbti_judgment: int | None = Field(
|
|
102
|
+
default=None, ge=1, le=10, description="T↔F (1-10)"
|
|
103
|
+
)
|
|
104
|
+
mbti_lifestyle: int | None = Field(
|
|
105
|
+
default=None, ge=1, le=10, description="J↔P (1-10)"
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Stats (nested object)
|
|
109
|
+
stats: CompanionStats = Field(
|
|
110
|
+
default_factory=CompanionStats, description="Ability stats"
|
|
111
|
+
)
|
|
33
112
|
|
|
34
113
|
|
|
35
114
|
class CompanionCreate(CompanionBase):
|
|
@@ -50,14 +129,37 @@ class CompanionUpdate(BaseModel):
|
|
|
50
129
|
|
|
51
130
|
aidol_id: str | None = Field(default=None, description="AIdol group ID")
|
|
52
131
|
name: str | None = Field(default=None, description="Companion name")
|
|
132
|
+
gender: Gender | None = Field(default=None, description="Gender")
|
|
133
|
+
grade: Grade | None = Field(default=None, description="Grade level")
|
|
53
134
|
biography: str | None = Field(default=None, description="Companion biography")
|
|
54
135
|
profile_picture_url: str | None = Field(
|
|
55
136
|
default=None, description="Profile picture URL"
|
|
56
137
|
)
|
|
138
|
+
position: Position | None = Field(default=None, description="Position in group")
|
|
57
139
|
system_prompt: str | None = Field(
|
|
58
140
|
default=None, description="AI system prompt (not exposed in responses)"
|
|
59
141
|
)
|
|
60
142
|
|
|
143
|
+
# MBTI scores (1-10)
|
|
144
|
+
mbti_energy: int | None = Field(default=None, ge=1, le=10, description="E↔I (1-10)")
|
|
145
|
+
mbti_perception: int | None = Field(
|
|
146
|
+
default=None, ge=1, le=10, description="S↔N (1-10)"
|
|
147
|
+
)
|
|
148
|
+
mbti_judgment: int | None = Field(
|
|
149
|
+
default=None, ge=1, le=10, description="T↔F (1-10)"
|
|
150
|
+
)
|
|
151
|
+
mbti_lifestyle: int | None = Field(
|
|
152
|
+
default=None, ge=1, le=10, description="J↔P (1-10)"
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Stats (nested object, optional for updates)
|
|
156
|
+
stats: CompanionStats | None = Field(default=None, description="Ability stats")
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# ---------------------------------------------------------------------------
|
|
160
|
+
# Response Schemas
|
|
161
|
+
# ---------------------------------------------------------------------------
|
|
162
|
+
|
|
61
163
|
|
|
62
164
|
class Companion(CompanionBase):
|
|
63
165
|
"""Companion response schema with id and timestamps.
|
|
@@ -78,10 +180,12 @@ class Companion(CompanionBase):
|
|
|
78
180
|
updated_at: datetime = Field(..., description="Last update timestamp")
|
|
79
181
|
|
|
80
182
|
|
|
81
|
-
class CompanionPublic(
|
|
82
|
-
"""Public companion response schema
|
|
183
|
+
class CompanionPublic(BaseModel):
|
|
184
|
+
"""Public companion response schema for frontend.
|
|
83
185
|
|
|
84
|
-
Excludes system_prompt for
|
|
186
|
+
- Excludes system_prompt for security
|
|
187
|
+
- Uses nested stats object
|
|
188
|
+
- Includes calculated mbti string
|
|
85
189
|
"""
|
|
86
190
|
|
|
87
191
|
model_config = ConfigDict(
|
|
@@ -89,5 +193,18 @@ class CompanionPublic(CompanionBase):
|
|
|
89
193
|
)
|
|
90
194
|
|
|
91
195
|
id: str = Field(..., description="Companion ID")
|
|
196
|
+
aidol_id: str | None = Field(default=None, description="AIdol group ID")
|
|
197
|
+
name: str | None = Field(default=None, description="Companion name")
|
|
198
|
+
gender: Gender | None = Field(default=None, description="Gender")
|
|
199
|
+
grade: Grade | None = Field(default=None, description="Grade level")
|
|
200
|
+
biography: str | None = Field(default=None, description="Companion biography")
|
|
201
|
+
profile_picture_url: str | None = Field(
|
|
202
|
+
default=None, description="Profile picture URL"
|
|
203
|
+
)
|
|
204
|
+
position: Position | None = Field(default=None, description="Position in group")
|
|
205
|
+
mbti: str | None = Field(default=None, description="Calculated MBTI (e.g., ENFP)")
|
|
206
|
+
stats: CompanionStats = Field(
|
|
207
|
+
default_factory=CompanionStats, description="Ability stats"
|
|
208
|
+
)
|
|
92
209
|
created_at: datetime = Field(..., description="Creation timestamp")
|
|
93
210
|
updated_at: datetime = Field(..., description="Last update timestamp")
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
aidol/__init__.py,sha256=iMN-aij1k6vElJt0sZQT4QYJjvoD27Q9vtZkQA0TY9c,141
|
|
2
|
+
aidol/api/__init__.py,sha256=skD_w82nT0v1hdKK9BBOycNERexIr8F1BmSmSono4Jk,276
|
|
3
|
+
aidol/api/aidol.py,sha256=DQzwF41bnfw8JpcrZlV3XDkvuH5AszyYCJwOmcRxTKg,6684
|
|
4
|
+
aidol/api/companion.py,sha256=QBsPgSjBp1USunB6Jth6fdWLwBzsI6KIq6XQZu9OifQ,6287
|
|
5
|
+
aidol/factories.py,sha256=HYkJN9qu1fZOgLW6hk3t0Ixh41mVB4tzzmOQQcso9tA,698
|
|
6
|
+
aidol/models/__init__.py,sha256=AljQMgSE9vHx203NFQZMknKpzHIfyFLLcOMnFpMOLAs,218
|
|
7
|
+
aidol/models/aidol.py,sha256=By82BqiAasLNy8ZCNON2m46BnSCfL2J_ZFLO6_MMFO0,903
|
|
8
|
+
aidol/models/aidol_lead.py,sha256=xCa1AqJdBBeW2Edcj1pK-cXbX5oatxzCOkPyqEGBXVw,619
|
|
9
|
+
aidol/models/companion.py,sha256=fom58GXjGvAxxndS4X4MrT1HWNw8Ps99BNEyPd5JhW0,1974
|
|
10
|
+
aidol/protocols.py,sha256=Zc9LWUcdHJlerI649v3maXbgXARiXrBiRd2cxNLnSDE,2667
|
|
11
|
+
aidol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
aidol/repositories/__init__.py,sha256=4kE68a-eRhXt9z5a2XCn1_2s-p3VMpQIdL3oRDb1Ns0,296
|
|
13
|
+
aidol/repositories/aidol.py,sha256=-hf7WW_sDx4vE9bHzKQnzfkgu-on7sqOem9gFO8x0EE,1810
|
|
14
|
+
aidol/repositories/aidol_lead.py,sha256=g15VJwOI-w_a1fe0OzSUUC0zdfqKSR2JHqywdcOvTfU,1516
|
|
15
|
+
aidol/repositories/companion.py,sha256=dUkJA0me2kmxqk3B4L0w4ENcHeAQFw5ki6RvZ5eLHDg,2877
|
|
16
|
+
aidol/schemas/__init__.py,sha256=sNurP-s24PgS4ZJ7xusZ7Z7wXtl1rdsnAxxdeubRXHE,923
|
|
17
|
+
aidol/schemas/aidol.py,sha256=wOfHaLu4I56elLLj6A3CGriPZE4Pz4fFAyC3emtvaCE,4135
|
|
18
|
+
aidol/schemas/aidol_lead.py,sha256=JS8U-ep0Ga6x0PdwXhJfTrcOCKgG0wfFW8pN5X35GUM,1070
|
|
19
|
+
aidol/schemas/companion.py,sha256=I4hi4LT-S9AC7lqt1jyYfd0vSqYmxYNm2k9EsZdyNyM,7584
|
|
20
|
+
aidol/services/__init__.py,sha256=3vdT_CtUfeDWbsPn7Xnp41sajovcl2nCvpZ8KNFPHYM,144
|
|
21
|
+
aidol/services/image_generation_service.py,sha256=naqOxe5jsSTs9__Nj3gwBtOQPkfWvgqVV4z6XkA6DGM,4359
|
|
22
|
+
py_aidol-0.2.0.dist-info/METADATA,sha256=oVVlTXIUXp2BPT61cQnQLav5lozJwul0H0SOOWJdrpc,2880
|
|
23
|
+
py_aidol-0.2.0.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
|
|
24
|
+
py_aidol-0.2.0.dist-info/RECORD,,
|
py_aidol-0.1.0.dist-info/RECORD
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
aidol/__init__.py,sha256=iMN-aij1k6vElJt0sZQT4QYJjvoD27Q9vtZkQA0TY9c,141
|
|
2
|
-
aidol/api/__init__.py,sha256=skD_w82nT0v1hdKK9BBOycNERexIr8F1BmSmSono4Jk,276
|
|
3
|
-
aidol/api/aidol.py,sha256=DQzwF41bnfw8JpcrZlV3XDkvuH5AszyYCJwOmcRxTKg,6684
|
|
4
|
-
aidol/api/companion.py,sha256=QBsPgSjBp1USunB6Jth6fdWLwBzsI6KIq6XQZu9OifQ,6287
|
|
5
|
-
aidol/factories.py,sha256=HYkJN9qu1fZOgLW6hk3t0Ixh41mVB4tzzmOQQcso9tA,698
|
|
6
|
-
aidol/models/__init__.py,sha256=nlmLezsKx1xGdJkKANkOj3QCZQVPniXkYwQBsj8Ockk,155
|
|
7
|
-
aidol/models/aidol.py,sha256=0t1OJiJBnmhpRCYczmsr1aYD8pMZqE3wKaUWIQiymKM,750
|
|
8
|
-
aidol/models/companion.py,sha256=F64BejN3ZWP4EyNDBiV0s63dofsAgMVZJi55JV0b5gk,954
|
|
9
|
-
aidol/protocols.py,sha256=Zc9LWUcdHJlerI649v3maXbgXARiXrBiRd2cxNLnSDE,2667
|
|
10
|
-
aidol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
aidol/repositories/__init__.py,sha256=hJbn-Pw0iGMMIYkUbEqLOy-gK_0LqCJLBba21pmZ0Pw,207
|
|
12
|
-
aidol/repositories/aidol.py,sha256=zwgXB823EZsrYYoJn2S05VD1bcuhSlcwnlVCJoD09p0,1744
|
|
13
|
-
aidol/repositories/companion.py,sha256=xzAHrdCexT4cXFPTg3yCmWoqou8edeZO0A22ozMieFg,1775
|
|
14
|
-
aidol/schemas/__init__.py,sha256=dakC_xvl4akjGRSOJdFnB1k6_RbNplGnPzEwI_7wwKA,661
|
|
15
|
-
aidol/schemas/aidol.py,sha256=aTS7hx4BGUvLDMgqo3CGVY_867GO0vnAeJhRFntGG1g,3834
|
|
16
|
-
aidol/schemas/companion.py,sha256=SCjvNETAZII256o0myCp6q1wzp999JIO99q8cKf8Yo0,3224
|
|
17
|
-
aidol/services/__init__.py,sha256=3vdT_CtUfeDWbsPn7Xnp41sajovcl2nCvpZ8KNFPHYM,144
|
|
18
|
-
aidol/services/image_generation_service.py,sha256=naqOxe5jsSTs9__Nj3gwBtOQPkfWvgqVV4z6XkA6DGM,4359
|
|
19
|
-
py_aidol-0.1.0.dist-info/METADATA,sha256=_c0y1xNNGOGHmKIeSfvCqWmYLPuGfDypFHg7jn8uVoM,2880
|
|
20
|
-
py_aidol-0.1.0.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
|
|
21
|
-
py_aidol-0.1.0.dist-info/RECORD,,
|
|
File without changes
|