conversation.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. # -*- coding: utf-8 -*-
  2. """
  3. Conversation Extension Points.
  4. Extension Points für STT, TTS, NLP und Intent-Handler.
  5. """
  6. from abc import abstractmethod
  7. from typing import Any, TYPE_CHECKING
  8. from trixy_core.plugins.extensions.extension import Extension
  9. from trixy_core.plugins.extensions.extension_point import ExtensionPoint, get_global_registry
  10. # Extension Point IDs
  11. INTENT_HANDLER_POINT = "conversation.intent_handler"
  12. STT_POINT = "conversation.stt"
  13. TTS_POINT = "conversation.tts"
  14. NLP_POINT = "conversation.nlp"
  15. class IntentHandlerExtension(Extension):
  16. """
  17. Extension für Intent-Handler.
  18. Ermöglicht Plugins, neue Intents zu verarbeiten:
  19. - Smart-Home-Steuerung
  20. - Kalender-Integration
  21. - E-Mail-Verarbeitung
  22. - Benutzerdefinierte Befehle
  23. Beispiel:
  24. class SmartHomeIntentExtension(IntentHandlerExtension):
  25. def __init__(self, plugin_name: str):
  26. super().__init__(
  27. "smarthome_intents",
  28. "Smart-Home Steuerung",
  29. plugin_name,
  30. intents=["turn_on_light", "turn_off_light", "set_temperature"],
  31. )
  32. async def create_instance(self, config):
  33. return SmartHomeIntentHandler(config)
  34. """
  35. def __init__(
  36. self,
  37. extension_id: str,
  38. name: str,
  39. plugin_name: str = "",
  40. intents: list[str] | None = None,
  41. priority: int = 0,
  42. description: str = "",
  43. ) -> None:
  44. """
  45. Initialisiert die IntentHandler Extension.
  46. Args:
  47. extension_id: Eindeutige ID
  48. name: Anzeigename
  49. plugin_name: Plugin-Name
  50. intents: Liste der verarbeiteten Intents
  51. priority: Priorität (höher = wird zuerst gefragt)
  52. description: Beschreibung
  53. """
  54. super().__init__(extension_id, name, plugin_name)
  55. self._info.description = description
  56. self._info.extension_point = INTENT_HANDLER_POINT
  57. self._info.priority = priority
  58. self._info.metadata["intents"] = intents or []
  59. @property
  60. def intents(self) -> list[str]:
  61. """Verarbeitete Intents."""
  62. return self._info.metadata.get("intents", [])
  63. def handles_intent(self, intent: str) -> bool:
  64. """Prüft ob dieser Handler einen Intent verarbeitet."""
  65. return intent in self.intents or "*" in self.intents
  66. @abstractmethod
  67. async def create_instance(self, config: dict[str, Any]):
  68. """Erstellt die IntentHandler-Instanz."""
  69. pass
  70. class STTExtension(Extension):
  71. """
  72. Extension für Speech-to-Text.
  73. Ermöglicht Plugins, neue STT-Engines hinzuzufügen:
  74. - Google Speech-to-Text
  75. - Amazon Transcribe
  76. - Azure Speech
  77. - Whisper (lokal)
  78. - Vosk (offline)
  79. Beispiel:
  80. class WhisperSTTExtension(STTExtension):
  81. def __init__(self, plugin_name: str):
  82. super().__init__(
  83. "whisper_stt",
  84. "OpenAI Whisper",
  85. plugin_name,
  86. engine="whisper",
  87. languages=["de", "en", "fr", "es"],
  88. offline=True,
  89. )
  90. async def create_instance(self, config):
  91. return WhisperSTT(model=config.get("model", "base"))
  92. """
  93. def __init__(
  94. self,
  95. extension_id: str,
  96. name: str,
  97. plugin_name: str = "",
  98. engine: str = "",
  99. languages: list[str] | None = None,
  100. offline: bool = False,
  101. description: str = "",
  102. ) -> None:
  103. """
  104. Initialisiert die STT Extension.
  105. Args:
  106. extension_id: Eindeutige ID
  107. name: Anzeigename
  108. plugin_name: Plugin-Name
  109. engine: Engine-Name
  110. languages: Unterstützte Sprachen
  111. offline: Funktioniert offline
  112. description: Beschreibung
  113. """
  114. super().__init__(extension_id, name, plugin_name)
  115. self._info.description = description
  116. self._info.extension_point = STT_POINT
  117. self._info.metadata["engine"] = engine
  118. self._info.metadata["languages"] = languages or ["en"]
  119. self._info.metadata["offline"] = offline
  120. @property
  121. def engine(self) -> str:
  122. """Engine-Name."""
  123. return self._info.metadata.get("engine", "")
  124. @property
  125. def languages(self) -> list[str]:
  126. """Unterstützte Sprachen."""
  127. return self._info.metadata.get("languages", [])
  128. @property
  129. def is_offline(self) -> bool:
  130. """Funktioniert offline."""
  131. return self._info.metadata.get("offline", False)
  132. @abstractmethod
  133. async def create_instance(self, config: dict[str, Any]):
  134. """Erstellt die STT-Engine-Instanz."""
  135. pass
  136. class TTSExtension(Extension):
  137. """
  138. Extension für Text-to-Speech.
  139. Ermöglicht Plugins, neue TTS-Engines hinzuzufügen:
  140. - Google TTS
  141. - Amazon Polly
  142. - Azure Speech
  143. - Coqui TTS (lokal)
  144. - eSpeak (offline)
  145. Beispiel:
  146. class CoquiTTSExtension(TTSExtension):
  147. def __init__(self, plugin_name: str):
  148. super().__init__(
  149. "coqui_tts",
  150. "Coqui TTS",
  151. plugin_name,
  152. engine="coqui",
  153. voices=["thorsten", "karlsson"],
  154. offline=True,
  155. )
  156. async def create_instance(self, config):
  157. return CoquiTTS(voice=config.get("voice", "thorsten"))
  158. """
  159. def __init__(
  160. self,
  161. extension_id: str,
  162. name: str,
  163. plugin_name: str = "",
  164. engine: str = "",
  165. voices: list[str] | None = None,
  166. languages: list[str] | None = None,
  167. offline: bool = False,
  168. description: str = "",
  169. ) -> None:
  170. """
  171. Initialisiert die TTS Extension.
  172. Args:
  173. extension_id: Eindeutige ID
  174. name: Anzeigename
  175. plugin_name: Plugin-Name
  176. engine: Engine-Name
  177. voices: Verfügbare Stimmen
  178. languages: Unterstützte Sprachen
  179. offline: Funktioniert offline
  180. description: Beschreibung
  181. """
  182. super().__init__(extension_id, name, plugin_name)
  183. self._info.description = description
  184. self._info.extension_point = TTS_POINT
  185. self._info.metadata["engine"] = engine
  186. self._info.metadata["voices"] = voices or []
  187. self._info.metadata["languages"] = languages or ["en"]
  188. self._info.metadata["offline"] = offline
  189. @property
  190. def engine(self) -> str:
  191. """Engine-Name."""
  192. return self._info.metadata.get("engine", "")
  193. @property
  194. def voices(self) -> list[str]:
  195. """Verfügbare Stimmen."""
  196. return self._info.metadata.get("voices", [])
  197. @property
  198. def languages(self) -> list[str]:
  199. """Unterstützte Sprachen."""
  200. return self._info.metadata.get("languages", [])
  201. @property
  202. def is_offline(self) -> bool:
  203. """Funktioniert offline."""
  204. return self._info.metadata.get("offline", False)
  205. @abstractmethod
  206. async def create_instance(self, config: dict[str, Any]):
  207. """Erstellt die TTS-Engine-Instanz."""
  208. pass
  209. class NLPExtension(Extension):
  210. """
  211. Extension für Natural Language Processing.
  212. Ermöglicht Plugins, neue NLP-Engines hinzuzufügen:
  213. - OpenAI GPT
  214. - Anthropic Claude
  215. - Llama (lokal)
  216. - Rasa NLU
  217. - spaCy
  218. Beispiel:
  219. class ClaudeNLPExtension(NLPExtension):
  220. def __init__(self, plugin_name: str):
  221. super().__init__(
  222. "claude_nlp",
  223. "Anthropic Claude",
  224. plugin_name,
  225. engine="claude",
  226. capabilities=["intent", "entity", "conversation"],
  227. )
  228. async def create_instance(self, config):
  229. return ClaudeNLP(api_key=config["api_key"])
  230. """
  231. def __init__(
  232. self,
  233. extension_id: str,
  234. name: str,
  235. plugin_name: str = "",
  236. engine: str = "",
  237. capabilities: list[str] | None = None,
  238. offline: bool = False,
  239. description: str = "",
  240. ) -> None:
  241. """
  242. Initialisiert die NLP Extension.
  243. Args:
  244. extension_id: Eindeutige ID
  245. name: Anzeigename
  246. plugin_name: Plugin-Name
  247. engine: Engine-Name
  248. capabilities: NLP-Fähigkeiten (intent, entity, sentiment, etc.)
  249. offline: Funktioniert offline
  250. description: Beschreibung
  251. """
  252. super().__init__(extension_id, name, plugin_name)
  253. self._info.description = description
  254. self._info.extension_point = NLP_POINT
  255. self._info.metadata["engine"] = engine
  256. self._info.metadata["capabilities"] = capabilities or []
  257. self._info.metadata["offline"] = offline
  258. @property
  259. def engine(self) -> str:
  260. """Engine-Name."""
  261. return self._info.metadata.get("engine", "")
  262. @property
  263. def capabilities(self) -> list[str]:
  264. """NLP-Fähigkeiten."""
  265. return self._info.metadata.get("capabilities", [])
  266. @property
  267. def is_offline(self) -> bool:
  268. """Funktioniert offline."""
  269. return self._info.metadata.get("offline", False)
  270. @abstractmethod
  271. async def create_instance(self, config: dict[str, Any]):
  272. """Erstellt die NLP-Engine-Instanz."""
  273. pass
  274. def setup_conversation_extension_points() -> dict[str, ExtensionPoint]:
  275. """
  276. Richtet alle Conversation Extension Points ein.
  277. Returns:
  278. Dict mit allen erstellten Extension Points
  279. """
  280. registry = get_global_registry()
  281. points = {}
  282. # Intent-Handler
  283. points[INTENT_HANDLER_POINT] = registry.create_point(
  284. id=INTENT_HANDLER_POINT,
  285. name="Intent-Handler",
  286. description="Erweiterung um neue Intent-Verarbeitung",
  287. category="conversation",
  288. allows_multiple=True,
  289. )
  290. # Speech-to-Text
  291. points[STT_POINT] = registry.create_point(
  292. id=STT_POINT,
  293. name="Speech-to-Text Engines",
  294. description="Erweiterung um neue STT-Engines (Whisper, Google, etc.)",
  295. category="conversation",
  296. allows_multiple=True,
  297. )
  298. # Text-to-Speech
  299. points[TTS_POINT] = registry.create_point(
  300. id=TTS_POINT,
  301. name="Text-to-Speech Engines",
  302. description="Erweiterung um neue TTS-Engines (Coqui, Polly, etc.)",
  303. category="conversation",
  304. allows_multiple=True,
  305. )
  306. # NLP
  307. points[NLP_POINT] = registry.create_point(
  308. id=NLP_POINT,
  309. name="NLP Engines",
  310. description="Erweiterung um neue NLP-Engines (GPT, Claude, Llama, etc.)",
  311. category="conversation",
  312. allows_multiple=True,
  313. )
  314. return points