首页 > 其他分享 >基于TigerBot-13b训练其函数调用能力

基于TigerBot-13b训练其函数调用能力

时间:2023-12-23 16:12:14浏览次数:42  
标签:13b string -- 函数调用 json train TigerBot input data

写在前面

原生的tigerbot似乎并不支持函数调用,于是我来支持一下

 

数据集

我在huggingface上找了个英文的数据集

https://huggingface.co/datasets/sadmoseby/sample-function-call

这里面包含了1k组的函数调用,这个数据集的特点如下:

1. 包含有单个/多个/没有函数调用的情形

2. 描述函数的json_schema与OpenAI格式的一致(但多函数情况下,并没有用列表框起来)

3. 数据虽然是多轮对话的数据,但是每一个都是一整条的数据,且每个的开头与tigerbot的头不太一致

 

数据转换

我写了一个数据转换的代码,具体任务如下:

1. 将多个函数时没有用列表格式框选的情况给修复了

2. 切分为了多轮的对话,有多条训练数据

3. 修改了开头的情况

代码如下

  1 import re
  2 
  3 import json
  4 import re
  5 
  6 # system_prompt中可能有多个函数,多个函数的话要转为标准的[]格式
  7 def get_function_json(input_string):
  8     # 使用正则表达式分割字符串,找出独立的 JSON 字符串
  9     json_strings = re.findall(r'\{[\s\S]+?\}\s*(?=\{|$)', input_string)
 10 
 11     # 解析每个 JSON 字符串并把它们加入到列表中
 12     json_objects = []
 13     for json_str in json_strings:
 14         input_string = input_string.replace(json_str, '')
 15         try:
 16             json_obj = json.loads(json_str)
 17             json_objects.append(json_obj)
 18         except json.JSONDecodeError as e:
 19             print(f"Error decoding JSON: {e}")
 20     # 打印结果或进行其他操作
 21     if json_objects:
 22         return input_string + json.dumps(json_objects, ensure_ascii=False, indent=4)
 23     else:
 24         return input_string
 25 
 26 # 切分读入的数据
 27 def split_string_with_keywords(s, keywords):
 28     # 将关键词列表转化为正则表达式,使用括号捕获分隔符
 29     # 比如 ['system', 'assistant'] 会被转换成 (system)|(assistant)
 30     regex_pattern = '({})'.format('|'.join(map(re.escape, keywords)))
 31 
 32     # 使用 re.split,它会返回包含分隔符的列表
 33     parts = re.split(regex_pattern, s)
 34 
 35     # 初始化结果列表
 36     result = []
 37 
 38     # 存储上一个匹配到的关键词,初始时没有关键词
 39     last_keyword = None
 40 
 41     # 遍历分割后的列表
 42     for part in parts:
 43         # 如果当前部分是关键词,记录下来并继续下一轮循环
 44         if part in keywords:
 45             last_keyword = part
 46             continue
 47         # 如果当前部分不是关键词,且上一部分是关键词,则将其作为结果加入
 48         if last_keyword:
 49             result.append((last_keyword, part.strip()))
 50             last_keyword = None  # 重置关键词
 51 
 52     return result
 53 
 54 max_len = 0
 55 
 56 
 57 def count_words_and_punctuation(s):
 58     # 使用正则表达式来匹配单词和标点符号
 59     # \w+ 匹配单词字符(字母、数字、下划线)出现一次或多次组成的单词
 60     # | 表示或,用来分隔不同的匹配规则
 61     # \s 表示空白字符
 62     # [^\w\s] 匹配任意不是单词字符和不是空白字符的字符,即标点符号
 63     matches = re.findall(r'\w+|[^\w\s]', s)
 64 
 65     # 计算匹配项的数量,即单词和标点符号的总数
 66     return len(matches)
 67 
 68 def solve(input):
 69     global max_len
 70     max_len = max(max_len , count_words_and_punctuation(input))
 71     import json
 72     # 基础替换
 73     input = input.replace('<|endoftext|>', '')
 74 
 75     replace_map = {
 76         'SYSTEM:' : '\n\n### System:\n ',
 77         'ASSISTANT:': '\n\n### Response:\n ',
 78         'USER:': '\n\n### Instruction:\n ',
 79         'FUNCTION RESPONSE:': '\n\n### Function:\n '
 80     }
 81 
 82     data = split_string_with_keywords(input, list(replace_map.keys()))
 83 
 84     # 更换函数的格式
 85     if data[0][0] == 'SYSTEM:':
 86         data[0] = (data[0][0], get_function_json(data[0][1]))
 87 
 88     return_data = []
 89     train_str = ''
 90     for element in data:
 91         train_str += replace_map[element[0]]
 92         if element[0] == 'ASSISTANT:':
 93             return_data.append({
 94                 "instruction": train_str,
 95                 "input": "",
 96                 "output": element[1]
 97             })
 98         train_str += element[1]
 99 
