wulewule / data /readme.md
zhiyun.xu
update demo
d573b56
|
raw
history blame
11 kB

悟了悟了数据制作教程

一、前言

高质量的数据集是训练和微调模型的关键,数据制作一般会借用一些大模型的API(如InterLM、DeepSeek、Qwen、OpenAI等),可以去对应官网查看或者用第三方的如硅基流动(注册会送一定量token,足够用来做数据)等,一般付费的效果更好。

本模型数据制作包含增量预训练数据和微调数据两部分,最终格式是适配了Xtuner训练格式的数据:

增量预训练数据是从网络上收集到的和《黑神话:悟空》、《西游记》、《悟空传》等相关的文本数据。

微调数据是用来给模型指令微调的问答对数据,制作难点在于知识的实时性和准确性,本模型借助茴香豆RAG功能,从收集的文本资料中提取准确的知识信息。

二、增量预训练数据

这一部分比较简单,不需要API,对收集到的原始文本数据切分后存为对应格式就行,可以参考 wulewule/data/generate_incremental_pretraining.py 这个脚本。

cd wulewule/data
python3 generate_incremental_pretraining.py --root-path ./ --save-path ./incremental_pretraining.jsonl

实现细节

文本切分

把原始数据切分成一个个小块给到模型训练(类似RAG中的chunking),使用了langchain中RecursiveCharacterTextSplitter方法对文本字符递归切分,额外增加了一些中文标点用来断句。

默认参数为:chunk-size(每个文本块的大小)为1024,chunk-overlap(相邻两个文本框重叠长度,防止丢失上下文信息)为50。

最终数据格式

xtuner 定义的增量预训练数据格式如下,"input"为空就行,文本块放在"output"里,想了解更多细节可以看xtuner官方增量预训练数据文档:

    [
        {
            "conversation":[
                {
                    "input": "",  ## 空的,未使用
                    "output": "xxx" ## 切分后的文本
                },
            ]
        },
        {
            "conversation":[
                {
                    "input": "",
                    "output": "xxx"
                },
            ]
        }
    ]

最终保存为jsonl格式,每行是一个字典,对应内容如下:

{"conversation": [{"input": "", "output": "《西游记白话文》\n\n\n 第1回 惊天地美猴王出世\n\n    这是一个神话故事,传说在很久很久以前,..."}]}

三、指令微调数据

普通大模型API只能基于训练时的知识库生成回答,很多知识都停留在过去,比如调用API问“黑神话悟空什么时候发布的”,大多数的都无法给出准确的答案(发布时间2024年08月20日),因为训练资料都是比这个日期之前的。

Qwen2.5-72B-Instruct_api_example

本模型先使用大模型API生成问题,然后借助茴香豆RAG功能,从收集的文本资料中提取对应问题准确的答案(如果本地资料未检索到,则联网检索答案)。

具体实现可以参考 wulewule/data/huixiangdou_rag_QA.py 这个脚本,使用前需要将data_utils.py中的"api_key"换成自己的,同时开启茴香豆server服务

实现细节

问题生成

借用大模型从【 "游戏概述", "章节与故事情节", "主要角色", "人物剧情梳理", "游戏世界观", "建筑与环境", "战斗系统", "游戏玩法", "艺术与音乐", "文化内涵", "市场影响", "彩蛋、网络梗" 】11个角度生成不同的问题:

aspects = [ "游戏概述", "章节与故事情节", "主要角色", "人物剧情梳理", "游戏世界观", "建筑与环境", "战斗系统", "游戏玩法", "艺术与音乐", "文化内涵", "市场影响", "彩蛋、网络梗" ]
question_number = 10
for ascpect in aspects:
    messages=[
        {"role":"system", "content": f"""你是一名提问助手,专注于围绕游戏《黑神话:悟空》的特定方面(例如主要角色、战斗机制或故事情节)提出问题,20个字以内。根据用户的指示,调整你的提问内容,引导玩家深入思考该方面的背景、动机及其在游戏中的作用和发展。不需要序号,最终返回为一个list,格式为['问题', '问题', ...]"""},
        {"role": "user", "content": f"请你就《黑神话:悟空》的‘{ascpect}’方面提出{question_number}个不同的问题,帮助玩家了解游戏在该方面的信息。"},
    ]
    text_res = response(messages, temperature=0.7)

messages中就是要给API的数据,基于上述prompt让它成为一个专门生成问题的助手,再从不同方面生成对应问题。

调用模型api

response函数就是调用API生成回答了,这边使用的是硅基流动平台(也可以用其他平台或者本地的模型),官网有很详细的文档,下面是一个使用requests的例子,需要将"" 换成你自己的:

import requests

url = "https://api.siliconflow.cn/v1/chat/completions"

