Get your key

LLM with no restrictions: integrate it with the OpenAI SDK

Integrating an LLM with no restrictions takes three changes to a standard OpenAI client: the base URL, the key and the model name. The rest of this walkthrough covers system prompts, streaming, tools and the error handling a production app needs.

Last updated

A glass pipeline carrying data cubes from a code console through a gateway with a traffic light and gauge

The three changes

If your code already talks to an OpenAI-style API, you are almost done. Swap these three values:

  1. Base URL: https://api.llmwithoutrestrictions.com/v1
  2. Key: sent as Authorization: Bearer <key>. The SDK does this for you. Get a key on the API key page.
  3. Model: uncensored

Python:

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.llmwithoutrestrictions.com/v1",
    api_key=os.environ["API_KEY"],
)

r = client.chat.completions.create(
    model="uncensored",
    messages=[
        {"role": "system", "content": "You are a concise assistant."},
        {"role": "user", "content": "List three uses for a tide table."},
    ],
)
print(r.choices[0].message.content)
print(r.usage)

Node:

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.llmwithoutrestrictions.com/v1",
  apiKey: process.env.API_KEY,
});

const r = await client.chat.completions.create({
  model: "uncensored",
  messages: [{ role: "user", content: "List three uses for a tide table." }],
});
console.log(r.choices[0].message.content);

The API also accepts POST /v1/responses and lists the model on GET /v1/models, in case your framework calls either.

Writing the system prompt

With a model tuned not to refuse lawful requests, the system prompt does a different job than it does on a filtered API. You are no longer spending words talking the model into helping. You use them to define the product. Good system prompts for this kind of model share a few habits:

A model without refusals does not remove your responsibility for the application. You still decide who can use it, what your own terms are, and what your app should not do. The one limit the service itself enforces is no sexual content involving minors, so build any age gating and moderation your product needs on your side.

Streaming

Set stream: true to receive tokens over server-sent events, with usage reported at the end. In Python:

import os
from openai import OpenAI

client = OpenAI(base_url="https://api.llmwithoutrestrictions.com/v1", api_key=os.environ["API_KEY"])

stream = client.chat.completions.create(
    model="uncensored",
    messages=[{"role": "user", "content": "Describe a lighthouse at dusk."}],
    stream=True,
    stream_options={"include_usage": True},
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    if chunk.usage:
        print("\n", chunk.usage)

One detail matters for reliability: a streamed request occupies its concurrency slot until the stream ends. If a user closes the tab and your server keeps the connection open, that slot stays taken. Close the stream when the client disconnects.

Sampling settings worth knowing

These parameters are passed through to the model: temperature, top_p, stop, seed and the frequency and presence penalties. Three habits pay off. Change one setting at a time, so you know what caused a difference. Use seed with a fixed prompt when you compare prompt versions, so a change in wording is not hidden by random variation. And add a presence or frequency penalty when long creative replies start repeating phrases. Leave max_tokens out when you want the model to finish naturally; the completion may use whatever remains of the 100,000-token window.

Tools and JSON mode

Tool calling follows the OpenAI format: pass tools and tool_choice, read tool_calls from the reply, run the function yourself and send the result back as a message with role: "tool". For structured output, add response_format={"type": "json_object"} and say in the prompt that the answer must be JSON.

import json, os
from openai import OpenAI

client = OpenAI(base_url="https://api.llmwithoutrestrictions.com/v1", api_key=os.environ["API_KEY"])

r = client.chat.completions.create(
    model="uncensored",
    response_format={"type": "json_object"},
    messages=[
        {"role": "system", "content": "Reply with a JSON object only."},
        {"role": "user", "content": "Give name, mood and tagline for a fictional tavern."},
    ],
)
data = json.loads(r.choices[0].message.content)
print(data)

Always wrap json.loads in a try block. JSON mode makes valid JSON likely, and your code should still survive the rare reply that is cut off or malformed.

Error handling that holds up

The error you will meet in practice is HTTP 429, and it has three causes you can tell apart:

A wrapper that honours Retry-After and falls back to exponential backoff, plus a semaphore that keeps you under the concurrency limit:

import os, time, threading
from openai import OpenAI, RateLimitError

client = OpenAI(
    base_url="https://api.llmwithoutrestrictions.com/v1",
    api_key=os.environ["API_KEY"],
    max_retries=0,
)
slots = threading.Semaphore(8)  # use 2 on a trial key

def ask(messages, tries=5):
    for attempt in range(tries):
        with slots:
            try:
                r = client.chat.completions.create(model="uncensored", messages=messages)
                return r.choices[0].message.content
            except RateLimitError as e:
                wait = float(e.response.headers.get("Retry-After", 2 ** attempt))
        time.sleep(wait)
    raise RuntimeError("still rate limited after retries")

Notice that the sleep happens outside the semaphore, so a waiting thread does not block a slot. Failed or refused requests are not charged, so retrying costs nothing extra. The response headers X-RateLimit-Limit-Requests and X-RateLimit-Limit-Concurrency tell you the limits that apply to your key, and X-Request-Id is worth logging for any report to support.

Testing the integration before launch

Most integration bugs show up under a few simple tests. Run them with a trial key, whose limit of 2 concurrent requests exposes problems early:

  1. Fire three requests at once and confirm the third returns a 429 with code concurrency, and that your wrapper waits and retries instead of crashing.
  2. Start a stream, then close the client halfway. Check that your server closes the upstream stream too, so the slot is freed.
  3. Feed a long conversation history and confirm your app trims or summarizes it long before it nears the 100,000-token window.
  4. Return a deliberately broken JSON string from a stub and make sure your parsing code handles it.
  5. Log X-Request-Id for every call, so a single bad reply can be traced later.

Ten minutes on this list catches the failures that otherwise appear on launch day, when several users send messages at the same moment.

Before you ship

Check the body size (8 MB maximum), set a sensible max_tokens if you want to cap cost, and watch X-Balance-USD so a low balance triggers an alert rather than an outage. You can also poll GET /v1/balance. Cost is easy to estimate: at $0.15 per 1M input and $0.50 per 1M output tokens, a request with 3,000 input and 600 output tokens costs $0.00045 plus $0.0003, so $0.00075. The documentation has the full parameter list, and our piece on what developers need to know covers the policy questions around unfiltered models.

Common questions

Do I need a special SDK?

No. Any OpenAI SDK or client works. Change the base URL, the key and the model name to uncensored.

Why do I get a 429 when I send only a few requests?

Check the error code. concurrency means too many requests at once, often open streams. rate_limited means too many per minute. A Retry-After: 5 header means a brief overload.

Are failed requests billed?

No. Failed or refused requests are not charged.

Does the system prompt still matter?

Yes. It sets role, format and persona. It no longer has to coax the model into answering lawful requests.

Get your API key

Sign up, copy the key, update the base URL. That is all.

Get your key