| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- # -*- coding: utf-8 -*-
- """
- NLP Provider Interfaces.
- Definiert die Basisklassen und Datenstrukturen für NLP-Provider.
- """
- from abc import ABC, abstractmethod
- from dataclasses import dataclass, field
- from enum import Enum, auto
- from typing import Any, TYPE_CHECKING
- if TYPE_CHECKING:
- from trixy_core.conversation.session import ConversationSession
- class NLPState(Enum):
- """Status eines NLP-Providers."""
- UNINITIALIZED = auto()
- INITIALIZING = auto()
- READY = auto()
- PROCESSING = auto()
- ERROR = auto()
- SHUTDOWN = auto()
- @dataclass
- class NLPConfig:
- """
- Konfiguration für einen NLP-Provider.
- Attributes:
- backend: Name des Backends (z.B. "llama_cpp", "ollama")
- model_name: Name des Modells
- model_path: Optionaler Pfad zum Modell
- use_gpu: GPU-Beschleunigung verwenden
- num_threads: Anzahl CPU-Threads
- temperature: Sampling-Temperatur (0.0 = deterministisch)
- max_tokens: Maximale Antwortlänge
- context_window: Größe des Kontextfensters
- extra: Zusätzliche backend-spezifische Optionen
- """
- backend: str = "llama_cpp"
- model_name: str = ""
- model_path: str | None = None
- use_gpu: bool = False
- num_threads: int = 4
- temperature: float = 0.1
- max_tokens: int = 256
- context_window: int = 2048
- extra: dict[str, Any] = field(default_factory=dict)
- @dataclass
- class NLPContext:
- """
- Kontext für eine NLP-Anfrage.
- Enthält alle relevanten Informationen für die Intent-Erkennung.
- Attributes:
- text: Der zu verarbeitende Text (STT-Ergebnis)
- satellite_id: ID des Satellites
- room_id: Raum-ID
- session_id: Konversations-Session-ID
- session: Optionale Konversations-Session für Verlauf
- available_intents: Liste verfügbarer Intents mit Metadaten
- user_context: Zusätzlicher Benutzerkontext
- language: Sprachcode (z.B. "de", "en")
- """
- text: str
- satellite_id: str = ""
- room_id: str = ""
- session_id: str = ""
- session: "ConversationSession | None" = None
- available_intents: list[dict[str, Any]] = field(default_factory=list)
- user_context: dict[str, Any] = field(default_factory=dict)
- language: str = "de"
- def get_conversation_history(self, max_turns: int = 5) -> list[dict[str, str]]:
- """
- Gibt die letzten N Konversations-Turns zurück.
- Args:
- max_turns: Maximale Anzahl Turns
- Returns:
- Liste von {"role": "user"|"assistant", "content": "..."}
- """
- if self.session is None:
- return []
- history = []
- turns = list(self.session.turns)[-max_turns:]
- for turn in turns:
- if turn.turn_type.name.startswith("USER"):
- history.append({"role": "user", "content": turn.content})
- elif turn.turn_type.name.startswith("ASSISTANT"):
- history.append({"role": "assistant", "content": turn.content})
- return history
- @dataclass
- class NLPResult:
- """
- Ergebnis einer NLP-Verarbeitung.
- Attributes:
- intent: Erkannter Intent-Name
- confidence: Konfidenz der Erkennung (0.0 - 1.0)
- slots: Extrahierte Slot-Werte
- response_text: Generierte Antwort (optional, für LLM-basierte NLP)
- raw_output: Rohausgabe des NLP-Modells
- processing_time: Verarbeitungszeit in Sekunden
- success: Ob die Verarbeitung erfolgreich war
- error: Fehlermeldung falls nicht erfolgreich
- """
- intent: str = ""
- confidence: float = 0.0
- slots: dict[str, Any] = field(default_factory=dict)
- response_text: str = ""
- raw_output: str = ""
- processing_time: float = 0.0
- success: bool = True
- error: str = ""
- @classmethod
- def failure(cls, error: str) -> "NLPResult":
- """Erstellt ein Fehler-Ergebnis."""
- return cls(success=False, error=error)
- def has_response(self) -> bool:
- """Prüft ob eine Antwort generiert wurde."""
- return bool(self.response_text)
- class NLPProvider(ABC):
- """
- Abstrakte Basisklasse für NLP-Provider.
- Ein NLP-Provider verarbeitet Text und erkennt Intents mit Slots.
- Optional kann er auch direkt Antworten generieren (LLM-basiert).
- Beispiel:
- class LLMNLPProvider(NLPProvider):
- async def initialize(self, config: NLPConfig) -> bool:
- self._model = load_model(config.model_path)
- return True
- async def process(self, context: NLPContext) -> NLPResult:
- response = await self._model.generate(context.text)
- return NLPResult(
- intent=response.intent,
- confidence=response.confidence,
- slots=response.slots,
- response_text=response.text
- )
- """
- def __init__(self) -> None:
- """Initialisiert den Provider."""
- self._state = NLPState.UNINITIALIZED
- self._config: NLPConfig | None = None
- @property
- def state(self) -> NLPState:
- """Aktueller Status des Providers."""
- return self._state
- @property
- def is_ready(self) -> bool:
- """Ist der Provider einsatzbereit?"""
- return self._state == NLPState.READY
- @property
- def config(self) -> NLPConfig | None:
- """Aktuelle Konfiguration."""
- return self._config
- @abstractmethod
- async def initialize(self, config: NLPConfig) -> bool:
- """
- Initialisiert den Provider mit der gegebenen Konfiguration.
- Args:
- config: Provider-Konfiguration
- Returns:
- True bei erfolgreicher Initialisierung
- """
- pass
- @abstractmethod
- async def process(self, context: NLPContext) -> NLPResult:
- """
- Verarbeitet Text und erkennt Intents.
- Args:
- context: NLP-Kontext mit Text und Metadaten
- Returns:
- NLP-Ergebnis mit Intent, Slots und optionaler Antwort
- """
- pass
- @abstractmethod
- async def shutdown(self) -> None:
- """Fährt den Provider herunter und gibt Ressourcen frei."""
- pass
- async def health_check(self) -> bool:
- """
- Führt einen Health-Check durch.
- Returns:
- True wenn der Provider funktionsfähig ist
- """
- return self._state == NLPState.READY
- def get_capabilities(self) -> list[str]:
- """
- Gibt die Fähigkeiten des Providers zurück.
- Returns:
- Liste von Fähigkeiten (z.B. ["intent", "response", "entity"])
- """
- return ["intent"]
- def supports_streaming(self) -> bool:
- """
- Unterstützt der Provider Streaming-Antworten?
- Returns:
- True wenn Streaming unterstützt wird
- """
- return False
|