再测 DeepSeek 各家 API 真实速度(附:测试脚本)

首先,我要给大家跪一个

在上一篇里面:务实测试:DeepSeek 各家 API 真实速度(附:测试脚本)

之前我的 token 计算方法错误,导致数据有 10% 的偏差(排序不变)


在这里感谢「茫然四顾」的问题指出



下方为准确的速度测试

DeepSeek 官方 + 阿里/百度/火山/腾讯云 + 硅基流动

(新增了百度和硅基普通版)

中国时间:2025-02-14 17:35:55

测试代码&log

https://colab.research.google.com/drive/1cUqspnOrft2Qp9Oq4sGfDzlsJN_WCogl

测试方法

代码我放在了最后,可以自己跑


测试包含以下步骤:

  • 通过 API 向模型服务器发送请求,记录当前时间为 t0

  • 当模型返回第一个字符时,记录为 t1,此刻开始推理

  • 当模型推理结束、开始生成内容时,记录为 t2

  • 当生成结束时,记录为 t3

  • 当 stream_options={“include_usage”: True} 的时候,模型会记录并输出以下信息类似这样的信息:

    CompletionUsage(completion_tokens=513, prompt_tokens=19, total_tokens=532, completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=None, audio_tokens=None, reasoning_tokens=377, rejected_prediction_tokens=None), prompt_tokens_details=PromptTokensDetails(audio_tokens=None, cached_tokens=0), prompt_cache_hit_tokens=0, prompt_cache_miss_tokens=19)

    • 推理阶段所使用的 token,记做:T推,就是 reasoning_tokens

    • 生成阶段所使用的 token,记做:T生,就是 completion_tokens-reasoning_tokens

    • 另:并非所有的接口,都返回了 CompletionTokensDetails 字段,比如硅基流动、腾讯云、阿里云就只返回了 completion_tokens,prompt_tokens 和 total_tokens。因此,对于这几个模型,只能统计平均速度。

  • 因此,可知:

    • 模型的首响应时间:t1 – t0

    • 模型的推理速度:T推/(t2-t1)

    • 模型的生成速度:T生/(t3-t2)

    • 模型的平均速度:(T推+T生)/(t3-t0)

在这里,我用的 Prompt 也非常简单(对于推理模型来说,太长的 prompt 也没意义)

#测试 prompt:给我写一首七言绝句,赞叹祖国的大好河山

代码

测试代码如下

记得先替换 API Key
然后 pip install openai

import timefrom openai import OpenAIfrom google.colab import userdataimport datetimeimport pytz

def test_provider(provider_config, messages): """ 根据传入的 provider 配置及消息,测试生成过程,并统计各阶段指标。 如果测试过程中出现任何错误,则打印错误信息并跳过当前服务商。 """ provider_name = provider_config.get("name", "Unnamed Provider") print(f"\n---------------------------") print(f"开始测试服务商:{provider_name}") print(f"---------------------------\n")
try: api_key = provider_config.get("api_key") base_url = provider_config.get("base_url") model = provider_config.get("model")
# 初始化客户端(请确保你使用的 OpenAI 客户端支持这些参数) client = OpenAI(api_key=api_key, base_url=base_url)
# 初始化 token 计数器与文本变量 prompt_tokens = 0 completion_tokens = 0 reasoning_tokens = 0 content_tokens = 0 total_tokens = 0
reasoning_text = "" content_text = ""
# 初始化计时变量 start_time = time.time() first_token_time = None
# 用于记录 reasoning 与 content 部分开始与结束的时刻 reasoning_start_time = None reasoning_end_time = None content_start_time = None content_end_time = None
# 吐槽:各家 usage_content 的更新方式不同,有的是过程中更新,有的是最后展示 usage_content = ""
# 发起流式请求 response = client.chat.completions.create( model=model, messages=messages, stream=True, stream_options={"include_usage": True}, )
# 遍历每个流式响应块 for chunk in response: # 若 chunk 中没有 choices 信息,则检查是否有 usage 信息打印后继续 if chunk.usage: usage_content = chunk.usage # 如果 completion_tokens_details 为 None,则说明没有单独的推理信息,此时设置 reasoning_tokens 为 0 if chunk.usage.completion_tokens_details is None: reasoning_tokens = 0 else: reasoning_tokens = chunk.usage.completion_tokens_details.reasoning_tokens prompt_tokens = chunk.usage.prompt_tokens completion_tokens = chunk.usage.completion_tokens content_tokens = completion_tokens - reasoning_tokens total_tokens = chunk.usage.total_tokens

# 获取第一个 choice 的 delta if not chunk.choices: continue delta = chunk.choices[0].delta # 尝试获取 reasoning 与 content 片段(可能为空字符串) reasoning_piece = getattr(delta, 'reasoning_content', "") content_piece = getattr(delta, 'content', "")
# 记录首个 token 到达时间(仅记录一次) if first_token_time is None and (reasoning_piece or content_piece): first_token_time = time.time() - start_time
# 如果有 reasoning 内容 if reasoning_piece: if reasoning_start_time is None: reasoning_start_time = time.time() reasoning_text += reasoning_piece reasoning_end_time = time.time() # 每次更新,最终记录最后一次收到的时刻 print(reasoning_piece, end='', flush=True)
# 如果有 content 内容 elif content_piece: if content_start_time is None: content_start_time = time.time() content_text += content_piece content_end_time = time.time() # 每次更新 print(content_piece, end='', flush=True)

