Kimi-K2Thinking / app.py
seawolf2357's picture
Update app.py
fa1e933 verified
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)