DeepSeek V4 API Python: Contoh Kode Minimal dengan Streaming

DeepSeek V4 API Python: Contoh Kode Minimal dengan Streaming

Halo semuanya! Dora di sini. Semuanya dimulai dengan iritasi kecil: saya terus-menerus menyalin boilerplate chat-completion yang sama antar proyek, menukar URL dasar dan nama model seperti label di toples. Bukan pekerjaan yang sulit, hanya yang membuat hari Anda terasa berat. Saya sudah melihat DeepSeek muncul cukup sering untuk menjadi penasaran, jadi saya menyisihkan beberapa pagi di akhir Januari 2026 untuk menghubungkan API “V4” mereka ke tumpukan Python saya dan melihat bagaimana rasanya dalam penggunaan nyata.

Saya tidak mengejar benchmark. Saya ingin tahu: apakah klien tetap tidak mengganggu saya, bisakah saya melakukan streaming dengan andal, dan apakah kesalahan gagal dengan cara yang mudah untuk dipikirkan? Berikut adalah apa yang saya coba, apa yang membuat saya tersesat, dan apa yang bekerja dengan tenang. Mari kita mulai!

Pengaturan Lingkungan

Dependensi

Saya membuat pengaturannya sederhana di macOS dengan Python 3.11. Anda bisa melakukan ini dengan pustaka standar, tetapi tiga paket kecil membuat hidup lebih mudah:

  • requests (HTTP yang mudah: cukup untuk sebagian besar kasus)
  • httpx (async dan timeout yang berperilaku baik)
  • python-dotenv (jadi saya tidak menempel kunci di sekitar) Jika Anda berencana melakukan streaming dengan Server-Sent Events, Anda dapat menggunakan requests dan mengurai baris sendiri (apa yang saya lakukan), atau bawa pembantu seperti sseclient-py. Saya tetap dengan requests, bagian yang lebih sedikit.

Instal

pip install requests httpx python-dotenv

Saya juga membuat lingkungan virtual minimal per proyek. Ini adalah saran yang membosankan, tetapi ini menyelamatkan Anda dari drift dependensi ketika Anda meninjau kembali ini dalam tiga bulan.

Konfigurasi Kunci API

Saya menyimpan kunci dalam variabel lingkungan. Tidak ada yang rumit:

# .env
DEEPSEEK_API_KEY=your_key_here

Kemudian di Python:

from dotenv import load_dotenv
import os

load_dotenv()

API_KEY = os.getenv("DEEPSEEK_API_KEY")

if not API_KEY:
    raise RuntimeError("Missing DEEPSEEK_API_KEY")

Dua catatan kecil dari pengaturan:

  • URL dasar dan nama model berubah lebih sering dari yang Anda pikirkan. Saya memeriksa dokumen API DeepSeek resmi sebelum setiap jalankan untuk mengkonfirmasi jalur dan model yang tersedia.
  • Saya menjaga timeout tetap eksplisit. Ini adalah kebiasaan yang terbayar setelah Anda mencapai batas laju atau kebisingan jaringan.

Permintaan Chat Dasar

Model mental sudah familiar jika Anda telah menggunakan chat-completions di tempat lain. DeepSeek mengekspos titik akhir chat dengan messages=[{"role": "...", "content": "..."}]. Itu membantu karena saya tidak harus membingkai ulang prompt saya.
Berikut adalah permintaan minimal yang saya gunakan dengan requests. Nama model bervariasi menurut akun dan wilayah, selama pengujian saya saya melihat referensi seperti deepseek-chat dan deepseek-reasoner. Jika dokumen Anda menyebutkan string model “V4”, gunakan itu. Jika tidak, pilih model chat tujuan umum terdekat yang tercantum di konsol Anda.

import os
import requests

API_KEY = os.environ["DEEPSEEK_API_KEY"]
BASE_URL = "https://api.deepseek.com/v1/chat/completions"

payload = {
    "model": "deepseek-chat", # check docs/console for the exact model
    "messages": [
        {"role": "system", "content": "You are a concise assistant."},
        {"role": "user", "content": "Give me two bullet points on the value of clear commit messages."}
    ],
    "temperature": 0.3,
    "max_tokens": 200
}

resp = requests.post(
    BASE_URL,
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json"
    },
    json=payload,
    timeout=30
)

resp.raise_for_status()

data = resp.json()
content = data["choices"][0]["message"]["content"]
print(content)

