本地跑起 DeepSeek-Coder 之后,想让现有 OpenAI SDK 工具直接连过去,通常只卡在三个地方:base_url 没指对、api_key 没给非空占位、模型名跟服务端实际返回的不一致。判断标准也简单:先看本地服务有没有暴露兼容 OpenAI 协议的端点,再按端点返回的信息去配客户端。下面按排查顺序给出一套可直接操作的配置与验证路径。
适用场景:本地已启动兼容 OpenAI 协议的服务(如 llama.cpp 或 vLLM),目标是用 OpenAI SDK 兼容工具连接。操作动作:先 curl 服务端 /v1/models 确认协议与可用模型名,再配置 base_url 与 api_key 占位,最后用 chat completion 请求做端到端验证。风险边界:不同后端服务的字段和路径可能略有差异,需以实际返回为准;本文不涉及 DeepSeek 云 API 的私有鉴权参数。
先检查本地服务是否暴露 /v1/models 端点
OpenAI 兼容服务通常把模型列表放在 /v1/models 路径下。本地服务默认地址可能是 http://localhost:8000 或 http://127.0.0.1:8080,具体端口取决于启动参数。先用 curl 直接探测:
curl http://localhost:8000/v1/models
如果服务正常,会返回类似下面的 JSON,重点看 data[].id 字段,那是后续配置模型名时必须要对上的值:
{
"object": "list",
"data": [
{"id": "deepseek-coder-6.7b-instruct", "object": "model"}
]
}
这一步能同时验证两件事:服务协议是否兼容、模型名到底是什么。如果 curl 直接报 connection refused,说明端口或监听地址不对;如果返回 404,说明该服务可能没有启用 OpenAI 兼容 API,需要回到服务启动参数中确认。
配置 OpenAI 库的 base_url 和 api_key 占位
OpenAI SDK 默认会请求 OpenAI 官方地址,本地接入时只需要覆盖 base_url,并让 api_key 是非空字符串即可。本地兼容服务通常不校验 api_key 内容,但空值可能导致某些 SDK 直接报错。Python 示例:
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="not-empty-placeholder", # 任意非空字符串
)
models = client.models.list()
print([m.id for m in models.data])
注意 base_url 要写到 /v1 这一层,而不是根地址。如果写成了 http://localhost:8000,SDK 可能拼出 http://localhost:8000/chat/completions,导致请求路径错误。把上面的 models.list() 跑通,说明客户端连接层没问题,接下来就处理具体报错。
处理 404、认证失败、模型名不存在等错误
常见错误可以按下面几类排查:
- 404 Not Found:多数是 base_url 末尾少写了 /v1,或者写成了 /v1/。建议统一写成 http://localhost:8000/v1,不带末尾斜杠。也可以检查服务端日志里实际收到的路径,确认是 /chat/completions 还是 /v1/chat/completions。
- 401 或 403 认证失败:本地兼容服务通常不校验 key,但某些 SDK 在 api_key 为 None 时会拒绝发起请求。给 api_key 填任意非空字符串,例如 sk-local-test。
- 404 model not found 或模型名无效:请求体里的 model 字段必须和 /v1/models 返回的 id 完全一致。比如服务端返回的是 deepseek-coder-6.7b-instruct,请求里写 deepseek-coder,就可能找不到模型。
先对照这三点改配置,再用下面的 curl 做一次完整请求,能更快定位是路径、鉴权还是模型名的问题。
用 curl 发送一次 chat completion 端到端验证
绕过 SDK,直接用 curl 发聊天补全请求,可以排除客户端拼装问题。下面是一个完整的 POST 示例:
curl -X POST http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer not-empty-placeholder" \
-d '{
"model": "deepseek-coder-6.7b-instruct",
"messages": [
{"role": "user", "content": "写一个 Python 函数计算斐波那契数列"}
],
"temperature": 0.2
}'
正常返回会类似:
{
"id": "chatcmpl-xxx",
"model": "deepseek-coder-6.7b-instruct",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "def fib(n): ..."
}
}
]
}
curl 返回能拿到 choices[0].message.content,说明服务端接口链路通。再回过去用 SDK 同样请求一遍,如果 SDK 报错,就把报错信息和服务端日志对比,重点看请求路径与 model 字段是否一致。
将配置固化到 .env 供脚本复用
把 base_url 和模型名写进 .env,既避免每次输入,也方便多个脚本共用同一份配置。示例变量:
OPENAI_BASE_URL=http://localhost:8000/v1
OPENAI_API_KEY=not-empty-placeholder
OPENAI_MODEL=deepseek-coder-6.7b-instruct
Python 里用 os.getenv 读取,配合 OpenAI 客户端初始化:
import os
from openai import OpenAI
client = OpenAI(
base_url=os.getenv("OPENAI_BASE_URL"),
api_key=os.getenv("OPENAI_API_KEY"),
)
response = client.chat.completions.create(
model=os.getenv("OPENAI_MODEL"),
messages=[{"role": "user", "content": "你好"}],
)
print(response.choices[0].message.content)
注意 .env 文件里的值不要加引号,行内不要有额外空格。如果后续服务换了端口或模型名,只需要改 .env,不要动代码逻辑。以上所有命令和代码,都需要结合本地服务的实际端口和模型 id 做替换。