100     return return_data
101 
102 import pandas as pd
103 
104 train_data = []
105 
106 # 读取Parquet文件
107 df = pd.read_parquet('train-00000-of-00001.parquet')
108 column_name = df.columns[0]
109 for value in df[column_name]:
110     train_data += solve(value)
111 
112 with open('train_function_call.json', 'w', encoding='utf-8') as f:
113     json.dump(train_data, f, ensure_ascii=False, indent=4)
114 print(max_len)

 改好格式的数据如下(以response来切分,response前为输入,response为需要模型生成的输出):

### System:
 You are a helpful assistant with access to the following functions. Use them if required -
[
    {
        "name": "search_books",
        "description": "Search for books based on specified criteria",
        "parameters": {
            "type": "object",
            "properties": {
                "title": {
                    "type": "string",
                    "description": "The title of the book"
                },
                "author": {
                    "type": "string",
                    "description": "The author of the book"
                },
                "genre": {
                    "type": "string",
                    "description": "The genre of the book"
                }
            },
            "required": [
                "title"
            ]
        }
    }
]

### Instruction:
 I am looking for a book but I can't remember the full title. I know it has the word "Sun" in it and it's a science fiction novel.

### Response:
 <functioncall> {"name": "search_books", "arguments": '{"title": "Sun", "genre": "science fiction"}'}

### Function:
 {"results": [{"title": "The Sun Also Rises in Space", "author": "John Doe", "genre": "science fiction"}, {"title": "Sunset on Mars", "author": "Jane Doe", "genre": "science fiction"}]}

### Response:
 I found two science fiction books with "Sun" in the title. The first one is "The Sun Also Rises in Space" by John Doe and the second one is "Sunset on Mars" by Jane Doe.

 

 

启动训练

笔者依然在恒源云上,基于tigerbot-13b-chat-v5-4k进行训练。

考虑到vllm暂时不支持PEFT格式的adapter,此次依然采用了freeze训练。

为了尽可能地训练更多的层,笔者采用了单个A100-80G的显卡,这样可以在seq_len达到3072的情况下,训练10层的tranformer参数。

注意,此次的template和以前不太一样(因为有各种的function和自己添加的system),所以添加了一个新的模板

 1 register_template(
 2     name="null",
 3     prefix=[
 4         ""
 5     ],
 6     prompt=[
 7         "{{query}}"
 8     ],
 9     system="",
10     sep=[]
11 )

训练命令如下

 1 python src/train_bash.py \
 2     --stage sft \
 3     --model_name_or_path /hy-tmp/tigerbot-13b-chat-v5-4k \
 4     --do_train True \
 5     --finetuning_type freeze \
 6     --num_layer_trainable 10 \
 7     --template null \
 8     --dataset_dir data \
 9     --dataset train_function_call \
10     --cutoff_len 3072 \
11     --learning_rate 1e-4 \
12     --num_train_epochs 1.0 \
13     --per_device_train_batch_size 4 \
14     --gradient_accumulation_steps 2 \
15     --logging_steps 1 \
16     --save_steps 10000 \
17     --output_dir /hy-tmp/tigerbot-13b-function-call \
18     --fp16 True \
19     --plot_loss True \
20     --overwrite_output_dir

标签:13b,string,--,函数调用,json,train,TigerBot,input,data
From: https://www.cnblogs.com/alphainf/p/17923227.html

