File size: 2,266 Bytes
80e393a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Wrapper para Provence/OpenProvence - Pruning de Contexto
"""

import re
import numpy as np

class ProvencePruner:
    """
    Wrapper que simula o comportamento do Provence para demonstração.
    Em produção, carregaria o modelo real do Hugging Face.
    """
    
    def __init__(self, model_name=None):
        self.model_name = model_name or "demo"
        
    def _split_sentences(self, text):
        """Divide texto em sentenças"""
        sentences = re.split(r'(?<=[.!?])\s+', text.strip())
        return [s.strip() for s in sentences if s.strip()]
    
    def _calculate_relevance(self, query, sentence):
        """
        Simula scoring de relevância (em produção, usaria o modelo Provence real)
        """
        query_words = set(query.lower().split())
        sent_words = set(sentence.lower().split())
        
        # Overlap básico
        overlap = len(query_words & sent_words)
        
        # Keywords técnicas que aumentam relevância
        technical_terms = {
            'pruning', 'context', 'rag', 'retrieval', 'agent', 
            'token', 'llm', 'relevância', 'compressão', 'provence',
            'semantic', 'highlighting', 'documento', 'query'
        }
        
        term_bonus = sum(1 for term in technical_terms if term in sentence.lower())
        
        # Score combinado
        score = min(1.0, (overlap * 0.15) + (term_bonus * 0.12) + 0.1)
        
        # Adiciona variação realista
        score += np.random.normal(0, 0.05)
        score = np.clip(score, 0.0, 1.0)
        
        return round(score, 3)
    
    def prune(self, query, document, threshold=0.5):
        """
        Executa pruning de contexto
        
        Returns:
            dict com sentenças, scores e máscara de keep/remove
        """
        sentences = self._split_sentences(document)
        scores = [self._calculate_relevance(query, sent) for sent in sentences]
        kept = [score >= threshold for score in scores]
        
        return {
            'sentences': sentences,
            'scores': scores,
            'kept': kept,
            'pruned_sentences': [s for s, k in zip(sentences, kept) if k],
            'compression_rate': round((1 - sum(kept) / len(sentences)) * 100, 1)
        }