aldohenrique commited on
Commit
d3a6527
·
verified ·
1 Parent(s): 70b4990

Update ai_logic.py

Browse files
Files changed (1) hide show
  1. ai_logic.py +67 -107
ai_logic.py CHANGED
@@ -16,38 +16,37 @@ VECTOR_STORE_PATH = "faiss_index_store.pkl"
16
  PROCESSED_URLS_PATH = "processed_urls.pkl"
17
  HF_TOKEN = os.getenv("HF_TOKEN")
18
  if not HF_TOKEN:
19
- raise ValueError("Token HF_TOKEN não encontrado. Defina a variável de ambiente HF_TOKEN.")
20
 
21
- # Lista de todos os modelos que queremos testar.
22
- CANDIDATE_MODELS = {
23
- # Originais
24
- "Mistral 7B (Acertivo)": "mistralai/Mistral-7B-Instruct-v0.3",
25
- "Phi-3 Mini (Rápido)": "microsoft/Phi-3-mini-4k-instruct",
26
- "Zephyr 7B (Equilibrado)": "HuggingFaceH4/zephyr-7b-beta",
27
-
28
- # 13 Novos Modelos
29
- "Gemma 2 9B (Google)": "google/gemma-2-9b-it",
30
- "Llama 3 8B (Meta)": "meta-llama/Meta-Llama-3-8B-Instruct",
31
- "Mixtral 8x7B (Mistral)": "mistralai/Mixtral-8x7B-Instruct-v0.1",
32
- "Qwen2 7B (Alibaba)": "Qwen/Qwen2-7B-Instruct",
33
- "Command R+ (Cohere)": "CohereForAI/c4ai-command-r-plus",
34
- "Gemma 7B (Google)": "google/gemma-7b-it",
35
- "Arctic (Snowflake)": "Snowflake/snowflake-arctic-instruct",
36
- "OpenChat 3.5": "openchat/openchat-3.5-0106",
37
- "Starling 7B (Nexus)": "Nexusflow/Starling-LM-7B-beta",
38
- "Yi 1.5 9B (01-AI)": "01-ai/Yi-1.5-9B-Chat",
39
- "CodeGemma 7B (Google)": "google/codegemma-7b-it",
40
- "Heron 13B (Donako)": "Donako/heron-chat-13b",
41
- "Stable Beluga 7B": "stabilityai/stable-beluga-7b"
42
  }
43
 
44
- # Dicionário que será preenchido apenas com os modelos disponíveis
45
- MODELS = {}
46
- DEFAULT_MODEL = "Phi-3 Mini (Rápido)"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
  # --- Gerenciamento de Sessão ---
49
  user_sessions: Dict[str, Dict[str, List | Dict]] = {} # {session_id: {'conversation': [], 'user_profile': {}}}
50
- MAX_MEMORY_LENGTH = 5
51
 
52
  def get_session_memory_path(session_id: str) -> str:
53
  """Retorna o caminho do arquivo de memória para a sessão."""
@@ -96,11 +95,13 @@ def update_user_profile(session_id: str, user_message: str):
96
  profile = user_sessions[session_id]['user_profile']
97
  message_lower = user_message.lower()
98
 
 
99
  if any(word in message_lower for word in ['básico', 'iniciante']):
100
  profile['nivel'] = 'iniciante'
101
  elif any(word in message_lower for word in ['avançado', 'complexo']):
102
  profile['nivel'] = 'avançado'
