Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 12 additions & 52 deletions Backend/agent/agent.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import sys
import logging
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from agent.context import get_relevant_context_from_vector_store
Expand All @@ -12,6 +13,8 @@
from agent.handlers.weight import handle as handle_weight
from agent.handlers.symptoms import handle as handle_symptoms
from agent.handlers.guidelines import handle as handle_guidelines
from agent.handlers.medicine import handle as handle_medicine
from agent.handlers.blood_pressure import handle as handle_bp

from agent.vector_store import register_vector_store_updater, update_guidelines_in_vector_store

Expand All @@ -20,84 +23,41 @@
"weight": handle_weight,
"symptoms": handle_symptoms,
"guidelines": handle_guidelines,
"medicine": handle_medicine,
"blood_pressure": handle_bp,
}

class BabyNestAgent:
def __init__(self, db_path: str):
self.db_path = db_path
self.context_cache = get_context_cache(db_path)

# Register embedding refresh
register_vector_store_updater(update_guidelines_in_vector_store)

def get_user_context(self, user_id: str = "default"):
"""Get user context from cache."""
return self.context_cache.get_context(user_id)

def run(self, query: str, user_id: str = "default"):
if not query or not isinstance(query, str):
return "Invalid query. Please provide a valid string."
return "Invalid query."

try:
# Step 1: Get user context from cache (no DB hit if cache is valid)
user_context = self.get_user_context(user_id)
if not user_context:
return "User profile not found. Please complete your profile setup first."

# Step 2: Classify intent to see if a specialized handler should be used.
user_context = self.get_user_context(user_id) or {"current_week": 1}
intent = classify_intent(query)
logging.info("Detected Intent: %s", intent)

if intent in dispatch_intent:
# Pass user context to handlers
return dispatch_intent[intent](query, user_context)

# Step 3: Retrieve relevant context from the vector store based on the query.
context = get_relevant_context_from_vector_store(query)

# Step 4: Build the prompt with the retrieved context and user context, then run the LLM.
prompt = build_prompt(query, context, user_context)
return run_llm(prompt)

except Exception as e:
return f"Error processing query: {e}"

def update_cache(self, user_id: str = "default", data_type: str = None, operation: str = "update"):
"""
Intelligently update cache based on database changes.

Args:
user_id: User ID to update cache for
data_type: Type of data that changed ('profile', 'weight', 'medicine', 'symptoms', 'blood_pressure', 'discharge')
operation: Type of operation ('create', 'update', 'delete')
"""
self.context_cache.update_cache(user_id, data_type, operation)

def invalidate_cache(self, user_id: str = None):
"""Invalidate cache for specific user or all users."""
self.context_cache.invalidate_cache(user_id)

def refresh_cache_and_embeddings(self):
"""Manually refresh cache and regenerate embeddings after database changes."""
print("🔄 Manually refreshing cache and regenerating embeddings...")
self.context_cache.invalidate_cache()
update_guidelines_in_vector_store()

def get_cache_stats(self):
"""Get cache statistics for monitoring."""
return self.context_cache.get_cache_stats()

def cleanup_cache(self):
"""Manually trigger cache cleanup."""
self.context_cache._cleanup_old_cache_files()
self.context_cache._cleanup_memory_cache()
print("🧹 Cache cleanup completed")
logging.exception("Error processing query")
return f"Error processing query: {e!s}"

# Global agent instance
_agent_instance = None

def get_agent(db_path: str) -> BabyNestAgent:
"""Get or create the global agent instance."""
global _agent_instance
if _agent_instance is None:
_agent_instance = BabyNestAgent(db_path)
return _agent_instance

return _agent_instance
37 changes: 37 additions & 0 deletions Backend/agent/handlers/blood_pressure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import re
import sqlite3
from db.db import open_db

def handle(query, user_context):
"""
Parses blood pressure readings (systolic/diastolic) from the user query,
validates the numeric ranges, and records the data into the database logs.
"""
db = open_db()
try:

match = re.search(r'(\d{1,3})\s*(?:/|over|-)\s*(\d{1,3})', query, re.IGNORECASE)
if not match:
return "Please provide BP in format like '120/80' or '120 over 80'."

systolic = int(match.group(1))
diastolic = int(match.group(2))

if not (70 <= systolic <= 250 and 40 <= diastolic <= 150):
return "BP values out of valid range. Please check."

