Spaces:
Sleeping
Sleeping
Upload 2 files
Browse files- config.py +2 -1
- embeddings.py +19 -12
config.py
CHANGED
|
@@ -19,4 +19,5 @@ CHROMA_COLLECTION_NAME: str = "faq"
|
|
| 19 |
SIMILARITY_THRESHOLD: float = float(os.getenv("SIMILARITY_THRESHOLD", "0.80"))
|
| 20 |
|
| 21 |
TOP_K = 3
|
| 22 |
-
CROSS_ENCODER_MODEL_NAME = "cross-encoder/mmarco-mMiniLMv2-L12-H384-v1"
|
|
|
|
|
|
| 19 |
SIMILARITY_THRESHOLD: float = float(os.getenv("SIMILARITY_THRESHOLD", "0.80"))
|
| 20 |
|
| 21 |
TOP_K = 3
|
| 22 |
+
CROSS_ENCODER_MODEL_NAME = "cross-encoder/mmarco-mMiniLMv2-L12-H384-v1"
|
| 23 |
+
CROSS_ENCODER_THRESHOLD: float = float(os.getenv("CROSS_ENCODER_THRESHOLD", "0.20"))
|
embeddings.py
CHANGED
|
@@ -23,11 +23,8 @@ import chromadb
|
|
| 23 |
from sentence_transformers import SentenceTransformer, CrossEncoder
|
| 24 |
import torch
|
| 25 |
from config import (
|
| 26 |
-
CHROMA_COLLECTION_NAME,
|
| 27 |
-
|
| 28 |
-
SIMILARITY_THRESHOLD,
|
| 29 |
-
TOP_K,
|
| 30 |
-
CROSS_ENCODER_MODEL_NAME
|
| 31 |
)
|
| 32 |
from faq_loader import FAQEntry
|
| 33 |
|
|
@@ -204,6 +201,7 @@ class EmbeddingManager:
|
|
| 204 |
# Récupérer la question et les paramètres depuis le payload
|
| 205 |
question = payload.question
|
| 206 |
similarity_threshold = payload.similarity_threshold if payload.similarity_threshold is not None else SIMILARITY_THRESHOLD
|
|
|
|
| 207 |
top_k = getattr(payload, "top_k", None) or TOP_K
|
| 208 |
|
| 209 |
# Générer l'embedding de la question
|
|
@@ -265,12 +263,22 @@ class EmbeddingManager:
|
|
| 265 |
for candidate, cross_score in zip(candidates, cross_scores):
|
| 266 |
candidate.cross_encoder_score = float(cross_score)
|
| 267 |
|
| 268 |
-
# Sélectionner le meilleur score cross-encoder
|
| 269 |
-
|
| 270 |
candidates,
|
| 271 |
-
key=lambda c: c.cross_encoder_score
|
|
|
|
|
|
|
|
|
|
| 272 |
)
|
| 273 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 274 |
logger.info(
|
| 275 |
"Candidats re-classés par cross-encoder: "
|
| 276 |
+ ", ".join(
|
|
@@ -278,10 +286,9 @@ class EmbeddingManager:
|
|
| 278 |
)
|
| 279 |
)
|
| 280 |
|
| 281 |
-
|
| 282 |
-
if best_candidate.cross_encoder_score is None or best_candidate.cross_encoder_score < cross_encoder_threshold:
|
| 283 |
logger.info(
|
| 284 |
-
f"
|
| 285 |
f"< seuil {cross_encoder_threshold}. Question: {question}"
|
| 286 |
)
|
| 287 |
return AnswerOutput(
|
|
@@ -294,7 +301,7 @@ class EmbeddingManager:
|
|
| 294 |
list_candidates=candidates,
|
| 295 |
confidence=False,
|
| 296 |
)
|
| 297 |
-
|
| 298 |
|
| 299 |
logger.info(
|
| 300 |
f"Match trouvé - Theme: {best_candidate.theme}, "
|
|
|
|
| 23 |
from sentence_transformers import SentenceTransformer, CrossEncoder
|
| 24 |
import torch
|
| 25 |
from config import (
|
| 26 |
+
CHROMA_COLLECTION_NAME, MODEL_NAME, SIMILARITY_THRESHOLD,
|
| 27 |
+
TOP_K, CROSS_ENCODER_MODEL_NAME, CROSS_ENCODER_THRESHOLD
|
|
|
|
|
|
|
|
|
|
| 28 |
)
|
| 29 |
from faq_loader import FAQEntry
|
| 30 |
|
|
|
|
| 201 |
# Récupérer la question et les paramètres depuis le payload
|
| 202 |
question = payload.question
|
| 203 |
similarity_threshold = payload.similarity_threshold if payload.similarity_threshold is not None else SIMILARITY_THRESHOLD
|
| 204 |
+
cross_encoder_threshold = payload.cross_encoder_threshold if payload.cross_encoder_threshold is not None else CROSS_ENCODER_THRESHOLD
|
| 205 |
top_k = getattr(payload, "top_k", None) or TOP_K
|
| 206 |
|
| 207 |
# Générer l'embedding de la question
|
|
|
|
| 263 |
for candidate, cross_score in zip(candidates, cross_scores):
|
| 264 |
candidate.cross_encoder_score = float(cross_score)
|
| 265 |
|
| 266 |
+
# Sélectionner le meilleur score cross-encoder et le second meilleur pour calculer l'écart entre les 2
|
| 267 |
+
ranked_candidates = sorted(
|
| 268 |
candidates,
|
| 269 |
+
key=lambda c: c.cross_encoder_score
|
| 270 |
+
if c.cross_encoder_score is not None
|
| 271 |
+
else float("-inf"),
|
| 272 |
+
reverse=True,
|
| 273 |
)
|
| 274 |
|
| 275 |
+
best_candidate = ranked_candidates[0]
|
| 276 |
+
second_candidate = ranked_candidates[1] if len(ranked_candidates) > 1 else None
|
| 277 |
+
|
| 278 |
+
best_score = best_candidate.cross_encoder_score or 0.0
|
| 279 |
+
relative_gap = abs((best_score - second_candidate.cross_encoder_score) / best_score) \
|
| 280 |
+
if second_candidate and best_score != 0 else 0
|
| 281 |
+
|
| 282 |
logger.info(
|
| 283 |
"Candidats re-classés par cross-encoder: "
|
| 284 |
+ ", ".join(
|
|
|
|
| 286 |
)
|
| 287 |
)
|
| 288 |
|
| 289 |
+
if best_candidate.cross_encoder_score is None or relative_gap < cross_encoder_threshold:
|
|
|
|
| 290 |
logger.info(
|
| 291 |
+
f"GAP entre 1er et 2ème meilleurs scores: {relative_gap:.3f} "
|
| 292 |
f"< seuil {cross_encoder_threshold}. Question: {question}"
|
| 293 |
)
|
| 294 |
return AnswerOutput(
|
|
|
|
| 301 |
list_candidates=candidates,
|
| 302 |
confidence=False,
|
| 303 |
)
|
| 304 |
+
|
| 305 |
|
| 306 |
logger.info(
|
| 307 |
f"Match trouvé - Theme: {best_candidate.theme}, "
|