needle-openai
An OpenAI-compatible HTTP API in front of Needle 2 — Cactus Compute's 45M-parameter model for tool calling, device use and structured extraction. Point any OpenAI client at it and get function calls back from a 14MB model that runs on CPU in ~100MB of RAM.
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8000/v1", api_key="not-needed")
response = client.chat.completions.create(
model="needle-2",
messages=[{"role": "user", "content": "what's it like in Lagos right now?"}],
tools=[
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}
],
)
print(response.choices[0].message.tool_calls[0].function)
# Function(arguments='{"city": "Lagos"}', name='get_weather')
[!IMPORTANT] Needle 2 is not a chat model. It emits tool calls or nothing at all — it has no free-form generation head. Read the fidelity notes before building on this; they list every place the OpenAI mapping is lossy and the two failure modes worth guarding against.
Quickstart
docker run -d -p 8000:8000 -v needle-cache:/cache ghcr.io/sirmmo/needle-openai:latest
curl -s localhost:8000/health
Or from a clone:
docker compose up -d
Or as a Python package (needs Python ≥3.10):
pip install needle-openai
pip install --no-deps cactus-needle==2.0.3 # see "Why --no-deps" in the docs
needle-openai --port 8000
First start downloads the native engine and weights from HuggingFace into
/cache — a few tens of MB, ~6s on a warm connection, cached across restarts.
Runnable examples: examples/openai_client.py and
examples/curl.sh.
What works
| Tool calling | tools / functions, parallel calls, the full agent loop. |
| Structured extraction | response_format with a JSON Schema → typed objects. |
| Streaming | SSE chunks, synthesized from the finished result. |
| Confidence gating | Calibrated 0–1 score on every response via x_needle. |
| Tuned weights | Serve a fine-tuned .cact with NEEDLE_WEIGHTS. |
| Auth | Optional bearer token; /health stays open. |
Endpoints
| Endpoint | Notes |
|---|---|
POST /v1/chat/completions |
Tools, streaming, structured output. |
POST /v1/completions |
Legacy text completion. |
GET /v1/models, GET /v1/models/{id} |
Model discovery. |
POST /v1/needle/extract |
Native extraction: text + JSON Schema → object. |
POST /v1/needle/complete |
Passthrough returning the engine's raw response. |
GET /health |
Readiness, queue depth, token-count mode. |
Full details in the API reference.
Key things to know
A short version of the fidelity notes:
- No free-form text. When no tool is called, the model's
reasoningtrace is returned ascontent. Asked"hello, who are you?"it replies "No tool available to query location or contact info." - Deterministic.
temperature,top_p,seedandnare accepted, ignored, and reported inx_needle.warnings. - One request at a time per container. The native engine is a single global session that segfaults under concurrent use, so everything serializes through one thread. 24 concurrent requests complete correctly in ~4.2s; scale by running more containers.
- Long inputs truncate silently and return a confident-looking wrong answer
with
confidence: 0.0. Gate onconfidence. response_format: {"type": "json_object"}returns 400 — Needle needs an explicit schema.
Development
pip install -r requirements.txt pytest httpx ruff
pytest # 57 tests, ~1s, no model download (fake engine)
docker compose up -d # live suite against the real engine
NEEDLE_TEST_BASE_URL=http://127.0.0.1:8000 pytest -m live
See Development and CONTRIBUTING.md.
License
MIT — see LICENSE. Needle 2 and its weights are licensed by Cactus Compute.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file needle_openai-0.1.1.tar.gz.
File metadata
- Download URL: needle_openai-0.1.1.tar.gz
- Upload date:
- Size: 30.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb05784380564218a5e6b5e11b1fb0c651b522c1d0743c6a12edb3189c95cae0
|
|
| MD5 |
d395334f92c026a566201732ff5fe1d4
|
|
| BLAKE2b-256 |
8bb5657607a8e0de3ab2e2b36ee59042ef56ea339c2963d9f963d94cee242502
|
Provenance
The following attestation bundles were made for needle_openai-0.1.1.tar.gz:
Publisher:
release.yml on sirmmo/needle-openai
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
needle_openai-0.1.1.tar.gz -
Subject digest:
cb05784380564218a5e6b5e11b1fb0c651b522c1d0743c6a12edb3189c95cae0 - Sigstore transparency entry: 2467321892
- Sigstore integration time:
-
Permalink:
sirmmo/needle-openai@8e843d4f742316295eb7babe4165b96150521aad -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/sirmmo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8e843d4f742316295eb7babe4165b96150521aad -
Trigger Event:
push
-
Statement type:
File details
Details for the file needle_openai-0.1.1-py3-none-any.whl.
File metadata
- Download URL: needle_openai-0.1.1-py3-none-any.whl
- Upload date:
- Size: 25.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79eff434e7850b772423bc90c26d4065910bea2382089d466b87020a56e08971
|
|
| MD5 |
97ac5a773d9de937efb7335ec022b8ac
|
|
| BLAKE2b-256 |
960620c7956c03c5c32445feace007fa56a6060ecb6f2334285e6d44729fd9bd
|
Provenance
The following attestation bundles were made for needle_openai-0.1.1-py3-none-any.whl:
Publisher:
release.yml on sirmmo/needle-openai
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
needle_openai-0.1.1-py3-none-any.whl -
Subject digest:
79eff434e7850b772423bc90c26d4065910bea2382089d466b87020a56e08971 - Sigstore transparency entry: 2467321922
- Sigstore integration time:
-
Permalink:
sirmmo/needle-openai@8e843d4f742316295eb7babe4165b96150521aad -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/sirmmo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8e843d4f742316295eb7babe4165b96150521aad -
Trigger Event:
push
-
Statement type: