Geoeasy commited on
Commit
0ca5822
·
verified ·
1 Parent(s): 060b339

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -36
app.py CHANGED
@@ -3,47 +3,87 @@ from pathlib import Path
3
  import gradio as gr
4
  import numpy as np
5
  import faiss
 
6
  from openai import OpenAI, OpenAIError
7
- from langchain_community.document_loaders import PyPDFLoader
8
- from langchain.text_splitter import RecursiveCharacterTextSplitter
9
 
10
  # ----------------------------
11
- # Context retrieval using local SentenceTransformer embeddings
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  # ----------------------------
13
- # Embedding model for context retrieval (local)
14
  embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
15
 
16
  def retrieve_context(query: str, k: int = 4) -> str:
17
- # encode locally
18
  q_emb = embedding_model.encode([query], convert_to_numpy=True)
19
  _, I = index.search(q_emb, k)
20
- return "
21
- ---
22
- ".join(chunks[i] for i in I[0])(query: str, k: int = 4) -> str:
23
- # call NVIDIA embeddings
24
- try:
25
- resp = client.embeddings.create(
26
- model=EMBED_MODEL,
27
- input=[query]
28
- )
29
- q_emb = np.array(resp.data[0].embedding, dtype=np.float32)
30
- except OpenAIError as e:
31
- raise RuntimeError(f"Embedding error: {e}")
32
- # search top k
33
- _, I = tmp_index.search(q_emb.reshape(1, -1), k)
34
  return "\n---\n".join(chunks[i] for i in I[0])
35
 
36
  # ----------------------------
37
- # Chatbot logic
38
  # ----------------------------
39
  dialog_history: list[tuple[str, str]] = []
40
 
41
- def chatbot(user_input, temperature, top_p, max_tokens):
 
 
 
42
  global dialog_history
43
  if not user_input:
44
  return dialog_history, ""
45
 
46
- # retrieve context
47
  context = retrieve_context(user_input)
48
  system_msg = {
49
  "role": "system",
@@ -53,16 +93,17 @@ def chatbot(user_input, temperature, top_p, max_tokens):
53
  f"=== Retrieved Context ===\n{context}\n\n"
54
  )
55
  }
56
- # build messages
 
57
  messages = [system_msg]
58
  for u, a in dialog_history:
59
- messages.extend([
60
  {"role": "user", "content": u},
61
  {"role": "assistant", "content": a}
62
- ])
63
  messages.append({"role": "user", "content": user_input})
64
 
65
- # call NVIDIA chat API streaming
66
  assistant_reply = ""
67
  try:
