繁中 ▾
取得 API 金鑰

DeepSeek API Python 範例:聊天、串流輸出、工具

DeepSeek API Python 設定僅需官方 openai 套件、Base URL、金鑰與模型 ID。以下範例涵蓋一般請求、串流輸出、JSON 模式、函式呼叫與重試,皆針對 OpenAI 相容的端點。

更新於

終端機面板串流發光資料 token 至伺服器區塊,描繪 Python API 呼叫

重點摘要

  • 安裝 openai,然後將 base_url 設為 https://api.deepseekapi.top/v1,並將模型設為 uncensored。
  • 串流輸出、JSON 模式和函式呼叫透過標準 SDK 參數運作。
  • 讀取 Retry-After 標頭並重試,以處理 HTTP 429。
  • 價格為每 1M 輸入 token $0.15,每 1M 輸出 token $0.50。

安裝並發送第一個請求

此服務並非官方的 DeepSeek API。它是一個託管的 OpenAI 相容端點,運行單一開放權重模型,ID 為 uncensored,由獨立供應商營運。由於它遵循 OpenAI 格式,標準 Python SDK 僅需修改 URL 和金鑰即可運作。

pip install openai

從 API 金鑰頁面取得金鑰。註冊後,你可以按一下即可領取 $0.50 的免費試用額度,無需信用卡,有效期 7 天。將金鑰儲存在環境變數中,而非原始碼檔案中:

export API_KEY="YOUR_KEY"
import os
from openai import OpenAI

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

resp = client.chat.completions.create(
    model="uncensored",
    messages=[
        {"role": "system", "content": "You are a concise assistant."},
        {"role": "user", "content": "Explain list comprehensions in two sentences."},
    ],
    temperature=0.7,
)

print(resp.choices[0].message.content)
print(resp.usage.prompt_tokens, resp.usage.completion_tokens)

這兩個用量數字是你計費的依據。將它們乘以價格即可得知任何呼叫的成本:輸入 token 數乘以 $0.15,輸出 token 數乘以 $0.50,各除以 1,000,000。

使用非同步客戶端

對於網頁伺服器及處理大量使用者的應用,請使用非同步客戶端。它擁有與同步客戶端相同的參數,在大多數程式碼中只需進行替換即可。

import asyncio
import os
from openai import AsyncOpenAI

client = AsyncOpenAI(
    base_url="https://api.deepseekapi.top/v1",
    api_key=os.environ["API_KEY"],
)

sem = asyncio.Semaphore(8)

async def ask(prompt):
    async with sem:
        r = await client.chat.completions.create(
            model="uncensored",
            messages=[{"role": "user", "content": prompt}],
        )
        return r.choices[0].message.content

async def main():
    prompts = ["Define idempotent.", "Define monotonic.", "Define pure function."]
    answers = await asyncio.gather(*(ask(p) for p in prompts))
    for a in answers:
        print(a)

asyncio.run(main())

訊號量設為 8,因為這是完整金鑰的並行請求限制。對於試用金鑰,請使用 2。若無上限,任務突發將產生 concurrency 錯誤,即使每個請求本身都是有效的。

串流回應

設定 stream=True,端點會傳送伺服器傳送事件。每個區塊包含 delta.content 中的一小段文字。要求用量意味著最後一個區塊會報告 token 計數。

# client = OpenAI(base_url="https://api.deepseekapi.top/v1", ...) as above
stream = client.chat.completions.create(
    model="uncensored",
    messages=[{"role": "user", "content": "Write a haiku about debugging."}],
    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.prompt_tokens, chunk.usage.completion_tokens)

兩個細節常讓人困擾。最終的用量區塊可能擁有空的 choices 列表,因此迴圈會先檢查 chunk.choices。串流請求會保留其並行請求槽位直到串流結束,因此請乾淨地跳出迴圈並關閉你放棄的串流。完整金鑰允許 8 個並行請求;試用金鑰允許 2 個。

JSON 模式

對於程式將要解析的輸出,請使用 response_format 搭配 json_object。同時在提示詞中提及 JSON 並描述你需要的結構。模型需要該指示;僅靠旗標無法提供結構描述。

# client = OpenAI(base_url="https://api.deepseekapi.top/v1", ...) as above
import json

resp = client.chat.completions.create(
    model="uncensored",
    messages=[
        {"role": "system", "content": "Reply with JSON only: {\"title\": str, \"tags\": [str]}"},
        {"role": "user", "content": "Summarize: a guide to caching HTTP responses."},
    ],
    response_format={"type": "json_object"},
    temperature=0,
)

data = json.loads(resp.choices[0].message.content)
print(data["title"], data["tags"])

請將 try/except 包在 json.loads 周圍。若回覆因 token 限制被截斷則無法解析,因此避免對 JSON 使用過小的 max_tokens。將 temperature 設為 0 並搭配 seed 可使重跑更具可重複性,因為兩者都會被傳遞。

函式呼叫

API 接受 tools 和 tool_choice,並在助手訊息中返回 tool_calls。你需自行執行函式,並將結果以 role: "tool" 訊息傳送回去。

# client = OpenAI(base_url="https://api.deepseekapi.top/v1", ...) as above
import json

tools = [{
    "type": "function",
    "function": {
        "name": "add",
        "description": "Add two numbers.",
        "parameters": {
            "type": "object",
            "properties": {"a": {"type": "number"}, "b": {"type": "number"}},
            "required": ["a", "b"],
        },
    },
}]

messages = [{"role": "user", "content": "What is 17.5 plus 24.25?"}]
first = client.chat.completions.create(
    model="uncensored", messages=messages, tools=tools, tool_choice="auto"
)