103
 
 
104
  topics = {
105
  'java': ['java', 'classe', 'objeto'],
106
  'web': ['html', 'css', 'javascript'],
@@ -116,7 +117,7 @@ def update_user_profile(session_id: str, user_message: str):
116
  def get_conversation_context(session_id: str) -> str:
117
  """Gera o contexto da conversa recente."""
118
  load_conversation_memory(session_id)
119
- conversation = user_sessions[session_id]['conversation'][-4:]
120
  if not conversation:
121
  return ""
122
  return "\n".join(f"{msg['role'].upper()}: {msg['content']}" for msg in conversation)
@@ -148,19 +149,18 @@ def get_all_blog_links(url: str) -> set:
148
  """Coleta todos os links do blog."""
149
  links = {url}
150
  visited = set()
151
- queue = [url]
152
- while queue:
153
- current_url = queue.pop(0)
154
  if current_url in visited:
155
  continue
156
  try:
157
- response = requests.get(current_url, timeout=10)
158
  soup = BeautifulSoup(response.content, 'html.parser')
159
  visited.add(current_url)
160
  for link in soup.find_all('a', href=True):
161
  href = urljoin(url, link['href'])
162
- if urlparse(href).netloc == urlparse(url).netloc and '/tag/' not in href and '/category/' not in href and href not in visited:
163
- queue.append(href)
164
  except Exception as e:
165
  print(f"Erro ao acessar {current_url}: {e}")
166
  return visited
@@ -168,7 +168,7 @@ def get_all_blog_links(url: str) -> set:
168
  def scrape_text_from_url(url: str) -> str:
169
  """Extrai texto de uma URL."""
170
  try:
171
- response = requests.get(url, timeout=10)
172
  soup = BeautifulSoup(response.content, 'html.parser')
173
  content = soup.find('article') or soup.find('main')
174
  return content.get_text(separator='\n', strip=True) if content else ""
@@ -221,11 +221,7 @@ class HuggingFaceAPIClient:
221
 
222
  def query_model(self, model_name: str, messages: List[Dict], max_tokens: int = 1000) -> str:
223
  """Faz requisição à API do Hugging Face."""
224
- url = f"https://api-inference.huggingface.co/models/{model_name}"
225
- # Para a nova API de chat
226
- if "/v1/chat/completions" not in url:
227
- url += "/v1/chat/completions"
228
-
229
  payload = {
230
  "model": model_name,
231
  "messages": messages,
@@ -233,65 +229,47 @@ class HuggingFaceAPIClient:
233
  "temperature": 0.7
234
  }
235
  try:
236
- response = requests.post(url, headers=self.headers, json=payload, timeout=30)
237
  response.raise_for_status()
238
  return response.json()["choices"][0]["message"]["content"].strip()
239
- except requests.exceptions.RequestException as e:
240
- # Captura erros de rede, timeout, HTTP etc.
241
- print(f"Erro na requisição para o modelo {model_name}: {e}")
242
- raise
243
- except (KeyError, IndexError) as e:
244
- # Captura erros na estrutura da resposta JSON
245
- print(f"Resposta inesperada do modelo {model_name}: {response.text}")
246
- raise
247
-
248
- api_client = HuggingFaceAPIClient(HF_TOKEN)
249
 
250
- # --- Verificação de Modelos Disponíveis ---
251
- def verificar_modelos_disponiveis():
252
- """
253
- Testa cada modelo da lista de candidatos e popula o dicionário MODELS
254
- apenas com aqueles que estão acessíveis e respondem.
255
- """
256
- global MODELS, DEFAULT_MODEL
257
- print("Verificando a disponibilidade dos modelos do Hugging Face...")
258
-
259
- test_messages = [{"role": "user", "content": "Ping"}]
260
-
261
- for friendly_name, model_id in CANDIDATE_MODELS.items():
262
- print(f" - Testando: {friendly_name} ({model_id})... ", end="")
263
  try:
264
- # Usamos um timeout curto e poucos tokens para um teste rápido
265
- api_client.query_model(model_id, test_messages, max_tokens=5)
266
- MODELS[friendly_name] = model_id
267
- print("✅ Disponível!")
268
  except Exception:
269
- print("❌ Indisponível ou erro.")
270
-
271
- if not MODELS:
272
- raise RuntimeError("Nenhum dos modelos configurados está disponível no momento. Verifique seu token HF_TOKEN e a disponibilidade dos modelos.")
273
 
274
- # Garante que o modelo padrão seja um que esteja disponível
275
- if DEFAULT_MODEL not in MODELS:
276
- # Pega o primeiro modelo da lista de disponíveis como novo padrão
277
- new_default_key = next(iter(MODELS))
278
- print(f"Aviso: O modelo padrão '{DEFAULT_MODEL}' não está disponível.")
279
- print(f"Definindo '{new_default_key}' como o novo padrão.")
280
- DEFAULT_MODEL = new_default_key
281
 
 
 
 
 
 
 
 
 
 
 
 
282
 
283
  # --- Chat Principal ---
284
- def responder_como_aldo(session_id: str, pergunta: str, modelo: str = None) -> str:
285
  """Gera resposta como Dr. Aldo Henrique."""
286
- if modelo is None:
287
- modelo = DEFAULT_MODEL # Usa o padrão dinâmico
288
-
289
  if not pergunta.strip():
290
  return "Por favor, faça uma pergunta válida."
291
 
292
  load_conversation_memory(session_id)
293
  update_user_profile(session_id, pergunta)
294
 
 
295
  contexto = []
296
  if perfil := get_user_profile_context(session_id):
297
  contexto.append(f"**Perfil do Usuário**\n{perfil}")
@@ -323,39 +301,21 @@ def responder_como_aldo(session_id: str, pergunta: str, modelo: str = None) -> s
323
  ]