Catatan Lapangan

  • Jalankan pertama kali tidak berkesan (lega). Strukturnya cocok dengan yang saya harapkan, yang membuat migrasi pustaka prompt kecil menjadi cepat.
  • Saya menjaga suhu rendah untuk jawaban yang dapat diulang. Itu terdengar jelas, tetapi saya masih lupa ketika saya memecahkan masalah.
  • Jika Anda membutuhkan jalankan deterministik, juga pin top_p dan seed jika API mendukungnya. Ketika dokumen diam, saya anggap non-deterministik.

Jika Anda membandingkan penyedia, keuntungan di sini adalah gesekan rendah. Kelemahannya adalah perbedaan tersembunyi di tepi, muatan kesalahan, akuntansi token, dan bentuk streaming. Tepi-tepi itu adalah tempat integrasi Anda merasa kokoh atau mengganggu.

Contoh Pembuatan Kode

Saya tidak meminta model untuk menulis modul penuh. Itu menjadi pekerjaan pembersihan. Tetapi untuk pembantu kecil, seperti “mengurai format cap waktu ini” atau “membuat draft SQL dengan placeholder,” ini berguna.
Saya menggunakan prompt yang sempit, kontrak yang jelas, dan batas keluaran kecil. Itu membuat model tidak berkeliaran dan membuat diff mudah untuk ditinjau.

import requests, os

API_KEY = os.environ["DEEPSEEK_API_KEY"]
BASE_URL = "https://api.deepseek.com/v1/chat/completions"

messages = [
    {"role": "system", "content": (
        "You generate small, safe Python helpers. "
        "Return only code inside one block."
    )},
    {"role": "user", "content": (
        "Write a Python function `parse_yyyymmdd` that takes a string like '2026-01-31' "
        "and returns a datetime.date. If invalid, return None. No external deps."
    )}
]

resp = requests.post(
    BASE_URL,
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json"
    },
    json={
        "model": "deepseek-chat", # or your V4-capable model
        "messages": messages,
        "temperature": 0,
        "max_tokens": 250
    },
    timeout=30
)

resp.raise_for_status()
code = resp.json()["choices"][0]["message"]["content"]
print(code)

Apa yang membantu dalam praktik

  • Saya selalu memberitahunya untuk mengembalikan hanya kode. Jika saya melewati itu, saya mendapatkan kalimat pembungkus yang tidak saya butuhkan.
  • Suhu 0 mengurangi suntingan yang berubah-ubah.
  • Saya membaca logika pula. Dalam jalankan saya menangani ValueError, tetapi saya masih menambahkan tes ekstra untuk spasi. Dua menit ekstra sekarang menghemat jam kemudian.

Ini tidak menghemat waktu pada upaya pertama. Setelah tiga atau empat pembantu kecil, saya perhatikan itu mengurangi upaya mental: lebih sedikit saklar tab, lebih sedikit momen “apa kode strptime yang tepat lagi?”. Itu cukup untuk saya.

Respons Streaming

Saya menyukai streaming untuk prompt apa pun yang bisa tumbuh. Ini memungkinkan saya keluar awal jika jawaban melayang, dan membuat respons panjang terasa kurang berat.
Streaming DeepSeek menggunakan pola biasa dalam pengujian saya: atur stream=true dan baca baris data hingga [DONE]. Saya tidak perlu klien khusus, requests dengan iter_lines baik-baik saja.

import os, json, requests

API_KEY = os.environ["DEEPSEEK_API_KEY"]
BASE_URL = "https://api.deepseek.com/v1/chat/completions"

payload = {
    "model": "deepseek-chat",
    "messages": [
        {"role": "system", "content": "Be brief."},
        {"role": "user", "content": "Summarize this: Streaming keeps the UI responsive and lets me stop early."}
    ],
    "stream": True,
    "temperature": 0.2,
}

with requests.post(
    BASE_URL,
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json"
    },
    json=payload,
    stream=True,
    timeout=60
) as r:
    r.raise_for_status()
    for line in r.iter_lines(decode_unicode=True):
        if not line:
            continue
        if line.startswith("data: "):
            chunk = line[len("data: "):]
            if chunk == "[DONE]":
                break
            try:
                obj = json.loads(chunk)
                delta = obj["choices"][0]["delta"].get("content", "")
                if delta:
                    print(delta, end="", flush=True)
            except json.JSONDecodeError:
                # I keep a small log when this happens: usually network blips
                pass

print()

Dua perilaku kecil yang saya sukai:

  • Token awal tiba dengan cepat (satu atau dua detik pada koneksi bersih). Bukan ilmiah, hanya cukup untuk terasa snappy ketika saya menghubungkannya ke alat CLI.
  • Penanda [DONE] muncul dengan andal. Ini terdengar sepele sampai tidak, terminal yang hilang membuat UI menggantung.

