Marylene commited on
Commit
05868b2
·
verified ·
1 Parent(s): be4fdb8

ajout libellé COICOP sortie

Browse files
Files changed (1) hide show
  1. quick_deploy_agent.py +54 -14
quick_deploy_agent.py CHANGED
@@ -17,6 +17,7 @@ FALLBACK_MODELS = [
17
  ]
18
 
19
 
 
20
  # ---- Mini référentiel COICOP (démo) ----
21
  COICOP_ITEMS = [
22
  {"code": "01.1.4.5.1", "label": "Laits caillés, fromage blanc, petites crèmes fromagères"},
@@ -29,6 +30,11 @@ COICOP_ITEMS = [
29
  {"code": "01.1.1.3", "label": "Pâtes, couscous et produits similaires"},
30
  ]
31
 
 
 
 
 
 
32
  def normalize_txt(s: str) -> str:
33
  if not s: return ""
34
  s = s.upper()
@@ -564,11 +570,14 @@ class Resolve(Tool):
564
  output_type = "object"
565
 
566
  def _fallback_min3(self):
567
- # ordre neutre et scores modestes
568
  base = [
569
- {"code":"01.1.4.5.2","score_final":0.50,"votes":0,"evidences":["fallback (aucune évidence)"]},
570
- {"code":"01.1.4.5.3","score_final":0.49,"votes":0,"evidences":["fallback (aucune évidence)"]},
571
- {"code":"01.1.4.5.5","score_final":0.48,"votes":0,"evidences":["fallback (aucune évidence)"]},
 
 
 
572
  ]
573
  return base
574
 
@@ -586,21 +595,36 @@ class Resolve(Tool):
586
  if isinstance(s, str):
587
  try: data = json.loads(s)
588
  except Exception: data = {}
589
- if not isinstance(data, dict): continue
 
590
  for c in data.get("candidates", []):
591
- code = c.get("code");
592
- if not code: continue
 
593
  score = float(c.get("score", c.get("score_final", 0.0)))
594
  why = c.get("why", "") or c.get("label", "")
 
 
 
595
  if code not in bucket:
596
- bucket[code] = {"code":code,"score":score,"votes":1,"evidences":[why] if why else []}
 
 
 
 
 
 
597
  else:
598
  bucket[code]["score"] = max(bucket[code]["score"], score)
599
  bucket[code]["votes"] += 1
600
- if why: bucket[code]["evidences"].append(why)
 
 
 
 
601
 
602
  if not bucket:
603
- # 🔁 Fallback global si VRAIMENT rien n'a pu être agrégé
604
  ranked = self._fallback_min3()
605
  final = ranked[0]
606
  alts = ranked[1:]
@@ -615,23 +639,39 @@ class Resolve(Tool):
615
  # Top fusionné : au moins 3
616
  min_top = max(3, topn if isinstance(topn, int) and topn>0 else 3)
617
  if len(ranked) < min_top:
618
- # compléter avec un petit fallback sans dupliquer
619
  already = {r["code"] for r in ranked}
620
  for fb in self._fallback_min3():
621
- if len(ranked) >= min_top: break
622
- if fb["code"] in already: continue
 
 
623
  ranked.append(fb)
624
 
 
625
  final = ranked[0]
626
  alts = ranked[1:1+min_top-1]
627
 
 
 
 
 
 
628
  ev = final.get("evidences", [])
629
  exp = (
630
  f"Choix {final['code']} (score {final['score_final']:.2f}) – votes={final.get('votes',0)} – raisons: {', '.join(sorted(set(ev)))}"
631
  if ev else
632
  f"Choix {final['code']} (score {final['score_final']:.2f}) – fallback partiel."
633
  )
634
- return {"final": final, "alternatives": alts, "candidates_top": ranked[:min_top], "explanation": exp}
 
 
 
 
 
 
 
 
635
 
636
 
637
 
 
17
  ]
18
 
19
 
20
+ # ---- Mini référentiel COICOP (démo) ----
21
  # ---- Mini référentiel COICOP (démo) ----
22
  COICOP_ITEMS = [
23
  {"code": "01.1.4.5.1", "label": "Laits caillés, fromage blanc, petites crèmes fromagères"},
 
30
  {"code": "01.1.1.3", "label": "Pâtes, couscous et produits similaires"},
31
  ]
32
 