324
 
325
  model_name = MODELS.get(modelo, MODELS[DEFAULT_MODEL])
326
- try:
327
- resposta = api_client.query_model(model_name, messages)
328
- add_to_memory(session_id, pergunta, resposta)
329
- return resposta
330
- except Exception as e:
331
- return f"Desculpe, houve um erro ao processar sua solicitação com o modelo {modelo}. Detalhes: {e}"
332
-
333
 
334
  # --- Inicialização ---
335
  def inicializar_sistema():
336
  """Inicializa o sistema."""
337
  print("Inicializando Chatbot Dr. Aldo...")
338
- verificar_modelos_disponiveis() # <-- NOVO: Verifica os modelos antes de continuar
339
  load_vector_store()
340
- print("\nSistema inicializado e pronto para uso!")
341
- print(f"Modelos disponíveis: {list(MODELS.keys())}")
342
- print(f"Modelo padrão: {DEFAULT_MODEL}")
343
-
344
 
345
  if __name__ == "__main__":
346
  inicializar_sistema()
347
-
348
  session_id = "teste_123"
349
- print("\n--- Testando o Chat ---")
350
-
351
- # Exemplo de pergunta
352
- pergunta_teste = "O que é um Large Language Model (LLM) e como ele se difere da IA tradicional?"
353
- print(f"\n[Usuário]: {pergunta_teste}")
354
-
355
- # A função agora usa o modelo padrão que foi verificado como disponível
356
- resposta_aldo = responder_como_aldo(session_id, pergunta_teste)
357
- print(f"\n[Dr. Aldo]: {resposta_aldo}")
358
-
359
- # Limpando a memória da sessão de teste
360
- print(f"\n--- Limpando Memória ---")
361
  print(clear_memory(session_id))
 
16
  PROCESSED_URLS_PATH = "processed_urls.pkl"
17
  HF_TOKEN = os.getenv("HF_TOKEN")
18
  if not HF_TOKEN:
19
+ raise ValueError("Token HF_TOKEN não encontrado")
20
 
