思维链技术(Chain-of-Thought, CoT)

news/2025/4/1 9:18:27/

思维链(Chain-of-Thought, CoT)是一种通过模拟人类逐步推理过程来提升大型语言模型(LLM)复杂任务表现的技术。其核心思想是让模型在生成最终答案前,先输出中间推理步骤,从而增强逻辑性和可解释性。

1. 基础示例:数学问题求解

  • 问题: “罗杰有5个网球,他又买了两盒网球,每盒有3个网球。他现在有多少网球?”
  • 传统Prompting(直接输出答案):模型可能直接输出错误答案(如"27"),因为缺乏中间计算步骤

CoT Prompting(分步推理):

问:罗杰有5个网球,他又买了两盒网球,每盒有3个网球。他现在有多少网球?  
答:罗杰一开始有5个网球,2盒3个网球,一共是2*3=6个网球,5+6=11。答案是11。

2.复杂推理:符号操作任务
问题
“将单词 ‘hello’ 的最后一个字母与 ‘world’ 的最后一个字母拼接起来。”

CoT Prompting:

1. 'hello'的最后一个字母是'o'2. 'world'的最后一个字母是'd'3. 拼接'o''d'得到'od'。  
最终答案:od

3. 零样本思维链(Zero-shot CoT
无需示例,仅通过指令触发推理:
问题
“若A=B+2,B=3*C,C=5,求A的值。”

指令
“让我们一步一步思考:”
模型自动生成:

1. 计算C=52. 计算B=3*5=153. 计算A=15+2=17。  
答案:17

代码示例:
准备数据

import json
import os
from typing import List, Dict, Any# 创建CoT训练数据集
def create_cot_dataset():"""创建包含思维链(CoT)示例的数据集"""cot_examples = [{"instruction": "解决以下数学问题,请一步一步思考。","input": "罗杰有5个网球,他又买了两盒网球,每盒有3个网球。他现在有多少网球?","output": "让我一步一步思考:\n1. 罗杰一开始有5个网球\n2. 他买了两盒网球,每盒有3个网球\n3. 两盒网球总共有2×3=6个网球\n4. 罗杰现在总共有5+6=11个网球\n因此,罗杰现在有11个网球。"},{"instruction": "解决以下数学问题,请一步一步思考。","input": "一个商店以每个15元的价格卖了8个苹果,又以每个10元的价格卖了12个橘子。商店总共赚了多少钱?","output": "让我一步一步思考:\n1. 苹果的收入:8个 × 15元 = 120元\n2. 橘子的收入:12个 × 10元 = 120元\n3. 总收入 = 苹果收入 + 橘子收入 = 120元 + 120元 = 240元\n因此,商店总共赚了240元。"},{"instruction": "解决以下逻辑问题,请一步一步思考。","input": "如果所有的A都是B,所有的B都是C,那么所有的A都是C吗?","output": "让我一步一步思考:\n1. 已知条件:所有的A都是B,所有的B都是C\n2. 对于任何一个A,它一定是B(根据条件1)\n3. 由于它是B,而所有的B都是C(根据条件2),所以这个A也一定是C\n4. 因此,所有的A都是C\n所以,结论\"所有的A都是C\"是正确的。",},{"instruction": "解决以下符号操作问题,请一步一步思考。","input": "将单词'hello'的最后一个字母与'world'的最后一个字母拼接起来。","output": "让我一步一步思考:\n1. 'hello'的最后一个字母是'o'\n2. 'world'的最后一个字母是'd'\n3. 将这两个字母拼接起来,得到'od'\n因此,答案是'od'。"},{"instruction": "解决以下代数问题,请一步一步思考。","input": "若A=B+2,B=3*C,C=5,求A的值。","output": "让我一步一步思考:\n1. 已知C=5\n2. 计算B:B=3*C=3*5=15\n3. 计算A:A=B+2=15+2=17\n因此,A的值是17。"}]# 添加更多复杂的CoT示例more_examples = [{"instruction": "解决以下概率问题,请一步一步思考。","input": "一个袋子里有3个红球和5个蓝球。如果随机抽取两个球,求抽到的两个球都是红球的概率。","output": "让我一步一步思考:\n1. 袋子里总共有3+5=8个球\n2. 第一次抽取红球的概率是3/8\n3. 在第一次抽到红球的情况下,第二次抽取红球的概率是2/7(因为还剩2个红球和5个蓝球)\n4. 两次都抽到红球的概率是(3/8)×(2/7)=6/56=3/28\n因此,抽到的两个球都是红球的概率是3/28。"},{"instruction": "解决以下物理问题,请一步一步思考。","input": "一辆汽车以60千米/小时的速度行驶了2小时,然后以80千米/小时的速度行驶了1小时。求汽车的平均速度。","output": "让我一步一步思考:\n1. 第一阶段:速度60千米/小时,时间2小时,距离=60×2=120千米\n2. 第二阶段:速度80千米/小时,时间1小时,距离=80×1=80千米\n3. 总距离=120+80=200千米\n4. 总时间=2+1=3小时\n5. 平均速度=总距离/总时间=200/3≈66.67千米/小时\n因此,汽车的平均速度约为66.67千米/小时。"}]cot_examples.extend(more_examples)# 保存数据集os.makedirs("d:\\Trae\\develop\\try\\data", exist_ok=True)with open("d:\\Trae\\develop\\try\\data\\cot_dataset.json", "w", encoding="utf-8") as f:json.dump(cot_examples, f, ensure_ascii=False, indent=2)print(f"已创建CoT数据集,包含{len(cot_examples)}个示例")return cot_examplesif __name__ == "__main__":create_cot_dataset()

lora微调

import os
import json
import torch
from transformers import (AutoModelForCausalLM,AutoTokenizer,Trainer,TrainingArguments
)
from datasets import Dataset
from peft import (LoraConfig,get_peft_model,prepare_model_for_kbit_training,TaskType
)def load_cot_dataset(file_path: str):"""加载CoT数据集"""with open(file_path, "r", encoding="utf-8") as f:data = json.load(f)return datadef prepare_dataset_for_lora(examples, tokenizer, max_length: int = 512):"""准备用于LoRA训练的数据集"""formatted_examples = []for example in examples:# 格式化为指令微调格式formatted_text = f"指令: {example['instruction']}\n问题: {example['input']}\n回答: {example['output']}"formatted_examples.append({"text": formatted_text})# 创建数据集dataset = Dataset.from_list(formatted_examples)# 对数据集进行分词处理def tokenize_function(examples):return tokenizer(examples["text"],padding="max_length",truncation=True,max_length=max_length,return_tensors="pt")tokenized_dataset = dataset.map(tokenize_function,batched=True,remove_columns=["text"])# 划分训练集和验证集tokenized_dataset = tokenized_dataset.train_test_split(test_size=0.1)return tokenized_datasetdef train_cot_with_lora():"""使用LoRA方法微调模型以学习CoT推理"""# 加载预训练模型和分词器model_name = "THUDM/chatglm3-6b"  # 可以替换为其他中文模型print(f"加载模型: {model_name}")tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)model = AutoModelForCausalLM.from_pretrained(model_name,trust_remote_code=True,torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,load_in_8bit=True if torch.cuda.is_available() else False)# 准备模型进行LoRA微调if torch.cuda.is_available():model = prepare_model_for_kbit_training(model)# 配置LoRAlora_config = LoraConfig(task_type=TaskType.CAUSAL_LM,r=8,  # LoRA的秩lora_alpha=32,lora_dropout=0.1,target_modules=["query_key_value"],  # 根据模型架构调整bias="none",)# 应用LoRA配置model = get_peft_model(model, lora_config)print(f"可训练参数数量: {model.print_trainable_parameters()}")# 加载CoT数据集cot_examples = load_cot_dataset("d:\\Trae\\develop\\try\\data\\cot_dataset.json")print(f"加载了{len(cot_examples)}CoT示例")# 准备训练数据集tokenized_dataset = prepare_dataset_for_lora(cot_examples, tokenizer)# 设置训练参数training_args = TrainingArguments(output_dir="d:\\Trae\\develop\\try\\cot_lora_model",overwrite_output_dir=True,num_train_epochs=3,per_device_train_batch_size=4,  # 使用LoRA可以用更大的批量per_device_eval_batch_size=4,gradient_accumulation_steps=4,evaluation_strategy="steps",eval_steps=50,save_strategy="steps",save_steps=50,save_total_limit=3,learning_rate=1e-4,weight_decay=0.01,warmup_steps=50,logging_dir="d:\\Trae\\develop\\try\\logs",logging_steps=10,fp16=torch.cuda.is_available(),report_to="none",)# 创建训练器trainer = Trainer(model=model,args=training_args,train_dataset=tokenized_dataset["train"],eval_dataset=tokenized_dataset["test"],)# 开始训练print("开始LoRA训练...")trainer.train()# 保存模型model.save_pretrained("d:\\Trae\\develop\\try\\cot_lora_model\\final")tokenizer.save_pretrained("d:\\Trae\\develop\\try\\cot_lora_model\\final")print("LoRA训练完成,模型已保存")if __name__ == "__main__":train_cot_with_lora()

推理

import torch
from transformers import AutoModelForCausalLM, AutoTokenizerdef load_cot_model(model_path: str):"""加载训练好的CoT模型"""tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)model = AutoModelForCausalLM.from_pretrained(model_path,trust_remote_code=True,torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32)return model, tokenizerdef generate_cot_response(model, tokenizer, instruction: str, problem: str, max_length: int = 1024):"""使用CoT模型生成包含推理步骤的回答"""# 构建输入提示prompt = f"指令: {instruction}\n问题: {problem}\n回答:"# 生成回答inputs = tokenizer(prompt, return_tensors="pt").to(model.device)outputs = model.generate(inputs.input_ids,max_length=max_length,temperature=0.7,top_p=0.9,do_sample=True,num_return_sequences=1)# 解码回答response = tokenizer.decode(outputs[0], skip_special_tokens=True)# 提取回答部分response = response.split("回答:")[1].strip() if "回答:" in response else responsereturn responsedef test_cot_model():"""测试CoT模型的推理能力"""# 加载模型model_path = "d:\\Trae\\develop\\try\\cot_model\\final"model, tokenizer = load_cot_model(model_path)model.to("cuda" if torch.cuda.is_available() else "cpu")model.eval()# 测试问题test_problems = [{"instruction": "解决以下数学问题,请一步一步思考。","problem": "小明有12个苹果,他给了小红3个,又给了小李2个,然后自己吃了1个。小明还剩下多少个苹果?"},{"instruction": "解决以下逻辑问题,请一步一步思考。","problem": "如果今天不是周一,那么明天不是周二。今天是周三,那么明天是周几?"},{"instruction": "解决以下代数问题,请一步一步思考。","problem": "若x+y=10且xy=21,求x²+y²的值。"}]# 对每个问题生成回答for i, test in enumerate(test_problems):print(f"\n测试 {i+1}:")print(f"指令: {test['instruction']}")print(f"问题: {test['problem']}")response = generate_cot_response(model, tokenizer, test['instruction'], test['problem'])print(f"回答:\n{response}")print("-" * 50)if __name__ == "__main__":test_cot_model()

