OpenAI SDK 调用 DeepSeek:从 HTTP 原理到项目实践

适用:W04首次接入,W05流式对话,W06知识库回答,W07动作规划,W08工作流解释节点。

先分清三个名字

SDK(Software Development Kit,软件开发工具包)在这里是一套模型调用客户端。安装 openai 并不意味着调用 OpenAI 的模型;本课程仍使用 DeepSeek 的服务地址、模型和密钥。SDK 帮我们发送请求、接收响应和分类异常;业务校验、工具权限、人工审批和费用控制仍由项目负责。

HTTP原理:业务代码 → 手写认证Header与JSON → HTTP请求 → DeepSeek
SDK实践:业务代码 → OpenAI客户端        → HTTP请求 → DeepSeek
共同验收:响应完整 → 读取用量 → 业务校验 → 展示或拒绝

W04用同一消息对照两种方式,后续模型调用以SDK为主。保留HTTP知识是为了能查请求地址、参数和状态码,不要求每周重写一套网络客户端。

先安装和验证,再填配置

进入自己的项目目录,用TRAE选中该周虚拟环境;没有虚拟环境时先按已学步骤创建并选择解释器。

python -m pip install "openai==2.26.0"
python -m pip check
python -c "import sys, openai; print(sys.executable); print(openai.__version__)"

本轮验证版本是2.26.0,不表示最新版;整周安装优先遵循该周requirements或锁文件,不自行升级其他依赖。SDK和HTTP底层库的版本应一起验证。

运行时填写环境变量,不把真实Key写入代码、截图、日志或Git:

$env:DEEPSEEK_API_KEY = "在本机填写,不发群聊"
$env:DEEPSEEK_MODEL = "填写实验卡中当前可用的模型名"

执行真实调用前,核对模型可用性、余额、输入内容和输出上限。不要复制过期模型名或费率;费用是服务商收取的调用费用,使用SDK不会免除费用。W04已有被Git忽略的本地TOML配置仍供性能演示使用,本次不读取或改写其中的密钥。

同一条消息,两种写法

先预测:改用SDK后,请求最终发给谁?返回的正文、Token用量和失败状态是否还需要我们处理?

下面两段是最小通信对照,不是完整客服实现。每次运行一段都会发起一次真实请求;课堂先用离线替身演示,不要为比较语法重复消耗额度。

# 共同输入:模型来自当前实验卡,Key来自本机环境。
import os
import httpx
from openai import OpenAI
 
key = os.environ["DEEPSEEK_API_KEY"]
model = os.environ["DEEPSEEK_MODEL"]
messages = [{"role": "user", "content": "查询订单前需要提供什么?"}]

HTTP原理示例:

with httpx.Client(timeout=30, follow_redirects=False) as client:
    response = client.post(
        "https://api.deepseek.com/chat/completions",
        headers={"Authorization": "Bearer " + key},
        json={"model": model, "messages": messages, "max_tokens": 128},
    )
    response.raise_for_status()
    body = response.json()
    print(body["choices"][0]["message"]["content"])

SDK实践示例:

with OpenAI(api_key=key, base_url="https://api.deepseek.com",
            timeout=30, max_retries=0) as client:
    response = client.chat.completions.create(
        model=model, messages=messages, max_tokens=128,
    )
    print(response.choices[0].message.content)
    print(response.usage)  # None表示服务端未提供,不是零消耗。
HTTP里看到的内容SDK里对应什么仍需本人检查
URL与认证Headerbase_url、api_key指向DeepSeek,不是默认OpenAI服务
JSON请求体create的命名参数model、messages、输出上限与业务条件
返回JSON带类型的响应对象,也可model_dump为字典finish_reason、正文类型、业务字段和usage
状态码/连接异常APIStatusError、APITimeoutError、APIConnectionError是否重试、记录什么、如何安全提示

客户端对象不等于业务Provider Adapter。Adapter要继续把SDK结果翻译成课程已约定的结果,不把SDK对象直接塞进订单或会话状态。