total_time = time.time() - start_time reasoning_time = (reasoning_end_time - reasoning_start_time) if (reasoning_start_time and reasoning_end_time) else 0 content_time = (content_end_time - content_start_time) if (content_start_time and content_end_time) else 0 if(usage_content): print("\n\n【Usage 信息】") print(usage_content) # 输出测试指标,格式参考如下 print("\n\n【%s】" % provider_name) if first_token_time is not None: print(f"首 token 响应时间:{first_token_time:.2f} 秒") else: print("未收到 token 响应。") if reasoning_tokens > 0: print(f"Reasoning 部分:{len(reasoning_text)} 字符,{reasoning_tokens} tokens, 用时:{reasoning_time:.2f} 秒, 生成速度:{reasoning_tokens / reasoning_time if reasoning_time > 0 else 0:.2f} tokens/s") print(f"Content 部分:{len(content_text)} 字符,{content_tokens} tokens, 用时:{content_time:.2f} 秒, 生成速度:{content_tokens / content_time if content_time > 0 else 0:.2f} tokens/s") # 总体生成始终打印 print(f"内容生成:{len(reasoning_text + content_text)} 字符,{completion_tokens} tokens, 总用时:{total_time:.2f} 秒, 生成速度:{completion_tokens / total_time if total_time > 0 else 0:.2f} tokens/s") print("\n***************************\n")
return { "provider": provider_name, "first_token_time": first_token_time, "reasoning_tokens": reasoning_tokens, "reasoning_time": reasoning_time, "content_tokens": content_tokens, "content_time": content_time, "total_tokens": total_tokens, "total_time": total_time, }
except Exception as e: # 如果出现任何错误,则打印错误信息并跳过该服务商 print(f"服务商 {provider_name} 测试过程中发生错误:{e}") print("\n---------------------------\n") return None

if __name__ == "__main__": # 待测试的对话消息(此处为示例:写一首七言绝句赞美祖国大好河山) messages = [ { 'role': 'user', 'content': "给我写一首七言绝句,赞叹祖国的大好河山" } ]
# 定义各服务商的配置 providers = [ { "name": "DeepSeek 官方", # 这个经常不可用 "api_key": userdata.get('Key_DeepSeek'), # 请替换为真实 API Key:https://platform.deepseek.com/api_keys "base_url": "https://api.deepseek.com", "model": "deepseek-reasoner" }, { "name": "阿里云/百炼", "api_key": userdata.get('Key_Aliyun'), # 请替换为真实 API Key:https://bailian.console.aliyun.com/?apiKey=1#/api-key "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", "model": "deepseek-r1" }, { "name": "百度千帆", "api_key": userdata.get('Key_Qianfan'), # 请替换为真实 API Key:https://console.bce.baidu.com/iam/#/iam/apikey/list "base_url": "https://qianfan.baidubce.com/v2", "model": "deepseek-r1" }, { "name": "硅基流动", "api_key": userdata.get('Key_Siliconflow'), # 请替换为真实 API Key:https://cloud.siliconflow.cn/account/ak "base_url": "https://api.siliconflow.cn/v1", "model": "deepseek-ai/DeepSeek-R1" }, { "name": "硅基流动Pro", "api_key": userdata.get('Key_Siliconflow'), # 请替换为真实 API Key:https://cloud.siliconflow.cn/account/ak "base_url": "https://api.siliconflow.cn/v1", "model": "Pro/deepseek-ai/DeepSeek-R1" }, { "name": "火山引擎", "api_key": userdata.get('Key_Volces'), # 请替换为真实 API Key:https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D "base_url": "https://ark.cn-beijing.volces.com/api/v3", "model": userdata.get('Endpoint_Volces_R1') # 火山引擎这里叫接入点,在这里创建:https://console.volcengine.com/ark/region:ark+cn-beijing/endpoint?config=%7B%7D }, { "name": "腾讯云", "api_key": userdata.get('Key_Tencentcloud'), # 请替换为真实 API Key:https://console.cloud.tencent.com/lkeap "base_url": "https://api.lkeap.cloud.tencent.com/v1", "model": "deepseek-r1" }, ]

print(f"本次测试开始于中国时间:{datetime.datetime.now(pytz.timezone('Asia/Shanghai')).strftime('%Y-%m-%d %H:%M:%S')}")
# 循环对每个服务商进行测试 for provider in providers: test_provider(provider, messages)
你也可以直接在 Colab 里面跑
https://colab.research.google.com/drive/1cUqspnOrft2Qp9Oq4sGfDzlsJN_WCogl



最后
还是先给大家道个歉,上一篇内容里,是我代码写错了,导致结果不对。
这个事儿也给我提个醒:做任何测试的时候,必附代码,必公开过程,必接受监督。

另外的,在测试的过程中,我也发现一些有趣的事情:大家的接口返回格式,不都完全一样:
  • 有的是在末位 token 一并给出 usage 信息(比如官方),有的则是在过程中不断更新(比如硅基流动)
  • 有的会分别给出推理、生成所用的 token 数量(比如官方),有的则只给出总和的 token(比如腾讯云)
  • 等等…

(文:赛博禅心)

欢迎分享

发表评论