http://www.ppmy.cn/news/1584352.html

相关文章

强大的AI网站推荐(第四集)—— Gamma

网站:Gamma 号称:展示创意的新媒介 博主评价:快速展示创意,重点是展示,在几秒钟内快速生成幻灯片、网站、文档等内容 推荐指数:🌟🌟🌟🌟🌟&#x…

[c++项目]基于微服务的聊天室服务端测试

项目概述 本测试报告针对基于C实现的微服务架构聊天室服务端进行全面测试。系统主要包含以下微服务: 用户认证服务(Auth Service)消息处理服务(Message Service)在线状态服务(Presence Service&#xff0…

python下载m3u8格式视频

一、安装 m3u8库 pip install requests pip install requests m3u8 二、编码实现 import os import re import requests import subprocess# 下载ts文件 def down_ts_file(base_url, m3u8_url, download_dir):# 从m3u8文件中获取所有ts的分片名称信息response requests.get…

【区块链安全 | 第十篇】智能合约概述

部分内容与前文互补。 文章目录 一个简单的智能合约子货币(Subcurrency)示例区块链基础交易区块预编译合约 一个简单的智能合约 我们从一个基础示例开始,该示例用于设置变量的值,并允许其他合约访问它。 // SPDX-License-Identi…

STM32F103_LL库+寄存器学习笔记11 - 串口收发的中断优先级梳理

导言 推荐的STM32 USARTDMA 中断优先级设置(完整方案): 以你的STM32F103 USART1 DMA实例为例: 推荐中断优先级设置中断优先级USART1空闲中断(接收相关)优先级0DMA1通道5接收中断(半满/满传输…

杂草YOLO系列数据集4000张

一份开源数据集——杂草YOLO数据集,该数据集适用于农业智能化、植物识别等计算机视觉应用场景。 数据集详情 ​训练集:3,664张高清标注图像​测试集:180张多样性场景样本​验证集:359张严格筛选数据 下载链接 杂草YOLO数据集分…

还款测试案例需要考虑的维度

还款测试案例需要考虑的维度主要包括以下几个方面‌: ‌正常还款流程‌:验证用户是否能正常登录系统,查看还款计划,选择正确的还款账户,输入还款金额,确认还款信息,并执行还款操作。同时&#x…

Python爬虫教程003:请求对象的定制、get请求的quote和urlencode方法

2.4 请求对象的定制 在 Python 爬虫中,User-Agent(UA)反爬是指网站通过检测请求头中的 User-Agent 来识别并屏蔽爬虫。许多网站会检查 UA 是否是常见的爬虫(如 Python-urllib 或 Scrapy),并拒绝非浏览器的…