first commit
This commit is contained in:
parent
0bf35dd5de
commit
48c76c3ff4
304
README.md
304
README.md
|
@ -1,3 +1,303 @@
|
||||||
# MiniCPM3-4B_a13567660624834560972296
|
---
|
||||||
|
license: apache-2.0
|
||||||
|
language:
|
||||||
|
- zh
|
||||||
|
- en
|
||||||
|
pipeline_tag: text-generation
|
||||||
|
---
|
||||||
|
<div align="center">
|
||||||
|
<img src="https://github.com/OpenBMB/MiniCPM/blob/main/assets/minicpm_logo.png?raw=true" width="500em" ></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
MiniCPM3-4B
|
<p align="center">
|
||||||
|
<a href="https://github.com/OpenBMB/MiniCPM/" target="_blank">MiniCPM Repo</a> |
|
||||||
|
<a href="https://arxiv.org/abs/2404.06395" target="_blank">MiniCPM Paper</a> |
|
||||||
|
<a href="https://github.com/OpenBMB/MiniCPM-V/" target="_blank">MiniCPM-V Repo</a> |
|
||||||
|
Join us in <a href="https://discord.gg/3cGQn9b3YM" target="_blank">Discord</a> and <a href="https://github.com/OpenBMB/MiniCPM/blob/main/assets/wechat.jpg" target="_blank">WeChat</a>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
MiniCPM3-4B is the 3rd generation of MiniCPM series. The overall performance of MiniCPM3-4B surpasses Phi-3.5-mini-Instruct and GPT-3.5-Turbo-0125, being comparable with many recent 7B~9B models.
|
||||||
|
|
||||||
|
Compared to MiniCPM1.0/MiniCPM2.0, MiniCPM3-4B has a more powerful and versatile skill set to enable more general usage. MiniCPM3-4B supports function call, along with code interpreter. Please refer to [Advanced Features](https://github.com/OpenBMB/MiniCPM/tree/main?tab=readme-ov-file#%E8%BF%9B%E9%98%B6%E5%8A%9F%E8%83%BD) for usage guidelines.
|
||||||
|
|
||||||
|
MiniCPM3-4B has a 32k context window. Equipped with LLMxMapReduce, MiniCPM3-4B can handle infinite context theoretically, without requiring huge amount of memory.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
### Inference with Transformers
|
||||||
|
```python
|
||||||
|
from modelscope import AutoModelForCausalLM, AutoTokenizer
|
||||||
|
import torch
|
||||||
|
|
||||||
|
path = "OpenBMB/MiniCPM3-4B"
|
||||||
|
device = "cuda"
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained(path, trust_remote_code=True)
|
||||||
|
model = AutoModelForCausalLM.from_pretrained(path, torch_dtype=torch.bfloat16, device_map=device, trust_remote_code=True)
|
||||||
|
|
||||||
|
messages = [
|
||||||
|
{"role": "user", "content": "推荐5个北京的景点。"},
|
||||||
|
]
|
||||||
|
model_inputs = tokenizer.apply_chat_template(messages, return_tensors="pt", add_generation_prompt=True).to(device)
|
||||||
|
|
||||||
|
model_outputs = model.generate(
|
||||||
|
model_inputs,
|
||||||
|
max_new_tokens=1024,
|
||||||
|
top_p=0.7,
|
||||||
|
temperature=0.7
|
||||||
|
)
|
||||||
|
|
||||||
|
output_token_ids = [
|
||||||
|
model_outputs[i][len(model_inputs[i]):] for i in range(len(model_inputs))
|
||||||
|
]
|
||||||
|
|
||||||
|
responses = tokenizer.batch_decode(output_token_ids, skip_special_tokens=True)[0]
|
||||||
|
print(responses)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inference with [vLLM](https://github.com/vllm-project/vllm)
|
||||||
|
|
||||||
|
For now, you need to install our forked version of vLLM.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install git+https://github.com/OpenBMB/vllm.git@minicpm3
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
from transformers import AutoTokenizer
|
||||||
|
from vllm import LLM, SamplingParams
|
||||||
|
|
||||||
|
model_name = "openbmb/MiniCPM3-4B"
|
||||||
|
prompt = [{"role": "user", "content": "推荐5个北京的景点。"}]
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
|
||||||
|
input_text = tokenizer.apply_chat_template(prompt, tokenize=False, add_generation_prompt=True)
|
||||||
|
|
||||||
|
llm = LLM(
|
||||||
|
model=model_name,
|
||||||
|
trust_remote_code=True,
|
||||||
|
tensor_parallel_size=1
|
||||||
|
)
|
||||||
|
sampling_params = SamplingParams(top_p=0.7, temperature=0.7, max_tokens=1024, repetition_penalty=1.02)
|
||||||
|
|
||||||
|
outputs = llm.generate(prompts=input_text, sampling_params=sampling_params)
|
||||||
|
|
||||||
|
print(outputs[0].outputs[0].text)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Evaluation Results
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Benchmark</td>
|
||||||
|
<td>Qwen2-7B-Instruct</td>
|
||||||
|
<td>GLM-4-9B-Chat</td>
|
||||||
|
<td>Gemma2-9B-it</td>
|
||||||
|
<td>Llama3.1-8B-Instruct</td>
|
||||||
|
<td>GPT-3.5-Turbo-0125</td>
|
||||||
|
<td>Phi-3.5-mini-Instruct(3.8B)</td>
|
||||||
|
<td>MiniCPM3-4B </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="15" align="left"><strong>English</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>MMLU</td>
|
||||||
|
<td>70.5</td>
|
||||||
|
<td>72.4</td>
|
||||||
|
<td>72.6</td>
|
||||||
|
<td>69.4</td>
|
||||||
|
<td>69.2</td>
|
||||||
|
<td>68.4</td>
|
||||||
|
<td>67.2 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>BBH</td>
|
||||||
|
<td>64.9</td>
|
||||||
|
<td>76.3</td>
|
||||||
|
<td>65.2</td>
|
||||||
|
<td>67.8</td>
|
||||||
|
<td>70.3</td>
|
||||||
|
<td>68.6</td>
|
||||||
|
<td>70.2 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>MT-Bench</td>
|
||||||
|
<td>8.41</td>
|
||||||
|
<td>8.35</td>
|
||||||
|
<td>7.88</td>
|
||||||
|
<td>8.28</td>
|
||||||
|
<td>8.17</td>
|
||||||
|
<td>8.60</td>
|
||||||
|
<td>8.41 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>IFEVAL (Prompt Strict-Acc.)</td>
|
||||||
|
<td>51.0</td>
|
||||||
|
<td>64.5</td>
|
||||||
|
<td>71.9</td>
|
||||||
|
<td>71.5</td>
|
||||||
|
<td>58.8</td>
|
||||||
|
<td>49.4</td>
|
||||||
|
<td>68.4 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="15" align="left"><strong>Chinese</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>CMMLU</td>
|
||||||
|
<td>80.9</td>
|
||||||
|
<td>71.5</td>
|
||||||
|
<td>59.5</td>
|
||||||
|
<td>55.8</td>
|
||||||
|
<td>54.5</td>
|
||||||
|
<td>46.9</td>
|
||||||
|
<td>73.3 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>CEVAL</td>
|
||||||
|
<td>77.2</td>
|
||||||
|
<td>75.6</td>
|
||||||
|
<td>56.7</td>
|
||||||
|
<td>55.2</td>
|
||||||
|
<td>52.8</td>
|
||||||
|
<td>46.1</td>
|
||||||
|
<td>73.6 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>AlignBench v1.1</td>
|
||||||
|
<td>7.10</td>
|
||||||
|
<td>6.61</td>
|
||||||
|
<td>7.10</td>
|
||||||
|
<td>5.68</td>
|
||||||
|
<td>5.82</td>
|
||||||
|
<td>5.73</td>
|
||||||
|
<td>6.74 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>FollowBench-zh (SSR)</td>
|
||||||
|
<td>63.0</td>
|
||||||
|
<td>56.4</td>
|
||||||
|
<td>57.0</td>
|
||||||
|
<td>50.6</td>
|
||||||
|
<td>64.6</td>
|
||||||
|
<td>58.1</td>
|
||||||
|
<td>66.8 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="15" align="left"><strong>Math</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>MATH</td>
|
||||||
|
<td>49.6</td>
|
||||||
|
<td>50.6</td>
|
||||||
|
<td>46.0</td>
|
||||||
|
<td>51.9</td>
|
||||||
|
<td>41.8</td>
|
||||||
|
<td>46.4</td>
|
||||||
|
<td>46.6 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>GSM8K</td>
|
||||||
|
<td>82.3</td>
|
||||||
|
<td>79.6</td>
|
||||||
|
<td>79.7</td>
|
||||||
|
<td>84.5</td>
|
||||||
|
<td>76.4</td>
|
||||||
|
<td>82.7</td>
|
||||||
|
<td>81.1 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>MathBench</td>
|
||||||
|
<td>63.4</td>
|
||||||
|
<td>59.4</td>
|
||||||
|
<td>45.8</td>
|
||||||
|
<td>54.3</td>
|
||||||
|
<td>48.9</td>
|
||||||
|
<td>54.9</td>
|
||||||
|
<td>65.6 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="15" align="left"><strong>Code</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>HumanEval+</td>
|
||||||
|
<td>70.1</td>
|
||||||
|
<td>67.1</td>
|
||||||
|
<td>61.6</td>
|
||||||
|
<td>62.8</td>
|
||||||
|
<td>66.5</td>
|
||||||
|
<td>68.9</td>
|
||||||
|
<td>68.3 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>MBPP+</td>
|
||||||
|
<td>57.1</td>
|
||||||
|
<td>62.2</td>
|
||||||
|
<td>64.3</td>
|
||||||
|
<td>55.3</td>
|
||||||
|
<td>71.4</td>
|
||||||
|
<td>55.8</td>
|
||||||
|
<td>63.2 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>LiveCodeBench v3</td>
|
||||||
|
<td>22.2</td>
|
||||||
|
<td>20.2</td>
|
||||||
|
<td>19.2</td>
|
||||||
|
<td>20.4</td>
|
||||||
|
<td>24.0</td>
|
||||||
|
<td>19.6</td>
|
||||||
|
<td>22.6 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="15" align="left"><strong>Function Call</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>BFCL v2</td>
|
||||||
|
<td>71.6</td>
|
||||||
|
<td>70.1</td>
|
||||||
|
<td>19.2</td>
|
||||||
|
<td>73.3</td>
|
||||||
|
<td>75.4</td>
|
||||||
|
<td>48.4</td>
|
||||||
|
<td>76.0 </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="15" align="left"><strong>Overall</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Average</td>
|
||||||
|
<td>65.3</td>
|
||||||
|
<td>65.0</td>
|
||||||
|
<td>57.9</td>
|
||||||
|
<td>60.8</td>
|
||||||
|
<td>61.0</td>
|
||||||
|
<td>57.2</td>
|
||||||
|
<td><strong>66.3</strong></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
## Statement
|
||||||
|
* As a language model, MiniCPM3-4B generates content by learning from a vast amount of text.
|
||||||
|
* However, it does not possess the ability to comprehend or express personal opinions or value judgments.
|
||||||
|
* Any content generated by MiniCPM3-4B does not represent the viewpoints or positions of the model developers.
|
||||||
|
* Therefore, when using content generated by MiniCPM3-4B, users should take full responsibility for evaluating and verifying it on their own.
|
||||||
|
|
||||||
|
## LICENSE
|
||||||
|
* This repository is released under the [Apache-2.0](https://github.com/OpenBMB/MiniCPM/blob/main/LICENSE) License.
|
||||||
|
* The usage of MiniCPM3-4B model weights must strictly follow [MiniCPM Model License.md](https://github.com/OpenBMB/MiniCPM/blob/main/MiniCPM%20Model%20License.md).
|
||||||
|
* The models and weights of MiniCPM3-4B are completely free for academic research. after filling out a ["questionnaire"](https://modelbest.feishu.cn/share/base/form/shrcnpV5ZT9EJ6xYjh3Kx0J6v8g) for registration, are also available for free commercial use.
|
||||||
|
|
||||||
|
## Citation
|
||||||
|
|
||||||
|
```
|
||||||
|
@article{hu2024minicpm,
|
||||||
|
title={MiniCPM: Unveiling the Potential of Small Language Models with Scalable Training Strategies},
|
||||||
|
author={Hu, Shengding and Tu, Yuge and Han, Xu and He, Chaoqun and Cui, Ganqu and Long, Xiang and Zheng, Zhi and Fang, Yewei and Huang, Yuxiang and Zhao, Weilin and others},
|
||||||
|
journal={arXiv preprint arXiv:2404.06395},
|
||||||
|
year={2024}
|
||||||
|
}
|
||||||
|
```
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"<|execute_end|>": 73444,
|
||||||
|
"<|execute_start|>": 73443,
|
||||||
|
"<|fim_middle|>": 73446,
|
||||||
|
"<|fim_prefix|>": 73445,
|
||||||
|
"<|fim_suffix|>": 73447,
|
||||||
|
"<|im_end|>": 73440,
|
||||||
|
"<|im_start|>": 73441,
|
||||||
|
"<|tool_call|>": 73442
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"_name_or_path": "openbmb/MiniCPM3-4B",
|
||||||
|
"architectures": [
|
||||||
|
"MiniCPM3ForCausalLM"
|
||||||
|
],
|
||||||
|
"auto_map": {
|
||||||
|
"AutoConfig": "configuration_minicpm.MiniCPM3Config",
|
||||||
|
"AutoModel": "modeling_minicpm.MiniCPM3Model",
|
||||||
|
"AutoModelForCausalLM": "modeling_minicpm.MiniCPM3ForCausalLM",
|
||||||
|
"AutoModelForSeq2SeqLM": "modeling_minicpm.MiniCPM3ForCausalLM",
|
||||||
|
"AutoModelForSequenceClassification": "modeling_minicpm.MiniCPM3ForSequenceClassification"
|
||||||
|
},
|
||||||
|
"bos_token_id": 1,
|
||||||
|
"eos_token_id": [2, 73440],
|
||||||
|
"hidden_act": "silu",
|
||||||
|
"initializer_range": 0.1,
|
||||||
|
"hidden_size": 2560,
|
||||||
|
"num_hidden_layers": 62,
|
||||||
|
"intermediate_size": 6400,
|
||||||
|
"max_position_embeddings": 32768,
|
||||||
|
"num_attention_heads": 40,
|
||||||
|
"num_key_value_heads": 40,
|
||||||
|
"qk_nope_head_dim": 64,
|
||||||
|
"qk_rope_head_dim": 32,
|
||||||
|
"q_lora_rank": 768,
|
||||||
|
"kv_lora_rank": 256,
|
||||||
|
"rms_norm_eps": 1e-05,
|
||||||
|
"rope_scaling": {
|
||||||
|
"type": "longrope",
|
||||||
|
"long_factor": [1.0591234137867171, 1.1241891283591912, 1.2596935748670968, 1.5380380402321725, 2.093982484148734, 3.1446935121267696, 4.937952647693647, 7.524541999994549, 10.475458000005451, 13.062047352306353, 14.85530648787323, 15.906017515851266, 16.461961959767827, 16.740306425132907, 16.87581087164081, 16.940876586213285],
|
||||||
|
"short_factor": [1.0591234137867171, 1.1241891283591912, 1.2596935748670968, 1.5380380402321725, 2.093982484148734, 3.1446935121267696, 4.937952647693647, 7.524541999994549, 10.475458000005451, 13.062047352306353, 14.85530648787323, 15.906017515851266, 16.461961959767827, 16.740306425132907, 16.87581087164081, 16.940876586213285],
|
||||||
|
"original_max_position_embeddings": 32768
|
||||||
|
},
|
||||||
|
"torch_dtype": "bfloat16",
|
||||||
|
"transformers_version": "4.41.0",
|
||||||
|
"use_cache": true,
|
||||||
|
"vocab_size": 73448,
|
||||||
|
"scale_emb": 12,
|
||||||
|
"dim_model_base": 256,
|
||||||
|
"scale_depth": 1.4
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
{"framework":"Pytorch","task":"text-generation"}
|
|
@ -0,0 +1,195 @@
|
||||||
|
# coding=utf-8
|
||||||
|
# Copyright 2022 EleutherAI and the HuggingFace Inc. team. All rights reserved.
|
||||||
|
#
|
||||||
|
# This code is based on EleutherAI's GPT-NeoX library and the GPT-NeoX
|
||||||
|
# and OPT implementations in this library. It has been modified from its
|
||||||
|
# original forms to accommodate minor architectural differences compared
|
||||||
|
# to GPT-NeoX and OPT used by the Meta AI team that trained the model.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
""" MiniCPM model configuration"""
|
||||||
|
|
||||||
|
from transformers.configuration_utils import PretrainedConfig
|
||||||
|
from transformers.utils import logging
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.get_logger(__name__)
|
||||||
|
|
||||||
|
MINICPM_PRETRAINED_CONFIG_ARCHIVE_MAP = {}
|
||||||
|
|
||||||
|
|
||||||
|
class MiniCPM3Config(PretrainedConfig):
|
||||||
|
r"""
|
||||||
|
This is the configuration class to store the configuration of a [`MiniCPMModel`]. It is used to instantiate an MiniCPM
|
||||||
|
model according to the specified arguments, defining the model architecture. Instantiating a configuration with the
|
||||||
|
defaults will yield a similar configuration to that of the MiniCPM-7B.
|
||||||
|
|
||||||
|
Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
|
||||||
|
documentation from [`PretrainedConfig`] for more information.
|
||||||
|
|
||||||
|
|
||||||
|
Args:
|
||||||
|
vocab_size (`int`, *optional*, defaults to 32000):
|
||||||
|
Vocabulary size of the MiniCPM model. Defines the number of different tokens that can be represented by the
|
||||||
|
`inputs_ids` passed when calling [`MiniCPMModel`]
|
||||||
|
hidden_size (`int`, *optional*, defaults to 4096):
|
||||||
|
Dimension of the hidden representations.
|
||||||
|
intermediate_size (`int`, *optional*, defaults to 11008):
|
||||||
|
Dimension of the MLP representations.
|
||||||
|
num_hidden_layers (`int`, *optional*, defaults to 32):
|
||||||
|
Number of hidden layers in the Transformer decoder.
|
||||||
|
num_attention_heads (`int`, *optional*, defaults to 32):
|
||||||
|
Number of attention heads for each attention layer in the Transformer decoder.
|
||||||
|
num_key_value_heads (`int`, *optional*):
|
||||||
|
This is the number of key_value heads that should be used to implement Grouped Query Attention. If
|
||||||
|
`num_key_value_heads=num_attention_heads`, the model will use Multi Head Attention (MHA), if
|
||||||
|
`num_key_value_heads=1 the model will use Multi Query Attention (MQA) otherwise GQA is used. When
|
||||||
|
converting a multi-head checkpoint to a GQA checkpoint, each group key and value head should be constructed
|
||||||
|
by meanpooling all the original heads within that group. For more details checkout [this
|
||||||
|
paper](https://arxiv.org/pdf/2305.13245.pdf). If it is not specified, will default to
|
||||||
|
`num_attention_heads`.
|
||||||
|
hidden_act (`str` or `function`, *optional*, defaults to `"silu"`):
|
||||||
|
The non-linear activation function (function or string) in the decoder.
|
||||||
|
max_position_embeddings (`int`, *optional*, defaults to 2048):
|
||||||
|
The maximum sequence length that this model might ever be used with. MiniCPM 1 supports up to 2048 tokens,
|
||||||
|
MiniCPM 2 up to 4096, CodeMiniCPM up to 16384.
|
||||||
|
initializer_range (`float`, *optional*, defaults to 0.02):
|
||||||
|
The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
|
||||||
|
rms_norm_eps (`float`, *optional*, defaults to 1e-06):
|
||||||
|
The epsilon used by the rms normalization layers.
|
||||||
|
use_cache (`bool`, *optional*, defaults to `True`):
|
||||||
|
Whether or not the model should return the last key/values attentions (not used by all models). Only
|
||||||
|
relevant if `config.is_decoder=True`.
|
||||||
|
pad_token_id (`int`, *optional*):
|
||||||
|
Padding token id.
|
||||||
|
bos_token_id (`int`, *optional*, defaults to 1):
|
||||||
|
Beginning of stream token id.
|
||||||
|
eos_token_id (`int`, *optional*, defaults to 2):
|
||||||
|
End of stream token id.
|
||||||
|
pretraining_tp (`int`, *optional*, defaults to 1):
|
||||||
|
Experimental feature. Tensor parallelism rank used during pretraining. Please refer to [this
|
||||||
|
document](https://huggingface.co/docs/transformers/parallelism) to understand more about it. This value is
|
||||||
|
necessary to ensure exact reproducibility of the pretraining results. Please refer to [this
|
||||||
|
issue](https://github.com/pytorch/pytorch/issues/76232).
|
||||||
|
tie_word_embeddings (`bool`, *optional*, defaults to `False`):
|
||||||
|
Whether to tie weight embeddings
|
||||||
|
rope_theta (`float`, *optional*, defaults to 10000.0):
|
||||||
|
The base period of the RoPE embeddings.
|
||||||
|
rope_scaling (`Dict`, *optional*):
|
||||||
|
Dictionary containing the scaling configuration for the RoPE embeddings. Currently supports two scaling
|
||||||
|
strategies: linear and dynamic. Their scaling factor must be a float greater than 1. The expected format is
|
||||||
|
`{"type": strategy name, "factor": scaling factor}`. When using this flag, don't update
|
||||||
|
`max_position_embeddings` to the expected new maximum. See the following thread for more information on how
|
||||||
|
these scaling strategies behave:
|
||||||
|
https://www.reddit.com/r/LocalMiniCPM/comments/14mrgpr/dynamically_scaled_rope_further_increases/. This is an
|
||||||
|
experimental feature, subject to breaking API changes in future versions.
|
||||||
|
attention_bias (`bool`, defaults to `False`, *optional*, defaults to `False`):
|
||||||
|
Whether to use a bias in the query, key, value and output projection layers during self-attention.
|
||||||
|
attention_dropout (`float`, *optional*, defaults to 0.0):
|
||||||
|
The dropout ratio for the attention probabilities.
|
||||||
|
|
||||||
|
```python
|
||||||
|
>>> from transformers import MiniCPMModel, MiniCPMConfig
|
||||||
|
|
||||||
|
>>> # Initializing a MiniCPM minicpm-7b style configuration
|
||||||
|
>>> configuration = MiniCPMConfig()
|
||||||
|
|
||||||
|
>>> # Initializing a model from the minicpm-7b style configuration
|
||||||
|
>>> model = MiniCPMModel(configuration)
|
||||||
|
|
||||||
|
>>> # Accessing the model configuration
|
||||||
|
>>> configuration = model.config
|
||||||
|
```"""
|
||||||
|
|
||||||
|
model_type = "minicpm3"
|
||||||
|
keys_to_ignore_at_inference = ["past_key_values"]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
vocab_size=32000,
|
||||||
|
hidden_size=4096,
|
||||||
|
intermediate_size=11008,
|
||||||
|
num_hidden_layers=32,
|
||||||
|
num_attention_heads=32,
|
||||||
|
num_key_value_heads=None,
|
||||||
|
qk_nope_head_dim=64,
|
||||||
|
qk_rope_head_dim=32,
|
||||||
|
q_lora_rank=768,
|
||||||
|
kv_lora_rank=256,
|
||||||
|
v_head_dim=None,
|
||||||
|
head_dim=None,
|
||||||
|
hidden_act="silu",
|
||||||
|
max_position_embeddings=2048,
|
||||||
|
initializer_range=0.02,
|
||||||
|
rms_norm_eps=1e-6,
|
||||||
|
use_cache=True,
|
||||||
|
pad_token_id=None,
|
||||||
|
bos_token_id=1,
|
||||||
|
eos_token_id=2,
|
||||||
|
pretraining_tp=1,
|
||||||
|
tie_word_embeddings=True,
|
||||||
|
rope_theta=10000.0,
|
||||||
|
rope_scaling=None,
|
||||||
|
attention_bias=False,
|
||||||
|
attention_dropout=0.0,
|
||||||
|
scale_emb=1,
|
||||||
|
dim_model_base=1,
|
||||||
|
scale_depth=1,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
self.vocab_size = vocab_size
|
||||||
|
self.max_position_embeddings = max_position_embeddings
|
||||||
|
self.hidden_size = hidden_size
|
||||||
|
self.intermediate_size = intermediate_size
|
||||||
|
self.num_hidden_layers = num_hidden_layers
|
||||||
|
self.num_attention_heads = num_attention_heads
|
||||||
|
self.qk_nope_head_dim = qk_nope_head_dim
|
||||||
|
self.qk_rope_head_dim = qk_rope_head_dim
|
||||||
|
self.q_lora_rank = q_lora_rank
|
||||||
|
self.kv_lora_rank = kv_lora_rank
|
||||||
|
|
||||||
|
if v_head_dim is None:
|
||||||
|
v_head_dim = qk_nope_head_dim
|
||||||
|
self.v_head_dim = v_head_dim
|
||||||
|
|
||||||
|
# for backward compatibility
|
||||||
|
if num_key_value_heads is None:
|
||||||
|
num_key_value_heads = num_attention_heads
|
||||||
|
|
||||||
|
self.num_key_value_heads = num_key_value_heads
|
||||||
|
self.hidden_act = hidden_act
|
||||||
|
self.initializer_range = initializer_range
|
||||||
|
self.rms_norm_eps = rms_norm_eps
|
||||||
|
self.pretraining_tp = pretraining_tp
|
||||||
|
self.use_cache = use_cache
|
||||||
|
self.rope_theta = rope_theta
|
||||||
|
self.rope_scaling = rope_scaling
|
||||||
|
self.attention_bias = attention_bias
|
||||||
|
self.attention_dropout = attention_dropout
|
||||||
|
self.scale_emb = scale_emb
|
||||||
|
self.dim_model_base = dim_model_base
|
||||||
|
self.scale_depth = scale_depth
|
||||||
|
self.head_dim = self.qk_nope_head_dim + self.qk_rope_head_dim
|
||||||
|
|
||||||
|
super().__init__(
|
||||||
|
pad_token_id=pad_token_id,
|
||||||
|
bos_token_id=bos_token_id,
|
||||||
|
eos_token_id=eos_token_id,
|
||||||
|
tie_word_embeddings=tie_word_embeddings,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
import flash_attn
|
||||||
|
self._attn_implementation = "flash_attention_2"
|
||||||
|
except:
|
||||||
|
pass
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"do_sample": true,
|
||||||
|
"top_p": 0.8,
|
||||||
|
"temperature": 0.8,
|
||||||
|
"bos_token_id": 1,
|
||||||
|
"eos_token_id": [2, 73440]
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,81 @@
|
||||||
|
{
|
||||||
|
"additional_special_tokens": [
|
||||||
|
{
|
||||||
|
"content": "<|im_end|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": "<|im_start|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": "<|tool_call|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": "<|execute_start|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": "<|execute_end|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": "<|fim_prefix|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": "<|fim_middle|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": "<|fim_suffix|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bos_token": {
|
||||||
|
"content": "<s>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
"eos_token": {
|
||||||
|
"content": "</s>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
"unk_token": {
|
||||||
|
"content": "<unk>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,431 @@
|
||||||
|
import ast
|
||||||
|
import json
|
||||||
|
import keyword
|
||||||
|
import traceback
|
||||||
|
import uuid
|
||||||
|
from collections import deque
|
||||||
|
from copy import deepcopy
|
||||||
|
from logging import getLogger
|
||||||
|
from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
|
from datamodel_code_generator import DataModelType
|
||||||
|
from datamodel_code_generator.format import PythonVersion
|
||||||
|
from datamodel_code_generator.model import get_data_model_types
|
||||||
|
from datamodel_code_generator.parser.jsonschema import JsonSchemaParser
|
||||||
|
from jsonschema import Draft202012Validator, exceptions, validate
|
||||||
|
|
||||||
|
from transformers import LlamaTokenizerFast
|
||||||
|
from transformers.tokenization_utils_base import BatchEncoding
|
||||||
|
from transformers.utils import TensorType
|
||||||
|
|
||||||
|
|
||||||
|
logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class MiniCPMTokenizer(LlamaTokenizerFast):
|
||||||
|
def apply_chat_template(
|
||||||
|
self,
|
||||||
|
conversation: Union[List[Dict[str, str]], List[List[Dict[str, str]]]],
|
||||||
|
tools: Optional[List[Dict]] = None,
|
||||||
|
documents: Optional[List[Dict[str, str]]] = None,
|
||||||
|
chat_template: Optional[str] = None,
|
||||||
|
add_generation_prompt: bool = False,
|
||||||
|
tokenize: bool = True,
|
||||||
|
padding: bool = False,
|
||||||
|
truncation: bool = False,
|
||||||
|
max_length: Optional[int] = None,
|
||||||
|
return_tensors: Optional[Union[str, TensorType]] = None,
|
||||||
|
return_dict: bool = False,
|
||||||
|
return_assistant_tokens_mask: bool = False,
|
||||||
|
tokenizer_kwargs: Optional[Dict[str, Any]] = None,
|
||||||
|
**kwargs,
|
||||||
|
) -> Union[str, List[int], List[str], List[List[int]], BatchEncoding]:
|
||||||
|
if tools is None:
|
||||||
|
tools = []
|
||||||
|
check_messages(conversation, tools)
|
||||||
|
functions = [tool["function"] for tool in tools]
|
||||||
|
conversation = self.reorder_tool_response(conversation)
|
||||||
|
input_messages = input_format(conversation, functions, add_to_system=True)
|
||||||
|
return super().apply_chat_template(
|
||||||
|
input_messages,
|
||||||
|
tools=None,
|
||||||
|
documents=documents,
|
||||||
|
chat_template=chat_template,
|
||||||
|
add_generation_prompt=add_generation_prompt,
|
||||||
|
tokenize=tokenize,
|
||||||
|
padding=padding,
|
||||||
|
truncation=truncation,
|
||||||
|
max_length=max_length,
|
||||||
|
return_tensors=return_tensors,
|
||||||
|
return_dict=return_dict,
|
||||||
|
return_assistant_tokens_mask=return_assistant_tokens_mask,
|
||||||
|
tokenizer_kwargs=tokenizer_kwargs,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
def reorder_tool_response(self, conversation: List[Dict[str, str]]):
|
||||||
|
tool_call_ids = deque()
|
||||||
|
tool_responses = deque()
|
||||||
|
|
||||||
|
new_conversation = []
|
||||||
|
for message in conversation:
|
||||||
|
if (
|
||||||
|
message["role"] == "assistant"
|
||||||
|
and "tool_calls" in message
|
||||||
|
and message["tool_calls"] is not None
|
||||||
|
and len(message["tool_calls"]) > 0
|
||||||
|
):
|
||||||
|
for tool_call in message["tool_calls"]:
|
||||||
|
tool_call_ids.append(tool_call["id"])
|
||||||
|
new_conversation.append(message)
|
||||||
|
elif message["role"] == "tool":
|
||||||
|
tool_call_id = message.get("tool_call_id", None)
|
||||||
|
if tool_call_id == tool_call_ids[0]:
|
||||||
|
new_conversation.append(message)
|
||||||
|
tool_call_ids.popleft()
|
||||||
|
while (
|
||||||
|
len(tool_call_ids) > 0
|
||||||
|
and len(tool_responses) > 0
|
||||||
|
and tool_call_ids[0] == tool_responses[0]["tool_call_id"]
|
||||||
|
):
|
||||||
|
new_conversation.append(tool_responses.popleft())
|
||||||
|
tool_call_ids.popleft()
|
||||||
|
else:
|
||||||
|
tool_responses.append(message)
|
||||||
|
else:
|
||||||
|
new_conversation.append(message)
|
||||||
|
if len(tool_call_ids) != 0:
|
||||||
|
raise ValueError(f"Message error, not all tool calls have responses: {tool_call_ids}")
|
||||||
|
if len(tool_responses) != 0:
|
||||||
|
raise ValueError(f"Message error, too many tool responses: {tool_responses}")
|
||||||
|
return new_conversation
|
||||||
|
|
||||||
|
def decode_function_call(
|
||||||
|
self,
|
||||||
|
sequence: str,
|
||||||
|
tool_call_start="<|tool_call_start|>",
|
||||||
|
tool_call_end="<|tool_call_end|>",
|
||||||
|
thought_start="<|thought_start|>",
|
||||||
|
thought_end="<|thought_end|>",
|
||||||
|
):
|
||||||
|
if thought_end in sequence and thought_start in sequence:
|
||||||
|
thought_string, sequence = sequence.rsplit(thought_end, 1)
|
||||||
|
thought_string = thought_string.split(thought_start, 1)[1]
|
||||||
|
else:
|
||||||
|
thought_string = ""
|
||||||
|
if tool_call_start in sequence and tool_call_end in sequence:
|
||||||
|
tool_call_string, content = sequence.rsplit(tool_call_end, 1)
|
||||||
|
tool_call_string = tool_call_string.split(tool_call_start, 1)[1]
|
||||||
|
try:
|
||||||
|
tool_calls = []
|
||||||
|
tool_call_string = tool_call_string.strip()
|
||||||
|
if tool_call_string.startswith("```"):
|
||||||
|
tool_call_string = tool_call_string.lstrip("```").strip()
|
||||||
|
if tool_call_string.startswith("python"):
|
||||||
|
tool_call_string = tool_call_string.lstrip("python").strip()
|
||||||
|
if tool_call_string.endswith("```"):
|
||||||
|
tool_call_string = tool_call_string.rstrip("```").strip()
|
||||||
|
for kw in keyword.kwlist:
|
||||||
|
tool_call_string = tool_call_string.replace("," + kw + "=", "," + kw + "_=")
|
||||||
|
tool_call_string = tool_call_string.replace(" " + kw + "=", " " + kw + "_=")
|
||||||
|
tool_call_string = tool_call_string.replace("(" + kw + "=", "(" + kw + "_=")
|
||||||
|
|
||||||
|
parsed = ast.parse(tool_call_string)
|
||||||
|
|
||||||
|
for elem in parsed.body:
|
||||||
|
assert isinstance(elem.value, ast.Call)
|
||||||
|
calls = resolve_ast_call(elem.value)
|
||||||
|
|
||||||
|
for func_name, func_args in calls.items():
|
||||||
|
new_args = {}
|
||||||
|
for k, v in func_args.items():
|
||||||
|
for kw in keyword.kwlist:
|
||||||
|
if k == kw + "_":
|
||||||
|
k = kw
|
||||||
|
new_args[k] = v
|
||||||
|
|
||||||
|
this_one = {"name": func_name, "arguments": new_args}
|
||||||
|
tool_calls.append(this_one)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"content": content.strip(),
|
||||||
|
"tool_calls": [
|
||||||
|
{"type": "function", "function": tool_call, "id": "call_" + uuid.uuid4().hex}
|
||||||
|
for tool_call in tool_calls
|
||||||
|
],
|
||||||
|
"role": "assistant",
|
||||||
|
}
|
||||||
|
except:
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
return {
|
||||||
|
"content": content.strip(),
|
||||||
|
"role": "assistant",
|
||||||
|
"thought": thought_string,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
return {
|
||||||
|
"content": sequence.strip(),
|
||||||
|
"role": "assistant",
|
||||||
|
"thought": thought_string,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def check_messages(conversation: List[Dict[str, str]], tools: List[Dict]):
|
||||||
|
if tools is not None:
|
||||||
|
for tool in tools:
|
||||||
|
if "type" not in tool or tool["type"] != "function":
|
||||||
|
raise ValueError(f"Tool {tool} is not valid")
|
||||||
|
if "name" not in tool["function"]:
|
||||||
|
raise ValueError(f"Tool {tool} is not valid")
|
||||||
|
if "parameters" not in tool["function"] or not check_tool(tool["function"]["parameters"]["properties"]):
|
||||||
|
raise ValueError(f"Tool {tool} is not valid")
|
||||||
|
for message in conversation:
|
||||||
|
if message["role"] == "assistant" and "tool_calls" in message and len(message["tool_calls"]) > 0:
|
||||||
|
for tool_call in message["tool_calls"]:
|
||||||
|
if "id" not in tool_call:
|
||||||
|
raise ValueError(f"Tool call {tool_call} is not valid")
|
||||||
|
if tool_call["type"] != "function":
|
||||||
|
raise ValueError(f"Tool call {tool_call} is not valid")
|
||||||
|
if "function" not in tool_call:
|
||||||
|
raise ValueError(f"Tool call {tool_call} is not valid")
|
||||||
|
if not check_tool(tool_call["function"]):
|
||||||
|
raise ValueError(f"Tool call function {tool_call['function']} is not valid")
|
||||||
|
elif message["role"] == "tool":
|
||||||
|
if "tool_call_id" not in message:
|
||||||
|
raise ValueError(f"Tool message {message['content']} is not valid")
|
||||||
|
|
||||||
|
|
||||||
|
def check_tool(tool_schema):
|
||||||
|
try:
|
||||||
|
Draft202012Validator.check_schema(tool_schema)
|
||||||
|
return True
|
||||||
|
except exceptions.SchemaError as e:
|
||||||
|
print(f"SchemaError: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def check_args(args, tool_schema):
|
||||||
|
try:
|
||||||
|
validate(instance=args, schema=tool_schema)
|
||||||
|
return True
|
||||||
|
except exceptions.ValidationError as e:
|
||||||
|
print(f"Data failed validation: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def message_format(msg, system_suffix="", user_prefix=""):
|
||||||
|
if "thought" in msg and msg["thought"] is not None and len(msg["thought"]) > 0:
|
||||||
|
thought_prefix = f"<|thought_start|>\n{msg['thought']}\n<|thought_end|>\n"
|
||||||
|
else:
|
||||||
|
thought_prefix = ""
|
||||||
|
if msg["role"] == "assistant":
|
||||||
|
content = msg.get("content", "")
|
||||||
|
if content is None:
|
||||||
|
content = ""
|
||||||
|
if "tool_calls" in msg and msg["tool_calls"] is not None and len(msg["tool_calls"]) > 0:
|
||||||
|
|
||||||
|
def add_quotes(variable):
|
||||||
|
if isinstance(variable, str):
|
||||||
|
return repr(variable)
|
||||||
|
else:
|
||||||
|
return str(variable)
|
||||||
|
|
||||||
|
tool_calls = []
|
||||||
|
for _tool_call in msg["tool_calls"]:
|
||||||
|
if _tool_call is None:
|
||||||
|
continue
|
||||||
|
tool_call = _tool_call["function"]
|
||||||
|
tool_name = tool_call["name"]
|
||||||
|
if "arguments" not in tool_call or tool_call["arguments"] is None:
|
||||||
|
continue
|
||||||
|
if isinstance(tool_call["arguments"], str):
|
||||||
|
try:
|
||||||
|
tool_call["arguments"] = json.loads(tool_call["arguments"])
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
args = ",".join([k + "=" + add_quotes(v) for k, v in tool_call["arguments"].items()])
|
||||||
|
tool_calls.append(f"{tool_name}({args})")
|
||||||
|
|
||||||
|
content = (
|
||||||
|
thought_prefix
|
||||||
|
+ "<|tool_call_start|>\n```python\n"
|
||||||
|
+ "\n".join(tool_calls).strip()
|
||||||
|
+ "\n```\n<|tool_call_end|>\n"
|
||||||
|
+ content
|
||||||
|
)
|
||||||
|
# msg["tool_call_string"] = "\n".join(tool_calls).strip()
|
||||||
|
msg["content"] = content
|
||||||
|
else:
|
||||||
|
content = thought_prefix + content
|
||||||
|
msg["content"] = content
|
||||||
|
elif msg["role"] == "user":
|
||||||
|
msg["content"] = user_prefix + "\n" + msg["content"]
|
||||||
|
elif msg["role"] == "system":
|
||||||
|
msg["content"] = msg["content"] + "\n" + system_suffix
|
||||||
|
msg["content"] = msg["content"].strip()
|
||||||
|
return msg
|
||||||
|
|
||||||
|
|
||||||
|
def jsonschema_to_code(jsonschema: dict) -> str:
|
||||||
|
input_text = json.dumps(jsonschema)
|
||||||
|
data_model_types = get_data_model_types(
|
||||||
|
DataModelType.PydanticBaseModel,
|
||||||
|
PythonVersion.PY_310,
|
||||||
|
)
|
||||||
|
parser = JsonSchemaParser(
|
||||||
|
source=input_text,
|
||||||
|
data_model_type=data_model_types.data_model,
|
||||||
|
data_model_root_type=data_model_types.root_model,
|
||||||
|
data_model_field_type=data_model_types.field_model,
|
||||||
|
data_type_manager_type=data_model_types.data_type_manager,
|
||||||
|
target_python_version=PythonVersion.PY_310,
|
||||||
|
dump_resolve_reference_action=data_model_types.dump_resolve_reference_action,
|
||||||
|
field_constraints=True,
|
||||||
|
)
|
||||||
|
results = parser.parse()
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def transform_function(function: dict):
|
||||||
|
"""turn json format of function into signature"""
|
||||||
|
params, default_params = [], []
|
||||||
|
for prop_name, prop in function["parameters"]["properties"].items():
|
||||||
|
if "default" in prop:
|
||||||
|
default_params.append(f'{prop_name}={repr(prop["default"])}')
|
||||||
|
elif prop_name not in function["parameters"].get("required", []):
|
||||||
|
default_params.append(f"{prop_name}={repr(None)}")
|
||||||
|
else:
|
||||||
|
params.append(prop_name)
|
||||||
|
ps = ", ".join(params + default_params)
|
||||||
|
res = "def {f_name}({ps}):\n".format(f_name=function["name"], ps=ps)
|
||||||
|
f_des = function.get("description", "")
|
||||||
|
content = jsonschema_to_code(function["parameters"])
|
||||||
|
if "class" in content:
|
||||||
|
i = content.index("class")
|
||||||
|
# print(content[:i])
|
||||||
|
content = content[i:]
|
||||||
|
classes, args = content.split("class Model(BaseModel):", 1)
|
||||||
|
lint_msg = f' """\n {f_des}\n Args:\n{args}\n """\n'
|
||||||
|
res += lint_msg
|
||||||
|
if len(classes) > 0:
|
||||||
|
res = classes + res
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def input_format(messages: List[Dict], tools: List[Dict], add_to_system=True):
|
||||||
|
"""
|
||||||
|
Process the input messages, global_arguments, tools, tool_choice,
|
||||||
|
and convert it into a input string.
|
||||||
|
The global arguments and tools can not be both empty.
|
||||||
|
parameters:
|
||||||
|
messages: List[Dict]
|
||||||
|
the input messages
|
||||||
|
For example:
|
||||||
|
tools: List[Dict]
|
||||||
|
the tools list you can use
|
||||||
|
For example:
|
||||||
|
"""
|
||||||
|
messages = deepcopy(messages)
|
||||||
|
tools = deepcopy(tools)
|
||||||
|
if tools is not None and len(tools) > 0:
|
||||||
|
header = (
|
||||||
|
"from enum import Enum\nfrom typing import List, Dict, Optional\nfrom pydantic import BaseModel, Field\n\n"
|
||||||
|
)
|
||||||
|
tools_string = header
|
||||||
|
for tool in tools:
|
||||||
|
try:
|
||||||
|
tools_string += "\n\n" + transform_function(tool)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
tools_template = """# Functions
|
||||||
|
Here is a list of functions that you can invoke:
|
||||||
|
```python
|
||||||
|
{tools}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Function Call Rule and Output Format
|
||||||
|
- If the user's question can be answered without calling any function, please answer the user's question directly. In this situation, you should return your thought and answer the user's question directly.
|
||||||
|
- If the user cannot be answered without calling any function, and the user does not provide enough information to call functions, please ask the user for more information. In this situation, you should return your thought and ask the user for more information.
|
||||||
|
- If the user's question cannot be answered without calling any function, and the user has provided enough information to call functions to solve it, you should call the functions. In this situation, the assistant should return your thought and call the functions.
|
||||||
|
- Use default parameters unless the user has specified otherwise.
|
||||||
|
- You should answer in the following format:
|
||||||
|
|
||||||
|
<|thought_start|>
|
||||||
|
{{explain why the user's question can be answered without calling a function or why you should ask the user for more information or why you should call one or more functions and your plan to solve the user's question.}}
|
||||||
|
<|thought_end|>
|
||||||
|
<|tool_call_start|>
|
||||||
|
```python
|
||||||
|
func1(params_name=params_value, params_name2=params_value2...)
|
||||||
|
func2(params)
|
||||||
|
```
|
||||||
|
<|tool_call_end|>
|
||||||
|
{{answer the user's question directly or ask the user for more information}}
|
||||||
|
"""
|
||||||
|
tools_string = tools_template.format(tools=tools_string).strip()
|
||||||
|
else:
|
||||||
|
tools_string = ""
|
||||||
|
|
||||||
|
if add_to_system:
|
||||||
|
return [message_format(msg, system_suffix=tools_string, user_prefix="") for msg in messages]
|
||||||
|
else:
|
||||||
|
return [message_format(msg, system_suffix="", user_prefix=tools_string) for msg in messages]
|
||||||
|
|
||||||
|
|
||||||
|
# This is a modified version of
|
||||||
|
# https://github.com/ShishirPatil/gorilla/blob/main/berkeley-function-call-leaderboard/bfcl/model_handler/utils.py
|
||||||
|
# Thanks to the gorilla team for the original implementation
|
||||||
|
def resolve_ast_call(elem):
|
||||||
|
# Handle nested attributes for deeply nested module paths
|
||||||
|
func_parts = []
|
||||||
|
func_part = elem.func
|
||||||
|
while isinstance(func_part, ast.Attribute):
|
||||||
|
func_parts.append(func_part.attr)
|
||||||
|
func_part = func_part.value
|
||||||
|
if isinstance(func_part, ast.Name):
|
||||||
|
func_parts.append(func_part.id)
|
||||||
|
func_name = ".".join(reversed(func_parts))
|
||||||
|
args_dict = {}
|
||||||
|
for arg in elem.keywords:
|
||||||
|
output = resolve_ast_by_type(arg.value)
|
||||||
|
args_dict[arg.arg] = output
|
||||||
|
return {func_name: args_dict}
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_ast_by_type(value):
|
||||||
|
if isinstance(value, ast.Constant):
|
||||||
|
if value.value is Ellipsis:
|
||||||
|
output = "..."
|
||||||
|
else:
|
||||||
|
output = value.value
|
||||||
|
elif isinstance(value, ast.UnaryOp):
|
||||||
|
output = -value.operand.value
|
||||||
|
elif isinstance(value, ast.List):
|
||||||
|
output = [resolve_ast_by_type(v) for v in value.elts]
|
||||||
|
elif isinstance(value, ast.Dict):
|
||||||
|
output = {resolve_ast_by_type(k): resolve_ast_by_type(v) for k, v in zip(value.keys, value.values)}
|
||||||
|
elif isinstance(value, ast.NameConstant): # Added this condition to handle boolean values
|
||||||
|
output = value.value
|
||||||
|
elif isinstance(value, ast.BinOp): # Added this condition to handle function calls as arguments
|
||||||
|
output = eval(ast.unparse(value))
|
||||||
|
elif isinstance(value, ast.Name):
|
||||||
|
output = value.id
|
||||||
|
elif isinstance(value, ast.Call):
|
||||||
|
if len(value.keywords) == 0:
|
||||||
|
output = ast.unparse(value)
|
||||||
|
else:
|
||||||
|
output = resolve_ast_call(value)
|
||||||
|
elif isinstance(value, ast.Tuple):
|
||||||
|
output = tuple(resolve_ast_by_type(v) for v in value.elts)
|
||||||
|
elif isinstance(value, ast.Lambda):
|
||||||
|
output = eval(ast.unparse(value.body[0].value))
|
||||||
|
elif isinstance(value, ast.Ellipsis):
|
||||||
|
output = "..."
|
||||||
|
elif isinstance(value, ast.Subscript):
|
||||||
|
try:
|
||||||
|
output = ast.unparse(value.body[0].value)
|
||||||
|
except:
|
||||||
|
output = ast.unparse(value.value) + "[" + ast.unparse(value.slice) + "]"
|
||||||
|
else:
|
||||||
|
raise Exception(f"Unsupported AST type: {type(value)}")
|
||||||
|
return output
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,119 @@
|
||||||
|
{
|
||||||
|
"auto_map": {
|
||||||
|
"AutoTokenizer": ["tokenization_minicpm.MiniCPMTokenizer", null]
|
||||||
|
},
|
||||||
|
"add_bos_token": true,
|
||||||
|
"add_eos_token": false,
|
||||||
|
"added_tokens_decoder": {
|
||||||
|
"0": {
|
||||||
|
"content": "<unk>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"1": {
|
||||||
|
"content": "<s>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"content": "</s>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"73440": {
|
||||||
|
"content": "<|im_end|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"73441": {
|
||||||
|
"content": "<|im_start|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"73442": {
|
||||||
|
"content": "<|tool_call|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"73443": {
|
||||||
|
"content": "<|execute_start|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"73444": {
|
||||||
|
"content": "<|execute_end|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"73445": {
|
||||||
|
"content": "<|fim_prefix|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"73446": {
|
||||||
|
"content": "<|fim_middle|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
},
|
||||||
|
"73447": {
|
||||||
|
"content": "<|fim_suffix|>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false,
|
||||||
|
"special": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additional_special_tokens": [
|
||||||
|
"<|im_end|>",
|
||||||
|
"<|im_start|>",
|
||||||
|
"<|tool_call|>",
|
||||||
|
"<|execute_start|>",
|
||||||
|
"<|execute_end|>",
|
||||||
|
"<|fim_prefix|>",
|
||||||
|
"<|fim_middle|>",
|
||||||
|
"<|fim_suffix|>"
|
||||||
|
],
|
||||||
|
"bos_token": "<s>",
|
||||||
|
"clean_up_tokenization_spaces": false,
|
||||||
|
"eos_token": "<|im_end|>",
|
||||||
|
"legacy": true,
|
||||||
|
"model_max_length": 1000000000000000019884624838656,
|
||||||
|
"pad_token": null,
|
||||||
|
"sp_model_kwargs": {},
|
||||||
|
"spaces_between_special_tokens": false,
|
||||||
|
"tokenizer_class": "MiniCPMTokenizer",
|
||||||
|
"unk_token": "<unk>",
|
||||||
|
"use_default_system_prompt": false,
|
||||||
|
"chat_template": "{% for message in messages %}{{'<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant\n' }}{% endif %}"
|
||||||
|
}
|
Loading…
Reference in New Issue