""" Naveed AI — Fast Conversational Chat Built by Naveed Khan | Powered by Qwen2.5 | Free Forever """ import os import re import json # ── Speed: silence tokenizer noise ──────────────────────────────────────────── os.environ.setdefault("TOKENIZERS_PARALLELISM", "false") # ── Bootstrap ───────────────────────────────────────────────────────────────── print("🚀 Starting Naveed AI…", flush=True) from config import get_config from model_loader import ModelLoader from inference import InferenceEngine cfg = get_config() _loader = ModelLoader(cfg) print(f"📦 Loading model: {cfg.model.default_model}", flush=True) _loader.load(model_id=cfg.model.default_model, auto_download=True) print("✅ Model ready!", flush=True) engine = InferenceEngine(_loader, cfg) # ── Gradio ───────────────────────────────────────────────────────────────────── import gradio as gr try: GRADIO_MAJOR = int(str(gr.__version__).split(".")[0]) except Exception: GRADIO_MAJOR = 4 USE_MSG_FMT = GRADIO_MAJOR >= 5 # message-dict format (v5/v6) vs tuple format (v4) # Gradio 6 removed type= param — messages format is always the default USE_TYPE_PARAM = (4 < GRADIO_MAJOR < 6) # only Gradio 5.x needs explicit type="messages" print(f"🎨 Gradio {gr.__version__} — {'messages' if USE_MSG_FMT else 'tuples'} mode", flush=True) # ── Helpers ──────────────────────────────────────────────────────────────────── def _text(content) -> str: """Normalise any Gradio message content → plain string.""" if content is None: return "" if isinstance(content, str): return content if isinstance(content, (int, float, bool)): return str(content) if isinstance(content, list): return " ".join(_text(i) for i in content if _text(i)).strip() if isinstance(content, dict): return _text(content.get("text") or content.get("content") or "") return str(content) def _render_think(text: str) -> str: """Convert blocks into a readable quote.""" def _block(m): thought = m.group(1).strip() return f"\n\n💭 *Thinking:*\n> {thought}\n\n---\n\n" return re.sub(r"(.*?)", _block, text, flags=re.DOTALL) # ── Chat function ────────────────────────────────────────────────────────────── def chat_fn(message: str, history): """ Real-time streaming chat. - history is a list of message-dicts (v5+) or [user, assistant] tuples (v4). - Yields updated history after every token so the UI streams live. """ message = message.strip() if not message: yield history return # Build messages list: system + trimmed history + new user turn sys_prompt = cfg.conversation.system_prompt messages = [{"role": "system", "content": sys_prompt}] max_turns = cfg.conversation.max_history_turns recent = history[-max_turns:] if len(history) > max_turns else history for item in recent: if USE_MSG_FMT: role = item.get("role", "user") content = _text(item.get("content", "")) if content and role in ("user", "assistant"): messages.append({"role": role, "content": content}) else: u = _text(item[0]) if len(item) > 0 else "" a = _text(item[1]) if len(item) > 1 else "" if u: messages.append({"role": "user", "content": u}) if a: messages.append({"role": "assistant", "content": a}) messages.append({"role": "user", "content": message}) # Append user turn to display history if USE_MSG_FMT: history = list(history) + [{"role": "user", "content": message}] else: history = list(history) + [[message, None]] # Stream assistant reply token-by-token response = "" try: for token in engine.chat_generate(messages, stream=True): response += token # Only run regex if tag is present (avoids regex overhead on every token) rendered = _render_think(response) if "" in response else response if USE_MSG_FMT: yield history + [{"role": "assistant", "content": rendered}] else: yield history[:-1] + [[message, rendered]] except Exception as exc: err = f"⚠️ Sorry, something went wrong: {exc}" if USE_MSG_FMT: yield history + [{"role": "assistant", "content": err}] else: yield history[:-1] + [[message, err]] return # Commit final clean turn final = _render_think(response) if "" in response else response if USE_MSG_FMT: yield history + [{"role": "assistant", "content": final}] else: yield history[:-1] + [[message, final]] # ── CSS ──────────────────────────────────────────────────────────────────────── CSS = """ .gradio-container { max-width: 860px !important; margin: auto !important; font-family: 'Inter', 'Segoe UI', system-ui, sans-serif !important; } footer { display: none !important; } .header-wrap { background: linear-gradient(135deg, #0f0c29 0%, #302b63 50%, #24243e 100%); border-radius: 16px; padding: 24px 32px 20px; margin-bottom: 12px; text-align: center; border: 1px solid #7c3aed33; } .header-wrap h1 { background: linear-gradient(135deg, #a78bfa, #60a5fa, #34d399); -webkit-background-clip: text; -webkit-text-fill-color: transparent; font-size: 2.3em; margin: 0 0 4px; font-weight: 800; letter-spacing: -0.6px; } .header-wrap p { color: #94a3b8; margin: 0; font-size: 0.96em; } .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #22c55e; margin-right: 6px; vertical-align: middle; animation: blink 2s infinite; } @keyframes blink { 0%,100%{opacity:1;} 50%{opacity:.35;} } #send-btn { background: #111827 !important; color: #fff !important; border-radius: 10px !important; font-weight: 600 !important; min-height: 48px !important; } #send-btn:hover { background: #1f2937 !important; } #clear-btn { border-radius: 10px !important; } /* API snippet accordion */ .api-accordion { margin-top: 10px; border: 1px solid #334155 !important; border-radius: 12px !important; background: #0f172a !important; } .api-accordion .label-wrap span { font-size: 0.9em !important; color: #94a3b8 !important; font-weight: 500 !important; } .api-tabs .tab-nav button { font-size: 0.82em !important; padding: 4px 10px !important; } .api-code pre { font-size: 0.82em !important; border-radius: 8px !important; background: #1e293b !important; } """ # ── Gradio UI ────────────────────────────────────────────────────────────────── with gr.Blocks(title="Naveed AI") as demo: # ── Header ────────────────────────────────────────────────────────────── gr.HTML("""

