Spaces:
Sleeping
Sleeping
File size: 6,307 Bytes
a793867 0af955d d44b7ca 0af955d 3f0ee67 0af955d 82fdd67 0af955d d44b7ca 0af955d d44b7ca 0af955d d44b7ca 0af955d caf6350 3f0ee67 0af955d d44b7ca 0af955d d44b7ca 0af955d d44b7ca 0af955d d44b7ca 0af955d d44b7ca 0af955d d44b7ca 0af955d d44b7ca 0af955d d44b7ca 0af955d d44b7ca 0af955d |
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 141 |
import gradio as gr
import chromadb
import pandas as pd
from sentence_transformers import SentenceTransformer
import re
import numpy
# --- 1. SETUP MODELS AND DATABASE ---
print("Loading embedding model...")
#embedding_model = SentenceTransformer('rufimelo/bert-large-portuguese-cased-sts')
embedding_model = SentenceTransformer('jmbrito/ptbr-similarity-e5-small')
client = chromadb.Client()
collection = client.get_or_create_collection(
name="transcript_comparison_app",
metadata={"hnsw:space": "cosine"}
)
print("ChromaDB collection ready.")
# --- 2. NEW: DEFINE AND PRE-COMPUTE GUIDELINE PROFILES ---
# Define the positive phrases for each guideline you want to test
GUIDELINE_PROFILES = {
"Agent Empathy": [
"Sinto muito por esse transtorno.",
"Eu entendo completamente sua frustração.",
"Imagino como isso deve ser chato, vamos resolver.",
"Lamento que você tenha passado por isso.",
"Compreendo sua situação e peço desculpas pelo ocorrido."
],
"Problem Resolution Offer": [
"Para resolver isso, posso te oferecer duas opções.",
"Temos algumas alternativas para solucionar seu problema.",
"A solução que posso propor é a seguinte.",
"Vamos encontrar uma forma de resolver isso para você."
],
"Polite Closing": [
"Obrigado por sua ligação, tenha um ótimo dia.",
"Agradecemos seu contato.",
"Se precisar de mais alguma coisa, é só ligar.",
"Tenha uma excelente semana."
]
}
# Pre-compute the averaged profile embeddings when the app starts
print("Computing guideline profile embeddings...")
profile_embeddings = {}
for guideline_name, phrases in GUIDELINE_PROFILES.items():
phrase_embeddings = embedding_model.encode(phrases)
profile_embeddings[guideline_name] = numpy.mean(phrase_embeddings, axis=0)
print("✅ Guideline profiles are ready.")
# --- 3. CORE FUNCTIONS ---
def index_transcript(transcript_text):
# This function remains the same
if not transcript_text.strip():
return "Please paste a transcript before indexing.", pd.DataFrame()
chunks = re.split(r'(?<=[.!?])\s+', transcript_text)
chunks = [chunk.strip() for chunk in chunks if len(chunk.strip()) > 5]
ids = [f"chunk_{i}" for i in range(len(chunks))]
if collection.count() > 0:
collection.delete(ids=collection.get()['ids'])
collection.add(embeddings=embedding_model.encode(chunks).tolist(), documents=chunks, ids=ids)
indexed_df = pd.DataFrame({"Indexed Chunks": chunks})
return f"✅ Indexed {len(chunks)} chunks successfully!", indexed_df
def search_with_single_query(query):
# This is the original search method
if not query.strip():
return pd.DataFrame()
query_embedding = embedding_model.encode(query).tolist()
results = collection.query(query_embeddings=[query_embedding], n_results=3)
documents = results['documents'][0]
distances = results['distances'][0]
similarities = [f"{1 - dist:.2f}" for dist in distances]
return pd.DataFrame({"Similarity": similarities, "Matching Chunk": documents})
def search_with_profile(guideline_name):
# This is the NEW search method using the pre-computed profiles
if not guideline_name:
return pd.DataFrame()
profile_embedding = profile_embeddings[guideline_name].tolist()
results = collection.query(query_embeddings=[profile_embedding], n_results=3)
documents = results['documents'][0]
distances = results['distances'][0]
similarities = [f"{1 - dist:.2f}" for dist in distances]
return pd.DataFrame({"Similarity": similarities, "Matching Chunk": documents})
# --- 4. GRADIO INTERFACE FOR COMPARISON ---
sample_transcript = """Atendente: Olá, bem-vindo à EletroMax. Meu nome é Sofia, em que posso ajudar?
Cliente: Oi, Sofia. Eu comprei uma cafeteira no site de vocês na semana passada, e ela simplesmente parou de funcionar.
Atendente: Puxa, que chato isso. Lamento que você tenha passado por isso. Pode me informar o número do pedido para eu localizar sua compra?
Cliente: Claro, o número é 11223344. Estou bem decepcionado, usei a cafeteira só duas vezes.
Atendente: Entendo perfeitamente sua frustração. Para resolver isso, posso te oferecer duas opções.
Cliente: Prefiro receber um novo.
Atendente: Combinado. Obrigado por sua ligação, tenha um ótimo dia.
"""
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🔍 Search Method Comparison")
gr.Markdown("Index a transcript once, then search using both methods to compare the results.")
with gr.Row():
# Indexing column is the same
with gr.Column(scale=1):
transcript_input = gr.Textbox(lines=15, label="Paste Transcript Here", value=sample_transcript)
index_button = gr.Button("Index Transcript", variant="primary")
index_status = gr.Label()
indexed_preview = gr.DataFrame(headers=["Indexed Chunks"], label="Indexed Data Preview")
gr.HTML("<hr>") # Add a horizontal line for separation
with gr.Row():
# Column for the simple, single query search
with gr.Column():
gr.Markdown("### Method 1: Single Query Search")
query_input = gr.Textbox(label="Enter a Simple Query", placeholder="Ex: o agente foi empático?")
search_button_single = gr.Button("Search Single Query")
results_output_single = gr.DataFrame(label="Single Query Results")
# Column for the new, profile-based search
with gr.Column():
gr.Markdown("### Method 2: Guideline Profile Search")
profile_input = gr.Dropdown(choices=list(GUIDELINE_PROFILES.keys()), label="Select a Guideline Profile")
search_button_profile = gr.Button("Search with Profile", variant="primary")
results_output_profile = gr.DataFrame(label="Profile Search Results")
# Wire up the components
index_button.click(fn=index_transcript, inputs=[transcript_input], outputs=[index_status, indexed_preview])
search_button_single.click(fn=search_with_single_query, inputs=[query_input], outputs=[results_output_single])
search_button_profile.click(fn=search_with_profile, inputs=[profile_input], outputs=[results_output_profile])
demo.launch()
|