Jika Anda perlu melakukan streaming ke aplikasi web, saya akan menempatkan lapisan server tipis di antara untuk menormalisasi acara. Ini adalah satu langkah ekstra, tetapi ini menjaga frontend Anda tetap sederhana.

Server-Sent Events

Di bawah tenda, Anda secara efektif membaca Server-Sent Events. Jika Anda lebih suka pembantu, sseclient-py bekerja, tetapi menggulung milik Anda di sini baik-baik saja asalkan Anda menjaga garis parsial dan timeout. Halaman dokumen tentang streaming di dokumen API DeepSeek cukup untuk menjalankan ini tanpa kejutan.

Penanganan Kesalahan

Sebagian besar kesalahan saya dapat diprediksi: kunci yang hilang, nama model yang buruk, atau timeout ketika saya mengatur kecepatan jaringan saya untuk mensimulasikan Wi‑Fi perjalanan.
Pola kecil yang saya gunakan kembali:

import httpx, time, os

API_KEY = os.environ["DEEPSEEK_API_KEY"]
BASE_URL = "https://api.deepseek.com/v1/chat/completions"

RETRIABLE = {408, 409, 425, 429, 500, 502, 503, 504}

async def chat_once(client, messages):
    resp = await client.post(
        BASE_URL,
        headers={"Authorization": f"Bearer {API_KEY}"},
        json={
            "model": "deepseek-chat",
            "messages": messages,
            "temperature": 0.2,
            "max_tokens": 300,
        },
        timeout=30,
    )
    if resp.status_code == 401:
        raise RuntimeError("Unauthorized. Check DEEPSEEK_API_KEY and account access.")
    if resp.status_code == 404:
        raise RuntimeError("Endpoint or model not found. Confirm model name in console/docs.")
    if resp.status_code in RETRIABLE:
        raise RuntimeError(f"Retryable status: {resp.status_code}")
    resp.raise_for_status()
    return resp.json()

async def chat_with_retries(messages, attempts=4):
    backoff = 0.5
    async with httpx.AsyncClient() as client:
        for i in range(attempts):
            try:
                return await chat_once(client, messages)
            except RuntimeError as e:
                msg = str(e)
                if "Retryable status" in msg and i < attempts - 1:
                    time.sleep(backoff)
                    backoff *= 2
                    continue
                raise

Beberapa catatan praktis:

  • Batas laju: Saya melihat 429 ketika saya meluncurkan tes paralel. Backoff eksponensial membantu, tetapi saya juga menambahkan jitter kecil (acak 50–150ms) untuk menghindari kawanan menggelegar.
  • Timeout hygiene: Saya menetapkan timeout koneksi/baca yang lebih pendek untuk pemeriksaan cepat (5–10 detik) dan yang lebih lama untuk prompt besar. Timeout tidak seharusnya semua 30 detik secara default: ia menyembunyikan masalah.
  • Muatan kesalahan: Ketika terjadi kesalahan, badan JSON menyertakan pesan yang saya bisa permukaan ke log. Saya masih membungkusnya dalam pengecualian saya sendiri jadi saya mengontrol apa yang mencapai UI.

Jika basis kode Anda sudah berbicara skema gaya OpenAI, ini dapat dikelola: bentuk pesan yang sama, tepi yang sedikit berbeda. Hal utama adalah ketat tentang nama model dan untuk mencatat badan respons penuh pada non-2xx jadi Anda tidak menebak.
Dokumentasi-wise, saya mengandalkan dokumen API DeepSeek resmi untuk nama parameter dan bentuk streaming. Setiap kali penyedia menggunakan titik akhir yang familiar, ini menggoda untuk menganggap paritas. Saya telah belajar untuk memeriksa dokumen terlebih dahulu dan menyalin kurang antara klien daripada yang saya pikir saya bisa.

Siapa yang mungkin menyukai ini

  • Jika Anda memiliki pembungkus Python yang ada untuk penyelesaian chat, jalur migrasi itu lembut.
  • Jika Anda peduli tentang streaming dan pengulangan sederhana, ia berperilaku dapat diprediksi.
  • Jika Anda memerlukan tooling yang sangat spesifik (skema function-calling, token penalaran, atau pekerjaan batch), Anda akan ingin membaca dokumen dengan cermat dan prototipe dengan satu tugas yang sempit sebelum Anda berkomitmen.

Saya tidak mencoba mengorkestra agen multi-langkah yang panjang di sini. Saya fokus pada prompt kecil, penggunaan sehari-hari, yang mengurangi gesekan. Itulah di mana API DeepSeek V4 dengan Python terasa cukup stabil untuk disimpan.