阿里巴巴新推出的Qwen3支持一个有意思的功能:混合推理。
混合推理实际上就是让模型能够同时实现“思考”与“非思考”的切换。
- 思考模式:模型能够逐步思考问题,模拟人类解决复杂问题时的思考过程。有利于模型解决复杂的推理问题,但耗时长、消耗token多。
- 非思考模式:模型能够直接产生回复,旨在提供更快速、更直接的响应。这非常适合那些答案相对直接、不需要冗长推理过程的场景,例如简单的问答、快速信息检索或常规对话。
Qwen3实现混合推理的关键在于,用一段空白的思考内容替代原始模型需要输出的思考,“欺骗”模型已经完成了思考,从而直接生成回复,跳过思考内容。这是一个非常简单又极为巧妙的方法。
那么这种混合推理的形式也应该能够迁移到DeepSeek中。
接下来,本文将会以transformers部署的DeepSeek-R1-1.5B模型为例,实现DeepSeek的混合推理。
下面是一份能够实现多轮对话的DeepSeek部署代码:
# 消息管理
messages = []
while True:
# 提示词
prompt = input('\n>>> ')
if prompt == '/bye':
break
messages.append({'role': 'user', 'content': prompt})
# 将消息记录转为模板格式
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
# 对将消息记录进行向量化
model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
# 生成内容
generated_ids = model.generate(
**model_inputs,
max_new_tokens=512,
)
# 截取输出部分
generated_ids = [
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
# 响应内容
text_output = tokenizer.batch_decode(generated_ids)[0]
if "</think>" in text_output:
response = "<think>\n" + text_output
else:
response = "<think>\n\n</think>" + text_output
print(response)
# 将响应内容添加到消息记录
messages.append({'role': "assistant", 'content': response})
我们可以对代码进行测试,测试对话如下:
>>> 你是谁
<think>
您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-R1。如您有任何任何问题,我会尽我所能为您提供帮助。
</think>
您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-R1。如您有任何任何问题,我会尽我所能为您提供帮助。<|end▁of▁sentence|>
当询问:“你是谁”时,DeepSeek输出了相应的思考内容(<think>标签中的内容),并在思考完成后给出了回复内容。
实现混合推理
我们的目的是尝试使用Qwen3的思路,让DeepSeek-R1跳过思考的过程,我们只需要添加下面的一行代码,就可以实现让DeepSeek-R1跳过思考:
text += "\n\n</think>"
将消息记录转为模板格式后,为模板添加一个空白的思考过程,就能够“骗过”模型,跳过思考,具体的代码为:
# 将消息记录转为模板格式
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
text += "\n\n</think>"
# 对将消息记录进行向量化
model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
再次向DeepSeek询问“你是谁”
>>> 你是谁
<think>
</think>
您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-R1。如您有任何任何问题,我会尽我所能为您提供帮助。<|end▁of▁sentence|>
跟预期一致,DeepSeek跳过了思考过程,直接产生了回复。
效果测试
那么这种方式的效果如何?我们通过一个简单的问题来测试一下:
问题:弟弟今年3岁了,姐姐的年龄是弟弟的2倍,当弟弟79岁时,姐姐将是多少岁?
正确答案:姐姐比弟弟大三岁,姐姐为82岁。
在思考模式下:
>>>弟弟今年3岁了,姐姐的年龄是弟弟的2倍,当弟弟79岁时,姐姐将是多少岁?
<think>
首先,弟弟今年3岁,姐姐的年龄是弟弟的2倍,因此姐姐今年6岁。
假设过了x年,弟弟79岁,那么x年等于79减去3,也就是76年。
同样,姐姐在这76年中也会增加76岁,因此姐姐那时的年龄将是6加上76,等于82岁。
所以,当弟弟79岁时,姐姐将是82岁。
</think>
**解答:**
1. **确定弟弟和姐姐的年龄关系:**
- 弟弟今年3岁。
- 姐姐的年龄是弟弟的2倍,因此姐姐今年的年龄是:
\[
3 \times 2 = 6 \text{岁}
\]
2. **计算弟弟从3岁到79岁所需的时间:**
\[
79 - 3 = 76 \text{年}
\]
3. **计算姐姐在这76年后的年龄:**
\[
6 + 76 = 82 \text{岁}
\]
**最终答案:**
\[
\boxed{82}
\]<|end▁of▁sentence|>
DeepSeek通过一步一步的思考,正确理解了问题,做出了正确回答。
在非思考模式下:
>>>弟弟今年3岁了,姐姐的年龄是弟弟的2倍,当弟弟79岁时,姐姐将是多少岁?
<think>
</think>
当弟弟79岁时,姐姐的年龄将是158岁。这是因为姐姐的年龄是弟弟年龄的两倍,无论弟弟何时长大,姐姐的年龄始终是弟弟年龄的两倍。<|end▁of▁sentence|>
模型误以为姐姐的年龄始终是弟弟的两倍,给出了离谱的错误答案。
对于DeepSeek-R1来说,其本身就是一个思考模型,并没有针对非思考模式进行额外的优化,因此其混合推理的效果可能不如Qwen3。而且DeepSeek无法实现Qwen3的软切换(使用“/think”与“/no_think”)。但Qwen3这种切换思考模式的方法,确实是一种值得学习的巧妙方法。