🧠 Naveed AI

Built by Naveed Khan  ·  Smart · Fast · Free Forever

""") # ── Chatbot ───────────────────────────────────────────────────────────── bot_kwargs = dict( value=[], show_label=False, height=520, ) if USE_TYPE_PARAM: bot_kwargs["type"] = "messages" chatbot = gr.Chatbot(**bot_kwargs) # ── Input row ─────────────────────────────────────────────────────────── with gr.Row(): msg = gr.Textbox( placeholder="Message Naveed AI…", show_label=False, scale=9, container=False, autofocus=True, lines=1, max_lines=6, elem_id="msg-input", ) send = gr.Button("Send ➤", elem_id="send-btn", scale=1, min_width=90) # Rotating placeholder via JS injected into page gr.HTML(""" """) # ── Controls ──────────────────────────────────────────────────────────── with gr.Row(): clear = gr.Button("🗑 Clear chat", variant="secondary", size="sm", elem_id="clear-btn", scale=1) gr.HTML('
') # spacer # ── Starter examples ──────────────────────────────────────────────────── gr.Examples( label="💡 Try asking…", examples=[ ["Who are you and what can you do?"], ["Explain quantum computing like I'm 10 years old"], ["Write a Python script to fetch today's Bitcoin price"], ["Give me a 7-day workout plan for a beginner"], ["Help me write a resignation letter — professional but friendly"], ["I heard coffee causes cancer. Is that true?"], ["What are the top 5 habits of highly successful people?"], ["Tell me something fascinating about the universe"], ], inputs=msg, ) # ── API code snippets (collapsible) ───────────────────────────────────────────────── with gr.Accordion("🔌 Use Naveed AI in your own app — free API", open=False, elem_classes=["api-accordion"]): with gr.Tabs(elem_classes=["api-tabs"]): with gr.TabItem("🐍 Python"): gr.Code( value='''from gradio_client import Client client = Client("bilalnaveed/Naveedai") # Single message result = client.predict( message="What are the top habits of successful people?", history=[], api_name="/chat_fn" ) print(result[-1]["content"]) # last assistant reply # Multi-turn conversation history = [] def ask(msg): global history history = client.predict(message=msg, history=history, api_name="/chat_fn") last = history[-1] return last.get("content", "") if isinstance(last, dict) else last[1] print(ask("Hello!")) print(ask("Tell me a fun science fact")) ''', language="python", elem_classes=["api-code"], interactive=False, ) with gr.TabItem("🌐 JavaScript"): gr.Code( value='''// Works in browser or Node.js — no API key needed async function askNaveedAI(message, history = []) { const res = await fetch( "https://bilalnaveed-naveedai.hf.space/run/predict", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ data: [message, history] }), } ); const json = await res.json(); const updatedHistory = json.data[0]; // full history array const lastMsg = updatedHistory[updatedHistory.length - 1]; return typeof lastMsg === "object" && lastMsg.content ? lastMsg.content : lastMsg[1]; // tuple fallback } // Usage askNaveedAI("Explain machine learning in 2 sentences").then(console.log); ''', language="javascript", elem_classes=["api-code"], interactive=False, ) with gr.TabItem("💻 cURL"): gr.Code( value='''# Call from any terminal — completely free curl -X POST "https://bilalnaveed-naveedai.hf.space/run/predict" \\ -H "Content-Type: application/json" \\ -d \'{"data": ["Who are you?", []]}\'\n''', language="shell", elem_classes=["api-code"], interactive=False, ) # ── Events ────────────────────────────────────────────────────────────── send.click(chat_fn, [msg, chatbot], [chatbot]).then( lambda: gr.update(value=""), None, [msg] ) msg.submit(chat_fn, [msg, chatbot], [chatbot]).then( lambda: gr.update(value=""), None, [msg] ) clear.click(lambda: [], None, [chatbot]) # ── Launch ───────────────────────────────────────────────────────────────────── demo.queue(max_size=15).launch( server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)), show_error=True, quiet=False, theme=gr.themes.Soft( primary_hue="violet", secondary_hue="blue", neutral_hue="slate", font=gr.themes.GoogleFont("Inter"), ), css=CSS, )