初始化项目,由ModelHub XC社区提供模型
Model: litert-community/FunctionGemma_270M_Mobile_Actions Source: Original Platform
This commit is contained in:
52
.gitattributes
vendored
Normal file
52
.gitattributes
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.arrow filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.bin.* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ftz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.h5 filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.joblib filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|
||||||
|
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.onnx filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ot filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.parquet filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pb filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pt filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pth filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.rar filter=lfs diff=lfs merge=lfs -text
|
||||||
|
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tflite filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.xz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.zstandard filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tfevents* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.db* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ark* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
**/*ckpt*data* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
**/*ckpt*.meta filter=lfs diff=lfs merge=lfs -text
|
||||||
|
**/*ckpt*.index filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|
||||||
|
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.gguf* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.ggml filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.llamafile* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pt2 filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.npy filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.npz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pickle filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.pkl filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.tar filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.wasm filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.zst filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|
||||||
|
tokenizer_config.json filter=lfs diff=lfs merge=lfs -text
|
||||||
|
tokenizer.model filter=lfs diff=lfs merge=lfs -text
|
||||||
|
tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
||||||
|
model.safetensors filter=lfs diff=lfs merge=lfs -text
|
||||||
242
README.md
Normal file
242
README.md
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
---
|
||||||
|
base_model: google/functiongemma-270m-it
|
||||||
|
tags:
|
||||||
|
- function-calling
|
||||||
|
- mobile-actions
|
||||||
|
- gemma
|
||||||
|
library_name: transformers
|
||||||
|
datasets:
|
||||||
|
- google/mobile-actions
|
||||||
|
language:
|
||||||
|
- en
|
||||||
|
license: gemma
|
||||||
|
---
|
||||||
|
|
||||||
|
# FunctionGemma 270M for Mobile Actions
|
||||||
|
|
||||||
|
This model is a fine-tuned version of [google/functiongemma-270m-it](https://huggingface.co/google/functiongemma-270m-it) specialized for mobile assistant actions. It has been trained on the [google/mobile-actions](https://huggingface.co/datasets/google/mobile-actions) dataset to perform structured function calling for common mobile device tasks.
|
||||||
|
|
||||||
|
## Model Description
|
||||||
|
|
||||||
|
**Base Model**: `google/functiongemma-270m-it` - A 270M parameter instruction-tuned model from Google's FunctionGemma family, designed for function calling tasks.
|
||||||
|
|
||||||
|
**Specialization**: Mobile assistant actions including:
|
||||||
|
- Calendar event management
|
||||||
|
- Email composition and sending
|
||||||
|
- Contact creation
|
||||||
|
- Flashlight control
|
||||||
|
- Wi-Fi settings navigation
|
||||||
|
- Map location display
|
||||||
|
|
||||||
|
**Training Objective**: The model learns to emit structured function calls in the format `call:<function_name>{arg1:value1,arg2:value2,...}` instead of natural language responses.
|
||||||
|
|
||||||
|
## Supported Functions
|
||||||
|
|
||||||
|
The model is optimized to call these mobile action functions:
|
||||||
|
|
||||||
|
1. **`turn_on_flashlight()`** - Turns the device flashlight on
|
||||||
|
2. **`turn_off_flashlight()`** - Turns the device flashlight off
|
||||||
|
3. **`create_contact(first_name, last_name, phone_number?, email?)`** - Creates a new contact
|
||||||
|
4. **`send_email(to, subject, body?)`** - Sends an email to a recipient
|
||||||
|
5. **`show_map(query)`** - Displays a location on the map by name, business, or address
|
||||||
|
6. **`open_wifi_settings()`** - Opens the Wi-Fi settings screen
|
||||||
|
7. **`create_calendar_event(title, datetime)`** - Creates a calendar event (datetime in ISO format: `YYYY-MM-DDTHH:MM:SS`)
|
||||||
|
|
||||||
|
## Training Details
|
||||||
|
|
||||||
|
### Training Data
|
||||||
|
|
||||||
|
- **Dataset**: [google/mobile-actions](https://huggingface.co/datasets/google/mobile-actions)
|
||||||
|
- **Format**: JSONL with prompt-completion pairs
|
||||||
|
- **Splits**:
|
||||||
|
- Training set: examples with `"metadata": "train"`
|
||||||
|
- Evaluation set: examples with `"metadata": "eval"`
|
||||||
|
- **Preprocessing**: Converted to TRL prompt-completion format with `completion_only_loss=True`
|
||||||
|
|
||||||
|
### Training Procedure
|
||||||
|
|
||||||
|
Fine-tuned using Hugging Face [TRL (Transformer Reinforcement Learning)](https://huggingface.co/docs/trl) with the `SFTTrainer`.
|
||||||
|
|
||||||
|
**Training Configuration**:
|
||||||
|
- **Epochs**: 4
|
||||||
|
- **Batch size**: 8 per device
|
||||||
|
- **Gradient accumulation steps**: 4
|
||||||
|
- **Learning rate**: 5e-5
|
||||||
|
- **Scheduler**: Cosine
|
||||||
|
- **Max sequence length**: 997 tokens (based on longest example: 897 tokens)
|
||||||
|
- **Optimizer**: AdamW (fused)
|
||||||
|
- **Precision**: bfloat16
|
||||||
|
- **Gradient checkpointing**: Enabled
|
||||||
|
- **Completion only loss**: True (trains only on model outputs, not prompts)
|
||||||
|
|
||||||
|
**Training Infrastructure**:
|
||||||
|
- **Hardware**: Google Colab A100 GPU
|
||||||
|
- **Training time**: ~20 minutes for 2 epochs
|
||||||
|
- **Library versions**: transformers==4.57.1, trl==0.25.1, datasets==4.4.1
|
||||||
|
|
||||||
|
### Training Results
|
||||||
|
|
||||||
|
Final metrics after 2 epochs:
|
||||||
|
|
||||||
|
| Step | Training Loss | Validation Loss | Mean Token Accuracy |
|
||||||
|
|------|---------------|-----------------|---------------------|
|
||||||
|
| 500 | 0.008800 | 0.013452 | 0.996691 |
|
||||||
|
|
||||||
|
The model achieved 99.67% token-level accuracy on the validation set, showing significant improvement over the base model's mobile action capabilities.
|
||||||
|
|
||||||
|
## Intended Use
|
||||||
|
|
||||||
|
This model is designed for:
|
||||||
|
- **Mobile AI assistants** that need to execute device actions based on user requests
|
||||||
|
- **Voice-controlled mobile applications**
|
||||||
|
- **Conversational agents** that interact with mobile device features
|
||||||
|
- **On-device AI** applications (can be converted to `.litertlm` format for deployment)
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
### Basic Inference
|
||||||
|
|
||||||
|
```python
|
||||||
|
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Load model and tokenizer
|
||||||
|
model_id = "jprtr/google_mobile_actions"
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
||||||
|
model = AutoModelForCausalLM.from_pretrained(
|
||||||
|
model_id,
|
||||||
|
device_map="auto",
|
||||||
|
attn_implementation="eager",
|
||||||
|
torch_dtype="auto",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create pipeline
|
||||||
|
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
|
||||||
|
|
||||||
|
# Define the tools (function schemas)
|
||||||
|
tools = [
|
||||||
|
{
|
||||||
|
"function": {
|
||||||
|
"name": "create_calendar_event",
|
||||||
|
"description": "Creates a new calendar event.",
|
||||||
|
"parameters": {
|
||||||
|
"type": "OBJECT",
|
||||||
|
"properties": {
|
||||||
|
"title": {"type": "STRING", "description": "The title of the event."},
|
||||||
|
"datetime": {"type": "STRING", "description": "The date and time in YYYY-MM-DDTHH:MM:SS format."},
|
||||||
|
},
|
||||||
|
"required": ["title", "datetime"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"function": {
|
||||||
|
"name": "send_email",
|
||||||
|
"description": "Sends an email.",
|
||||||
|
"parameters": {
|
||||||
|
"type": "OBJECT",
|
||||||
|
"properties": {
|
||||||
|
"to": {"type": "STRING", "description": "The recipient email address."},
|
||||||
|
"subject": {"type": "STRING", "description": "The email subject."},
|
||||||
|
"body": {"type": "STRING", "description": "The email body."},
|
||||||
|
},
|
||||||
|
"required": ["to", "subject"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
# ... add other function definitions
|
||||||
|
]
|
||||||
|
|
||||||
|
# Create messages
|
||||||
|
messages = [
|
||||||
|
{
|
||||||
|
"role": "developer",
|
||||||
|
"content": (
|
||||||
|
"Current date and time given in YYYY-MM-DDTHH:MM:SS format: 2025-07-10T19:06:29\n"
|
||||||
|
"Day of week is Thursday\n"
|
||||||
|
"You are a model that can do function calling with the following functions\n"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": 'Schedule a "team meeting" tomorrow at 4pm.',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
# Apply chat template
|
||||||
|
prompt = tokenizer.apply_chat_template(
|
||||||
|
messages,
|
||||||
|
tools=tools,
|
||||||
|
tokenize=False,
|
||||||
|
add_generation_prompt=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Generate
|
||||||
|
output = pipe(prompt, max_new_tokens=200)[0]["generated_text"][len(prompt):].strip()
|
||||||
|
print("Model output:", output)
|
||||||
|
# Example output: call:create_calendar_event{datetime:2025-07-11T16:00:00,title:team meeting}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parsing Function Calls
|
||||||
|
|
||||||
|
The model outputs function calls in a simple format:
|
||||||
|
```
|
||||||
|
call:<function_name>{arg1:value1,arg2:value2,...}
|
||||||
|
```
|
||||||
|
|
||||||
|
For multiple function calls, they appear sequentially:
|
||||||
|
```
|
||||||
|
call:create_calendar_event{datetime:2025-07-15T10:30:00,title:Dental Checkup}
|
||||||
|
call:send_email{to:user@example.com,subject:Appointment,body:See you there!}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can parse these by:
|
||||||
|
1. Splitting on `call:` to identify individual function calls
|
||||||
|
2. Extracting the function name (text before `{`)
|
||||||
|
3. Parsing the arguments block (content within `{}`)
|
||||||
|
|
||||||
|
## Evaluation
|
||||||
|
|
||||||
|
The model was evaluated on the held-out test set from the mobile-actions dataset. Evaluation metrics compare exact string matching of the model's function call outputs against ground truth labels.
|
||||||
|
|
||||||
|
**Key Observations**:
|
||||||
|
- The base FunctionGemma 270M model often fails to call appropriate functions for mobile actions
|
||||||
|
- After fine-tuning, the model reliably generates correct function calls with proper argument formatting
|
||||||
|
- Token-level accuracy on the validation set: **99.67%**
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- The model is specialized for the 7 mobile action functions listed above and may not generalize well to other function calling tasks
|
||||||
|
- Date/time parsing relies on context provided in the developer message (current date/time must be specified)
|
||||||
|
- The model outputs may occasionally include variations in argument formatting that are semantically correct but don't exactly match the expected format
|
||||||
|
- This is a 270M parameter model, so while efficient for mobile deployment, it may have lower accuracy than larger models
|
||||||
|
|
||||||
|
## On-Device Deployment
|
||||||
|
|
||||||
|
The model can be converted to `.litertlm` format for on-device deployment using `ai-edge-torch`. See the [training notebook](https://colab.research.google.com/github/google-gemini/gemma-cookbook/blob/main/FunctionGemma/%5BFunctionGemma%5DFinetune_FunctionGemma_270M_for_Mobile_Actions_with_Hugging_Face.ipynb) for conversion instructions.
|
||||||
|
|
||||||
|
The converted model can be deployed on:
|
||||||
|
- Android devices via [Google AI Edge](https://ai.google.dev/edge)
|
||||||
|
- [AI Edge Gallery app](https://play.google.com/store/apps/details?id=com.google.ai.edge.gallery)
|
||||||
|
|
||||||
|
## Training Notebook
|
||||||
|
|
||||||
|
For full training details, hyperparameter tuning, and evaluation, see the original Colab notebook:
|
||||||
|
[Finetune FunctionGemma 270M for Mobile Actions](https://colab.research.google.com/github/google-gemini/gemma-cookbook/blob/main/FunctionGemma/%5BFunctionGemma%5DFinetune_FunctionGemma_270M_for_Mobile_Actions_with_Hugging_Face.ipynb)
|
||||||
|
|
||||||
|
## Citation
|
||||||
|
|
||||||
|
If you use this model, please cite the original FunctionGemma paper and the Google Mobile Actions dataset:
|
||||||
|
|
||||||
|
```bibtex
|
||||||
|
@misc{functiongemma2024,
|
||||||
|
title={FunctionGemma: Function Calling for Gemma Models},
|
||||||
|
author={Google},
|
||||||
|
year={2024},
|
||||||
|
url={https://huggingface.co/google/functiongemma-270m-it}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This model is released under the Gemma license. See the [Gemma Terms of Use](https://ai.google.dev/gemma/terms) for details.
|
||||||
4
added_tokens.json
Normal file
4
added_tokens.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"<end_of_image>": 262145,
|
||||||
|
"<image_soft_token>": 262144
|
||||||
|
}
|
||||||
279
chat_template.jinja
Normal file
279
chat_template.jinja
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
{%- macro format_parameters(properties, required) -%}
|
||||||
|
{%- set standard_keys = ['description', 'type', 'properties', 'required', 'nullable'] -%}
|
||||||
|
{%- set ns = namespace(found_first=false) -%}
|
||||||
|
{%- for key, value in properties | dictsort -%}
|
||||||
|
{%- if key not in standard_keys -%}
|
||||||
|
{%- if ns.found_first %},{% endif -%}
|
||||||
|
{%- set ns.found_first = true -%}
|
||||||
|
{{- key }}:{description:<escape>{{ value['description'] }}<escape>
|
||||||
|
{%- if value['type'] | upper == 'STRING' -%}
|
||||||
|
{%- if value['enum'] -%}
|
||||||
|
,enum:{{ format_argument(value['enum']) }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- elif value['type'] | upper == 'OBJECT' -%}
|
||||||
|
,properties:{
|
||||||
|
{%- if value['properties'] is defined and value['properties'] is mapping -%}
|
||||||
|
{{- format_parameters(value['properties'], value['required'] | default([])) -}}
|
||||||
|
{%- elif value is mapping -%}
|
||||||
|
{{- format_parameters(value, value['required'] | default([])) -}}
|
||||||
|
{%- endif -%}
|
||||||
|
}
|
||||||
|
{%- if value['required'] -%}
|
||||||
|
,required:[
|
||||||
|
{%- for item in value['required'] | default([]) -%}
|
||||||
|
<escape>{{- item -}}<escape>
|
||||||
|
{%- if not loop.last %},{% endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
]
|
||||||
|
{%- endif -%}
|
||||||
|
{%- elif value['type'] | upper == 'ARRAY' -%}
|
||||||
|
{%- if value['items'] is mapping and value['items'] -%}
|
||||||
|
,items:{
|
||||||
|
{%- set ns_items = namespace(found_first=false) -%}
|
||||||
|
{%- for item_key, item_value in value['items'] | dictsort -%}
|
||||||
|
{%- if item_value is not none -%}
|
||||||
|
{%- if ns_items.found_first %},{% endif -%}
|
||||||
|
{%- set ns_items.found_first = true -%}
|
||||||
|
{%- if item_key == 'properties' -%}
|
||||||
|
properties:{
|
||||||
|
{%- if item_value is mapping -%}
|
||||||
|
{{- format_parameters(item_value, value['items']['required'] | default([])) -}}
|
||||||
|
{%- endif -%}
|
||||||
|
}
|
||||||
|
{%- elif item_key == 'required' -%}
|
||||||
|
required:[
|
||||||
|
{%- for req_item in item_value -%}
|
||||||
|
<escape>{{- req_item -}}<escape>
|
||||||
|
{%- if not loop.last %},{% endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
]
|
||||||
|
{%- elif item_key == 'type' -%}
|
||||||
|
{%- if item_value is string -%}
|
||||||
|
type:{{ format_argument(item_value | upper) }}
|
||||||
|
{%- else -%}
|
||||||
|
type:{{ format_argument(item_value | map('upper') | list) }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- else -%}
|
||||||
|
{{ item_key }}:{{ format_argument(item_value) }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
,type:<escape>{{ value['type'] | upper }}<escape>}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- endmacro -%}
|
||||||
|
{% macro format_function_declaration(tool_data) -%}
|
||||||
|
declaration:{{- tool_data['function']['name'] -}}
|
||||||
|
{description:<escape>{{- tool_data['function']['description'] -}}<escape>
|
||||||
|
{%- set params = tool_data['function']['parameters'] -%}
|
||||||
|
{%- if params -%}
|
||||||
|
,parameters:{
|
||||||
|
{%- if params['properties'] -%}
|
||||||
|
properties:{ {{- format_parameters(params['properties'], params['required']) -}} },
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if params['required'] -%}
|
||||||
|
required:[
|
||||||
|
{%- for item in params['required'] -%}
|
||||||
|
<escape>{{- item -}}<escape>
|
||||||
|
{{- ',' if not loop.last -}}
|
||||||
|
{%- endfor -%}
|
||||||
|
],
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if params['type'] -%}
|
||||||
|
type:<escape>{{- params['type'] | upper -}}<escape>}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
}
|
||||||
|
{%- endmacro -%}
|
||||||
|
{% macro format_argument(argument, escape_keys=True) -%}
|
||||||
|
{%- if argument is string -%}
|
||||||
|
{{- '<escape>' + argument + '<escape>' -}}
|
||||||
|
{%- elif argument is boolean -%}
|
||||||
|
{%- if argument -%}
|
||||||
|
{{- 'true' -}}
|
||||||
|
{%- else -%}
|
||||||
|
{{- 'false' -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- elif argument is mapping -%}
|
||||||
|
{{- '{' -}}
|
||||||
|
{%- set ns = namespace(found_first=false) -%}
|
||||||
|
{%- for key, value in argument | dictsort -%}
|
||||||
|
{%- if ns.found_first %},{% endif -%}
|
||||||
|
{%- set ns.found_first = true -%}
|
||||||
|
{%- if escape_keys -%}
|
||||||
|
{{- '<escape>' + key + '<escape>' -}}
|
||||||
|
{%- else -%}
|
||||||
|
{{- key -}}
|
||||||
|
{%- endif -%}
|
||||||
|
:{{- format_argument(value, escape_keys=escape_keys) -}}
|
||||||
|
{%- endfor -%}
|
||||||
|
{{- '}' -}}
|
||||||
|
{%- elif argument is sequence -%}
|
||||||
|
{{- '[' -}}
|
||||||
|
{%- for item in argument -%}
|
||||||
|
{{- format_argument(item, escape_keys=escape_keys) -}}
|
||||||
|
{%- if not loop.last %},{% endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{{- ']' -}}
|
||||||
|
{%- else -%}
|
||||||
|
{{- argument -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endmacro -%}
|
||||||
|
{{ bos_token }}
|
||||||
|
{%- set ns = namespace(prev_message_type=None) -%}
|
||||||
|
{#- Tool Declarations -#}
|
||||||
|
{%- set loop_messages = messages -%}
|
||||||
|
{%- if tools or messages[0]['role'] == 'system' or messages[0]['role'] == 'developer' -%}
|
||||||
|
{{- '<start_of_turn>developer\n' -}}
|
||||||
|
{%- if messages[0]['role'] == 'system' or messages[0]['role'] == 'developer' -%}
|
||||||
|
{%- if messages[0]['content'] is string -%}
|
||||||
|
{{- messages[0]['content'] | trim -}}
|
||||||
|
{%- elif messages[0]['content'] is sequence -%}
|
||||||
|
{%- for item in messages[0]['content'] -%}
|
||||||
|
{%- if item['type'] == 'text' -%}
|
||||||
|
{{- item['text'] | trim -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- set loop_messages = messages[1:] -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if tools -%}
|
||||||
|
{%- for tool in tools %}
|
||||||
|
{{- '<start_function_declaration>' -}}
|
||||||
|
{{- format_function_declaration(tool) | trim }}
|
||||||
|
{{- '<end_function_declaration>' -}}
|
||||||
|
{%- endfor %}
|
||||||
|
{%- endif -%}
|
||||||
|
{{- '<end_of_turn>\n' }}
|
||||||
|
{%- endif %}
|
||||||
|
{#- Loop through messages. -#}
|
||||||
|
{%- for message in loop_messages -%}
|
||||||
|
{%- if (message['role'] == 'assistant') -%}
|
||||||
|
{#- Rename "assistant" to "model". -#}
|
||||||
|
{%- set role = "model" -%}
|
||||||
|
{%- else -%}
|
||||||
|
{%- set role = message['role'] -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if role != 'tool' -%}
|
||||||
|
{%- if ns.prev_message_type != 'tool_response' -%}
|
||||||
|
{{- '<start_of_turn>' + role + '\n' }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- set ns.prev_message_type = None -%}
|
||||||
|
{%- if 'content' in message and message['content'] is not none -%}
|
||||||
|
{%- if message['content'] is string -%}
|
||||||
|
{{ message['content'] | trim }}
|
||||||
|
{%- elif message['content'] is sequence -%}
|
||||||
|
{%- for item in message['content'] -%}
|
||||||
|
{%- if item['type'] == 'image' -%}
|
||||||
|
{{ '<start_of_image>' }}
|
||||||
|
{%- elif item['type'] == 'text' -%}
|
||||||
|
{{ item['text'] | trim }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- else -%}
|
||||||
|
{{ raise_exception("Invalid content type in user/assistant message") }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- set ns.prev_message_type = 'content' -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if 'tool_calls' in message and message['tool_calls'] and message['tool_calls'] is iterable -%}
|
||||||
|
{#- Tool Calls -#}
|
||||||
|
{%- for tool_call in message['tool_calls'] -%}
|
||||||
|
{% set function = tool_call['function'] %}
|
||||||
|
{{- '<start_function_call>call:' + function['name'] + '{' -}}
|
||||||
|
{%- if 'arguments' in function -%}
|
||||||
|
{%- if function['arguments'] is mapping -%}
|
||||||
|
{%- set ns = namespace(found_first=false) -%}
|
||||||
|
{%- for key, value in function['arguments'] | dictsort -%}
|
||||||
|
{%- if ns.found_first %},{% endif -%}
|
||||||
|
{%- set ns.found_first = true -%}
|
||||||
|
{{- key -}}:{{- format_argument(value, escape_keys=False) -}}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- elif function['arguments'] is string -%}
|
||||||
|
{# This handles string-JSON, just in case #}
|
||||||
|
{{ function['arguments'] }}
|
||||||
|
{%- endif %}
|
||||||
|
{%- endif -%}
|
||||||
|
{{- '}<end_function_call>' -}}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- if loop.last -%}
|
||||||
|
{{ '<start_function_response>' }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- set ns.prev_message_type = 'tool_call' -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- else -%}
|
||||||
|
{#- Tool Responses -#}
|
||||||
|
{%- if 'content' in message and message['content'] -%}
|
||||||
|
{%- if message['content'] is mapping -%}
|
||||||
|
{%- if 'name' in message['content'] and 'response' in message['content'] -%}
|
||||||
|
{{ '<start_function_response>response:' + message['content']['name'] | trim + '{' }}
|
||||||
|
{%- set response_ns = namespace(found_first=false) -%}
|
||||||
|
{%- for key, value in message['content']['response'] | dictsort -%}
|
||||||
|
{%- if response_ns.found_first %},{% endif -%}
|
||||||
|
{%- set response_ns.found_first = true -%}
|
||||||
|
{{- key -}}:{{- format_argument(value, escape_keys=False) -}}
|
||||||
|
{%- endfor -%}
|
||||||
|
{{- '}<end_function_response>' -}}
|
||||||
|
{%- elif 'name' in message -%}
|
||||||
|
{{ '<start_function_response>response:' + message['name'] | trim + '{' }}
|
||||||
|
{%- set response_ns = namespace(found_first=false) -%}
|
||||||
|
{%- for key, value in message['content'] | dictsort -%}
|
||||||
|
{%- if response_ns.found_first %},{% endif -%}
|
||||||
|
{%- set response_ns.found_first = true -%}
|
||||||
|
{{- key -}}:{{- format_argument(value, escape_keys=False) -}}
|
||||||
|
{%- endfor -%}
|
||||||
|
{{- '}<end_function_response>' -}}
|
||||||
|
{%- else -%}
|
||||||
|
{{ raise_exception("Invalid tool response mapping: must contain 'name' and 'response' keys, or 'name' must be in the message.") }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- elif message['content'] is string -%}
|
||||||
|
{%- if 'name' in message -%}
|
||||||
|
{{ '<start_function_response>response:' + message['name'] | trim + '{value:' + format_argument(message['content'], escape_keys=False) + '}<end_function_response>' }}
|
||||||
|
{%- else -%}
|
||||||
|
{{ raise_exception("Invalid tool response: 'name' must be provided.") }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- elif message['content'] is sequence -%}
|
||||||
|
{%- for item in message['content'] -%}
|
||||||
|
{%- if item is mapping -%}
|
||||||
|
{%- if 'name' in item and 'response' in item -%}
|
||||||
|
{{ '<start_function_response>response:' + item['name'] | trim + '{' }}
|
||||||
|
{%- set response_ns = namespace(found_first=false) -%}
|
||||||
|
{%- for key, value in item['response'] | dictsort -%}
|
||||||
|
{%- if response_ns.found_first %},{% endif -%}
|
||||||
|
{%- set response_ns.found_first = true -%}
|
||||||
|
{{- key -}}:{{- format_argument(value, escape_keys=False) -}}
|
||||||
|
{%- endfor -%}
|
||||||
|
{{- '}<end_function_response>' -}}
|
||||||
|
{%- elif 'name' in message -%}
|
||||||
|
{{ '<start_function_response>response:' + message['name'] | trim + '{' }}
|
||||||
|
{%- set response_ns = namespace(found_first=false) -%}
|
||||||
|
{%- for key, value in item | dictsort -%}
|
||||||
|
{%- if response_ns.found_first %},{% endif -%}
|
||||||
|
{%- set response_ns.found_first = true -%}
|
||||||
|
{{- key -}}:{{- format_argument(value, escape_keys=False) -}}
|
||||||
|
{%- endfor -%}
|
||||||
|
{{- '}<end_function_response>' -}}
|
||||||
|
{%- else -%}
|
||||||
|
{{ raise_exception("Invalid tool response mapping: must contain 'name' and 'response' keys, or 'name' must be in the message.") }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- else -%}
|
||||||
|
{{ raise_exception("Invalid tool response message: multiple responses must all be mappings") }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- else -%}
|
||||||
|
{{ raise_exception("Invalid content type in tool message: must be mapping, sequence of mappings, or string.") }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- set ns.prev_message_type = 'tool_response' -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- if ns.prev_message_type not in ['tool_call', 'tool_response'] -%}
|
||||||
|
{{ '<end_of_turn>\n' }}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- if add_generation_prompt -%}
|
||||||
|
{%- if ns.prev_message_type != 'tool_response' -%}
|
||||||
|
{{- '<start_of_turn>model\n' -}}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
54
config.json
Normal file
54
config.json
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"_sliding_window_pattern": 6,
|
||||||
|
"architectures": [
|
||||||
|
"Gemma3ForCausalLM"
|
||||||
|
],
|
||||||
|
"attention_bias": false,
|
||||||
|
"attention_dropout": 0.0,
|
||||||
|
"attn_logit_softcapping": null,
|
||||||
|
"bos_token_id": 2,
|
||||||
|
"dtype": "float32",
|
||||||
|
"eos_token_id": 1,
|
||||||
|
"final_logit_softcapping": null,
|
||||||
|
"head_dim": 256,
|
||||||
|
"hidden_activation": "gelu_pytorch_tanh",
|
||||||
|
"hidden_size": 640,
|
||||||
|
"initializer_range": 0.02,
|
||||||
|
"intermediate_size": 2048,
|
||||||
|
"layer_types": [
|
||||||
|
"sliding_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"full_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"full_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"sliding_attention",
|
||||||
|
"full_attention"
|
||||||
|
],
|
||||||
|
"max_position_embeddings": 32768,
|
||||||
|
"model_type": "gemma3_text",
|
||||||
|
"num_attention_heads": 4,
|
||||||
|
"num_hidden_layers": 18,
|
||||||
|
"num_key_value_heads": 1,
|
||||||
|
"pad_token_id": 0,
|
||||||
|
"query_pre_attn_scalar": 256,
|
||||||
|
"rms_norm_eps": 1e-06,
|
||||||
|
"rope_local_base_freq": 10000.0,
|
||||||
|
"rope_scaling": null,
|
||||||
|
"rope_theta": 1000000.0,
|
||||||
|
"sliding_window": 512,
|
||||||
|
"transformers_version": "4.57.1",
|
||||||
|
"use_bidirectional_attention": false,
|
||||||
|
"use_cache": true,
|
||||||
|
"vocab_size": 262144
|
||||||
|
}
|
||||||
1
configuration.json
Normal file
1
configuration.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"framework": "pytorch", "task": "text-generation", "allow_remote": true}
|
||||||
15
generation_config.json
Normal file
15
generation_config.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"bos_token_id": 2,
|
||||||
|
"cache_implementation": "hybrid",
|
||||||
|
"do_sample": true,
|
||||||
|
"eos_token_id": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
50,
|
||||||
|
106
|
||||||
|
],
|
||||||
|
"pad_token_id": 0,
|
||||||
|
"top_k": 64,
|
||||||
|
"top_p": 0.95,
|
||||||
|
"transformers_version": "4.57.1"
|
||||||
|
}
|
||||||
3
model.safetensors
Normal file
3
model.safetensors
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:0ce45dc209d23833095d7eeea6797643bc0bf8851d76b9c2e009a0cf2246229e
|
||||||
|
size 1072419256
|
||||||
34
special_tokens_map.json
Normal file
34
special_tokens_map.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"boi_token": "<start_of_image>",
|
||||||
|
"bos_token": {
|
||||||
|
"content": "<bos>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
"eoi_token": "<end_of_image>",
|
||||||
|
"eos_token": {
|
||||||
|
"content": "<eos>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
"image_token": "<image_soft_token>",
|
||||||
|
"pad_token": {
|
||||||
|
"content": "<pad>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
},
|
||||||
|
"sfr_token": "<start_function_response>",
|
||||||
|
"unk_token": {
|
||||||
|
"content": "<unk>",
|
||||||
|
"lstrip": false,
|
||||||
|
"normalized": false,
|
||||||
|
"rstrip": false,
|
||||||
|
"single_word": false
|
||||||
|
}
|
||||||
|
}
|
||||||
3
tokenizer.json
Normal file
3
tokenizer.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:b6b09a0b4a803ad453063ca4bb49a784540e8120004e2450e025df2b27d41fb2
|
||||||
|
size 33384899
|
||||||
3
tokenizer.model
Normal file
3
tokenizer.model
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:aa009fcbc3589a9904d30d04834094fea4653c2ac6d2de2cd1262d4f7a50ceb3
|
||||||
|
size 4689144
|
||||||
3
tokenizer_config.json
Normal file
3
tokenizer_config.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:c33878647bdc69ce85d4b9aeef953815afd8405f8d85001ab0bbb89aa14d2554
|
||||||
|
size 1155714
|
||||||
Reference in New Issue
Block a user