Introduction

Rein-NPC-4B is a new open-weights model for game NPCs that have to do things, not just chat: sell the potion, repair the chainmail, call the guards, and stay the same character when a player tries to rename them. Hugging Face user jmc0, who maintains the Rein project, pushed the model card and GGUF files to Hugging Face on November 9 at about 03:00 MYT, with a browser playground where a small town of three characters runs on your own GPU. It's Apache-2.0, it runs in llama-server, and the Q4_K_M file needs about 3.4 GB of VRAM.

What shipped

  • Model: Rein-NPC-4B, a fine-tune of Qwen/Qwen3.5-4B
  • Vendor: jmc0 on Hugging Face, with code and evaluation at jasielmacedo/rein
  • Modality: runtime game AI for NPC decisions, tool calls and character consistency
  • Open vs API: open weights, Apache-2.0, no hosted API
  • Where to run it today: the Rein NPC playground Space in your browser (a cached 3 GB download), or locally through llama.cpp, LLMUnity, wllama, vLLM or Transformers
  • Concrete fact: bf16, Q8_0 and Q4_K_M GGUFs, plus a split Q4_K_M set for in-browser use

How it works

The trick is small. Rein-NPC is plain Qwen3.5-4B with 64 new tokens added, and those tokens' embedding rows are the only trained parameters. Every original weight is untouched, so the model chats exactly like the base model. What the extra tokens add is a decision mode.

Each player turn becomes two requests to the same loaded model. First, a one-token completion asks one of the character's rules about the conversation so far, with the options behind letters. The probabilities of those letters are the answer, for example show_inventory at 0.99 and none at 0.01. Second, an ordinary chat request writes the reply, shaped by that decision. The game either prefills the tool call, bans the <tool_call> token with a logit bias so the NPC can't loop on tools, or appends a one-line reminder to the player's message.

You describe a character in a short YAML sheet: a persona, a scene with live game state, the function schemas the NPC can call, and typed rules. The example shopkeeper, Mira Ashgrove, has a tool rule over show_inventory, sell_item, buy_item, repair_gear and call_guards, a name lock, and a lore guard that says sales can't be undone. No training is needed for a new character.

The numbers they publish

  • Across ten test characters with 80 player turns each, the NPC took the action the turn called for 96% of the time, against 42% for the base model on its own
  • Characters kept a locked name or trait 90% of the time under attack, against 78% without Rein
  • On 28,433 test questions about rules not seen in training, decisions scored 0.958, against 0.846 for Kev-4B, a generic decision model of the same size
  • Players can write in another language than the sheet. In the card's sample run, a Portuguese offer to sell a silver ring correctly triggered buy_item

Try it

hf download jmc0/Rein-NPC-4B-GGUF Rein-NPC-4B-Q4_K_M.gguf examples/shop-keeper.yaml \
  examples/decide.json examples/reply.json --local-dir rein-npc
cd rein-npc
llama-server -m Rein-NPC-4B-Q4_K_M.gguf --port 8080 -ngl 99 -c 32768 --parallel 2

# 1. decide: one token, read the letter probabilities
curl -s localhost:8080/completion -H "content-type: application/json" -d @examples/decide.json
# 2. reply: normal chat with the tool call prefilled or banned
curl -s localhost:8080/v1/chat/completions -H "content-type: application/json" -d @examples/reply.json

Two parallel slots let chat and decisions interleave, and with cache_prompt each extra rule costs about 100 tokens on top of the shared state.

Limits worth knowing

The author is upfront here. Rein-NPC reads explicit requests far better than situations nobody spells out, so a fainting soldier may not trigger the healing tool. A lore reminder doesn't say which fact is under attack, and end-to-end lore adherence only moved from 0.70 to 0.77. It isn't a safety or moderation filter, results come from a single seed, and the 1,352 hand-written test questions were written by the author. Your game's own validation still has to check tool arguments.

Why it matters for game devs

Most local NPC stacks bolt a classifier or a second model on top of the chat model to decide when to act. Rein keeps it to one 4B file you can ship on the player's machine, uses features every runtime already has (prefill, logit bias, a reminder line), and turns "should this NPC act now?" into a calibrated probability your game logic can threshold. It's a solid base to watch if you're building shopkeepers, quest givers or companions that need to touch game state.

—Titus