1.环境配置
from sparkai.llm.llm import ChatSparkLLM, ChunkPrintHandler
from sparkai.core.messages import ChatMessage
import numpy as np
from tqdm import tqdm
def chatbot(prompt):
#星火认知大模型Spark3.5 Max的URL值,其他版本大模型URL值请前往文档(https://www.xfyun.cn/doc/spark/Web.html)查看
SPARKAI_URL = ''
#星火认知大模型调用秘钥信息,请前往讯飞开放平台控制台(https://console.xfyun.cn/services/bm35)查看
SPARKAI_APP_ID = ''
SPARKAI_API_SECRET = ''
SPARKAI_API_KEY = ''
#星火认知大模型Spark3.5 Max的domain值,其他版本大模型domain值请前往文档(https://www.xfyun.cn/doc/spark/Web.html)查看
SPARKAI_DOMAIN = 'generalv3.5'
spark = ChatSparkLLM(
spark_api_url=SPARKAI_URL,
spark_app_id=SPARKAI_APP_ID,
spark_api_key=SPARKAI_API_KEY,
spark_api_secret=SPARKAI_API_SECRET,
spark_llm_domain=SPARKAI_DOMAIN,
streaming=False,
)
messages = [ChatMessage(
role="user",
content=prompt
)]
handler = ChunkPrintHandler()
a = spark.generate([messages], callbacks=[handler])
return a.generations[0][0].message.content
chatbot
函数接受一个 prompt
参数,该参数是用户输入的聊天消息。ChatSparkLLM
类实例化一个大模型对象,通过提供的配置参数进行初始化。streaming=False
指定不使用流式传输。
2.数据处理Prompt
content = ''
prompt = f'''
你是一个数据分析大师,你需要从群聊对话中进行分析,里面对话的角色中大部分是客服角色,你需要从中区分出有需求的客户,并得到以下四类数据。
****群聊对话****
{content}
****分析数据****
客户基本信息:需要从中区分出客户角色,并得到客户基本信息,其中包括姓名、手机号码、邮箱、地区、详细地址、性别、年龄和生日
客户意向与预算信息: 客户意向与预算信息包括咨询类型、意向产品、购买异议点、预算是否充足、总体预算金额以及预算明细
客户购买准备情况:户购买准备情况包括竞品信息、客户是否有意向、客户是否有卡点以及客户购买阶段
跟进计划信息: 跟进计划信息包括参与人、时间点和具体事项,这些信息用于指导销售团队在未来的跟进工作中与客户互动
****注意****
1.只输出客户基本信息、客户意向与预算信息、客户购买准备情况、跟进计划信息对应的信息,不要输出无关内容
2.不要输出分析内容
3.输出内容格式为md格式
'''
这里我们对原群聊对话设计了一个总结Prompt,目的是将原始对话内容进行精简。方便做微调数据。
一方面直接将群聊对话作为数据集的话,会导致上下文过长,超过限制。还有上下文太长会导致抽取效果变差。
过长的上下文也会导致训练时长和费用倍增。
3.训练数据集制作
jsonl_data 是用来训练的规范单行数据,需要由训练数据组成一个jsonl文件(每行是一个json数据的文件),格式如下
jsonl_data = {"instruction":"假设你是一个智能交互助手,基于用户的输入文本,解析其中语义,抽取关键信息,以json格式生成结构化的语义内容。","input":"请调小空气净化器的湿度到1","output":"{\"intent\":\"CONTROL\",\"slots\":[{\"name\":\"device\",\"normValue\":\"airCleaner\",\"value\":\"空气净化器\"},{\"name\":\"insType\",\"normValue\":\"set\",\"value\":\"调小\"},{\"name\":\"attr\",\"normValue\":\"humidity\",\"value\":\"湿度\"},{\"name\":\"attrValue\",\"normValue\":\"1\",\"value\":\"1\"}],\"sample\":\"请调小空气净化器的湿度到1\"}"}
这段代码旨在创建一个用于训练的 JSONL 文件(traindata.jsonl
),其中每条数据包含对群聊对话的分析结果。由于数据量不足,通过重复数据集12次来满足最低训练集行数要求。主要步骤解读:1.打开文件用于写入 2.遍历数据列表 3. 提取输入输出数据 4.构建 Prompt 并调用 chatbot
函数 5.构建要写入文件的数据格式 6. 重复写入数据以扩充训练集
with open('traindata.jsonl', 'w', encoding='utf-8') as file:
# 训练集行数(130)不符合要求,范围:1500~90000000
# 遍历数据列表,并将每一行写入文件
# 这里为了满足微调需求我们重复12次数据集 130*12=1560
for line_data in tqdm(data):
line_input = line_data["chat_text"]
line_output = line_data["infos"]
content = line_input
prompt = f'''
你是一个数据分析大师,你需要从群聊对话中进行分析,里面对话的角色中大部分是客服角色,你需要从中区分出有需求的客户,并得到以下四类数据。
****群聊对话****
{content}
****分析数据****
客户基本信息:需要从中区分出客户角色,并得到客户基本信息,其中包括姓名、手机号码、邮箱、地区、详细地址、性别、年龄和生日
客户意向与预算信息: 客户意向与预算信息包括咨询类型、意向产品、购买异议点、预算是否充足、总体预算金额以及预算明细
客户购买准备情况:户购买准备情况包括竞品信息、客户是否有意向、客户是否有卡点以及客户购买阶段
跟进计划信息: 跟进计划信息包括参与人、时间点和具体事项,这些信息用于指导销售团队在未来的跟进工作中与客户互动
****注意****
1.只输出客户基本信息、客户意向与预算信息、客户购买准备情况、跟进计划信息对应的信息,不要输出无关内容
2.不要输出分析内容
3.输出内容格式为md格式
'''
res = chatbot(prompt=prompt)
# print(res)
line_write = {
"instruction":jsonl_data["instruction"],
"input":json.dumps(res, ensure_ascii=False),
"output":json.dumps(line_output, ensure_ascii=False)
}
# 因为数据共有130行,为了能满足训练需要的1500条及以上,我们将正常训练数据扩充12倍。
for time in range(12):
file.write(json.dumps(line_write, ensure_ascii=False) + '\n') # '\n' 用于在每行末尾添加换行符
4.测试集制作
# 验证集制作(提交版本)
# input,target
import json
# 打开并读取JSON文件
with open('test_data.json', 'r', encoding='utf-8') as file:
data_test = json.load(file)
import csv
# 打开一个文件用于写入CSV数据
with open('test.csv', 'w', newline='', encoding='utf-8') as csvfile:
# 创建一个csv writer对象
csvwriter = csv.writer(csvfile)
csvwriter.writerow(["input","target"])
# 遍历数据列表,并将每一行写入CSV文件
for line_data in tqdm(data_test):
content = line_data["chat_text"]
prompt = f'''
你是一个数据分析大师,你需要从群聊对话中进行分析,里面对话的角色中大部分是客服角色,你需要从中区分出有需求的客户,并得到以下四类数据。
****群聊对话****
{content}
****分析数据****
客户基本信息:需要从中区分出客户角色,并得到客户基本信息,其中包括姓名、手机号码、邮箱、地区、详细地址、性别、年龄和生日
客户意向与预算信息: 客户意向与预算信息包括咨询类型、意向产品、购买异议点、预算是否充足、总体预算金额以及预算明细
客户购买准备情况:户购买准备情况包括竞品信息、客户是否有意向、客户是否有卡点以及客户购买阶段
跟进计划信息: 跟进计划信息包括参与人、时间点和具体事项,这些信息用于指导销售团队在未来的跟进工作中与客户互动
****注意****
1.只输出客户基本信息、客户意向与预算信息、客户购买准备情况、跟进计划信息对应的信息,不要输出无关内容
2.不要输出分析内容
3.输出内容格式为md格式
'''
res = chatbot(prompt=prompt)
# print(line_data["chat_text"])
## 文件内容校验失败: test.jsonl(不含表头起算)第1行的内容不符合规则,限制每组input和target字符数量总和上限为8000,当前行字符数量:10721
line_list = [res, "-"]
csvwriter.writerow(line_list)
# break
5.测试集与训练集制作区别
文件格式:
- 第一段代码将数据写入
JSONL
文件(traindata.jsonl
)。 - 第二段代码将数据写入
CSV
文件(test.csv
)。
写入文件的内容格式:
- 第一段代码中的每行数据包含
instruction
、input
和output
字段,且为了满足训练集的行数要求,每行数据被重复写入 12 次。 - 第二段代码中的每行数据包含
input
和target
字段,且没有重复写入数据。
文件写入方式:
- 第一段代码使用
json.dumps
将字典对象转换为 JSON 字符串,然后写入文件。 - 第二段代码使用
csv.writer
将数据列表写入 CSV 文件。
字符数量限制提示:
- 第二段代码在注释中指出了字符数量限制的问题,并提到当前行字符数量超出 8000 字符的限制。
6.微调推理
# 定义写入函数
def write_json(json_file_path, data):
#"""写入json文件"""
with open(json_file_path, 'w') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
import SparkApi
import json
#以下密钥信息从控制台获取
appid = "" #填写控制台中获取的 APPID 信息
api_secret = "" #填写控制台中获取的 APISecret 信息
api_key ="" #填写控制台中获取的 APIKey 信息
#调用微调大模型时,设置为“patch”
domain = "patchv3"
#云端环境的服务地址
# Spark_url = "wss://spark-api-n.xf-yun.com/v1.1/chat" # 微调v1.5环境的地址
Spark_url = "wss://spark-api-n.xf-yun.com/v3.1/chat" # 微调v3.0环境的地址
text =[]
# length = 0
def getText(role,content):
jsoncon = {}
jsoncon["role"] = role
jsoncon["content"] = content
text.append(jsoncon)
return text
def getlength(text):
length = 0
for content in text:
temp = content["content"]
leng = len(temp)
length += leng
return length
def checklen(text):
while (getlength(text) > 8000):
del text[0]
return text
def core_run(text,prompt):
# print('prompt',prompt)
text.clear
Input = prompt
question = checklen(getText("user",Input))
SparkApi.answer =""
# print("星火:",end = "")
SparkApi.main(appid,api_key,api_secret,Spark_url,domain,question)
getText("assistant",SparkApi.answer)
# print(text)
return text[-1]['content']
text = []
res = core_run(text,'你好吗?')
详细解读:
-
写入 JSON 文件的函数:
write_json
函数接受文件路径和数据,并将数据写入到指定的 JSON 文件中。
-
密钥信息和 API 地址:
- 设置与 SparkApi 通信所需的密钥信息(
appid
,api_secret
,api_key
)和 API 地址(Spark_url
)。
- 设置与 SparkApi 通信所需的密钥信息(
-
获取文本长度的函数:
getText
函数将对话角色和内容添加到text
列表中。getlength
函数计算text
列表中所有内容的总长度。checklen
函数确保text
列表中的总长度不超过 8000 字符,超出时删除最早的内容。
-
核心运行函数:
core_run
函数执行对话,构建用户输入并调用 SparkApi 进行处理,然后将返回的结果添加到text
列表中,并返回最新的对话内容。
-
运行示例:
- 创建一个空的
text
列表,并调用core_run
函数进行对话示例,传入输入内容 '你好吗?'。
- 创建一个空的
7.获取结果
这段代码通过读取 CSV 文件中的数据,逐行处理并生成相应的 JSON 数据,将处理后的结果存储到一个新的列表中。代码还包括处理 JSON 解析错误的机制,并在解析失败时使用一个预定义的空字典作为默认值。data_dict_empty
是一个包含所有可能字段的空字典,用于在解析失败时作为默认值。submit_data
用于存储处理后的数据,每个元素是一个包含 infos
(解析后的数据字典)和 index
(行号)的字典。
import pandas as pd
import re
# 读取Excel文件
df_test = pd.read_csv('test.csv',)
data_dict_empty = {
"基本信息-姓名": "",
"基本信息-手机号码": "",
"基本信息-邮箱": "",
"基本信息-地区": "",
"基本信息-详细地址": "",
"基本信息-性别": "",
"基本信息-年龄": "",
"基本信息-生日": "",
"咨询类型": [],
"意向产品": [],
"购买异议点": [],
"客户预算-预算是否充足": "",
"客户预算-总体预算金额": "",
"客户预算-预算明细": "",
"竞品信息": "",
"客户是否有意向": "",
"客户是否有卡点": "",
"客户购买阶段": "",
"下一步跟进计划-参与人": [],
"下一步跟进计划-时间点": "",
"下一步跟进计划-具体事项": ""
}
submit_data = []
for id,line_data in tqdm(enumerate(df_test['input'])):
# print(line_data)
content = line_data
text = []
prompt = json.dumps(content,ensure_ascii=False)
# print(json.dumps(content,ensure_ascii=False))
res = core_run(text,prompt)
try:
data_dict = json.loads(res)
except json.JSONDecodeError as e:
data_dict = data_dict_empty
submit_data.append({"infos":data_dict,"index":id+1})
# 预计执行8min
- 对每一行的
input
数据进行处理,构建prompt
并调用core_run
函数。 - 尝试将
core_run
返回的结果解析为 JSON,如果解析失败,则使用data_dict_empty
作为默认值。 - 将处理后的数据(
infos
和index
)添加到submit_data
列表中。
注:微调模型
模型微调在平台进行,采用零代码微调,微调方法为LoRA
LoRA在固定预训练大模型本身的参数基础上,在保留自注意力模块中原始权重矩阵的基础上,对权重矩阵进行低秩分解,训练过程中只更新低秩部分的参数。
再此不进行详细解释。