Spaces:
Sleeping
Sleeping
File size: 7,373 Bytes
f5eb34f | 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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | """
Aba de Exploração da Base de Conhecimento
Permite visualizar documentos armazenados e testar busca semântica
"""
import time
import gradio as gr
from src.database import DatabaseManager
from src.embeddings import EmbeddingManager
def create_exploration_tab(db_manager: DatabaseManager, embedding_manager: EmbeddingManager, session_id: str):
"""Cria aba de exploração da base de conhecimento"""
with gr.Tab(" Exploração da Base"):
gr.Markdown("""
## Exploração da Base de Conhecimento
Visualize documentos armazenados e teste a busca semântica:
- **Documentos**: Veja todos os chunks armazenados
- **Busca Semântica**: Teste queries e veja resultados ranqueados
- **Scores de Similaridade**: Entenda a relevância dos resultados
""")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### Estatísticas do Banco")
refresh_stats_btn = gr.Button(" Atualizar Estatísticas", size="sm")
db_stats_display = gr.JSON(label="Métricas da Base de Dados")
gr.Markdown("### Busca Semântica")
search_query = gr.Textbox(
label="Query de Busca",
placeholder="Digite sua pergunta ou termo de busca...",
lines=2
)
top_k_search = gr.Slider(
minimum=1,
maximum=20,
value=5,
step=1,
label="Top K (quantidade de resultados)"
)
search_btn = gr.Button(" Buscar", variant="primary")
with gr.Column(scale=2):
gr.Markdown("### Resultados da Busca")
search_status = gr.Markdown("Aguardando query de busca...")
with gr.Accordion(" Resultados Detalhados", open=True):
search_results = gr.Dataframe(
headers=["Rank", "Score", "Título", "Conteúdo (preview)"],
label="Documentos Recuperados",
wrap=True
)
with gr.Accordion(" Análise de Scores", open=False):
scores_analysis = gr.Markdown("Sem dados")
with gr.Accordion(" Conteúdo Completo", open=False):
full_content_display = gr.Textbox(
label="Conteúdo dos Resultados",
lines=15,
max_lines=30,
interactive=False
)
with gr.Row():
gr.Markdown("### 📚 Documentos Armazenados")
with gr.Row():
docs_limit = gr.Slider(
minimum=10,
maximum=200,
value=50,
step=10,
label="Limite de documentos a exibir"
)
refresh_docs_btn = gr.Button(" Carregar Documentos")
documents_display = gr.Dataframe(
headers=["ID", "Título", "Preview", "Data"],
label="Base de Conhecimento",
wrap=True
)
# Função para atualizar estatísticas
def refresh_stats():
stats = db_manager.get_database_stats()
if not stats:
return {"erro": "Não foi possível conectar ao banco"}
return stats
# Função para busca semântica
def semantic_search(query, k):
if not query or not query.strip():
return (
" Digite uma query para buscar",
[],
"Nenhuma análise disponível",
""
)
start_time = time.time()
# Gera embedding da query
query_embedding = embedding_manager.encode_single(query, normalize=True)
# Busca no banco (apenas na sessão do usuário)
results = db_manager.search_similar(query_embedding, k=int(k), session_id=session_id)
search_time = (time.time() - start_time) * 1000
if not results:
return (
f" Nenhum resultado encontrado (tempo: {search_time:.0f}ms)",
[],
"Sem resultados para análise",
""
)
# Prepara dados para tabela
table_data = []
full_contents = []
for i, result in enumerate(results, 1):
preview = result['content'][:100] + "..." if len(result['content']) > 100 else result['content']
table_data.append([
i,
f"{result['score']:.4f}",
result['title'],
preview
])
full_contents.append(f"--- Resultado {i} (Score: {result['score']:.4f}) ---")
full_contents.append(f"Título: {result['title']}")
full_contents.append(f"Conteúdo:\n{result['content']}\n")
# Análise de scores
scores = [r['score'] for r in results]
avg_score = sum(scores) / len(scores)
max_score = max(scores)
min_score = min(scores)
analysis_md = f"""
**Análise dos Scores de Similaridade**
- **Tempo de busca**: {search_time:.0f}ms
- **Resultados encontrados**: {len(results)}
- **Score máximo**: {max_score:.4f} (melhor match)
- **Score mínimo**: {min_score:.4f} (pior match)
- **Score médio**: {avg_score:.4f}
**Interpretação**:
- Scores próximos de 1.0 = alta similaridade
- Scores próximos de 0.5 = similaridade moderada
- Scores abaixo de 0.3 = baixa similaridade
"""
status_md = f" **Busca concluída** em {search_time:.0f}ms | {len(results)} resultados"
full_text = "\n".join(full_contents)
return status_md, table_data, analysis_md, full_text
# Função para carregar documentos
def load_documents(limit):
docs = db_manager.get_all_documents(limit=int(limit), session_id=session_id)
if not docs:
return []
table_data = []
for doc in docs:
preview = doc['content'][:80] + "..." if len(doc['content']) > 80 else doc['content']
created_str = str(doc['created_at']) if doc['created_at'] else "N/A"
table_data.append([
doc['id'],
doc['title'],
preview,
created_str
])
return table_data
# Conecta eventos
refresh_stats_btn.click(
fn=refresh_stats,
outputs=[db_stats_display]
)
search_btn.click(
fn=semantic_search,
inputs=[search_query, top_k_search],
outputs=[search_status, search_results, scores_analysis, full_content_display]
)
refresh_docs_btn.click(
fn=load_documents,
inputs=[docs_limit],
outputs=[documents_display]
)
return {
"search_query": search_query,
"search_btn": search_btn
}
|