Spaces:
Runtime error
Runtime error
File size: 15,467 Bytes
871b828 97fe68d 871b828 5291dfc 871b828 97fe68d 2577504 97fe68d 2577504 871b828 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d 087c95a 97fe68d 5291dfc 97fe68d cabb89e 97fe68d 5291dfc 97fe68d 3b3c93e 97fe68d 3b3c93e 97fe68d 3b3c93e 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d 5291dfc b76b9b2 97fe68d 5291dfc 97fe68d b76b9b2 97fe68d 5e3bbd7 5291dfc 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d c7de55e 5291dfc 871b828 97fe68d c7de55e 871b828 97fe68d 5291dfc 97fe68d 5291dfc 97fe68d 5291dfc 871b828 97fe68d cabb89e 97fe68d c7de55e 97fe68d c7de55e 97fe68d c7de55e 97fe68d c7de55e 97fe68d c7de55e 97fe68d 087c95a c7de55e 087c95a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 | """
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 <think>β¦</think> 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"<think>(.*?)</think>", _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 <think> tag is present (avoids regex overhead on every token)
rendered = _render_think(response) if "<think>" 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 "<think>" 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("""
<div class="header-wrap">
<h1>π§ Naveed AI</h1>
<p>
<span class="dot"></span>
Built by <strong style="color:#c4b5fd">Naveed Khan</strong>
Β· Smart Β· Fast Β· Free Forever
</p>
</div>
""")
# ββ 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("""
<script>
(function() {
const hints = [
"Message Naveed AIβ¦",
"Ask me anythingβ¦",
"What\u2019s on your mind?",
"Try: \"Explain AI in simple words\"",
"Try: \"Write me a Python script\"",
"Try: \"Give me a workout plan\"",
"Try: \"Help me write a cover letter\"",
"Try: \"What is quantum computing?\"",
"Try: \"Is this news headline real?\"",
];
let i = 0;
function rotatePlaceholder() {
const input = document.querySelector('#msg-input textarea');
if (input && !input.value) {
i = (i + 1) % hints.length;
input.setAttribute('placeholder', hints[i]);
}
}
setInterval(rotatePlaceholder, 3000);
})();
</script>
""")
# ββ Controls ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
with gr.Row():
clear = gr.Button("π Clear chat", variant="secondary",
size="sm", elem_id="clear-btn", scale=1)
gr.HTML('<div style="flex:4"></div>') # 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,
)
|