File size: 4,891 Bytes
35abf28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
from collections import Counter
import json

def predict_category(new_incident, k=3, supabase=None, embed_text=None):
    """

    Predice la categoría de un nuevo incidente basándose en similitudes con embeddings

    almacenados en Supabase. Retorna los niveles de clasificación, el id_case más similar

    y el tareas_json completo asociado.

    """

    if supabase is None or embed_text is None:
        raise ValueError("Debes proporcionar los parámetros 'supabase' y 'embed_text'.")

    # Obtener embedding del nuevo incidente
    query_emb = embed_text(new_incident)

    # Llamada al procedimiento remoto en Supabase
    result = supabase.rpc("match_case_email", {
        "query_embedding": query_emb,
        "match_count": k
    }).execute()


    matches = result.data
    if not matches:
        return {
            "niveles": None,
            "id_case": None,
            "tareas_json": None
        }

    # Mostrar matches y validar tareas_json
    for i, m in enumerate(matches):
        print(f"\n🔍 Match #{i+1} - ID_CASE: {m['id_case']} - Similaridad: {m['similarity']:.2f}")
        if m.get("tareas_json"):
            print("🧠 tareas_json detectado ✅")
            print(str(m["tareas_json"])[:500])  # solo muestra primeros 500 caracteres
        else:
            print("⚠️ tareas_json está vacío o es None ❌")

    # Clasificación por mayoría (niveles)
    niveles = {}
    for lvl in ["case_level_0", "case_level_1", "case_level_2", "case_level_3"]:
        valores = [m[lvl] for m in matches if m.get(lvl)]
        niveles[lvl.replace("case_", "nivel_")] = Counter(valores).most_common(1)[0][0] if valores else None

    print("\n📥 Input del cliente:")
    print(new_incident)

    print("\n🔎 Casos similares:")
    for m in matches:
        print(
            f"  ({m['similarity']:.2f}) [{m['id_case']}] {m['description_context']} → "
            f"{m['case_level_0']} / {m['case_level_1']} / {m['case_level_2']} / {m['case_level_3']}"
        )

    print("\n📊 Clasificación:")
    for key, val in niveles.items():
        print(f"  {key.capitalize()}: {val}")

    # Obtener el match con mayor similarity (siempre, tenga o no tareas_json)
    match_mas_similar = matches[0] if matches else None

    # Obtener el match con tareas_json válido y mejor similarity
    match_con_tareas = next(
        (m for m in sorted(matches, key=lambda x: x["similarity"], reverse=True)
        if m.get("tareas_json")),
        None
    )

    if not match_con_tareas:
        print("❌ Ningún match tiene tareas_json válido.")
        resumen = (
            f"📥 **Correo contextualizado:**\n{new_incident}\n\n"
            "🔎 **Casos similares encontrados (sin tareas_json):**\n"
            + "\n".join([
                f"({m['similarity']:.2f}) [ID_CASE {m['id_case']}] {m['description_context']} → "
                f"{m['case_level_0']} / {m['case_level_1']} / {m['case_level_2']} / {m['case_level_3']}"
                for m in matches
            ])
        )
        return {
            "niveles": niveles,
            "id_case": None,
            "tareas_json": None,
            "resumen": resumen
        }

    # Extraer el tareas_json completo (sin cortar)
    tareas_json = match_con_tareas["tareas_json"]
    id_case_con_tareas = match_con_tareas["id_case"]
    id_case_mas_similar = match_mas_similar["id_case"]

    # Extraer la clasificación del caso más similar (real)
    nivel_0 = match_mas_similar.get("case_level_0")
    nivel_1 = match_mas_similar.get("case_level_1")
    nivel_2 = match_mas_similar.get("case_level_2")
    nivel_3 = match_mas_similar.get("case_level_3")


    print(f"\n✅ Retornando tareas_json del caso más similar (ID_CASE: {id_case_mas_similar})")

    # 🔹 Construir resumen legible para interfaz
    resumen = f"📥 Interpretación del correo:\n{new_incident}\n\n"

    resumen += "🔎 Casos similares de Product Issues en Vibia encontrados desde Julio 2025:\n"
    for m in matches[:3]:
        resumen += (
            f"  🎯 Caso Nº {m['id_case']} (score: {m['similarity']:.2f}) : {m['description_context'][:400]}...\n"
            f"  Clasificación → {m['case_level_0']} / {m['case_level_1']} / {m['case_level_2']} / {m['case_level_3']}\n\n"
        )

    resumen += (
        f"🧠 Clasificación recomendada (basada en el caso más similar Nº {id_case_mas_similar})\n"
        f"  Level 0: {nivel_0}\n"
        f"  Level 1: {nivel_1}\n"
        f"  Level 2: {nivel_2}\n"
        f"  Level 3: {nivel_3}\n\n"
    )


    # ✅ Retornar ambos: resumen legible + datos técnicos
    return {
        "resumen": resumen,
        "niveles": niveles,
        "id_case": id_case_con_tareas,
        "tareas_json": tareas_json
    }