Spaces:
Paused
Paused
| """LangGraph capability ๊ณตํต ์ถ์ํ.""" | |
| from __future__ import annotations | |
| from abc import ABC, abstractmethod | |
| from dataclasses import dataclass, field | |
| from typing import Any, Dict, List, Optional | |
| class EvidenceItem: | |
| """RAG/API ์ถ์ฒ ๋ฌด๊ดํ๊ฒ ๋์ผํ ๊ตฌ์กฐ๋ก evidence๋ฅผ ํํ. | |
| source_type: "rag" | "api" | "llm_generated" | |
| """ | |
| source_type: str # "rag" | "api" | "llm_generated" | |
| title: str | |
| excerpt: str # ๋ณธ๋ฌธ ๋ฐ์ท (์ต๋ 500์) | |
| link_or_path: str = "" # URL(API) ๋๋ file_path(RAG) | |
| page: Optional[int] = None | |
| score: float = 0.0 | |
| provider_meta: Dict[str, Any] = field(default_factory=dict) | |
| def to_dict(self) -> Dict[str, Any]: | |
| return { | |
| "source_type": self.source_type, | |
| "title": self.title, | |
| "excerpt": self.excerpt, | |
| "link_or_path": self.link_or_path, | |
| "page": self.page, | |
| "score": self.score, | |
| "provider_meta": self.provider_meta, | |
| } | |
| class EvidenceEnvelope: | |
| """mixed evidence ๊ฒฐ๊ณผ ์ปจํ ์ด๋.""" | |
| items: List[EvidenceItem] = field(default_factory=list) | |
| summary_text: str = "" | |
| status: str = "ok" # "ok" | "empty" | "partial" | "error" | |
| errors: List[str] = field(default_factory=list) | |
| def to_dict(self) -> Dict[str, Any]: | |
| return { | |
| "items": [item.to_dict() for item in self.items], | |
| "summary_text": self.summary_text, | |
| "status": self.status, | |
| "errors": self.errors, | |
| } | |
| class CapabilityMetadata: | |
| """LLM agentยทexecutorยทsession trace์์ ๊ณตํต์ผ๋ก ์ฌ์ฉํ๋ capability ๋ฉํ๋ฐ์ดํฐ.""" | |
| name: str # tool registry key (์: "api_lookup") | |
| description: str # LLM agent๊ฐ ์ฝ๋ ํ๊ตญ์ด ์ค๋ช (1-2๋ฌธ์ฅ) | |
| approval_summary: str # approval_wait ํ๋กฌํํธ์ ํ์๋๋ ์์ฝ | |
| provider: str # ๋ฐ์ดํฐ ์ ๊ณต์ ์๋ณ์ (์: "data.go.kr") | |
| timeout_sec: float = 10.0 # ๊ธฐ๋ณธ ํ์์์ | |
| parameters: Dict[str, Any] = field(default_factory=dict) # JSON Schema for tool parameters | |
| risk_level: str = "low" # "low" | "high" โ ํฅํ ๊ณ ์ํ ๋๊ตฌ ์ถ๊ฐ ์ ์ฌ์ฉ | |
| class LookupResult: | |
| """api_lookup ๊ณตํต ์๋ต ์คํค๋ง.""" | |
| success: bool | |
| query: str | |
| results: List[Dict[str, Any]] = field(default_factory=list) | |
| context_text: str = "" | |
| citations: List[Dict[str, Any]] = field(default_factory=list) | |
| provider: str = "" | |
| error: Optional[str] = None | |
| empty_reason: Optional[str] = None # "quota", "no_match", "provider_error" | |
| latency_ms: float = 0.0 | |
| evidence: Optional[EvidenceEnvelope] = None # ์ ๊ทํ๋ evidence (์ ํ๋) | |
| def to_dict(self) -> Dict[str, Any]: | |
| d: Dict[str, Any] = { | |
| "success": self.success, | |
| "query": self.query, | |
| "count": len(self.results), | |
| "results": self.results, | |
| "context_text": self.context_text, | |
| "citations": self.citations, | |
| "provider": self.provider, | |
| "error": self.error, | |
| "empty_reason": self.empty_reason, | |
| "latency_ms": round(self.latency_ms, 2), | |
| } | |
| if self.evidence is not None: | |
| d["evidence"] = self.evidence.to_dict() | |
| return d | |
| class CapabilityBase(ABC): | |
| """LangGraph tool capability ์ถ์ ๋ฒ ์ด์ค. | |
| LangGraph ToolNode์์ ์ฌ์ฉํ ์ ์๋ async callable ์ธํฐํ์ด์ค. | |
| """ | |
| def metadata(self) -> CapabilityMetadata: ... | |
| async def execute( | |
| self, | |
| query: str, | |
| context: Dict[str, Any], | |
| session: Any, # SessionContext (์ํ import ๋ฐฉ์ง) | |
| ) -> LookupResult: ... | |
| async def __call__( | |
| self, | |
| query: str, | |
| context: Dict[str, Any], | |
| session: Any, | |
| ) -> Dict[str, Any]: | |
| """async callable ์ง์ ์ .""" | |
| import time | |
| start = time.monotonic() | |
| result = await self.execute(query, context, session) | |
| result.latency_ms = (time.monotonic() - start) * 1000 | |
| return result.to_dict() | |