Spaces:
Sleeping
Sleeping
File size: 7,045 Bytes
1b447de |
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 |
"""
Expansão de Queries (Multi-Query Retrieval)
Gera múltiplas variações de uma query para melhorar cobertura da busca.
"""
import re
from typing import List, Dict, Any, Optional
from src.generation import GenerationManager
class QueryExpander:
"""Expande queries em múltiplas variações para melhor retrieval"""
def __init__(self, generation_manager: GenerationManager):
"""
Args:
generation_manager: Gerenciador de geração de texto
"""
self.generation_manager = generation_manager
def expand_query(
self,
query: str,
num_variations: int = 3,
method: str = "llm"
) -> List[str]:
"""
Expande query em múltiplas variações
Args:
query: Query original
num_variations: Número de variações a gerar
method: Método de expansão ("llm", "template", "paraphrase")
Returns:
Lista com query original + variações
"""
if method == "llm":
return self._expand_with_llm(query, num_variations)
elif method == "template":
return self._expand_with_templates(query, num_variations)
elif method == "paraphrase":
return self._expand_with_paraphrase(query, num_variations)
else:
return [query]
def _expand_with_llm(self, query: str, num_variations: int) -> List[str]:
"""
Usa LLM para gerar variações da query
Estratégia: Pede ao LLM para reformular a pergunta de formas diferentes
"""
prompt = f"""Você é um assistente que ajuda a reformular perguntas para melhorar buscas.
Pergunta original: "{query}"
Gere {num_variations} reformulações diferentes desta pergunta. Cada reformulação deve:
- Manter o mesmo significado e intenção
- Usar palavras e estruturas diferentes
- Ser igualmente específica
Formato de saída (uma por linha):
1. [primeira reformulação]
2. [segunda reformulação]
3. [terceira reformulação]
Reformulações:"""
try:
response = self.generation_manager.generate(
prompt=prompt,
max_tokens=200,
temperature=0.7
)
# Extrai variações do response
variations = self._parse_llm_variations(response)
# Garante que temos pelo menos a query original
if not variations:
variations = [query]
elif query not in variations:
variations.insert(0, query)
return variations[:num_variations + 1] # +1 para incluir original
except Exception as e:
print(f"Erro ao expandir query com LLM: {e}")
return [query]
def _parse_llm_variations(self, response: str) -> List[str]:
"""
Extrai variações do response do LLM
Procura por linhas numeradas ou bullets
"""
variations = []
# Tenta extrair linhas numeradas: "1. texto", "2. texto"
pattern = r'^\d+\.\s*(.+)$'
for line in response.split('\n'):
line = line.strip()
match = re.match(pattern, line)
if match:
variation = match.group(1).strip()
if variation:
variations.append(variation)
# Se não encontrou numeradas, tenta bullets: "- texto", "* texto"
if not variations:
pattern = r'^[-*]\s*(.+)$'
for line in response.split('\n'):
line = line.strip()
match = re.match(pattern, line)
if match:
variation = match.group(1).strip()
if variation:
variations.append(variation)
return variations
def _expand_with_templates(self, query: str, num_variations: int) -> List[str]:
"""
Usa templates fixos para expandir query
Útil quando LLM não está disponível ou para casos simples
"""
templates = [
query, # Original
f"Explique sobre {query}",
f"O que é {query}?",
f"Como funciona {query}?",
f"Qual a definição de {query}?",
f"Informações sobre {query}",
]
return templates[:num_variations + 1]
def _expand_with_paraphrase(self, query: str, num_variations: int) -> List[str]:
"""
Usa paraphrasing simples baseado em sinônimos
Nota: Implementação básica. Para produção, considere usar
modelo de paraphrase como T5 ou BART
"""
# Implementação simplificada com algumas variações comuns
variations = [query]
# Substituições comuns em português
substitutions = [
("o que é", "qual é"),
("como funciona", "qual o funcionamento de"),
("explique", "descreva"),
("diferença entre", "distinção entre"),
("vantagens", "benefícios"),
]
for old, new in substitutions:
if old in query.lower():
variation = query.lower().replace(old, new).capitalize()
if variation not in variations:
variations.append(variation)
if len(variations) > num_variations:
break
return variations[:num_variations + 1]
def get_expansion_info(self, method: str) -> Dict[str, Any]:
"""
Retorna informações sobre método de expansão
Args:
method: Nome do método
Returns:
Dicionário com informações
"""
info = {
"llm": {
"name": "LLM-based",
"description": "Usa modelo de linguagem para gerar variações contextuais",
"pros": "Variações de alta qualidade, contextuais",
"cons": "Mais lento, requer LLM disponível",
"best_for": "Queries complexas e conceituais"
},
"template": {
"name": "Template-based",
"description": "Usa templates fixos para reformular queries",
"pros": "Rápido, determinístico, sem dependências",
"cons": "Variações genéricas, pode não preservar nuances",
"best_for": "Queries simples, prototipação rápida"
},
"paraphrase": {
"name": "Paraphrase-based",
"description": "Usa substituições de sinônimos e paráfrases",
"pros": "Balanceado, mantém estrutura original",
"cons": "Limitado por dicionário de sinônimos",
"best_for": "Queries médias, quando LLM não está disponível"
}
}
return info.get(method, {
"name": method,
"description": "Método desconhecido",
"pros": "N/A",
"cons": "N/A",
"best_for": "N/A"
})
|