fix: robust category matching — normalize dashes/accents + partial match
The AI often returns 'Guerre - Moyen-Orient' (ASCII dash) instead of 'Guerre — Moyen-Orient' (em-dash), causing exact match to fail silently. Fix: normalize unicode, collapse all dash variants, then try exact → normalized → partial substring matching. Also log the raw AI response for debugging, increase max_tokens 1200→2000. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -186,7 +186,7 @@ def evaluate_event_impacts(
|
||||
messages=[{"role": "user", "content": prompt}],
|
||||
response_format={"type": "json_object"},
|
||||
temperature=0.25,
|
||||
max_tokens=1200,
|
||||
max_tokens=2000,
|
||||
)
|
||||
raw = json.loads(response.choices[0].message.content)
|
||||
except Exception as e:
|
||||
@@ -198,25 +198,48 @@ def evaluate_event_impacts(
|
||||
key_driver = raw.get("key_driver", "")
|
||||
|
||||
# ── Use AI-chosen category ────────────────────────────────────────────────
|
||||
import unicodedata, re as _re
|
||||
|
||||
def _normalize(s: str) -> str:
|
||||
"""Lowercase, strip accents, collapse all dash/space variants."""
|
||||
s = unicodedata.normalize("NFD", s)
|
||||
s = "".join(c for c in s if unicodedata.category(c) != "Mn") # strip accents
|
||||
s = _re.sub(r"[–—―\-–—]", "-", s) # normalize dashes
|
||||
return s.lower().strip()
|
||||
|
||||
ai_cat_name = (raw.get("matched_category") or "").strip()
|
||||
if ai_cat_name and ai_cat_name.lower() != "none":
|
||||
# Validate against known categories (case-insensitive)
|
||||
matched = next((c for c in all_cats if c["name"].lower() == ai_cat_name.lower()), None)
|
||||
logger.info(f"[impact_service] AI returned matched_category='{ai_cat_name}' for event {event_id}")
|
||||
|
||||
if ai_cat_name and ai_cat_name.lower() not in ("none", "null", ""):
|
||||
# Exact match first, then normalized fuzzy match
|
||||
matched = (
|
||||
next((c for c in all_cats if c["name"].lower() == ai_cat_name.lower()), None)
|
||||
or next((c for c in all_cats if _normalize(c["name"]) == _normalize(ai_cat_name)), None)
|
||||
# Partial: AI name is contained in category name or vice versa
|
||||
or next((c for c in all_cats
|
||||
if _normalize(ai_cat_name) in _normalize(c["name"])
|
||||
or _normalize(c["name"]) in _normalize(ai_cat_name)), None)
|
||||
)
|
||||
if matched:
|
||||
matched_cat_name = matched["name"]
|
||||
logger.info(f"[impact_service] AI matched event {event_id} → category '{matched_cat_name}'")
|
||||
# Auto-update event sub_type if not already set
|
||||
logger.info(f"[impact_service] Matched event {event_id} → '{matched_cat_name}'")
|
||||
current_sub = (event.get("sub_type") or "").strip()
|
||||
if not current_sub:
|
||||
try:
|
||||
from services.database import update_market_event
|
||||
update_market_event(event_id, {**event, "sub_type": matched_cat_name,
|
||||
"source_refs": event.get("source_refs", [])})
|
||||
logger.info(f"[impact_service] Auto-set sub_type='{matched_cat_name}' on event {event_id}")
|
||||
from services.database import update_market_event, get_all_market_events
|
||||
# Re-fetch full event to get proper JSON fields
|
||||
full_ev = next((e for e in get_all_market_events() if e["id"] == event_id), None)
|
||||
if full_ev:
|
||||
refs = full_ev.get("source_refs") or "[]"
|
||||
if isinstance(refs, str):
|
||||
refs = json.loads(refs)
|
||||
update_market_event(event_id, {**full_ev, "sub_type": matched_cat_name,
|
||||
"source_refs": refs})
|
||||
logger.info(f"[impact_service] Auto-set sub_type='{matched_cat_name}' on event {event_id}")
|
||||
except Exception as _e:
|
||||
logger.warning(f"[impact_service] Could not auto-set sub_type: {_e}")
|
||||
else:
|
||||
logger.warning(f"[impact_service] AI returned unknown category '{ai_cat_name}' for event {event_id}")
|
||||
logger.warning(f"[impact_service] No category match for AI response '{ai_cat_name}' (event {event_id})")
|
||||
|
||||
cat_label = matched_cat_name or (event.get("sub_type") or "").strip() or (event.get("category") or "")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user