Text Generation
Transformers
Safetensors
qwen2
godot
gdscript
qlora
game-development
conversational
text-generation-inference
Instructions to use khursheed/VibeGame-8B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use khursheed/VibeGame-8B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="khursheed/VibeGame-8B") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("khursheed/VibeGame-8B") model = AutoModelForCausalLM.from_pretrained("khursheed/VibeGame-8B", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use khursheed/VibeGame-8B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "khursheed/VibeGame-8B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "khursheed/VibeGame-8B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/khursheed/VibeGame-8B
- SGLang
How to use khursheed/VibeGame-8B with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "khursheed/VibeGame-8B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "khursheed/VibeGame-8B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "khursheed/VibeGame-8B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "khursheed/VibeGame-8B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use khursheed/VibeGame-8B with Docker Model Runner:
docker model run hf.co/khursheed/VibeGame-8B
File size: 10,529 Bytes
ae36cfb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | #!/usr/bin/env python3
"""Generate once using local Ollama or a local Unsloth adapter. No paid API."""
from __future__ import annotations
import argparse
import hashlib
import importlib.metadata
import json
from pathlib import Path
import sys
import time
import urllib.parse
import urllib.request
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
from vibegame.project import SYSTEM_PROMPT, parse_project
def file_hash(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as handle:
for block in iter(lambda: handle.read(8 * 1024 * 1024), b""):
digest.update(block)
return digest.hexdigest()
def directory_fingerprint(path: Path) -> dict:
files = {str(item.relative_to(path)): file_hash(item) for item in sorted(path.rglob("*"))
if item.is_file() and item.suffix in {".json", ".safetensors", ".bin", ".model", ".gguf"}}
return {"path": str(path.resolve()), "sha256": hashlib.sha256(json.dumps(files, sort_keys=True).encode()).hexdigest(), "files": files}
class OllamaGenerator:
def __init__(self, model: str, url: str = "http://127.0.0.1:11434", **kwargs):
parsed = urllib.parse.urlparse(url)
if parsed.scheme != "http" or parsed.hostname not in {"127.0.0.1", "localhost", "::1"} or parsed.username:
raise ValueError("Only local, unauthenticated Ollama HTTP is allowed")
self.url, self.model = url.rstrip("/"), model
tags = self._post("/api/tags", None)
matching = [item for item in tags.get("models", []) if item.get("name") in {model, model + ":latest"} or item.get("model") in {model, model + ":latest"}]
if not matching:
raise RuntimeError("Model is not installed in local Ollama; automatic pull is disabled")
self.metadata = {"backend": "ollama-local", "model": model, "model_digest": matching[0]["digest"],
"runtime": self._post("/api/version", None), "system_prompt_sha256": hashlib.sha256(SYSTEM_PROMPT.encode()).hexdigest()}
def _post(self, endpoint: str, payload):
body = None if payload is None else json.dumps(payload).encode()
request = urllib.request.Request(self.url + endpoint, data=body, headers={"Content-Type": "application/json"})
with urllib.request.urlopen(request, timeout=900) as response:
return json.load(response)
def generate(self, prompt: str, max_new_tokens: int = 3072) -> dict:
start = time.monotonic()
result = self._post("/api/generate", {"model": self.model, "system": SYSTEM_PROMPT, "prompt": prompt,
"stream": False, "options": {"temperature": 0, "seed": 42, "num_predict": max_new_tokens, "num_ctx": 4096}})
elapsed = time.monotonic() - start
return {"output": result["response"], "generation_seconds": elapsed, "generation_call_seconds": elapsed,
"tokens": result.get("eval_count"), "done_reason": result.get("done_reason")}
class UnslothGenerator:
def __init__(self, adapter: str, base_model: str | None = None, **kwargs):
from unsloth import FastLanguageModel
import torch
if not torch.cuda.is_available():
raise RuntimeError("Unsloth generation requires CUDA; local Ollama is the CPU/Mac alternative")
adapter_path = Path(adapter).expanduser().resolve(strict=True)
if not (adapter_path / "adapter_config.json").exists():
raise ValueError("Expected a local saved PEFT adapter")
config = json.loads((adapter_path / "adapter_config.json").read_text())
declared_base = config["base_model_name_or_path"]
manifest = json.loads((adapter_path / "run_manifest.json").read_text())
signature = manifest["signature"]
pinned_base, pinned_revision = signature["base_model"], signature["base_revision"]
if base_model is not None and base_model != pinned_base:
raise ValueError("Requested base model differs from the pinned training manifest")
# PEFT adapter configs do not necessarily preserve the training revision.
# Load the exact pinned quantized base first, then attach local LoRA weights.
self.model, self.tokenizer = FastLanguageModel.from_pretrained(model_name=pinned_base, revision=pinned_revision,
max_seq_length=4096, dtype=torch.float16, load_in_4bit=True, trust_remote_code=False, use_exact_model_name=True)
from bitsandbytes.nn import Linear4bit
for module in self.model.modules():
if isinstance(module, Linear4bit):
module.compute_dtype = torch.float16
module.compute_type_is_set = True
from peft import PeftModel
from transformers import AutoTokenizer
self.model = PeftModel.from_pretrained(self.model, str(adapter_path), is_trainable=False)
self.tokenizer = AutoTokenizer.from_pretrained(str(adapter_path), trust_remote_code=False)
FastLanguageModel.for_inference(self.model)
self.torch = torch
self.metadata = {"backend": "unsloth", "adapter": directory_fingerprint(adapter_path), "base_model": pinned_base, "adapter_declared_base": declared_base,
"requested_base_model": base_model, "base_revision": pinned_revision,
"torch_version": torch.__version__, "cuda_version": torch.version.cuda,
"packages": {name: importlib.metadata.version(name) for name in ["unsloth", "transformers", "peft", "bitsandbytes"]},
"gpu": torch.cuda.get_device_name(), "system_prompt_sha256": hashlib.sha256(SYSTEM_PROMPT.encode()).hexdigest()}
try:
from huggingface_hub import snapshot_download
self.metadata["base_artifacts"] = directory_fingerprint(Path(snapshot_download(repo_id=pinned_base, revision=pinned_revision, local_files_only=True)))
except Exception as exc:
self.metadata["base_artifacts_error"] = type(exc).__name__ + ": " + str(exc)
def generate(self, prompt: str, max_new_tokens: int = 3072) -> dict:
return self.generate_many([prompt], max_new_tokens)[0]
def generate_many(self, prompts: list[str], max_new_tokens: int = 3072) -> list[dict]:
call_started = time.monotonic()
if not 1 <= len(prompts) <= 32:
raise ValueError("Free T4 inference batches must contain one to thirty-two prompts")
texts = [self.tokenizer.apply_chat_template(
[{"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": prompt}],
tokenize=False, add_generation_prompt=True) for prompt in prompts]
previous_padding = self.tokenizer.padding_side
self.tokenizer.padding_side = "left"
try:
inputs = self.tokenizer(texts, return_tensors="pt", padding=True, add_special_tokens=False).to("cuda")
finally:
self.tokenizer.padding_side = previous_padding
length = inputs.input_ids.shape[1]
if length + max_new_tokens > 4096:
raise ValueError("Prompt plus generation exceeds the 4096-token bound; do not truncate evaluation prompts")
self.torch.cuda.synchronize()
start = time.monotonic()
with self.torch.inference_mode():
output = self.model.generate(**inputs, max_new_tokens=max_new_tokens, do_sample=False,
use_cache=True, pad_token_id=self.tokenizer.eos_token_id)
self.torch.cuda.synchronize()
elapsed = time.monotonic() - start
eos = self.model.generation_config.eos_token_id
eos_ids = set(eos if isinstance(eos, list) else [eos, self.tokenizer.eos_token_id])
results = []
for index, sequence in enumerate(output[:, length:].tolist()):
stop = next((i for i, token in enumerate(sequence) if token in eos_ids), None)
generated = sequence if stop is None else sequence[:stop + 1]
results.append({"output": self.tokenizer.decode(generated, skip_special_tokens=True),
"generation_seconds": elapsed, "generation_batch_size": len(prompts),
"latency_note": "generation_seconds times model.generate; generation_call_seconds includes chat formatting, tokenization, device transfers and decoding for the whole batch. Neither is divided by batch size.",
"tokens": len(generated), "prompt_tokens": int(inputs.attention_mask[index].sum().item()),
"done_reason": "stop" if stop is not None else "length"})
call_elapsed = time.monotonic() - call_started
for result in results:
result["generation_call_seconds"] = call_elapsed
return results
def add_backend_args(parser):
parser.add_argument("--backend", choices=["ollama", "unsloth"], required=True)
parser.add_argument("--model", help="Installed Ollama model tag")
parser.add_argument("--ollama-url", default="http://127.0.0.1:11434")
parser.add_argument("--adapter", help="Local Unsloth adapter directory")
parser.add_argument("--base-model", default=None)
parser.add_argument("--max-new-tokens", type=int, default=3072)
def make_generator(args):
if not 1 <= args.max_new_tokens <= 3072:
raise ValueError("Generation must use 1–3072 tokens, reserving context for instructions")
if args.backend == "ollama":
if not args.model:
raise ValueError("--model is required for Ollama")
return OllamaGenerator(args.model, args.ollama_url)
if not args.adapter:
raise ValueError("--adapter is required for Unsloth")
return UnslothGenerator(args.adapter, args.base_model)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
add_backend_args(parser)
parser.add_argument("--prompt", required=True)
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
if args.output.exists():
parser.error("Output already exists; refusing to overwrite a generation")
generator = make_generator(args)
result = generator.generate(args.prompt, args.max_new_tokens)
args.output.parent.mkdir(parents=True, exist_ok=True)
with args.output.open("x") as handle:
handle.write(result["output"])
result["metadata"] = generator.metadata
args.output.with_suffix(args.output.suffix + ".generation.json").write_text(json.dumps(result, indent=2) + "\n")
parse_project(result["output"])
print(args.output)
|