Ahmed-El-Sharkawy's picture
Upload 3 files
3f41fce verified
raw
history blame
5.51 kB
import os, sys, time, asyncio
from typing import List, Dict
import gradio as gr
from dotenv import load_dotenv
# Windows event loop (prevents asyncio warnings on Win)
if sys.platform.startswith("win"):
try:
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
except Exception:
pass
# config from .env or defaults
load_dotenv()
APP_Name = os.getenv("APP_Name", "Ghaymah GenAI chatbots")
APP_Version = os.getenv("APP_Version", "0.1.0")
API_KEY = os.getenv("API_KEY", "")
# Models from .env or fallback to your set
MODELS = [m.strip() for m in os.getenv("Models", "").split(",") if m.strip()] or [
"gemma-3-4b-it",
"QwQ-32B",
"DeepSeek-V3-0324",
"Qwen/Qwen3-32B",
"zai-org/GLM-4.5-Air",
"moonshotai/Kimi-K2-Instruct",
]
# Friendly descriptions & logo
MODEL_INFO = {
"gemma-3-4b-it": "Google Gemma-3 4B Instruct — light, fast, solid reasoning.",
"QwQ-32B": "QwQ-32B — reasoning-focused; strong long-form answers.",
"DeepSeek-V3-0324": "DeepSeek V3 (0324) — versatile, great multi-step reasoning.",
"Qwen/Qwen3-32B": "Qwen3-32B — multilingual, good code & math.",
"zai-org/GLM-4.5-Air": "GLM-4.5-Air — efficient generalist, good latency.",
"moonshotai/Kimi-K2-Instruct": "Kimi K2 Instruct — long-context, helpful writing.",
}
LOGO_PATH = "download.jpeg" # change to your image if different
# ── OpenAI-compatible client ──────────────────────────────────────────────────
from openai import OpenAI
BASE_URL = "https://genai.ghaymah.systems"
client = OpenAI(api_key=API_KEY, base_url=BASE_URL) if API_KEY else None
SYSTEM_SEED = "You are Ghaymah Assistant. Be concise and helpful."
# Helpers
BACKOFF = [5, 10, 20] # basic retry for 429s
def safe_chat_complete(model: str, messages: List[Dict], max_tokens: int = 800) -> str:
if not client:
return "⚠️ Missing API_KEY in .env"
attempt = 0
while True:
try:
resp = client.chat.completions.create(
model=model,
messages=messages,
max_tokens=max_tokens,
temperature=0.3,
timeout=90,
)
return resp.choices[0].message.content or ""
except Exception as e:
msg = str(e)
if ("429" in msg or "Rate" in msg) and attempt < len(BACKOFF):
time.sleep(BACKOFF[attempt]); attempt += 1
continue
return f"Request failed for `{model}`: {e}"
def init_state():
return {"messages": [{"role": "system", "content": SYSTEM_SEED}]}
# Gradio app
with gr.Blocks(title=APP_Name) as demo:
state = gr.State(init_state())
gr.Markdown(f"# {APP_Name} \n<span style='opacity:.7'>v{APP_Version}</span>")
with gr.Row():
# Left: Chat
with gr.Column(scale=3):
chat = gr.Chatbot(label="Chat", height=520, type="messages", value=[])
user_in = gr.Textbox(label="Your message", placeholder="Type here…", lines=2)
with gr.Row():
send_btn = gr.Button("Send", variant="primary")
clear_btn = gr.Button("Clear")
# Right: Model selector + logo + info
with gr.Column(scale=1, min_width=320):
model_choice = gr.Radio(
choices=MODELS,
value=MODELS[0],
label="Models",
info="Select Your Model Here",
)
gr.Image(LOGO_PATH, show_label=False, container=False)
info_md = gr.Markdown(MODEL_INFO.get(MODELS[0], ""))
def _update_info(m: str) -> str:
title = f"**{m}**"
desc = MODEL_INFO.get(m, "")
return f"{title}\n\n{desc}"
model_choice.change(_update_info, model_choice, info_md)
# Step 1: push the user message into the chat stream
def on_submit(msg, chat_messages):
if not msg:
return "", (chat_messages or [])
updated = (chat_messages or []) + [{"role": "user", "content": msg}]
return "", updated
def bot_step(chat_messages, chosen_model, st):
msgs = [{"role": "system", "content": SYSTEM_SEED}]
# only include last 2 visible messages
for m in (chat_messages or [])[-2:]:
role, content = m.get("role"), m.get("content")
if role in ("user", "assistant") and isinstance(content, str):
msgs.append({"role": role, "content": content})
reply = safe_chat_complete(chosen_model, msgs, max_tokens=800)
updated = (chat_messages or []) + [{"role": "assistant", "content": reply}]
st = st or init_state()
st["messages"] = msgs + [{"role": "assistant", "content": reply}]
return updated, st
# Clear
def on_clear():
return [], init_state()
# Wire events
user_in.submit(on_submit, [user_in, chat], [user_in, chat]) \
.then(bot_step, [chat, model_choice, state], [chat, state])
send_btn.click(on_submit, [user_in, chat], [user_in, chat]) \
.then(bot_step, [chat, model_choice, state], [chat, state])
clear_btn.click(on_clear, outputs=[chat, state])
if __name__ == "__main__":
demo.queue()
demo.launch(debug=True)