Instructions to use OmniJev/PlayJev-0.8B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use OmniJev/PlayJev-0.8B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="OmniJev/PlayJev-0.8B") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("OmniJev/PlayJev-0.8B") model = AutoModelForMultimodalLM.from_pretrained("OmniJev/PlayJev-0.8B", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.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=40) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use OmniJev/PlayJev-0.8B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "OmniJev/PlayJev-0.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": "OmniJev/PlayJev-0.8B", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/OmniJev/PlayJev-0.8B
- SGLang
How to use OmniJev/PlayJev-0.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 "OmniJev/PlayJev-0.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": "OmniJev/PlayJev-0.8B", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'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 "OmniJev/PlayJev-0.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": "OmniJev/PlayJev-0.8B", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Docker Model Runner
How to use OmniJev/PlayJev-0.8B with Docker Model Runner:
docker model run hf.co/OmniJev/PlayJev-0.8B
PlayJev: A Multimodal JEV-Like Model for Small Games
🎮 Gallery
One model, one prompt, ten games. Every tile opens that game on the demo with the model playing; the number under each is its score against the teacher (1.00 = matches the teacher, 0 = random play).
Space Invaders 👾 1.00 |
Racer 🏎️ 1.00 |
Sokoban 📦 1.00 |
Snake 🐍 0.79 |
Pacman 👻 0.52 |
Infinite Mario 🍄 0.32 |
Tetris 🧱 0.30 |
Floppy Bird 🐦 0.16 |
Breakout 🧊 0.14 |
2048 🔢 0.13 |
🏆 Scores
16 held-out episodes per game, argmax move, episodes capped at 1500 steps. Random play and the teacher run the same seeds through the same harness. vs teacher is (model - random) / (teacher - random), so 0 is random play and 1.00 is the teacher. In the chart the light bars are behaviour cloning and the first DAgger round, the dark bar is this release.
| Game | Random | PlayJev | Teacher | vs teacher |
|---|---|---|---|---|
| 👾 Space Invaders | 215 | 400 | 400 | 1.00 |
| 🏎️ Racer | 238 | 6707 | 6712 | 1.00 |
| 📦 Sokoban | 6.6 | 102.1 | 102.2 | 1.00 |
| 🐍 Snake | 1.0 | 89.5 | 114 | 0.79 |
| 👻 Pacman | 113 | 3702 | 7026 | 0.52 |
| 🍄 Infinite Mario | 613 | 1764 | 4229 | 0.32 |
| 🧱 Tetris | 162 | 4718 | 15288 | 0.30 |
| 🐦 Floppy Bird | 0.0 | 13.8 | 84.0 | 0.16 |
| 🧊 Breakout | 496 | 2712 | 16547 | 0.14 |
| 🔢 2048 | 1021 | 3386 | 19593 | 0.13 |
| mean | 0.53 |
🧠 How It Decides
The model never sees a game's name. It sees the current frame and the list of moves, and it answers with one of them.
The input is the current frame and the list of moves, rendered with the frozen OpenJev prompt. The answer is
the single token after Answer:, and the probability over moves is the softmax over the option letters at
that position: one forward pass, no sampling, nothing generated. Moves are shuffled in every training sample,
so position carries no information. Where velocity matters the vision tower also takes the previous frame, at
no extra token cost.
The demo's single game view is the whole model in one picture: the frame on the left is the only input, the bars are what the forward pass returns, the line below them is how sure it was at every step so far.
from playjev.model import PlayJevModel # github.com/OmniJev/PlayJev
model = PlayJevModel("OmniJev/PlayJev-0.8B").load()
d = model.decide([frame], options)[0] # one forward pass, a probability per move
d.choice, d.probs, d.confidence # the move it takes, the distribution, how sure it is
The prompt, the readout and the option format are built in playjev/model.py, and the demo prints the exact prompt for every game.
🏋️ Training
| 🤖 Ten teachers one program per game plays on the internal state and labels every frame with a soft target |
📸 863k frames behaviour cloning, one epoch, full fine-tuning of the 0.8B base |
🔁 Two DAgger rounds the model plays 40k frames per game, the teachers relabel what it visited |
One program per game (BFS, expectimax, placement search, A* with deadlock pruning, physics search) plays on the game's internal state and labels frames with a soft target. The model trains on 863k such frames, then on two DAgger rounds where it plays 40k frames per game and the teachers relabel what it visited. Full fine-tuning, one epoch per round, batch 64, learning rate 2e-5, fp32 master weights with bf16 autocast. The trainer is playjev/train_sft.py.
🔭 Open Problems
- 🏃 Motion (Breakout, Mario): one still frame carries no velocity, so the previous frame goes in as a second image.
- 🎯 Single-step precision (Floppy Bird, Tetris): the move that decides the episode is a few hundred frames out of 40k.
- 🔍 Tile digits at 448 px (2048): relabelling cannot help where the digits are unreadable, resolution can.
- ⏱️ Latency: at 83 to 100 ms per step the decision lands one step late, and training on labels shifted one step buys part of it back.
📄 Licence
Apache-2.0, same as the base model. The ten games are other people's work and stay in the code repository under their own licences.
- Downloads last month
- -
Model tree for OmniJev/PlayJev-0.8B
Base model
Qwen/Qwen3.5-0.8B-Base