roundb commited on
Commit
7cdcbb1
·
verified ·
1 Parent(s): 1843bfb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -47
app.py CHANGED
@@ -5,6 +5,7 @@
5
  import os
6
  from pathlib import Path
7
  import pickle
 
8
 
9
  import gradio as gr
10
  import faiss
@@ -12,8 +13,6 @@ from sentence_transformers import SentenceTransformer
12
  from openai import OpenAI
13
 
14
  # ========= NVIDIA API =========
15
- # Em local: defina NV_API_KEY ou NVIDIA_API_KEY no ambiente.
16
- # Em Hugging Face Spaces: crie um "Repository secret" chamado NVIDIA_API_KEY.
17
  NV_API_KEY = os.environ.get("NVIDIA_API_KEY") or os.environ.get("NV_API_KEY")
18
  if not NV_API_KEY:
19
  raise RuntimeError(
@@ -87,13 +86,13 @@ metadatas = emb_data["metadatas"]
87
  # Mesmo modelo de embeddings usado no build_index.py
88
  embedding_model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
89
 
90
- # Histórico do chat: lista de (user, assistant)
91
- dialog_history = []
 
92
 
93
 
94
  # ========= Recuperação de contexto =========
95
  def retrieve_context(query: str, k: int = 4) -> str:
96
- """Busca k trechos mais relevantes no índice FAISS para a pergunta."""
97
  if not query or not query.strip():
98
  return ""
99
 
@@ -113,8 +112,7 @@ def retrieve_context(query: str, k: int = 4) -> str:
113
 
114
 
115
  # ========= Streaming da NVIDIA =========
116
- def nv_stream(messages, temperature: float, top_p: float, max_tokens: int):
117
- """Stream da resposta da NVIDIA (LLaMA 3)."""
118
  reply = ""
119
  stream = client.chat.completions.create(
120
  model=CHAT_MODEL,
@@ -154,20 +152,25 @@ def chatbot(user_input: str, temperature: float, top_p: float, max_tokens: int):
154
  ),
155
  }
156
 
157
- messages = [system_msg]
158
- for u, a in dialog_history:
159
- messages.append({"role": "user", "content": u})
160
- messages.append({"role": "assistant", "content": a})
161
- messages.append({"role": "user", "content": user_input})
162
 
163
  reply_full = ""
164
  try:
165
  for partial in nv_stream(messages, temperature, top_p, max_tokens):
166
  reply_full = partial
167
- dialog_history.append((user_input, reply_full))
 
 
 
 
 
168
  except Exception as e:
169
  reply_full = f"⚠️ Erro na API NVIDIA: {type(e).__name__}: {e}"
170
- dialog_history.append((user_input, reply_full))
 
 
 
171
 
172
  return dialog_history, ""
173
 
@@ -178,7 +181,7 @@ def clear_history():
178
  return [], ""
179
 
180
 
181
- # ========= CSS simples / layout padrão =========
182
  custom_css = r"""
183
  body, .gradio-container {
184
  background: #ffffff;
@@ -258,9 +261,7 @@ body, .gradio-container {
258
 
259
 
260
  # ========= Layout Gradio =========
261
- # Gradio 6+: css e theme foram movidos para o launch()
262
  with gr.Blocks(title=APP_TITLE) as demo:
263
- # Header
264
  with gr.Group(elem_id="header-box"):
265
  gr.HTML(
266
  f"""
@@ -276,12 +277,11 @@ with gr.Blocks(title=APP_TITLE) as demo:
276
  gr.Markdown(INTRO)
277
 
278
  with gr.Row():
279
- # Coluna principal (chat)
280
  with gr.Column(scale=3):
281
  with gr.Group(elem_classes="card"):
282
  gr.Markdown("### 💬 Conversa Jurídica")
283
 
