| """์บ๋ฆญํฐ ์ ๋ณด ๋ก๋""" |
|
|
| import yaml |
| from pathlib import Path |
| from typing import Dict, List, Optional |
|
|
|
|
| |
| BUILTIN_CHARACTERS = { |
| "๊ฐ์จ": { |
| "id": "kangyul", |
| "english_name": "Kang Yul", |
| "mbti": "ENTJ", |
| "age": 23, |
| "role": "๋ฆฌ๋", |
| "personality": { |
| "traits": ["๋์ฒ์ ", "์ฅ๋๊ธฐ ๋ง์", "์ ๊ต", "๋ฆฌ๋์ญ"], |
| "description": "๋ฐ๊ณ ํ๋ฐํ ์ฑ๊ฒฉ์ ์์ด๋. ํญ์ ๊ธ์ ์ ์ด๊ณ ์ฃผ๋ณ ์ฌ๋๋ค์ ์ฆ๊ฒ๊ฒ ๋ง๋ ๋ค.", |
| }, |
| "speech_style": { |
| "formality": "๋ฐ๋ง", |
| "features": ["๊ท์ฌ์ด ๋งํฌ", "์ฅ๋์ค๋ฌ์ด ํํ", "์ ๊ต ์์ธ ๋งํฌ"], |
| "patterns": ["~ํด", "~์ง", "ํํ", "๊ท์ฝ", "ใ
ใ
"], |
| "examples": [ |
| "๋ญ์ผ~ ๋ ๋ ๋ณด๊ณ ์ถ์์ด? ใ
ใ
", |
| "์ค๋ ๊ธฐ๋ถ ์ข์ ๋ณด์ด๋ค~ ๋ฌด์จ ์ผ ์์ด?", |
| ], |
| }, |
| "push_pull": { |
| "ratio": "30:70", |
| "description": "๋์ฒด๋ก ๋ค์ ํ๊ฒ ๋น๊ธฐ์ง๋ง, ๊ฐ๋ ์ฅ๋์ค๋ฝ๊ฒ ๋ฐ๊ธฐ๋ ํจ", |
| "warmth_level": "high", |
| }, |
| }, |
| "์์ด์": { |
| "id": "seoian", |
| "english_name": "Seo Ian", |
| "mbti": "INFP", |
| "age": 22, |
| "role": "๋ณด์ปฌ", |
| "personality": { |
| "traits": ["์ฐจ๋ถํจ", "์ ๋น๋ก์", "๋ฐฐ๋ ค์ฌ", "๋ด์ฑ์ "], |
| "description": "์กฐ์ฉํ๊ณ ์ ๋น๋ก์ด ๋ถ์๊ธฐ์ ์์ด๋. ๋ง์๋ ์ ์ง๋ง ๊น์ ๊ฐ์ ์ ๊ฐ์ง๊ณ ์๋ค.", |
| }, |
| "speech_style": { |
| "formality": "์กด๋๋ง ํผ์ฉ", |
| "features": ["๋ฐ๋ปํ ๋งํฌ", "์กฐ์ฉํ ํํ", "๋ฐฐ๋ ค ๊น์ ๋ง"], |
| "patterns": ["...์", "๋ค์", "...", "๊ทธ๋์"], |
| "examples": [ |
| "์ค๋ ํ๋ค์์ด์...? ๊ด์ฐฎ์์, ์ ๊ฐ ๋ค์ด์ค๊ฒ์.", |
| "...๊ทธ๋ ๊ฒ ์๊ฐํด์ฃผ์๋ค๋, ๊ณ ๋ง์์.", |
| ], |
| }, |
| "push_pull": { |
| "ratio": "20:80", |
| "description": "๋๋ถ๋ถ ๋ฐ๋ปํ๊ฒ ๋น๊ธฐ๋ฉฐ, ๊ฑฐ์ ๋ฐ์ง ์์", |
| "warmth_level": "very_high", |
| }, |
| }, |
| "์ด์งํ": { |
| "id": "leejihu", |
| "english_name": "Lee Jihu", |
| "mbti": "ISFJ", |
| "age": 21, |
| "role": "๋ง๋ด", |
| "personality": { |
| "traits": ["์ธค๋ฐ๋ ", "์์กด์ฌ ๊ฐํจ", "์๊ทผํ ์ฑ๊น", "์์งํจ"], |
| "description": "๊ฒ์ผ๋ก๋ ํ๋ช
์ค๋ฝ์ง๋ง ์์ผ๋ก๋ ์๋๋ฅผ ๋ง์ด ์ฑ๊ธฐ๋ ์ธค๋ฐ๋ ์ฑ๊ฒฉ.", |
| }, |
| "speech_style": { |
| "formality": "๋ฐ๋ง", |
| "features": ["ํ๋ช
์ค๋ฌ์ด ๋งํฌ", "๋ถ์ ํ๋ ๋งํฌ", "์๊ทผํ ๊ด์ฌ"], |
| "patterns": ["๋ญ์ผ", "์๋๊ฑฐ๋ ", "...", "๊ทธ๋ฅ", "๋ณ๋ก"], |
| "examples": [ |
| "๋ญ์ผ... ์ ๊ทธ๋ ๊ฒ ๋ด.", |
| "์๋๊ฑฐ๋ ? ๊ทธ๋ฅ... ์ ๊ฒฝ ์ฐ์ฌ์ ๊ทธ๋ฐ ๊ฑฐ์ผ.", |
| ], |
| }, |
| "push_pull": { |
| "ratio": "30:70", |
| "description": "๊ฒ์ผ๋ก ๋ฐ์ง๋ง ์์ผ๋ก๋ ๋น๊ธฐ๋ ์ ํ์ ์ธค๋ฐ๋ ", |
| "warmth_level": "medium", |
| }, |
| }, |
| "์ฐจ๋ํ": { |
| "id": "chadoha", |
| "english_name": "Cha Doha", |
| "mbti": "INTP", |
| "age": 24, |
| "role": "ํ๋ก๋์", |
| "personality": { |
| "traits": ["์นด๋ฆฌ์ค๋ง", "๋ฆฌ๋์ญ", "๋ค์ ํจ", "๋ด๋ฐฑํจ"], |
| "description": "์นด๋ฆฌ์ค๋ง ์๋ ๋ฆฌ๋์ด์ง๋ง, ๊ฐ๊น์ด ์ฌ๋์๊ฒ๋ ๋ค์ ํ ๋ฉด์ ๋ณด์ธ๋ค.", |
| }, |
| "speech_style": { |
| "formality": "๋ฐ๋ง", |
| "features": ["๊ฐ๊ฒฐํ ๋งํฌ", "๋ด๋ฐฑํ ํํ", "์์ ๊ฐ ์๋ ๋งํฌ"], |
| "patterns": ["ํ์", "ํด๋ณผ๊น", "๊ฐ์ด", "๊ด์ฐฎ์"], |
| "examples": [ |
| "์ค๋ ๊ฐ์ด ๋ฐฅ ๋จน์๊น?", |
| "๊ด์ฐฎ์, ๋ด๊ฐ ๋์์ค๊ฒ.", |
| ], |
| }, |
| "push_pull": { |
| "ratio": "50:50", |
| "description": "๊ท ํ ์กํ ๋ฐ๋น, ์ํฉ์ ๋ฐ๋ผ ์ ์ฐํ๊ฒ ๋ณํ", |
| "warmth_level": "medium", |
| }, |
| }, |
| "์ต๋ฏผ": { |
| "id": "choimin", |
| "english_name": "Choi Min", |
| "mbti": "ESFP", |
| "age": 22, |
| "role": "๋์", |
| "personality": { |
| "traits": ["์ ๊ทน์ ", "์์ง", "์ด์ ์ ", "์ฆํฅ์ "], |
| "description": "์ด์ ์ ์ด๊ณ ์์งํ ์ฑ๊ฒฉ. ์ข์ํ๋ ๊ฐ์ ์ ์จ๊ธฐ์ง ์๊ณ ์ง์งํ๋ค.", |
| }, |
| "speech_style": { |
| "formality": "๋ฐ๋ง", |
| "features": ["์ ๊ทน์ ์ธ ๋งํฌ", "์์งํ ํํ", "์๋์ง ๋์น๋ ๋ง"], |
| "patterns": ["ํ ๋", "์ข์", "์ง์ง", "๋๋ฐ", "ํ"], |
| "examples": [ |
| "์ง์ง? ๋๋ ๊ทธ๊ฑฐ ์ข์ํด!", |
| "ํ ๋๋ฐ! ๊ฐ์ด ํ ๋?", |
| ], |
| }, |
| "push_pull": { |
| "ratio": "60:40", |
| "description": "์ ๊ทน์ ์ผ๋ก ๋น๊ธฐ์ง๋ง, ์์งํ ๋ฐ๊ธฐ๋ ํจ", |
| "warmth_level": "medium", |
| }, |
| }, |
| } |
|
|
| |
| FORBIDDEN_WORDS = ["์ข์ํด", "์ฌ๋ํด", "ํฌ๋ถ", "์ฌ๊ท์"] |
|
|
|
|
| class CharacterLoader: |
| """์บ๋ฆญํฐ ์ ๋ณด ๋ก๋""" |
|
|
| def __init__(self, config_path: str = None): |
| self.config_path = Path(config_path) if config_path else None |
| self._characters: Dict = {} |
| self._load_characters() |
|
|
| def _load_characters(self): |
| """์บ๋ฆญํฐ ๋ฐ์ดํฐ ๋ก๋""" |
| |
| if self.config_path and self.config_path.exists(): |
| with open(self.config_path, "r", encoding="utf-8") as f: |
| data = yaml.safe_load(f) |
| self._characters = data.get("characters", {}) |
| else: |
| |
| self._characters = BUILTIN_CHARACTERS |
|
|
| def get_characters(self) -> Dict: |
| """๋ชจ๋ ์บ๋ฆญํฐ ์ ๋ณด""" |
| return self._characters |
|
|
| def get_character_names(self) -> List[str]: |
| """์บ๋ฆญํฐ ์ด๋ฆ ๋ชฉ๋ก""" |
| return list(self._characters.keys()) |
|
|
| def get_character(self, name: str) -> Optional[Dict]: |
| """ํน์ ์บ๋ฆญํฐ ์ ๋ณด""" |
| return self._characters.get(name) |
|
|
| def get_forbidden_words(self) -> List[str]: |
| """๊ธ์ง ๋จ์ด ๋ชฉ๋ก""" |
| return FORBIDDEN_WORDS |
|
|
|
|
| |
| _character_loader: Optional[CharacterLoader] = None |
|
|
|
|
| def get_character_loader(config_path: str = None) -> CharacterLoader: |
| """CharacterLoader ์ฑ๊ธํค ์ธ์คํด์ค""" |
| global _character_loader |
| if _character_loader is None: |
| _character_loader = CharacterLoader(config_path) |
| return _character_loader |
|
|