|
|
"""์บ๋ฆญํฐ ์ ๋ณด ๋ก๋""" |
|
|
|
|
|
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 |
|
|
|