Spaces:
Running
Running
File size: 4,529 Bytes
f5eb34f 1b447de f5eb34f 1b447de f5eb34f 1b447de f5eb34f 1b447de f5eb34f 1b447de f5eb34f 1b447de f5eb34f 1b447de f5eb34f 1b447de f5eb34f 1b447de 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 |
"""
Geração de respostas usando LLMs
"""
from typing import Optional, List, Dict, Any, Iterator
from .config import LLM_PROVIDER, DEFAULT_TEMPERATURE, DEFAULT_MAX_TOKENS
from .llms.factory import create_llm
from .llms.base import BaseLLM
class GenerationManager:
"""Gerenciador de geração de texto com suporte a múltiplos providers"""
def __init__(self, provider: Optional[str] = None, model_id: Optional[str] = None):
"""
Inicializa gerenciador de geração
Args:
provider: Nome do provider (huggingface, openai, anthropic, ollama)
Se None, usa LLM_PROVIDER do .env
model_id: ID do modelo. Se None, usa default do provider
"""
self.provider_name = provider or LLM_PROVIDER
self.model_id = model_id
self.llm: Optional[BaseLLM] = None
def get_client(self) -> Optional[BaseLLM]:
"""Obtém cliente LLM (lazy loading com fallback)"""
if self.llm is None:
self.llm = create_llm(
provider=self.provider_name,
model_id=self.model_id,
fallback=True
)
return self.llm
def build_rag_prompt(
self,
question: str,
contexts: List[Dict[str, Any]],
system_prompt: Optional[str] = None
) -> str:
"""
Constrói prompt para RAG
Args:
question: Pergunta do usuário
contexts: Lista de contextos recuperados
system_prompt: Prompt de sistema customizado
Returns:
Prompt formatado
"""
if system_prompt is None:
system_prompt = "Use os trechos fornecidos para responder à pergunta de forma precisa e concisa."
context_text = "\n\n".join([
f"Trecho {i+1} (fonte: {ctx['title']}):\n{ctx['content']}"
for i, ctx in enumerate(contexts)
])
prompt = f"""{system_prompt}
Contexto:
{context_text}
Pergunta: {question}
Resposta:"""
return prompt
def generate(
self,
prompt: str,
temperature: float = DEFAULT_TEMPERATURE,
max_tokens: int = DEFAULT_MAX_TOKENS
) -> str:
"""
Gera resposta usando LLM
Args:
prompt: Prompt para o modelo
temperature: Temperatura de geração
max_tokens: Máximo de tokens a gerar
Returns:
Texto gerado
"""
client = self.get_client()
if client is None:
return "Erro: Nenhum provider LLM disponível. Verifique as configurações no .env"
if not client.is_available():
error_info = client.get_model_info()
return f"Erro: Provider {error_info.get('provider')} indisponível. {client.last_error}"
try:
response = client.generate(
prompt=prompt,
temperature=temperature,
max_tokens=max_tokens
)
return response
except Exception as e:
return f"Erro na geração: {str(e)}"
def generate_stream(
self,
prompt: str,
temperature: float = DEFAULT_TEMPERATURE,
max_tokens: int = DEFAULT_MAX_TOKENS
) -> Iterator[str]:
"""
Gera resposta em streaming (se suportado pelo provider)
Args:
prompt: Prompt para o modelo
temperature: Temperatura de geração
max_tokens: Máximo de tokens a gerar
Yields:
Tokens gerados progressivamente
"""
# Nota: Streaming ainda não implementado para todos os providers
# Por enquanto, retorna resposta completa
response = self.generate(prompt, temperature, max_tokens)
yield response
def format_sources(self, contexts: List[Dict[str, Any]]) -> str:
"""
Formata fontes para exibição
Args:
contexts: Lista de contextos
Returns:
String formatada com fontes
"""
if not contexts:
return "\n\n**Fontes:** Nenhuma fonte encontrada"
sources = []
for i, ctx in enumerate(contexts, 1):
preview = ctx['content'][:150] + "..." if len(ctx['content']) > 150 else ctx['content']
score = ctx.get('score', 0)
sources.append(
f"{i}. **{ctx['title']}** (relevância: {score:.2%})\n _{preview}_"
)
return "\n\n**Fontes:**\n" + "\n\n".join(sources)
|