| 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) |