Download main.py from DeepImagix/AlysiumTinyLLM: direct link, hf CLI and curl.
- Browser
- Download file 3.04 kB
-
https://huggingface.co/DeepImagix/AlysiumTinyLLM/resolve/main/main.py
- Command line
-
hf download hf://DeepImagix/AlysiumTinyLLM/main.py
-
curl -L -o main.py https://huggingface.co/DeepImagix/AlysiumTinyLLM/resolve/main/main.py
3.04 kB
| import re | |
| import pickle | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from pydantic import BaseModel | |
| from model import TinyLM | |
| import config | |
| # ---------- Load model once at startup ---------- | |
| print("Loading Alysium TinyLM (word-level)...") | |
| with open("tinylm.pkl", "rb") as f: | |
| ckpt = pickle.load(f) | |
| model = ckpt["model"] | |
| word_to_idx = ckpt["word_to_idx"] | |
| idx_to_word = ckpt["idx_to_word"] | |
| ctx_size = ckpt["context_size"] | |
| PAD = ckpt["pad_token"] | |
| pad_id = word_to_idx[PAD] | |
| print(f"Model loaded. params={model.num_params():,} vocab={len(word_to_idx)} context={ctx_size}") | |
| # ---------- FastAPI app ---------- | |
| app = FastAPI( | |
| title="Alysium TinyLM API", | |
| description="Lightweight word-level language model", | |
| version="4.0" | |
| ) | |
| # Allow your frontend / Neuraprompt AI to call this API | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], # you can restrict this later | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| class ChatRequest(BaseModel): | |
| message: str | |
| max_new_words: int = config.MAX_NEW_WORDS | |
| temperature: float = config.TEMPERATURE | |
| top_k: int = config.TOP_K | |
| class ChatResponse(BaseModel): | |
| reply: str | |
| def tokenize(text: str): | |
| return [w for w in re.findall(r"[a-z0-9']+|[.!?]", text.lower()) if w.strip()] | |
| def generate(prompt: str, max_new: int = 12, temperature: float = 0.45, top_k: int = 8) -> str: | |
| words = tokenize(prompt) | |
| ids = [word_to_idx.get(w, pad_id) for w in words] | |
| if len(ids) < ctx_size: | |
| ids = [pad_id] * (ctx_size - len(ids)) + ids | |
| else: | |
| ids = ids[-ctx_size:] | |
| generated = [] | |
| for _ in range(max_new): | |
| _, _, probs = model.forward(ids) | |
| next_id = model.sample(probs, temperature=temperature, top_k=top_k) | |
| next_word = idx_to_word.get(next_id, "") | |
| if next_word and next_word != PAD: | |
| generated.append(next_word) | |
| ids = ids[1:] + [next_id] | |
| # join words, tidy spacing around punctuation | |
| text = " ".join(generated) | |
| text = re.sub(r"\s+([.!?])", r"\1", text) | |
| return text.strip() | |
| def home(): | |
| return { | |
| "name": "Alysium TinyLM", | |
| "version": "4.0", | |
| "type": "word-level", | |
| "vocab_size": len(word_to_idx), | |
| "parameters": model.num_params(), | |
| "status": "running", | |
| "docs": "/docs" | |
| } | |
| def chat(req: ChatRequest): | |
| if not req.message or not req.message.strip(): | |
| raise HTTPException(status_code=400, detail="Message cannot be empty") | |
| try: | |
| reply = generate( | |
| req.message, | |
| max_new=req.max_new_words, | |
| temperature=req.temperature, | |
| top_k=req.top_k | |
| ) | |
| if not reply: | |
| reply = "..." | |
| return ChatResponse(reply=reply) | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| def health(): | |
| return {"status": "ok"} | |