payload = {
    "model": "deepseek-ai/DeepSeek-V2.5",
    "messages": [
        {
            "role": "user",
            "content": "SiliconCloud推出分层速率方案与免费模型RPM提升10倍,对于整个大模型应用领域带来哪些改变?"
        }
    ],
    "stream": False,
    "max_tokens": 512,
    "stop": ["<string>"],
    "temperature": 0.7,
    "top_p": 0.7,
    "top_k": 50,
    "frequency_penalty": 0.5,
    "n": 1,
    "response_format": {"type": "json_object"}
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.request("POST", url, json=payload, headers=headers)

print(response.text)

或者是用OpenAI的方式,api_key换成你自己的

from openai import OpenAI

client = OpenAI(
    base_url='https://api.siliconflow.cn/v1',
    api_key='your-api-key'
)

def response(messages, max_tokens=512, temperature=0.5):
    res = client.chat.completions.create(
        model="deepseek-ai/DeepSeek-V2.5",
        messages=messages,
        max_tokens=max_tokens,
        temperature=temperature,
    ).choices[0].message.content
    return res

最终API返回的数据都是string类型,虽然prompt中说明了固定格式,但如果API模型效果没那么好,可能不会按这个格式输出,所以最好用正则处理一下结果,这里用的"deepseek-ai/DeepSeek-V2.5"好像没遇到这种情况。

开启茴香豆RAG服务

参考实战营-茴香豆本地标准版搭建的讲解,进行环境和模型配置即可,不再赘述。

用data目录下的文本数据创建自己的知识库后,开启服务端,监听 23333 端口,使用 chat_in_group pipeline:

python3 -m huixiangdou.server --pipeline chat_in_group

# cURL 测试状态回调接口
curl -X POST http://127.0.0.1:23333/huixiangdou_stream  -H "Content-Type: application/json" -d '{"text": "how to install mmpose","image": ""}'
# cURL 测试同步接口
curl -X POST http://127.0.0.1:23333/huixiangdou_inference  -H "Content-Type: application/json" -d '{"text": "how to install mmpose","image": ""}'

如果需要开启网络检索,当模型本地检索不到结果时进行联网检索,需要注册Serper,参考开启网络搜索

调用RAG生成回答

将API得到的问题给到茴香豆RAG,然后得到最终答案即可,参考下方函数

def generate_answers(questions="黑神话悟空什么时候发布的",  english=False):
    """
        参考https://github.com/InternLM/HuixiangDou/blob/main/README_zh.md 先开启对应的服务
    """
    # 定义请求的URL
    url = 'http://127.0.0.1:23333/huixiangdou_inference'

    # 定义你要发送的数据
    data = {
        "text": f"{questions}",
        "image": ""
    }

    # 将数据转换成json格式
    payload = json.dumps(data)

    # 设置请求头
    headers = {
        'Content-Type': 'application/json'
    }

    # 发送POST请求
    rag_response = requests.post(url, data=payload, headers=headers)
    # 检查请求是否成功
    if rag_response.status_code != 200:
        logger.error(f"请求失败,状态码:{rag_response.status_code}")

    res_txt = rag_response.text
    res = json.loads(res_txt, strict=False)
    answer = ""
    for step in res["step"]:
        if step["state"] == "success":
            answer = step["response"]
            logger.info(f"got response: {answer}")
    if answer == "":
        logger.error(f'no answer: {res_txt}')
    return answer

最终数据格式

以下时xtuner使用的指令微调数据格式,如果是多轮对话,只需要再第一次对话中加入"system",最好这个system prompt和你最终使用时给模型的prompt保持一致

[{
    "conversation":[
        {
            "system": "xxx",
            "input": "xxx",
            "output": "xxx"
        }
    ]
},
{
    "conversation":[
        {
            "system": "xxx",
            "input": "xxx",
            "output": "xxx"
        },
        {
            "input": "xxx",
            "output": "xxx"
        }
    ]
}]

最终保存为jsonl格式,每行是一个字典,以下是一个例子

{"conversation": [{"system": "你是悟了悟了,...", "input": "游戏世界观的设定灵感来源是什么?", "output": "《黑神话:悟空》的游戏世界观深受《西游记》的影响,但在此基础上进行了大胆的创新和扩展。游戏构建了一个佛道衰败、妖魔横行的末法时代背景,其中许多角色和地点都源自《西游记》,如孙悟空、牛魔王、蜘蛛精等,这些角色在游戏世界中被赋予了新的故事和性格。同时,游戏还增加了新的神话元素和角色,如黄眉老祖、黑熊精等,这些新角色的加入丰富了游戏的世界观和剧情。因此,游戏世界观的设定灵感来源主要是《西游记》,但通过创新和扩展,构建了一个既熟悉又新奇的神话世界。"}, {"input": "在《黑神话:悟空》中,孙悟空的棍法技能在不同战斗场景中如何应用?请简要回答", "output": "在《黑神话:悟空》中,孙悟空的棍法技能在不同战斗场景中有着不同的应用方式,以下是简要回答:..."}]}