接入DeepSeek API时,第一次请求失败,并不一定是提示词或模型参数有问题。密钥没有传入当前进程、账号余额不足、网络连接失败,都可能让后续调试停在第一步。如果直接运行长文生成任务,错误来源反而更难区分。

DeepSeek API接入前检查:余额查询、认证与错误定位方法示意图
把 AI 用到实际任务 · 原创方法示意图

这篇教程先完成一个小目标:用Python调用官方余额查询接口,检查请求是否带上认证信息、响应结构是否符合预期,并根据HTTP状态定位下一步。查询成功只是接入检查的一部分,不代表模型调用、额度和业务结果都已验收。

本文依据DeepSeek官方认证、余额和错误码文档编写。程序及异常分支已使用本地模拟响应验证,没有使用读者密钥查询真实账户,也没有发起收费模型生成。文中的金额都是教学样例,不是本站或任何用户的真实余额。

一、准备账号与最小运行环境

DeepSeek API是在线服务,本篇不需要在电脑部署大模型或租GPU。需要的是一个能访问官方API的网络环境、Python 3,以及你自己在DeepSeek开放平台创建的API密钥。

网页聊天账号能使用产品,不等于某个API密钥已经存在或余额已经满足调用要求。从官方文档的开放平台入口登录,在账号内创建并管理密钥;具体权益和计费以平台当前显示为准,本文不承诺赠送额度或固定套餐。

在终端运行python --version确认命令可用。若系统使用python3命令,后续相应替换。示例只用标准库,不需要先安装OpenAI SDK,因此遇到问题时可以少排查一层依赖版本。

把程序保存到独立练习目录。不要将真实密钥写入源代码、截图或公开仓库,也不需要把密钥发送给AI助手。本程序默认从环境变量读取;未设置时,在本机终端用隐藏输入方式询问。

二、先理解这次请求会做什么

官方OpenAI兼容接口的基础地址为https://api.deepseek.com,余额查询路径为GET /user/balance。认证使用Authorization请求头中的Bearer密钥。本篇固定请求这个官方HTTPS地址,不接受从网页或聊天复制来的任意“中转地址”。

与生成文本的接口不同,余额查询不需要填写模型名称、messages或提示词。不要把一段聊天请求体贴到余额接口,也不要为了查询余额修改成文本生成请求。本文不对该查询接口的收费政策作额外推断,只说明它不会发起模型文本生成任务。

响应的is_available表示余额是否足以进行API调用;balance_infos按币种列出余额信息。total_balance、granted_balance和topped_up_balance在官方结构中都是字符串,分别对应可用总余额、未过期赠送部分和充值部分。

币种不同的记录分别看,不能把人民币和美元直接相加。金额用Decimal读取,避免把十进制字符串先转成二进制浮点数再进行不必要的近似计算。

三、保存一个不输出密钥的检查程序

将下面内容保存为balance_check.py。程序只输出余额概要或简短错误分类,不打印认证请求头、完整异常对象或原始错误响应体。

import getpass
import json
import os
from decimal import Decimal, InvalidOperation
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen


URL = "https://api.deepseek.com/user/balance"


def summarize(data):
    if not isinstance(data, dict):
        raise ValueError("response must be object")
    available = data.get("is_available")
    infos = data.get("balance_infos")
    if type(available) is not bool or not isinstance(infos, list):
        raise ValueError("unexpected balance schema")
    lines = ["is_available=" + str(available)]
    for info in infos:
        if not isinstance(info, dict):
            raise ValueError("invalid balance row")
        currency = info.get("currency")
        if currency not in ("CNY", "USD"):
            raise ValueError("unexpected currency")
        amounts = []
        for name in ("total_balance", "granted_balance", "topped_up_balance"):
            raw = info.get(name)
            if not isinstance(raw, str):
                raise ValueError("amount must be string")
            try:
                amount = Decimal(raw)
            except InvalidOperation as exc:
                raise ValueError("invalid amount") from exc
            if not amount.is_finite():
                raise ValueError("non-finite amount")
            amounts.append(name + "=" + str(amount))
        lines.append(currency + " " + " ".join(amounts))
    return lines


def fetch_balance(key, opener=urlopen):
    if not isinstance(key, str) or not key.strip():
        raise ValueError("missing API key")
    request = Request(URL, headers={
        "Authorization": "Bearer " + key.strip(),
        "Accept": "application/json",
    }, method="GET")
    with opener(request, timeout=15) as response:
        raw = response.read(65537)
    if len(raw) > 65536:
        raise ValueError("response too large")
    return summarize(json.loads(raw.decode("utf-8")))


def main():
    key = os.environ.get("DEEPSEEK_API_KEY", "").strip()
    if not key:
        key = getpass.getpass("DeepSeek API key (hidden): ").strip()
    try:
        for line in fetch_balance(key):
            print(line)
    except HTTPError as exc:
        print("HTTP", exc.code, "- check official error-code documentation")
        return 1
    except (URLError, TimeoutError):
        print("Network connection failed or timed out; no balance confirmed")
        return 1
    except (ValueError, UnicodeError):
        print("Key missing or response invalid; no balance confirmed")
        return 1
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

