API docs
Guides

Use the OpenAI SDK

Point any OpenAI client at Nucleus and chat with your fine-tuned model without changing your code.

Nucleus speaks the OpenAI wire format at https://api.nucleus-ai.io/v1. Point any OpenAI client at that base URL with your Nucleus API key and change nothing else: the official SDKs, and every framework or proxy built on them, work as they are. Requests to these routes need a key with the infer scope.

This guide covers SDK setup, model selection, the two completion routes, streaming and the reasoning controls. For the full parameter tables see the OpenAI-compatible reference.

Point the SDK at Nucleus

Pass the Nucleus base URL and your key when you construct the client. Everything else about your code stays the same.

from openai import OpenAI

client = OpenAI(
    base_url='https://api.nucleus-ai.io/v1',
    api_key=API_KEY,  # nk_live_...
)

Pick a model

The model parameter accepts either a base model ID, such as Qwen/Qwen3-8B, or the nucleus:// path of your fine-tuned sampler weights:

nucleus://run_3Bz:train:0/sampler_weights/000240

A finished fine-tuning job reports this path as result_model, so serving your own model is a copy-paste away. See Serving for how weights become servable.

Chat completions or completions

There are two routes, and for almost everything you want chat completions. It takes a messages array and renders it server-side with the model's chat template, so you never touch tokens or templates. It is the easy on-ramp.

Completions is raw text continuation: your prompt string goes to the model exactly as written, with no chat template applied. Reach for it when you want the model to continue text rather than hold a conversation.

resp = client.completions.create(
    model='Qwen/Qwen3-8B',
    prompt='The capital of France is',
    max_tokens=8,
)
print(resp.choices[0].text)  # " Paris."

Both routes support max_tokens, temperature, top_p and stream.

Streaming

Set stream to true and tokens arrive as server-sent events. The SDKs turn the stream into an iterator of deltas, exactly as they do against OpenAI.

stream = client.chat.completions.create(
    model='Qwen/Qwen3-8B',
    messages=[{'role': 'user', 'content': 'Write a haiku about GPUs.'}],
    stream=True,
)
for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.content:
        print(delta.content, end='', flush=True)

Reasoning controls

Chat completions separates the model's reasoning from its answer by default: separate_reasoning defaults to true, and the reasoning arrives as reasoning_content on the message while content carries only the final answer.

{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "reasoning_content": "17 × 23 = 391",
        "content": "391"
      },
      "finish_reason": "stop"
    }
  ]
}

Set separate_reasoning to false to keep the reasoning inline in content.

reasoning_effort controls how hard the model thinks before answering. It accepts the named levels from none up to xhigh, or a float between 0.0 and 0.99 for finer control. none skips reasoning entirely, which is the cheapest and fastest setting for simple requests.

resp = client.chat.completions.create(
    model='Qwen/Qwen3-8B',
    messages=[{'role': 'user', 'content': 'What is 17 x 23?'}],
    reasoning_effort='high',
)
print(resp.choices[0].message.reasoning_content)
print(resp.choices[0].message.content)

Chat with your fine-tuned model

End to end: take the result_model path from your finished job, point the SDK at Nucleus and hold a conversation with your own model.

from openai import OpenAI

client = OpenAI(
    base_url='https://api.nucleus-ai.io/v1',
    api_key=API_KEY,
)

MODEL = 'nucleus://run_3Bz:train:0/sampler_weights/000240'  # result_model from your job

history = [
    {'role': 'system', 'content': 'You are a support assistant for Acme.'},
    {'role': 'user', 'content': 'How do I reset my API key?'},
]

resp = client.chat.completions.create(
    model=MODEL,
    messages=history,
    max_tokens=512,
    temperature=0.2,
)
answer = resp.choices[0].message.content
print(answer)

history.append({'role': 'assistant', 'content': answer})
history.append({'role': 'user', 'content': 'And if I have lost the old one?'})

resp = client.chat.completions.create(model=MODEL, messages=history, max_tokens=512)
print(resp.choices[0].message.content)

If you use the Anthropic SDK or Claude Code instead, see Use the Anthropic SDK and Claude Code.

Use the OpenAI SDK | Nucleus AI API