68
  stream = client.chat.completions.create(
@@ -83,7 +124,9 @@ def chatbot(user_input, temperature, top_p, max_tokens):
83
  dialog_history.append((user_input, assistant_reply))
84
  return dialog_history, ""
85
 
86
- # clear history
 
 
87
  def clear_history():
88
  global dialog_history
89
  dialog_history = []
@@ -101,13 +144,44 @@ custom_css = r"""
101
  --radius: 8px;
102
  --spacing: 1rem;
103
  }
104
- body { background: var(--bg-light); color: var(--txt-dark); font-family: 'Helvetica Neue', sans-serif; }
105
- #chat-window { height: 65vh; overflow-y: auto; padding: var(--spacing); border: 1px solid #ddd; border-radius: var(--radius); }
106
- #input-area { display: flex; margin-top: var(--spacing); }
107
- #user-input { flex: 1; padding: 0.6rem; border: 1px solid #ccc; border-radius: var(--radius) 0 0 var(--radius); }
108
- #send-button { padding: 0 1rem; background: var(--primary); color: white; border: none; border-radius: 0 var(--radius) var(--radius) 0; cursor: pointer; }
109
- .sidebar { background: var(--bg-light); padding: var(--spacing); border-left: 1px solid #eee; }
110
- .sidebar h3 { margin-top: 0; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  """
112
 
113
  with gr.Blocks(title=APP_TITLE, css=custom_css, theme=gr.themes.Base()) as demo:
@@ -115,15 +189,21 @@ with gr.Blocks(title=APP_TITLE, css=custom_css, theme=gr.themes.Base()) as demo:
115
  gr.Markdown(INTRO)
116
 
117
  with gr.Row():
 
118
  with gr.Column(scale=3):
119
  chatbot_ui = gr.Chatbot(type="tuples", elem_id="chat-window")
120
  with gr.Row(elem_id="input-area"):
121
  txt = gr.Textbox(placeholder="Digite sua pergunta…", lines=2, elem_id="user-input")
122
  btn = gr.Button("Enviar", elem_id="send-button")
123
- btn.click(chatbot, [txt, gr.Slider(0,1,0.6), gr.Slider(0,1,0.95), gr.Slider(64,2048,512)], [chatbot_ui, txt])
124
- txt.submit(chatbot, [txt, gr.Slider(0,1,0.6), gr.Slider(0,1,0.95), gr.Slider(64,2048,512)], [chatbot_ui, txt])
 
 
 
 
125
  gr.Button("Limpar").click(clear_history, [], [chatbot_ui, txt])
126
 
 
127
  with gr.Column(scale=1, elem_classes="sidebar"):
128
  if Path(PDF_PATH).exists():
129
  gr.Markdown(f"[📄 Baixar CV em PDF](/file={PDF_PATH})")
@@ -140,3 +220,4 @@ if __name__ == "__main__":
140
 
141
 
142
 
 
 
3
  import gradio as gr
4
  import numpy as np
5
  import faiss
6
+ from sentence_transformers import SentenceTransformer
7
  from openai import OpenAI, OpenAIError
 
 
8
 
9
  # ----------------------------
10
+ # NVIDIA API Key (via Space Variables & Secrets)
11
+ # ----------------------------
12
+ NV_API_KEY = os.environ.get("NV_API_KEY")
13
+ if not NV_API_KEY:
14
+ raise RuntimeError(
15
+ "🔒 NV_API_KEY not set. "
16
+ "In your Hugging Face Space, go to Settings → Variables & Secrets and create NV_API_KEY."
17
+ )
18
+
19
+ # NVIDIA-compatible OpenAI client for chat
20
+ client = OpenAI(
21
+ base_url="https://integrate.api.nvidia.com/v1",
22
+ api_key=NV_API_KEY
23
+ )
24
+ CHAT_MODEL = "meta/llama3-8b-instruct"
25
+
26
+ # ----------------------------
27
+ # Application configuration
28
+ # ----------------------------
29
+ APP_TITLE = "CVchat – Ronaldo Menezes"
30
+ INTRO = (
31
+ "👋 Olá! Eu sou o CVchat do Ronaldo Menezes.\n"
32
+ "Converse sobre minha experiência, projetos, tecnologias, resultados e muito mais.\n\n"
33
+ "Exemplos de perguntas:\n"
34
+ "• Quem é o Ronaldo Menezes\n"
35
+ "• Resuma sua experiência com Process Mining.\n"
36
+ "• Que linguagens e ferramentas você domina?\n"
37
+ "• Fale de um projeto com financiamento público que você liderou.\n"
38
+ )
39
+ SUGGESTION_QUESTIONS = [
40
+ "Links & exemplos de trabalhos",
41
+ "Quais tecnologias você mais usa?",
42
+ "Resuma sua experiência com Machine Learning.",
43
+ "Artigo sobre Landsat ou Sentinel?",
44
+ "Você já trabalhou com mainframe/COBOL?",
45
+ "Certificações?",
46
+ ]
47
+
48
+ # Paths for FAISS files
49
+ INDEX_FILE = "r_docs.index"
50
+ CHUNKS_FILE = "r_chunks.npy"
51
+ PDF_PATH = "CV-Ronaldo_Menezes_2025_06.pdf"
52
+
53
+ # verify index files exist
54
+ if not Path(INDEX_FILE).exists() or not Path(CHUNKS_FILE).exists():
55
+ raise FileNotFoundError(
56
+ "Index not found. Run build_index.py to generate r_docs.index and r_chunks.npy."
57
+ )
58
+
59
+ # load FAISS index and chunks
60
+ index = faiss.read_index(INDEX_FILE)
61
+ chunks = np.load(CHUNKS_FILE, allow_pickle=True)(CHUNKS_FILE, allow_pickle=True)
62
+
63
+ # ----------------------------
64
+ # Local embedding model (context retrieval)
65
  # ----------------------------
 
66
  embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
67
 
68
  def retrieve_context(query: str, k: int = 4) -> str:
 
69
  q_emb = embedding_model.encode([query], convert_to_numpy=True)
70
  _, I = index.search(q_emb, k)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  return "\n---\n".join(chunks[i] for i in I[0])
72
 
73
  # ----------------------------
74
+ # Chatbot state
75
  # ----------------------------
76
  dialog_history: list[tuple[str, str]] = []
77
 
78
+ # ----------------------------
79
+ # Chat function
80
+ # ----------------------------
81
+ def chatbot(user_input: str, temperature: float, top_p: float, max_tokens: int):
82
  global dialog_history
83
  if not user_input:
84
  return dialog_history, ""
85
 
86
+ # build system message with retrieved context
87
  context = retrieve_context(user_input)
88
  system_msg = {
89
  "role": "system",
 
93
  f"=== Retrieved Context ===\n{context}\n\n"
94
  )
95
  }
