DiTy's picture
Update README.md
94e5830 verified
|
raw
history blame
20.6 kB
metadata
base_model: DiTy/gemma-2-9b-it-russian-function-calling-GGUF
datasets:
  - DiTy/function-calling-trl
language:
  - ru
library_name: transformers
license: apache-2.0
pipeline_tag: text-generation
tags:
  - conversational
  - gemma2
  - function-calling
  - trl

DiTy/gemma-2-9b-it-russian-function-calling-DPO-GGUF

This model is a aligned version of DiTy/gemma-2-9b-it-russian-function-calling-GGUF for more Stricted Function Calling task. Which means that the model avoids answering user questions that are not related to the described functions.

Example of behavior of the base and alignment model:

PROMPT File Size Description

The model has been trained using non-synthetic preference data, fully annotated by humans only, on the Russian version of the DiTy/function-calling-trl dataset.

In addition to safetensors, the model is available in GGUF formats (in this case, you need to download only a single file (how to inference GGUF model)):

Filename Quant type File Size Description
gemma-2-9B-it-russian-function-calling-F16.gguf F16 18.5GB Base model with float16
gemma-2-9B-it-russian-function-calling-Q8_0.gguf Q8_0 9.83GB Extremely high quality, generally unneeded but max available quant.
gemma-2-9B-it-russian-function-calling-Q6_K.gguf Q6_K 7.59GB Very high quality, near perfect, recommended.
gemma-2-9B-it-russian-function-calling-Q5_K_M.gguf Q5_K_M 6.65GB High quality, very usable.
gemma-2-9B-it-russian-function-calling-Q5_K_S.gguf Q5_K_S 6.48GB High quality, very usable.

Model card разделы

Использование (HuggingFace Transformers)

Ниже представлены некоторые фрагменты кода о том, как быстро приступить к запуску модели. Сначала установите библиотеку Transformers с помощью:

pip install -U transformers

Как подготовить ваши функции (tools) для Function Calling

Вы должны написать функции (инструменты), используемые моделью, в коде на Python и обязательно добавить Python docstrings, как в примере ниже:

def get_weather(city: str):
    """
    Функция, которая возвращает погоду в заданном городе.
    
    Args:
        city: Город, для которого надо узнать погоду.
    """
    import random
    
    return "sunny" if random.random() > 0.5 else "rainy"
def get_sunrise_sunset_times(city: str):
    """
    Функция, которая возвращает время восхода и заката для заданного города для текущей даты (дата от пользователя не требуется), в формате списка: [sunrise_time, sunset_time].
    
    Args:
        city: Город, в котором можно узнать время восхода и захода солнца.
    """
    return ["6:00", "18:00"]

Просто используйте chat template для генерации

Далее вам нужно загрузить модель и токенизатор:

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained(
    "DiTy/gemma-2-9b-it-russian-function-calling-GGUF",
    device_map="auto",
    torch_dtype=torch.bfloat16,  # use float16 or float32 if bfloat16 is not available to you.
    cache_dir=PATH_TO_MODEL_DIR,  # optional
)
tokenizer = AutoTokenizer.from_pretrained(
    "DiTy/gemma-2-9b-it-russian-function-calling-GGUF",
    cache_dir=PATH_TO_MODEL_DIR,  # optional
)

Чтобы получить результат генерации, просто используйте apply_chat_template. Чтобы учесть наши написанные функции (инструменты), нам нужно передать их в виде списка через атрибут tools, а также использовать add_prompt_generation=True.

history_messages = [
    {"role": "system", "content": "Ты - полезный помощник, имеющий доступ к следующим функциям. Используйте их при необходимости - "},
    {"role": "user", "content": "Привет, не мог бы ты сказать мне, во сколько в Краснодаре восходит солнце?"}
]
inputs = tokenizer.apply_chat_template(
    history_messages,
    tokenize=False,
    add_generation_prompt=True,  # adding prompt for generation
    tools=[get_weather, get_sunrise_sunset_times],  # our functions (tools)
)
print(inputs)

Тогда наш inputs будет выглядеть следующим образом:

<bos><start_of_turn>user
Ты - полезный помощник, имеющий доступ к следующим функциям. Используйте их при необходимости - {
    "name": "get_weather",
    "description": "Функция, которая возвращает погоду в заданном городе.",
    "parameters": {
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "Город, для которого надо узнать погоду."
            }
        },
        "required": [
            "city"
        ]
    }
},
{
    "name": "get_sunrise_sunset_times",
    "description": "Функция, которая возвращает время восхода и заката для заданного города для текущей даты (дата от пользователя не требуется), в формате списка: [sunrise_time, sunset_time].",
    "parameters": {
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "Город, в котором можно узнать время восхода и захода солнца."
            }
        },
        "required": [
            "city"
        ]
    }
}
Привет, не мог бы ты сказать мне, во сколько в Краснодаре восходит солнце?<end_of_turn>
<start_of_turn>model

