import asyncio import os import re import time import traceback from dotenv import load_dotenv from edge_tts import Communicate from agent import Agent from util.logger import get_logger load_dotenv() logger = get_logger("NORA") TTS_VOICE = "de-DE-AmalaNeural" class NoraChat: def __init__(self): self.agent = Agent() async def run(self): print("\n" + "=" * 40) print(" N.O.R.A START") print("=" * 40 + "\n") logger.info("Verbinde MCP...") await self.agent.mcp.connect() logger.info("Lade Tools...") await self.agent.load_tools() print("N.O.R.A ist bereit. (exit zum Beenden)\n") try: while True: user = input("Du: ").strip() if user.lower() in ["exit", "quit", "bye", "stop"]: break if not user: continue logger.info(f"USER: {user}") response = await self.agent.run(user) logger.info(f"NORA: {response}") print(f"\nN.O.R.A: {response}\n") await self.speak(response) except KeyboardInterrupt: pass finally: await self.agent.mcp.close() logger.info("Shutdown abgeschlossen") async def speak(self, text: str): try: # Nur die ersten zwei Sätze sprechen sentences = re.split(r'(?<=[.!?])\s+', text.strip()) speech_text = " ".join(sentences[:2]) if not speech_text: return filename = f"response_{int(time.time())}.mp3" tts = Communicate( speech_text, voice=TTS_VOICE ) await tts.save(filename) os.system(f"mpg123 -q {filename}") os.remove(filename) except Exception: logger.error("TTS Fehler") logger.error(traceback.format_exc()) async def main(): chat = NoraChat() await chat.run() if __name__ == "__main__": asyncio.run(main())