Ahmed-El-Sharkawy commited on
Commit
82bf06f
·
verified ·
1 Parent(s): 7e69a5b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +42 -30
app.py CHANGED
@@ -3,16 +3,20 @@ from typing import List, Dict
3
  import gradio as gr
4
  from dotenv import load_dotenv
5
  from openai import OpenAI
 
 
 
6
 
7
- # ---- Windows event loop fix ----
8
  if sys.platform.startswith("win"):
9
  try:
10
  asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
11
  except Exception:
12
  pass
13
 
14
- # ---- Env ----
15
  load_dotenv()
 
 
16
  API_KEY = os.getenv("API_KEY")
17
  HOST = os.getenv("HOST")
18
  Embed_Model_Name = os.getenv("EMBEDDING_MODEL_NAME")
@@ -24,14 +28,21 @@ RPM_LIMIT = 2
24
  MIN_SECONDS_BETWEEN = 30
25
  N_DIM = 384
26
 
27
- # ---- OpenAI client ----
28
  client = None
29
  if API_KEY:
30
  client = OpenAI(api_key=API_KEY, base_url="https://genai.ghaymah.systems")
31
 
32
- # ---- Your RAG bits ----
33
- from embedder import EmbeddingModel
34
- from Reranker import Reranker
 
 
 
 
 
 
 
35
 
36
  def safe_chat_complete(model: str, messages: List[Dict], max_tokens: int = 9000) -> str:
37
  delays = [5, 10, 20]