96
+
97
+ # assemble conversation
98
  messages = [system_msg]
99
  for u, a in dialog_history:
100
+ messages += [
101
  {"role": "user", "content": u},
102
  {"role": "assistant", "content": a}
103
+ ]
104
  messages.append({"role": "user", "content": user_input})
105
 
106
+ # call NVIDIA chat API
107
  assistant_reply = ""
108
  try:
109
  stream = client.chat.completions.create(
 
124
  dialog_history.append((user_input, assistant_reply))
125
  return dialog_history, ""
126
 
127
+ # ----------------------------
128
+ # Clear chat history
129
+ # ----------------------------
130
  def clear_history():
131
  global dialog_history
132
  dialog_history = []
 
144
  --radius: 8px;
145
  --spacing: 1rem;
146
  }
147
+ body {
148
+ background: var(--bg-light);
149
+ color: var(--txt-dark);
150
+ font-family: 'Helvetica Neue', sans-serif;
151
+ }
152
+ #chat-window {
153
+ height: 65vh;
154
+ overflow-y: auto;
155
+ padding: var(--spacing);
156
+ border: 1px solid #ddd;
157
+ border-radius: var(--radius);
158
+ }
159
+ #input-area {
160
+ display: flex;
161
+ margin-top: var(--spacing);
162
+ }
163
+ #user-input {
164
+ flex: 1;
165
+ padding: 0.6rem;
166
+ border: 1px solid #ccc;
167
+ border-radius: var(--radius) 0 0 var(--radius);
168
+ }
169
+ #send-button {
170
+ padding: 0 1rem;
171
+ background: var(--primary);
172
+ color: white;
173
+ border: none;
174
+ border-radius: 0 var(--radius) var(--radius) 0;
175
+ cursor: pointer;
176
+ }
177
+ .sidebar {
178
+ background: var(--bg-light);
179
+ padding: var(--spacing);
180
+ border-left: 1px solid #eee;
181
+ }
182
+ .sidebar h3 {
183
+ margin-top: 0;
184
+ }
185
  """
186
 
187
  with gr.Blocks(title=APP_TITLE, css=custom_css, theme=gr.themes.Base()) as demo:
 
189
  gr.Markdown(INTRO)
190
 
191
  with gr.Row():
192
+ # main chat column
193
  with gr.Column(scale=3):
194
  chatbot_ui = gr.Chatbot(type="tuples", elem_id="chat-window")
195
  with gr.Row(elem_id="input-area"):
196
  txt = gr.Textbox(placeholder="Digite sua pergunta…", lines=2, elem_id="user-input")
197
  btn = gr.Button("Enviar", elem_id="send-button")
198
+ btn.click(chatbot,
199
+ [txt, gr.Slider(0,1,0.6), gr.Slider(0,1,0.95), gr.Slider(64,2048,512)],
200
+ [chatbot_ui, txt])
201
+ txt.submit(chatbot,
202
+ [txt, gr.Slider(0,1,0.6), gr.Slider(0,1,0.95), gr.Slider(64,2048,512)],
203
+ [chatbot_ui, txt])
204
  gr.Button("Limpar").click(clear_history, [], [chatbot_ui, txt])
205
 
206
+ # sidebar with PDF & suggestions
207
  with gr.Column(scale=1, elem_classes="sidebar"):
208
  if Path(PDF_PATH).exists():
209
  gr.Markdown(f"[📄 Baixar CV em PDF](/file={PDF_PATH})")
 
220
 
221
 
222
 
223
+