Spaces:
Running
Running
| import gradio as gr | |
| from huggingface_hub import InferenceClient | |
| import os | |
| # ============================================ | |
| # Kimi-K2-Thinking Streaming Chat | |
| # Provider: Novita (HuggingFace) | |
| # Gradio 6.0 Compatible - Full Width Layout | |
| # ============================================ | |
| # Initialize Novita Client | |
| client = InferenceClient( | |
| provider="novita", | |
| api_key=os.environ.get("HF_TOKEN"), | |
| ) | |
| def chat_stream(messages): | |
| """Streaming via Novita provider""" | |
| stream = client.chat.completions.create( | |
| model="moonshotai/Kimi-K2-Thinking", | |
| messages=messages, | |
| max_tokens=4096, | |
| temperature=0.7, | |
| top_p=0.95, | |
| stream=True | |
| ) | |
| for chunk in stream: | |
| if chunk.choices and len(chunk.choices) > 0: | |
| delta = chunk.choices[0].delta | |
| if hasattr(delta, 'content') and delta.content: | |
| yield delta.content | |
| def chat_respond(message, history): | |
| """ | |
| Streaming chat | |
| Gradio 6.0 messages format: [{"role": "user/assistant", "content": "..."}] | |
| """ | |
| if not message.strip(): | |
| return history | |
| # Build API messages | |
| api_messages = [{ | |
| "role": "system", | |
| "content": "You are Kimi-K2-Thinking, a helpful AI assistant built by Moonshot AI. You excel at deep reasoning, coding, and complex problem solving. Respond in the same language as the user." | |
| }] | |
| # Add history (Gradio 6.0 messages format) | |
| for h in history: | |
| if isinstance(h, dict): | |
| api_messages.append({"role": h.get("role", "user"), "content": h.get("content", "")}) | |
| api_messages.append({"role": "user", "content": message}) | |
| response_text = "" | |
| try: | |
| for chunk in chat_stream(api_messages): | |
| response_text += chunk | |
| new_history = history + [ | |
| {"role": "user", "content": message}, | |
| {"role": "assistant", "content": response_text} | |
| ] | |
| yield new_history | |
| except Exception as e: | |
| new_history = history + [ | |
| {"role": "user", "content": message}, | |
| {"role": "assistant", "content": f"Error: {str(e)}"} | |
| ] | |
| yield new_history | |
| def clear_chat_fn(): | |
| """Clear chat history""" | |
| return [], "" | |
| # ============================================ | |
| # Comic Classic Theme CSS | |
| # ============================================ | |
| css = """ | |
| @import url('https://fonts.googleapis.com/css2?family=Bangers&family=Comic+Neue:wght@400;700&display=swap'); | |
| .gradio-container { | |
| background-color: #FEF9C3 !important; | |
| background-image: radial-gradient(#1F2937 1px, transparent 1px) !important; | |
| background-size: 20px 20px !important; | |
| min-height: 100vh !important; | |
| font-family: 'Comic Neue', cursive, sans-serif !important; | |
| } | |
| .huggingface-space-header, #space-header, .space-header, [class*="space-header"] { | |
| display: none !important; | |
| } | |
| footer, .footer, .gradio-footer, .built-with-gradio { | |
| display: none !important; | |
| } | |
| .header-text h1 { | |
| font-family: 'Bangers', cursive !important; | |
| color: #1F2937 !important; | |
| font-size: 3.5rem !important; | |
| text-align: center !important; | |
| text-shadow: 4px 4px 0px #FACC15, 6px 6px 0px #1F2937 !important; | |
| letter-spacing: 3px !important; | |
| -webkit-text-stroke: 2px #1F2937 !important; | |
| } | |
| .subtitle { | |
| text-align: center !important; | |
| font-family: 'Comic Neue', cursive !important; | |
| font-size: 1.2rem !important; | |
| color: #1F2937 !important; | |
| font-weight: 700 !important; | |
| } | |
| .gr-panel, .gr-box, .block, .gr-group { | |
| background: #FFFFFF !important; | |
| border: 3px solid #1F2937 !important; | |
| border-radius: 8px !important; | |
| box-shadow: 6px 6px 0px #1F2937 !important; | |
| } | |
| textarea, input[type="text"] { | |
| background: #FFFFFF !important; | |
| border: 3px solid #1F2937 !important; | |
| border-radius: 8px !important; | |
| color: #1F2937 !important; | |
| font-family: 'Comic Neue', cursive !important; | |
| font-size: 1rem !important; | |
| font-weight: 700 !important; | |
| } | |
| textarea:focus, input[type="text"]:focus { | |
| border-color: #3B82F6 !important; | |
| box-shadow: 4px 4px 0px #3B82F6 !important; | |
| outline: none !important; | |
| } | |
| .gr-button-primary, button.primary { | |
| background: #3B82F6 !important; | |
| border: 3px solid #1F2937 !important; | |
| border-radius: 8px !important; | |
| color: #FFFFFF !important; | |
| font-family: 'Bangers', cursive !important; | |
| font-size: 1.3rem !important; | |
| letter-spacing: 2px !important; | |
| padding: 14px 28px !important; | |
| box-shadow: 5px 5px 0px #1F2937 !important; | |
| text-shadow: 1px 1px 0px #1F2937 !important; | |
| } | |
| .gr-button-primary:hover, button.primary:hover { | |
| background: #2563EB !important; | |
| transform: translate(-2px, -2px) !important; | |
| box-shadow: 7px 7px 0px #1F2937 !important; | |
| } | |
| .gr-button-secondary, button.secondary { | |
| background: #EF4444 !important; | |
| border: 3px solid #1F2937 !important; | |
| border-radius: 8px !important; | |
| color: #FFFFFF !important; | |
| font-family: 'Bangers', cursive !important; | |
| font-size: 1.1rem !important; | |
| box-shadow: 4px 4px 0px #1F2937 !important; | |
| } | |
| .gr-button-secondary:hover, button.secondary:hover { | |
| background: #DC2626 !important; | |
| transform: translate(-2px, -2px) !important; | |
| } | |
| .chatbot { | |
| border: 3px solid #1F2937 !important; | |
| border-radius: 12px !important; | |
| box-shadow: 6px 6px 0px #1F2937 !important; | |
| background: #FFFFFF !important; | |
| } | |
| pre, code { | |
| background: #1F2937 !important; | |
| color: #10B981 !important; | |
| border: 2px solid #10B981 !important; | |
| border-radius: 6px !important; | |
| font-family: 'Courier New', monospace !important; | |
| } | |
| ::-webkit-scrollbar { width: 12px; } | |
| ::-webkit-scrollbar-track { background: #FEF9C3; border: 2px solid #1F2937; } | |
| ::-webkit-scrollbar-thumb { background: #3B82F6; border: 2px solid #1F2937; } | |
| ::-webkit-scrollbar-thumb:hover { background: #EF4444; } | |
| @media (max-width: 768px) { | |
| .header-text h1 { font-size: 2.2rem !important; } | |
| } | |
| """ | |
| # ============================================ | |
| # Gradio Interface - Full Width Layout | |
| # ============================================ | |
| with gr.Blocks(fill_height=True) as demo: | |
| # Inject CSS via HTML | |
| gr.HTML(f"<style>{css}</style>") | |
| # HOME Badge | |
| gr.HTML(""" | |
| <div style="text-align: center; margin: 20px 0 10px 0;"> | |
| <a href="https://www.humangen.ai" target="_blank" style="text-decoration: none;"> | |
| <img src="https://img.shields.io/static/v1?label=HOME&message=HUMANGEN.AI&color=0000ff&labelColor=ffcc00&style=for-the-badge" alt="HOME"> | |
| </a> | |
| </div> | |
| """) | |
| # Header Title | |
| gr.Markdown("""# Kimi-K2-Thinking CHAT""", elem_classes="header-text") | |
| gr.Markdown("""<p class="subtitle">Moonshot AI's Advanced Reasoning Model - Deep Thinking and Complex Problem Solving</p>""") | |
| # Model Info Box | |
| gr.HTML(""" | |
| <div style="background: linear-gradient(135deg, #EC4899 0%, #F97316 100%); border: 3px solid #1F2937; border-radius: 12px; padding: 15px; color: white; box-shadow: 5px 5px 0px #1F2937; margin: 0 auto 20px auto; max-width: 1200px;"> | |
| <div style="display: flex; justify-content: space-around; flex-wrap: wrap; text-align: center;"> | |
| <div><strong style="font-size: 1.5rem;">Kimi-K2</strong><br><span style="font-size: 0.9rem;">Model</span></div> | |
| <div><strong style="font-size: 1.5rem;">Moonshot AI</strong><br><span style="font-size: 0.9rem;">Developer</span></div> | |
| <div><strong style="font-size: 1.5rem;">Thinking</strong><br><span style="font-size: 0.9rem;">Mode</span></div> | |
| <div><strong style="font-size: 1.5rem;">Novita</strong><br><span style="font-size: 0.9rem;">Provider</span></div> | |
| </div> | |
| </div> | |
| """) | |
| # Chatbot - Full Width | |
| chatbot = gr.Chatbot( | |
| label="Chat", | |
| height=500, | |
| show_label=False, | |
| elem_classes="chatbot" | |
| ) | |
| # Input Row | |
| with gr.Row(): | |
| msg = gr.Textbox( | |
| label="", | |
| placeholder="Enter your message... (coding, analysis, creative writing, anything!)", | |
| scale=8, | |
| container=False | |
| ) | |
| submit_btn = gr.Button("SEND", variant="primary", scale=2) | |
| # Clear Button | |
| clear_btn = gr.Button("CLEAR CHAT", variant="secondary") | |
| # Event Handlers | |
| def respond(message, history): | |
| if not message.strip(): | |
| yield history | |
| return | |
| for result in chat_respond(message, history): | |
| yield result | |
| # Connect events | |
| msg.submit(respond, [msg, chatbot], [chatbot]).then( | |
| lambda: "", outputs=[msg] | |
| ) | |
| submit_btn.click(respond, [msg, chatbot], [chatbot]).then( | |
| lambda: "", outputs=[msg] | |
| ) | |
| clear_btn.click(clear_chat_fn, outputs=[chatbot, msg]) | |
| if __name__ == "__main__": | |
| demo.launch(ssr_mode=False) |