diabetesLLM / core /clarifying.py
KS00Max's picture
adjusted for better response
a417583
from __future__ import annotations
import math
from typing import Dict, List, Optional
from .models import ClarifyingQuestion, IntentMeta
def _entropy(probs: List[float]) -> float:
return -sum(p * math.log(p + 1e-12) for p in probs if p > 0)
def _find_question(questions: List[ClarifyingQuestion], topic_groups: List[str]) -> Optional[ClarifyingQuestion]:
topic_set = set(topic_groups)
for q in questions:
if not q.applies_to_topic_groups:
return q
if topic_set.intersection(set(q.applies_to_topic_groups)):
return q
return questions[0] if questions else None
def select_clarifying(
patient_state: Dict[str, object],
intent_scores: Dict[str, float],
intents: Dict[str, IntentMeta],
highlevel_questions: List[ClarifyingQuestion],
detail_questions: List[ClarifyingQuestion],
) -> Optional[ClarifyingQuestion]:
state = patient_state or {}
# Check if topic is already determined from patient state
current_topic = state.get("topic_group")
topic_already_set = current_topic and current_topic not in ("other", "unknown", "")
if not intent_scores:
# No intent candidates - only ask highlevel if topic not yet set
if not topic_already_set:
return highlevel_questions[0] if highlevel_questions else None
# Topic is set but no intents matched - proceed to answer
return None
sorted_pairs = sorted(intent_scores.items(), key=lambda x: x[1], reverse=True)
top_id, top_score = sorted_pairs[0]
top2 = sorted_pairs[1][1] if len(sorted_pairs) > 1 else 0.0
probs = [s for _, s in sorted_pairs]
ent = _entropy(probs)
inferred_topics = list({intents[intent_id].topic_group for intent_id, _ in sorted_pairs if intent_id in intents})
# Only ask highlevel question for TRULY AMBIGUOUS cases:
# - Topic not already set by user
# - Top intent score is very low (< 0.30)
# - High entropy (uncertainty across multiple topics)
# - Multiple topics with no clear winner
truly_ambiguous = (
top_score < 0.30 and
ent > 1.2 and
len(inferred_topics) > 1
)
if not topic_already_set and truly_ambiguous:
return _find_question(highlevel_questions, inferred_topics)
# Determine the topic to use: prefer user-set topic, fallback to inferred
best_topic = current_topic if topic_already_set else (intents[top_id].topic_group if top_id in intents else None)
def _detail_for(topic: str) -> Optional[ClarifyingQuestion]:
return _find_question(detail_questions, [topic])
# Ask detail questions only if the specific state info is missing
# These questions help provide targeted, situation-specific advice
if best_topic == "sick_day" and state.get("food_intake_level") in ("unknown", "", None):
return _detail_for("sick_day")
if best_topic == "travel" and state.get("travel_overseas") is None:
return _detail_for("travel")
if best_topic == "diet" and state.get("insulin_experience") in ("unknown", "", None):
return _detail_for("diet")
if best_topic in ("complication", "hypoglycemia") and state.get("hypoglycemia_concern") in ("unknown", "", None):
return _detail_for("complication")
if best_topic == "neuropathy" and state.get("acute_neurologic_red_flags") in (None, ""):
return _detail_for("neuropathy")
if best_topic == "footcare" and state.get("foot_infection_risk") in (None, ""):
return _detail_for("footcare")
# No clarifying needed - proceed to answer generation
return None