参数和默认行为:这几处要看懂

  • max_retries=0:关闭SDK自动重试,避免一次课堂操作悄悄变成多次付费请求。是否允许重试由应用结合业务决定,写操作更不能直接重试。
  • timeout=30:配置网络等待上限,不等于端到端业务总时限。W05还检查流式处理经过的时间;阻塞读取受网络超时控制。
  • max_tokens:限制输出,不代表输入免费,也不代表账户硬预算。
  • DeepSeek特有字段通过 extra_body 传入,例如 extra_body={"thinking": {"type": "disabled"}};兼容接口不意味着所有模型支持所有参数。
  • response_format={"type": "json_object"} 只约束JSON形式;金额、引用、允许的动作仍需业务代码检查。
  • 不把原始异常正文直接打印到学生屏幕:服务端错误可能包含请求信息。只记录安全错误类别和状态码,不输出Key。

W05:为什么流式不能只检查“收到了一些文字”

SDK常见写法 create(stream=True) 返回分块迭代器,正文通常从 chunk.choices[0].delta.content 读取;usage可能在没有choices的最后一块出现,不能用分块数量猜Token。

本课程既有要求还需要明确核对服务结束标记。普通分块迭代会隐藏 [DONE],因此当前Adapter使用公开入口 chat.completions.with_streaming_response.create(stream=True, ...),通过 response.iter_lines()检查SSE(服务器发送事件)行,再翻译成既有五种课堂事件。

完成必须同时看到有效正文、finish_reason=stop、[DONE];截断或缺结束标记返回ERROR。用户取消要关闭生成器和网络响应,记录本地CANCELLED,不提交最终assistant消息,也不新增第六种事件。用量缺失保持未知,取消不等于服务端未计费。

W06–W08:SDK只替换通信,不替换业务责任

  • W06:先检查检索证据,再调用SDK;空证据零调用,模型伪造引用仍被拒绝。向量编码继续使用原有编码器,不能拿聊天客户端替代Embedding模型。
  • W07:SDK返回的是不可信动作候选,Engine继续检查三工具范围、预算、停止与人工审批。SDK不获得创建工单权限。
  • W08:图的筛选、状态、审批与恢复不变;显式开启SDK解释依赖时,模型只选择已有商品与用户偏好中匹配的事实,再由程序验证并渲染价格和引用。它是受限解释,不是自由推荐或算法评分。
  • W08原有路由与售后流程默认仍走教学Fixture/Replay;接入一个真实解释节点不能证明全图已接真实服务,也不能替代Docker或新进程恢复验收。

迁移前后怎样证明没有退步

故障/风险怎样发现怎样处理与复验
装错解释器打印解释器路径和SDK版本选对虚拟环境后重装,运行pip check
地址或认证错误离线401测试与安全错误类别检查本机配置,不展示Key;离线测试确认只有一次请求
自动重试导致调用变多HTTP替身统计429/超时请求数显式max_retries=0,再断言一次动作一次请求
流中断却保存了最终回复模拟缺DONE和用户取消检查ERROR/CANCELLED、零最终提交及响应关闭
用量缺失被当成免费去掉响应usage字段保留未知,不生成零费用结论
换SDK后业务校验消失输入伪造引用、未知工具、错误商品特征保留原验证器,运行正常与反例测试

耗时仍用单调时钟测量;非流式总耗时、首段正文等待、整条业务链耗时分别记录。SDK解析开销也包含在实际调用耗时内,不能把离线替身结果当成真实性能提升。费用用真实usage乘当前已核实费率;模型或费率不匹配时保留待核对。

课后自己解释

  1. 为什么安装openai仍能使用DeepSeek?如果忘记base_url会怎样?
  2. SDK自动重试、Agent重规划和业务工单幂等分别解决什么问题?
  3. 看到stop但没有结束标记,为什么不能提交最终回复?
  4. 换SDK后,哪些业务测试应该一行不改仍然通过?

官方参考:DeepSeek首次调用;OpenAI Python客户端用法与错误处理。本页安装版本以本轮离线验证为准,真实服务仍需本人补验。