tinyLLM-Demo / app.py
chris0809's picture
Add thinking mode toggle
6d65cd4 verified
Raw History Blame Contribute Delete
3.92 kB
"""Small CPU-friendly Hugging Face Space for the public tinyLLM checkpoints."""
from __future__ import annotations
import threading
import gradio as gr
import spaces
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
BASE_REPO = "chris0809/tinyLLM-0.51B-SFT"
_model = None
_tokenizer = None
_lock = threading.RLock()
def load_runtime():
global _model, _tokenizer
with _lock:
if _model is None:
_tokenizer = AutoTokenizer.from_pretrained(BASE_REPO)
_model = AutoModelForCausalLM.from_pretrained(
BASE_REPO,
trust_remote_code=True,
dtype=torch.bfloat16,
).to("cuda").eval()
return _model, _tokenizer
@spaces.GPU(duration=45)
def respond(message: str, history: list[dict], max_new_tokens: int, thinking_mode: bool):
if not message.strip():
yield "请输入一个问题。"
return
with _lock:
model, tokenizer = load_runtime()
messages = [
{"role": row["role"], "content": row["content"]}
for row in history
if row.get("role") in {"user", "assistant"} and isinstance(row.get("content"), str)
]
messages.append({"role": "user", "content": message.strip()})
prompt = tokenizer.apply_chat_template(
messages,
tokenize=False,
enable_thinking=thinking_mode,
add_generation_prompt=True,
)
inputs = {
key: value.to(next(model.parameters()).device)
for key, value in tokenizer(prompt, return_tensors="pt").items()
}
streamer = TextIteratorStreamer(
tokenizer,
skip_prompt=True,
skip_special_tokens=True,
)
kwargs = {
**inputs,
"streamer": streamer,
"max_new_tokens": int(max_new_tokens),
"do_sample": False,
"repetition_penalty": 1.10,
"no_repeat_ngram_size": 12,
"use_cache": True,
}
worker = threading.Thread(target=model.generate, kwargs=kwargs, daemon=True)
worker.start()
text = ""
for piece in streamer:
text += piece
yield text
worker.join()
# ZeroGPU provides a CUDA emulation context during startup, so the weights can
# stay GPU-resident and are ready when the decorated function receives a slot.
load_runtime()
with gr.Blocks(title="tinyLLM 0.51B") as demo:
gr.Markdown(
"# tinyLLM 0.51B\n"
"从零训练的中英双语小模型。这里在线运行公开的 0.51B SFT checkpoint。"
)
max_tokens = gr.Slider(32, 256, value=128, step=32, label="Maximum new tokens")
thinking_mode = gr.Checkbox(
value=False,
label="Thinking mode(数学或多步推理)",
info="自动使用训练时的思维协议;普通聊天建议关闭。",
)
gr.ChatInterface(
fn=respond,
additional_inputs=[max_tokens, thinking_mode],
type="messages",
examples=[
["用两句话介绍一下你自己。", 128, False],
["What is 12 minus 5? Give a short answer.", 96, True],
["Write three bullet points about small language models.", 160, False],
],
cache_examples=False,
concurrency_limit=1,
)
gr.Markdown(
"多模态权重已发布在 [tinyLLM-0.51B-VLM]"
"(https://huggingface.co/chris0809/tinyLLM-0.51B-VLM)。"
"[ARC GRPO](https://huggingface.co/chris0809/tinyLLM-0.51B-ARC-GRPO) 和 "
"[IFEval OPD](https://huggingface.co/chris0809/tinyLLM-0.51B-IFEval-OPD) LoRA 也可单独下载。"
"完整图片演示建议使用 GitHub 中的本地 Demo;这个免费 Space 主要用于快速验证文本基座。"
)
if __name__ == "__main__":
demo.launch()