第 1 课

拿到 key 跑通首个请求:curl、Python、JavaScript 与计费

认清 deepseek-flash 与 deepseek-v4-pro,创建 API key,用 curl、Python、JavaScript 各发一次请求,查模型列表与余额,并看懂报错和峰谷计费。

图文20 分钟DeepSeek 官方文档 ↗

课程目录第 1 / 3 课

学习位置仅保存在当前浏览器,有效期 180 天。

01 / 图文教材

图文教材

本课按 DeepSeek 官方 首次调用 API、模型 & 价格、错误码、Lists Models 与 Get User Balance 整理(2026-10-22 核对);报错输出为 2026-10-22 实测,SDK 版本 openai 3.36.0(Python)。 目标:拿到 API key,用 curl、Python、JavaScript 各发一次请求,查清自己能用哪些模型、还剩多少余额,并看懂计费和常见报错。

你将得到什么

  • 一个放在环境变量里的 DEEPSEEK_API_KEY
  • 一条能直接复制的 curl 请求,以及看懂响应字段的对照表
  • first_call.py 与 first_call.mjs 两个可运行脚本
  • 查模型列表、查余额的两条命令,和一张常见报错表

一、先认清现在的两个模型名

2026 年 10 月 17 日 DeepSeek 发布 V4.1-Flash-1017,官方文档同时把 Flash 的调用名统一成 deepseek-flash。按官方「模型 & 价格」页,现在 API 只有两个模型名:

调用名背后的模型版本要点
deepseek-flashDeepSeek-V4.1-Flash-1017默认首选;支持图像理解;并发上限 2500
deepseek-v4-proDeepSeek-V4-Pro-0813旗舰;不支持图像;并发上限 500

两者都是 1M 上下文、最大输出 384K,都默认开启思考模式,都支持 JSON 输出、工具调用、Anthropic 格式和 Responses API。

旧名 deepseek-v4-flash、deepseek-v4-flash-vision-exp 仍能调用,但官方已注明对应模型下线,请求实际由 V4.1-Flash-1017 处理、按 Flash 价格计费。新代码直接写 deepseek-flash。

二、创建 API key 并放进环境变量

  1. 打开 DeepSeek 开放平台 https://platform.deepseek.com/api_keys ,登录后点「创建 API key」,复制保存(只显示一次)。
  2. 在 https://platform.deepseek.com/top_up 充值。余额为 0 时请求会返回 402。

把 key 放进环境变量,后面所有命令都从这里读:

export DEEPSEEK_API_KEY="your-api-key"

Windows PowerShell 用 setx DEEPSEEK_API_KEY "your-api-key",然后重开终端。

key 只放环境变量或密钥管理器,不要写进代码、截图或提交到仓库。下文命令一律用 $DEEPSEEK_API_KEY 引用你的 key;第五节故意写的 not-a-real-key 是假 key。

三、第一条 curl 请求

DeepSeek 用 OpenAI 兼容格式,OpenAI 格式的 base_url 是 https://api.deepseek.com。下面是官方首页的示例,开着思考模式、思考强度 high:

curl https://api.deepseek.com/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${DEEPSEEK_API_KEY}" \
  -d '{
        "model": "deepseek-flash",
        "messages": [
          {"role": "system", "content": "You are a helpful assistant."},
          {"role": "user", "content": "Hello!"}
        ],
        "thinking": {"type": "enabled"},
        "reasoning_effort": "high",
        "stream": false
      }'

对照结果(官方 API 文档的示例响应;你的 id、时间戳和回答会不同,开着思考模式时 message 里还会多一个 reasoning_content 字段):

{
  "id": "930c60df-bf64-41c9-a88e-3ec75f81e00e",
  "choices": [
    {
      "finish_reason": "stop",
      "index": 0,
      "message": {
        "content": "Hello! How can I help you today?",
        "role": "assistant"
      },
      "logprobs": null
    }
  ],
  "created": 1705651092,
  "model": "deepseek-flash",
  "object": "chat.completion",
  "system_fingerprint": "fp_7a09fdf9c2",
  "usage": {
    "completion_tokens": 10,
    "prompt_tokens": 16,
    "total_tokens": 26,
    "prompt_tokens_details": {
      "cached_tokens": 0
    },
    "prompt_cache_hit_tokens": 0,
    "prompt_cache_miss_tokens": 16
  }
}
字段含义
choices[0].message.content最终回答
choices[0].finish_reasonstop 表示正常结束;length 表示被 max_tokens 截断
usage.prompt_cache_hit_tokens输入里命中硬盘缓存的 token,按缓存命中价计费
usage.prompt_cache_miss_tokens输入里未命中缓存的 token
usage.completion_tokens输出 token