Теперь мы можем сгенерировать ответ модели. Будьте осторожны, потому что после apply_chat_template нет необходимости добавлять специальные токены во время токенизации. Поэтому используем add_special_tokens=False:

terminator_ids = [
    tokenizer.eos_token_id,
    tokenizer.convert_tokens_to_ids("<end_of_turn>"),
]
prompt_ids =  tokenizer.encode(inputs, add_special_tokens=False, return_tensors='pt').to(model.device)
generated_ids = model.generate(
    prompt_ids,
    max_new_tokens=512,
    eos_token_id=terminator_ids,
    bos_token_id=tokenizer.bos_token_id,
)
generated_response = tokenizer.decode(generated_ids[0][prompt_ids.shape[-1]:], skip_special_tokens=False)  # `skip_special_tokens=False` for debug
print(generated_response)

Мы получаем генерацию в виде вызова функции:

Вызов функции: {"name": "get_sunrise_sunset_times", "arguments": {"city": "Краснодар"}}<end_of_turn>

Отлично, теперь мы можем получать и обрабатывать результаты с помощью нашей вызываемой функции, а затем предоставлять модели ответ функции:

history_messages = [
    {"role": "system", "content": "Ты - полезный помощник, имеющий доступ к следующим функциям. Используйте их при необходимости - "},
    {"role": "user", "content": "Привет, не мог бы ты сказать мне, во сколько в Краснодаре восходит солнце?"},
    {"role": "function-call", "content": '{"name": "get_sunrise_sunset_times", "arguments": {"city": "Los Angeles"}}'},
    {"role": "function-response", "content": '{"times_list": ["6:00", "18:00"]}'},  # гипотетический ответ от нашей функции
]
inputs = tokenizer.apply_chat_template(
    history_messages,
    tokenize=False,
    add_generation_prompt=True,  # добавление запроса для генерации
    tools=[get_weather, get_sunrise_sunset_times],  # наши функции (tools)
)
print(inputs)

Давайте убедимся, что inputs верны:

<bos><start_of_turn>user
Ты - полезный помощник, имеющий доступ к следующим функциям. Используйте их при необходимости - {
    "name": "get_weather",
    "description": "Функция, которая возвращает погоду в заданном городе.",
    "parameters": {
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "Город, для которого надо узнать погоду."
            }
        },
        "required": [
            "city"
        ]
    }
},
{
    "name": "get_sunrise_sunset_times",
    "description": "Функция, которая возвращает время восхода и заката для заданного города для текущей даты (дата от пользователя не требуется), в формате списка: [sunrise_time, sunset_time].",
    "parameters": {
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "Город, в котором можно узнать время восхода и захода солнца."
            }
        },
        "required": [
            "city"
        ]
    }
}
Привет, не мог бы ты сказать мне, во сколько в Краснодаре восходит солнце?<end_of_turn>
<start_of_turn>model
Вызов функции: {"name": "get_sunrise_sunset_times", "arguments": {"city": "Краснодар"}}<end_of_turn>
<start_of_turn>user
Ответ от функции: {"times_list": ["6:00", "18:00"]}<end_of_turn>
<start_of_turn>model

Аналогично, мы генерируем ответ модели:

prompt_ids =  tokenizer.encode(inputs, add_special_tokens=False, return_tensors='pt').to(model.device)
generated_ids = model.generate(
    prompt_ids,
    max_new_tokens=512,
    eos_token_id=terminator_ids,
    bos_token_id=tokenizer.bos_token_id,
)
generated_response = tokenizer.decode(generated_ids[0][prompt_ids.shape[-1]:], skip_special_tokens=False)  # `skip_special_tokens=False` for debug
print(generated_response)

В результате мы получаем ответ модели:

В Краснодаре солнце восходит в 6:00 утра и заходит в 18:00 вечера.<end_of_turn>

Использование через transformers pipeline

