py-aidol 0.3.0__py3-none-any.whl → 0.5.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.
@@ -1,7 +1,7 @@
1
1
  """
2
- Image generation service for AIdol
2
+ Image generation service for AIdol.
3
3
 
4
- Generates images using OpenAI DALL-E 3 for AIdol emblems and Companion profiles.
4
+ Generates images using Google Gemini for AIdol emblems and Companion profiles.
5
5
  """
6
6
 
7
7
  from __future__ import annotations
@@ -15,6 +15,8 @@ import PIL.Image
15
15
  from google import genai
16
16
  from google.genai import errors as genai_errors
17
17
 
18
+ from aidol.settings import GoogleGenAISettings
19
+
18
20
  logger = logging.getLogger(__name__)
19
21
 
20
22
 
@@ -31,23 +33,33 @@ class ImageGenerationService:
31
33
 
32
34
  client: "genai.Client | None" = None
33
35
 
34
- def __init__(self, api_key: str | None = None, settings=None):
36
+ def __init__(self, settings: GoogleGenAISettings | None = None):
35
37
  """
36
38
  Initialize the Image Generation service.
37
39
 
40
+ Supports two authentication methods:
41
+ 1. Google AI API: settings.api_key
42
+ 2. Vertex AI API (ADC): settings.cloud_project (location=global hardcoded)
43
+
38
44
  Args:
39
- api_key: Google API Key.
40
- settings: Unused, kept for compatibility.
45
+ settings: GoogleGenAISettings for configuration.
41
46
  """
42
-
43
- # Use explicitly provided api_key, otherwise fallback to settings or env
44
- if api_key:
45
- self.client = genai.Client(api_key=api_key)
46
- elif settings and hasattr(settings, "api_key") and settings.api_key:
47
+ # Priority 1: Settings with api_key (Google AI API)
48
+ if settings and settings.api_key:
47
49
  self.client = genai.Client(api_key=settings.api_key)
50
+ # Priority 2: Settings with cloud_project (Vertex AI, location=global)
51
+ elif settings and settings.cloud_project:
52
+ self.client = genai.Client(
53
+ vertexai=True,
54
+ project=settings.cloud_project,
55
+ location="global",
56
+ )
48
57
  else:
49
- # Try loading from GOOGLE_API_KEY environment variable (Client handles this)
50
- self.client = genai.Client()
58
+ logger.error(
59
+ "No authentication configured. "
60
+ "Set GOOGLE_API_KEY or GOOGLE_CLOUD_PROJECT"
61
+ )
62
+ self.client = None
51
63
 