21
+ # Lista inicial de modelos
22
+ MODELS = {
23
+ "Mistral 7B (Mais acertivo)": "mistralai/Mistral-7B-Instruct-v0.3",
24
+ "Phi-3 Mini (Mais rápido)": "microsoft/Phi-3-mini-4k-instruct",
25
+ "Zephyr 7B (Meio Termo)": "HuggingFaceH4/zephyr-7b-beta"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
27
 
28
+ # Novos modelos para testar
29
+ NEW_MODELS_TO_TEST = [
30
+ ("LLaMA 2-7B Chat", "meta-llama/Llama-2-7b-chat"),
31
+ ("LLaMA 3.2-3B Instruct", "meta-llama/Llama-3.2-3B-Instruct"),
32
+ ("Gemma 2B Instruct", "google/gemma-2b-it"),
33
+ ("Qwen2 7B Instruct", "Qwen/Qwen2-7B-Instruct"),
34
+ ("Falcon 7B Instruct", "tiiuae/falcon-7b-instruct"),
35
+ ("Mixtral 8x7B Instruct", "mistralai/Mixtral-8x7B-Instruct-v0.1"),
36
+ ("LLaMA 3.1-8B Instruct", "meta-llama/Llama-3.1-8B-Instruct"),
37
+ ("GPT2 XL", "gpt2-xl"),
38
+ ("T5 Base", "t5-base"),
39
+ ("Grok 2 Mini", "xAI/grok2-mini"),
40
+ ("CodeLlama 7B Instruct", "codellama/CodeLlama-7b-Instruct-hf"),
41
+ ("Starling LM 7B", "HuggingFaceH4/starling-lm-7b-alpha"),
42
+ ("OpenHermes 2.5 Mistral", "teknium/OpenHermes-2.5-Mistral-7B")
43
+ ]
44
+
45
+ DEFAULT_MODEL = "Mistral 7B (Mais acertivo)"
46
 
47
  # --- Gerenciamento de Sessão ---
48
  user_sessions: Dict[str, Dict[str, List | Dict]] = {} # {session_id: {'conversation': [], 'user_profile': {}}}
49
+ MAX_MEMORY_LENGTH = 5 # Máximo de trocas (user + assistant)
50
 
51
  def get_session_memory_path(session_id: str) -> str:
52
  """Retorna o caminho do arquivo de memória para a sessão."""
 
95
  profile = user_sessions[session_id]['user_profile']
96
  message_lower = user_message.lower()
97
 
98
+ # Atualiza nível
99
  if any(word in message_lower for word in ['básico', 'iniciante']):
100
  profile['nivel'] = 'iniciante'
101
  elif any(word in message_lower for word in ['avançado', 'complexo']):
102
  profile['nivel'] = 'avançado'
103
 
104
+ # Atualiza interesses
105
  topics = {
106
  'java': ['java', 'classe', 'objeto'],
107
  'web': ['html', 'css', 'javascript'],
 
117
  def get_conversation_context(session_id: str) -> str:
118
  """Gera o contexto da conversa recente."""
119
  load_conversation_memory(session_id)
120
+ conversation = user_sessions[session_id]['conversation'][-4:] # Últimas 2 trocas
121
  if not conversation:
122
  return ""
123
  return "\n".join(f"{msg['role'].upper()}: {msg['content']}" for msg in conversation)
 
149
  """Coleta todos os links do blog."""
150
  links = {url}
151
  visited = set()
152
+ while links:
153
+ current_url = links.pop()
 
154
  if current_url in visited:
155
  continue
156
  try:
157
+ response = requests.get(current_url, timeout=500)
158
  soup = BeautifulSoup(response.content, 'html.parser')
159
  visited.add(current_url)
160
  for link in soup.find_all('a', href=True):
161
  href = urljoin(url, link['href'])
162
+ if urlparse(href).netloc == urlparse(url).netloc and '/tag/' not in href and '/category/' not in href:
163
+ links.add(href)
164
  except Exception as e:
165
  print(f"Erro ao acessar {current_url}: {e}")
166
  return visited
 
168
  def scrape_text_from_url(url: str) -> str:
169
  """Extrai texto de uma URL."""
170
  try:
171
+ response = requests.get(url, timeout=500)
172
  soup = BeautifulSoup(response.content, 'html.parser')
173
  content = soup.find('article') or soup.find('main')
174
  return content.get_text(separator='\n', strip=True) if content else ""
 
221
 
222
  def query_model(self, model_name: str, messages: List[Dict], max_tokens: int = 1000) -> str:
223
  """Faz requisição à API do Hugging Face."""
224
+ url = f"https://api-inference.huggingface.co/models/{model_name}/v1/chat/completions"
 
 
 
 
225
  payload = {
226
  "model": model_name,
227
  "messages": messages,
 
229
  "temperature": 0.7
230
  }
231
  try:
232
+ response = requests.post(url, headers=self.headers, json=payload, timeout=10)
233
  response.raise_for_status()
234
  return response.json()["choices"][0]["message"]["content"].strip()
235
+ except Exception as e:
236
+ return f"Erro na API: {str(e)}"
 
 
 
 
 
 
 
 
237
 
238
+ def test_model_availability(self, model_name: str) -> bool:
239
+ """Testa se um modelo está disponível na API do Hugging Face."""
240
+ test_messages = [
241
+ {"role": "user", "content": "Teste de disponibilidade."}
242
+ ]
 
 
 
 
 
 
 
 
243
  try:
244
+ response = self.query_model(model_name, test_messages, max_tokens=10)
245
+ return not response.startswith("Erro na API")
 
 
246
  except Exception:
247
+ return False
 
 
 
248
 
249
+ api_client = HuggingFaceAPIClient(HF_TOKEN)
 
 
 
 
 
 
250
 
251
+ # --- Função para Testar e Atualizar Modelos ---
252
+ def test_and_update_models():
253
+ """Testa a disponibilidade dos novos modelos e atualiza a lista MODELS."""
254
+ print("Testando disponibilidade dos novos modelos...")
255
+ for model_label, model_name in NEW_MODELS_TO_TEST:
256
+ if api_client.test_model_availability(model_name):
257
+ MODELS[model_label] = model_name
258
+ print(f"Modelo {model_label} ({model_name}) adicionado à lista.")
259
+ else:
260
+ print(f"Modelo {model_label} ({model_name}) não disponível.")
261
+ print(f"Total de modelos disponíveis: {len(MODELS)}")
262
 
263
  # --- Chat Principal ---
264
+ def responder_como_aldo(session_id: str, pergunta: str, modelo: str = DEFAULT_MODEL) -> str:
265
  """Gera resposta como Dr. Aldo Henrique."""
 
 
 
266
  if not pergunta.strip():
267
  return "Por favor, faça uma pergunta válida."
268
 
269
  load_conversation_memory(session_id)
270
  update_user_profile(session_id, pergunta)
271
 
272
+ # Monta contexto
273
  contexto = []
274
  if perfil := get_user_profile_context(session_id):
275
  contexto.append(f"**Perfil do Usuário**\n{perfil}")
 
301
  ]
302
 
303
  model_name = MODELS.get(modelo, MODELS[DEFAULT_MODEL])
304
+ resposta = api_client.query_model(model_name, messages)
305
+ add_to_memory(session_id, pergunta, resposta)
306
+ return resposta
 
 
 
 
307
 
308
  # --- Inicialização ---
309
  def inicializar_sistema():
310
  """Inicializa o sistema."""
311
  print("Inicializando Chatbot Dr. Aldo...")
312
+ test_and_update_models() # Testa e atualiza modelos disponíveis
313
  load_vector_store()
314
+ print("Sistema inicializado!")
 
 
 
315
 
316
  if __name__ == "__main__":
317
  inicializar_sistema()
 
318
  session_id = "teste_123"
319
+ print(responder_como_aldo(session_id, "O que é Java?"))
320
+ print(responder_como_aldo(session_id, "Mostre um exemplo de código Java."))
 
 
 
 
 
 
 
 
 
 
321
  print(clear_memory(session_id))