File size: 13,445 Bytes
89b9bf6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
"""
🧠 Agent Pruning Lab
Demonstração visual de Context Pruning com Provence e Semantic Highlighting
para sistemas de Agentes LLM - Hugging Face Space
"""

import streamlit as st
import json
import random
from components.visualizer import SemanticHighlighter
from components.provence_wrapper import ProvencePruner
from components.agent_simulator import AgentSimulator

# Configuração da página
st.set_page_config(
    page_title="🧠 Agent Pruning Lab",
    page_icon="✂️",
    layout="wide",
    initial_sidebar_state="expanded"
)

# CSS Customizado
st.markdown("""
<style>
    .main-header {
        font-size: 3rem;
        font-weight: 800;
        background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        margin-bottom: 0.5rem;
    }
    .sub-header {
        font-size: 1.2rem;
        color: #666;
        margin-bottom: 2rem;
    }
    .metric-card {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        padding: 1.5rem;
        border-radius: 15px;
        color: white;
        text-align: center;
        box-shadow: 0 10px 30px rgba(102, 126, 234, 0.3);
    }
    .metric-value {
        font-size: 2.5rem;
        font-weight: 700;
    }
    .metric-label {
        font-size: 0.9rem;
        opacity: 0.9;
    }
    .pruned-text {
        background-color: #ff6b6b20;
        text-decoration: line-through;
        color: #999;
        padding: 2px 4px;
        border-radius: 3px;
    }
    .kept-text {
        background-color: #51cf6620;
        color: #2b8a3e;
        padding: 2px 4px;
        border-radius: 3px;
        font-weight: 500;
    }
    .highlight-low { background-color: #fff3bf; }
    .highlight-med { background-color: #ffd8a8; }
    .highlight-high { background-color: #ff8787; }
    .agent-thought {
        background: #f8f9fa;
        border-left: 4px solid #667eea;
        padding: 1rem;
        margin: 0.5rem 0;
        border-radius: 0 8px 8px 0;
        font-family: 'Courier New', monospace;
    }
    .stTabs [data-baseweb="tab-list"] {
        gap: 8px;
    }
    .stTabs [data-baseweb="tab"] {
        background-color: #f0f2f6;
        border-radius: 8px 8px 0 0;
        padding: 10px 20px;
    }
</style>
""", unsafe_allow_html=True)

# Inicialização dos componentes
@st.cache_resource
def load_models():
    return ProvencePruner(), SemanticHighlighter(), AgentSimulator()

pruner, highlighter, agent = load_models()

# Header
st.markdown('<h1 class="main-header">🧠 Agent Pruning Lab</h1>', unsafe_allow_html=True)
st.markdown('<p class="sub-header">Context Pruning com Provence + Semantic Highlighting para Agentes LLM</p>', unsafe_allow_html=True)

# Sidebar
with st.sidebar:
    st.markdown("### ⚙️ Configurações do Agente")
    
    model_choice = st.selectbox(
        "Modelo de Pruning",
        ["OpenProvence-XSmall (30M)", "OpenProvence-Small (110M)", "Simulação (Demo)"],
        index=2
    )
    
    pruning_threshold = st.slider(
        "Threshold de Pruning",
        0.0, 1.0, 0.5, 0.05,
        help="Sentenças com score abaixo são removidas"
    )
    
    highlight_mode = st.radio(
        "Modo de Visualização",
        ["Semantic Highlighting", "Binary Keep/Remove", "Heatmap de Relevância"],
        index=0
    )
    
    st.markdown("---")
    st.markdown("### 📚 Sobre")
    st.info("""
    **Provence** é um método de pruning de contexto desenvolvido pela Naver Labs Europe [^7^].
    
    **Semantic Highlighting** visualiza a relevância token-a-token do contexto [^11^].
    
    Combinação ideal para agentes que precisam processar documentos longos de forma eficiente.
    """)
    
    st.markdown("---")
    st.markdown("🔗 [Paper Provence](https://arxiv.org/abs/2501.16214)")
    st.markdown("🔗 [OpenProvence GitHub](https://github.com/hotchpotch/open_provence)")

# Tabs principais
tab1, tab2, tab3, tab4 = st.tabs([
    "🎮 Demo Interativo", 
    "📊 Benchmarks", 
    "🔬 Análise Técnica",
    "📖 Documentação"
])

