DeepSeek exposes an OpenAI-compatible API, so moving from OpenAI is one of the easiest migrations there is: point the OpenAI SDK at DeepSeek’s base URL, swap the key, and change the model. No request/response remapping.
API concept mapping
| Concept | OpenAI | DeepSeek |
|---|---|---|
| SDK | openai | openai (same) with base_url |
| Base URL | default | https://api.deepseek.com |
| Auth | OPENAI_API_KEY | DEEPSEEK_API_KEY |
| Endpoint | /chat/completions | /chat/completions (same) |
| Model | gpt-5.4 / mini | deepseek-chat (non-thinking), deepseek-reasoner (thinking) |
| Response | choices[0].message.content | choices[0].message.content (same) |
| Tools / streaming | standard | standard (compatible) |
The whole migration
Keep the OpenAI SDK. Set base_url="https://api.deepseek.com", use your DeepSeek key, and set the model to deepseek-chat or deepseek-reasoner. Done.
Before / after
from openai import OpenAI
client = OpenAI() # OPENAI_API_KEY
resp = client.chat.completions.create(
model="gpt-5.4",
messages=[
{"role": "system", "content": "You are concise."},
{"role": "user", "content": "Explain rate limits in one line."},
],
)
print(resp.choices[0].message.content) import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
resp = client.chat.completions.create(
model="deepseek-chat", # or "deepseek-reasoner" for thinking
messages=[
{"role": "system", "content": "You are concise."},
{"role": "user", "content": "Explain rate limits in one line."},
],
)
print(resp.choices[0].message.content) Gotchas
Watch for these
- Model names drift. DeepSeek has renamed model ids over time (e.g. the
deepseek-chat/deepseek-reasoneraliases map to the current V4 generation). Confirm the live id in DeepSeek’s docs before shipping. reasonerreturns reasoning content. The thinking model exposes a separate reasoning field and longer outputs — budget tokens and don’t feed reasoning back as input.- Re-tune prompts and re-run evals. Compatible API ≠ identical behavior; outputs differ from GPT models.
- Some OpenAI-only params (certain response_format / tool edge cases) may differ — test tool calling specifically.
What to do next
- Centralize your model id and base URL in config so the swap is one line.
- Shadow-run DeepSeek on a slice of traffic and diff outputs.
- Price it first — DeepSeek is often the cheapest option; confirm with the cost calculator.
- Going back later? See DeepSeek → OpenAI.
Frequently asked questions
Is DeepSeek really OpenAI-compatible?
Yes — it implements the OpenAI chat-completions API, so the official OpenAI SDKs work by setting
base_url to DeepSeek and using a DeepSeek key. Most apps migrate with config changes only.Which DeepSeek model replaces GPT-5.4?
Use
deepseek-chat for standard (non-thinking) responses and deepseek-reasoner for chain-of-thought tasks. Verify the current model ids in DeepSeek's docs, as they're periodically renamed.Will my tool calling and streaming keep working?
Generally yes — both are supported through the compatible API. Still test tool/function calling end to end, since edge-case parameter handling can differ between providers.