想要流式输出,把 "stream": false 改成 true。

四、用 Python 和 JavaScript 各跑一次

官方 SDK 示例直接用 OpenAI 的 SDK,只改 base_url。

Python(Python 3.9+):

pip3 install openai

新建 first_call.py:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ.get("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com",
)

response = client.chat.completions.create(
    model="deepseek-flash",
    messages=[
        {"role": "system", "content": "You are a helpful assistant"},
        {"role": "user", "content": "Hello"},
    ],
    stream=False,
    reasoning_effort="high",
    extra_body={"thinking": {"type": "enabled"}},
)
print(response.choices[0].message.content)
python3 first_call.py

对照结果:终端打印一句问候语,例如 Hello! How can I help you today?(措辞每次可能不同)。

注意 thinking 不是 OpenAI SDK 的标准参数,Python 里要放进 extra_body,这是官方文档的写法。

JavaScript(Node.js 18+):

npm install openai

新建 first_call.mjs:

import OpenAI from "openai";

const openai = new OpenAI({
  baseURL: "https://api.deepseek.com",
  apiKey: process.env.DEEPSEEK_API_KEY,
});

async function main() {
  const completion = await openai.chat.completions.create({
    messages: [{ role: "system", content: "You are a helpful assistant." }],
    model: "deepseek-flash",
    thinking: { type: "enabled" },
    reasoning_effort: "high",
    stream: false,
  });
  console.log(completion.choices[0].message.content);
}

main();
node first_call.mjs

对照结果:打印一段自我介绍或问候(只给了 system 消息,模型会主动打招呼)。

五、key 出错时长什么样

先认识报错,排错会快很多。下面三种情况都在 2026-10-22 实测过。

① 用假 key 调 curl:

curl -s https://api.deepseek.com/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer not-a-real-key" \
  -d '{"model":"deepseek-flash","messages":[{"role":"user","content":"Hello!"}]}'

对照结果(HTTP 401,request_id 每次不同):

{"error":{"message":"Authentication Fails, Your api key: ****-key is invalid (request_id: 5b034c2f-92ef-416f-b019-43b5001243df)","type":"authentication_error","param":null,"code":"invalid_request_error"}}

② Python 脚本用假 key(DEEPSEEK_API_KEY=not-a-real-key python3 first_call.py),最后一行是:

openai.AuthenticationError: Error code: 401 - {'error': {'message': 'Authentication Fails, Your api key: ****-key is invalid (request_id: 1cbc1cdb-0587-4a43-be93-ec24cc2c509a)', 'type': 'authentication_error', 'param': None, 'code': 'invalid_request_error'}}

③ 忘了设置环境变量,Python SDK 在发请求前就会报:

openai.OpenAIError: Missing credentials. Please pass an `api_key`, `workload_identity`, `admin_api_key`, or set the `OPENAI_API_KEY` or `OPENAI_ADMIN_KEY` environment variable.

看到这句不要去设 OPENAI_API_KEY,检查 DEEPSEEK_API_KEY 有没有 export 到当前终端即可。

官方错误码表里最常见的几种:

状态码原因怎么办
400请求体格式错误按报错提示改请求体
401API key 错误检查 key,或重新创建
402余额不足到 top_up 页面充值
422参数错误按报错提示改参数
429请求太快或超过并发降低频率;并发按账号计,与 key 无关
500 / 503服务端错误或过载稍等后重试

六、查模型列表和余额

这两个接口不消耗 token,适合做连通性自检。

curl -s https://api.deepseek.com/models \
  -H "Authorization: Bearer $DEEPSEEK_API_KEY"

对照结果(官方 API 文档示例,已截短):

{
  "object": "list",
  "data": [
    {
      "id": "deepseek-flash",
      "object": "model",
      "owned_by": "deepseek",
      "name": "DeepSeek-V4.1-Flash",
      "context_window": 1048576,
      "max_output_tokens": 393216,
      "input_modalities": ["text", "image"],
      "effort": { "supported_levels": ["low", "high", "max"], "default_level": "high" }
    },
    {
      "id": "deepseek-v4-pro",
      "object": "model",
      "owned_by": "deepseek",
      "name": "DeepSeek-V4-Pro",
      "context_window": 1048576,
      "max_output_tokens": 393216,
      "input_modalities": ["text"],
      "effort": { "supported_levels": ["low", "high", "max"], "default_level": "high" }
    }
  ]
}
curl -s https://api.deepseek.com/user/balance \
  -H "Authorization: Bearer $DEEPSEEK_API_KEY"

