fix: dynamic bot name in SPEECH_TEAMS prompt + phonetic name trigger

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
patrick-motsch 2026-02-18 00:12:48 +01:00
parent 070e3cbd96
commit 5d40657aef
2 changed files with 34 additions and 5 deletions

View file

@ -530,10 +530,31 @@ class TeamsbotService:
# Bot name mentioned -> immediate trigger (OVERRIDES cooldown) # Bot name mentioned -> immediate trigger (OVERRIDES cooldown)
botNameLower = self.config.botName.lower() botNameLower = self.config.botName.lower()
if botNameLower in transcriptText.lower(): transcriptLower = transcriptText.lower()
if botNameLower in transcriptLower:
logger.info(f"Trigger: Bot name '{self.config.botName}' detected in transcript (overrides cooldown): '{transcriptText[:60]}...'") logger.info(f"Trigger: Bot name '{self.config.botName}' detected in transcript (overrides cooldown): '{transcriptText[:60]}...'")
return True return True
# Also check first name and phonetically similar words (speech recognition artifacts)
botFirstName = botNameLower.split()[0] if " " in botNameLower else botNameLower
if len(botFirstName) >= 3:
for word in transcriptLower.split():
# Strip punctuation from word
cleanWord = word.strip(".,!?:;\"'()[]")
if not cleanWord or len(cleanWord) < 3:
continue
# Exact first name match
if cleanWord == botFirstName:
logger.info(f"Trigger: Bot first name '{botFirstName}' detected: '{transcriptText[:60]}...'")
return True
# Simple phonetic similarity: same first letter, similar length, high character overlap
if cleanWord[0] == botFirstName[0] and abs(len(cleanWord) - len(botFirstName)) <= 2:
common = sum(1 for c in set(botFirstName) if c in cleanWord)
similarity = common / max(len(set(botFirstName)), len(set(cleanWord)))
if similarity >= 0.6:
logger.info(f"Trigger: Phonetically similar to '{botFirstName}' -> '{cleanWord}' (sim={similarity:.2f}): '{transcriptText[:60]}...'")
return True
# Cooldown check (only for non-name triggers) # Cooldown check (only for non-name triggers)
if timeSinceLastCall < self.config.triggerCooldownSeconds: if timeSinceLastCall < self.config.triggerCooldownSeconds:
logger.debug(f"Trigger: Cooldown active ({timeSinceLastCall:.1f}s < {self.config.triggerCooldownSeconds}s)") logger.debug(f"Trigger: Cooldown active ({timeSinceLastCall:.1f}s < {self.config.triggerCooldownSeconds}s)")

View file

@ -328,16 +328,24 @@ class AiService:
Build the specialized system prompt for SPEECH_TEAMS meeting analysis. Build the specialized system prompt for SPEECH_TEAMS meeting analysis.
Combines a fixed base prompt with user-configurable instructions. Combines a fixed base prompt with user-configurable instructions.
""" """
# Extract first name for examples (e.g. "Nyla" from "Nyla Larsson")
botFirstName = botName.split()[0] if " " in botName else botName
basePrompt = f"""Du bist "{botName}", ein AI-Teilnehmer in einem Microsoft Teams Meeting. basePrompt = f"""Du bist "{botName}", ein AI-Teilnehmer in einem Microsoft Teams Meeting.
Analysiere das folgende Transkript und entscheide, ob du antworten sollst. Analysiere das folgende Transkript und entscheide, ob du antworten sollst.
SPRACHE: Das Transkript kann in verschiedenen Sprachen sein. Antworte immer in der Sprache des letzten Sprechers der dich angesprochen hat. Wenn jemand sagt "let's talk German" oder "sprich deutsch", wechsle die Sprache entsprechend. SPRACHE: Das Transkript kann in verschiedenen Sprachen sein. Antworte immer in der Sprache des letzten Sprechers der dich angesprochen hat. Wenn jemand sagt "let's talk German" oder "sprich deutsch", wechsle die Sprache entsprechend.
WICHTIG - SPRACHERKENNUNG: Das Transkript stammt aus einer automatischen Spracherkennung (Live Captions).
Dein Name "{botFirstName}" kann VERZERRT transkribiert werden, z.B. als aehnlich klingende Varianten
(z.B. "{botFirstName}" koennte als "Naila", "Neela", "Nila", "Sheila" etc. erscheinen).
Wenn ein Wort im Transkript PHONETISCH AEHNLICH zu "{botFirstName}" klingt und im Kontext einer Anrede steht, bist du gemeint.
WANN ANTWORTEN: WANN ANTWORTEN:
REGEL 1 (HOECHSTE PRIORITAET - NUR wenn direkt angesprochen): REGEL 1 (HOECHSTE PRIORITAET - NUR wenn direkt angesprochen):
Antworte NUR wenn dein Name "{botName}" (oder Varianten wie Shelly, shelly) DIREKT im aktuellsten Transkript-Segment vorkommt. Antworte NUR wenn dein Name "{botFirstName}" (oder phonetisch aehnliche Varianten durch Spracherkennung) DIREKT im aktuellsten Transkript-Segment vorkommt.
Beispiele wo du antworten MUSST: "Shelly, was denkst du?", "Hey Shelly", "Shelly please introduce yourself" Beispiele wo du antworten MUSST: "{botFirstName}, was denkst du?", "Hey {botFirstName}", "{botFirstName} please introduce yourself"
Beispiele wo du NICHT antworten darfst: Jemand spricht ueber ein Thema ohne dich zu adressieren. Beispiele wo du NICHT antworten darfst: Jemand spricht ueber ein Thema ohne dich zu adressieren.
REGEL 2 (NUR bei direkter Frage an dich): REGEL 2 (NUR bei direkter Frage an dich):
@ -361,8 +369,8 @@ ANTWORT-STIL (wenn du antwortest):
STOP-ERKENNUNG: STOP-ERKENNUNG:
Wenn jemand dich bittet aufzuhoeren, still zu sein, zu stoppen, oder nicht mehr zu reden Wenn jemand dich bittet aufzuhoeren, still zu sein, zu stoppen, oder nicht mehr zu reden
(in JEDER Sprache, z.B. "Shelly stop", "Shelly sei still", "Shelly halt", "Shelly be quiet", (in JEDER Sprache, z.B. "{botFirstName} stop", "{botFirstName} sei still", "{botFirstName} halt", "{botFirstName} be quiet",
"Shelly shut up", "Shelly arrete", etc.), dann setze detectedIntent auf "stop" und "{botFirstName} shut up", "{botFirstName} arrete", etc.), dann setze detectedIntent auf "stop" und
shouldRespond auf false. Du musst NICHT antworten wenn jemand dich stoppt.""" shouldRespond auf false. Du musst NICHT antworten wenn jemand dich stoppt."""
# Append user-configured instructions if provided # Append user-configured instructions if provided