52
64
  def generate_and_download_image(
53
65
  self,
@@ -0,0 +1,63 @@
1
+ """Response generation service for TEXT responses.
2
+
3
+ Service layer for generating LLM responses.
4
+ Integrators can extend for AUDIO/VIDEO response types.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from langchain_core.messages import BaseMessage, SystemMessage
10
+
11
+ from aidol.providers.llm import LLMProvider
12
+ from aidol.schemas import ModelSettings
13
+
14
+
15
+ class ResponseGenerationService:
16
+ """Response generation service for TEXT responses.
17
+
18
+ Basic implementation for text-only response generation.
19
+ Integrators can extend for additional response types (AUDIO/VIDEO).
20
+
21
+ Responsibilities:
22
+ - Provide response format prompts (empty for TEXT)
23
+ - Generate response from prepared context
24
+ """
25
+
26
+ def __init__(
27
+ self,
28
+ provider: LLMProvider,
29
+ model_settings: ModelSettings,
30
+ ) -> None:
31
+ """Initialize ResponseGenerationService.
32
+
33
+ Args:
34
+ provider: LLMProvider for LLM calls.
35
+ model_settings: Model configuration (model name, temperature, etc.)
36
+ """
37
+ self.provider = provider
38
+ self.model_settings = model_settings
39
+
40
+ def get_response_format_prompts(self) -> list[SystemMessage]:
41
+ """Get response format prompts for TEXT responses.
42
+
43
+ This method encapsulates the responsibility of creating format-specific prompts,
44
+ ensuring that prompt configuration remains within the service layer.
45
+
46
+ TEXT responses don't require additional format prompts.
47
+ Integrators can override for AUDIO/VIDEO response types.
48
+
49
+ Returns:
50
+ Empty list for TEXT responses.
51
+ """
52
+ return []
53
+
54
+ def generate_response(self, context: list[BaseMessage]) -> str:
55
+ """Generate response from prepared context.
56
+
57
+ Args:
58
+ context: Prepared context from ContextService.
59
+
60
+ Returns:
61
+ Generated text response.
62
+ """
63
+ return self.provider.completion(self.model_settings, context)
aidol/settings.py ADDED
@@ -0,0 +1,46 @@
1
+ """
2
+ Environment settings for aidol module.
3
+
4
+ Provides GoogleGenAISettings for image generation with Google Gemini.
5
+ """
6
+
7
+ from pydantic_settings import BaseSettings
8
+
9
+
10
+ class Settings(BaseSettings):
11
+ """Environment-based settings for aidol module."""
12
+
13
+ openai_model: str = "gpt-4o-mini"
14
+
15
+ class Config:
16
+ env_prefix = "AIDOL_"
17
+
18
+
19
+ class GoogleGenAISettings(BaseSettings):
20
+ """
21
+ Google Gen AI SDK settings for Gemini image generation.
22
+
23
+ Supports two authentication methods:
24
+ 1. Google AI API: GOOGLE_API_KEY
25
+ 2. Vertex AI API (ADC): GOOGLE_CLOUD_PROJECT
26
+
27
+ For Google AI API:
28
+ export GOOGLE_API_KEY=your-api-key
29
+
30
+ For Vertex AI with ADC:
31
+ export GOOGLE_CLOUD_PROJECT=your-project-id
32
+ gcloud auth application-default login
33
+
34
+ Note: Vertex AI uses location="global" (hardcoded) because
35
+ Gemini image generation models only support the global endpoint.
36
+
37
+ Environment variables:
38
+ GOOGLE_API_KEY: Google API key (optional)
39
+ GOOGLE_CLOUD_PROJECT: GCP project ID for Vertex AI (optional)
40
+ """
41
+
42
+ api_key: str | None = None
43
+ cloud_project: str | None = None
44
+
45
+ class Config:
46
+ env_prefix = "GOOGLE_"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py-aidol
3
- Version: 0.3.0
3
+ Version: 0.5.0
4
4
  Summary: Create and chat with your own AI idol group
5
5
  License: Apache-2.0
6
6
  Keywords: kpop,idol,aidol,ai-companion,chatbot,image-generation
@@ -16,6 +16,9 @@ Requires-Dist: aioia-core (>=2.2.0,<3.0.0)
16
16
  Requires-Dist: fastapi (>=0.115.12,<0.116.0)
17
17
  Requires-Dist: google-genai (>=1.60.0,<2.0.0)
18
18
  Requires-Dist: httpx (>=0.28.1,<0.29.0)
19
+ Requires-Dist: langchain-core (>=0.3.0)
20
+ Requires-Dist: langchain-openai (>=0.3.0)
21
+ Requires-Dist: litellm (>=1.60.0)
19
22
  Requires-Dist: openai (>=1.0.0)
20
23
  Requires-Dist: pillow (>=10.0.0,<11.0.0)
21
24
  Requires-Dist: psycopg2-binary (>=2.9.9,<3.0.0)
@@ -34,7 +37,7 @@ AI 아이돌 그룹 생성 및 채팅 Python 패키지
34
37
  ## 주요 기능
35
38
 
36
39
  - AI 아이돌 그룹/멤버 CRUD
37
- - DALL-E 3 이미지 생성 (엠블럼, 프로필)
40
+ - Google Gemini 이미지 생성 (엠블럼, 프로필)
38
41
  - 텍스트 채팅 (페르소나 기반 응답)
39
42
  - Buppy 통합 Adapter 패턴
40
43
 
@@ -62,7 +65,7 @@ from aidol.factories import AIdolRepositoryFactory, CompanionRepositoryFactory
62
65
  # AIdol 라우터
63
66
  aidol_router = AIdolRouter(
64
67
  repository_factory=AIdolRepositoryFactory(),
65
- openai_settings=openai_settings,
68
+ google_settings=google_settings,
66
69
  image_storage=image_storage,
67
70
  )
68
71
 
@@ -87,11 +90,27 @@ make format
87
90
 
88
91
  ## 환경 변수
89
92
 
90
- ### 필수 (이미지 생성 )
93
+ ### 이미지 생성 인증 (선택, ADC 지원)
91
94
 
92
95
  | 변수 | 설명 |
93
96
  |------|------|
94
- | `OPENAI_API_KEY` | OpenAI API 키 |
97
+ | `GOOGLE_API_KEY` | Google API 키 (Google AI API) |
98
+ | `GOOGLE_CLOUD_PROJECT` | GCP 프로젝트 ID (Vertex AI) |
99
+
100
+ **인증 방법:**
101
+
102
+ **Option 1: Google AI API (API Key)**
103
+ ```bash
104
+ export GOOGLE_API_KEY=your-api-key
105
+ ```
106
+
107
+ **Option 2: Vertex AI (ADC)**
108
+ ```bash
109
+ export GOOGLE_CLOUD_PROJECT=your-project-id
110
+ gcloud auth application-default login # 로컬 개발
111
+ ```
112
+
113
+ > **참고**: Vertex AI 사용 시 `location=global`이 하드코딩되어 있습니다 (Gemini 이미지 생성 모델 요구사항).
95
114
 
96
115
  ### 선택
97
116
 
@@ -106,7 +125,8 @@ make format
106
125
 
107
126
  - aioia-core (공통 인프라)
108
127
  - FastAPI, SQLAlchemy, Pydantic
109
- - OpenAI (이미지 생성, 채팅)
128
+ - Google Generative AI (이미지 생성)
129
+ - OpenAI (채팅)
110
130
  - Pillow (이미지 처리)
111
131
 
112
132
  ## 라이선스
@@ -0,0 +1,41 @@
1
+ aidol/__init__.py,sha256=iMN-aij1k6vElJt0sZQT4QYJjvoD27Q9vtZkQA0TY9c,141
2
+ aidol/api/__init__.py,sha256=JWcwxYJ32_qzD_86_FR9wUAfSQMT6G2lqDtssrPJPj4,398
3
+ aidol/api/aidol.py,sha256=AIpDMTTOxht1eEVk4YITvmJzvklpYlDTpQVrIuSjeUw,6588
4
+ aidol/api/chatroom.py,sha256=wQ-NhjUqR_9BkNMBzwQlwc-_jse6GhqssC3zminWL4E,12154
5
+ aidol/api/common.py,sha256=w8ERo96t9tat4HPs1qw9JhyoJ8cj5crHCe92Hp3Usug,2198
6
+ aidol/api/companion.py,sha256=BgOXub9-0Zncht7xMxvbLzJgOTmh-Ef23_TdU_tr5BE,11080
7
+ aidol/api/lead.py,sha256=RSf3GcIUVJu752rU9HG7Wy22UmnrRZnN_NGWkpTRDfE,3921
8
+ aidol/context/__init__.py,sha256=b_DP8Qlmiv2jhKVSE61XQUAcIujwbtob435pjkeVHAM,722
9
+ aidol/context/builder.py,sha256=XLKaj-buUNTyp9ucslGDshZ8TyTQ5xK7vACjtkV7x7o,12252
10
+ aidol/factories.py,sha256=t7g0GJYHvY57J9mZUY2vX8HSqOFclWChaPOw8Ohyw8U,1261
11
+ aidol/models/__init__.py,sha256=Y7DOy85izcXy5dwuXlYy0xxMV1r5ZjZbDH5Tmp8Hsr0,301
12
+ aidol/models/aidol.py,sha256=By82BqiAasLNy8ZCNON2m46BnSCfL2J_ZFLO6_MMFO0,903
13
+ aidol/models/aidol_lead.py,sha256=xCa1AqJdBBeW2Edcj1pK-cXbX5oatxzCOkPyqEGBXVw,619
14
+ aidol/models/chatroom.py,sha256=R_u0GFmVO_qhHYuvDIuRK47hHuPOvXopMbAF2Qn4F9k,1587
15
+ aidol/models/companion.py,sha256=fom58GXjGvAxxndS4X4MrT1HWNw8Ps99BNEyPd5JhW0,1974
16
+ aidol/protocols.py,sha256=ZuaRNfIEHwfgGkMcFYhPX5so8No2SQx_jBfN9kOJC9k,5286
17
+ aidol/providers/__init__.py,sha256=BJK--YO-_t4uxUd5-l3_icd1ZbyPwKv_Ykal_tpXs8w,292
18
+ aidol/providers/llm/__init__.py,sha256=IsgUx2tdmd481yHQI3cEmPSrVMcYPekAtBpIsqI6hC8,342
19
+ aidol/providers/llm/base.py,sha256=qsIjyZq0ohy9nCj8_nownvK_w-d4NPnjG7mzqwboaao,5029
20
+ aidol/providers/llm/openai.py,sha256=ZktcVpvZlBTqlifoJV9chqRY4lW2hMkZv4IM-jLnu18,3467
21
+ aidol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ aidol/repositories/__init__.py,sha256=3I81EjKHML8TdouGCibnWjnSQOHNSYHPy7KXVcyO7zw,381
23
+ aidol/repositories/aidol.py,sha256=-hf7WW_sDx4vE9bHzKQnzfkgu-on7sqOem9gFO8x0EE,1810
24
+ aidol/repositories/aidol_lead.py,sha256=vmCHXdTtxDSiRpd_n7DuyecZDPLls56r0N5vyT_v9zI,1488
25
+ aidol/repositories/chatroom.py,sha256=sKhKNn5-A9bEUvNT1qpNccRPlRTjEbOu0FZ3677sn3g,4479
26
+ aidol/repositories/companion.py,sha256=dUkJA0me2kmxqk3B4L0w4ENcHeAQFw5ki6RvZ5eLHDg,2877
27
+ aidol/schemas/__init__.py,sha256=L-2wyp7Kdw0qM3p1-8vdeRJnqvsDPBomaotK1_jI8wY,1663
28
+ aidol/schemas/aidol.py,sha256=wOfHaLu4I56elLLj6A3CGriPZE4Pz4fFAyC3emtvaCE,4135
29
+ aidol/schemas/aidol_lead.py,sha256=JS8U-ep0Ga6x0PdwXhJfTrcOCKgG0wfFW8pN5X35GUM,1070
30
+ aidol/schemas/chatroom.py,sha256=2jD-rlHGjq5mxH4SB9K2dp_FYfKG9WlH9ON_z5D13TM,4370
31
+ aidol/schemas/companion.py,sha256=I4hi4LT-S9AC7lqt1jyYfd0vSqYmxYNm2k9EsZdyNyM,7584
32
+ aidol/schemas/model_settings.py,sha256=GqvBLWsWOQAUGMEE76LGQdGp_K-fPhKfPaYhXRUr2dc,1033
33
+ aidol/schemas/persona.py,sha256=6T3Dg8QKndsNl4XzMTWxzEhEvtEmtf_F6q-33L9rUro,550
34
+ aidol/services/__init__.py,sha256=Jar-Gzep5mS4-dPizee4uiSDZAM8Q7SCchyYPu-U2mI,258
35
+ aidol/services/companion_service.py,sha256=tNNWiIFmJQ-I3UBW06baOANXhBx5oTKoT6nkqfnDisA,2490
36
+ aidol/services/image_generation_service.py,sha256=zDs9HP_JckHFJJZUIo2ADSsHGppat-8V-ttu8DlN-BU,3862
37
+ aidol/services/response_generation_service.py,sha256=S5Xt-uVbYRc-qH_xHJkb-2xhKWm96DtWvCM8lIUGmi0,1942
38
+ aidol/settings.py,sha256=mi8JN6C88Fv0vgRsnyupJVw6Wy_aFMxEkq635yar1_I,1178
39
+ py_aidol-0.5.0.dist-info/METADATA,sha256=Qbj7C54L-30dqnRTgEn2oL7ZyA1w2avr4q6YhT85U-4,3547
40
+ py_aidol-0.5.0.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
41
+ py_aidol-0.5.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.3.0
2
+ Generator: poetry-core 2.3.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,27 +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=8fRkYq6-pEVKpQWbamv45IT2-b9FIgilSoPWg3itiK0,6486
4
- aidol/api/common.py,sha256=R_2RjV_XjAI5TuTSXNbYEjE-wY3wC_hP2Bww0z2g5ZA,2094
5
- aidol/api/companion.py,sha256=XVZum54ueskJgcaAA2Z_Z6xa3Zpy0CGrl3MIQIga-kY,10738
6
- aidol/api/lead.py,sha256=RSf3GcIUVJu752rU9HG7Wy22UmnrRZnN_NGWkpTRDfE,3921
7
- aidol/factories.py,sha256=5VhEbUVQEo-WruOdDauOi9xGgMxrgT339glocC1ua4o,983
8
- aidol/models/__init__.py,sha256=AljQMgSE9vHx203NFQZMknKpzHIfyFLLcOMnFpMOLAs,218
9
- aidol/models/aidol.py,sha256=By82BqiAasLNy8ZCNON2m46BnSCfL2J_ZFLO6_MMFO0,903
10
- aidol/models/aidol_lead.py,sha256=xCa1AqJdBBeW2Edcj1pK-cXbX5oatxzCOkPyqEGBXVw,619
11
- aidol/models/companion.py,sha256=fom58GXjGvAxxndS4X4MrT1HWNw8Ps99BNEyPd5JhW0,1974
12
- aidol/protocols.py,sha256=8-7iwbtMv5vQUAYGRbbKvm6YfYZZ1VZz6dufse_DYp4,3375
13
- aidol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- aidol/repositories/__init__.py,sha256=4kE68a-eRhXt9z5a2XCn1_2s-p3VMpQIdL3oRDb1Ns0,296
15
- aidol/repositories/aidol.py,sha256=-hf7WW_sDx4vE9bHzKQnzfkgu-on7sqOem9gFO8x0EE,1810
16
- aidol/repositories/aidol_lead.py,sha256=vmCHXdTtxDSiRpd_n7DuyecZDPLls56r0N5vyT_v9zI,1488
17
- aidol/repositories/companion.py,sha256=dUkJA0me2kmxqk3B4L0w4ENcHeAQFw5ki6RvZ5eLHDg,2877
18
- aidol/schemas/__init__.py,sha256=sNurP-s24PgS4ZJ7xusZ7Z7wXtl1rdsnAxxdeubRXHE,923
19
- aidol/schemas/aidol.py,sha256=wOfHaLu4I56elLLj6A3CGriPZE4Pz4fFAyC3emtvaCE,4135
20
- aidol/schemas/aidol_lead.py,sha256=JS8U-ep0Ga6x0PdwXhJfTrcOCKgG0wfFW8pN5X35GUM,1070
21
- aidol/schemas/companion.py,sha256=I4hi4LT-S9AC7lqt1jyYfd0vSqYmxYNm2k9EsZdyNyM,7584
22
- aidol/services/__init__.py,sha256=3vdT_CtUfeDWbsPn7Xnp41sajovcl2nCvpZ8KNFPHYM,144
23
- aidol/services/companion_service.py,sha256=tNNWiIFmJQ-I3UBW06baOANXhBx5oTKoT6nkqfnDisA,2490
24
- aidol/services/image_generation_service.py,sha256=fq4ua1sO4xT4BK0b-Db2u_G0lbXElbO63MFZfstOlWY,3456
25
- py_aidol-0.3.0.dist-info/METADATA,sha256=xuQO_y10IvUUZe4Z-VcQkOnQ9ICHjVtSY5iVE5A0oTE,2926
26
- py_aidol-0.3.0.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
27
- py_aidol-0.3.0.dist-info/RECORD,,