对照结果(官方示例;数字是你账号的实际余额):

{
  "is_available": true,
  "balance_infos": [
    {
      "currency": "CNY",
      "total_balance": "110.00",
      "granted_balance": "10.00",
      "topped_up_balance": "100.00"
    }
  ]
}

granted_balance 是赠送余额,topped_up_balance 是充值余额;两者都有时先扣赠送余额。

本课按 DeepSeek 官方 思考模式、JSON Output 与 Tool Calls 指南整理(2026-10-22 核对);代码沿用官方示例,只把 key 统一改为从环境变量读取。 目标:学会开关思考模式和调思考强度,读出思考内容并正确拼接多轮对话;让模型输出可直接解析的 JSON;写一个会自己调用函数、能跑多轮的工具循环。

你将得到什么

  • thinking_demo.py:同一个问题分别用「思考」和「不思考」跑一次
  • json_demo.py:把一段文本解析成严格 JSON
  • tool_loop.py:思考模式下的多轮工具调用循环,以及官方给出的逐轮对照输出

先修:已完成第 1 课,DEEPSEEK_API_KEY 已在环境变量中,已 pip3 install openai。

一、思考模式的开关与强度

两个模型都默认开启思考模式,默认强度 high。OpenAI 格式下用两个参数控制:

作用参数取值
开关思考thinking{"type": "enabled"} 或 {"type": "disabled"}
思考强度reasoning_effortlow / high / max

官方还说明了几条容易踩的坑:

  • 其他工具传来的强度会被映射:minimal 按 low,medium 和 xhigh 按 high,ultra 按 max。
  • 思考模式下 temperature、presence_penalty、frequency_penalty 不生效(传了不报错,但没有效果)。
  • 用 OpenAI 的 Python SDK 时,thinking 要放进 extra_body。

新建 thinking_demo.py:

import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["DEEPSEEK_API_KEY"], base_url="https://api.deepseek.com")
question = [{"role": "user", "content": "9.11 and 9.8, which is greater?"}]

# 1) 思考模式:先输出思维链 reasoning_content,再输出最终回答 content
r1 = client.chat.completions.create(
    model="deepseek-flash",
    messages=question,
    reasoning_effort="high",
    extra_body={"thinking": {"type": "enabled"}},
)
print("== thinking ==")
print("reasoning_content:", r1.choices[0].message.reasoning_content[:200], "...")
print("content:", r1.choices[0].message.content)

# 2) 非思考模式:直接回答,更快、更省 token
r2 = client.chat.completions.create(
    model="deepseek-flash",
    messages=question,
    extra_body={"thinking": {"type": "disabled"}},
)
print("== non-thinking ==")
print("content:", r2.choices[0].message.content)
print("tokens:", r1.usage.completion_tokens, "vs", r2.usage.completion_tokens)
python3 thinking_demo.py

对照结果(结构如下,具体文字每次不同):

== thinking ==
reasoning_content: (一段英文推理:比较小数部分 0.11 和 0.8 ……)...
content: 9.8 is greater than 9.11 ...
== non-thinking ==
content: 9.8 is greater than 9.11 ...
tokens: (较大的数) vs (较小的数)

最后一行能直观看到:思考模式输出的 token 明显更多。简单问答、分类、改写可以关掉思考省钱;数学、代码、多步规划保持开启。

二、多轮对话:思考内容要不要传回去

思维链在 reasoning_content 字段里,和 content 同级。下一轮要不要把它传回去,取决于请求里有没有 tools 参数:

请求情况reasoning_content 怎么处理
不带 tools不需要传回;传了也会被忽略,不拼进上下文
带 tools之前所有轮次的都必须完整传回,否则返回 400

不带工具时,官方示例的第二轮写法是直接把上一轮的 message 追加进去:

messages.append(response.choices[0].message)
messages.append({"role": "user", "content": "How many Rs are there in the word 'strawberry'?"})
response = client.chat.completions.create(
    model="deepseek-flash",
    messages=messages,
    reasoning_effort="high",
    extra_body={"thinking": {"type": "enabled"}},
)

response.choices[0].message 里已经含有 content、reasoning_content(以及有工具调用时的 tool_calls),直接 append 最省事,带不带工具都不会错。