with tab1:
    st.markdown("### 🎯 Simule um Agente de Pesquisa")
    
    col1, col2 = st.columns([1, 1])
    
    with col1:
        st.markdown("#### ❓ Query do Agente")
        query = st.text_area(
            "O que o agente precisa encontrar?",
            value="Quais são os principais benefícios do context pruning em sistemas RAG?",
            height=80
        )
        
        st.markdown("#### 📄 Documento de Entrada")
        document = st.text_area(
            "Cole um documento longo ou use o exemplo:",
            value="""A inteligência artificial tem revolucionado diversos setores da economia global. 
No campo da medicina, algoritmos de deep learning são utilizados para diagnóstico precoce de câncer. 
Em finanças, modelos preditivos analisam padrões de mercado. 
No entanto, um dos maiores desafios em sistemas de Retrieval-Augmented Generation (RAG) é o gerenciamento eficiente de contexto longo. 
Quando documentos irrelevantes são incluídos no prompt, o modelo desperdiça tokens e pode gerar respostas imprecisas. 
Técnicas como context pruning, especialmente métodos como Provence, permitem remover sentenças irrelevantes mantendo apenas o conteúdo necessário. 
Isso resulta em redução de latência e melhoria na qualidade das respostas. 
Estudos mostram que Provence consegue taxas de compressão de até 95% sem perda de performance [^1^]. 
Além disso, o Semantic Highlighting permite visualizar quais partes do texto são mais relevantes para uma query específica. 
Em sistemas multi-agente, onde múltiplos agentes trocam contexto, o pruning se torna ainda mais crítico para evitar propagação de ruído. 
A Naver Labs Europe desenvolveu o Provence como um modelo leve baseado em DeBERTa que realiza pruning e reranking em um único forward pass [^4^]. 
O modelo é treinado com labels de prata geradas por LLMs, identificando quais sentenças foram de fato utilizadas para gerar respostas. 
Resultados em benchmarks como Natural Questions e HotpotQA demonstram melhorias consistentes.""",
            height=300
        )
        
        run_button = st.button("🚀 Executar Pipeline do Agente", type="primary", use_container_width=True)
    
    with col2:
        st.markdown("#### 🧠 Simulação do Agente")
        
        if run_button:
            with st.spinner("🔍 Agente processando..."):
                # Simula o pipeline completo
                results = agent.run_pipeline(query, document, pruning_threshold)
                
                # Métricas
                col_m1, col_m2, col_m3 = st.columns(3)
                with col_m1:
                    st.markdown(f"""
                    <div class="metric-card">
                        <div class="metric-value">{results['compression_rate']}%</div>
                        <div class="metric-label">Compressão</div>
                    </div>
                    """, unsafe_allow_html=True)
                with col_m2:
                    st.markdown(f"""
                    <div class="metric-card">
                        <div class="metric-value">{results['tokens_saved']}</div>
                        <div class="metric-label">Tokens Economizados</div>
                    </div>
                    """, unsafe_allow_html=True)
                with col_m3:
                    st.markdown(f"""
                    <div class="metric-card">
                        <div class="metric-value">{results['relevance_score']:.2f}</div>
                        <div class="metric-label">Score de Relevância</div>
                    </div>
                    """, unsafe_allow_html=True)
                
                st.markdown("---")
                
                # Visualização do resultado
                st.markdown("#### ✂️ Resultado do Pruning")
                
                if highlight_mode == "Semantic Highlighting":
                    html_output = highlighter.render_semantic_highlighting(
                        results['sentences'], 
                        results['scores']
                    )
                    st.markdown(html_output, unsafe_allow_html=True)
                    
                elif highlight_mode == "Binary Keep/Remove":
                    for sent, score, kept in zip(results['sentences'], results['scores'], results['kept']):
                        css_class = "kept-text" if kept else "pruned-text"
                        st.markdown(f'<span class="{css_class}">{sent}</span> ', unsafe_allow_html=True)
                        
                else:  # Heatmap
                    fig = highlighter.render_heatmap(results['sentences'], results['scores'])
                    st.plotly_chart(fig, use_container_width=True)
                
                # Pensamento do agente
                st.markdown("---")
                st.markdown("#### 💭 Raciocínio do Agente")
                for thought in results['agent_thoughts']:
                    st.markdown(f'<div class="agent-thought">{thought}</div>', unsafe_allow_html=True)
        else:
            st.info("👈 Configure a query e clique em 'Executar Pipeline do Agente'")