Generation via pipeline
from transformers import pipeline
generation_pipeline = pipeline(
    "text-generation",
    model="DiTy/gemma-2-9b-it-russian-function-calling-GGUF",
    model_kwargs={
        "torch_dtype": torch.bfloat16,  # use float16 or float32 if bfloat16 is not supported for you. 
        "cache_dir": PATH_TO_MODEL_DIR,  # OPTIONAL
    },
    device_map="auto",
)
history_messages = [
    {"role": "system", "content": "Ты - полезный помощник, имеющий доступ к следующим функциям. Используйте их при необходимости - "},
    {"role": "user", "content": "Привет, не мог бы ты сказать мне, во сколько в Краснодаре восходит солнце?"},
    {"role": "function-call", "content": '{"name": "get_sunrise_sunset_times", "arguments": {"city": "Краснодар"}}'},
    {"role": "function-response", "content": '{"times_list": ["6:00", "18:00"]}'}
]
inputs = generation_pipeline.tokenizer.apply_chat_template(
    history_messages,
    tokenize=False,
    add_generation_prompt=True,
    tools=[get_weather, get_sunrise_sunset_times],
)
terminator_ids = [
    generation_pipeline.tokenizer.eos_token_id,
    generation_pipeline.tokenizer.convert_tokens_to_ids("<end_of_turn>")
]
outputs = generation_pipeline(
    inputs,
    max_new_tokens=512,
    eos_token_id=terminator_ids,
)
print(outputs[0]["generated_text"][len(inputs):])

Prompt структура и ожидаемый контент

Для наиболее корректной работы модели предполагается, что будет использоваться apply_chat_template. Необходимо передать историю сообщений в определенном формате.

history_messages = [
    {"role": "...", "content": "..."},
    ...
]

Для использования доступны следующие роли:

  • system - это необязательная роль, ее содержимое всегда размещается в самом начале и перед перечислением функций, доступных модели (инструментов). Вы всегда можете воспользоваться стандартным вариантом, который использовался во время обучения: "Ты - полезный помощник, имеющий доступ к следующим функциям. Используйте их при необходимости - "
  • user - запрос пользователя передается через эту роль.
  • function-call - тело вызова функции передается через эту роль. Хотя модель обучена генерировать вызов функции в виде "Вызов функции: {...}<end_of_turn>", вы все равно должны передать только тело "{...}" в поле "content", поскольку используя apply_chat_template, постскриптум в инструкциях добавляется автоматически.
  • function-response - в этой роли мы должны передать ответ нашей функции в поле "content" в виде словаря '{"name_returnable_value": value}'.
  • model - содержимое, относящееся к этой роли, считается сгенерированным текстом модели.

Структура истории чата для Function Calling

[
    {"role": "system", "content": "Ты - полезный помощник, имеющий доступ к следующим функциям. Используйте их при необходимости - "},
    {"role": "user", "content": "Привет, не мог бы ты сказать мне, во сколько в Краснодаре восходит солнце?"},
    {"role": "function-call", "content": '{"name": "get_sunrise_sunset_times", "arguments": {"city": "Краснодар"}}'},
    {"role": "function-response", "content": '{"times_list": ["6:00", "18:00"]}'}
]

Это выглядит как:

<bos><start_of_turn>user
Ты - полезный помощник, имеющий доступ к следующим функциям. Используйте их при необходимости - {
    "name": "get_weather",
    "description": "Функция, которая возвращает погоду в заданном городе.",
    "parameters": {
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "Город, для которого надо узнать погоду."
            }
        },
        "required": [
            "city"
        ]
    }
},
{
    "name": "get_sunrise_sunset_times",
    "description": "Функция, которая возвращает время восхода и заката для заданного города для текущей даты (дата от пользователя не требуется), в формате списка: [sunrise_time, sunset_time].",
    "parameters": {
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "Город, в котором можно узнать время восхода и захода солнца."
            }
        },
        "required": [
            "city"
        ]
    }
}
Привет, не мог бы ты сказать мне, во сколько в Краснодаре восходит солнце?<end_of_turn>
<start_of_turn>model
Вызов функции: {"name": "get_sunrise_sunset_times", "arguments": {"city": "Краснодар"}}<end_of_turn>
<start_of_turn>user
Ответ от функции: {"times_list": ["6:00", "18:00"]}<end_of_turn>

Структура истории чата для обычного user-model шаблона

[
    {"role": "system", "content": "Ты добрый помощник"},
    {"role": "user", "content": "Расскажи мне о Москве"}
]

Это выглядит как:

<bos><start_of_turn>user
Ты добрый помощник
Расскажи мне о Москве<end_of_turn>

Оценка моделей

В процессе обучения ошибка валидации была приближена к следующим значениям:

Citation

@article{gemma_2024,
    title={Gemma},
    url={https://www.kaggle.com/m/3301},
    DOI={10.34740/KAGGLE/M/3301},
    publisher={Kaggle},
    author={Gemma Team},
    year={2024}
}