Skip to content
All docs

Code

LiteLLM

Point LiteLLM at nokeep with the openai/ prefix and api_base. It works in the proxy and in the Python SDK.

Checked 29 October 2026

The proxy

config.yaml
model_list:
  - model_name: deepseek-v4.1-flash-uncensored
    litellm_params:
      model: openai/deepseek-v4.1-flash-uncensored
      api_base: https://nokeep.ai/v1
      api_key: os.environ/NOKEEP_API_KEY
    model_info:
      input_cost_per_token: 0.00000045
      cache_read_input_token_cost: 0.000000011
      output_cost_per_token: 0.00000175
  - model_name: glm-5.3-flash-uncensored
    litellm_params:
      model: openai/glm-5.3-flash-uncensored
      api_base: https://nokeep.ai/v1
      api_key: os.environ/NOKEEP_API_KEY
    model_info:
      input_cost_per_token: 0.0000002
      cache_read_input_token_cost: 0.00000004
      output_cost_per_token: 0.00000065
Shell
pip install 'litellm[proxy]'
export NOKEEP_API_KEY="sk-nokeep-test"  # your own key once it connects
litellm --config config.yaml

Your apps then call the proxy (by default http://0.0.0.0:4000) with the model_name, and the proxy calls nokeep. model_info gives LiteLLM nokeep’s prices, per token, so its spend tracking matches your bill. Without it, LiteLLM has no price for nokeep’s models and can’t count what the calls cost.

The Python SDK

Shell
pip install litellm
export NOKEEP_API_KEY="sk-nokeep-test"  # your own key once it connects
Python
import os
import litellm

reply = litellm.completion(
    model="openai/deepseek-v4.1-flash-uncensored",
    api_base="https://nokeep.ai/v1",
    api_key=os.environ["NOKEEP_API_KEY"],
    messages=[{"role": "user", "content": "Name three good names for a tavern."}],
)
print(reply.choices[0].message.content)
print(reply.usage)

A native nokeep provider has been proposed to LiteLLM. Until it is released, the openai/ prefix with api_base is the way in; it sends the request as it is.

Stream

Python
import os
import litellm

stream = litellm.completion(
    model="openai/deepseek-v4.1-flash-uncensored",
    api_base="https://nokeep.ai/v1",
    api_key=os.environ["NOKEEP_API_KEY"],
    messages=[{"role": "user", "content": "Tell me a story in three lines."}],
    stream=True,
    stream_options={"include_usage": True},
)
for chunk in stream:
    if chunk.choices:
        print(chunk.choices[0].delta.content or "", end="", flush=True)
    if getattr(chunk, "usage", None):
        print("\n", chunk.usage)

Tools, thinking and samplers

Python
import os
import litellm

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get the weather in a city",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"],
        },
    },
}]

reply = litellm.completion(
    model="openai/deepseek-v4.1-flash-uncensored",
    api_base="https://nokeep.ai/v1",
    api_key=os.environ["NOKEEP_API_KEY"],
    messages=[{"role": "user", "content": "What's the weather in Lisbon?"}],
    tools=tools,
    reasoning_effort="high",
    max_tokens=4000,
    extra_body={"min_p": 0.05},  # fields LiteLLM has no argument for
)
print(reply.choices[0].message.tool_calls)

With the openai/ prefix, reasoning_effort and tools pass through unchanged. In the proxy, set fixed fields per model under litellm_params (for example reasoning_effort: high), or let each caller send their own. See Tool calls and Thinking.

Gotchas

  • `reasoning_effort` takes only the model’s own values. deepseek-v4.1-flash-uncensored takes none, low, high, max; glm-5.3-flash-uncensored takes low, high. Other apps’ minimal, medium and xhigh run at the model’s nearest level (medium as high, xhigh as max where the model has it); any other value gets 400 invalid_reasoning_effort. See Thinking.
  • GLM picks its own tools. glm-5.3-flash-uncensored takes tool_choice auto or none only. Forcing a tool (required, or naming a function) gets 400 unsupported_tool_choice. Use DeepSeek when you need to force one.
  • Fields a model can’t take are dropped, not refused. The call still answers, and the x-nokeep-ignored response header names what was left out. GLM keeps only tools, tool_choice and reasoning_effort, so its temperature and response_format are dropped. See which fields each model takes.
  • Content parts are text and pictures only. image_url parts work on deepseek-v4.1-flash-uncensored; GLM reads text alone. Audio and file parts (a PDF) get 400 unsupported_input.
  • `n` must be 1. Ask for several replies with several calls.

drop_params: true makes LiteLLM drop the fields it believes a provider can’t take before the call. nokeep already drops what a model can’t take and names it in x-nokeep-ignored, so you don’t need it.

Questions

Do I put my nokeep key in config.yaml?

No. Write api_key: os.environ/NOKEEP_API_KEY and LiteLLM reads the key from the environment when it starts.

Why does LiteLLM show no cost for nokeep calls?

It doesn’t know nokeep’s prices. Add the model_info block from the config above; the prices in it come from the same table as your bill. The bill itself rounds each call up to a whole credit.