# backend/app/llm/provider.py from __future__ import annotations from abc import ABC, abstractmethod from dataclasses import dataclass @dataclass class Classification: type: str # task | event | idea sphere: str # work | life project_id: str | None = None proj_label: str = "" tone: str = "ink" due_text: str = "" when_text: str = "" extra: str = "" reason: str = "" # 한국어 confidence: float = 0.0 model: str = "" class LLMProvider(ABC): name: str = "base" def tool_capable(self) -> bool: """tool-call(함수 호출) 가능한 모델인가. 기본 False → 에이전트는 scripted 폴백.""" return False @abstractmethod def health(self) -> dict: ... @abstractmethod def generate_json(self, prompt: str, schema: dict | None = None) -> dict: ... @abstractmethod def classify_capture(self, raw: str, context: dict) -> Classification: ... def list_models(self) -> list[str]: """사용 가능한 모델 목록(설정 페이지 드롭다운용). 기본 빈 목록.""" return [] _cached: LLMProvider | None = None def get_provider(force: str | None = None) -> LLMProvider: """실 LLM(Ollama) 전용. 휴리스틱 폴백 제거(phase-16+): 미가동 시 호출부에서 예외. 테스트는 conftest 가 get_provider 의존성을 결정적 FakeLLM 으로 오버라이드한다. force 인자는 하위호환용(현재 Ollama 단일 — 무시). """ from .ollama import OllamaProvider return OllamaProvider() def reset_provider_cache(): global _cached _cached = None