
解锁用户偏好:用微软的 Phi-4 Slm 和 Unsloth 三步预测反应
聊天机器人竞技场
聊天机器人竞技场¹是由加州大学伯克利分校天空计算实验室开发的平台,旨在通过匿名、随机的对战来基准测试和比较大型语言模型(LLMs)。它采用众包的方法,用户可以提问并为他们偏好的回答投票。
例如,考虑这个场景:一个用户向LLMs(例如,ChatGPT、Claude.ai、Llama等)提问,并返回两个不同的回答。用户会选择和偏好哪一个回答?
这是一个有趣的问题,因为它交叉了机器学习和行为心理学。为了以合理的成功率预测用户选择,预测模型必须分析用户行为和偏好的模式。
Phi-4²,微软的新14B模型,其性能与开放人工智能的GPT-4o-mini相当,现在已经可用。因此,值得探索Phi-4理解文本内容并基于此进行分析的能力。我们将使用Phi-4来分析实际用户问题,请它评估两个响应选项,并生成我们可以稍后用来通过微调改进模型的新特征。
我们特别使用unsloth³库,因为它提供了Phi-4的优化版本,使您可以在本地机器或谷歌Colab上更快、更少内存地生成和微调模型。这个库在本教程系列的第二部分特别有用,我们将在本帖中使用生成的特征来改进用户最有可能从提示中选择的响应的预测。
教程系列概述
本文是三部分系列的第一部分。在这篇文章中,我们将重点介绍如何使用Phi-4模型和unsloth生成新特征。第二篇文章将介绍如何利用这些特征高效地微调模型,同样使用unsloth。在最后一篇文章中,我们将演示如何使用微调后的模型对新提示进行推理,特别是预测用户更喜欢响应A还是响应B。
我们在这第一篇文章中将涵盖的内容
在这第一篇文章中,我们将重点关注以下关键步骤:
- 安装、设置和加载 Phi-4 模型与 unsloth。
- 根据定义的标准 制作提示指令。
- 使用提示指令 准备数据集。
- 请求 Phi-4 模型 为新特征生成文本。
- 实时流式传输 生成的文本并将其保存为 csv 文件。
安装、初始设置和模型加载
安装非常简单。您可以使用 pip 安装最新版本的 unsloth:
!pip install unsloth
!pip install --force-reinstall --no-cache-dir --no-deps git+https://github.com/unslothai/unsloth.git
我在谷歌Colab上运行这个,安装只需几分钟。安装完成后,初始设置通过从 unsloth 库和 PyTorch 导入 FastLanguageModel 开始。它配置了关键参数,包括最大序列长度为 2048,并且我们将使用 4位量化选项来减少内存使用。
from unsloth import FastLanguageModel
import torch
max_seq_length = 2048
load_in_4bit = True
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/Phi-4",
max_seq_length = max_seq_length,
load_in_4bit = load_in_4bit,
)
如果成功加载,您将看到类似下面的输出:
🦥 Unsloth: Will patch your computer to enable 2x faster free finetuning.
🦥 Unsloth Zoo will now patch everything to make training faster!
\==((====))== Unsloth 2025.1.5: Fast Llama patching. Transformers: 4.47.1.
\\\\ /| GPU: NVIDIA A100-SXM4-40GB. Max memory: 39.564 GB. Platform: Linux.
O^O/ \\\_/ \\ Torch: 2.5.1+cu121. CUDA: 8.0. CUDA Toolkit: 12.1. Triton: 3.1.0
\\ / Bfloat16 = TRUE. FA [Xformers = 0.0.29.post1. FA2 = False]
"-____-" Free Apache license: http://github.com/unslothai/unsloth
Unsloth: Fast downloading is enabled - ignore downloading bars which are red colored!
制作您的提示指令
接下来,我们将制作实际的提示,以便使用 Phi-4 来分析用户提出的问题。在此过程中,我们还需要为大型语言模型(LLMs)提供两个响应选项。Phi-4 将根据某些标准分析内容,并预测用户最可能选择哪个响应。总之,我们需要将以下输入提供给 Phi-4 大型语言模型(LLMs):
- 用户提出的查询/问题/提示。
- 响应选项 A 的文本内容。
- 响应选项 B 的文本内容。
- 目标/标签(用户选择的响应:响应 A 或 B)。
在实践中,我们需要将用户查询、响应和提示组合成一个单一的消息,以便发送给 Phi-4,如下所示。
messages = [
{
........ [code to be added later here]
f"Query:\\n{row['prompt']}\\n\\n"
f"Response A:\\n{row['response_a']}\\n\\n"
f"Response B:\\n{row['response_b']}\\n"
},
]
准备数据集
为了演示,我们将要求 Phi-4 根据 4 个不同的标准生成四个新特征。当然,您可以根据其他标准添加任意数量的特征。这些特征包括:
-
why_response_a
: 用户选择响应 A 而不是响应 B 的关键因素。 -
why_response_b
: 用户选择响应 B 而不是响应 A 的关键因素。 -
strongest_factor_a
: 可能导致用户偏好响应 A 的单一最强因素。 -
strongest_factor_b
: 可能导致用户偏好响应 B 的单一最强因素。
因此,我们将向我们的消息中附加一个新的提示指令,以便将其组合为 Phi-4 的单个提示,如下所示:
messages = [
{
"role": "user",
"content": (
"You are a judge with expertise in machine learning and behavioral psychology, specializing in analyzing user responses to given prompts. "
"Your task is to evaluate the provided query and responses to determine which response the user is most likely to choose based on patterns in user behavior and preferences. "
"Carefully analyze the reasoning behind each potential choice and populate the following four variables step-by-step:\\n\\n"
"1. **why_response_a**: Summarize all key points as bullet points as to why the user might choose Response A over Response B.\\n"
"2. **why_response_b**: Summarize all key points as bullet points as to why the user might choose Response B over Response A.\\n"
"3. **strongest_factor_a**: Summarize in one bullet point the single strongest factor that could lead the user to prefer Response A.\\n"
"4. **strongest_factor_b**: Summarize in one bullet point the single strongest factor that could lead the user to prefer Response B.\\n\\n"
"**Instructions**:\\n"
"- Think critically and systematically before addressing each variable.\\n"
"- Consider the nuances of user behavior, preferences, and contextual influences in your analysis.\\n"
"- Present your findings in a structured format, and conclude with your recommendation: either 'Response A' or 'Response B'.\\n\\n"
"**Respond with the following structured output**:\\n"
"```\\n"
"why_response_a: [bullet points here]\\n"
"why_response_b: [bullet points here here]\\n"
"strongest_factor_a: [Your strongest factor as a bullet point for Response A here]\\n"
"strongest_factor_b: [Your strongest factor as a bullet point for Response B here]\\n"
f"Query:\\n{row['prompt']}\\n\\n"
f"Response A:\\n{row['response_a']}\\n\\n"
f"Response B:\\n{row['response_b']}\\n"
),
}
]
如前所述,这四个标准在此帖子的演示中被选中,但请随意添加或删除您认为可能相关的其他标准。
接下来,我们将从 csv 文件中读取数据,并提取每一行的相关列。这些列包括提示、响应 A、响应 B 和目标/标签/赢家。然后,我们将把提取的数据输入到消息中,顺序处理数据框的每一行。
import pandas as pd
file_path = "/content/drive/MyDrive/2025/Phi4/train.csv"
df = pd.read_csv(file_path)
datasets = []
遍历数据框的行
for _, row in df.iterrows():
# 动态构建消息
messages = [
{
"role": "user",
"content": (
"您是一位在机器学习和行为心理学方面具有专业知识的评审,专门分析用户对给定提示的响应。 "
"您的任务是评估提供的查询和响应,以确定用户最有可能根据用户行为和偏好的模式选择哪个响应。 "
"仔细分析每个潜在选择背后的推理,并逐步填充以下四个变量:\n\n"
"1. **why_response_a**: 总结用户可能选择响应A而非响应B的所有关键点,以项目符号形式列出。\n"
"2. **why_response_b**: 总结用户可能选择响应B而非响应A的所有关键点,以项目符号形式列出。\n"
"3. **strongest_factor_a**: 用一个项目符号总结可能导致用户偏好响应A的单一最强因素。\n"
"4. **strongest_factor_b**: 用一个项目符号总结可能导致用户偏好响应B的单一最强因素。\n\n"
"**说明**:\n"
"- 在处理每个变量之前,进行批判性和系统性的思考。\n"
"- 在分析中考虑用户行为、偏好和上下文影响的细微差别。\n"
"- 以结构化格式呈现您的发现,并以您的推荐结束:'响应A'或'响应B'。\n\n"
"**请用以下结构化输出进行回复**:\n"
"```\n"
"why_response_a: [在此处列出要点]\n"
"why_response_b: [在此处列出要点]\n"
"strongest_factor_a: [您对响应A的最强因素作为项目符号在此处]\n"
"strongest_factor_b: [您对响应B的最强因素作为项目符号在此处]\n"
"Recommendation: [您的最终推荐:响应A或响应B]\n"
f"Query:\n{row['prompt']}\n\n"
f"Response A:\n{row['response_a']}\n\n"
f"Response B:\n{row['response_b']}\n"
),
}
]
[…]
将结果作为字典附加到列表中
datasets.append({
'id': row['id'], # Include the id from the DataFrame
'prompt': row['prompt'],
'response_a': row['response_a'],
'response_b': row['response_b'],
'generated_text': generated_text
})
这段代码执行多个步骤来处理数据并生成新特征。
首先,它将 train.csv
文件加载到一个数据框中,该数据框作为进一步处理的输入数据集。
然后,代码使用 iterrows()
遍历数据框的每一行。对于每一行,它提取 prompt
、response_a
、response_b
和 winner
(目标/标签)的值。这些值以及 Phi-4 的特定指令被组合成一个单一的提示(称为 messages
)。
在每次迭代中,从 query
、response_a
和 response_b
列中提取内容并填充到提示指令中。这个组合的提示随后作为输入传递给 Phi-4,生成新特征(代码中尚未显示)。在每次迭代后,生成的特征(generated_text
)被添加到一个列表中,该列表在每一步都被更新。
Ask Phi-4 LLM to Generate Text for New Features
现在缺少的部分是将每个提示消息在每次迭代中传递给Phi-4模型。我们只需将messages
变量传递给tokenizer.apply_chat_template()
函数,如下所示:
inputs = tokenizer.apply_chat_template(
messages,
tokenize=True,
add_generation_prompt=True,
return_tensors="pt",
).to("cuda")
tokenize=True
选项确保文本被转换为令牌ID,这些是模型处理的数字输入。输出被准备为PyTorch张量(return_tensors="pt"
),并转移到GPU(.to("cuda")
)以加快计算速度。
_ = model.generate(
input_ids=inputs,
streamer=capture_streamer,
max_new_tokens=2000,
use_cache=True,
temperature=0.0,
)
接下来,调用model.generate
函数以生成我们所需的特征文本。inputs
被传递给input_ids
,而max_new_tokens=2000
参数指定模型可以生成的最大令牌数量,以防止输出过长。use_cache=True
设置提高了计算效率,temperature=0.0
确保结果是确定性的,这意味着模型对于相同的输入将始终产生相同的输出。
实时流式文本输出并保存为csv文件
正如您可能注意到的,从大型语言模型(LLMs)生成文本在配备消费级GPU的本地机器上通常会很慢,这就是为什么在生成文本的同时流式输出可能更可取,而不是等到最后再等待整个文本的生成。您可能在像聊天机器人竞技场这样的工具中观察到了这种行为。
为了启用此功能,我们使用CaptureStreamer
,这是一个自定义类,扩展了transformers
库中的TextStreamer
类。这个类充当收集器,收集模型生成的文本块。CaptureStreamer
在流式传输时捕获Phi-4的输出,使得程序化存储和处理生成的文本变得更加容易。该类以一个空字符串初始化以存储捕获的文本,每个生成的文本片段通过on_finalized_text
方法逐步添加。在每次迭代中,捕获的文本存储在captured_output
变量中。
class CaptureStreamer(TextStreamer):
def __init__(self, tokenizer, skip_prompt=True):
super().__init__(tokenizer, skip_prompt=skip_prompt)
self.captured_output = ""
def on_finalized_text(self, text: str, stream_end: bool = False):
"""
Override the on_finalized_text method to accumulate all text.
"""
self.captured_output += text
您可以在迭代循环中按如下方式调用此函数:
generated_text = capture_streamer.captured_output
我们现在拥有了从Phi-4生成文本的完整代码。如果一切正常,您应该会看到类似于下面示例的输出:
正如您所观察到的,Phi-4为我们在提示指令中定义的四个标准(即why_response_a、why_response_b、strongest_factor_a和strongest_factor_b)填充内容。例如,响应A因其具体性、代码示例、真实细节和对官方文档的引用而受到青睐。另一方面,用户可能更喜欢响应B,因为它涵盖全面、提供一般性指导和结构化步骤。此外,您将注意到,Phi-4将响应A的最强因素识别为其详细的、特定语言的代码示例,而响应B的最强因素是其广泛的语言覆盖。
最后,在循环迭代结束时,生成的特征作为新列添加到数据框中并保存为CSV文件,以便于在未来步骤中解析和微调。我们将在本系列教程的下一部分中使用此CSV文件进一步改进模型。
df.to_csv("synthetic_features.csv", index=False)
摘要
在这篇文章中,我概述了从给定查询或提示生成新特征所需的步骤。在本教程系列的第二部分中,我将带您了解如何从csv文件中解析生成的特征,并使用它们来微调Phi-4模型。通过微调Phi-4,我们的目标是创建一个能够准确预测用户对提示/查询响应的Phi-4模型。
参考文献
- 聊天机器人竞技场(前称 LMSYS):免费 AI 聊天以比较和测试最佳 AI 聊天机器人:https://lmarena.ai/
- 介绍 Phi-4:微软最新的小型语言模型,专注于复杂推理:https://techcommunity.microsoft.com/blog/aiplatformblog/introducing-phi-4-microsoft%E2%80%99s-newest-small-language-model-specializing-in-comple/4357090
- unsloth:https://unsloth.ai/