三、JSON Output:让模型只输出合法 JSON

官方要求同时做到四点:

  1. 设置 response_format={"type": "json_object"};
  2. system 或 user 提示词里出现 "json" 这个词,并给出期望格式的示例;
  3. max_tokens 设得够大,避免 JSON 被截断;
  4. 官方提示该功能偶尔会返回空 content,可通过调整提示词缓解。

新建 json_demo.py(官方示例):

import json
import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["DEEPSEEK_API_KEY"], base_url="https://api.deepseek.com")

system_prompt = """
The user will provide some exam text. Please parse the "question" and "answer" and output them in JSON format.

EXAMPLE INPUT:
Which is the highest mountain in the world? Mount Everest.

EXAMPLE JSON OUTPUT:
{
    "question": "Which is the highest mountain in the world?",
    "answer": "Mount Everest"
}
"""

user_prompt = "Which is the longest river in the world? The Nile River."

messages = [{"role": "system", "content": system_prompt},
            {"role": "user", "content": user_prompt}]

response = client.chat.completions.create(
    model="deepseek-flash",
    messages=messages,
    response_format={"type": "json_object"},
)

print(json.loads(response.choices[0].message.content))
python3 json_demo.py

对照结果(官方文档给出的模型输出):

{
    "question": "Which is the longest river in the world?",
    "answer": "The Nile River"
}

终端里打印的是 Python 字典:{'question': 'Which is the longest river in the world?', 'answer': 'The Nile River'}。如果 json.loads 报错或 content 为空,按第 4 点调整提示词后重试。

四、工具调用:让模型自己决定调哪个函数

模型本身不执行函数,它只返回「想调用哪个函数、参数是什么」,由你的代码执行后把结果以 role: "tool" 消息交回去,直到模型不再要求调用工具、给出最终回答。

下面是官方「思考模式 + 工具调用」示例,两个函数用假数据模拟。新建 tool_loop.py:

import os
import json
from datetime import datetime
from openai import OpenAI

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_date",
            "description": "Get the current date",
            "parameters": {"type": "object", "properties": {}},
        },
    },
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get weather of a location, the user should supply the location and date.",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "The city name"},
                    "date": {"type": "string", "description": "The date in format YYYY-mm-dd"},
                },
                "required": ["location", "date"],
            },
        },
    },
]

def get_date_mock():
    return datetime.now().strftime("%Y-%m-%d")

def get_weather_mock(location, date):
    return "Cloudy 7~13°C"

TOOL_CALL_MAP = {"get_date": get_date_mock, "get_weather": get_weather_mock}

def run_turn(turn, messages):
    sub_turn = 1
    while True:
        response = client.chat.completions.create(
            model="deepseek-flash",
            messages=messages,
            tools=tools,
            reasoning_effort="high",
            extra_body={"thinking": {"type": "enabled"}},
        )
        # 整条 message 追加回去:带 tools 时 reasoning_content 必须传回
        messages.append(response.choices[0].message)
        reasoning_content = response.choices[0].message.reasoning_content
        content = response.choices[0].message.content
        tool_calls = response.choices[0].message.tool_calls
        print(f"Turn {turn}.{sub_turn}\n{reasoning_content=}\n{content=}\n{tool_calls=}")
        if tool_calls is None:  # 没有工具调用 = 已给出最终回答
            break
        for tool in tool_calls:
            tool_function = TOOL_CALL_MAP[tool.function.name]
            tool_result = tool_function(**json.loads(tool.function.arguments))
            print(f"tool result for {tool.function.name}: {tool_result}\n")
            messages.append({"role": "tool", "tool_call_id": tool.id, "content": tool_result})
        sub_turn += 1
    print()

client = OpenAI(api_key=os.environ["DEEPSEEK_API_KEY"], base_url="https://api.deepseek.com")

messages = [{"role": "user", "content": "How's the weather in Hangzhou Tomorrow"}]
run_turn(1, messages)

messages.append({"role": "user", "content": "How's the weather in Guangzhou Tomorrow"})
run_turn(2, messages)
python3 tool_loop.py

对照结果(官方文档的样例输出,已删去 Turn 1.3 与 Turn 2.2 回答正文中的部分修饰语;日期是官方运行当天,你看到的是你的「明天」):

Turn 1.1
reasoning_content="The user is asking about the weather in Hangzhou tomorrow. I need to get tomorrow's date first, then call the weather function."
content="Let me check tomorrow's weather in Hangzhou for you. First, let me get tomorrow's date."
tool_calls=[ChatCompletionMessageFunctionToolCall(id='call_00_kw66qNnNto11bSfJVIdlV5Oo', function=Function(arguments='{}', name='get_date'), type='function', index=0)]
tool result for get_date: 2026-04-19