@@ -69,11 +80,11 @@ def build_single_system_context(query: str, max_total_chars: int = 9000, k: int
69
  snippets.append(txt)
70
 
71
  if not snippets:
72
- return ("You are a strict RAG assistant. No context was retrieved from the vector store for this query. "
73
- "If the answer is not present, say you don’t know.")
74
 
75
- header = ("You are a strict RAG assistant. Answer ONLY using the provided context snippets. "
76
- "If the answer is not present, say you don’t know. ")
77
  body_budget = max_total_chars - len(header)
78
  body_parts, used = [], 0
79
  for snip in snippets:
@@ -89,7 +100,7 @@ def build_single_system_context(query: str, max_total_chars: int = 9000, k: int
89
  footer = "Sources:\n" + "\n".join(f"- {s}" for s in uniq_sources) + "\n" if uniq_sources else ""
90
  return (header + "".join(body_parts) + footer).strip()
91
 
92
- SYSTEM_SEED = "You are a strict RAG assistant. Answer ONLY using the provided context."
93
  def init_state():
94
  return {"messages": [{"role": "system", "content": SYSTEM_SEED}], "last_call_ts": None}
95
 
@@ -101,7 +112,6 @@ def record_call_time(state: dict):
101
  state["last_call_ts"] = time.time()
102
 
103
  def respond(user_message: str, state: dict):
104
- # Basic env checks – we still show a bot response so the UI proves it’s working
105
  missing = []
106
  if not API_KEY: missing.append("API_KEY")
107
  if not HOST: missing.append("HOST")
@@ -132,19 +142,27 @@ def respond(user_message: str, state: dict):
132
  state["messages"].append({"role": "assistant", "content": reply})
133
  return reply, state
134
 
135
- # Gradio UI: messages API (Gradio >= 5)
136
- with gr.Blocks(title="Ghaymah Chatbot") as demo:
137
- state = gr.State(init_state()) # {"messages": [...], "last_call_ts": ...}
 
 
 
 
 
 
 
 
 
 
 
138
 
139
  with gr.Row():
140
  # LEFT: chat + input
141
  with gr.Column(scale=3):
142
- gr.Markdown("# ☁ Ghaymah Chatbot")
143
-
144
- # Start with an explicit empty list so it's never None
145
  chatbot = gr.Chatbot(label="Chat", height=520, type="messages", value=[])
146
-
147
- # Input + buttons under the chat
148
  txt = gr.Textbox(
149
  placeholder="Ask anything about the Ghaymah documentation…",
150
  label="Your message",
@@ -155,13 +173,13 @@ with gr.Blocks(title="Ghaymah Chatbot") as demo:
155
  send_btn = gr.Button("Send", variant="primary")
156
  clear_btn = gr.Button("Clear")
157
 
158
- # RIGHT: logo + status text (from the first screenshot), stacked vertically
159
  with gr.Column(scale=1, min_width=300):
160
  gr.Image(
161
  value="download.jpeg",
162
  interactive=False,
163
  show_label=False,
164
- container=False, # no surrounding card/frame
165
  show_fullscreen_button=False,
166
  )
167
  gr.Markdown(
@@ -170,24 +188,21 @@ with gr.Blocks(title="Ghaymah Chatbot") as demo:
170
  f"RPM limit: **{RPM_LIMIT}** (min {MIN_SECONDS_BETWEEN}s between calls) \n"
171
  )
172
 
173
- # Step 1: add a user message immediately
174
  def _on_user_submit(user_input, chat_messages):
175
  try:
176
  if not user_input:
177
  return "", (chat_messages or [])
178
- chat_messages = chat_messages or [] # guard for None
179
  updated = chat_messages + [{"role": "user", "content": user_input}]
180
  print("[on_submit] user:", user_input)
181
  return "", updated
182
  except Exception as e:
183
  print("[on_submit][ERROR]", repr(e))
184
- # keep textbox text so you can retry; don't mutate chat on error
185
  return user_input, (chat_messages or [])
186
 
187
  txt.submit(_on_user_submit, [txt, chatbot], [txt, chatbot])
188
  send_btn.click(_on_user_submit, [txt, chatbot], [txt, chatbot])
189
 
190
- # Step 2: call backend and append assistant message
191
  def _bot_step(chat_messages, state):
192
  try:
193
  chat_messages = chat_messages or []
@@ -201,24 +216,21 @@ with gr.Blocks(title="Ghaymah Chatbot") as demo:
201
  return chat_messages, state
202
 
203
  print("[bot_step] responding to:", last_user)
204
- bot_reply, new_state = respond(last_user, state) # <-- your 2-arg respond
205
 
206
  updated = chat_messages + [{"role": "assistant", "content": bot_reply}]
207
  return updated, new_state
208
 
209
  except Exception as e:
210
  print("[bot_step][ERROR]", repr(e))
211
- # show the error in the chat so you see *something* in the UI
212
  updated = (chat_messages or []) + [
213
  {"role": "assistant", "content": f"⚠️ Internal error: {e}"}
214
  ]
215
  return updated, state
216
 
217
- # Submit (Enter)
218
  txt.submit(_on_user_submit, [txt, chatbot], [txt, chatbot])\
219
  .then(_bot_step, [chatbot, state], [chatbot, state])
220
 
221
- # Click (Send)
222
  send_btn.click(_on_user_submit, [txt, chatbot], [txt, chatbot])\
223
  .then(_bot_step, [chatbot, state], [chatbot, state])
224
 
 
3
  import gradio as gr
4
  from dotenv import load_dotenv
5
  from openai import OpenAI
6
+ import base64
7
+ from embedder import EmbeddingModel
8
+ from Reranker import Reranker
9
 
 
10
  if sys.platform.startswith("win"):
11
  try:
12
  asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
13
  except Exception:
14
  pass
15
 
16
+ # Env
17
  load_dotenv()
18
+ APP_Name = os.getenv("APP_Name", "Rag chatbot in Ghaymah documentation system")
19
+ APP_Version = os.getenv("APP_Version", "1.0.0")
20
  API_KEY = os.getenv("API_KEY")
21
  HOST = os.getenv("HOST")
22
  Embed_Model_Name = os.getenv("EMBEDDING_MODEL_NAME")
 
28
  MIN_SECONDS_BETWEEN = 30
29
  N_DIM = 384
30
 
31
+ # OpenAI client
32
  client = None
33
  if API_KEY:
34
  client = OpenAI(api_key=API_KEY, base_url="https://genai.ghaymah.systems")
35
 
36
+ CSS = """
37
+ .app-header{display:flex;align-items:center;gap:12px;justify-content:center;margin:6px 0 16px}
38
+ .app-header img{height:60px;border-radius:12px}
39
+ .app-title{font-weight:800;font-size:28px;line-height:1.1}
40
+ .app-sub{opacity:.7;font-size:14px}
41
+ """
42
+
43
+ COMPANY_LOGO = "download.jpeg"
44
+ OWNER_NAME = "ENG. Ahmed Yasser El Sharkawy"
45
+
46
 
47
  def safe_chat_complete(model: str, messages: List[Dict], max_tokens: int = 9000) -> str:
48
  delays = [5, 10, 20]
 
80
  snippets.append(txt)
81
 
82
  if not snippets:
83
+ return ("You are ghaymah expert . follow instraction to be strict RAG assistant. No context was retrieved from the vector store for this query. "
84
+ "If the answer is not present, say do not mention in ghaymah documentation.")
85
 
86
+ header = ("You are ghaymah expert. follow instraction to be strict RAG assistant. Answer ONLY using the provided context snippets. "
87
+ "If the answer is not present, say do not mention in ghaymah documentation.")
88
  body_budget = max_total_chars - len(header)
89
  body_parts, used = [], 0
90
  for snip in snippets:
 
100
  footer = "Sources:\n" + "\n".join(f"- {s}" for s in uniq_sources) + "\n" if uniq_sources else ""
101
  return (header + "".join(body_parts) + footer).strip()
102
 
103
+ SYSTEM_SEED = "You are ghaymah expert. follow instraction to be strict RAG assistant. Answer ONLY using the provided context snippets."
104
  def init_state():
105
  return {"messages": [{"role": "system", "content": SYSTEM_SEED}], "last_call_ts": None}
106
 
 
112
  state["last_call_ts"] = time.time()
113
 
114
  def respond(user_message: str, state: dict):
 
115
  missing = []
116
  if not API_KEY: missing.append("API_KEY")
117
  if not HOST: missing.append("HOST")
 
142
  state["messages"].append({"role": "assistant", "content": reply})
143
  return reply, state
144
 
145
+ # Gradio UI
146
+ with gr.Blocks(title=f"{APP_Name} v{APP_Version}", css=CSS) as demo:
147
+ header_logo_src = logo_data_uri(COMPANY_LOGO)
148
+ logo_html = f"<img src='{header_logo_src}' alt='logo'>" if header_logo_src else ""
149
+ gr.HTML(f"""
150
+ <div class="app-header">
151
+ {logo_html}
152
+ <div class="app-header-text">
153
+ <div class="app-title">{APP_Name}</div>
154
+ <div class="app-sub">v{APP_Version} • {OWNER_NAME}</div>
155
+ </div>
156
+ </div>
157
+ """)
158
+ state = gr.State(init_state())
159
 
160
  with gr.Row():
161
  # LEFT: chat + input
162
  with gr.Column(scale=3):
163
+
 
 
164
  chatbot = gr.Chatbot(label="Chat", height=520, type="messages", value=[])
165
+
 
166
  txt = gr.Textbox(
167
  placeholder="Ask anything about the Ghaymah documentation…",
168
  label="Your message",
 
173
  send_btn = gr.Button("Send", variant="primary")
174
  clear_btn = gr.Button("Clear")
175
 
176
+ # RIGHT
177
  with gr.Column(scale=1, min_width=300):
178
  gr.Image(
179
  value="download.jpeg",
180
  interactive=False,
181
  show_label=False,
182
+ container=False,
183
  show_fullscreen_button=False,
184
  )
185
  gr.Markdown(
 
188
  f"RPM limit: **{RPM_LIMIT}** (min {MIN_SECONDS_BETWEEN}s between calls) \n"
189
  )
190
 
 
191
  def _on_user_submit(user_input, chat_messages):
192
  try:
193
  if not user_input:
194
  return "", (chat_messages or [])
195
+ chat_messages = chat_messages or []
196
  updated = chat_messages + [{"role": "user", "content": user_input}]
197
  print("[on_submit] user:", user_input)
198
  return "", updated
199
  except Exception as e:
200
  print("[on_submit][ERROR]", repr(e))
 
201
  return user_input, (chat_messages or [])
202
 
203
  txt.submit(_on_user_submit, [txt, chatbot], [txt, chatbot])
204
  send_btn.click(_on_user_submit, [txt, chatbot], [txt, chatbot])
205
 
 
206
  def _bot_step(chat_messages, state):
207
  try:
208
  chat_messages = chat_messages or []
 
216
  return chat_messages, state
217
 
218
  print("[bot_step] responding to:", last_user)
219
+ bot_reply, new_state = respond(last_user, state)
220
 
221
  updated = chat_messages + [{"role": "assistant", "content": bot_reply}]
222
  return updated, new_state
223
 
224
  except Exception as e:
225
  print("[bot_step][ERROR]", repr(e))
 
226
  updated = (chat_messages or []) + [
227
  {"role": "assistant", "content": f"⚠️ Internal error: {e}"}
228
  ]
229
  return updated, state
230
 
 
231
  txt.submit(_on_user_submit, [txt, chatbot], [txt, chatbot])\
232
  .then(_bot_step, [chatbot, state], [chatbot, state])
233
 
 
234
  send_btn.click(_on_user_submit, [txt, chatbot], [txt, chatbot])\
235
  .then(_bot_step, [chatbot, state], [chatbot, state])
236