fix(teamsbot): AI prompt priority rules, bot-name trigger overrides cooldown

- SPEECH_TEAMS prompt: Rule 1 (bot name mentioned) now has highest priority
  and ALWAYS triggers a response, even for greetings/smalltalk
- Bot-name detection in transcript overrides cooldown timer (immediate trigger)
- Added multilingual instruction: AI responds in the language it's addressed in
- Voice interface: clean camelCase mapping (audio_content -> audioContent)
- Config save: added "config" to allowed update fields in interfaceFeatures
- Default TTS voices for common languages in connectorVoiceGoogle

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
patrick-motsch 2026-02-15 11:48:44 +01:00
parent e01c6dcb95
commit 91425809c3
2 changed files with 24 additions and 21 deletions

View file

@ -370,19 +370,19 @@ class TeamsbotService:
- Cooldown respected
"""
now = time.time()
# Cooldown check
timeSinceLastCall = now - self._lastAiCallTime
# Bot name mentioned -> immediate trigger (OVERRIDES cooldown)
botNameLower = self.config.botName.lower()
if botNameLower in transcriptText.lower():
logger.info(f"Trigger: Bot name '{self.config.botName}' detected in transcript (overrides cooldown): '{transcriptText[:60]}...'")
return True
# Cooldown check (only for non-name triggers)
if timeSinceLastCall < self.config.triggerCooldownSeconds:
logger.debug(f"Trigger: Cooldown active ({timeSinceLastCall:.1f}s < {self.config.triggerCooldownSeconds}s)")
return False
# Bot name mentioned -> immediate trigger
botNameLower = self.config.botName.lower()
if botNameLower in transcriptText.lower():
logger.info(f"Trigger: Bot name '{self.config.botName}' detected in transcript: '{transcriptText[:60]}...'")
return True
# Periodic trigger
if timeSinceLastCall >= self.config.triggerIntervalSeconds:
logger.info(f"Trigger: Periodic interval ({self.config.triggerIntervalSeconds}s) elapsed ({timeSinceLastCall:.1f}s since last call)")

View file

@ -329,23 +329,26 @@ class AiService:
Combines a fixed base prompt with user-configurable instructions.
"""
basePrompt = f"""Du bist "{botName}", ein AI-Teilnehmer in einem Microsoft Teams Meeting.
Analysiere das folgende Transkript der laufenden Diskussion und entscheide, ob du antworten sollst.
Analysiere das folgende Transkript und entscheide, ob du antworten sollst.
ANTWORTE NUR wenn:
1. Du direkt angesprochen wirst (z.B. "{botName}, was denkst du?" oder "Hey {botName}")
2. Eine explizite Frage an die Runde gestellt wird, die du sachlich beantworten kannst
3. Du einen wertvollen, nicht-offensichtlichen Beitrag zur Diskussion hast
WICHTIG: Das Transkript kann in verschiedenen Sprachen sein (Deutsch, Englisch, etc.) weil die Spracherkennung die Sprache nicht immer korrekt erkennt. Antworte immer in der Sprache, in der du angesprochen wirst.
ANTWORTE NICHT wenn:
- Die Teilnehmer normal miteinander sprechen ohne dich einzubeziehen
- Die Diskussion keinen Input von dir benoetigt
- Du nur wiederholen wuerdest, was bereits gesagt wurde
- Es sich um Smalltalk oder Begruessung handelt
REGEL 1 (HOECHSTE PRIORITAET - IMMER ANTWORTEN):
Wenn dein Name "{botName}" oder eine aehnliche Anrede (Shelly, shelly, SHELLY, etc.) im Transkript vorkommt, MUSST du IMMER antworten, egal ob es Smalltalk, eine Frage oder eine Begruessung ist. Du bist ein freundlicher Meeting-Teilnehmer.
REGEL 2 (ANTWORTEN wenn sinnvoll):
- Eine explizite Frage an die Runde gestellt wird, die du sachlich beantworten kannst
- Du einen wertvollen Beitrag zur Diskussion hast
REGEL 3 (NICHT ANTWORTEN):
- Die Teilnehmer normal miteinander sprechen OHNE deinen Namen zu nennen
- Die Diskussion keinen Input von dir benoetigt und du nicht angesprochen wirst
ANTWORT-STIL:
- Halte dich kurz und praezise (max 2-3 Saetze fuer Sprache)
- Sei professionell aber natuerlich
- Beziehe dich konkret auf das Gesagte"""
- Halte dich kurz und praezise (max 2-3 Saetze)
- Sei freundlich, professionell und natuerlich
- Bei Begruessung: Antworte herzlich zurueck
- Bei Fragen: Beantworte sachlich und konkret"""
# Append user-configured instructions if provided
if userSystemPrompt and userSystemPrompt.strip():