Guides
Migrating to llamay
From OpenAI, Anthropic, Ollama or llama.cpp. In most cases the change is a base URL, because llamay speaks those APIs rather than translating them — the differences that remain are listed here rather than discovered.
From the OpenAI API
Change two lines. The SDK does not need to know.
Python
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:11435/v1",
api_key="not-used", # required by the SDK, ignored unless -api-key is set
)
client.chat.completions.create(
model="", # "" means the server's loaded model
messages=[{"role": "user", "content": "hello"}],
)
TypeScript
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "http://127.0.0.1:11435/v1",
apiKey: "not-used",
});
await client.chat.completions.create({
model: "",
messages: [{ role: "user", content: "hello" }],
});
Or set OPENAI_BASE_URL and touch no code at all — which is the
version that works for a dependency you do not control.
export OPENAI_BASE_URL=http://127.0.0.1:11435/v1
export OPENAI_API_KEY=not-used
What is different
| Field | llamay |
|---|---|
model | A file or a store name. "" means whatever the server loaded. |
stop | Supported, as a string or a list. |
response_format | Supported, and enforced while sampling rather than checked after. A schema cannot come back malformed. |
tools, tool_choice | Supported. Arguments are generated under the tool's own schema. |
n | Accepted and ignored. Send the request twice, or fork a context. |
logit_bias, presence_penalty, frequency_penalty | Supported. |
user | Accepted and ignored — there is no abuse pipeline to report to. |
usage | Returned, plus prompt_tokens_details.cached_tokens and llamay's own prefill and decode timings. |
Unknown fields are ignored rather than refused. A client that sends something llamay does not implement gets an answer, not a 400. That is deliberate — SDKs send fields by default that you never chose — but it means a typo is silent. If a parameter seems to do nothing, check it against the API reference.
From the Anthropic API
from anthropic import Anthropic
client = Anthropic(base_url="http://127.0.0.1:11435", api_key="not-used")
client.messages.create(
model="", max_tokens=512,
system="Answer in one sentence.",
messages=[{"role": "user", "content": "hello"}],
)
/v1/messages is served natively: system as a string
or a list of blocks, stop_sequences, tools and
tool_choice, streaming in Anthropic's event shape, and
stop_reason distinguishing end_turn from
stop_sequence with stop_sequence naming which one
matched. max_tokens is required there, as it is upstream.
From Ollama
Your models come with you. llamay reads Ollama's store directly, so nothing is re-downloaded and nothing is converted.
llamay run -m llama3.2:3b -p "hello" # the model Ollama already pulled
llamay serve # /api/chat, /api/generate, /api/tags all served
| Ollama | llamay |
|---|---|
ollama run llama3.2 | llamay run -m llama3.2 |
ollama serve | llamay serve |
ollama pull … | llamay pull …, or POST /api/pull |
ollama list | llamay list, or GET /api/tags |
Port 11434 | Port 11435 — both can run at once |
options.num_predict | Same, and options.stop works |
| Modelfile | No equivalent. Put the system prompt in the request, or in a context you fork. |
The different port is on purpose: you can point one client at each and compare them on the same machine, against the same weights, without stopping either.
From llama.cpp
Same GGUF files, same quantisation names, same tokenizer behaviour — the correctness page covers what is checked against llama.cpp and what that check actually proves.
| llama.cpp | llamay |
|---|---|
llama-server -m model.gguf | llamay serve -m model.gguf |
-c 8192 | -ctx 8192 |
-ngl 99 | Not needed — the GPU build offloads what it can and says what it declined |
-np 4 | -conc 4 |
--grammar-file x.gbnf | --grammar x.gbnf |
-ctk q8_0 -ctv q8_0 | -kv q8, or -kv vq8 for quantised values with exact keys |
| Slots | Contexts — named, forkable, and writable to a file |
The thing with no equivalent upstream is the state engine: a context is a first-class object you can fork N ways as a page-table copy, snapshot to disk, and restore on another machine.
LangChain, LlamaIndex and the rest
Anything that takes an OpenAI-compatible base URL works unchanged.
LangChain
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
base_url="http://127.0.0.1:11435/v1",
api_key="not-used", model="",
)
LlamaIndex
from llama_index.llms.openai_like import OpenAILike
llm = OpenAILike(
api_base="http://127.0.0.1:11435/v1",
api_key="not-used", model="",
is_chat_model=True,
)
For embeddings, point the same base URL at /v1/embeddings and
start the server with -embed. One process then holds the
decoder, the encoder and the cross-encoder, which is what makes a local
retrieval stack a single binary rather than three services.
A migration checklist
- Point the base URL at llamay and run your existing tests. Most will pass.
- Pick a model that fits. A 7B is not GPT-4. See sizing, and expect to shorten prompts — prompting local models is about exactly this.
- Replace format-by-prose with
response_format. Then delete the sentences asking for JSON; they are now competing with instructions that still matter. - Move stable material into the system turn so the prefix cache can hold it, and take the timestamp out of it.
- Handle 429 rather than 500. A local server has a finite queue and says so with a
Retry-After. - Check
[DONE]on streams. A truncated stream and a finished one otherwise look the same. - Decide what happens when it cannot answer. Local-first with hosted overflow is a documented pattern, and the redaction step in the middle only works because it is local.
What to expect, honestly
Quality
A 7B will not match a frontier model on open-ended reasoning. On extraction, classification, routing and rewriting — most of what production actually runs — the gap is much smaller than the benchmarks suggest.
Latency
First token is usually faster: no network. Throughput depends on your hardware, and a warm prefix is the difference between 200 ms and 8 s on a long system prompt.
Cost
Fixed rather than per token. That inverts the economics of anything high volume and low value per item, which is where most disappointing API bills come from.
Operations
You now own uptime, memory and model updates. That is a real cost and the honest trade for the three above.
Where to go next
Prompting local models is the adjustment that matters most after the base URL. Errors is what the new failures mean. Deployment patterns is where it runs once it is more than your laptop.