Spaces:
Running
Running
| """pocket_context_loader โ ์นด๋ ๋ธ๋ฆฌํ ๋ก๋ (BaseAgent, LLM ์์). | |
| ํ์ฌ ํฌ์ผ ์นด๋์ ๋ชฉํ/ํ์ฉ๋ฒ์ + ์ธ๋ฌผ ์ํธ + ์ ๋ขฐ ๋ ๋ฒจ๋ณ ๊ฒฐ์ | |
| session.state์ ์ ์ฌํ๋ค. ์คํฌ์ผ๋ฌ ํํฐ: ํ์ฌ ์นด๋ ์ดํ์ ์ฝํ ์ธ ๋ ์ฃ์ง ์๋๋ค. | |
| """ | |
| from __future__ import annotations | |
| import os | |
| from typing import Any, AsyncGenerator | |
| from google.adk.agents import BaseAgent | |
| from google.adk.agents.invocation_context import InvocationContext | |
| from google.adk.events import Event, EventActions | |
| from pydantic import ConfigDict | |
| from engine.services.state import HiddenState | |
| # P0 0-3 ํ์ฐ ์ถ๋ ฅ โ ์ ๋ขฐ ๋ ๋ฒจ โ ์นด๋ฅด๋ฐ๋ผ์ '๊ฒฐ' (์ซ์ ๋ ธ์ถ ๊ธ์ง์ ๊ตฌํ๋ถ) | |
| TRUST_TEXTURES = { | |
| "trust_high": "๋จ๋ฆฌ๋ ์ง์ฌ. ๊ฐ์ฅ ๋ค์ ํ๊ณ , ๊พธ๋ฐ์ด ๋ฒ๊ฒจ์ง ์๊ฐ์ด ์จ๋ค. " | |
| "์กฐ๊ฑด์ด ๋๋ฉด ์ฌ์ธต์ ๋ง์ ๊บผ๋ผ ์ ์๋ค.", | |
| "trust_mid": "๋๋ฅธํ ๋ค์ . ์ผ์ ํ์ ๊ฐ ํ๋ถํ๊ณ ํธ์ํ๋ค. ํ๋ฉด์ ๊ณ ๋ฐฑ๊น์ง๋ง.", | |
| "neutral": "์ฌํ ๋ฏธ์๋ก ์ฆ๋ต์ ํผํ๊ณ , ๊ด์ฌ์ ์๋์๊ฒ ๋๋๋ฆฐ๋ค.", | |
| "doubt_mid": "์ธ์งข์๊ณผ ๊ฒฝ๊ณ. ์ ์์ฒ๊ฐ ์ฑ์ ๊ฑฐ๋ฆฐ๋ค. '๋๋ฅผ ๋ฏฟ์ง ๋ชปํ๋'๊ฐ ๋ฐฐ์ด ๋์จ๋ค.", | |
| "doubt_high": "์ง์ฐฉ๊ณผ ๋ถ์. ๊ฐ์์ ์ค๋ ์ง์ ๊น์ง ๊ฐ๋, ๊ทธ ๋ฐ์ ์ธ๋ก์์ด ์์ด ๋์จ๋ค. " | |
| "๋ฌผ๋ฆฌ์ ๋๋ณ์ ์ ๋ ์๋ค.", | |
| } | |
| DEFAULT_POCKET_CARD = os.environ.get("POCKET_CARD", "E06-09") | |
| def _clean(text: str) -> str: | |
| """instruction ์นํ๊ฐ ์์ โ ์ค๊ดํธ ์ ๊ฑฐ (state ๋ณ์ ์ฌํด์ ๋ฐฉ์ง).""" | |
| return text.replace("{", "(").replace("}", ")") | |
| class PocketContextLoader(BaseAgent): | |
| model_config = ConfigDict(arbitrary_types_allowed=True) | |
| repo: Any # ContentRepository โ services ๊ฒฝ์ ์์ด ์ฝ๊ธฐ ์ ์ฉ ์กฐํ๋ง | |
| async def _run_async_impl(self, ctx: InvocationContext) -> AsyncGenerator[Event, None]: | |
| state = ctx.session.state | |
| card_id = state.get("pocket_card_id", DEFAULT_POCKET_CARD) | |
| card = self.repo.get_card(card_id) # ํฌ์ผ ์นด๋ ์์ = ํ์ฌ ์์ | |
| # ์ ๋ขฐ ๋ ๋ฒจ ํ์ฐ (session.state์ ์จ์ ๊ฐ ๊ธฐ์ค) | |
| hs = HiddenState(trust_score=int(state.get("hidden_trust", 0)), | |
| doubt_score=int(state.get("hidden_doubt", 0))) | |
| # ์นด๋ ๋ธ๋ฆฌํ: ์ง๋ฌธ(๊ฒ์ดํธ ๋ฐ์) + ๋ชฉํ(๋ ธํธ) + ์ต์ปค ๋์ฌ | |
| visible = [b for b in card.narration | |
| if b.gate == "all" or (b.gate == "trust_high" and hs.deep_unlock)] | |
| # ๋์ฌ(์ค์ ๋์ฌยท์ต์ปค)๋ ์๋ฅด์ง ์๋๋ค โ ๋ณ์ฃผ์ ๊ธฐ์ค์ด๋ฏ๋ก ์๋ฌธ ๊ทธ๋๋ก | |
| lines = [] | |
| for b in visible[:10]: | |
| if b.type == "dialogue_center": | |
| lines.append(f' ํต์ฌ ๋์ฌ: โ{b.text}โ') | |
| elif b.type == "character_dialogue": | |
| lines.append(f' {b.speaker or "์นด๋ฅด๋ฐ๋ผ"}: "{b.text}"') | |
| else: | |
| lines.append(f" {b.text[:150]}") | |
| anchors = [f"- {b.speaker or '์นด๋ฅด๋ฐ๋ผ'}: \"{b.text}\"" for b in visible if b.anchor] | |
| # ์บ๋ฆญํฐ์ฉ ๋ธ๋ฆฌํ โ ๋ ธํธ(์ฐ์ถ ๋ฉํยทํด๊ธ ์กฐ๊ฑดยท๋ถ๊ธฐ ์ ๋ณด)๋ ์ ๋ ์ฃ์ง ์๋๋ค. | |
| # ๋ ธํธ์๋ ๊ฒ์ดํธ ๋ฐ ๋์ฌ๊ฐ ์ธ์ฉ๋ ์ ์์ด ์บ๋ฆญํฐ์๊ฒ ์ฃผ๋ฉด ์คํฌ์ผ๋ฌ ๋์๊ฐ ๋๋ค | |
| brief = ( | |
| f"์ฅ๋ฉด: {card.id} ยท {card.title}\n" | |
| f"์ฅ๋ฉด ์ํฉ(๊ณ ์ ์ง๋ฌธ):\n" + "\n".join(lines) | |
| + ("\n์ฐธ๊ณ ๋์ฌ ํจํด(๊ทธ๋๋ก ์ฐ์ง ๋ง๊ณ ๋ณ์ฃผ):\n" + "\n".join(anchors) if anchors else "") | |
| ) | |
| # ๋๋ ํฐ์ฉ ๋ ธํธ โ ํ์ ๊ธฐ์ค(๋ชฉํ ๋นํธยท์ดํ ๋ฒ์)์ด๋ฏ๋ก ๋๋ ํฐ์๊ฒ๋ง ๊ฐ๋ค | |
| note = f"์ฅ๋ฉด ๋ชฉํ(์ฐ์ถ ๋ ธํธ): {card.note[:500]}" if card.note else "๋ช ์๋ ๋ ธํธ ์์." | |
| carmilla = self.repo.characters.get("carmilla") | |
| sheet = "" | |
| if carmilla: | |
| sheet = (f"{carmilla.display_name} โ {carmilla.description}\n" | |
| f"๊ธฐ์ง: {', '.join(carmilla.personality.traits)}\n" | |
| f"ํ๋ฒ: {', '.join(carmilla.speech.style + carmilla.speech.tone)}\n" | |
| + "\n".join(f"์ ์ฝ: {k.value}" for k in carmilla.immutable_constraints | |
| if k.value)) | |
| delta = { | |
| "pocket_card_id": card_id, | |
| "pocket_brief": _clean(brief), | |
| "pocket_note": _clean(note), | |
| "carmilla_sheet": _clean(sheet), | |
| "trust_texture": TRUST_TEXTURES[hs.trust_level], | |
| "trust_level": hs.trust_level, | |
| "deep_unlock": hs.deep_unlock, | |
| "guard_directive": state.get("guard_directive", "ํน์ด์ฌํญ ์์."), | |
| } | |
| yield Event(invocation_id=ctx.invocation_id, author=self.name, | |
| actions=EventActions(state_delta=delta)) | |
| def create_pocket_context_loader(repo) -> PocketContextLoader: | |
| return PocketContextLoader(name="pocket_context_loader", repo=repo) | |