msg = first.choices[0].message
if msg.tool_calls:
    messages.append(msg)
    for call in msg.tool_calls:
        args = json.loads(call.function.arguments)
        result = args["a"] + args["b"]
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": str(result),
        })
    final = client.chat.completions.create(
        model="uncensored", messages=messages, tools=tools
    )
    print(final.choices[0].message.content)
else:
    print(msg.content)

務必防禦性地解析 arguments。這是模型產生的 JSON 字串,可能存在格式錯誤。在執行動作前請驗證它,特別是當函式涉及檔案或資料庫時。

錯誤、限制與重試

超出限制的請求會返回 HTTP 429。錯誤程式碼會告知是哪種限制:rate_limited 代表每分鐘請求數(完整金鑰為 300,試用金鑰為 60),concurrency 代表同時請求過多。在暫時過載時,你也會收到帶有 Retry-After: 5 的 429。SDK 會引發 openai.RateLimitError。

# client = OpenAI(base_url="https://api.deepseekapi.top/v1", ...) as above
import time
import openai

def ask(prompt, tries=4):
    for attempt in range(tries):
        try:
            r = client.chat.completions.create(
                model="uncensored",
                messages=[{"role": "user", "content": prompt}],
            )
            return r.choices[0].message.content
        except openai.RateLimitError as e:
            wait = int(e.response.headers.get("Retry-After", 5))
            time.sleep(wait * (attempt + 1))
    raise RuntimeError("still rate limited")

print(ask("Name three Python web frameworks."))

如果你發送許多請求,請使用訊號量或具有 8 個工作執行緒的執行緒池來限制你自己的並行請求數,或是試用金鑰的 2 個。這可避免 concurrency 錯誤,而非透過重試來克服。

讀取標頭

每個回應都包含 X-Request-Id、X-Balance-USD、X-RateLimit-Limit-Requests 和 X-RateLimit-Limit-Concurrency。SDK 透過原始回應暴露這些標頭:

# client = OpenAI(base_url="https://api.deepseekapi.top/v1", ...) as above
raw = client.chat.completions.with_raw_response.create(
    model="uncensored",
    messages=[{"role": "user", "content": "ping"}],
)
print(raw.headers.get("X-Balance-USD"), raw.headers.get("X-Request-Id"))
completion = raw.parse()

在每次失敗時記錄請求 ID,可使支援問題更容易回答。失敗或遭拒的請求不會計費。

保持對話持續

API 是無狀態的。它不會記住先前的請求,因此多輪聊天意味著每次都要傳送整個歷史記錄。建立一個列表並將其附加:

# client = OpenAI(base_url="https://api.deepseekapi.top/v1", ...) as above
history = [{"role": "system", "content": "You are a helpful tutor."}]

def chat(user_text):
    history.append({"role": "user", "content": user_text})
    r = client.chat.completions.create(model="uncensored", messages=history)
    reply = r.choices[0].message.content
    history.append({"role": "assistant", "content": reply})
    return reply

print(chat("What is a closure?"))
print(chat("Show me one in Python."))

每個回合都會重新傳送所有內容,因此輸入 token 數會隨著回合增加。一旦列表變長,請刪除舊訊息,或要求模型摘要早期部分並取代它。雖然 100,000-token 上下文視窗空間充足,但帳單會隨著歷史記錄增長,因此修剪過的列表成本更低。

選擇採樣值

程式碼和提取請使用 temperature 0 到 0.3,一般聊天約為 0.7,小說則更高。top_p、stop、seed 以及頻率和存在懲罰都會被傳遞,因此行為與 OpenAI 文件所述一致。一次只更改一項並進行比較。

規劃成本與上下文

上下文視窗為 100,000 個 token(包含提示詞與完成內容),請求主體限制為 8 MB。完成內容可使用視窗剩餘的任何空間,max_tokens 是可選的。為批次作業設定它仍是良好的實踐。

一個實作範例:1,000 個摘要的批次,每個包含 1,500 個輸入 token 和 200 個輸出 token。

  • 輸入:1,000 × 1,500 = 1,500,000 個 token,即 1.5 × $0.15 = $0.225
  • 輸出:1,000 × 200 = 200,000 個 token,即 0.2 × $0.50 = $0.10
  • 總計:$0.325

計費方式為從預付額度按量付費,無訂閱制,且額度永不過期。儲值金額為 $20 至 $500 的整數,$50 起加贈 5%、$100 起加贈 10%、$200 起加贈 15%,可透過信用卡或加密貨幣支付。請見 定價頁面,以及 快速入門文件中的 curl 與 Node 範例。若你只需尋找金鑰,API 金鑰概覽有相關說明。

提示詞不會用於訓練。此服務僅限文字:無影像、音訊、嵌入或微調,因此請不要針對這些端點進行規劃。

問答

我需要特殊的 DeepSeek 函式庫嗎?

不需要。安裝 openai 套件,將 base_url 設為 https://api.deepseekapi.top/v1,並使用模型 ID uncensored。這不是官方的 DeepSeek API。

Python SDK 支援在此處串流輸出嗎?

是的。傳遞 stream=True,並加入包含 include_usage 的 stream_options,以便在最後一個區塊取得 token 計數。

我該如何處理 429 錯誤?

捕獲 openai.RateLimitError,讀取 Retry-After 標頭,並在重試前等待。錯誤程式碼會告知是速率限制還是並行限制。

我可以先測試再付費嗎?

是的。註冊後,在 API 金鑰頁面按一下即可獲得 $0.50 的免費試用額度,有效期 7 天,無需信用卡。

只差一張表單,即可取得金鑰

建立帳號、複製金鑰、更改基礎 URL。這就是整個設定過程。

取得 API 金鑰