Ornith 1.5 9B: the self-improving open-weight model as an API
Ornith 1.5 9B is a dense 9-billion-parameter model from ornith-ai. It is the smallest of the three Ornith 1.5 scales. It is the one built for single-GPU and edge deployment. It is trained with a self-improvement loop. Rather than learning only from human-curated tasks, it generates its own training tasks and builds its own scaffolds. It improves through reinforcement learning on its own solution attempts. The publisher ships the weights under MIT and publishes self-hosting recipes, but no first-party API. This platform closes that gap. The model will serve under the alias ornith-1.5-9b on an OpenAI-compatible chat endpoint, metered per token from a prepaid wallet. The row is not on the public models list yet, and no date is promised.
Last verified: 2026-09-25
What it is
The official model card describes a 9B dense model designed for efficient single-GPU deployment. A quantized Ornith-1.5-9B-Mobile variant exists for phones. Per the publisher's release post, the family spans three scales: a 397B mixture-of-experts flagship, a 35B mixture-of-experts mid-size model, and this 9B dense model. The lineage is public. Ornith 1.0 was built on top of Qwen3.5 and Gemma 4. The build added continued pretraining, mid-training, and post-training. Ornith 1.5 extends that base with the expanded self-improvement loop.
The identity facts that matter for planning:
| Fact | Value | Where the number comes from |
|---|---|---|
| Parameters | about 9B, dense | model card |
| Weights size | about 19 GB in bf16 | model card |
| License | MIT | model card |
| Native context window | 262,144 tokens | model card |
| Served window on this route | 100,000 tokens | this platform |
| Default behavior | reasoning on, thinking trace returned separately | model card |
| Tool calling | OpenAI-style tool_calls | model card |
| Edge variant | Ornith-1.5-9B-Mobile, quantized | model card and release post |
Two behaviors shape how you build against it.
It is a reasoning model. By default each assistant turn opens with a thinking trace before the final answer. The serving recipes in the card parse that trace into a separate reasoning_content field, and this platform's route does the same. Your application receives the answer in content and the reasoning in reasoning_content. Logs stay clean and nothing gets pasted into the chat history by accident. You can turn thinking off per request with reasoning_effort: "minimal" (details in API usage below).
It is tool-aware. The model emits well-formed function calls that surface as OpenAI-style tool_calls. The card states it works out of the box with standard agent frameworks. On the agentic benchmarks the publisher reports, MCP-Atlas at 54.2 and ClawEval at 66.5, the 9B sits between same-size peers and models several times larger.
The context numbers deserve their own sentence because pages conflict on them. The model's native window is 262,144 tokens. The serving recipes on the card confirm it (--max-model-len 262144 in the official vLLM command). On this platform the served window is 100,000 tokens. That is the honest number for capacity planning. The card also documents YaRN RoPE scaling for self-hosters who need more, roughly one million tokens at a scaling factor of 4.0. One real caveat: the scaling applies statically to every request. It can slightly reduce quality on ordinary-length inputs.
On this platform the model answers to ornith-1.5-9b on the chat route. It is coming soon, with no date promised; the models index reflects the catalog as it stands, and the chat category page covers the route family.
Use cases
The model's profile, a small dense reasoning model with tool calling, points at specific jobs.
- Contained coding work. Single-file scripts, functions, small refactors, test scaffolding, command-line utilities. This is where the size class earns its keep: fast answers to bounded problems. For whole-codebase agent work, the 35B sibling is the built lane on this platform.
- Tool-calling features at small scale. The OpenAI-style
tool_callsoutput and the separate reasoning field make it a fit for agent loops, MCP-style integrations, and assistants that need to show or log why they acted. - High-volume generation where 9B is enough. Drafting, classification, extraction, chat backends: jobs where the quality bar is met by this class of model and the winning properties are throughput and a per-token meter. The throughput numbers measured on the reference GPU class are in Benchmarks below.
- Review-friendly reasoning. Because the thinking trace arrives in its own field, human-in-the-loop workflows can audit the reasoning without cluttering the answer pipeline.
- Local-to-hosted portability. The request shape is the same OpenAI-compatible chat format you would use against a local vLLM or llama.cpp server. Teams prototype locally and step up to the metered route by swapping the base URL and the model id, with no client rewrite.
Run it locally or call the API
The MIT license means the local road is fully open. For some teams it is the right one. The official local routes: the Ollama library build (ollama run ornith-1.5:9b, a 6.6 GB package at 4-bit quantization), and the publisher's GGUF repository behind llama.cpp's llama-server. The vLLM and SGLang recipes on the model card cover full-precision serving on a single 80 GB GPU.
The honest decision rule:
Run it locally when a machine is already there and traffic is steady enough to keep a GPU warm. Run it locally when you need the weights inside a boundary you control, or when you want to fine-tune.
Call the API when you want the model without the upkeep. No quantization choices. No runtime version pins (the card requires vLLM 0.19.1+, SGLang 0.5.9+, transformers 5.8.1+). No idle hardware. A metered bill instead. The hosted route adds what a local server does not ship. It brings per-token metering drawn from a prepaid wallet, keys you can revoke independently, and a dated throughput baseline you can plan against.
API usage
The route is POST /v1/chat/completions with a Bearer key from the console, in the OpenAI-compatible shape your client already speaks. The model id is ornith-1.5-9b.
POST /v1/chat/completions
Authorization: Bearer <your key>
Content-Type: application/json
Four laws of this endpoint that save debugging time:
reasoning_effortis the thinking control. Accepted values areminimal,low,medium, andhigh.minimalturns thinking off; the other three run it. The model's own serving dialect carries this switch nested underchat_template_kwargs.enable_thinking, and the platform performs that mapping behind the endpoint. For thinking control,reasoning_effortis the only accepted form. A hand-rolledenable_thinkingor a hand-rolledchat_template_kwargsobject returns a 400 parameter error, so a wrong knob fails loudly at the door instead of silently.- Unknown parameters are rejected. Accepted top-level params include the OpenAI-compatible core:
model,messages,stream,max_tokensandmax_completion_tokens, the sampling controls (temperature,top_p,top_k,min_p,frequency_penalty,presence_penalty),stop,seed,n,logit_bias,user, the tool controls (tools,tool_choice,parallel_tool_calls),response_format,reasoning_effort,stream_options,metadata,logprobsandtop_logprobs, andsession_idfor delta-only conversation turns. A key outside the accepted set returns a parameter error rather than being silently ignored. - Metering counts what the model actually moves. Input tokens, output tokens, and cached input tokens each meter at their own rate. The pricing page renders the current rates once the row is listed. Thinking tokens count as output tokens, so a reasoning-heavy request bills accordingly.
- The wallet is the spend limit. The route draws from a prepaid wallet: a request that arrives after the balance is gone is refused with a named error instead of quietly going into debt. Each API key can be revoked on its own, so an exposed key is disabled without touching the rest.
Streaming works the usual way: "stream": true returns server-sent events, and omitting it returns one aggregated JSON body. Both bill identically.
The route ships with sampler defaults tuned for this build. The card's own recommendations (temperature 0.6 with top_p 0.95 for precise coding, temperature 1.0 for general tasks) can be sent explicitly if your application wants them.
curl
curl -X POST "https://api.ironstratum.com/v1/chat/completions" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "ornith-1.5-9b",
"messages": [
{"role": "user", "content": "Write a Python function that retries a request with exponential backoff."}
],
"reasoning_effort": "minimal"
}'
python
import os
import requests
resp = requests.post(
"https://api.ironstratum.com/v1/chat/completions",
headers={"Authorization": "Bearer " + os.environ["KEY"]},
json={
"model": "ornith-1.5-9b",
"messages": [
{
"role": "user",
"content": "Write a Python function that retries a request with exponential backoff.",
}
],
"reasoning_effort": "high",
},
timeout=120,
)
resp.raise_for_status()
message = resp.json()["choices"][0]["message"]
print(message.get("reasoning_content", "")[:200])
print(message["content"])
openai-sdk
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.ironstratum.com/v1",
api_key=os.environ["KEY"],
)
completion = client.chat.completions.create(
model="ornith-1.5-9b",
messages=[
{
"role": "user",
"content": "Write a Python function that retries a request with exponential backoff.",
}
],
reasoning_effort="high",
)
message = completion.choices[0].message
print(message.content)
An existing OpenAI SDK integration moves over by exactly two lines: the base_url and the model id.
Benchmarks
Two evidence layers, both dated, plus one honesty note the SERP is actively arguing about.
This platform's lane. Measurements taken 2026-08-22 on a 3060-class GPU running the Q5_K_M build, single-stream basis. Records: the platform launch catalog, section C, and the measurement notes recorded beside the model's row.
| Metric | Value | Basis |
|---|---|---|
| Decode throughput, single stream | 47.2 tokens/s | measured, bench-lite p50 on the live card |
| Aggregate decode, 4 concurrent streams | 157.7 tokens/s | measured |
| Fresh prefill at 50k tokens | about 35 s (about 1415 tokens/s) | measured |
| Warm incremental prefill | about 1100 tokens/s | measured |
These are service-planning numbers from a dated measurement window, not a standing SLA. One physics note matters for capacity planning. A conversation that grows toward the window cap prefills new turns at the warm rate above. A request that arrives carrying a very large cold prompt is bound by fresh-prefill time. A cold prompt near the full 100k window exceeds this card class's request-await budget. Workloads that start every request with a huge document belong on the 35B route, which runs on a larger card for exactly that reason.
For calibration against local hardware: llm-bench.io, a community benchmark aggregator, records a peak of 94.0 tokens/s for this model as of August 2026. That peak comes from four community runs on two GPUs. The fastest ran on an RTX 3080 through LM Studio with a 4.4 GB quantized build at an 8,192-token context. Different configuration, different owner, different question. Community peaks measure aggressively quantized local builds at short contexts. Our 47.2 tokens/s is a single-stream p50 on the platform's own build at its served window. Read them as answers to different questions, not as rivals.
The model's own scores. From the official model card, all rows averaged over five runs under the publisher's harness setups. Named harnesses include OpenHands for SWE-bench and Harbor/Terminus-2 for Terminal-Bench. Anti-hacking safeguards include removed git history and disabled network access:
| Benchmark | Ornith-1.5-9B | Ornith-1.0-9B | Qwen3.5-9B | Qwen3.6-35B-A3B | Gemma-4-31B |
|---|---|---|---|---|---|
| Terminal-Bench 2.1 (Terminus-2) | 46.2 | 43.1 | 21.3 | 52.5 | 42.1 |
| Terminal-Bench 2.1 (Claude Code) | 47.0 | 40.6 | 18.9 | 49.2 | not reported |
| SWE-bench Verified | 70.6 | 69.4 | 53.2 | 73.4 | 52.0 |
| SWE-bench Pro | 47.5 | 42.9 | 31.3 | 49.5 | 35.7 |
| GPQA Diamond | 86.4 | 82.5 | 81.7 | 86.0 | 84.3 |
| HLE (with tools) | 30.5 | 26.4 | 24.5 | 28.9 | 26.5 |
| MCP-Atlas | 54.2 | 49.4 | 46.8 | 62.8 | 55.0 |
| ClawEval | 66.5 | 63.1 | 53.2 | 68.7 | 48.5 |
Read the table for what it is. A 9B model clears its own predecessor on every row. It clears the Qwen3.5 9B it was built from by wide margins and sits close to models three to four times its size. The 35B sibling is ahead on six of the eight rows shown; the 9B is ahead on GPQA Diamond and tool-assisted HLE.
Provenance. Every number in that table is provider-run. The card is explicit about its method, which is to its credit. Independent coverage has not yet reproduced it at scale. The directories that track provenance list the model as unranked pending non-generated evidence. Independent local write-ups report mixed results on agentic tasks. None of those secondary write-ups appear as citations here because they disagree with each other. What we publish on our side is different in kind: throughput and metering measurements from the reference hardware class, dated above. For answer quality, the decision rule is to run your own workload. The per-token meter with the wallet stop exists so that doing so is cheap to try, with any overshoot capped at the one request in flight when the balance runs dry.
Getting started
- Create an account through the console's invite flow. The console is invite-only at launch. It is where the wallet balance and key rotation are kept.
- Create an API key. The intended shape is one key per project. Each key revokes independently, so disabling one never halts the others.
- Check the rate. Per-token metering means the pricing page carries the full rate card. Load what you are willing to spend. A request arriving after the balance is gone is refused with a named error.
- Make the first call. Run the curl tab with
KEYexported. Areasoning_contentfield in the response means thinking ran;"reasoning_effort": "minimal"switches it off next time.
The chat category page covers the rest of the chat family, and the models index lists every model on the platform.