with tab2:
    st.markdown("### 📊 Benchmarks de Performance")
    
    data = {
        "Método": ["Sem Pruning", "Truncation Simples", "Provence", "XProvence", "Semantic Highlighter"],
        "F1 Score": ["—", "42.3%", "66.76%", "58.97%", "46.37%"],
        "Compressão": ["0%", "60%", "80-95%", "75-85%", "70-80%"],
        "Latência Extra": ["0ms", "0ms", "~0ms*", "~0ms*", "5-10ms"],
        "Multilíngue": ["—", "Sim", "Inglês", "Sim", "Sim"]
    }
    
    import pandas as pd
    df = pd.DataFrame(data)
    st.dataframe(df, use_container_width=True, hide_index=True)
    
    st.caption("*Provence integra pruning com reranking, adicionando latência quase zero [^4^]")
    
    st.markdown("---")
    st.markdown("#### 🏆 Resultados em Datasets")
    
    col_b1, col_b2 = st.columns(2)
    with col_b1:
        st.markdown("**Natural Questions**")
        st.progress(0.89, text="Provence: 89% retenção de acurácia")
        st.progress(0.72, text="Baseline: 72% retenção de acurácia")
    with col_b2:
        st.markdown("**HotpotQA (Multi-hop)**")
        st.progress(0.85, text="Provence: 85% retenção de acurácia")
        st.progress(0.68, text="Baseline: 68% retenção de acurácia")

with tab3:
    st.markdown("### 🔬 Análise Técnica Detalhada")
    
    st.markdown("""
    #### Arquitetura Provence
    
    Provence utiliza uma arquitetura **dual-head** baseada em DeBERTa-V3 [^5^]:
    
    1. **Reranking Head**: Prediz score de relevância do documento inteiro
    2. **Pruning Head**: Gera máscara binária token-a-token indicando relevância
    
    Durante o treinamento, o modelo otimiza simultaneamente:
    - Binary Cross-Entropy para pruning
    - MSE para distilação do reranker original
    
    #### Semantic Highlighting vs Traditional Highlighting
    
    | Aspecto | Traditional (Keyword) | Semantic Highlighting |
    |---------|----------------------|----------------------|
    | Base | Matching literal | Similaridade semântica |
    | Sinônimos | ❌ Não detecta | ✅ Detecta |
    | Paráfrases | ❌ Não detecta | ✅ Detecta |
    | Custo | Baixo | Moderado |
    | Precisão | Baixa para RAG | Alta para RAG |
    
    #### Integração em Agentes
    
    Em workflows agentic, o pruning é aplicado em múltiplos pontos [^12^]:
    - **Pré-LLM**: Filtra documentos recuperados
    - **Inter-agente**: Resume contexto entre agentes
    - **Pós-tool**: Compacta outputs de ferramentas token-heavy
    """)

with tab4:
    st.markdown("### 📖 Como Usar Este Projeto")
    
    st.markdown("""
    #### 🚀 Deploy no Hugging Face Spaces
    
    1. Crie um novo Space em [huggingface.co/spaces](https://huggingface.co/spaces)
    2. Escolha **Streamlit** como SDK
    3. Faça push deste código:
    
    ```bash
    git clone https://huggingface.co/spaces/seu-username/agent-pruning-lab
    cd agent-pruning-lab
    # Copie os arquivos deste projeto
    git add .
    git commit -m "Initial commit"
    git push
    ```
    
    #### 🔧 Integração com Seu Agente
    
    ```python
    from components.provence_wrapper import ProvencePruner
    
    pruner = ProvencePruner(model_name="hotchpotch/open_provence_xsmall")
    
    # No seu pipeline RAG
    retrieved_docs = retriever.search(query)
    pruned_docs = pruner.prune(query, retrieved_docs, threshold=0.5)
    response = llm.generate(query, context=pruned_docs)
    ```
    
    #### 📚 Referências
    
    - [Provence Paper - ICLR 2025](https://arxiv.org/abs/2501.16214) [^7^]
    - [OpenProvence Implementation](https://github.com/hotchpotch/open_provence) [^8^]
    - [Semantic Highlighting Blog - Milvus](https://milvus.io/blog/semantic-highlighting-model-for-rag-context-pruning-and-token-saving.md) [^11^]
    - [Context Engineering - LangChain](https://www.langchain.com/blog/context-engineering-for-agents) [^12^]
    """)

# Footer
st.markdown("---")
st.markdown("""
<div style="text-align: center; color: #666; padding: 1rem;">
    <p>🧠 Agent Pruning Lab | Built with ❤️ for Hugging Face Spaces</p>
    <p>Demonstrando Provence + Semantic Highlighting para Agentes LLM Modernos</p>
</div>
""", unsafe_allow_html=True)