- Models
- DecisionNode Edge, 2.2B parameters, and DecisionNode Edge Mini, 0.85B
- Version
- 0.9.2: the 0.9.1 weights with runtime 0.9.2, which adds point and box questions
- Weights
- On Hugging Face: decisionnode-edge and decisionnode-edge-mini, from Bynn Intelligence
- Answers
- Choice, Score, Truth, Number, Point and Box, over text and up to 16 images
- Format
- The request and response of
/v1/decide - Runtime
- The Python package
decisionnode-edge, Python 3.10 or newer - Runs on
- NVIDIA GPUs, Apple silicon, x86 CPUs and the devices llama.cpp supports, on the fastest backend installed
- Hosting
- Yours. We never host Edge, so it has no price, no API endpoint and no rate limits
- Licence
- AGPL-3.0, or a commercial licence from Bynn Intelligence Inc. for closed products and services
Both are System One models, as the hosted models are: one pass, no deliberation, a calibrated probability over the options you allowed (what that means). They run on your hardware instead of ours.
Two sizes#
| Model | Parameters | Decision accuracy | Use it | Weights |
|---|---|---|---|---|
| DecisionNode Edge | 2.2B | 74.2% | When accuracy matters most | Hugging Face |
| DecisionNode Edge Mini | 0.85B | 69.2% | On CPUs and constrained devices | Hugging Face |
Decision accuracy is the mean over the same 15-suite evaluation the hosted models are measured on, where DecisionNode MoE scores 81.7% and DecisionNode Flash 78.3% (benchmarks). Edge is about 5 points more accurate than Edge Mini; Edge Mini runs about 1.8 times faster on a CPU. Preliminary results, October 2026.
Install#
The runtime is one Python package, decisionnode-edge. The base install runs both models on PyTorch; extras add image support and the faster backends (below).
pip install decisionnode-edge # PyTorch, Transformers and safetensors
pip install "decisionnode-edge[images]" # adds image supportEach model repository also carries the runtime in its runtime/ folder, so a machine can install it from the downloaded model folder: the last tab above installs the same package. Its README covers the build options for each backend.
Quick start#
Download a model once, load it, and send the request you would send to /v1/decide. This is the support message from the Quickstart, answered on your own machine by DecisionNode Edge.
from huggingface_hub import snapshot_download
from decisionnode_edge import EdgeModel
model = EdgeModel.load(snapshot_download("bynn-intelligence-com/decisionnode-edge"))
response = model.decide({
"state": "Customer: I was charged twice and nobody has replied for 3 days.",
"questions": {
"route": {
"type": "choice",
"instructions": "Where should this go?",
"criteria": {"billing": "money", "bug": "broken", "account": "login"},
},
"urgency": {
"type": "score",
"instructions": "How urgent is this?",
"criteria": ["routine", "today", "urgent", "critical"],
},
"refund": {"type": "truth", "instructions": "Refund this automatically?"},
},
})
print(response["answers"]["route"]["choice"], response["answers"]["refund"]["truth"])There is no model field: the folder you load is the model, and the response names it, decisionnode-edge-0.9.1 (decisionnode-edge-mini-0.9.1 for Edge Mini). Every answer has the shape the API returns, and usage counts input tokens as the API does, though nothing is billed. The same request always gets the same answer.
Images#
Pass images as base64 data with a media_type, as the API takes them, or as a local path. Every question in the request sees every image.
model.decide({
"state": {
"claim": {"merchant": "Nordic Rail", "total": "740.00", "currency": "SEK"},
},
"images": [{"id": "receipt", "path": "receipt.jpg"}],
"questions": {
"total_matches": {
"type": "truth",
"instructions": "Does the total on the receipt equal the total in the claim?",
},
"items": {
"type": "number",
"instructions": "How many line items are on the receipt?",
"min": 0,
"max": 50,
},
},
})From the command line or over HTTP#
# one request, its answers as JSON
python -m decisionnode_edge ./decisionnode-edge request.json
# a local HTTP server
python -m decisionnode_edge serve ./decisionnode-edge --port 8000serve answers POST /v1/decide on 127.0.0.1:8000 by default, so code written for the hosted API, an SDK included, runs against it with only the base URL changed. It listens on the loopback address unless you tell it otherwise, answers one request at a time, and takes --api-key with a file holding a key when other machines may reach it. Over HTTP, images go as base64 data only.
Recommended setup#
Run Edge where the decision is made: on the robot, the drone, the camera or your own servers. It answers every question first, in milliseconds and without a network round trip. A question that comes back with low confidence goes to DecisionNode Flash on the hosted API, and one that DecisionNode Flash is still unsure of goes to DecisionNode MoE, our most accurate model. Most questions are settled on the device; only the hard ones reach the API.
- 1.On the device. DecisionNode Edge answers every question, locally.
- 2.Below 0.7, DecisionNode Flash. Only the questions still under the threshold go to the hosted API.
- 3.Still below 0.7, DecisionNode MoE. Its answer is final. Below the threshold, your code takes its safe action: hold, decline or slow down.
route"billing"0.92settled hereurgency2.24 of 30.65to the APIrefund0.13 false0.74settled here
route (settled on the device, not sent)urgencyrefund (settled on the device, not sent)
Its answer replaces the one from the device.
The final word. Below 0.70 here, your code takes its safe action: hold, decline or slow down.
The Quickstart's support request on DecisionNode Edge 0.9.2: route and refund are settled on the device, and only urgency, at 0.65, goes on to DecisionNode Flash. A Truth answer's sureness is its distance from 0.50, doubled: refund at 0.13 reads as 0.74.
import os
import requests
from huggingface_hub import snapshot_download
from decisionnode_edge import EdgeModel
edge = EdgeModel.load(snapshot_download("bynn-intelligence-com/decisionnode-edge"))
API = "https://api.decisionnode.com/v1/decide"
HEADERS = {"Authorization": f"Bearer {os.environ['DECISIONNODE_API_KEY']}"}
def confidence(answer):
if answer["type"] == "truth": # distance from 0.5, on the same 0 to 1 scale
return abs(2 * answer["truth"] - 1)
return answer["confidence"]
def decide(request, threshold=0.7):
answers = edge.decide(request)["answers"]
for model in ("decisionnode-1.0-flash", "decisionnode-1.0"):
unsure = {k: q for k, q in request["questions"].items() if confidence(answers[k]) < threshold}
if not unsure:
break
hosted = requests.post(API, headers=HEADERS, timeout=10,
json={**request, "model": model, "questions": unsure, "fallback": False})
hosted.raise_for_status()
answers.update(hosted.json()["answers"])
return answers # still below the threshold: take the safe actionPass images as base64 data with a media_type rather than a local path, so the same request is valid on the device and on the hosted API. Only the questions that are still unsure are sent, and the same request always gets the same answer, so each question costs at most one call per hosted model.
All three models take one request format and return calibrated probabilities, so the same request and the same threshold work at every step. 0.7 is the bar the playground's generated code acts at; tune it per question on your own data (confidence-gated routing). The code sends "fallback": false, so the final word comes from DecisionNode MoE itself and not from DecisionNode Flash in its place when it has no ready capacity; that call can then answer 529, to retry after Retry-After (how).
Question types and limits#
| Type | You send | You get | Runs on |
|---|---|---|---|
| Choice | 1 to 255 options, each with an optional description | The chosen option, a confidence and a probability for every option | Edge and the hosted API |
| Score | 1 to 10 ordered levels, lowest first | The expected level, a confidence and a probability for every level | Edge and the hosted API |
| Truth | A statement, with optional true and false criteria | The probability that the statement is true | Edge and the hosted API |
| Number | min, max and step, up to 4,096 values | The most probable value, the expected value, a confidence and the probable values | Edge and the hosted API |
| Point | An image and what to point to | A point (x, y) in pixels or fractions of the image, the probability that the thing is there, and a confidence | Edge and the hosted API |
| Box | An image and what to box | A box (x1, y1, x2, y2), the probability that the thing is there, and a confidence | Edge and the hosted API |
- Images: up to 16 per request, JPEG, PNG or WebP. Every question sees every image.
- Input length: evaluated on inputs of up to 8,192 tokens. The runtime accepts up to 16,384 and refuses a longer input rather than cutting it.
- One pass per question: a request with several questions takes one forward pass for each, whether a choice has 2 options or 255. A point takes 3 short passes on the picture and a box 5.
- Write the meaning into the question. The model reads
instructionsandcriteria, never the question's key.
Points and boxes#
A point question asks where something is in a picture, a box question asks for a rectangle around it. Add max (2 to 16) to get every match as a list. Each answer gives the place in pixels or, with "units": "normalized", fractions of the picture, present (the probability that the thing is in the picture at all) and a confidence for the place. See Points and boxes for the full answer shapes.
model.decide({
"images": [{"id": "belt", "path": "belt.jpg"}],
"questions": {
"pick": {
"type": "point",
"instructions": "The yellow package closest to the robot arm.",
},
"damage": {
"type": "box",
"instructions": "The damaged package.",
"units": "normalized",
},
"parcels": {"type": "box", "instructions": "Every parcel on the belt.", "max": 10},
},
})On 300 held-out photos with one object each:
| Model | Point on the thing | Box, IoU 0.5 or more | Box, mean IoU |
|---|---|---|---|
| DecisionNode Edge | 94.3% | 85.0% | 0.71 |
| DecisionNode Edge Mini | 90.3% | 65.7% | 0.53 |
| DecisionNode MoE, hosted | 96.0% | 92.7% | 0.85 |
| DecisionNode Flash, hosted | 95.0% | 89.7% | 0.81 |
Asked for every match on 197 pictures with up to 16 objects:
| Model | Points, precision | Points, recall | Boxes, precision | Boxes, recall |
|---|---|---|---|---|
| DecisionNode Edge | 63.0% | 59.0% | 51.0% | 42.0% |
| DecisionNode Edge Mini | 52.0% | 49.0% | 26.0% | 22.0% |
| DecisionNode MoE, hosted | 72.1% | 67.2% | 69.2% | 54.7% |
| DecisionNode Flash, hosted | 68.8% | 66.3% | 64.6% | 52.2% |
On boxes the hosted models are more accurate, and Edge is more accurate than Edge Mini. Where a box has to be right, send the question to DecisionNode Flash or DecisionNode MoE with the same request. The hosted figures are the ones on benchmarks, measured on the same pictures. Preliminary results, October 2026.
On the hosted API#
The hosted API also runs what Edge 0.9.2 does not: video, boosters, knowledge, fine-tuning, sessions, batch jobs, uploads and image URLs and inputs longer than 16,384 tokens. A question that needs one of them goes to DecisionNode Flash or DecisionNode MoE with the same request format.
Devices and backends#
EdgeModel.load picks the fastest backend installed on the machine. Every backend applies the same decision head and calibration, so answers stay consistent from one device to the next. Images, and inputs longer than a backend takes, run on PyTorch automatically. The median time for one question at about 500 tokens of input, on the device each backend was measured on:
| Device | Backend | Measured on | Edge | Edge Mini |
|---|---|---|---|---|
| NVIDIA GPU | vLLM | RTX PRO 6000 | 9.5 ms | 7.3 ms |
| Apple silicon | MLX | M5 Max | 35 ms | 17 ms |
| x86 CPU | OpenVINO | Ryzen 7 9800X3D | 0.46 s | 0.24 s |
| Any device llama.cpp supports, NVIDIA Jetson included | llama.cpp, the 8-bit build | RTX PRO 6000 | 14 ms | 10.5 ms |
| Any | PyTorch, the reference | RTX PRO 6000 | 14 ms | 14 ms |
llama.cpp with the 8-bit build takes 55 ms on an Apple M5 Max and 1.1 s on an AMD Ryzen 7 9800X3D for Edge, and 30 ms and 0.58 s for Edge Mini. In bfloat16 the weights take 4.43 GB of memory for Edge and 1.7 GB for Edge Mini; the 8-bit GGUF builds are 2.0 GB and 0.8 GB. A GPU with 6 GB of memory serves Edge requests of up to about 8,000 tokens in bfloat16.
Licence#
Both models and the decisionnode-edge runtime are released under the GNU Affero General Public License v3.0. It suits personal projects, research and open-source work: if you distribute Edge or a work based on it, or let others use such a work over a network, the AGPL requires you to make its complete source available to them under the same licence.
To use Edge in a closed-source product, a device you sell or a service you run for your customers without those obligations, write to licensing@bynn.com for a commercial licence from Bynn Intelligence Inc. The hosted models are used under the Terms, not this licence.
Decisions about people need human oversight on Edge as on the API. Do not use it on its own for consequential decisions about individuals: uses in hiring, credit, housing, insurance, education, benefits, law enforcement or health care need a person who reviews each decision and can overrule it, in line with the Acceptable Use Policy. See Responsible use.