程序设置十五秒网络超时,并给读取长度加了上限,目的是让首次诊断范围可控。这不是完整生产监控程序,也没有自动充值、自动重试或密钥管理功能。

四、首次运行与输入方式

在本机交互式终端运行python balance_check.py。若当前进程没有DEEPSEEK_API_KEY,程序会显示隐藏输入提示。粘贴你自己的密钥并按回车;正常的隐藏输入不会逐字显示字符。

不要把真实密钥作为命令行参数拼在命令后面,也不要在在线代码运行器执行这个步骤。若终端提示无法隐藏输入,先停止操作,换成本机支持隐藏输入的终端,再重新运行。

若已经通过自己的安全配置设置环境变量,确认运行脚本的终端实际继承了变量。系统设置窗口中新建变量后,旧终端不一定自动获得更新;可以重新打开终端,或者直接使用本程序的隐藏输入方式。无需为了证明变量存在而把其内容打印出来。

读取时程序会去掉密钥首尾空白,但不会修复复制错误、替换字符或猜测缺失部分。出现认证失败,回到自己账号的密钥管理界面核对,而不是连续尝试别人提供的密钥。

五、正确解读返回结果

官方文档示例使用CNY,total_balance为110.00、granted_balance为10.00、topped_up_balance为100.00。对于这份教学响应,本程序会打印可用判断与三个对应字段。这些数字只是结构示例,不能作为任何真实账号的余额证明。

如果is_available为False,应检查账号余额和平台状态,不要直接开始批量任务。如果为True,只能说该次查询返回了可用判断;随后调用模型仍可能遇到速率限制、参数错误、服务端故障或其他条件变化。

如果列表为空,程序只能打印is_available,而没有币种金额行。不要自己补一个零余额,也不要把没有金额信息当作完整对账成功。先与平台显示和官方当前响应规范核对,保留“尚未确认金额”的结论。

本程序没有将余额写入文件。确需记录运行结果时,保存检查时间、HTTP状态和是否确认接入即可;若记录具体金额,按自己的账号资料管理规则保存,不放进公开问题单。

六、按错误类型定位下一步

  • 401表示认证失败,优先核对密钥来源、是否已撤销,以及当前程序是否真的拿到正确值。不要通过重复请求来期待错误密钥自动恢复。
  • 402在官方错误码中表示余额不足。先核查账号状态;是否充值由账号持有人决定,程序不代做付款。
  • 400和422分别与请求格式、参数有关。余额查询使用GET且不带聊天请求体;检查是否误改路径、方法或加入其他接口字段。
  • 429与请求频率或并发限制有关。这类检查不需要频繁轮询,停止重复点击,按当前官方限制安排后续请求。
  • 500或503属于服务端异常或负载问题。保留时间和状态,稍后再试;持续出现时对照官方状态渠道。
  • 网络失败或超时尚未拿到有效业务响应,不能直接解释成余额不足,也不要关闭HTTPS证书校验来强行通过。

这些是官方错误分类与排查顺序,不意味着余额接口必然返回列表中每一种状态。实际请求的状态、官方说明和账号页面应共同核对。

七、再进入业务功能,而不是扩大诊断脚本

验收完成时,你应该知道密钥由哪里输入、请求发往哪个官方地址、响应有哪些字段,以及失败后先查哪一层。把这四件事确认后,再单独准备一个很小的模型请求,核对当前模型名与计费信息。

不要把查余额成功写成“AI应用已经部署完成”。完整应用还需要测试输入输出、费用上限、异常处理和业务验收;本文只完成连接前检查。如果使用第三方客户端,还要检查它自己的基础地址、认证配置和日志行为,而不能把本地脚本的结果直接套给另一个工具。

八、用三次小检查避免误判接入状态

第一次只运行程序并观察是否出现隐藏输入提示。如果明明设置了环境变量却仍然询问密钥,说明当前进程没有读取到非空值;这时先排查运行环境,不要猜测是服务端拒绝请求。常见情况是编辑器、系统终端和定时任务使用了不同的启动环境。

第二次在网络正常、自己确认密钥有效的情况下运行,观察能否得到符合结构的结果。把HTTP成功和业务可用判断分开记录:服务器能够返回余额信息,并不意味着可用判断一定为真。若响应无法按结构解释,先保存“结构未确认”的结论,不把乱码、登录页或代理提示页当作余额。

第三次才在你的应用里检查同一账号的配置。对照基础地址、密钥来源和启动方式,确认没有把其他服务的变量名填进来。本篇脚本固定使用官方接口;第三方客户端若使用不同地址,其结果不能由本次检查自动背书。

准备向支持人员求助时,可以提供运行时间、Python版本、错误类别、HTTP状态和经过检查的接口路径。不要提供密钥截图,也不必发送包含认证信息的完整请求。别人需要知道的是哪一层失败,而不是掌握你的账号访问凭据。

如果后续计划在服务器自动检查,还需单独安排密钥存放、运行权限和低频检查策略。不要把交互式隐藏输入脚本直接塞进无人值守任务,让程序一直等输入;本文完成的是手动接入诊断,自动运行应在明确需求后另行设计。

官方资料