33
+ # ✅ Map code -> libellé (avec un libellé pour le code générique)
34
+ CODE_TO_LABEL = {it["code"]: it["label"] for it in COICOP_ITEMS}
35
+ CODE_TO_LABEL.setdefault("01.1.4.5", "Fromages (générique)")
36
+
37
+
38
  def normalize_txt(s: str) -> str:
39
  if not s: return ""
40
  s = s.upper()
 
570
  output_type = "object"
571
 
572
  def _fallback_min3(self):
573
+ # ordre neutre et scores modestes (avec libellés)
574
  base = [
575
+ {"code":"01.1.4.5.2","label": CODE_TO_LABEL.get("01.1.4.5.2",""),
576
+ "score_final":0.50,"votes":0,"evidences":["fallback (aucune évidence)"]},
577
+ {"code":"01.1.4.5.3","label": CODE_TO_LABEL.get("01.1.4.5.3",""),
578
+ "score_final":0.49,"votes":0,"evidences":["fallback (aucune évidence)"]},
579
+ {"code":"01.1.4.5.5","label": CODE_TO_LABEL.get("01.1.4.5.5",""),
580
+ "score_final":0.48,"votes":0,"evidences":["fallback (aucune évidence)"]},
581
  ]
582
  return base
583
 
 
595
  if isinstance(s, str):
596
  try: data = json.loads(s)
597
  except Exception: data = {}
598
+ if not isinstance(data, dict):
599
+ continue
600
  for c in data.get("candidates", []):
601
+ code = c.get("code")
602
+ if not code:
603
+ continue
604
  score = float(c.get("score", c.get("score_final", 0.0)))
605
  why = c.get("why", "") or c.get("label", "")
606
+ # ✅ libellé via le mapping (fallback sur un éventuel label déjà présent)
607
+ label = CODE_TO_LABEL.get(code, c.get("label", ""))
608
+
609
  if code not in bucket:
610
+ bucket[code] = {
611
+ "code": code,
612
+ "label": label, # <-- ajouté
613
+ "score": score,
614
+ "votes": 1,
615
+ "evidences": [why] if why else []
616
+ }
617
  else:
618
  bucket[code]["score"] = max(bucket[code]["score"], score)
619
  bucket[code]["votes"] += 1
620
+ if why:
621
+ bucket[code]["evidences"].append(why)
622
+ # garde un label si absent
623
+ if not bucket[code].get("label"):
624
+ bucket[code]["label"] = label
625
 
626
  if not bucket:
627
+ # 🔁 Fallback global si VRAIMENT rien n'a pu être agrégé (avec labels)
628
  ranked = self._fallback_min3()
629
  final = ranked[0]
630
  alts = ranked[1:]
 
639
  # Top fusionné : au moins 3
640
  min_top = max(3, topn if isinstance(topn, int) and topn>0 else 3)
641
  if len(ranked) < min_top:
642
+ # compléter avec un petit fallback sans dupliquer (avec labels)
643
  already = {r["code"] for r in ranked}
644
  for fb in self._fallback_min3():
645
+ if len(ranked) >= min_top:
646
+ break
647
+ if fb["code"] in already:
648
+ continue
649
  ranked.append(fb)
650
 
651
+ # Sélection finale
652
  final = ranked[0]
653
  alts = ranked[1:1+min_top-1]
654
 
655
+ # Sécurise le label si jamais manquant (ne change rien au scoring)
656
+ final.setdefault("label", CODE_TO_LABEL.get(final["code"], ""))
657
+ for a in alts:
658
+ a.setdefault("label", CODE_TO_LABEL.get(a["code"], ""))
659
+
660
  ev = final.get("evidences", [])
661
  exp = (
662
  f"Choix {final['code']} (score {final['score_final']:.2f}) – votes={final.get('votes',0)} – raisons: {', '.join(sorted(set(ev)))}"
663
  if ev else
664
  f"Choix {final['code']} (score {final['score_final']:.2f}) – fallback partiel."
665
  )
666
+
667
+ # candidates_top avec labels assurés
668
+ candidates_top = []
669
+ for r in ranked[:min_top]:
670
+ r.setdefault("label", CODE_TO_LABEL.get(r["code"], ""))
671
+ candidates_top.append(r)
672
+
673
+ return {"final": final, "alternatives": alts, "candidates_top": candidates_top, "explanation": exp}
674
+
675
 
676
 
677