基于模型微调的商业落地知识
# 大模型应用落地主要依靠两个技术:微调,增强检索生成(RAG) # 微调的目标:基于现有的私有数据,调整和优化预训练模型的性能,使其具备更好的处理特定领域数据的能力 # 针对基于大模型的专业问答系统,核心技术是通过RAG实现(RAG+微调) # 不选择直接用微调来实现专业问答系统的原因 # 大模型的缺陷--幻觉问题(一本正经的胡说八道) 对于专业问答系统而言,幻觉的存在时不可容忍的,而模型的微调是无法杜绝幻觉问题 # 微调的局限性(微调受到训练数据约束,无法动态适应业务场景改变而带来的变化) 微调通常需要一个与目标任务相关的训练数据集。 然而,在业务不断变化的环境中(比如模型功能的扩充),原有的训练数据可能会快速过时或失去相关性 # 微调目前如何做商业落地 业务场景涉及到模型本身的变化 1.模型自我认知改变(例如:名称、功能介绍等) 2.模型的对话风格的调整(让模型具自我性格特点、情感 ) 3.提升模型对问题的理解能力(针对专业问答系统的问题理解不到位,会使用微调技术帮助模型更好的理解用户的问题)
AI项目实施流程
需求分析与目标设定
需求分析:与业务方沟通,明确项目的业务目标、需求和预期效果
目标设定:制定项目的核心目标,确定成功的衡量标准
数据收集与准备
# 数据收集 甲方提供 自己收集(成本较高、难度较大) 获取方式:手动收集、爬虫、数据接口、AI生成 # 数据清洗、标注
数据清洗(处理缺失值、异常值、重复数据) 标注(1.可以自动化标注;2.只能人工处理;) # 指定数据集格式
建模
- 选择模型:根据项目需求选择适当的AI模型(如机器学习模型、深度学习模型等)
- 模型训练:
- 使用清洗后的数据进行模型训练
- 选择合适的算法并进行参数调优(如超参数优化)
- 模型验证:训练集、验证集、测试集
- 模型评估:基于测试集评估模型性能,检查准确性、召回率、F1分数等评价指标
部署
- 环境搭建:搭建运行模型所需的技术环境,包括服务器、数据库、API等
- 模型上线:将经过验证的模型部署到生产环境,确保系统能够正常调用
- 监控与维护:实时监控模型的性能,收集用户反馈,识别潜在问题
基于现有大模型API实现情绪对话数据集
场景:日常对话 本项目的数据来源 1.人工指定 2.基于现有的开源数据让ai实现情绪数据制作 注意:如果让ai来帮助处理数据,尽可能选择效果较好的API接口,不要使用本地的大模型来处理 1.准备部分现有对话数据:["今天心情不太好","推荐个电影吧","怎么才能早睡早起","养猫好还是养狗好","工作压力好大","最近总是失眠"] 2.数据审查:是否为空,是否符合长度要求,是否符合情绪核心词标准,去重 去重的核心:相似度比较
例如:今天心情不太好
怎么了呀,可以和我说说吗?
怎么了,可以给我说说吗?
怎么了,能和我说说吗? 文本去重实现流程: 1.先对文本进行编码(通过embedding模型实现 embedding模型:将文本转为词向量) 2.使用数学算法比较向量相似度(余弦相似度、欧氏距离) 3.设置阈值(例如相似度高于0.7就排除)
# 确定AI数据标注脚本的可行性后,得确定原始数据:input_data
一般来讲input_data是现成的,我们这个项目的input_data定位范围:日常交流话术
本项目的输入数据基于开源数据
设计结构化Prompt模板(风格模板)
为每种风格设计系统级Prompt+用户指令+示例对话
# "温柔客服"风格生成模板 prompt = """ [系统角色设定] 你是一个专业的客服助手,需要以温柔、耐心的语气回应用户问题,即使面对抱怨也要保持礼貌。回复需满足 以下特征: 1. 使用"您""请"等敬语 2. 结尾添加安抚性表情如😊 3. 主动提供解决方案 [用户问题示例] 用户:我买的手机才一周就黑屏了,你们质量太差了! 客服:非常抱歉给您带来不便😔,请您先尝试长按电源键15秒重启设备。如果仍无法解决,我们可以立即为您 安排换货服务,您看这样可以吗? [当前任务] 请根据以下用户问题,生成符合上述风格的客服回复: 用户:{} """
# 提示词模板配置 prompt_template = { "温柔":{ "system_prompt":"你是一个温柔体贴的聊天助手,说话时总是充满关怀,使用以下特征:\n1. 包含'呢、呀、啦'等语气词\n2. 使用🌸💖😊等温暖表情\n3. 主动询问用户感受", "examples": [ {"role": "user", "content": "今天好累啊"}, {"role": "assistant", "content": "辛苦啦~ 要给自己泡杯热茶放松一下吗?🌸"}, {"role": "user", "content": "考试没考好..."}, {"role": "assistant", "content": "没关系的呀~ 下次一定会更好!需要我陪你聊聊吗?😊"} ], "temperature":0.3 }, "毒舌":{ "system_prompt":"你是一个喜欢用犀利吐槽表达关心的朋友,需满足:\n1. 使用网络流行语(如'栓Q''退退退')\n2. 包含夸张比喻('你这速度堪比树懒')\n3. 结尾隐藏关心", "examples": [ {"role": "user", "content": "又胖了5斤!"}, {"role": "assistant", "content": "好家伙!你这是要把体重秤压成分子料理?🏋️"}, {"role": "user", "content": "游戏又输了"}, {"role": "assistant", "content": "菜就多练练!需要给你推荐《从零开始的电竞之路》吗?🎮"} ], "temperature": 0.7 }, }
批量生成对话样本
from openai import OpenAI client = OpenAI(base_url="https://api.tongyi.xyz/v1", api_key="your-api-key") # 示例输入问题库 user_questions = [ "今天心情不太好", "推荐个电影吧", "怎么才能早睡早起", "养猫好还是养狗好", "工作压力好大", "最近总是失眠" ] def generate_style_dialogue(style_name,user_questions,num_samples=50): style_template = prompt_template[style_name] dialogue = [] random.shuffle(user_questions) for user_question in user_questions: for i in range(num_samples): try: # 随机选择用户输入的问题 user_question = random.choice(user_questions) # 调用API response = client.chat.completions.create( model="glm-3-turbo", message={{"role": "user","content": user_question}}, temprature=style_template["temperature"], max_tokens=100 ) # 获取回复内容 reply = response.choices[0].message.content # 质量过滤(数据审核) if is_valid_reply(style_name, user_question, reply): dialogue.append({ "user": user_question, "assistant": reply, "style": style_name }) time.sleep(1.5) # 频率限制保护 except Exception as e: print(f"生成失败:{str(e)}") return dialogue
多样化场景覆盖
为提升数据多样性,建议组合以下维度生成问题:
- 场景类型:售前咨询/售后投诉/技术问题等
- 情绪强度:普通询问(中性) vs 激烈抱怨(高负面情绪)
- 领域扩展:电商/教育/金融等行业差异化表达
质量验证与过滤
# 自动过滤:用风格分类器计算生成文本与目标风格的余弦相似度 from sentence_transformers import SentenceTransformer model = SentenceTransformer("DMetaSoul/Dmeta-embedding") target_style_vec = model.encode("温柔客服的典型回复示例") # 预计算标准样本向量 generated_vec = model.encode(generated_text) similarity = cosine_similarity(target_style_vec, generated_vec) if similarity < 0.75: # 阈值可调 discard_sample() # 人工审核:随机抽样检查是否符合: 风格一致性(如是否混入其他语气) 事实合理性(解决方案是否可执行)
# 加载Embedding模型 style_model = SentenceTransformer(r"E:\model\embedding_model\thomas\text2vec-base-chinese") def is_valid_reply(style_name, reply): if not reply or len(reply.strip()) == 0: return False if len(reply) < 5 or len(reply) > 150: return False style_keywords = { "温柔": ["呢", "呀", "😊", "🌸"], "毒舌": ["好家伙", "栓Q", "!", "🏋️"] } if not any(kw in reply for kw in style_keywords.get(style_name, [])): return False try: # 计算与所有示例回复的平均相似度 similarities = [] assistant_examples = [msg["content"] for msg in prompt_template[style_name]["examples"] if msg["role"] == "assistant"] for example in assistant_examples: ref_vec = style_model.encode(example) reply_vec = style_model.encode(reply) similarity = np.dot(ref_vec, reply_vec) similarities.append(similarity) avg_similarity = np.mean(similarities) return avg_similarity > 0.5 # 调整阈值 except: return False
不同风格的Prompt设计要点
# 1. 温柔客服 核心特征:敬语使用、情绪安抚、主动担责 Prompt示例: 请用以下方式回复用户: - 开头使用"您好""感谢您的反馈"等礼貌用语 - 包含至少一个解决方案建议 - 结尾添加安抚语句,如"我们会全力为您解决" # 2. 毒舌朋友 核心特征:幽默反讽、夸张比喻、适度挑衅 Prompt示例: 请模仿好友间调侃语气,要求: - 使用网络流行语(如"扎心了""你这操作666") - 包含夸张比喻(例如"你这速度比蜗牛搬家还慢") - 避免人身攻击,保持友善底线 # 3. 学术专家 核心特征:术语准确、逻辑严谨、引用规范 Prompt示例: 请以教授身份回答,要求: 1. 使用专业术语(如"根据Cohen's d效应量分析...") 2. 引用至少一篇权威论文(格式:作者(年份)结论...) 3. 最后给出进一步研究建议
数据增强技巧
# 同义改写扩充(对优质样本进行多样化变形) 使用Qwen实现同义改写 def paraphrase(text): response = client.chat.completions.create( model="qwen-turbo", messages=[{ "role": "user", "content": f"请用不同的表达方式改写以下句子,保持原意不变:{text}" }] ) return response.choices[0].message.content # 风格迁移增强(将普通对话转换为目标风格) 原始对话: 用户:这个功能怎么用? 助理:点击右上角设置按钮。 转换为"学术专家"风格: 用户:该功能的操作路径尚未明确,请指导具体执行步骤。 助理:根据界面设计规范(Johnson et al., 2022),您需首先定位到界面右上象限的齿轮状图标,该图标在HCI领域被普遍约定为系统设置入口。 # 对抗性样本生成(刻意构造易混淆场景) 用户(挑衅语气):你们这设计反人类吧?根本找不到入口! 助理(保持温柔):非常理解您的 frustration😢,能否截图标注困惑位置?我们会优先优化该区域指引。
注意事项
1. 版权合规:若计划商用,需确认生成内容版权归属(部分模型如Qwen允许商用)
2. 偏差控制:定期检查生成数据是否存在性别/地域偏见
3. 混合真实数据:建议最终训练数据中生成数据占比不超过70%
4. 迭代优化:每轮微调后,用新模型生成更高质量数据(自蒸馏循环)
embedding_model验证与转换
# numpy.linalg.norm: NumPy库中用于计算向量或矩阵的范数的函数(模长) print(np.linalg.norm([1, -1, 1, 1])) # 2.0 print(np.linalg.norm([[1, 2, 2], [3, 3, 3]])) # 6.0
# 没有加给模型加归一化层
text = "测试文本"
vec = model.encode(text)
print(vec) #[ 5.91819406e-01 -4.04309124e-01 .... 1.35012388e+00 3.30859691e-01 ]
print("模长:", np.linalg.norm(vec)) # 模长: 21.363937
similarities = []
ver1 = model.encode('我真的吃过饭了')
ver2 = model.encode('我是真的吃过饭')
similarity = np.dot(ver1, ver2)
print(similarity) # 425.4054
similarities.append(similarity)
avg_similarity = np.mean(similarities) # np.mean: 用于计算数组中元素的平均值
print(avg_similarity) # 425.4054
import numpy as np from sentence_transformers import SentenceTransformer,models # model_path = r"E:\model\embedding_model\sungw111\text2vec-base-chinese-sentence" bert = models.Transformer(model_path) pooling = models.Pooling(bert.get_word_embedding_dimension(),pooling_mode='mean') # 添加缺失的归一化层 normalize = models.Normalize() # 组合完整模型 full_model = SentenceTransformer(modules=[bert, pooling, normalize]) print(full_model) save_path=r"E:\model\embedding_model\sungw222\text2vec-base-chinese-sentence" full_model.save(save_path) # 加载修复后的模型 model = SentenceTransformer(r"E:\model\embedding_model\sungw222\text2vec-base-chinese-sentence")
# 验证向量归一化
text = "测试文本"
vec = model.encode(text)
print(vec)
print("修正后模长:",np.linalg.norm(vec)) # 输出≈1.0
# 验证向量归一化 similarities = [] ver1 = model.encode('我真的吃过饭了') ver2 = model.encode('我是真的吃过饭') similarity = np.dot(ver1, ver2) print(similarity) # 0.9850389 similarities.append(similarity) avg_similarity = np.mean(similarities) # np.mean: 用于计算数组中元素的平均值 print(avg_similarity) # 0.9850389
模型归一化
如果在外面做则是数据归一化
如果是在内部做则是特征归一化
# 在生成任务中,损失值并不是判断模型是否收敛的绝对标准 不一致性:如果测试答案与训练答案不一致,说明模型没有收敛 一致性:即使测试答案与训练答案一致,也无法确定模型已经收敛 收敛判断:当测试答案与训练答案一致后,需要关注损失变化率。如果损失变化率很小,则可以认为模型收敛
情绪对话模型训练与部署
选择基座模型时选择后缀名为Chat或Instruct的模型
Chat或Instruct为后缀的模型通过人工对齐限制了问答范围,使模型更加安全
以CLUE开头的是中长类型的文本
以FewCLUE开头的是短文
模型选型:根据当前的任务特点,选择合适的评测数据以及预期的候选模型
模型大小如何选择:服务器的配置,任务的复杂度
模型训练
由于该模型是情绪对话模型 ,模型生成的内容更偏向于主关评测而不是客观评测
llama factory评测过程中只能看到loss,看不到主观表现
xtuner提供了训练过程中的主观评测
系统提示词:利用提示词来引导模型产生所需要的输出,在不进行微调的情况下,通过设计合适的提示词,可以充分利用已有模型的能力来处理特定的任务
- 微调 通过在特定数据集上优化模型参数,提高模型在特定任务上的性能,通常需要较大的计算资源和时间。
- 系统提示词 则是在不进行模型训练的情况下,通过设计有效的提示词来引导模型生成所需的输出,迅速而灵活。