284
- # ✅ REMOVIDO: type="tuples" (não existe nesta versão)
285
  chatbot_ui = gr.Chatbot(
286
  elem_id="chat-window",
287
  label="Chatbot",
@@ -302,30 +302,15 @@ with gr.Blocks(title=APP_TITLE) as demo:
302
  top_p = gr.Slider(0, 1, value=0.9, label="Top-p")
303
  max_tokens = gr.Slider(64, 2048, value=512, step=64, label="Max Tokens")
304
 
305
- btn_send.click(
306
- chatbot,
307
- [txt, temperature, top_p, max_tokens],
308
- [chatbot_ui, txt],
309
- )
310
- txt.submit(
311
- chatbot,
312
- [txt, temperature, top_p, max_tokens],
313
- [chatbot_ui, txt],
314
- )
315
- btn_clear.click(
316
- clear_history,
317
- [],
318
- [chatbot_ui, txt],
319
- )
320
-
321
- # Sidebar
322
  with gr.Column(scale=2):
323
  with gr.Group(elem_classes="card"):
324
  gr.Markdown("### 💡 Sugestões rápidas")
325
  for q in SUGGESTION_QUESTIONS:
326
- gr.Button(q, elem_classes="suggestion-btn").click(
327
- lambda s=q: s, outputs=[txt]
328
- )
329
 
330
  gr.Markdown("---")
331
  gr.Markdown("### 📚 Explorar por tema")
@@ -333,16 +318,13 @@ with gr.Blocks(title=APP_TITLE) as demo:
333
  for theme, qs in SUGGESTIONS_THEMES.items():
334
  with gr.Accordion(theme, open=False):
335
  for q in qs:
336
- gr.Button(q, elem_classes="suggestion-btn").click(
337
- lambda s=q: s, outputs=[txt]
338
- )
339
 
340
- gr.Markdown(
341
- '<div class="app-footer">EcoLexIA · Sistema RAG para legislação ambiental em Portugal</div>'
342
- )
343
 
344
- # Para Hugging Face Spaces basta que a variável `demo` exista;
345
- # manter o launch permite rodar localmente.
346
  if __name__ == "__main__":
 
347
  demo.launch(theme=gr.themes.Soft(), css=custom_css)
348
 
 
 
5
  import os
6
  from pathlib import Path
7
  import pickle
8
+ from typing import List, Dict, Any
9
 
10
  import gradio as gr
11
  import faiss
 
13
  from openai import OpenAI
14
 
15
  # ========= NVIDIA API =========
 
 
16
  NV_API_KEY = os.environ.get("NVIDIA_API_KEY") or os.environ.get("NV_API_KEY")
17
  if not NV_API_KEY:
18
  raise RuntimeError(
 
86
  # Mesmo modelo de embeddings usado no build_index.py
87
  embedding_model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
88
 
89
+ # Gradio atual espera "messages format":
90
+ # lista de dicts: {"role": "user"/"assistant", "content": "..."}
91
+ dialog_history: List[Dict[str, str]] = []
92
 
93
 
94
  # ========= Recuperação de contexto =========
95
  def retrieve_context(query: str, k: int = 4) -> str:
 
96
  if not query or not query.strip():
97
  return ""
98
 
 
112
 
113
 
114
  # ========= Streaming da NVIDIA =========
115
+ def nv_stream(messages: List[Dict[str, str]], temperature: float, top_p: float, max_tokens: int):
 
116
  reply = ""
117
  stream = client.chat.completions.create(
118
  model=CHAT_MODEL,
 
152
  ),
153
  }
154
 
155
+ # Mensagens que vão para o modelo = system + histórico + user atual
156
+ messages: List[Dict[str, str]] = [system_msg] + dialog_history + [{"role": "user", "content": user_input}]
 
 
 
157
 
158
  reply_full = ""
159
  try:
160
  for partial in nv_stream(messages, temperature, top_p, max_tokens):
161
  reply_full = partial
162
+
163
+ # Atualiza histórico no formato messages (compatível com Gradio)
164
+ dialog_history = dialog_history + [
165
+ {"role": "user", "content": user_input},
166
+ {"role": "assistant", "content": reply_full},
167
+ ]
168
  except Exception as e:
169
  reply_full = f"⚠️ Erro na API NVIDIA: {type(e).__name__}: {e}"
170
+ dialog_history = dialog_history + [
171
+ {"role": "user", "content": user_input},
172
+ {"role": "assistant", "content": reply_full},
173
+ ]
174
 
175
  return dialog_history, ""
176
 
 
181
  return [], ""
182
 
183
 
184
+ # ========= CSS =========
185
  custom_css = r"""
186
  body, .gradio-container {
187
  background: #ffffff;
 
261
 
262
 
263
  # ========= Layout Gradio =========
 
264
  with gr.Blocks(title=APP_TITLE) as demo:
 
265
  with gr.Group(elem_id="header-box"):
266
  gr.HTML(
267
  f"""
 
277
  gr.Markdown(INTRO)
278
 
279
  with gr.Row():
 
280
  with gr.Column(scale=3):
281
  with gr.Group(elem_classes="card"):
282
  gr.Markdown("### 💬 Conversa Jurídica")
283
 
284
+ # ✅ Agora o valor/retorno é messages-format (dicts role/content)
285
  chatbot_ui = gr.Chatbot(
286
  elem_id="chat-window",
287
  label="Chatbot",
 
302
  top_p = gr.Slider(0, 1, value=0.9, label="Top-p")
303
  max_tokens = gr.Slider(64, 2048, value=512, step=64, label="Max Tokens")
304
 
305
+ btn_send.click(chatbot, [txt, temperature, top_p, max_tokens], [chatbot_ui, txt])
306
+ txt.submit(chatbot, [txt, temperature, top_p, max_tokens], [chatbot_ui, txt])
307
+ btn_clear.click(clear_history, [], [chatbot_ui, txt])
308
+
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  with gr.Column(scale=2):
310
  with gr.Group(elem_classes="card"):
311
  gr.Markdown("### 💡 Sugestões rápidas")
312
  for q in SUGGESTION_QUESTIONS:
313
+ gr.Button(q, elem_classes="suggestion-btn").click(lambda s=q: s, outputs=[txt])
 
 
314
 
315
  gr.Markdown("---")
316
  gr.Markdown("### 📚 Explorar por tema")
 
318
  for theme, qs in SUGGESTIONS_THEMES.items():
319
  with gr.Accordion(theme, open=False):
320
  for q in qs:
321
+ gr.Button(q, elem_classes="suggestion-btn").click(lambda s=q: s, outputs=[txt])
322
+
323
+ gr.Markdown('<div class="app-footer">EcoLexIA · Sistema RAG para legislação ambiental em Portugal</div>')
324
 
 
 
 
325
 
 
 
326
  if __name__ == "__main__":
327
+ # Gradio 6+: css e theme no launch
328
  demo.launch(theme=gr.themes.Soft(), css=custom_css)
329
 
330
+