Spaces:
Sleeping
Sleeping
Update alz_companion/agent.py
Browse files- alz_companion/agent.py +43 -39
alz_companion/agent.py
CHANGED
|
@@ -25,23 +25,24 @@ except Exception:
|
|
| 25 |
gTTS = None
|
| 26 |
|
| 27 |
from .prompts import (
|
| 28 |
-
SYSTEM_TEMPLATE,
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
ANSWER_TEMPLATE_ADQ_MODERATE,
|
| 32 |
-
ANSWER_TEMPLATE_ADQ_ADVANCED,
|
| 33 |
-
# --- END OF ADDITION ---
|
| 34 |
SAFETY_GUARDRAILS, RISK_FOOTER, render_emotion_guidelines,
|
|
|
|
| 35 |
NLU_ROUTER_PROMPT, SPECIALIST_CLASSIFIER_PROMPT,
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
|
|
|
|
|
|
| 43 |
)
|
| 44 |
|
|
|
|
| 45 |
_BEHAVIOR_ALIASES = {
|
| 46 |
"repeating questions": "repetitive_questioning", "repetitive questions": "repetitive_questioning",
|
| 47 |
"confusion": "confusion", "wandering": "wandering", "agitation": "agitation",
|
|
@@ -565,77 +566,80 @@ def make_rag_chain(vs_general: FAISS, vs_personal: FAISS, *, for_evaluation: boo
|
|
| 565 |
|
| 566 |
# --- REVISED MUSIC PLAYBACK LOGIC ---
|
| 567 |
if "play_music_request" in query_type:
|
|
|
|
|
|
|
| 568 |
if not music_manifest_path or not os.path.exists(music_manifest_path):
|
| 569 |
return {"answer": "I'm sorry, there is no music in the library yet.", "sources": [], "audio_playback_url": None}
|
| 570 |
-
|
| 571 |
with open(music_manifest_path, "r") as f:
|
| 572 |
manifest = json.load(f)
|
| 573 |
-
|
| 574 |
if not manifest:
|
| 575 |
return {"answer": "I'm sorry, there is no music in the library yet.", "sources": [], "audio_playback_url": None}
|
| 576 |
-
|
| 577 |
found_song = None
|
| 578 |
query_lower = query.lower()
|
| 579 |
-
|
| 580 |
# 1. First, search for a specific Title or Artist mentioned in the query.
|
| 581 |
for song_id, data in manifest.items():
|
| 582 |
if data["title"].lower() in query_lower or data["artist"].lower() in query_lower:
|
| 583 |
found_song = data
|
| 584 |
break
|
| 585 |
-
|
| 586 |
-
#
|
| 587 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 588 |
if not found_song:
|
| 589 |
detected_emotion_raw = kwargs.get("emotion_tag")
|
| 590 |
detected_emotion = detected_emotion_raw.lower() if detected_emotion_raw else ""
|
| 591 |
detected_behavior_raw = kwargs.get("scenario_tag")
|
| 592 |
detected_behavior = detected_behavior_raw.lower() if detected_behavior_raw else ""
|
| 593 |
-
|
| 594 |
-
# --- NEW DEBUG PRINT ADDED HERE ---
|
| 595 |
print(f"[DEBUG] Music Search: Using NLU tags. Behavior='{detected_behavior}', Emotion='{detected_emotion}'")
|
| 596 |
|
| 597 |
-
search_tags = [
|
| 598 |
|
| 599 |
for nlu_tag in search_tags:
|
| 600 |
if not nlu_tag or nlu_tag == "none": continue
|
| 601 |
|
| 602 |
-
# Get the core word from the NLU tag (e.g., "reminiscence" from "reminiscence_prompting")
|
| 603 |
core_nlu_word = nlu_tag.split('_')[0]
|
| 604 |
-
|
| 605 |
-
# --- NEW DEBUG PRINT ADDED HERE ---
|
| 606 |
print(f" [DEBUG] Music Search Loop: Using core_nlu_word='{core_nlu_word}' for matching.")
|
| 607 |
-
# --- END OF ADDITION ---
|
| 608 |
|
| 609 |
for song_id, data in manifest.items():
|
| 610 |
-
for mood_tag in data
|
| 611 |
-
|
| 612 |
mood_words = re.split(r'[\s/]', mood_tag.lower())
|
| 613 |
-
|
| 614 |
-
# --- NEW DEBUG PRINT ADDED HERE ---
|
| 615 |
-
print(f" [DEBUG] MOODS Search Loop: Using mood_words='{mood_words}' for matching.")
|
| 616 |
-
# --- END OF ADDITION ---
|
| 617 |
-
|
| 618 |
-
# Check if the core NLU word is one of the words in the mood tag
|
| 619 |
if core_nlu_word in mood_words:
|
| 620 |
found_song = data
|
| 621 |
break
|
| 622 |
if found_song: break
|
| 623 |
if found_song: break
|
| 624 |
-
# --- MODIFICATION END ---
|
| 625 |
|
| 626 |
# 3. If still not found, handle generic requests by playing a random song.
|
| 627 |
if not found_song:
|
|
|
|
| 628 |
generic_keywords = ["music", "song", "something", "anything"]
|
| 629 |
if any(keyword in query_lower for keyword in generic_keywords):
|
| 630 |
random_song_id = random.choice(list(manifest.keys()))
|
| 631 |
found_song = manifest[random_song_id]
|
| 632 |
|
|
|
|
| 633 |
if found_song:
|
| 634 |
-
|
| 635 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 636 |
else:
|
| 637 |
return {"answer": "I couldn't find a song matching your request in the library.", "sources": [], "audio_playback_url": None}
|
| 638 |
-
# --- END OF REVISED MUSIC LOGIC ---
|
| 639 |
# END --- MUSIC PLAYBACK LOGIC ---
|
| 640 |
|
| 641 |
p_name = patient_name or "the patient"
|
|
|
|
| 25 |
gTTS = None
|
| 26 |
|
| 27 |
from .prompts import (
|
| 28 |
+
SYSTEM_TEMPLATE,
|
| 29 |
+
|
| 30 |
+
ROUTER_PROMPT,
|
|
|
|
|
|
|
|
|
|
| 31 |
SAFETY_GUARDRAILS, RISK_FOOTER, render_emotion_guidelines,
|
| 32 |
+
|
| 33 |
NLU_ROUTER_PROMPT, SPECIALIST_CLASSIFIER_PROMPT,
|
| 34 |
+
ANSWER_TEMPLATE_CALM,
|
| 35 |
+
ANSWER_TEMPLATE_ADQ, ANSWER_TEMPLATE_ADQ_MODERATE, ANSWER_TEMPLATE_ADQ_ADVANCED,
|
| 36 |
+
|
| 37 |
+
ANSWER_TEMPLATE_FACTUAL, ANSWER_TEMPLATE_FACTUAL_MULTI, ANSWER_TEMPLATE_SUMMARIZE,
|
| 38 |
+
|
| 39 |
+
ANSWER_TEMPLATE_GENERAL_KNOWLEDGE, ANSWER_TEMPLATE_GENERAL,
|
| 40 |
+
|
| 41 |
+
QUERY_EXPANSION_PROMPT,
|
| 42 |
+
MUSIC_PREAMBLE_PROMPT
|
| 43 |
)
|
| 44 |
|
| 45 |
+
|
| 46 |
_BEHAVIOR_ALIASES = {
|
| 47 |
"repeating questions": "repetitive_questioning", "repetitive questions": "repetitive_questioning",
|
| 48 |
"confusion": "confusion", "wandering": "wandering", "agitation": "agitation",
|
|
|
|
| 566 |
|
| 567 |
# --- REVISED MUSIC PLAYBACK LOGIC ---
|
| 568 |
if "play_music_request" in query_type:
|
| 569 |
+
if "play_music_request" in query_type:
|
| 570 |
+
# Manifest loading logic
|
| 571 |
if not music_manifest_path or not os.path.exists(music_manifest_path):
|
| 572 |
return {"answer": "I'm sorry, there is no music in the library yet.", "sources": [], "audio_playback_url": None}
|
|
|
|
| 573 |
with open(music_manifest_path, "r") as f:
|
| 574 |
manifest = json.load(f)
|
|
|
|
| 575 |
if not manifest:
|
| 576 |
return {"answer": "I'm sorry, there is no music in the library yet.", "sources": [], "audio_playback_url": None}
|
| 577 |
+
|
| 578 |
found_song = None
|
| 579 |
query_lower = query.lower()
|
| 580 |
+
|
| 581 |
# 1. First, search for a specific Title or Artist mentioned in the query.
|
| 582 |
for song_id, data in manifest.items():
|
| 583 |
if data["title"].lower() in query_lower or data["artist"].lower() in query_lower:
|
| 584 |
found_song = data
|
| 585 |
break
|
| 586 |
+
|
| 587 |
+
# Define emotion tag here to make it available for the preamble later
|
| 588 |
+
detected_emotion_raw = kwargs.get("emotion_tag")
|
| 589 |
+
detected_emotion = detected_emotion_raw.lower() if detected_emotion_raw else ""
|
| 590 |
+
|
| 591 |
+
|
| 592 |
+
# 2. If not found, use the detected NLU tags to find the FIRST mood match.
|
| 593 |
if not found_song:
|
| 594 |
detected_emotion_raw = kwargs.get("emotion_tag")
|
| 595 |
detected_emotion = detected_emotion_raw.lower() if detected_emotion_raw else ""
|
| 596 |
detected_behavior_raw = kwargs.get("scenario_tag")
|
| 597 |
detected_behavior = detected_behavior_raw.lower() if detected_behavior_raw else ""
|
| 598 |
+
|
|
|
|
| 599 |
print(f"[DEBUG] Music Search: Using NLU tags. Behavior='{detected_behavior}', Emotion='{detected_emotion}'")
|
| 600 |
|
| 601 |
+
search_tags = [detected_emotion, detected_behavior]
|
| 602 |
|
| 603 |
for nlu_tag in search_tags:
|
| 604 |
if not nlu_tag or nlu_tag == "none": continue
|
| 605 |
|
|
|
|
| 606 |
core_nlu_word = nlu_tag.split('_')[0]
|
|
|
|
|
|
|
| 607 |
print(f" [DEBUG] Music Search Loop: Using core_nlu_word='{core_nlu_word}' for matching.")
|
|
|
|
| 608 |
|
| 609 |
for song_id, data in manifest.items():
|
| 610 |
+
for mood_tag in data.get("moods", []): # Use .get for safety
|
| 611 |
+
if not mood_tag or not isinstance(mood_tag, str): continue
|
| 612 |
mood_words = re.split(r'[\s/]', mood_tag.lower())
|
| 613 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 614 |
if core_nlu_word in mood_words:
|
| 615 |
found_song = data
|
| 616 |
break
|
| 617 |
if found_song: break
|
| 618 |
if found_song: break
|
|
|
|
| 619 |
|
| 620 |
# 3. If still not found, handle generic requests by playing a random song.
|
| 621 |
if not found_song:
|
| 622 |
+
print("[DEBUG] Music Search: No specific song or NLU match found. Selecting a random song.")
|
| 623 |
generic_keywords = ["music", "song", "something", "anything"]
|
| 624 |
if any(keyword in query_lower for keyword in generic_keywords):
|
| 625 |
random_song_id = random.choice(list(manifest.keys()))
|
| 626 |
found_song = manifest[random_song_id]
|
| 627 |
|
| 628 |
+
# Step 4: Construct the final response, adding the empathetic preamble if a song was found.
|
| 629 |
if found_song:
|
| 630 |
+
preamble_text = ""
|
| 631 |
+
# Only generate a preamble if there was a clear emotional context.
|
| 632 |
+
if detected_emotion and detected_emotion != "none":
|
| 633 |
+
preamble_prompt = MUSIC_PREAMBLE_PROMPT.format(emotion=detected_emotion, query=query)
|
| 634 |
+
preamble_text = call_llm([{"role": "user", "content": preamble_prompt}], temperature=0.7)
|
| 635 |
+
preamble_text = preamble_text.strip() + " "
|
| 636 |
+
|
| 637 |
+
action_text = f"Of course. Playing '{found_song['title']}' by {found_song['artist']} for you."
|
| 638 |
+
final_answer = preamble_text + action_text
|
| 639 |
+
|
| 640 |
+
return {"answer": final_answer, "sources": ["Personal Music Library"], "audio_playback_url": found_song['filepath']}
|
| 641 |
else:
|
| 642 |
return {"answer": "I couldn't find a song matching your request in the library.", "sources": [], "audio_playback_url": None}
|
|
|
|
| 643 |
# END --- MUSIC PLAYBACK LOGIC ---
|
| 644 |
|
| 645 |
p_name = patient_name or "the patient"
|