week = user_context.get('week_number', 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Inconsistent user context key across handlers.

Line 24 uses week_number but the agent (Backend/agent/agent.py line 46) provides current_week in the default context, and the prompt builder (Backend/agent/prompt.py) also expects current_week. This mismatch will cause the week to always default to 1.

🔧 Proposed fix for context key consistency
-        week = user_context.get('week_number', 1)
+        week = user_context.get('current_week', 1)

Apply the same fix to Backend/agent/handlers/medicine.py line 19 and Backend/agent/handlers/insights.py line 12.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
week = user_context.get('week_number', 1)
week = user_context.get('current_week', 1)
🤖 Prompt for AI Agents
In @Backend/agent/handlers/blood_pressure.py at line 24, The handler is reading
the wrong context key ('week_number') so it always defaults to 1; update the
user_context lookups to use 'current_week' instead: change the assignment that
uses user_context.get('week_number', 1) to user_context.get('current_week', 1)
in the blood_pressure handler and apply the same change in the medicine and
insights handlers so all handlers use the same 'current_week' key as the agent
and prompt builder.



db.execute(
'INSERT INTO blood_pressure_logs (week_number, systolic, diastolic, time) VALUES (?, ?, ?, datetime("now"))',
(week, systolic, diastolic)
)
db.commit()
return f"Recorded BP: {systolic}/{diastolic} for week {week}."
except sqlite3.Error as e:
return f"Database error: {str(e)}"
except Exception as e:
return f"Unexpected error: {str(e)}"
finally:
db.close()
35 changes: 35 additions & 0 deletions Backend/agent/handlers/medicine.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import re
import sqlite3
from db.db import open_db

def handle(query, user_context):
"""
Extracts medicine name, dosage, and time from user query using regex
and persists the record into the weekly_medicine database table.
"""
db = open_db()
try:

name_match = re.search(r'(?:took|taking|take)\s+([\w\s\-()]+?)(?:\s+\d|\s+at|$)', query, re.IGNORECASE)
name = name_match.group(1).strip() if name_match else "Medicine"

dose_match = re.search(r'(\d+\s*(?:tablet|pill|capsule|mg|ml|unit)s?)', query, re.IGNORECASE)
dose = dose_match.group(1).strip() if dose_match else "1 unit"

time_match = re.search(r'at\s+(\d{1,2}(?::\d{2})?\s*(?:am|pm)?)', query, re.IGNORECASE)
time = time_match.group(1) if time_match else "00:00"

week = user_context.get('week_number', 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Same context key inconsistency.

This line has the same issue as Backend/agent/handlers/blood_pressure.py line 24. Use current_week instead of week_number to match the context structure provided by the agent.

🤖 Prompt for AI Agents
In @Backend/agent/handlers/medicine.py at line 19, The code reads the week from
the wrong context key: change user_context.get('week_number', 1) to
user_context.get('current_week', 1) so the handler in medicine.py uses the same
context key as the blood_pressure handler; update any dependent uses of the
local variable week if they assume the new key but no further logic changes are
required.


db.execute(
'INSERT INTO weekly_medicine (week_number, name, dose, time) VALUES (?, ?, ?, ?)',
(week, name, dose, time)
)
db.commit()
return f"Logged {name} ({dose}) at {time} for week {week}."
except sqlite3.Error as e:
return f"Database error: {str(e)}"
except Exception as e:
return f"Unexpected error: {str(e)}"
finally:
db.close()
8 changes: 6 additions & 2 deletions Backend/agent/intent.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# agent/intent.py

def classify_intent(query: str) -> str:
if not query or not isinstance(query, str):
return "general"
Expand All @@ -10,6 +10,10 @@ def classify_intent(query: str) -> str:
return "weight"
elif "symptom" in query:
return "symptoms"
elif "medicine" in query or "took" in query or "tablet" in query or "pill" in query:
return "medicine"
Comment on lines +16 to +17
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

The keyword "took" is too generic and may cause false positives.

The word "took" appears in many non-medicine contexts (e.g., "I took a walk", "I took notes"). Consider requiring a combination of keywords or using a regex pattern that looks for medicine-related context.

Suggested improvement
-    elif "medicine" in query or "took" in query or "tablet" in query or "pill" in query:
+    elif "medicine" in query or "tablet" in query or "pill" in query or ("took" in query and any(kw in query for kw in ["mg", "tablet", "pill", "capsule", "dose"])):
         return "medicine"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
elif "medicine" in query or "took" in query or "tablet" in query or "pill" in query:
return "medicine"
elif "medicine" in query or "tablet" in query or "pill" in query or ("took" in query and any(kw in query for kw in ["mg", "tablet", "pill", "capsule", "dose"])):
return "medicine"
🤖 Prompt for AI Agents
In @Backend/agent/intent.py around lines 13 - 14, The branch that returns
"medicine" currently triggers on the generic token "took", which causes false
positives; update the condition in the intent detection (the elif that returns
"medicine") to either remove the standalone "took" check or require it to match
a medicine context (e.g., use a regex like r"\btook (a
)?(pill|tablet|dose|medicine|medication)\b" or require both "took" and a
medicine keyword present), so the intent only fires when "took" appears with a
medication-related word.

elif "bp" in query or "blood pressure" in query or "/" in query:
return "blood_pressure"
Comment on lines +18 to +19
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Overly broad "/" pattern will cause false positives.

The "/" character alone as a trigger for blood_pressure intent will match URLs, date formats (e.g., "1/2/2026"), file paths, and fractions. This could misclassify many unrelated queries.

Additionally, the ordering creates an issue: a query like "I took my BP 120/80" would be classified as "medicine" (due to "took") rather than "blood_pressure".

Proposed fix: Use a more specific BP pattern
-    elif "bp" in query or "blood pressure" in query or "/" in query:
+    elif "bp" in query or "blood pressure" in query or re.search(r'\d{2,3}\s*/\s*\d{2,3}', query):
         return "blood_pressure"

This requires adding import re at the top of the file. The pattern specifically matches numeric BP readings like "120/80".

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In @Backend/agent/intent.py around lines 15 - 16, The current condition checking
`elif "bp" in query or "blood pressure" in query or "/" in query` is too broad
and causes false positives and misordering with the `medicine` intent; import
the `re` module, replace the `"/"` check with a regex that matches numeric BP
formats (e.g., use re.search for a pattern like r'\b\d{2,3}/\d{2,3}\b' to detect
readings such as "120/80") in the `elif "bp" in query or "blood pressure" in
query ...` branch that returns "blood_pressure", and move this blood_pressure
check to run before the branch that returns "medicine" so inputs like "I took my
BP 120/80" are classified as "blood_pressure".

elif "vaccine" in query or "guideline" in query or "what tests" in query or "recommend" in query:
return "guidelines"
return "general"
return "general"
Loading