File size: 4,000 Bytes
9a9ecdb
 
 
81ba821
b222eb2
9a9ecdb
 
 
 
1c2502c
81ba821
b222eb2
81ba821
1c2502c
81ba821
9a9ecdb
81ba821
9a9ecdb
 
1c2502c
8ed82c4
81ba821
 
1c2502c
b222eb2
 
 
 
1c2502c
9a9ecdb
 
 
 
1c2502c
81ba821
9a9ecdb
 
 
 
 
81ba821
1c2502c
 
b222eb2
630354a
ac49ae9
b222eb2
1c2502c
 
630354a
b222eb2
9a9ecdb
 
b222eb2
7b2d825
 
81ba821
b222eb2
81ba821
 
b222eb2
ac49ae9
b222eb2
81ba821
 
ac49ae9
b222eb2
 
ac49ae9
81ba821
 
b222eb2
630354a
b222eb2
630354a
 
b222eb2
 
630354a
b222eb2
630354a
81ba821
b222eb2
 
81ba821
b222eb2
ac49ae9
 
 
b222eb2
 
 
 
 
5135aaf
00d2e51
b222eb2
ac49ae9
 
 
 
b222eb2
630354a
b222eb2
9a9ecdb
1c2502c
81ba821
b222eb2
81ba821
1c2502c
ac49ae9
b222eb2
 
 
 
81ba821
9a9ecdb
b222eb2
 
 
 
9a9ecdb
81ba821
b222eb2
 
 
 
5135aaf
ac49ae9
b222eb2
 
 
 
 
 
ac49ae9
9a9ecdb
630354a
b222eb2
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
130
131
132
133
134
135
136
137
138
139
140
import os
import gradio as gr
import joblib
import numpy as np
from transformers import pipeline
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression


# ============================================================
# 1. Baseline de Sentimentos
# ============================================================

BASELINE_PATH = "baseline_pipe.pkl"

def train_small_baseline(save_path=BASELINE_PATH, max_samples=8000):
    from datasets import load_dataset
    import pandas as pd

    ds = load_dataset("amazon_polarity", split="train")
    ds_small = ds.shuffle(seed=42).select(range(max_samples))
    df = pd.DataFrame({"text": ds_small["content"], "label": ds_small["label"]})

    pipe = Pipeline([
        ("tfidf", TfidfVectorizer(max_features=20000)),
        ("clf", LogisticRegression(max_iter=1000)),
    ])

    pipe.fit(df["text"], df["label"])
    joblib.dump(pipe, save_path)
    return pipe


def load_baseline():
    if os.path.exists(BASELINE_PATH):
        return joblib.load(BASELINE_PATH)
    return train_small_baseline()


baseline_model = load_baseline()


def classify_only(text):
    text = (text or "").strip()
    if not text:
        return "Erro: digite um texto."

    proba = baseline_model.predict_proba([text])[0]
    pred = int(np.argmax(proba))
    lbl = "positivo" if pred == 1 else "negativo"
    conf = float(np.max(proba))

    return f"Sentimento: {lbl}\nConfiança: {conf:.3f}"


# ============================================================
# 2. IA Generativa - FLAN T5 (modelo aberto)
# ============================================================

generator = pipeline(
    "text2text-generation",
    model="google/flan-t5-base",
)

SYSTEM_PROMPT = (
    "Você é um atendente virtual educado e empático. "
    "Responda SEMPRE em português do Brasil."
)


def chatbot_logic(user_message, history):
    """
    Função usada pelo ChatInterface — history é automático.
    """

    # Detecta sentimento
    proba = baseline_model.predict_proba([user_message])[0]
    pred = int(np.argmax(proba))
    sent = "positivo" if pred == 1 else "negativo"
    conf = float(np.max(proba))

    if sent == "negativo":
        orient = "O cliente está insatisfeito. Mostre empatia, peça desculpas e ofereça ajuda."
    else:
        orient = "O cliente está satisfeito. Agradeça e incentive a continuar usando o serviço."

    prompt = (
        f"{SYSTEM_PROMPT}\n\n"
        f"Contexto de sentimento:\n- Sentimento: {sent}\n- Confiança: {conf:.3f}\n"
        f"Orientação: {orient}\n\n"
        f"Histórico prévio:\n{history}\n\n"
        f"Mensagem do cliente: {user_message}\n\n"
        "Gere uma resposta educada e profissional."
    )

    out = generator(
        prompt,
        max_length=200,
        do_sample=True,
        temperature=0.7,
    )[0]["generated_text"]

    return out


# ============================================================
# 3. Interface Gradio — ChatInterface = sem bugs!
# ============================================================


with gr.Blocks(title="Chatbot de Sentimentos") as demo:

    gr.Markdown("""
# Chatbot de Sentimentos (ML + IA Generativa)
**Professor Rodrigo — Projeto Final ML & DL**

- Classificação: TF-IDF + Regressão Logística  
- Geração: `google/flan-t5-base`  
- Sem API aberta (evita erro "No API found")
    """)

    with gr.Tab("Análise de Sentimento"):
        txt = gr.Textbox(lines=4, label="Digite um comentário")
        out = gr.Textbox(lines=3, label="Resultado")
        btn = gr.Button("Analisar")
        btn.click(classify_only, txt, out)

    with gr.Tab("Chatbot (Análise + Resposta)"):
        gr.ChatInterface(
            fn=chatbot_logic,
            title="Atendente Virtual",
            examples=["O produto chegou quebrado", "Amei o serviço!"],
            retry_btn=None,
            undo_btn=None,
        )


demo.queue(api_open=False).launch()