本文面向有 Python 基础的开发者,聚焦 DeepSeek-R1 的 API 接入与实战使用,帮你搞清楚「什么时候该用 R1,什么时候 V3 就够了」。
背景:推理模型是什么,为什么需要它
传统大模型(比如 DeepSeek-V3)是一步到位的:给个 prompt,直接输出答案。这种方式在大多数场景下都够用,但遇到需要多步推导的问题时就容易翻车——数学证明算错步骤、代码推导逻辑跳步、复杂规划遗漏约束条件。
推理模型(Reasoning Model) 的核心思路是「先想清楚再回答」。模型在给出最终答案之前,会生成一段内部思考过程(thinking tokens),这段推理链条可以显著提升复杂问题的准确率。
DeepSeek-R1 就是这类模型的代表。它在数学竞赛、代码推理、逻辑推断等基准测试上的表现,不输甚至超过了同期的很多闭源模型。
DeepSeek-R1 vs DeepSeek-V3:核心区别
| 维度 | DeepSeek-V3 | DeepSeek-R1 |
|---|---|---|
| 架构特点 | 标准自回归生成 | 显式思维链(CoT) |
| 推理能力 | 适合知识检索、写作、代码补全 | 适合复杂推理、数学证明、多步规划 |
| 响应速度 | 快 | 慢(thinking 阶段耗时) |
| Token 消耗 | 低 | 高(thinking tokens 额外计费) |
| 适用场景 | 80% 日常任务 | 需要「想清楚」的任务 |
简单来说:V3 是快枪手,R1 是慢工细活的老匠人。
API 接入
DeepSeek 提供兼容 OpenAI Chat Completions 格式的 API,接入成本极低。
安装依赖
pip install openai # 使用 openai SDK 兼容调用
基础调用示例
from openai import OpenAI
# 初始化客户端,指向 DeepSeek API
client = OpenAI(
api_key="your_deepseek_api_key", # 从 platform.deepseek.com 获取
base_url="https://api.deepseek.com/v1"
)
def call_r1(prompt: str, system: str = None) -> dict:
"""调用 DeepSeek-R1,返回思维链和最终答案"""
messages = []
if system:
messages.append({"role": "system", "content": system})
messages.append({"role": "user", "content": prompt})
response = client.chat.completions.create(
model="deepseek-reasoner", # R1 的模型名称
messages=messages,
)
choice = response.choices[0].message
return {
"thinking": choice.reasoning_content, # 思维链内容
"answer": choice.content, # 最终答案
"usage": response.usage,
}
# 简单测试
result = call_r1("9.11 和 9.9 哪个大?")
print("思维过程:", result["thinking"][:200], "...")
print("最终答案:", result["answer"])
注意 reasoning_content 字段:这是 R1 特有的,存放了模型的「内心独白」。普通对话模型不会返回这个字段。
四类推理任务实测
1. 数学推理
数学是 R1 最亮眼的场景。我们用一道竞赛题测试:
math_prompt = """
证明:对任意正整数 n,以下不等式成立:
1/1 + 1/4 + 1/9 + ... + 1/n² < 2 - 1/n
"""
result = call_r1(math_prompt)
print("=== 数学推理测试 ===")
print(f"思维链长度:{len(result['thinking'])} 字符")
print(f"答案:\n{result['answer']}")
print(f"Token 消耗:输入 {result['usage'].prompt_tokens},输出 {result['usage'].completion_tokens},推理 {result['usage'].reasoning_tokens}")
R1 会在 thinking 阶段用数学归纳法一步步推导,最终给出规范的证明过程。这类问题直接用 V3 经常出现「跳步」或「结论跳跃」的问题。
2. 逻辑推理
logic_prompt = """
五个人(Alice、Bob、Carol、Dave、Eve)站成一排。已知条件:
1. Alice 不在最左边
2. Bob 紧靠 Carol 右边
3. Dave 在 Eve 左边某处
4. Carol 不在最右边
5. Alice 在 Bob 右边某处
请推导出所有可能的排列方式。
"""
result = call_r1(logic_prompt)
print("=== 逻辑推理测试 ===")
print(f"思维链片段:{result['thinking'][:500]}")
print(f"\n最终答案:{result['answer']}")
R1 会在 thinking 阶段穷举所有位置组合,逐条验证约束,最终给出满足全部条件的排列。
3. 代码推理(Debug 场景)
code_debug_prompt = """
下面这段 Python 代码有 bug,请找出所有问题并修复:
```python
def find_duplicates(nums):
seen = {}
duplicates = []
for i, num in enumerate(nums):
if num in seen:
duplicates.append(num)
seen[num] = i
return list(set(duplicates))
# 期望:找出所有重复超过2次的数字
result = find_duplicates([1, 2, 2, 3, 3, 3, 4])
print(result) # 期望输出 [3],实际输出 [2, 3]
请分析 bug 原因,给出修复方案。
"""
result = call_r1(code_debug_prompt)
print("=== 代码推理测试 ===")
print(f"分析过程:{result['thinking'][:400]}...")
print(f"\n修复方案:{result['answer']}")
R1 的 thinking 阶段会逐行追踪变量状态,找出问题:当前代码把「出现过一次以上」的数都算作重复,而不是「出现超过两次」。
### 4. 多步骤规划
```python
planning_prompt = """
我需要将一个 MySQL 数据库从单机迁移到主从架构,数据量约 500GB,业务每天有 200 万次写操作,要求迁移期间停机时间不超过 5 分钟。
请制定详细的迁移方案,包括:回滚计划、风险点识别、每个步骤的时间预估。
"""
result = call_r1(planning_prompt)
print("=== 多步骤规划测试 ===")
print(f"规划思路(前500字):{result['thinking'][:500]}...")
print(f"\n最终方案:{result['answer']}")
提取和使用 thinking tokens
thinking tokens 不只是给人看的,在某些场景下可以二次利用:
def r1_with_thinking_analysis(prompt: str) -> dict:
"""提取 R1 的推理链,做二次分析"""
result = call_r1(prompt)
# 统计推理步骤数(简单按换行分割)
thinking_lines = [
line.strip()
for line in result["thinking"].split("\n")
if line.strip()
]
# 提取关键决策点(包含"因此"、"所以"、"结论"等词的行)
decision_keywords = ["因此", "所以", "结论", "综上", "可以得出", "hence", "therefore"]
key_decisions = [
line for line in thinking_lines
if any(kw in line.lower() for kw in decision_keywords)
]
return {
"answer": result["answer"],
"thinking_length": len(result["thinking"]),
"thinking_steps": len(thinking_lines),
"key_decisions": key_decisions[:5], # 最多展示5个关键决策
"reasoning_tokens": result["usage"].reasoning_tokens,
}
# 示例
analysis = r1_with_thinking_analysis("如何设计一个支持百万并发的消息队列系统?")
print(f"推理链长度:{analysis['thinking_length']} 字符")
print(f"推理步骤数:{analysis['thinking_steps']}")
print(f"消耗推理 tokens:{analysis['reasoning_tokens']}")
print("关键决策点:")
for i, decision in enumerate(analysis['key_decisions'], 1):
print(f" {i}. {decision}")
成本对比:R1 vs V3
DeepSeek 对 thinking tokens 单独计费,实际成本会高于表面定价:
def estimate_cost(usage, model: str) -> float:
"""
估算单次调用成本(人民币)
价格以官网为准,此处为示意
"""
# DeepSeek 官方定价(每百万 token,单位:元)
pricing = {
"deepseek-chat": { # V3
"input": 1.0,
"output": 2.0,
"reasoning": 0, # 无推理 token
},
"deepseek-reasoner": { # R1
"input": 4.0,
"output": 16.0,
"reasoning": 4.0, # thinking tokens 按输入价计费
},
}
p = pricing.get(model, pricing["deepseek-chat"])
cost = (
usage.prompt_tokens / 1_000_000 * p["input"]
+ usage.completion_tokens / 1_000_000 * p["output"]
+ getattr(usage, "reasoning_tokens", 0) / 1_000_000 * p["reasoning"]
)
return round(cost, 6)
# 实际调用后统计成本
result = call_r1("用动态规划解最长公共子序列问题,给出完整代码和复杂度分析")
cost = estimate_cost(result["usage"], "deepseek-reasoner")
print(f"本次调用成本:约 ¥{cost}")
print(f" - 输入 tokens:{result['usage'].prompt_tokens}")
print(f" - 推理 tokens:{result['usage'].reasoning_tokens}")
print(f" - 输出 tokens:{result['usage'].completion_tokens}")
实测数据(参考):
- 简单数学题:推理 tokens ≈ 500-1500,成本 ≈ ¥0.005-0.015
- 复杂证明/规划:推理 tokens ≈ 3000-8000,成本 ≈ ¥0.02-0.05
- 代码 debug:推理 tokens ≈ 1000-3000,成本 ≈ ¥0.01-0.03
适用场景建议
该用 R1 的情况:
- 数学证明、竞赛题、定量推导
- 多约束条件的逻辑推理(排列组合、时序推断)
- 代码 bug 的根因分析(不是简单补全,而是要追踪执行逻辑)
- 复杂系统设计,需要考虑多个权衡因素
- 算法设计,需要证明正确性
用 V3 就够的情况:
- 代码补全、文档生成、注释撰写
- 知识问答、资料整理、内容改写
- 简单的 CRUD 代码生成
- 对话式交互,响应速度优先
- 大批量处理,成本敏感
一个实用的判断标准:如果这个问题让你自己做,你需要打草稿、分步骤推导——那用 R1。如果你能凭经验直接给出答案——用 V3。
笔者在开发 TheRouter 时就实现了类似的自动路由逻辑:根据请求中是否包含数学/证明/复杂推理等关键特征,自动将请求分配到 R1 或 V3,让调用方无需手动判断模型档次。
完整示例:带成本追踪的任务路由
from openai import OpenAI
from enum import Enum
client = OpenAI(
api_key="your_deepseek_api_key",
base_url="https://api.deepseek.com/v1"
)
class ModelTier(Enum):
FAST = "deepseek-chat" # V3:快速、低成本
REASON = "deepseek-reasoner" # R1:深度推理
def smart_call(prompt: str, tier: ModelTier = ModelTier.FAST) -> dict:
"""统一调用接口,自动处理 R1 的 reasoning_content"""
response = client.chat.completions.create(
model=tier.value,
messages=[{"role": "user", "content": prompt}],
)
msg = response.choices[0].message
return {
"answer": msg.content,
"thinking": getattr(msg, "reasoning_content", None),
"usage": response.usage,
}
# 使用示例
tasks = [
("写一个 Python 读取 CSV 文件的函数", ModelTier.FAST),
("证明 sqrt(2) 是无理数", ModelTier.REASON),
("给这段代码加注释:def fib(n): return n if n<2 else fib(n-1)+fib(n-2)", ModelTier.FAST),
("分析以下递归实现的时间复杂度并给出优化方案:...", ModelTier.REASON),
]
for prompt, tier in tasks:
result = smart_call(prompt, tier)
has_thinking = "有" if result["thinking"] else "无"
print(f"[{tier.name}] {prompt[:30]}... → 推理链:{has_thinking},输出 {result['usage'].completion_tokens} tokens")
总结
DeepSeek-R1 的核心价值不是「更聪明」,而是「想得更清楚」。通过显式的推理链条,它在复杂问题上的准确率和可靠性远超直接生成答案的模型。代价是更高的延迟和 token 消耗。
选型建议:先用 V3 快速验证,遇到准确率不够的任务再切到 R1。不要因为 R1「更强」就无脑全用 R1,合理的模型选择才是降本提效的关键。
如有问题欢迎在评论区交流。代码均已在 Python 3.10+ 环境验证。
作者:TheRouter 开发者,专注 AI 模型路由网关。项目主页:therouter.ai