# MiniCPM5-1B Demo from pathlib import Path import os import time import logging import threading import gradio as gr import spaces import torch from huggingface_hub import login from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer from utils_chatbot import organize_messages_from_messages, stream2display_text logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) MODEL_PATH = "openbmb/MiniCPM5-1B" hf_token = os.environ.get("HF_TOKEN") if hf_token: login(token=hf_token) logger.info("Logged in to Hugging Face Hub") else: logger.warning("HF_TOKEN not set — private/gated models will be inaccessible") tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained( MODEL_PATH, torch_dtype=torch.bfloat16, trust_remote_code=True, ).to("cuda") @spaces.GPU(duration=60) def gpu_generate_stream(inputs, history, temperature, top_p, enable_think): prompt_text = tokenizer.apply_chat_template( inputs, tokenize=False, add_generation_prompt=True, enable_thinking=enable_think, ) model_inputs = tokenizer([prompt_text], return_tensors="pt").to("cuda") history.append({"role": "assistant", "content": ""}) yield "", history streamer = TextIteratorStreamer( tokenizer, skip_prompt=True, skip_special_tokens=False, ) gen_kwargs = dict( **model_inputs, streamer=streamer, max_new_tokens=4096, ) if temperature > 0: gen_kwargs.update(temperature=temperature, top_p=top_p, do_sample=True) else: gen_kwargs.update(do_sample=False) thread = threading.Thread(target=model.generate, kwargs=gen_kwargs) thread.start() stream_text = "" gen_tk_count = 0 start_time = time.time() for new_token_text in streamer: if not new_token_text: continue stream_text += new_token_text gen_tk_count += 1 elapsed = time.time() - start_time token_per_sec = gen_tk_count / elapsed if elapsed > 0 else 0 display_text = stream2display_text(stream_text, token_per_sec) history[-1]["content"] = display_text yield "", history thread.join() history[-1]["content"] = stream_text.replace("<|im_end|>", "") yield "", history def gen_response_stream(message, history, temperature, top_p, enable_think): chat_msg_ls = organize_messages_from_messages(message, history) history.append({"role": "user", "content": message}) yield from gpu_generate_stream( chat_msg_ls, history, temperature=temperature, top_p=top_p, enable_think=enable_think, ) def create_app(): assets_path = Path.cwd().absolute() / "assets" gr.set_static_paths(paths=[assets_path]) with gr.Blocks() as demo: # Header gr.HTML( '
' '
' ' ' '
' ' MiniCPM5-1B' ' By OpenBMB' '
' '
' '
' ' ' ' MiniCPM5-1B' '
' '
' ) with gr.Row(elem_classes=["main-row"]): with gr.Column(scale=4, elem_classes=["chat-col"]): chatbot = gr.Chatbot( show_label=False, placeholder="Send a message to start chatting...", height="70vh", elem_classes=["dark-chatbot"], ) prompt = gr.Textbox( show_label=False, placeholder="Ask MiniCPM5...", lines=1, elem_classes=["input-pill"], ) with gr.Column(scale=1, min_width=220, elem_classes=["settings-col"]): gr.HTML('
Settings
') temperature = gr.Slider( minimum=0, maximum=1, value=0.9, step=0.05, label="Temperature", elem_classes=["dark-slider"], ) top_p = gr.Slider( minimum=0, maximum=1, value=0.95, step=0.01, label="Top-p", elem_classes=["dark-slider"], ) enable_think = gr.Checkbox( label="Enable Thinking", value=True, elem_classes=["dark-checkbox"], ) clear = gr.Button( "Clear History", variant="secondary", elem_classes=["clear-btn"], ) prompt.submit( gen_response_stream, inputs=[prompt, chatbot, temperature, top_p, enable_think], outputs=[prompt, chatbot], ) clear.click(lambda: None, None, chatbot, queue=False) return demo THEME = gr.themes.Base( primary_hue=gr.themes.Color( c50="#eef2ff", c100="#e0e7ff", c200="#c7d2fe", c300="#a5b4fc", c400="#818cf8", c500="#6366f1", c600="#4f46e5", c700="#4338ca", c800="#3730a3", c900="#312e81", c950="#1e1b4b", ), secondary_hue="slate", neutral_hue="slate", font=[gr.themes.GoogleFont("Inter"), "system-ui", "sans-serif"], ).set( body_background_fill="#05070A", body_background_fill_dark="#05070A", body_text_color="#e2e8f0", body_text_color_dark="#e2e8f0", block_background_fill="rgba(255,255,255,0.03)", block_background_fill_dark="rgba(255,255,255,0.03)", block_border_color="rgba(255,255,255,0.08)", block_border_color_dark="rgba(255,255,255,0.08)", block_label_text_color="#94a3b8", block_label_text_color_dark="#94a3b8", block_title_text_color="#e2e8f0", block_title_text_color_dark="#e2e8f0", input_background_fill="rgba(255,255,255,0.04)", input_background_fill_dark="rgba(255,255,255,0.04)", input_border_color="rgba(255,255,255,0.08)", input_border_color_dark="rgba(255,255,255,0.08)", input_placeholder_color="#64748b", input_placeholder_color_dark="#64748b", button_primary_background_fill="linear-gradient(135deg, #3B5BFF, #27D4EA)", button_primary_background_fill_dark="linear-gradient(135deg, #3B5BFF, #27D4EA)", button_primary_text_color="#ffffff", button_secondary_background_fill="rgba(255,255,255,0.06)", button_secondary_background_fill_dark="rgba(255,255,255,0.06)", button_secondary_text_color="#94a3b8", button_secondary_border_color="rgba(255,255,255,0.1)", button_secondary_border_color_dark="rgba(255,255,255,0.1)", slider_color="#6366f1", slider_color_dark="#6366f1", checkbox_background_color="rgba(255,255,255,0.06)", checkbox_background_color_dark="rgba(255,255,255,0.06)", checkbox_border_color="rgba(255,255,255,0.15)", checkbox_border_color_dark="rgba(255,255,255,0.15)", checkbox_label_text_color="#cbd5e1", checkbox_label_text_color_dark="#cbd5e1", shadow_drop="none", shadow_drop_lg="none", ) CSS = """ /* Force dark background everywhere */ html, body, .gradio-container, .main, footer { background: #05070A !important; } footer { display: none !important; } /* Header */ .app-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 24px; border-bottom: 1px solid rgba(255,255,255,0.05); } .header-left { display: flex; align-items: center; gap: 12px; } .header-logo { width: 40px; height: 40px; border-radius: 10px; filter: drop-shadow(0 0 12px rgba(39,212,234,0.35)); } .header-title { display: flex; flex-direction: column; } .title-main { font-size: 18px; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(to right, #fff, rgba(255,255,255,0.6)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .title-sub { font-size: 10px; text-transform: uppercase; letter-spacing: 0.2em; color: rgba(255,255,255,0.35); font-weight: 600; } .header-badge { display: flex; align-items: center; gap: 6px; font-size: 10px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(255,255,255,0.5); background: rgba(255,255,255,0.04); padding: 6px 14px; border-radius: 100px; border: 1px solid rgba(255,255,255,0.06); } .status-dot { width: 6px; height: 6px; border-radius: 50%; background: #27D4EA; animation: pulse-dot 2s infinite; } @keyframes pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } /* Layout */ .main-row { gap: 0 !important; } .chat-col { padding-right: 8px !important; } .settings-col { border-left: 1px solid rgba(255,255,255,0.06) !important; padding: 20px !important; } .settings-title { font-size: 14px; font-weight: 700; color: rgba(255,255,255,0.7); margin-bottom: 12px; letter-spacing: 0.05em; text-transform: uppercase; } /* Chatbot dark styling */ .dark-chatbot { border: none !important; background: transparent !important; } .dark-chatbot .wrapper { background: transparent !important; } .dark-chatbot .bubble-wrap { background: transparent !important; } .dark-chatbot .message-row { animation: msg-fade-in 0.35s cubic-bezier(0.16, 1, 0.3, 1) forwards; } @keyframes msg-fade-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } } /* User message bubble */ .dark-chatbot .role-user .message-bubble-border { background: linear-gradient(135deg, #3B5BFF, #27D4EA) !important; border: none !important; border-radius: 20px 20px 4px 20px !important; box-shadow: 0 6px 20px rgba(59,91,255,0.15); } .dark-chatbot .role-user .message-bubble-border .message-content { color: #ffffff !important; } /* Bot message bubble */ .dark-chatbot .role-assistant .message-bubble-border { background: rgba(255,255,255,0.03) !important; border: 1px solid rgba(255,255,255,0.08) !important; border-radius: 20px 20px 20px 4px !important; backdrop-filter: blur(8px); } .dark-chatbot .role-assistant .message-bubble-border .message-content { color: #e2e8f0 !important; } /* Thinking block (blockquote in bot messages) */ .dark-chatbot .role-assistant blockquote { background: rgba(59,91,255,0.06) !important; border-left: 3px solid #3B5BFF !important; border-radius: 4px 10px 10px 4px; padding: 10px 14px !important; color: #8B949E !important; font-style: italic; margin-bottom: 10px !important; } /* Input pill */ .input-pill { border: 1px solid rgba(255,255,255,0.08) !important; border-radius: 24px !important; background: rgba(255,255,255,0.04) !important; backdrop-filter: blur(20px); transition: all 0.3s ease; } .input-pill:focus-within { border-color: rgba(99,102,241,0.4) !important; background: rgba(255,255,255,0.06) !important; box-shadow: 0 0 30px rgba(99,102,241,0.06); } .input-pill textarea, .input-pill input { background: transparent !important; border: none !important; color: #e2e8f0 !important; } /* Settings controls */ .dark-slider input[type="range"] { accent-color: #6366f1; } .clear-btn button { border-radius: 12px !important; transition: all 0.2s ease; } .clear-btn button:hover { background: rgba(255,255,255,0.1) !important; color: #fff !important; } /* Code blocks in chat */ .dark-chatbot pre { background: rgba(0,0,0,0.4) !important; border: 1px solid rgba(255,255,255,0.06) !important; border-radius: 10px !important; color: #e2e8f0 !important; } .dark-chatbot code { color: #a5b4fc !important; } """ demo = create_app() if __name__ == "__main__": demo.launch(theme=THEME, css=CSS)