Turn 1.2
reasoning_content="Today is 2026-04-19, so tomorrow is 2026-04-20. Now I'll call the weather function for Hangzhou."
content=''
tool_calls=[ChatCompletionMessageFunctionToolCall(id='call_00_H2SCW6136vWJGq9SQlBuhVt4', function=Function(arguments='{"location": "Hangzhou", "date": "2026-04-20"}', name='get_weather'), type='function', index=0)]
tool result for get_weather: Cloudy 7~13°C

Turn 1.3
reasoning_content='The weather result is in. Let me share this with the user.'
content="Here's the weather forecast for **Hangzhou tomorrow (April 20, 2026)**: ..."
tool_calls=None

Turn 2.1
reasoning_content='The user is asking about the weather in Guangzhou tomorrow. Today is 2026-04-19, so tomorrow is 2026-04-20. I can directly call the weather function.'
content=''
tool_calls=[ChatCompletionMessageFunctionToolCall(id='call_00_8URkLt5NjmNkVKhDmMcNq9Mo', function=Function(arguments='{"location": "Guangzhou", "date": "2026-04-20"}', name='get_weather'), type='function', index=0)]
tool result for get_weather: Cloudy 7~13°C

Turn 2.2
reasoning_content='The weather result for Guangzhou is the same as Hangzhou. Let me share this with the user.'
content="Here's the weather forecast for **Guangzhou tomorrow (April 20, 2026)**: ..."
tool_calls=None

读这段输出要看三件事:

  • Turn 1 里模型先调 get_date 拿到今天日期,再调 get_weather,说明它会自己规划调用顺序;
  • Turn 2 没有再调 get_date,因为第一轮的推理已经在上下文里(这正是带 tools 时必须传回 reasoning_content 的原因);
  • tool_calls=None 时循环结束,content 就是最终回答。

五、两个进阶开关(按需)

  • strict 模式(Beta):要求工具参数严格符合你定义的 JSON Schema。用法是把 base_url 改成 https://api.deepseek.com/beta,并给每个 function 加 "strict": true。思考和非思考模式都支持。
  • 非思考模式调工具:只把 extra_body 改成 {"thinking": {"type": "disabled"}},其余写法相同,适合对延迟敏感、逻辑简单的工具调用。

本课检查清单

  • thinking_demo.py 两种模式都给出了正确答案,且能看出 token 差异
  • json_demo.py 打印出含 question 和 answer 的字典
  • tool_loop.py 跑出了与对照结果同样结构的 Turn 1.1–1.3、2.1–2.2
  • 能说清楚:什么情况下必须把 reasoning_content 传回

下一课:把 DeepSeek 接进 Claude Code 当编码 Agent 的大脑,再用官方 Search / Fetch 接口给自己的应用加上联网能力。

七、算清楚费用:峰谷价与缓存

官方价格按每百万 tokens 计,空闲时段是高峰时段的一半。高峰时段为北京时间周一至周五(不含法定节假日)9:00–12:00、14:00–18:00,其余时间(含周末、节假日全天)都是空闲时段。

每百万 tokensdeepseek-flashdeepseek-v4-pro
输入·缓存命中(高峰 / 空闲)0.04 元 / 0.02 元0.30 元 / 0.15 元
输入·缓存未命中(高峰 / 空闲)2 元 / 1 元9 元 / 4.5 元
输出(高峰 / 空闲)8 元 / 4 元27 元 / 13.5 元

两点实用结论:

  • 批量任务尽量放到晚上或周末跑,价格直接减半。
  • 硬盘缓存默认开启、不用改代码:多轮对话或反复用同一段长文档提问时,重复的前缀按缓存命中价计费,看响应里的 prompt_cache_hit_tokens 就知道省了多少。

本课检查清单

  • echo $DEEPSEEK_API_KEY 能看到你的 key
  • curl、first_call.py、first_call.mjs 都打印出了回答
  • /models 返回了 deepseek-flash 和 deepseek-v4-pro
  • 认得 401 / 402 / 429 三种报错

下一课:打开和关闭思考模式、读出思考内容,让模型输出严格 JSON,并写一个会自己调用函数的工具循环。

本课资料

适用环境

  • 网页
  • API
  • iOS
  • Android

官方文档

DeepSeek ↗