Uses
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "/root/app/Reason/checkpoints"
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
from typing import List, Dict
def new_apply_chat_template(history:List[Dict[str, str]], add_reasoning_generation_prompt:bool=True, add_assistant_generation_prompt:bool=False):
if add_reasoning_generation_prompt:
return "".join([f"<|im_start|>{i['role']}\n{i['content']}<|im_end|>\n" for i in history]) + "<|im_start|><|reasoning|>\n"
if add_assistant_generation_prompt:
return "".join([f"<|im_start|>{i['role']}\n{i['content']}<|im_end|>\n" for i in history]) + "<|im_start|>assistant\n"
from IPython.display import Markdown, display
device = "cuda"
history = []
history.append({"role": "system", "content": "You are a helpful assistant"})
while True:
question = input('User:' + '\n')
print(question)
print('\n')
history.append({"role": "user", "content": question})
input_text = new_apply_chat_template(
history,
add_reasoning_generation_prompt=True
)
model_inputs = tokenizer([input_text], return_tensors="pt").to(device)
if model_inputs.input_ids.size()[1]>32000:
break
generated_ids = model.generate(
model_inputs.input_ids,
max_new_tokens=3000
)
if len(generated_ids)>32000:
break
generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)]
reasoning_response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
history.append({"role": "<|reasoning|>", "content": reasoning_response})
print('reasoning:\n')
#print(response)
display(Markdown(reasoning_response))
print("------------")
print('\n')
input_text = new_apply_chat_template(
history,
add_assistant_generation_prompt=True
)
model_inputs = tokenizer([input_text], return_tensors="pt").to(device)
if model_inputs.input_ids.size()[1]>32000:
break
generated_ids = model.generate(
model_inputs.input_ids,
max_new_tokens=3000
)
if len(generated_ids)>32000:
break
generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)]
assistant_response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
history.append({"role": "assistant", "content": assistant_response})
print('assistant:\n')
display(Markdown(assistant_response))
print("------------")
print("超过模型字数上线,已退出")
在模型中加入 <|reasoning|>
特殊标记:
- 训练数据格式修改
- 在
prepare_conversation_template
方法中,对话模板增加了 reasoning 部分 - 对话流程变成: system → user → reasoning → assistant
- 这让模型能够学习到推理过程和最终答案之间的关系
- 模型架构变化
- 通过
add_special_tokens
方法添加了新的特殊标记<|reasoning|>
- 扩展了模型的词表大小(通过
resize_token_embeddings
) - 让模型能够识别和生成这个特殊标记
- 训练目标的改变
- 模型不仅要学习生成答案,还要学习生成推理过程
- 在
create_answer_mask
中,模型需要同时预测 reasoning 和 assistant 部分
- 推理能力增强
- 模型被训练去显式地展示推理过程
- 有助于生成更可解释的答案
- 可以帮助模型形成更结构化的思维链路
让模型在回答问题时不仅给出答案,还能展示推理过程,提高模型回答的可解释性和可靠性。
与不改变词表的本质区别在于:
- 不改词表的方式:
<|reasoning|>
会被拆分成普通token序列来处理- 模型将其视为普通文本,类似于看到 "reasoning" 这个词
- 占用更多token位置(因为被拆分)
- 没有特殊的语义表示学习
- 添加到词表的方式:
<|reasoning|>
作为单个特殊token处理- 模型可以学习到这个标记专门的语义表示
- 只占用一个token位置
- 能够建立独特的语义空间
具体影响:
# 假设tokenizer编码示例
# 不加入词表:
"<|reasoning|>" -> [1234, 5678, 9012] # 被拆分成多个基础token
# 加入词表:
"<|reasoning|>" -> [32000] # 单个特殊token
从训练效果看:
- 加入词表能让模型更好地识别和区分推理部分的边界
- 不加入词表依然可以起到标记作用,但模型需要从上下文学习这种模式
- 加入词表的方式通常效果更好,因为给了模型更明确的语义信号
- Downloads last month
- 27