Spaces:
Paused
Paused
Commit ·
600ed76
1
Parent(s): a32006d
upgrade to Qwen3-Coder-30B-A3B-Instruct (MoE, 3B active) - ZeroGPU xlarge
Browse files
README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
---
|
| 2 |
-
title: CodeCraft -
|
| 3 |
emoji: 💻
|
| 4 |
colorFrom: indigo
|
| 5 |
colorTo: purple
|
|
@@ -12,29 +12,37 @@ python_version: "3.12"
|
|
| 12 |
|
| 13 |
# CodeCraft - AI Coding Assistant
|
| 14 |
|
| 15 |
-
Powered by **
|
|
|
|
| 16 |
|
| 17 |
-
Chat with a
|
| 18 |
-
refactoring, explanation, and general programming help across all major languages.
|
| 19 |
|
| 20 |
## Features
|
| 21 |
|
| 22 |
- 💬 **Chat interface** with syntax-highlighted code blocks
|
| 23 |
-
- ⚙️ **Adjustable parameters**: temperature, top-p, max tokens, system prompt
|
| 24 |
-
- 📡 **Built-in API endpoint** at `/
|
| 25 |
- 🎨 **Syntax-highlighted output** via Gradio Markdown + code blocks
|
|
|
|
|
|
|
| 26 |
|
| 27 |
## API Usage
|
| 28 |
|
| 29 |
-
Every Gradio Space exposes a
|
| 30 |
|
| 31 |
```python
|
| 32 |
import requests
|
| 33 |
|
| 34 |
response = requests.post(
|
| 35 |
-
"https://
|
| 36 |
json={
|
| 37 |
-
"data": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
}
|
| 39 |
)
|
| 40 |
print(response.json())
|
|
@@ -42,5 +50,4 @@ print(response.json())
|
|
| 42 |
|
| 43 |
## Model
|
| 44 |
|
| 45 |
-
[Qwen/
|
| 46 |
-
7B parameter code-specific LLM with 128K context, instruction-tuned for chat and coding tasks.
|
|
|
|
| 1 |
---
|
| 2 |
+
title: CodeCraft - Qwen3-Coder-30B
|
| 3 |
emoji: 💻
|
| 4 |
colorFrom: indigo
|
| 5 |
colorTo: purple
|
|
|
|
| 12 |
|
| 13 |
# CodeCraft - AI Coding Assistant
|
| 14 |
|
| 15 |
+
Powered by **Qwen3-Coder-30B-A3B-Instruct** running on Hugging Face ZeroGPU (xlarge).
|
| 16 |
+
A Mixture-of-Experts model with 30B total params (3B active) — matches or exceeds much larger models on coding benchmarks.
|
| 17 |
|
| 18 |
+
Chat with a cutting-edge coding assistant. Supports code generation, debugging, refactoring, explanation, and general programming help across all major languages.
|
|
|
|
| 19 |
|
| 20 |
## Features
|
| 21 |
|
| 22 |
- 💬 **Chat interface** with syntax-highlighted code blocks
|
| 23 |
+
- ⚙️ **Adjustable parameters**: temperature, top-p, max tokens (up to 8192), system prompt
|
| 24 |
+
- 📡 **Built-in API endpoint** at `/gradio_api/call/predict` for programmatic use
|
| 25 |
- 🎨 **Syntax-highlighted output** via Gradio Markdown + code blocks
|
| 26 |
+
- 🔄 **256K context** — handle entire codebases in conversation
|
| 27 |
+
- 🛠️ **Agentic tool-use** support (function calling, ReAct, structured output)
|
| 28 |
|
| 29 |
## API Usage
|
| 30 |
|
| 31 |
+
Every Gradio Space exposes a REST API at `/gradio_api/call/predict`. For this Space:
|
| 32 |
|
| 33 |
```python
|
| 34 |
import requests
|
| 35 |
|
| 36 |
response = requests.post(
|
| 37 |
+
"https://serotoninboi-codecraft.hf.space/gradio_api/call/predict",
|
| 38 |
json={
|
| 39 |
+
"data": [
|
| 40 |
+
"write a fibonacci function in rust",
|
| 41 |
+
"You are a helpful coding assistant.",
|
| 42 |
+
0.3,
|
| 43 |
+
0.9,
|
| 44 |
+
2048
|
| 45 |
+
]
|
| 46 |
}
|
| 47 |
)
|
| 48 |
print(response.json())
|
|
|
|
| 50 |
|
| 51 |
## Model
|
| 52 |
|
| 53 |
+
[Qwen/Qwen3-Coder-30B-A3B-Instruct](https://huggingface.co/Qwen/Qwen3-Coder-30B-A3B-Instruct) — 30B MoE (3B active) code-specific LLM with 256K context, built for agentic coding tasks.
|
|
|
app.py
CHANGED
|
@@ -8,12 +8,12 @@ from transformers import (
|
|
| 8 |
TextIteratorStreamer,
|
| 9 |
)
|
| 10 |
from threading import Thread
|
| 11 |
-
from typing import
|
| 12 |
|
| 13 |
# ---------------------------------------------------------------------------
|
| 14 |
-
# Module-scope model loading
|
| 15 |
# ---------------------------------------------------------------------------
|
| 16 |
-
MODEL_ID = "Qwen/
|
| 17 |
|
| 18 |
quant_config = BitsAndBytesConfig(
|
| 19 |
load_in_4bit=True,
|
|
@@ -36,9 +36,9 @@ DEFAULT_SYSTEM = "You are an expert coding assistant. Write clean, efficient, we
|
|
| 36 |
|
| 37 |
|
| 38 |
# ---------------------------------------------------------------------------
|
| 39 |
-
# ZeroGPU-decorated generation
|
| 40 |
# ---------------------------------------------------------------------------
|
| 41 |
-
@spaces.GPU(duration=
|
| 42 |
def generate(
|
| 43 |
messages: list[dict],
|
| 44 |
temperature: float,
|
|
@@ -46,9 +46,8 @@ def generate(
|
|
| 46 |
max_new_tokens: int,
|
| 47 |
) -> str:
|
| 48 |
"""Run model inference inside a ZeroGPU worker process.
|
| 49 |
-
|
| 50 |
Args are pickled across the process boundary.
|
| 51 |
-
Returns CPU text
|
| 52 |
"""
|
| 53 |
inputs = tokenizer.apply_chat_template(
|
| 54 |
messages,
|
|
@@ -72,9 +71,9 @@ def generate(
|
|
| 72 |
|
| 73 |
|
| 74 |
# ---------------------------------------------------------------------------
|
| 75 |
-
# Streaming variant
|
| 76 |
# ---------------------------------------------------------------------------
|
| 77 |
-
@spaces.GPU(duration=
|
| 78 |
def generate_stream(
|
| 79 |
messages: list[dict],
|
| 80 |
temperature: float,
|
|
@@ -123,7 +122,7 @@ def predict(
|
|
| 123 |
top_p: float,
|
| 124 |
max_tokens: int,
|
| 125 |
):
|
| 126 |
-
"""Chat function
|
| 127 |
messages = [{"role": "system", "content": system_prompt}]
|
| 128 |
for user_msg, asst_msg in history:
|
| 129 |
messages.append({"role": "user", "content": user_msg})
|
|
@@ -161,7 +160,7 @@ def chat_fn(
|
|
| 161 |
|
| 162 |
|
| 163 |
# ---------------------------------------------------------------------------
|
| 164 |
-
#
|
| 165 |
# ---------------------------------------------------------------------------
|
| 166 |
LANGUAGES = ["python", "javascript", "typescript", "rust", "go", "java", "cpp",
|
| 167 |
"csharp", "ruby", "php", "sql", "bash", "html", "css", "json", "yaml"]
|
|
@@ -169,10 +168,11 @@ LANGUAGES = ["python", "javascript", "typescript", "rust", "go", "java", "cpp",
|
|
| 169 |
|
| 170 |
def build_examples():
|
| 171 |
return [
|
| 172 |
-
["Write a Python function that
|
| 173 |
["Create a Rust function that reads a CSV file and returns the row count."],
|
| 174 |
-
["Explain the difference between an interface and a type in TypeScript."],
|
| 175 |
-
["Write a Go HTTP server that serves static files on port 8080."],
|
|
|
|
| 176 |
]
|
| 177 |
|
| 178 |
|
|
@@ -189,8 +189,8 @@ def create_ui():
|
|
| 189 |
fill_width=True,
|
| 190 |
) as demo:
|
| 191 |
gr.Markdown(
|
| 192 |
-
"#
|
| 193 |
-
"Powered by **
|
| 194 |
)
|
| 195 |
|
| 196 |
chatbot = gr.Chatbot(
|
|
@@ -211,7 +211,7 @@ def create_ui():
|
|
| 211 |
submit_btn = gr.Button("Send", variant="primary", scale=1, min_width=80)
|
| 212 |
clear_btn = gr.Button("Clear", scale=1, min_width=80)
|
| 213 |
|
| 214 |
-
with gr.Accordion("
|
| 215 |
with gr.Row():
|
| 216 |
system_prompt = gr.Textbox(
|
| 217 |
label="System Prompt",
|
|
@@ -230,7 +230,7 @@ def create_ui():
|
|
| 230 |
value=0.9, step=0.05,
|
| 231 |
)
|
| 232 |
max_tokens = gr.Slider(
|
| 233 |
-
label="Max Tokens", minimum=128, maximum=
|
| 234 |
value=2048, step=128,
|
| 235 |
)
|
| 236 |
|
|
@@ -254,37 +254,33 @@ def create_ui():
|
|
| 254 |
yield "", history, []
|
| 255 |
yield "", history, [message]
|
| 256 |
|
| 257 |
-
# Wire submit via message box
|
| 258 |
msg.submit(
|
| 259 |
respond,
|
| 260 |
inputs=[msg, history_state, system_prompt, temperature, top_p, max_tokens],
|
| 261 |
outputs=[msg, chatbot, history_state],
|
| 262 |
-
concurrency_limit=
|
| 263 |
api_name="predict",
|
| 264 |
)
|
| 265 |
submit_btn.click(
|
| 266 |
respond,
|
| 267 |
inputs=[msg, history_state, system_prompt, temperature, top_p, max_tokens],
|
| 268 |
outputs=[msg, chatbot, history_state],
|
| 269 |
-
concurrency_limit=
|
| 270 |
api_name=False,
|
| 271 |
)
|
| 272 |
|
| 273 |
-
# Clear conversation
|
| 274 |
def clear_conversation():
|
| 275 |
return [], "", []
|
| 276 |
|
| 277 |
clear_btn.click(
|
| 278 |
clear_conversation,
|
| 279 |
outputs=[history_state, chatbot, msg],
|
| 280 |
-
concurrency_limit=
|
| 281 |
)
|
| 282 |
|
| 283 |
-
# -- API endpoint exposure (auto by Gradio, but re-binding as top-level fn) --
|
| 284 |
gr.Markdown(
|
| 285 |
"""
|
| 286 |
-
###
|
| 287 |
-
|
| 288 |
This Space exposes a REST API at `/gradio_api/call/predict`.
|
| 289 |
See the [Gradio docs](https://www.gradio.app/guides/sharing-your-app#api) for usage.
|
| 290 |
"""
|
|
@@ -295,5 +291,5 @@ def create_ui():
|
|
| 295 |
|
| 296 |
if __name__ == "__main__":
|
| 297 |
demo = create_ui()
|
| 298 |
-
demo.queue(default_concurrency_limit=
|
| 299 |
demo.launch()
|
|
|
|
| 8 |
TextIteratorStreamer,
|
| 9 |
)
|
| 10 |
from threading import Thread
|
| 11 |
+
from typing import Generator
|
| 12 |
|
| 13 |
# ---------------------------------------------------------------------------
|
| 14 |
+
# Module-scope model loading - ZeroGPU manages GPU offload transparently
|
| 15 |
# ---------------------------------------------------------------------------
|
| 16 |
+
MODEL_ID = "Qwen/Qwen3-Coder-30B-A3B-Instruct"
|
| 17 |
|
| 18 |
quant_config = BitsAndBytesConfig(
|
| 19 |
load_in_4bit=True,
|
|
|
|
| 36 |
|
| 37 |
|
| 38 |
# ---------------------------------------------------------------------------
|
| 39 |
+
# ZeroGPU-decorated generation - xlarge for 30B MoE model
|
| 40 |
# ---------------------------------------------------------------------------
|
| 41 |
+
@spaces.GPU(duration=180, size="xlarge")
|
| 42 |
def generate(
|
| 43 |
messages: list[dict],
|
| 44 |
temperature: float,
|
|
|
|
| 46 |
max_new_tokens: int,
|
| 47 |
) -> str:
|
| 48 |
"""Run model inference inside a ZeroGPU worker process.
|
|
|
|
| 49 |
Args are pickled across the process boundary.
|
| 50 |
+
Returns CPU text - safe for unpickling in the main process.
|
| 51 |
"""
|
| 52 |
inputs = tokenizer.apply_chat_template(
|
| 53 |
messages,
|
|
|
|
| 71 |
|
| 72 |
|
| 73 |
# ---------------------------------------------------------------------------
|
| 74 |
+
# Streaming variant - yields tokens as they're generated
|
| 75 |
# ---------------------------------------------------------------------------
|
| 76 |
+
@spaces.GPU(duration=180, size="xlarge")
|
| 77 |
def generate_stream(
|
| 78 |
messages: list[dict],
|
| 79 |
temperature: float,
|
|
|
|
| 122 |
top_p: float,
|
| 123 |
max_tokens: int,
|
| 124 |
):
|
| 125 |
+
"""Chat function - called both from UI and the auto-generated Gradio API."""
|
| 126 |
messages = [{"role": "system", "content": system_prompt}]
|
| 127 |
for user_msg, asst_msg in history:
|
| 128 |
messages.append({"role": "user", "content": user_msg})
|
|
|
|
| 160 |
|
| 161 |
|
| 162 |
# ---------------------------------------------------------------------------
|
| 163 |
+
# Helpers
|
| 164 |
# ---------------------------------------------------------------------------
|
| 165 |
LANGUAGES = ["python", "javascript", "typescript", "rust", "go", "java", "cpp",
|
| 166 |
"csharp", "ruby", "php", "sql", "bash", "html", "css", "json", "yaml"]
|
|
|
|
| 168 |
|
| 169 |
def build_examples():
|
| 170 |
return [
|
| 171 |
+
["Write a Python async function that downloads a URL and retries 3 times on failure."],
|
| 172 |
["Create a Rust function that reads a CSV file and returns the row count."],
|
| 173 |
+
["Explain the difference between an interface and a type in TypeScript with examples."],
|
| 174 |
+
["Write a Go HTTP server that serves static files on port 8080 with CORS support."],
|
| 175 |
+
["Refactor this Python class to use dependency injection: class Database: ..."],
|
| 176 |
]
|
| 177 |
|
| 178 |
|
|
|
|
| 189 |
fill_width=True,
|
| 190 |
) as demo:
|
| 191 |
gr.Markdown(
|
| 192 |
+
"# CodeCraft - AI Coding Assistant\n"
|
| 193 |
+
"Powered by **Qwen3-Coder-30B-A3B-Instruct** (MoE, 3B active) - ZeroGPU xlarge"
|
| 194 |
)
|
| 195 |
|
| 196 |
chatbot = gr.Chatbot(
|
|
|
|
| 211 |
submit_btn = gr.Button("Send", variant="primary", scale=1, min_width=80)
|
| 212 |
clear_btn = gr.Button("Clear", scale=1, min_width=80)
|
| 213 |
|
| 214 |
+
with gr.Accordion("Settings", open=False):
|
| 215 |
with gr.Row():
|
| 216 |
system_prompt = gr.Textbox(
|
| 217 |
label="System Prompt",
|
|
|
|
| 230 |
value=0.9, step=0.05,
|
| 231 |
)
|
| 232 |
max_tokens = gr.Slider(
|
| 233 |
+
label="Max Tokens", minimum=128, maximum=8192,
|
| 234 |
value=2048, step=128,
|
| 235 |
)
|
| 236 |
|
|
|
|
| 254 |
yield "", history, []
|
| 255 |
yield "", history, [message]
|
| 256 |
|
|
|
|
| 257 |
msg.submit(
|
| 258 |
respond,
|
| 259 |
inputs=[msg, history_state, system_prompt, temperature, top_p, max_tokens],
|
| 260 |
outputs=[msg, chatbot, history_state],
|
| 261 |
+
concurrency_limit=4,
|
| 262 |
api_name="predict",
|
| 263 |
)
|
| 264 |
submit_btn.click(
|
| 265 |
respond,
|
| 266 |
inputs=[msg, history_state, system_prompt, temperature, top_p, max_tokens],
|
| 267 |
outputs=[msg, chatbot, history_state],
|
| 268 |
+
concurrency_limit=4,
|
| 269 |
api_name=False,
|
| 270 |
)
|
| 271 |
|
|
|
|
| 272 |
def clear_conversation():
|
| 273 |
return [], "", []
|
| 274 |
|
| 275 |
clear_btn.click(
|
| 276 |
clear_conversation,
|
| 277 |
outputs=[history_state, chatbot, msg],
|
| 278 |
+
concurrency_limit=4,
|
| 279 |
)
|
| 280 |
|
|
|
|
| 281 |
gr.Markdown(
|
| 282 |
"""
|
| 283 |
+
### API
|
|
|
|
| 284 |
This Space exposes a REST API at `/gradio_api/call/predict`.
|
| 285 |
See the [Gradio docs](https://www.gradio.app/guides/sharing-your-app#api) for usage.
|
| 286 |
"""
|
|
|
|
| 291 |
|
| 292 |
if __name__ == "__main__":
|
| 293 |
demo = create_ui()
|
| 294 |
+
demo.queue(default_concurrency_limit=4)
|
| 295 |
demo.launch()
|