相关文章

  • 中文TigerBot-70B大模型:领先Llama-2,全球开源新标杆,300B数据驱动
    引言随着大型语言模型(LLM)在自然语言处理领域的日益重要,新型多语言多任务模型——TigerBot-70B的问世,标志着全球范围内一个新的技术里程碑的达成。TigerBot-70B不仅在性能上匹敌行业巨头如OpenAI的模型,而且其创新算法和数据处理方式在行业内引起广泛关注。Huggingface模型下载:https:......
  • 使用双卡/8卡3090微调llama2-70B/13B模型
    写在前面本篇博文将会教大家如何在消费级的设备(或者各种超级便宜的洋垃圾上)实现13B/70B等无法在单张消费级显卡上加载(但可以在一台机器上的多张卡上加载)的模型的微调。由于绝大部分做实验,仅要求实现推理,或者在微调时没有资源上到全量/13B+级别的真·大模型的微调,没有涉及到将一......
  • 超越边界:Mistral 7B挑战AI新标准,全面超越Llama 2 13B
    引言在人工智能领域,模型的性能一直是衡量其价值和应用潜力的关键指标。近日,一个新的里程碑被设立:MistralAI发布了其最新模型Mistral7B,它在众多基准测试中全面超越了Llama213B模型,标志着AI技术的一个重大进步。Mistral7BvsLlama213BMistral7B的发布,不仅是一次技术上的突破......
  • 多重继承下的虚函数调用
    C++中虚函数调用采用所谓的虚函数表(vtable)实现,对于简单的单继承,其实现如下图所示:(其中ClassA为ClassB的基类,详见深入浅出MFCP68)你也许会想到:C++支持多继承,在多继承的情况下,vatble以及内存布局该如何实现?以下也许就是你想要的答案代码:C继承于A和B,运行环境VC6.0classA......
  • f通过new关键词进行函数调用,之后无论如何都会返回一个与F关联的普通对象(因为不是通过
    varF=function(){};Object.prototype.a=function(){};Function.prototype.b=function(){};varf=newF();关于这段代码的描述,正确的是:Af能取到a,但取不到bBf能取到a,bCF能取到b,不能取到aDF能取到a,不能取到b正确答案:A网上有一道美团外卖的面试题是这样的:Function......
  • P7831 [CCO2021] Travelling Merchant CWOI1113B
    首先将边反向,再按\(r\)从大到小排序,这样可以使得答案的转移没有后效性。令\(ans_i\)表示\(i\)这个点最少有多少资产方能无限地走下去。(初值为\(inf\))依次枚举每一条边。(令\(u\)为这条边的起点,\(v\)为这条边的终点)首先对现在的图进行一遍topo,转移方程为\(ans_v=m......
  • 【chatgpt问答记录】双端队列、栈和函数调用栈
    collections.deque和queue.Queue的区别Q:collections.deque()跟queue.Queue()有什么区别?collections.deque()和queue.Queue是两种不同的数据结构,它们有一些区别:实现方式:collections.deque()是Python标准库提供的双端队列数据结构,使用双向链表实现,具有高效的在两端进行......
  • C语言程序设计 求阶乘递归函数调用示例
    ......
  • JavaScript 函数、函数构造、函数调用、参数、函数返回值、变量的作用域、预解析
    一、函数及函数的构造函数是一个可重用的代码块,用来完成某个特定功能。每当需要反复执行一段代码时,可以利用函数来避免重复书写相同代码。函数包含着的代码只能在函数被调用时才会执行,就可以避免页面载入时执行该脚本简单来说就是一个封装,封装的是一个特定的功能,重复使用函......
  • baichuan2-13b-chat加速
    当前加速框架层出不穷,到底哪个能一统天下未可知,那在当前阶段我们加速大模型该选取哪个框架呢。目前存在的大模型加速框架:VLLM,TGI,FasterTransformer,DeepSpeed-MII,FlexFlowServer,LMDeploy等等等等。但是这些框架大部分支持的模型都很少,或只支持英文模型,支持中文模型的更少,目前......