Update handler.py
Browse files- handler.py +94 -0
handler.py
CHANGED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Dict, Any
|
2 |
+
from llama_cpp import Llama
|
3 |
+
from huggingface_hub import hf_hub_download
|
4 |
+
|
5 |
+
class EndpointHandler:
|
6 |
+
def __init__(self, path=""):
|
7 |
+
# Configuração do modelo
|
8 |
+
self.model_name_or_path = "souzat19/Llama3.1_fn14133.29122024"
|
9 |
+
self.model_basename = "unsloth.Q8_0.gguf"
|
10 |
+
|
11 |
+
# Download do modelo
|
12 |
+
model_path = hf_hub_download(
|
13 |
+
repo_id=self.model_name_or_path,
|
14 |
+
filename=self.model_basename
|
15 |
+
)
|
16 |
+
|
17 |
+
# Inicialização do modelo
|
18 |
+
self.model = Llama(
|
19 |
+
model_path=model_path,
|
20 |
+
n_threads=2,
|
21 |
+
n_batch=512,
|
22 |
+
n_gpu_layers=-1,
|
23 |
+
n_ctx=4096
|
24 |
+
)
|
25 |
+
|
26 |
+
# Template do prompt no formato Alpaca
|
27 |
+
self.prompt_template = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
|
28 |
+
### Instruction:
|
29 |
+
Você é um assistente especializado em planejamento de compras públicas de acordo com a Lei 14.133/2021 e regulamentos infralegais. Responda de forma clara, detalhada e didática e utilize exemplos práticos para explicar os conceitos.
|
30 |
+
### Input:
|
31 |
+
{input}
|
32 |
+
### Response:
|
33 |
+
"""
|
34 |
+
|
35 |
+
def __call__(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
36 |
+
"""
|
37 |
+
Processa a entrada e retorna a resposta do modelo.
|
38 |
+
|
39 |
+
Args:
|
40 |
+
data: Dicionário contendo a entrada do usuário
|
41 |
+
Formato esperado: {"text": "pergunta do usuário"}
|
42 |
+
|
43 |
+
Returns:
|
44 |
+
Dict contendo a resposta do modelo
|
45 |
+
"""
|
46 |
+
try:
|
47 |
+
# Extrai o texto da entrada
|
48 |
+
input_text = data.get("text", "")
|
49 |
+
if not input_text:
|
50 |
+
return {"error": "Input text is required"}
|
51 |
+
|
52 |
+
# Formata o prompt
|
53 |
+
formatted_prompt = self.prompt_template.format(input=input_text)
|
54 |
+
|
55 |
+
# Gera a resposta
|
56 |
+
response = self.model(
|
57 |
+
prompt=formatted_prompt,
|
58 |
+
max_tokens=2096,
|
59 |
+
temperature=0.5,
|
60 |
+
top_p=0.95,
|
61 |
+
top_k=50,
|
62 |
+
stop=['### Response:', '### Input:', '### Instruction:'],
|
63 |
+
echo=True
|
64 |
+
)
|
65 |
+
|
66 |
+
# Extrai a resposta do modelo
|
67 |
+
response_text = response['choices'][0]['text']
|
68 |
+
|
69 |
+
# Processa a resposta para extrair apenas a parte após "### Response:"
|
70 |
+
if "### Response:" in response_text:
|
71 |
+
answer = response_text.split("### Response:")[1].strip()
|
72 |
+
else:
|
73 |
+
answer = response_text.strip()
|
74 |
+
|
75 |
+
return {"response": answer}
|
76 |
+
|
77 |
+
except Exception as e:
|
78 |
+
return {"error": f"Error during inference: {str(e)}"}
|
79 |
+
|
80 |
+
def preprocess(self, text: str) -> str:
|
81 |
+
"""
|
82 |
+
Pré-processa o texto de entrada se necessário
|
83 |
+
"""
|
84 |
+
# Remove espaços extras e normaliza quebras de linha
|
85 |
+
text = " ".join(text.split())
|
86 |
+
return text.strip()
|
87 |
+
|
88 |
+
def validate_input(self, text: str) -> bool:
|
89 |
+
"""
|
90 |
+
Valida a entrada do usuário
|
91 |
+
"""
|
92 |
+
if not text or len(text.strip()) == 0:
|
93 |
+
return False
|
94 |
+
return True
|