|
|
import gradio as gr |
|
|
from huggingface_hub import InferenceClient |
|
|
import os |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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="zai-org/GLM-4.7", |
|
|
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 |
|
|
|
|
|
|
|
|
api_messages = [{ |
|
|
"role": "system", |
|
|
"content": "You are GLM-4.7, a helpful AI assistant built by Zhipu AI. You excel at coding, reasoning, and creative tasks. Respond in the same language as the user." |
|
|
}] |
|
|
|
|
|
|
|
|
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 [], "" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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; } |
|
|
} |
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with gr.Blocks(fill_height=True) as demo: |
|
|
|
|
|
|
|
|
gr.HTML(f"<style>{css}</style>") |
|
|
|
|
|
|
|
|
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> |
|
|
""") |
|
|
|
|
|
|
|
|
gr.Markdown("""# GLM-4.7 CHAT""", elem_classes="header-text") |
|
|
gr.Markdown("""<p class="subtitle">Zhipu AI's Latest Open Source Model - Powerful Reasoning and Coding Capabilities</p>""") |
|
|
|
|
|
|
|
|
gr.HTML(""" |
|
|
<div style="background: linear-gradient(135deg, #10B981 0%, #3B82F6 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;">GLM-4.7</strong><br><span style="font-size: 0.9rem;">Model</span></div> |
|
|
<div><strong style="font-size: 1.5rem;">Zhipu AI</strong><br><span style="font-size: 0.9rem;">Developer</span></div> |
|
|
<div><strong style="font-size: 1.5rem;">Open Source</strong><br><span style="font-size: 0.9rem;">License</span></div> |
|
|
<div><strong style="font-size: 1.5rem;">Novita</strong><br><span style="font-size: 0.9rem;">Provider</span></div> |
|
|
</div> |
|
|
</div> |
|
|
""") |
|
|
|
|
|
|
|
|
chatbot = gr.Chatbot( |
|
|
label="Chat", |
|
|
height=500, |
|
|
show_label=False, |
|
|
elem_classes="chatbot" |
|
|
) |
|
|
|
|
|
|
|
|
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_btn = gr.Button("CLEAR CHAT", variant="secondary") |
|
|
|
|
|
|
|
|
def respond(message, history): |
|
|
if not message.strip(): |
|
|
yield history |
|
|
return |
|
|
for result in chat_respond(message, history): |
|
|
yield result |
|
|
|
|
|
|
|
|
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) |