Image-Text-to-Text
Transformers
Safetensors
GGUF
qwen3_5
system-one
decision-making
classification
calibration
structured-output
on-device
multimodal
Instructions to use bynn-intelligence-com/decisionnode-edge with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use bynn-intelligence-com/decisionnode-edge with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="bynn-intelligence-com/decisionnode-edge")# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("bynn-intelligence-com/decisionnode-edge") model = AutoModelForMultimodalLM.from_pretrained("bynn-intelligence-com/decisionnode-edge", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use bynn-intelligence-com/decisionnode-edge with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf bynn-intelligence-com/decisionnode-edge:Q8_0 # Run inference directly in the terminal: llama cli -hf bynn-intelligence-com/decisionnode-edge:Q8_0
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf bynn-intelligence-com/decisionnode-edge:Q8_0 # Run inference directly in the terminal: llama cli -hf bynn-intelligence-com/decisionnode-edge:Q8_0
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf bynn-intelligence-com/decisionnode-edge:Q8_0 # Run inference directly in the terminal: ./llama-cli -hf bynn-intelligence-com/decisionnode-edge:Q8_0
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf bynn-intelligence-com/decisionnode-edge:Q8_0 # Run inference directly in the terminal: ./build/bin/llama-cli -hf bynn-intelligence-com/decisionnode-edge:Q8_0
Use Docker
docker model run hf.co/bynn-intelligence-com/decisionnode-edge:Q8_0
- Llama new
- LM Studio
- Jan
- vLLM
How to use bynn-intelligence-com/decisionnode-edge with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "bynn-intelligence-com/decisionnode-edge" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "bynn-intelligence-com/decisionnode-edge", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/bynn-intelligence-com/decisionnode-edge:Q8_0
- SGLang
How to use bynn-intelligence-com/decisionnode-edge 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 "bynn-intelligence-com/decisionnode-edge" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "bynn-intelligence-com/decisionnode-edge", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'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 "bynn-intelligence-com/decisionnode-edge" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "bynn-intelligence-com/decisionnode-edge", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Ollama
How to use bynn-intelligence-com/decisionnode-edge with Ollama:
ollama run hf.co/bynn-intelligence-com/decisionnode-edge:Q8_0
- Unsloth Desktop
- Docker Model Runner
How to use bynn-intelligence-com/decisionnode-edge with Docker Model Runner:
docker model run hf.co/bynn-intelligence-com/decisionnode-edge:Q8_0
- Lemonade
How to use bynn-intelligence-com/decisionnode-edge with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull bynn-intelligence-com/decisionnode-edge:Q8_0
Run and chat with the model
lemonade run user.decisionnode-edge-Q8_0
List all available models
lemonade list
- Atomic Chat
DecisionNode Edge 0.9.2: point and box questions, the /v1/systemone route as hosted, a box calibration
7706b50 verified Download runtime/src/decisionnode_edge/answers.py from bynn-intelligence-com/decisionnode-edge: direct link, hf CLI and curl.
- Browser
- Download file 9.74 kB
-
https://huggingface.co/bynn-intelligence-com/decisionnode-edge/resolve/main/runtime/src/decisionnode_edge/answers.py
- Command line
-
hf download hf://bynn-intelligence-com/decisionnode-edge/runtime/src/decisionnode_edge/answers.py
-
curl -L -o answers.py https://huggingface.co/bynn-intelligence-com/decisionnode-edge/resolve/main/runtime/src/decisionnode_edge/answers.py
9.74 kB
| """Calibration and the answer objects of the hosted API. | |
| Calibration (calibration.json): | |
| choice, score p = softmax(z / T(K)), T(K) = t0 + t1 * ln K, K clamped to the fitted range | |
| truth p_yes = sigmoid((z_yes - z_no) / T + b) | |
| coord p = softmax(z), a point or box question's reading, never calibrated (places.py) | |
| A parameter set exists per input kind ("text", "image"); a missing one is the identity. | |
| The answers, rounded as the hosted API rounds them: | |
| choice {"type", "choice", "confidence", "probabilities": {option: p}} options in alphabetical order | |
| score {"type", "score", "confidence", "legend": {"0": level}, "probabilities": {"0": p}} | |
| truth {"type", "truth"} | |
| number {"type", "number", "expected", "confidence", "probabilities": {value: p}} | |
| point {"type", "x", "y", "present", "confidence", "image", "width", "height"} places.py | |
| box {"type", "x1", "y1", "x2", "y2", "present", "confidence", "image", "width", "height"} | |
| with `max`: {"type", "count", "present", "complete", "points" | "boxes": [...], "image", "width", "height"} | |
| `choice`, `score`, `number` and the confidences come from the unrounded probabilities. A probability list is rounded | |
| to 2 decimals entry by entry, then its largest entries move by 0.01 until it sums to 1 (`round_probabilities`). | |
| `exact_sum` (the rounding of /v1/systemone, where benchmarks check the sum): the probabilities are normalised first, and | |
| the list sums to exactly 1.00 in hundredths, every value a clean 2-decimal number. | |
| """ | |
| from __future__ import annotations | |
| import math | |
| from decimal import Decimal, localcontext | |
| from typing import Sequence | |
| T_MIN, T_MAX = 0.05, 100.0 | |
| UNIT = 0.01 | |
| # --------------------------------------------------------------------------- | |
| # Calibration | |
| # --------------------------------------------------------------------------- | |
| def _temperature(params: dict, k: int) -> float: | |
| if params.get("k_min") is not None: | |
| k = min(max(k, params["k_min"]), params["k_max"]) | |
| t = float(params.get("t0", 1.0)) + float(params.get("t1", 0.0)) * math.log(k) | |
| return min(T_MAX, max(T_MIN, t)) | |
| def calibrated(logits: Sequence[float], kind: str, calibration: dict, has_images: bool) -> list[float]: | |
| """Calibrated class probabilities from a question's code logits (class order: options or levels as given, | |
| [yes, no] for truth).""" | |
| if kind == "coord": | |
| return softmax(logits) | |
| params = (calibration.get("image" if has_images else "text") or {}).get("choice" if kind == "number" else kind) or {} | |
| z = [float(x) for x in logits] | |
| if kind == "truth": | |
| x = (z[0] - z[1]) / float(params.get("temperature", 1.0)) + float(params.get("bias", 0.0)) | |
| p = 1.0 / (1.0 + math.exp(-x)) if x >= 0 else math.exp(x) / (1.0 + math.exp(x)) | |
| return [p, 1.0 - p] | |
| if len(z) == 1: | |
| return [1.0] | |
| t = _temperature(params, len(z)) | |
| scaled = [x / t for x in z] | |
| top = max(scaled) | |
| log_total = math.log(sum(math.exp(x - top) for x in scaled)) | |
| return [math.exp(x - top - log_total) for x in scaled] | |
| def softmax(logits: Sequence[float]) -> list[float]: | |
| """A plain softmax (the largest score subtracted first): a coordinate row's probabilities.""" | |
| z = [float(x) for x in logits] | |
| if not z or not all(math.isfinite(x) for x in z): | |
| raise ValueError("scores must be a list of finite numbers") | |
| top = max(z) | |
| e = [math.exp(x - top) for x in z] | |
| total = math.fsum(e) | |
| return [x / total for x in e] | |
| # --------------------------------------------------------------------------- | |
| # Rounding | |
| # --------------------------------------------------------------------------- | |
| def _units(x: float) -> int: | |
| """x in hundredths, halves up (the epsilon absorbs binary error: 0.805 rounds to 0.81).""" | |
| return int(math.floor(x * 100.0 + 0.5 + 1e-9)) | |
| def round2(x: float) -> float: | |
| value = _units(x) / 100.0 | |
| return 0.0 if value == 0 else value | |
| def normalised(probs: Sequence[float]) -> list[float]: | |
| """The probabilities divided by their float64 sum (a sum within 1e-9 of 1); a list that sums to 0 as it is.""" | |
| p = [float(x) for x in probs] | |
| total = math.fsum(p) | |
| if total <= 0 or not math.isfinite(total): | |
| return p | |
| return [x / total for x in p] | |
| def round_probabilities(probs: Sequence[float], exact_sum: bool = False) -> list[float]: | |
| """Round to 2 decimals, then move the |n| largest entries by 0.01, n = int((1 - fsum(rounded)) / 0.01). | |
| A moved entry is not rounded again (0.81 + 0.01 is 0.8200000000000001), as the hosted API returns it. | |
| `exact_sum` (pass normalised probabilities): n is 100 less the sum of the rounded hundredths, and every value is the | |
| clean 2-decimal number, so the hundredths sum to exactly 100.""" | |
| p = [float(x) for x in probs] | |
| units = [_units(x) for x in p] | |
| rounded = [u / 100.0 for u in units] | |
| if exact_sum: | |
| left = abs(100 - sum(units)) | |
| step = 1 if sum(units) < 100 else -1 | |
| order = sorted(range(len(p)), key=lambda i: (-p[i], i)) | |
| while left: # every entry moves once, the largest first; a list that needs more moves round again | |
| progressed = False | |
| for i in order: | |
| if not left: | |
| break | |
| if units[i] + step < 0: | |
| continue | |
| units[i] += step | |
| left -= 1 | |
| progressed = True | |
| if not progressed: | |
| raise ValueError("probabilities cannot be rounded to a list that sums to 1") | |
| return [0.0 if u == 0 else u / 100.0 for u in units] | |
| n = int((1.0 - math.fsum(rounded)) / UNIT) | |
| if n: | |
| step = 1 if n > 0 else -1 | |
| for i in sorted(range(len(p)), key=lambda i: (-p[i], i))[: abs(n)]: | |
| rounded[i] = rounded[i] + UNIT if step > 0 else rounded[i] - UNIT | |
| return [0.0 if x == 0 else x for x in rounded] | |
| def _argmax_first(probs: Sequence[float]) -> int: | |
| best = 0 | |
| for i, p in enumerate(probs): | |
| if p > probs[best]: | |
| best = i | |
| return best | |
| # --------------------------------------------------------------------------- | |
| # Answers | |
| # --------------------------------------------------------------------------- | |
| def choice_answer(keys: Sequence[str], probs: Sequence[float], exact_sum: bool = False) -> dict: | |
| if exact_sum: | |
| probs = normalised(probs) | |
| best = _argmax_first(probs) | |
| k = len(probs) | |
| confidence = 1.0 if k == 1 else min(1.0, max(0.0, (k * probs[best] - 1.0) / (k - 1.0))) | |
| shown = round_probabilities(probs, exact_sum) | |
| return {"type": "choice", "choice": keys[best], "confidence": round2(confidence), "probabilities": dict(sorted(zip(keys, shown)))} | |
| def score_answer(levels: Sequence, probs: Sequence[float], exact_sum: bool = False) -> dict: | |
| if exact_sum: | |
| probs = normalised(probs) | |
| k = len(probs) | |
| if k == 1: | |
| confidence = 1.0 | |
| else: | |
| mode = _argmax_first(probs) | |
| spread = sum(p * abs(i - mode) for i, p in enumerate(probs)) | |
| confidence = min(1.0, max(0.0, 1.0 - spread / ((k * k // 4) / k))) | |
| return { | |
| "type": "score", | |
| "score": round2(sum(i * p for i, p in enumerate(probs))), | |
| "confidence": round2(confidence), | |
| "legend": {str(i): level for i, level in enumerate(levels)}, | |
| "probabilities": {str(i): x for i, x in enumerate(round_probabilities(probs, exact_sum))}, | |
| } | |
| def truth_answer(probs: Sequence[float]) -> dict: | |
| return {"type": "truth", "truth": round2(probs[0])} | |
| def _expected_text(value: float, decimals: int) -> str: | |
| """Halves up to `decimals` (at most 15 significant digits), with a decimal point, never -0.0.""" | |
| with localcontext() as ctx: | |
| ctx.prec = 200 | |
| exact = Decimal(value) | |
| whole = abs(int(exact)) | |
| decimals = min(decimals, 15 - (len(str(whole)) if whole else 0)) | |
| units = (exact * Decimal(10) ** decimals + Decimal("0.5") + Decimal("1e-9")).to_integral_value(rounding="ROUND_FLOOR") | |
| text = format(units * Decimal(10) ** -decimals, "f") | |
| if "." in text: | |
| text = text.rstrip("0") | |
| text = text + "0" if text.endswith(".") else text | |
| else: | |
| text += ".0" | |
| return "0.0" if text == "-0.0" else text | |
| def _number(text: str) -> int | float: | |
| return float(text) if "." in text else int(text) | |
| def number_answer(grid, probs: Sequence[float]) -> dict: | |
| """The most probable value, the probability-weighted mean (`expected`), the probability of the value | |
| (`confidence`) and every value above 0.001 to 3 decimals (rounded entries that sum above 1 lose 0.001 each, | |
| the largest first, the answer's own last).""" | |
| best = _argmax_first(probs) | |
| texts = grid.texts() | |
| expected = math.fsum(float(text) * p for text, p in zip(texts, probs)) | |
| listed = [i for i in range(grid.n) if probs[i] > 0.001 or i == best] | |
| millis = {i: int(math.floor(probs[i] * 1000.0 + 0.5 + 1e-9)) for i in listed} | |
| excess = sum(millis.values()) - 1000 | |
| order = sorted((i for i in listed if i != best), key=lambda i: (-probs[i], i)) | |
| while excess > 0: | |
| lowered = False | |
| for i in order: | |
| if excess <= 0: | |
| break | |
| if millis[i] > 0: | |
| millis[i] -= 1 | |
| excess -= 1 | |
| lowered = True | |
| if not lowered: | |
| millis[best] -= 1 | |
| excess -= 1 | |
| return { | |
| "type": "number", | |
| "number": _number(texts[best]), | |
| "expected": float(_expected_text(expected, max(2, grid.d))), | |
| "confidence": round2(probs[best]), | |
| "probabilities": {texts[i]: millis[i] / 1000.0 for i in listed}, | |
| } | |