rahul7star commited on
Commit
d1693de
·
verified ·
1 Parent(s): 96e1647

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +131 -48
app.py CHANGED
@@ -1,10 +1,11 @@
1
  """
2
- OhamLab — AI Intelligence
3
  Loads knowledge from rahul7star/OhamLab-LLM markdown corpus, caches embeddings,
4
  and provides retrieval-augmented chat through Hugging Face router.
5
  """
6
 
7
  import os
 
8
  import json
9
  import time
10
  import textwrap
@@ -25,11 +26,12 @@ HF_TOKEN = (
25
  if not HF_TOKEN:
26
  raise RuntimeError("❌ Missing HF_TOKEN / OPENAI_API_KEY / HUGGINGFACE_TOKEN environment variable.")
27
 
28
- MODEL_ID = "openai/gpt-oss-20b" # Chat model (via HF router)
29
- EMBED_MODEL = "BAAI/bge-small-en-v1.5" # Router-compatible embedding model
30
- HF_REPO = "rahul7star/OhamLab-LLM" # Knowledge repo
31
- CACHE_PATH = "/tmp/ohamlab_emb_cache.json" # Cache file
32
 
 
33
  client = OpenAI(base_url="https://router.huggingface.co/v1", api_key=HF_TOKEN)
34
  api = HfApi(token=HF_TOKEN)
35
 
@@ -37,7 +39,7 @@ api = HfApi(token=HF_TOKEN)
37
  # 2. Load and Chunk Markdown Files
38
  # ---------------------------
39
  def load_ohamlab_knowledge():
40
- """Load all .md files from Hugging Face repo and split into ~500-char chunks."""
41
  files = list_repo_files(HF_REPO, repo_type="model", token=HF_TOKEN)
42
  md_files = [f for f in files if f.endswith(".md")]
43
  chunks = []
@@ -56,25 +58,13 @@ def load_ohamlab_knowledge():
56
  chunks.append({"file": f, "text": buf.strip()})
57
  except Exception as e:
58
  print(f"⚠️ Failed to load {f}: {e}")
59
- print(f"📚 Loaded {len(chunks)} text chunks from {len(md_files)} markdown files.")
60
  return chunks
61
 
62
  # ---------------------------
63
- # 3. Embeddings (with Cache & Retry)
64
  # ---------------------------
65
- def create_embeddings_with_retry(texts, retries=3, delay=2):
66
- """Generate embeddings with retries on failure."""
67
- for attempt in range(retries):
68
- try:
69
- res = client.embeddings.create(model=EMBED_MODEL, input=texts)
70
- return [d.embedding for d in res.data]
71
- except Exception as e:
72
- print(f"⚠️ Embedding attempt {attempt+1} failed: {e}")
73
- time.sleep(delay)
74
- raise RuntimeError("❌ Failed to generate embeddings after retries.")
75
-
76
  def get_embeddings_with_cache():
77
- """Generate or load cached embeddings for OhamLab knowledge."""
78
  if os.path.exists(CACHE_PATH):
79
  try:
80
  with open(CACHE_PATH, "r") as f:
@@ -89,12 +79,16 @@ def get_embeddings_with_cache():
89
  chunks = load_ohamlab_knowledge()
90
  texts = [c["text"] for c in chunks]
91
  print(f"📘 Generating embeddings for {len(texts)} OhamLab chunks...")
92
-
93
  all_embs = []
94
  for i in range(0, len(texts), 50):
95
  batch = texts[i:i + 50]
96
- embs = create_embeddings_with_retry(batch)
97
- all_embs.extend(embs)
 
 
 
 
 
98
  time.sleep(0.5)
99
 
100
  data = [{"text": t, "embedding": e} for t, e in zip(texts, all_embs)]
@@ -109,9 +103,9 @@ OHAMLAB_TEXTS, OHAMLAB_EMBS = get_embeddings_with_cache()
109
  # 4. Semantic Retrieval
110
  # ---------------------------
111
  def retrieve_knowledge(query, top_k=3):
112
- """Retrieve top-k most relevant text snippets from markdown knowledge bank."""
113
  try:
114
- q_emb = create_embeddings_with_retry([query])[0]
115
  sims = np.dot(OHAMLAB_EMBS, q_emb) / (
116
  np.linalg.norm(OHAMLAB_EMBS, axis=1) * np.linalg.norm(q_emb)
117
  )
@@ -122,17 +116,17 @@ def retrieve_knowledge(query, top_k=3):
122
  return ""
123
 
124
  # ---------------------------
125
- # 5. System Prompt
126
  # ---------------------------
127
  def build_system_prompt(context: str, mode: str = "chat") -> str:
128
  return textwrap.dedent(f"""
129
- You are OhamLab — AI Intelligence Software.
130
 
131
  Guidelines:
132
- - Only answer using information retrieved from the OhamLab knowledge bank (.md files).
133
- - Do NOT hallucinate. If the answer is not found, respond: "I could not find an answer in my knowledge base."
134
- - Always answer with clarity, precision, and factual grounding.
135
  - Avoid code unless explicitly requested.
 
136
  - Mode: {mode.upper()}
137
 
138
  --- OhamLab Context (Retrieved Snippets) ---
@@ -141,7 +135,7 @@ def build_system_prompt(context: str, mode: str = "chat") -> str:
141
  """).strip()
142
 
143
  # ---------------------------
144
- # 6. Response Generation
145
  # ---------------------------
146
  def generate_response(user_input, history, mode="chat"):
147
  context = retrieve_knowledge(user_input)
@@ -153,28 +147,45 @@ def generate_response(user_input, history, mode="chat"):
153
  resp = client.chat.completions.create(
154
  model=MODEL_ID,
155
  messages=messages,
156
- temperature=0.0, # deterministic for knowledge-only answers
157
  max_tokens=1200,
158
  )
159
  return resp.choices[0].message.content.strip()
160
  except Exception as e:
161
  print(f"⚠️ Model call failed: {e}")
162
- return "⚠️ OhamLab encountered a temporary issue generating your response."
163
 
164
  # ---------------------------
165
- # 7. Chat Logic
166
  # ---------------------------
 
 
 
 
 
 
 
 
 
167
  def chat_with_model(user_message, chat_history):
 
 
 
 
168
  if not user_message:
169
  return chat_history, ""
 
170
  if chat_history is None:
171
  chat_history = []
172
 
 
173
  history = [
174
  {"role": m["role"], "content": m["content"]}
175
  for m in chat_history
176
  if isinstance(m, dict) and "role" in m
177
  ]
 
 
178
  history.append({"role": "user", "content": user_message})
179
 
180
  try:
@@ -183,33 +194,99 @@ def chat_with_model(user_message, chat_history):
183
  tb = traceback.format_exc()
184
  bot_reply = f"⚠️ OhamLab encountered an error:\n\n{e}\n\n{tb}"
185
 
 
186
  history.append({"role": "assistant", "content": bot_reply})
 
187
  return history, ""
188
 
 
189
  def reset_chat():
 
190
  return []
191
 
 
192
  # ---------------------------
193
- # 8. Gradio UI
194
  # ---------------------------
 
195
  def build_ui():
196
  with gr.Blocks(
197
  theme=gr.themes.Soft(primary_hue="indigo"),
198
  css="""
 
 
 
 
199
  [data-testid="share-btn"],
200
  [data-testid="delete-btn"],
201
  .message-controls,
202
- .message-actions { display: none !important; visibility: hidden !important; }
203
- #ohamlab .message.user { background-color: #4f46e5 !important; color: white !important; border-radius: 14px !important; align-self: flex-end !important; text-align: right !important; margin-left: 25%; }
204
- #ohamlab .message.assistant { background-color: #f8f9fa !important; color: #111 !important; border-radius: 14px !important; align-self: flex-start !important; text-align: left !important; margin-right: 25%; }
205
- .gradio-container { max-width: 900px !important; margin: auto; padding-top: .5rem; }
206
- textarea { resize: none !important; border-radius: 12px !important; border: 1px solid #d1d5db !important; box-shadow: 0 1px 3px rgba(0,0,0,0.08); }
207
- button.primary { background-color: #4f46e5 !important; color: white !important; border-radius: 10px !important; padding: 0.6rem 1.4rem !important; font-weight: 600; transition: all 0.2s ease-in-out; }
208
- button.primary:hover { background-color: #4338ca !important; }
209
- button.secondary { background-color: #f3f4f6 !important; border-radius: 10px !important; color: #374151 !important; font-weight: 500; transition: all 0.2s ease-in-out; }
210
- button.secondary:hover { background-color: #e5e7eb !important; }
211
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  ) as demo:
 
 
213
  chatbot = gr.Chatbot(
214
  label="💠 OhamLab Conversation",
215
  height=520,
@@ -218,24 +295,29 @@ def build_ui():
218
  avatar_images=[None, None],
219
  )
220
 
 
221
  with gr.Row():
222
  msg = gr.Textbox(
223
- placeholder="Ask OhamLab anything ...",
224
  lines=3,
225
  show_label=False,
226
  scale=12,
227
  container=False,
228
  )
229
 
 
230
  with gr.Row(equal_height=True, variant="compact"):
231
- send = gr.Button("Send", variant="primary")
232
- clear = gr.Button("Clear", variant="secondary")
233
 
 
234
  send.click(chat_with_model, inputs=[msg, chatbot], outputs=[chatbot, msg])
235
  msg.submit(chat_with_model, inputs=[msg, chatbot], outputs=[chatbot, msg])
236
  clear.click(reset_chat, outputs=chatbot)
 
237
  return demo
238
 
 
239
  # ---------------------------
240
  # Entrypoint
241
  # ---------------------------
@@ -243,3 +325,4 @@ if __name__ == "__main__":
243
  print("🚀 Starting OhamLab Assistant...")
244
  demo = build_ui()
245
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
 
1
  """
2
+ OhamLab — AI Intelligence
3
  Loads knowledge from rahul7star/OhamLab-LLM markdown corpus, caches embeddings,
4
  and provides retrieval-augmented chat through Hugging Face router.
5
  """
6
 
7
  import os
8
+ import re
9
  import json
10
  import time
11
  import textwrap
 
26
  if not HF_TOKEN:
27
  raise RuntimeError("❌ Missing HF_TOKEN / OPENAI_API_KEY / HUGGINGFACE_TOKEN environment variable.")
28
 
29
+ MODEL_ID = "openai/gpt-oss-20b" # Chat model (via HF router)
30
+ EMBED_MODEL = "text-embedding-3-small" # Embedding model
31
+ HF_REPO = "rahul7star/OhamLab-LLM" # Knowledge repo
32
+ CACHE_PATH = "/tmp/ohamlab_emb_cache.json" # Cache file
33
 
34
+ # Client
35
  client = OpenAI(base_url="https://router.huggingface.co/v1", api_key=HF_TOKEN)
36
  api = HfApi(token=HF_TOKEN)
37
 
 
39
  # 2. Load and Chunk Markdown Files
40
  # ---------------------------
41
  def load_ohamlab_knowledge():
42
+ """Loads all .md files from Hugging Face repo and splits into ~500-char chunks."""
43
  files = list_repo_files(HF_REPO, repo_type="model", token=HF_TOKEN)
44
  md_files = [f for f in files if f.endswith(".md")]
45
  chunks = []
 
58
  chunks.append({"file": f, "text": buf.strip()})
59
  except Exception as e:
60
  print(f"⚠️ Failed to load {f}: {e}")
 
61
  return chunks
62
 
63
  # ---------------------------
64
+ # 3. Generate or Load Embeddings (with Cache)
65
  # ---------------------------
 
 
 
 
 
 
 
 
 
 
 
66
  def get_embeddings_with_cache():
67
+ """Generate or load cached embeddings for OhamLab context."""
68
  if os.path.exists(CACHE_PATH):
69
  try:
70
  with open(CACHE_PATH, "r") as f:
 
79
  chunks = load_ohamlab_knowledge()
80
  texts = [c["text"] for c in chunks]
81
  print(f"📘 Generating embeddings for {len(texts)} OhamLab chunks...")
 
82
  all_embs = []
83
  for i in range(0, len(texts), 50):
84
  batch = texts[i:i + 50]
85
+ try:
86
+ res = client.embeddings.create(model=EMBED_MODEL, input=batch)
87
+ embs = [d.embedding for d in res.data]
88
+ all_embs.extend(embs)
89
+ except Exception as e:
90
+ print(f"⚠️ Embedding batch failed ({i}): {e}")
91
+ all_embs.extend([[0.0] * 1536] * len(batch)) # fallback
92
  time.sleep(0.5)
93
 
94
  data = [{"text": t, "embedding": e} for t, e in zip(texts, all_embs)]
 
103
  # 4. Semantic Retrieval
104
  # ---------------------------
105
  def retrieve_knowledge(query, top_k=3):
106
+ """Retrieve top-k most relevant text snippets."""
107
  try:
108
+ q_emb = client.embeddings.create(model=EMBED_MODEL, input=[query]).data[0].embedding
109
  sims = np.dot(OHAMLAB_EMBS, q_emb) / (
110
  np.linalg.norm(OHAMLAB_EMBS, axis=1) * np.linalg.norm(q_emb)
111
  )
 
116
  return ""
117
 
118
  # ---------------------------
119
+ # 5. System Prompt with Context Injection
120
  # ---------------------------
121
  def build_system_prompt(context: str, mode: str = "chat") -> str:
122
  return textwrap.dedent(f"""
123
+ You are OhamLab — AI Intelligence Software
124
 
125
  Guidelines:
126
+ - Always answer with clarity, scientific accuracy, and concise insight.
127
+ - Incorporate OhamLab research knowledge when relevant.
 
128
  - Avoid code unless explicitly requested.
129
+ - Be confident but label speculation clearly.
130
  - Mode: {mode.upper()}
131
 
132
  --- OhamLab Context (Retrieved Snippets) ---
 
135
  """).strip()
136
 
137
  # ---------------------------
138
+ # 6. Model Call
139
  # ---------------------------
140
  def generate_response(user_input, history, mode="chat"):
141
  context = retrieve_knowledge(user_input)
 
147
  resp = client.chat.completions.create(
148
  model=MODEL_ID,
149
  messages=messages,
150
+ temperature=0.7,
151
  max_tokens=1200,
152
  )
153
  return resp.choices[0].message.content.strip()
154
  except Exception as e:
155
  print(f"⚠️ Model call failed: {e}")
156
+ return "⚠️ OahmLab encountered a temporary issue generating your response."
157
 
158
  # ---------------------------
159
+ # 7. Gradio Chat UI
160
  # ---------------------------
161
+ import traceback
162
+ import gradio as gr
163
+
164
+ # ---------------------------
165
+ # Chat Logic
166
+ # ---------------------------
167
+
168
+
169
+
170
  def chat_with_model(user_message, chat_history):
171
+ """
172
+ Maintains full conversational context and returns updated chat history.
173
+ The assistant speaks as 'OhamLab'.
174
+ """
175
  if not user_message:
176
  return chat_history, ""
177
+
178
  if chat_history is None:
179
  chat_history = []
180
 
181
+ # Convert Gradio message list (dict-based) to usable context
182
  history = [
183
  {"role": m["role"], "content": m["content"]}
184
  for m in chat_history
185
  if isinstance(m, dict) and "role" in m
186
  ]
187
+
188
+ # Append current user message
189
  history.append({"role": "user", "content": user_message})
190
 
191
  try:
 
194
  tb = traceback.format_exc()
195
  bot_reply = f"⚠️ OhamLab encountered an error:\n\n{e}\n\n{tb}"
196
 
197
+ # Add OhamLab's response as assistant role
198
  history.append({"role": "assistant", "content": bot_reply})
199
+
200
  return history, ""
201
 
202
+
203
  def reset_chat():
204
+ """Resets the chat session."""
205
  return []
206
 
207
+
208
  # ---------------------------
209
+ # Gradio Chat UI
210
  # ---------------------------
211
+
212
  def build_ui():
213
  with gr.Blocks(
214
  theme=gr.themes.Soft(primary_hue="indigo"),
215
  css="""
216
+ /* --- Hide share/delete icons --- */
217
+ #ohamlab .wrap.svelte-1lcyrj3 > div > div > button {
218
+ display: none !important;
219
+ }
220
  [data-testid="share-btn"],
221
  [data-testid="delete-btn"],
222
  .message-controls,
223
+ .message-actions {
224
+ display: none !important;
225
+ visibility: hidden !important;
226
+ }
227
+
228
+ /* --- User (Right) Message Bubble --- */
229
+ #ohamlab .message.user {
230
+ background-color: #4f46e5 !important;
231
+ color: white !important;
232
+ border-radius: 14px !important;
233
+ align-self: flex-end !important;
234
+ text-align: right !important;
235
+ margin-left: 25%;
236
+ }
237
+
238
+ /* --- OhamLab (Left) Message Bubble --- */
239
+ #ohamlab .message.assistant {
240
+ background-color: #f8f9fa !important;
241
+ color: #111 !important;
242
+ border-radius: 14px !important;
243
+ align-self: flex-start !important;
244
+ text-align: left !important;
245
+ margin-right: 25%;
246
+ }
247
+
248
+
249
+ #ohamlab .chatbot .wrap.svelte-1lcyrj3 > div > div > button {
250
+ display: none !important; /* hide share/delete icons */
251
+ }
252
+
253
+ /* --- Overall Container --- */
254
+ .gradio-container {
255
+ max-width: 900px !important;
256
+ margin: auto;
257
+ padding-top: .5rem;
258
+ }
259
+ textarea {
260
+ resize: none !important;
261
+ border-radius: 12px !important;
262
+ border: 1px solid #d1d5db !important;
263
+ box-shadow: 0 1px 3px rgba(0,0,0,0.08);
264
+ }
265
+ button.primary {
266
+ background-color: #4f46e5 !important;
267
+ color: white !important;
268
+ border-radius: 10px !important;
269
+ padding: 0.6rem 1.4rem !important;
270
+ font-weight: 600;
271
+ transition: all 0.2s ease-in-out;
272
+ }
273
+ button.primary:hover {
274
+ background-color: #4338ca !important;
275
+ }
276
+ button.secondary {
277
+ background-color: #f3f4f6 !important;
278
+ border-radius: 10px !important;
279
+ color: #374151 !important;
280
+ font-weight: 500;
281
+ transition: all 0.2s ease-in-out;
282
+ }
283
+ button.secondary:hover {
284
+ background-color: #e5e7eb !important;
285
+ }
286
+ """,
287
  ) as demo:
288
+
289
+ # Chatbot area
290
  chatbot = gr.Chatbot(
291
  label="💠 OhamLab Conversation",
292
  height=520,
 
295
  avatar_images=[None, None],
296
  )
297
 
298
+ # Input box (full width)
299
  with gr.Row():
300
  msg = gr.Textbox(
301
+ placeholder="Ask OhamLab anything ..",
302
  lines=3,
303
  show_label=False,
304
  scale=12,
305
  container=False,
306
  )
307
 
308
+ # Buttons (Send + Clear)
309
  with gr.Row(equal_height=True, variant="compact"):
310
+ send = gr.Button("Send", variant="primary", elem_classes=["primary"])
311
+ clear = gr.Button("Clear", variant="secondary", elem_classes=["secondary"])
312
 
313
+ # Wiring
314
  send.click(chat_with_model, inputs=[msg, chatbot], outputs=[chatbot, msg])
315
  msg.submit(chat_with_model, inputs=[msg, chatbot], outputs=[chatbot, msg])
316
  clear.click(reset_chat, outputs=chatbot)
317
+
318
  return demo
319
 
320
+
321
  # ---------------------------
322
  # Entrypoint
323
  # ---------------------------
 
325
  print("🚀 Starting OhamLab Assistant...")
326
  demo = build_ui()
327
  demo.launch(server_name="0.0.0.0", server_port=7860)
328
+