Commit 317a82e2 authored by chenych's avatar chenych
Browse files

Add QWQ-32B

parent 37b0ad9f
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -20,6 +20,32 @@ CSS = r"""
border-radius: 100vh !important;
}
.thinking-summary {
padding: 8px !important;
}
.thinking-summary span {
border-radius: 4px !important;
padding: 4px !important;
cursor: pointer !important;
font-size: 14px !important;
background: rgb(245, 245, 245) !important;
}
.dark .thinking-summary span {
background: rgb(73, 73, 73) !important;
}
.thinking-container {
border-left: 2px solid #a6a6a6 !important;
padding-left: 10px !important;
margin: 4px 0 !important;
}
.thinking-container p {
color: #a6a6a6 !important;
}
.modal-box {
position: fixed !important;
top: 50%;
......
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -15,11 +15,10 @@
from typing import TYPE_CHECKING, Any, Dict
from .chatter import WebChatModel
from .common import load_config
from .common import create_ds_config, get_time, load_config
from .locales import LOCALES
from .manager import Manager
from .runner import Runner
from .utils import create_ds_config, get_time
if TYPE_CHECKING:
......@@ -27,6 +26,10 @@ if TYPE_CHECKING:
class Engine:
r"""
A general engine to control the behaviors of Web UI.
"""
def __init__(self, demo_mode: bool = False, pure_chat: bool = False) -> None:
self.demo_mode = demo_mode
self.pure_chat = pure_chat
......@@ -38,7 +41,7 @@ class Engine:
def _update_component(self, input_dict: Dict[str, Dict[str, Any]]) -> Dict["Component", "Component"]:
r"""
Gets the dict to update the components.
Updates gradio components according to the (elem_id, properties) mapping.
"""
output_dict: Dict["Component", "Component"] = {}
for elem_id, elem_attr in input_dict.items():
......@@ -48,9 +51,11 @@ class Engine:
return output_dict
def resume(self):
user_config = load_config() if not self.demo_mode else {}
r"""
Gets the initial value of gradio components and restores training status if necessary.
"""
user_config = load_config() if not self.demo_mode else {} # do not use config in demo mode
lang = user_config.get("lang", None) or "en"
init_dict = {"top.lang": {"value": lang}, "infer.chat_box": {"visible": self.chatter.loaded}}
if not self.pure_chat:
......@@ -74,6 +79,9 @@ class Engine:
yield self._update_component({"eval.resume_btn": {"value": True}})
def change_lang(self, lang: str):
r"""
Updates the displayed language of gradio components.
"""
return {
elem: elem.__class__(**LOCALES[elem_name][lang])
for elem_name, elem in self.manager.get_elem_iter()
......
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -15,6 +15,7 @@
import os
import platform
from ..extras.misc import is_env_enabled
from ..extras.packages import is_gradio_available
from .common import save_config
from .components import (
......@@ -73,7 +74,7 @@ def create_web_demo() -> "gr.Blocks":
engine = Engine(pure_chat=True)
with gr.Blocks(title="Web Demo", css=CSS) as demo:
lang = gr.Dropdown(choices=["en", "ru", "zh", "ko"], scale=1)
lang = gr.Dropdown(choices=["en", "ru", "zh", "ko", "ja"], scale=1)
engine.manager.add_elems("top", dict(lang=lang))
_, _, chat_elems = create_chat_box(engine, visible=True)
......@@ -87,14 +88,14 @@ def create_web_demo() -> "gr.Blocks":
def run_web_ui() -> None:
gradio_ipv6 = os.getenv("GRADIO_IPV6", "0").lower() in ["true", "1"]
gradio_share = os.getenv("GRADIO_SHARE", "0").lower() in ["true", "1"]
gradio_ipv6 = is_env_enabled("GRADIO_IPV6")
gradio_share = is_env_enabled("GRADIO_SHARE")
server_name = os.getenv("GRADIO_SERVER_NAME", "[::]" if gradio_ipv6 else "0.0.0.0")
create_ui().queue().launch(share=gradio_share, server_name=server_name, inbrowser=True)
def run_web_demo() -> None:
gradio_ipv6 = os.getenv("GRADIO_IPV6", "0").lower() in ["true", "1"]
gradio_share = os.getenv("GRADIO_SHARE", "0").lower() in ["true", "1"]
gradio_ipv6 = is_env_enabled("GRADIO_IPV6")
gradio_share = is_env_enabled("GRADIO_SHARE")
server_name = os.getenv("GRADIO_SERVER_NAME", "[::]" if gradio_ipv6 else "0.0.0.0")
create_web_demo().queue().launch(share=gradio_share, server_name=server_name, inbrowser=True)
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -15,10 +15,10 @@
LOCALES = {
"lang": {
"en": {
"label": "Lang",
"label": "Language",
},
"ru": {
"label": "язык",
"label": "Язык",
},
"zh": {
"label": "语言",
......@@ -26,15 +26,18 @@ LOCALES = {
"ko": {
"label": "언어",
},
"ja": {
"label": "言語",
},
},
"model_name": {
"en": {
"label": "Model name",
"info": "Input the name prefix to search for the model.",
"info": "Input the initial name to search for the model.",
},
"ru": {
"label": "Название модели",
"info": "Введите префикс имени для поиска модели.",
"info": "Введите начальное имя для поиска модели.",
},
"zh": {
"label": "模型名称",
......@@ -42,7 +45,11 @@ LOCALES = {
},
"ko": {
"label": "모델 이름",
"info": "모델을 검색하기 위해 이름 접두어를 입력하세요.",
"info": "모델을 검색할 초기 이름을 입력하세요.",
},
"ja": {
"label": "モデル名",
"info": "モデルを検索するための初期名を入力してください。",
},
},
"model_path": {
......@@ -62,6 +69,10 @@ LOCALES = {
"label": "모델 경로",
"info": "사전 훈련된 모델의 경로 또는 Hugging Face의 모델 식별자.",
},
"ja": {
"label": "モデルパス",
"info": "事前学習済みモデルへのパス、または Hugging Face のモデル識別子。",
},
},
"finetuning_type": {
"en": {
......@@ -76,6 +87,9 @@ LOCALES = {
"ko": {
"label": "파인튜닝 방법",
},
"ja": {
"label": "ファインチューニング方法",
},
},
"checkpoint_path": {
"en": {
......@@ -90,6 +104,9 @@ LOCALES = {
"ko": {
"label": "체크포인트 경로",
},
"ja": {
"label": "チェックポイントパス",
},
},
"quantization_bit": {
"en": {
......@@ -108,6 +125,10 @@ LOCALES = {
"label": "양자화 비트",
"info": "양자화 활성화 (QLoRA).",
},
"ja": {
"label": "量子化ビット",
"info": "量子化を有効にする (QLoRA)。",
},
},
"quantization_method": {
"en": {
......@@ -126,51 +147,69 @@ LOCALES = {
"label": "양자화 방법",
"info": "사용할 양자화 알고리즘.",
},
"ja": {
"label": "量子化方法",
"info": "使用する量子化アルゴリズム。",
},
},
"template": {
"en": {
"label": "Prompt template",
"info": "The template used in constructing prompts.",
"label": "Chat template",
"info": "The chat template used in constructing prompts.",
},
"ru": {
"label": "Шаблон запроса",
"info": "Шаблон, используемый при формировании запросов.",
"label": "Шаблон чата",
"info": "Шаблон чата используемый для составления подсказок.",
},
"zh": {
"label": "提示模板",
"label": "对话模板",
"info": "构建提示词时使用的模板。",
},
"ko": {
"label": "프롬프트 템플릿",
"info": "프롬프트 구성에 사용될 템플릿.",
"label": "채팅 템플릿",
"info": "프롬프트 작성에 사용되는 채팅 템플릿.",
},
"ja": {
"label": "チャットテンプレート",
"info": "プロンプトの構築に使用されるチャットテンプレート。",
},
},
"rope_scaling": {
"en": {
"label": "RoPE scaling",
"info": "RoPE scaling method to use.",
},
"ru": {
"label": "Масштабирование RoPE",
"info": "Метод масштабирования RoPE для использования.",
},
"zh": {
"label": "RoPE 插值方法",
},
"zh": {"label": "RoPE 插值方法", "info": "RoPE 插值时使用的方法。"},
"ko": {
"label": "RoPE 스케일링",
"info": "사용할 RoPE 스케일링 방법.",
},
"ja": {
"label": "RoPE スケーリング",
"info": "使用する RoPE スケーリング方法。",
},
},
"booster": {
"en": {
"label": "Booster",
"info": "Approach used to boost training speed.",
},
"ru": {
"label": "Ускоритель",
"info": "Подход, используемый для ускорения обучения.",
},
"zh": {
"label": "加速方式",
},
"zh": {"label": "加速方式", "info": "使用的加速方法。"},
"ko": {
"label": "부스터",
"info": "훈련 속도를 향상시키기 위해 사용된 접근 방식.",
},
"ja": {
"label": "ブースター",
"info": "トレーニング速度を向上させるためのアプローチ。",
},
},
"training_stage": {
......@@ -190,6 +229,10 @@ LOCALES = {
"label": "학습 단계",
"info": "수행할 학습 방법.",
},
"ja": {
"label": "ステージ",
"info": "トレーニングで実行するステージ。",
},
},
"dataset_dir": {
"en": {
......@@ -208,6 +251,10 @@ LOCALES = {
"label": "데이터 디렉토리",
"info": "데이터 디렉토리의 경로.",
},
"ja": {
"label": "データディレクトリ",
"info": "データディレクトリへのパス。",
},
},
"dataset": {
"en": {
......@@ -222,6 +269,9 @@ LOCALES = {
"ko": {
"label": "데이터셋",
},
"ja": {
"label": "データセット",
},
},
"data_preview_btn": {
"en": {
......@@ -236,6 +286,9 @@ LOCALES = {
"ko": {
"value": "데이터셋 미리보기",
},
"ja": {
"value": "データセットをプレビュー",
},
},
"preview_count": {
"en": {
......@@ -250,6 +303,9 @@ LOCALES = {
"ko": {
"label": "개수",
},
"ja": {
"label": "カウント",
},
},
"page_index": {
"en": {
......@@ -264,6 +320,9 @@ LOCALES = {
"ko": {
"label": "페이지",
},
"ja": {
"label": "ページ",
},
},
"prev_btn": {
"en": {
......@@ -278,6 +337,9 @@ LOCALES = {
"ko": {
"value": "이전",
},
"ja": {
"value": "前へ",
},
},
"next_btn": {
"en": {
......@@ -292,6 +354,9 @@ LOCALES = {
"ko": {
"value": "다음",
},
"ja": {
"value": "次へ",
},
},
"close_btn": {
"en": {
......@@ -306,6 +371,9 @@ LOCALES = {
"ko": {
"value": "닫기",
},
"ja": {
"value": "閉じる",
},
},
"preview_samples": {
"en": {
......@@ -320,6 +388,9 @@ LOCALES = {
"ko": {
"label": "샘플",
},
"ja": {
"label": "サンプル",
},
},
"learning_rate": {
"en": {
......@@ -338,6 +409,10 @@ LOCALES = {
"label": "학습률",
"info": "AdamW의 초기 학습률.",
},
"ja": {
"label": "学習率",
"info": "AdamW の初期学習率。",
},
},
"num_train_epochs": {
"en": {
......@@ -356,6 +431,10 @@ LOCALES = {
"label": "에포크",
"info": "수행할 총 학습 에포크 수.",
},
"ja": {
"label": "エポック数",
"info": "実行するトレーニングの総エポック数。",
},
},
"max_grad_norm": {
"en": {
......@@ -374,6 +453,10 @@ LOCALES = {
"label": "최대 그레디언트 노름(norm)",
"info": "그레디언트 클리핑을 위한 노름(norm).",
},
"ja": {
"label": "最大勾配ノルム",
"info": "勾配クリッピングのためのノルム。",
},
},
"max_samples": {
"en": {
......@@ -392,6 +475,10 @@ LOCALES = {
"label": "최대 샘플 수",
"info": "데이터셋 당 최대 샘플 수.",
},
"ja": {
"label": "最大サンプル数",
"info": "データセットごとの最大サンプル数。",
},
},
"compute_type": {
"en": {
......@@ -410,6 +497,10 @@ LOCALES = {
"label": "연산 유형",
"info": "혼합 정밀도 훈련을 사용할지 여부.",
},
"ja": {
"label": "計算タイプ",
"info": "混合精度トレーニングを使用するかどうか。",
},
},
"cutoff_len": {
"en": {
......@@ -428,6 +519,10 @@ LOCALES = {
"label": "컷오프 길이",
"info": "입력 시퀀스의 최대 토큰 수.",
},
"ja": {
"label": "カットオフ長",
"info": "入力シーケンスの最大トークン数。",
},
},
"batch_size": {
"en": {
......@@ -446,6 +541,10 @@ LOCALES = {
"label": "배치 크기",
"info": "각 GPU에서 처리되는 샘플 수.",
},
"ja": {
"label": "バッチサイズ",
"info": "各 GPU で処理されるサンプル数。",
},
},
"gradient_accumulation_steps": {
"en": {
......@@ -464,6 +563,10 @@ LOCALES = {
"label": "그레디언트 누적",
"info": "그레디언트 누적 단계 수.",
},
"ja": {
"label": "勾配累積",
"info": "勾配累積のステップ数。",
},
},
"val_size": {
"en": {
......@@ -482,6 +585,10 @@ LOCALES = {
"label": "검증 데이터셋 크기",
"info": "개발 데이터셋에서 검증 데이터의 비율.",
},
"ja": {
"label": "検証セットサイズ",
"info": "データセット全体に対する検証セットの割合。",
},
},
"lr_scheduler_type": {
"en": {
......@@ -500,6 +607,10 @@ LOCALES = {
"label": "LR 스케줄러",
"info": "학습률 스케줄러의 이름.",
},
"ja": {
"label": "学習率スケジューラ",
"info": "学習率スケジューラの名前。",
},
},
"extra_tab": {
"en": {
......@@ -514,6 +625,9 @@ LOCALES = {
"ko": {
"label": "추가 구성(configuration)",
},
"ja": {
"label": "追加設定",
},
},
"logging_steps": {
"en": {
......@@ -532,6 +646,10 @@ LOCALES = {
"label": "로깅 스텝",
"info": "이전 로깅과 다음 로깅 간 스텝 수.",
},
"ja": {
"label": "ロギングステップ",
"info": "2 つのログ間のステップ数。",
},
},
"save_steps": {
"en": {
......@@ -550,6 +668,10 @@ LOCALES = {
"label": "저장 스텝",
"info": "이전 체크포인트와 다음 체크포인트 사이의 스텝 수.",
},
"ja": {
"label": "保存ステップ",
"info": "2 つのチェックポイント間のステップ数。",
},
},
"warmup_steps": {
"en": {
......@@ -568,6 +690,10 @@ LOCALES = {
"label": "Warmup 스텝",
"info": "Warmup에 사용되는 스텝 수.",
},
"ja": {
"label": "ウォームアップステップ",
"info": "ウォームアップに使用されるステップ数。",
},
},
"neftune_alpha": {
"en": {
......@@ -586,6 +712,10 @@ LOCALES = {
"label": "NEFTune 알파",
"info": "임베딩 벡터에 추가되는 노이즈의 크기.",
},
"ja": {
"label": "NEFTune alpha",
"info": "埋め込みベクトルに追加されるノイズの大きさ。",
},
},
"extra_args": {
"en": {
......@@ -604,6 +734,10 @@ LOCALES = {
"label": "추가 인수",
"info": "JSON 형식으로 트레이너에게 전달할 추가 인수입니다.",
},
"ja": {
"label": "追加引数",
"info": "JSON 形式でトレーナーに渡される追加引数。",
},
},
"packing": {
"en": {
......@@ -622,6 +756,10 @@ LOCALES = {
"label": "시퀀스 패킹",
"info": "고정된 길이의 샘플로 시퀀스를 패킹합니다.",
},
"ja": {
"label": "シーケンスパッキング",
"info": "シーケンスを固定長のサンプルにパッキングします。",
},
},
"neat_packing": {
"en": {
......@@ -640,6 +778,10 @@ LOCALES = {
"label": "니트 패킹 사용",
"info": "패킹된 시퀀스 간의 크로스 어텐션을 피합니다.",
},
"ja": {
"label": "無汚染パッキングを使用",
"info": "パッキング後のシーケンス間のクロスアテンションを避けます。",
},
},
"train_on_prompt": {
"en": {
......@@ -658,6 +800,10 @@ LOCALES = {
"label": "프롬프트도 학습",
"info": "프롬프트에서 라벨 마스킹을 비활성화합니다 (SFT에만 해당).",
},
"ja": {
"label": "プロンプトで学習",
"info": "プロンプト部分にマスクを追加しない(SFT のみ)。",
},
},
"mask_history": {
"en": {
......@@ -676,6 +822,10 @@ LOCALES = {
"label": "히스토리 마스킹",
"info": "대화 데이터의 마지막 턴만 학습합니다 (SFT에만 해당).",
},
"ja": {
"label": "履歴をマスク",
"info": "最後のターンのみを学習する(SFT のみ)。",
},
},
"resize_vocab": {
"en": {
......@@ -694,6 +844,10 @@ LOCALES = {
"label": "토큰 임베딩의 사이즈 조정",
"info": "토크나이저 어휘와 임베딩 레이어의 크기를 조정합니다.",
},
"ja": {
"label": "トークン埋め込みのサイズ変更",
"info": "トークナイザーの語彙と埋め込み層のサイズを変更します。",
},
},
"use_llama_pro": {
"en": {
......@@ -712,23 +866,9 @@ LOCALES = {
"label": "LLaMA Pro 사용",
"info": "확장된 블록의 매개변수를 학습 가능하게 만듭니다.",
},
},
"shift_attn": {
"en": {
"label": "Enable S^2 Attention",
"info": "Use shift short attention proposed by LongLoRA.",
},
"ru": {
"label": "Включить S^2 внимание",
"info": "Использовать сдвиг внимания на короткие дистанции предложенный LongLoRA.",
},
"zh": {
"label": "使用 S^2 Attention",
"info": "使用 LongLoRA 提出的 shift short attention。",
},
"ko": {
"label": "S^2 Attention 사용",
"info": "LongLoRA에서 제안한 shift short attention을 사용합니다.",
"ja": {
"label": "LLaMA Pro を有効化",
"info": "拡張ブロックのパラメータのみをトレーニングします。",
},
},
"report_to": {
......@@ -748,6 +888,10 @@ LOCALES = {
"label": "외부 logger 활성화",
"info": "TensorBoard 또는 wandb를 사용하여 실험을 기록합니다.",
},
"ja": {
"label": "外部ロガーを有効化",
"info": "TensorBoard または wandb を使用して実験を記録します。",
},
},
"freeze_tab": {
"en": {
......@@ -762,6 +906,9 @@ LOCALES = {
"ko": {
"label": "Freeze tuning 설정",
},
"ja": {
"label": "フリーズチューニング設定",
},
},
"freeze_trainable_layers": {
"en": {
......@@ -780,6 +927,10 @@ LOCALES = {
"label": "학습 가능한 레이어",
"info": "학습 가능하게 설정할 마지막(+)/처음(-) 히든 레이어의 수.",
},
"ja": {
"label": "学習可能なレイヤー",
"info": "最後(+)/最初(-)の学習可能な隠れ層の数。",
},
},
"freeze_trainable_modules": {
"en": {
......@@ -798,6 +949,10 @@ LOCALES = {
"label": "학습 가능한 모듈",
"info": "학습 가능한 모듈의 이름. 여러 모듈을 구분하려면 쉼표(,)를 사용하세요.",
},
"ja": {
"label": "学習可能なモジュール",
"info": "学習可能なモジュールの名前。複数のモジュールを区切るにはカンマを使用します。",
},
},
"freeze_extra_modules": {
"en": {
......@@ -820,7 +975,11 @@ LOCALES = {
},
"ko": {
"label": "추가 모듈 (선택 사항)",
"info": "학습 가능한 모듈의 이름(히든 레이어 제외). 모듈 간에는 쉼표(,)로 구분하십시오.",
"info": "히든 레이어 외에 학습 가능하게 설정할 모듈의 이름. 모듈 간에는 쉼표(,)로 구분하십시오.",
},
"ja": {
"label": "追加モジュール(オプション)",
"info": "隠れ層以外の学習可能なモジュールの名前。複数のモジュールを区切るにはカンマを使用します。",
},
},
"lora_tab": {
......@@ -836,6 +995,9 @@ LOCALES = {
"ko": {
"label": "LoRA 구성",
},
"ja": {
"label": "LoRA 設定",
},
},
"lora_rank": {
"en": {
......@@ -854,6 +1016,10 @@ LOCALES = {
"label": "LoRA 랭크",
"info": "LoRA 행렬의 랭크.",
},
"ja": {
"label": "LoRA ランク",
"info": "LoRA 行列のランク。",
},
},
"lora_alpha": {
"en": {
......@@ -872,6 +1038,10 @@ LOCALES = {
"label": "LoRA 알파",
"info": "LoRA 스케일링 계수.",
},
"ja": {
"label": "LoRA alpha",
"info": "LoRA スケーリング係数。",
},
},
"lora_dropout": {
"en": {
......@@ -890,6 +1060,10 @@ LOCALES = {
"label": "LoRA 드롭아웃",
"info": "LoRA 가중치의 드롭아웃 비율.",
},
"ja": {
"label": "LoRA ドロップアウト",
"info": "LoRA 重みのドロップアウト確率。",
},
},
"loraplus_lr_ratio": {
"en": {
......@@ -908,6 +1082,10 @@ LOCALES = {
"label": "LoRA+ LR 비율",
"info": "LoRA에서 B 행렬의 LR 비율.",
},
"ja": {
"label": "LoRA+ LR 比率",
"info": "LoRA+ の B 行列の学習率倍率。",
},
},
"create_new_adapter": {
"en": {
......@@ -926,6 +1104,10 @@ LOCALES = {
"label": "새 어댑터 생성",
"info": "기존 어댑터 위에 무작위로 초기화된 가중치를 가진 새 어댑터를 생성합니다.",
},
"ja": {
"label": "新しいアダプターを作成",
"info": "既存のアダプター上にランダムに初期化された新しいアダプターを作成します。",
},
},
"use_rslora": {
"en": {
......@@ -944,6 +1126,10 @@ LOCALES = {
"label": "rslora 사용",
"info": "LoRA 레이어에 랭크 안정화 스케일링 계수를 사용합니다.",
},
"ja": {
"label": "rslora を使用",
"info": "LoRA 層にランク安定化スケーリング方法を使用します。",
},
},
"use_dora": {
"en": {
......@@ -962,6 +1148,10 @@ LOCALES = {
"label": "DoRA 사용",
"info": "가중치-분해 LoRA를 사용합니다.",
},
"ja": {
"label": "DoRA を使用",
"info": "重み分解された LoRA を使用します。",
},
},
"use_pissa": {
"en": {
......@@ -980,6 +1170,10 @@ LOCALES = {
"label": "PiSSA 사용",
"info": "PiSSA 방법을 사용합니다.",
},
"ja": {
"label": "PiSSA を使用",
"info": "PiSSA メソッドを使用します。",
},
},
"lora_target": {
"en": {
......@@ -998,6 +1192,10 @@ LOCALES = {
"label": "LoRA 모듈 (선택 사항)",
"info": "LoRA를 적용할 모듈의 이름. 모듈 간에는 쉼표(,)로 구분하십시오.",
},
"ja": {
"label": "LoRA モジュール(オプション)",
"info": "LoRA を適用するモジュールの名前。複数のモジュールを区切るにはカンマを使用します。",
},
},
"additional_target": {
"en": {
......@@ -1022,6 +1220,10 @@ LOCALES = {
"label": "추가 모듈 (선택 사항)",
"info": "LoRA 레이어 외에 학습 가능하게 설정할 모듈의 이름. 모듈 간에는 쉼표(,)로 구분하십시오.",
},
"ja": {
"label": "追加モジュール(オプション)",
"info": "LoRA 層以外の学習可能なモジュールの名前。複数のモジュールを区切るにはカンマを使用します。",
},
},
"rlhf_tab": {
"en": {
......@@ -1036,6 +1238,9 @@ LOCALES = {
"ko": {
"label": "RLHF 구성",
},
"ja": {
"label": "RLHF 設定",
},
},
"pref_beta": {
"en": {
......@@ -1054,6 +1259,10 @@ LOCALES = {
"label": "베타 값",
"info": "손실 함수에서 베타 매개 변수의 값.",
},
"ja": {
"label": "Beta 値",
"info": "損失関数における beta ハイパーパラメータの値。",
},
},
"pref_ftx": {
"en": {
......@@ -1072,6 +1281,10 @@ LOCALES = {
"label": "Ftx 감마",
"info": "최종 로스 함수에서 SFT 로스의 가중치.",
},
"ja": {
"label": "Ftx gamma",
"info": "損失関数における SFT 損失の重み。",
},
},
"pref_loss": {
"en": {
......@@ -1090,6 +1303,10 @@ LOCALES = {
"label": "로스 유형",
"info": "로스 함수의 유형.",
},
"ja": {
"label": "損失タイプ",
"info": "損失関数のタイプ。",
},
},
"reward_model": {
"en": {
......@@ -1108,6 +1325,10 @@ LOCALES = {
"label": "리워드 모델",
"info": "PPO 학습에서 사용할 리워드 모델의 어댑터.",
},
"ja": {
"label": "報酬モデル",
"info": "PPO トレーニングにおける報酬モデルのアダプター。",
},
},
"ppo_score_norm": {
"en": {
......@@ -1126,6 +1347,10 @@ LOCALES = {
"label": "스코어 정규화",
"info": "PPO 학습에서 스코어를 정규화합니다.",
},
"ja": {
"label": "スコア正規化",
"info": "PPO トレーニングにおける報酬スコアの正規化。",
},
},
"ppo_whiten_rewards": {
"en": {
......@@ -1144,6 +1369,10 @@ LOCALES = {
"label": "보상 백화",
"info": "PPO 훈련에서 보상을 백화(Whiten)합니다.",
},
"ja": {
"label": "報酬のホワイトニング",
"info": "PPO トレーニングにおいて報酬スコアをホワイトニング処理します。",
},
},
"galore_tab": {
"en": {
......@@ -1158,23 +1387,30 @@ LOCALES = {
"ko": {
"label": "GaLore 구성",
},
"ja": {
"label": "GaLore 設定",
},
},
"use_galore": {
"en": {
"label": "Use GaLore",
"info": "Use GaLore optimizer.",
"info": "Use [GaLore](https://github.com/jiaweizzhao/GaLore) optimizer.",
},
"ru": {
"label": "Использовать GaLore",
"info": "Используйте оптимизатор GaLore.",
"info": "Используйте оптимизатор [GaLore](https://github.com/jiaweizzhao/GaLore).",
},
"zh": {
"label": "使用 GaLore",
"info": "使用 GaLore 优化器。",
"info": "使用 [GaLore](https://github.com/jiaweizzhao/GaLore) 优化器。",
},
"ko": {
"label": "GaLore 사용",
"info": "GaLore 최적화를 사용하세요.",
"info": "[GaLore](https://github.com/jiaweizzhao/GaLore) 최적화를 사용하세요.",
},
"ja": {
"label": "GaLore を使用",
"info": "[GaLore](https://github.com/jiaweizzhao/GaLore) オプティマイザーを使用します。",
},
},
"galore_rank": {
......@@ -1194,6 +1430,10 @@ LOCALES = {
"label": "GaLore 랭크",
"info": "GaLore 그레디언트의 랭크.",
},
"ja": {
"label": "GaLore ランク",
"info": "GaLore 勾配のランク。",
},
},
"galore_update_interval": {
"en": {
......@@ -1212,6 +1452,10 @@ LOCALES = {
"label": "업데이트 간격",
"info": "GaLore 프로젝션을 업데이트할 간격의 스텝 수.",
},
"ja": {
"label": "更新間隔",
"info": "隣接する 2 回の投影更新間のステップ数。",
},
},
"galore_scale": {
"en": {
......@@ -1230,6 +1474,10 @@ LOCALES = {
"label": "GaLore 스케일",
"info": "GaLore 스케일링 계수.",
},
"ja": {
"label": "GaLore スケール",
"info": "GaLore スケーリング係数。",
},
},
"galore_target": {
"en": {
......@@ -1248,6 +1496,10 @@ LOCALES = {
"label": "GaLore 모듈",
"info": "GaLore를 적용할 모듈의 이름. 모듈 간에는 쉼표(,)로 구분하십시오.",
},
"ja": {
"label": "GaLore モジュール",
"info": "GaLore を適用するモジュールの名前。複数のモジュールを区切るにはカンマを使用します。",
},
},
"apollo_tab": {
"en": {
......@@ -1262,23 +1514,30 @@ LOCALES = {
"ko": {
"label": "APOLLO 구성",
},
"ja": {
"label": "APOLLO 設定",
},
},
"use_apollo": {
"en": {
"label": "Use APOLLO",
"info": "Use APOLLO optimizer.",
"info": "Use [APOLLO](https://github.com/zhuhanqing/APOLLO) optimizer.",
},
"ru": {
"label": "Использовать APOLLO",
"info": "Используйте оптимизатор APOLLO.",
"info": "Используйте оптимизатор [APOLLO](https://github.com/zhuhanqing/APOLLO).",
},
"zh": {
"label": "使用 APOLLO",
"info": "使用 APOLLO 优化器。",
"info": "使用 [APOLLO](https://github.com/zhuhanqing/APOLLO) 优化器。",
},
"ko": {
"label": "APOLLO 사용",
"info": "APOLLO 최적화를 사용하세요.",
"info": "[APOLLO](https://github.com/zhuhanqing/APOLLO) 최적화를 사용하세요.",
},
"ja": {
"label": "APOLLO を使用",
"info": "[APOLLO](https://github.com/zhuhanqing/APOLLO) オプティマイザーを使用します。",
},
},
"apollo_rank": {
......@@ -1298,6 +1557,10 @@ LOCALES = {
"label": "APOLLO 랭크",
"info": "APOLLO 그레디언트의 랭크.",
},
"ja": {
"label": "APOLLO ランク",
"info": "APOLLO 勾配のランク。",
},
},
"apollo_update_interval": {
"en": {
......@@ -1316,6 +1579,10 @@ LOCALES = {
"label": "업데이트 간격",
"info": "APOLLO 프로젝션을 업데이트할 간격의 스텝 수.",
},
"ja": {
"label": "更新間隔",
"info": "隣接する 2 回の投影更新間のステップ数。",
},
},
"apollo_scale": {
"en": {
......@@ -1334,6 +1601,10 @@ LOCALES = {
"label": "APOLLO 스케일",
"info": "APOLLO 스케일링 계수.",
},
"ja": {
"label": "APOLLO スケール",
"info": "APOLLO スケーリング係数。",
},
},
"apollo_target": {
"en": {
......@@ -1352,6 +1623,10 @@ LOCALES = {
"label": "APOLLO 모듈",
"info": "APOLLO를 적용할 모듈의 이름. 모듈 간에는 쉼표(,)로 구분하십시오.",
},
"ja": {
"label": "APOLLO モジュール",
"info": "APOLLO を適用するモジュールの名前。複数のモジュールを区切るにはカンマを使用します。",
},
},
"badam_tab": {
"en": {
......@@ -1366,23 +1641,30 @@ LOCALES = {
"ko": {
"label": "BAdam 설정",
},
"ja": {
"label": "BAdam 設定",
},
},
"use_badam": {
"en": {
"label": "Use BAdam",
"info": "Enable the BAdam optimizer.",
"info": "Enable the [BAdam](https://github.com/Ledzy/BAdam) optimizer.",
},
"ru": {
"label": "Использовать BAdam",
"info": "Включите оптимизатор BAdam.",
"info": "Включите оптимизатор [BAdam](https://github.com/Ledzy/BAdam).",
},
"zh": {
"label": "使用 BAdam",
"info": "使用 BAdam 优化器。",
"info": "使用 [BAdam](https://github.com/Ledzy/BAdam) 优化器。",
},
"ko": {
"label": "BAdam 사용",
"info": "BAdam 옵티마이저를 사용합니다.",
"info": "[BAdam](https://github.com/Ledzy/BAdam) 옵티마이저를 사용합니다.",
},
"ja": {
"label": "BAdam を使用",
"info": "[BAdam](https://github.com/Ledzy/BAdam) オプティマイザーを使用します。",
},
},
"badam_mode": {
......@@ -1402,6 +1684,10 @@ LOCALES = {
"label": "BAdam 모드",
"info": "레이어-BAdam 옵티마이저인지 비율-BAdam 옵티마이저인지.",
},
"ja": {
"label": "BAdam モード",
"info": "layer-wise または ratio-wise BAdam オプティマイザーを使用します。",
},
},
"badam_switch_mode": {
"en": {
......@@ -1420,6 +1706,10 @@ LOCALES = {
"label": "스위치 모드",
"info": "레이어-BAdam을 위한 블록 선택 전략.",
},
"ja": {
"label": "切り替え戦略",
"info": "Layer-wise BAdam オプティマイザーのブロック切り替え戦略。",
},
},
"badam_switch_interval": {
"en": {
......@@ -1438,6 +1728,10 @@ LOCALES = {
"label": "전환 간격",
"info": "레이어-BAdam을 위한 블록 업데이트 간 스텝 수.",
},
"ja": {
"label": "切り替え頻度",
"info": "Layer-wise BAdam オプティマイザーのブロック切り替え頻度。",
},
},
"badam_update_ratio": {
"en": {
......@@ -1456,6 +1750,10 @@ LOCALES = {
"label": "업데이트 비율",
"info": "비율-BAdam의 업데이트 비율.",
},
"ja": {
"label": "ブロック更新比率",
"info": "Ratio-wise BAdam オプティマイザーの更新比率。",
},
},
"swanlab_tab": {
"en": {
......@@ -1470,23 +1768,30 @@ LOCALES = {
"ko": {
"label": "SwanLab 설정",
},
"ja": {
"label": "SwanLab 設定",
},
},
"use_swanlab": {
"en": {
"label": "Use SwanLab",
"info": "Enable SwanLab for experiment tracking and visualization.",
"info": "Enable [SwanLab](https://swanlab.cn/) for experiment tracking and visualization.",
},
"ru": {
"label": "Использовать SwanLab",
"info": "Включить SwanLab для отслеживания и визуализации экспериментов.",
"info": "Включить [SwanLab](https://swanlab.cn/) для отслеживания и визуализации экспериментов.",
},
"zh": {
"label": "使用 SwanLab",
"info": "启用 SwanLab 进行实验跟踪和可视化。",
"info": "启用 [SwanLab](https://swanlab.cn/) 进行实验跟踪和可视化。",
},
"ko": {
"label": "SwanLab 사용",
"info": "SwanLab를 사용하여 실험을 추적하고 시각화합니다.",
"info": "[SwanLab](https://swanlab.cn/) 를 사용하여 실험을 추적하고 시각화합니다.",
},
"ja": {
"label": "SwanLab を使用",
"info": "[SwanLab](https://swanlab.cn/) を有効にして実験の追跡と可視化を行います。",
},
},
"swanlab_project": {
......@@ -1502,6 +1807,9 @@ LOCALES = {
"ko": {
"label": "SwanLab 프로젝트",
},
"ja": {
"label": "SwanLab プロジェクト",
},
},
"swanlab_run_name": {
"en": {
......@@ -1516,6 +1824,9 @@ LOCALES = {
"ko": {
"label": "SwanLab 실험 이름 (선택 사항)",
},
"ja": {
"label": "SwanLab 実験名(オプション)",
},
},
"swanlab_workspace": {
"en": {
......@@ -1534,6 +1845,10 @@ LOCALES = {
"label": "SwanLab 작업 영역 (선택 사항)",
"info": "SwanLab 조직의 작업 영역, 비어 있으면 기본적으로 개인 작업 영역에 있습니다.",
},
"ja": {
"label": "SwanLab ワークスペース(オプション)",
"info": "SwanLab のワークスペース。デフォルトでは個人ワークスペースです。",
},
},
"swanlab_api_key": {
"en": {
......@@ -1545,13 +1860,17 @@ LOCALES = {
"info": "API ключ для SwanLab.",
},
"zh": {
"label": "SwanLab API密钥(非必填)",
"label": "SwanLab API 密钥(非必填)",
"info": "用于在编程环境登录 SwanLab,已登录则无需填写。",
},
"ko": {
"label": "SwanLab API 키 (선택 사항)",
"info": "SwanLab의 API 키.",
},
"ja": {
"label": "SwanLab API キー(オプション)",
"info": "SwanLab の API キー。",
},
},
"swanlab_mode": {
"en": {
......@@ -1570,6 +1889,10 @@ LOCALES = {
"label": "SwanLab 모드",
"info": "클라우드 버전 또는 오프라인 버전.",
},
"ja": {
"label": "SwanLab モード",
"info": "クラウド版またはオフライン版 SwanLab を使用します。",
},
},
"cmd_preview_btn": {
"en": {
......@@ -1584,6 +1907,9 @@ LOCALES = {
"ko": {
"value": "명령어 미리보기",
},
"ja": {
"value": "コマンドをプレビュー",
},
},
"arg_save_btn": {
"en": {
......@@ -1598,6 +1924,9 @@ LOCALES = {
"ko": {
"value": "Argument 저장",
},
"ja": {
"value": "引数を保存",
},
},
"arg_load_btn": {
"en": {
......@@ -1612,6 +1941,9 @@ LOCALES = {
"ko": {
"value": "Argument 불러오기",
},
"ja": {
"value": "引数を読み込む",
},
},
"start_btn": {
"en": {
......@@ -1626,6 +1958,9 @@ LOCALES = {
"ko": {
"value": "시작",
},
"ja": {
"value": "開始",
},
},
"stop_btn": {
"en": {
......@@ -1640,6 +1975,9 @@ LOCALES = {
"ko": {
"value": "중단",
},
"ja": {
"value": "中断",
},
},
"output_dir": {
"en": {
......@@ -1658,6 +1996,10 @@ LOCALES = {
"label": "출력 디렉토리",
"info": "결과를 저장할 디렉토리.",
},
"ja": {
"label": "出力ディレクトリ",
"info": "結果を保存するパス。",
},
},
"config_path": {
"en": {
......@@ -1676,6 +2018,10 @@ LOCALES = {
"label": "설정 경로",
"info": "Arguments 저장 파일 경로.",
},
"ja": {
"label": "設定パス",
"info": "トレーニングパラメータを保存する設定ファイルのパス。",
},
},
"device_count": {
"en": {
......@@ -1694,6 +2040,10 @@ LOCALES = {
"label": "디바이스 수",
"info": "사용 가능한 디바이스 수.",
},
"ja": {
"label": "デバイス数",
"info": "現在利用可能な演算デバイス数。",
},
},
"ds_stage": {
"en": {
......@@ -1712,6 +2062,10 @@ LOCALES = {
"label": "DeepSpeed 단계",
"info": "분산 학습을 위한 DeepSpeed 단계.",
},
"ja": {
"label": "DeepSpeed stage",
"info": "マルチ GPU トレーニングの DeepSpeed stage。",
},
},
"ds_offload": {
"en": {
......@@ -1730,6 +2084,10 @@ LOCALES = {
"label": "오프로딩 활성화",
"info": "DeepSpeed 오프로딩 활성화 (훈련 속도 느려짐).",
},
"ja": {
"label": "オフロードを使用",
"info": "DeepSpeed オフロードを使用します(速度が遅くなります)。",
},
},
"output_box": {
"en": {
......@@ -1744,6 +2102,9 @@ LOCALES = {
"ko": {
"value": "준비 완료.",
},
"ja": {
"value": "準備完了。",
},
},
"loss_viewer": {
"en": {
......@@ -1758,6 +2119,9 @@ LOCALES = {
"ko": {
"label": "손실",
},
"ja": {
"label": "損失",
},
},
"predict": {
"en": {
......@@ -1772,6 +2136,9 @@ LOCALES = {
"ko": {
"label": "예측 결과 저장",
},
"ja": {
"label": "予測結果を保存",
},
},
"infer_backend": {
"en": {
......@@ -1786,6 +2153,9 @@ LOCALES = {
"ko": {
"label": "추론 엔진",
},
"ja": {
"label": "推論エンジン",
},
},
"infer_dtype": {
"en": {
......@@ -1800,6 +2170,9 @@ LOCALES = {
"ko": {
"label": "추론 데이터 유형",
},
"ja": {
"label": "推論データタイプ",
},
},
"load_btn": {
"en": {
......@@ -1814,6 +2187,9 @@ LOCALES = {
"ko": {
"value": "모델 불러오기",
},
"ja": {
"value": "モデルを読み込む",
},
},
"unload_btn": {
"en": {
......@@ -1828,6 +2204,9 @@ LOCALES = {
"ko": {
"value": "모델 언로드",
},
"ja": {
"value": "モデルをアンロード",
},
},
"info_box": {
"en": {
......@@ -1842,6 +2221,9 @@ LOCALES = {
"ko": {
"value": "모델이 언로드되었습니다. 모델을 먼저 불러오십시오.",
},
"ja": {
"value": "モデルがロードされていません。最初にモデルをロードしてください。",
},
},
"role": {
"en": {
......@@ -1856,6 +2238,9 @@ LOCALES = {
"ko": {
"label": "역할",
},
"ja": {
"label": "役割",
},
},
"system": {
"en": {
......@@ -1870,6 +2255,9 @@ LOCALES = {
"ko": {
"placeholder": "시스템 프롬프트 (선택 사항)",
},
"ja": {
"placeholder": "システムプロンプト(オプション)",
},
},
"tools": {
"en": {
......@@ -1884,6 +2272,9 @@ LOCALES = {
"ko": {
"placeholder": "툴 (선택 사항)",
},
"ja": {
"placeholder": "ツールリスト(オプション)",
},
},
"image": {
"en": {
......@@ -1898,6 +2289,9 @@ LOCALES = {
"ko": {
"label": "이미지 (선택 사항)",
},
"ja": {
"label": "画像(オプション)",
},
},
"video": {
"en": {
......@@ -1912,6 +2306,9 @@ LOCALES = {
"ko": {
"label": "비디오 (선택 사항)",
},
"ja": {
"label": "動画(オプション)",
},
},
"query": {
"en": {
......@@ -1926,6 +2323,9 @@ LOCALES = {
"ko": {
"placeholder": "입력...",
},
"ja": {
"placeholder": "入力...",
},
},
"submit_btn": {
"en": {
......@@ -1940,6 +2340,9 @@ LOCALES = {
"ko": {
"value": "제출",
},
"ja": {
"value": "送信",
},
},
"max_length": {
"en": {
......@@ -1954,6 +2357,9 @@ LOCALES = {
"ko": {
"label": "최대 길이",
},
"ja": {
"label": "最大長",
},
},
"max_new_tokens": {
"en": {
......@@ -1968,6 +2374,9 @@ LOCALES = {
"ko": {
"label": "응답의 최대 길이",
},
"ja": {
"label": "最大生成長",
},
},
"top_p": {
"en": {
......@@ -1982,6 +2391,9 @@ LOCALES = {
"ko": {
"label": "Top-p",
},
"ja": {
"label": "Top-p",
},
},
"temperature": {
"en": {
......@@ -1996,6 +2408,43 @@ LOCALES = {
"ko": {
"label": "온도",
},
"ja": {
"label": "温度",
},
},
"skip_special_tokens": {
"en": {
"label": "Skip special tokens",
},
"ru": {
"label": "Пропустить специальные токены",
},
"zh": {
"label": "跳过特殊 token",
},
"ko": {
"label": "스페셜 토큰을 건너뛰기",
},
"ja": {
"label": "スペシャルトークンをスキップ",
},
},
"escape_html": {
"en": {
"label": "Escape HTML tags",
},
"ru": {
"label": "Исключить HTML теги",
},
"zh": {
"label": "转义 HTML 标签",
},
"ko": {
"label": "HTML 태그 이스케이프",
},
"ja": {
"label": "HTML タグをエスケープ",
},
},
"clear_btn": {
"en": {
......@@ -2010,6 +2459,9 @@ LOCALES = {
"ko": {
"value": "기록 지우기",
},
"ja": {
"value": "履歴をクリア",
},
},
"export_size": {
"en": {
......@@ -2028,6 +2480,10 @@ LOCALES = {
"label": "최대 샤드 크기 (GB)",
"info": "모델 파일의 최대 크기.",
},
"ja": {
"label": "最大シャードサイズ(GB)",
"info": "単一のモデルファイルの最大サイズ。",
},
},
"export_quantization_bit": {
"en": {
......@@ -2046,6 +2502,10 @@ LOCALES = {
"label": "양자화 비트 내보내기",
"info": "내보낸 모델의 양자화.",
},
"ja": {
"label": "量子化ビットをエクスポート",
"info": "エクスポートするモデルを量子化します。",
},
},
"export_quantization_dataset": {
"en": {
......@@ -2064,6 +2524,10 @@ LOCALES = {
"label": "양자화 데이터셋 내보내기",
"info": "양자화에 사용되는 교정 데이터셋.",
},
"ja": {
"label": "量子化データセットをエクスポート",
"info": "量子化プロセスで使用されるキャリブレーションデータセット。",
},
},
"export_device": {
"en": {
......@@ -2082,6 +2546,10 @@ LOCALES = {
"label": "내보낼 장치",
"info": "모델을 내보내는 데 사용할 장치.",
},
"ja": {
"label": "エクスポートデバイス",
"info": "モデルをエクスポートするために使用するデバイスタイプ。",
},
},
"export_legacy_format": {
"en": {
......@@ -2100,6 +2568,10 @@ LOCALES = {
"label": "레거시 형식 내보내기",
"info": "모델을 저장하는 데 safetensors를 사용하지 않습니다.",
},
"ja": {
"label": "レガシーフォーマットをエクスポート",
"info": "safetensors フォーマットを使用せずにモデルを保存します。",
},
},
"export_dir": {
"en": {
......@@ -2118,6 +2590,10 @@ LOCALES = {
"label": "내보내기 디렉토리",
"info": "내보낸 모델을 저장할 디렉토리.",
},
"ja": {
"label": "エクスポートディレクトリ",
"info": "エクスポートしたモデルを保存するフォルダのパス。",
},
},
"export_hub_model_id": {
"en": {
......@@ -2136,6 +2612,10 @@ LOCALES = {
"label": "HF 허브 ID (선택 사항)",
"info": "모델을 Hugging Face 허브에 업로드하기 위한 레포 ID.",
},
"ja": {
"label": "HF Hub ID(オプション)",
"info": "Hugging Face Hub にモデルをアップロードするためのリポジトリ ID。",
},
},
"export_btn": {
"en": {
......@@ -2150,6 +2630,9 @@ LOCALES = {
"ko": {
"value": "내보내기",
},
"ja": {
"value": "エクスポート",
},
},
}
......@@ -2160,167 +2643,216 @@ ALERTS = {
"ru": "Процесс уже запущен, пожалуйста, сначала прервите его.",
"zh": "任务已存在,请先中断训练。",
"ko": "프로세스가 실행 중입니다. 먼저 중단하십시오.",
"ja": "プロセスが実行中です。最初に中断してください。",
},
"err_exists": {
"en": "You have loaded a model, please unload it first.",
"ru": "Вы загрузили модель, сначала разгрузите ее.",
"zh": "模型已存在,请先卸载模型。",
"ko": "모델이 로드되었습니다. 먼저 언로드하십시오.",
"ja": "モデルがロードされています。最初にアンロードしてください。",
},
"err_no_model": {
"en": "Please select a model.",
"ru": "Пожалуйста, выберите модель.",
"zh": "请选择模型。",
"ko": "모델을 선택하십시오.",
"ja": "モデルを選択してください。",
},
"err_no_path": {
"en": "Model not found.",
"ru": "Модель не найдена.",
"zh": "模型未找到。",
"ko": "모델을 찾을 수 없습니다.",
"ja": "モデルが見つかりません。",
},
"err_no_dataset": {
"en": "Please choose a dataset.",
"ru": "Пожалуйста, выберите набор данных.",
"zh": "请选择数据集。",
"ko": "데이터 세트를 선택하십시오.",
"ja": "データセットを選択してください。",
},
"err_no_adapter": {
"en": "Please select an adapter.",
"ru": "Пожалуйста, выберите адаптер.",
"zh": "请选择适配器。",
"ko": "어댑터를 선택하십시오.",
"ja": "アダプターを選択してください。",
},
"err_no_output_dir": {
"en": "Please provide output dir.",
"ru": "Пожалуйста, укажите выходную директорию.",
"zh": "请填写输出目录。",
"ko": "출력 디렉토리를 제공하십시오.",
"ja": "出力ディレクトリを入力してください。",
},
"err_no_reward_model": {
"en": "Please select a reward model.",
"ru": "Пожалуйста, выберите модель вознаграждения.",
"zh": "请选择奖励模型。",
"ko": "리워드 모델을 선택하십시오.",
"ja": "報酬モデルを選択してください。",
},
"err_no_export_dir": {
"en": "Please provide export dir.",
"ru": "Пожалуйста, укажите каталог для экспорта.",
"zh": "请填写导出目录。",
"ko": "Export 디렉토리를 제공하십시오.",
"ja": "エクスポートディレクトリを入力してください。",
},
"err_gptq_lora": {
"en": "Please merge adapters before quantizing the model.",
"ru": "Пожалуйста, объедините адаптеры перед квантованием модели.",
"zh": "量化模型前请先合并适配器。",
"ko": "모델을 양자화하기 전에 어댑터를 병합하십시오.",
"ja": "モデルを量子化する前にアダプターをマージしてください。",
},
"err_failed": {
"en": "Failed.",
"ru": "Ошибка.",
"zh": "训练出错。",
"ko": "실패했습니다.",
"ja": "失敗しました。",
},
"err_demo": {
"en": "Training is unavailable in demo mode, duplicate the space to a private one first.",
"ru": "Обучение недоступно в демонстрационном режиме, сначала скопируйте пространство в частное.",
"zh": "展示模式不支持训练,请先复制到私人空间。",
"ko": "데모 모드에서는 훈련을 사용할 수 없습니다. 먼저 프라이빗 레포지토리로 작업 공간을 복제하십시오.",
"ja": "デモモードではトレーニングは利用できません。最初にプライベートスペースに複製してください。",
},
"err_tool_name": {
"en": "Tool name not found.",
"ru": "Имя инструмента не найдено.",
"zh": "工具名称未找到。",
"ko": "툴 이름을 찾을 수 없습니다.",
"ja": "ツール名が見つかりません。",
},
"err_json_schema": {
"en": "Invalid JSON schema.",
"ru": "Неверная схема JSON.",
"zh": "Json 格式错误。",
"ko": "잘못된 JSON 스키마입니다.",
"ja": "JSON スキーマが無効です。",
},
"err_config_not_found": {
"en": "Config file is not found.",
"ru": "Файл конфигурации не найден.",
"zh": "未找到配置文件。",
"ko": "Config 파일을 찾을 수 없습니다.",
"ja": "設定ファイルが見つかりません。",
},
"warn_no_cuda": {
"en": "CUDA environment was not detected.",
"ru": "Среда CUDA не обнаружена.",
"zh": "未检测到 CUDA 环境。",
"ko": "CUDA 환경이 감지되지 않았습니다.",
"ja": "CUDA 環境が検出されませんでした。",
},
"warn_output_dir_exists": {
"en": "Output dir already exists, will resume training from here.",
"ru": "Выходной каталог уже существует, обучение будет продолжено отсюда.",
"zh": "输出目录已存在,将从该断点恢复训练。",
"ko": "출력 디렉토리가 이미 존재합니다. 위 출력 디렉토리에 저장된 학습을 재개합니다.",
"ja": "出力ディレクトリが既に存在します。このチェックポイントからトレーニングを再開します。",
},
"info_aborting": {
"en": "Aborted, wait for terminating...",
"ru": "Прервано, ожидание завершения...",
"zh": "训练中断,正在等待进程结束……",
"ko": "중단되었습니다. 종료를 기다리십시오...",
"ja": "トレーニングが中断されました。プロセスの終了を待っています...",
},
"info_aborted": {
"en": "Ready.",
"ru": "Готово.",
"zh": "准备就绪。",
"ko": "준비되었습니다.",
"ja": "準備完了。",
},
"info_finished": {
"en": "Finished.",
"ru": "Завершено.",
"zh": "训练完毕。",
"ko": "완료되었습니다.",
"ja": "トレーニングが完了しました。",
},
"info_config_saved": {
"en": "Arguments have been saved at: ",
"ru": "Аргументы были сохранены по адресу: ",
"zh": "训练参数已保存至:",
"ko": "매개변수가 저장되었습니다: ",
"ja": "トレーニングパラメータが保存されました: ",
},
"info_config_loaded": {
"en": "Arguments have been restored.",
"ru": "Аргументы были восстановлены.",
"zh": "训练参数已载入。",
"ko": "매개변수가 복원되었습니다.",
"ja": "トレーニングパラメータが読み込まれました。",
},
"info_loading": {
"en": "Loading model...",
"ru": "Загрузка модели...",
"zh": "加载中……",
"ko": "모델 로딩 중...",
"ja": "モデルをロード中...",
},
"info_unloading": {
"en": "Unloading model...",
"ru": "Выгрузка модели...",
"zh": "卸载中……",
"ko": "모델 언로딩 중...",
"ja": "モデルをアンロード中...",
},
"info_loaded": {
"en": "Model loaded, now you can chat with your model!",
"ru": "Модель загружена, теперь вы можете общаться с вашей моделью!",
"zh": "模型已加载,可以开始聊天了!",
"ko": "모델이 로드되었습니다. 이제 모델과 채팅할 수 있습니다!",
"ja": "モデルがロードされました。チャットを開始できます!",
},
"info_unloaded": {
"en": "Model unloaded.",
"ru": "Модель выгружена.",
"zh": "模型已卸载。",
"ko": "모델이 언로드되었습니다.",
"ja": "モデルがアンロードされました。",
},
"info_thinking": {
"en": "🌀 Thinking...",
"ru": "🌀 Думаю...",
"zh": "🌀 思考中...",
"ko": "🌀 생각 중...",
"ja": "🌀 考えています...",
},
"info_thought": {
"en": "✅ Thought",
"ru": "✅ Думать закончено",
"zh": "✅ 思考完成",
"ko": "✅ 생각이 완료되었습니다",
"ja": "✅ 思考完了",
},
"info_exporting": {
"en": "Exporting model...",
"ru": "Экспорт модели...",
"zh": "正在导出模型……",
"ko": "모델 내보내기 중...",
"ja": "モデルをエクスポート中...",
},
"info_exported": {
"en": "Model exported.",
"ru": "Модель экспортирована.",
"zh": "模型导出完成。",
"ko": "모델이 내보내졌습니다.",
"ja": "モデルのエクスポートが完了しました。",
},
"info_swanlab_link": {
"en": "### SwanLab Link\n",
"ru": "### SwanLab ссылка\n",
"zh": "### SwanLab 链接\n",
"ko": "### SwanLab 링크\n",
"ja": "### SwanLab リンク\n",
},
}
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -20,6 +20,10 @@ if TYPE_CHECKING:
class Manager:
r"""
A class to manage all the gradio components in Web UI.
"""
def __init__(self) -> None:
self._id_to_elem: Dict[str, "Component"] = {}
self._elem_to_id: Dict["Component", str] = {}
......
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -23,10 +23,21 @@ from transformers.utils import is_torch_npu_available
from ..extras.constants import LLAMABOARD_CONFIG, PEFT_METHODS, TRAINING_STAGES
from ..extras.misc import is_gpu_or_npu_available, torch_gc, use_ray
from ..extras.packages import is_gradio_available, is_transformers_version_equal_to_4_46
from .common import DEFAULT_CACHE_DIR, DEFAULT_CONFIG_DIR, QUANTIZATION_BITS, get_save_dir, load_config
from ..extras.packages import is_gradio_available
from .common import (
DEFAULT_CACHE_DIR,
DEFAULT_CONFIG_DIR,
abort_process,
gen_cmd,
get_save_dir,
load_args,
load_config,
load_eval_results,
save_args,
save_cmd,
)
from .control import get_trainer_info
from .locales import ALERTS, LOCALES
from .utils import abort_process, gen_cmd, get_eval_results, get_trainer_info, load_args, save_args, save_cmd
if is_gradio_available():
......@@ -40,6 +51,10 @@ if TYPE_CHECKING:
class Runner:
r"""
A class to manage the running status of the trainers.
"""
def __init__(self, manager: "Manager", demo_mode: bool = False) -> None:
self.manager = manager
self.demo_mode = demo_mode
......@@ -57,6 +72,9 @@ class Runner:
abort_process(self.trainer.pid)
def _initialize(self, data: Dict["Component", Any], do_train: bool, from_preview: bool) -> str:
r"""
Validates the configuration.
"""
get = lambda elem_id: data[self.manager.get_elem_by_id(elem_id)]
lang, model_name, model_path = get("top.lang"), get("top.model_name"), get("top.model_path")
dataset = get("train.dataset") if do_train else get("eval.dataset")
......@@ -98,6 +116,9 @@ class Runner:
return ""
def _finalize(self, lang: str, finish_info: str) -> str:
r"""
Cleans the cached memory and resets the runner.
"""
finish_info = ALERTS["info_aborted"][lang] if self.aborted else finish_info
gr.Info(finish_info)
self.trainer = None
......@@ -108,6 +129,9 @@ class Runner:
return finish_info
def _parse_train_args(self, data: Dict["Component", Any]) -> Dict[str, Any]:
r"""
Builds and validates the training arguments.
"""
get = lambda elem_id: data[self.manager.get_elem_by_id(elem_id)]
model_name, finetuning_type = get("top.model_name"), get("top.finetuning_type")
user_config = load_config()
......@@ -120,7 +144,7 @@ class Runner:
preprocessing_num_workers=16,
finetuning_type=finetuning_type,
template=get("top.template"),
rope_scaling=get("top.rope_scaling") if get("top.rope_scaling") in ["linear", "dynamic"] else None,
rope_scaling=get("top.rope_scaling") if get("top.rope_scaling") != "none" else None,
flash_attn="fa2" if get("top.booster") == "flashattn2" else "auto",
use_unsloth=(get("top.booster") == "unsloth"),
enable_liger_kernel=(get("top.booster") == "liger_kernel"),
......@@ -144,8 +168,7 @@ class Runner:
mask_history=get("train.mask_history"),
resize_vocab=get("train.resize_vocab"),
use_llama_pro=get("train.use_llama_pro"),
shift_attn=get("train.shift_attn"),
report_to="all" if get("train.report_to") else "none",
report_to=get("train.report_to"),
use_galore=get("train.use_galore"),
use_apollo=get("train.use_apollo"),
use_badam=get("train.use_badam"),
......@@ -157,7 +180,7 @@ class Runner:
plot_loss=True,
trust_remote_code=True,
ddp_timeout=180000000,
include_num_input_tokens_seen=False if is_transformers_version_equal_to_4_46() else True, # FIXME
include_num_input_tokens_seen=True,
)
args.update(json.loads(get("train.extra_args")))
......@@ -171,7 +194,7 @@ class Runner:
args["model_name_or_path"] = get_save_dir(model_name, finetuning_type, get("top.checkpoint_path"))
# quantization
if get("top.quantization_bit") in QUANTIZATION_BITS:
if get("top.quantization_bit") != "none":
args["quantization_bit"] = int(get("top.quantization_bit"))
args["quantization_method"] = get("top.quantization_method")
args["double_quantization"] = not is_torch_npu_available()
......@@ -239,6 +262,12 @@ class Runner:
args["badam_switch_interval"] = get("train.badam_switch_interval")
args["badam_update_ratio"] = get("train.badam_update_ratio")
# report_to
if "none" in args["report_to"]:
args["report_to"] = "none"
elif "all" in args["report_to"]:
args["report_to"] = "all"
# swanlab config
if get("train.use_swanlab"):
args["swanlab_project"] = get("train.swanlab_project")
......@@ -263,6 +292,9 @@ class Runner:
return args
def _parse_eval_args(self, data: Dict["Component", Any]) -> Dict[str, Any]:
r"""
Builds and validates the evaluation arguments.
"""
get = lambda elem_id: data[self.manager.get_elem_by_id(elem_id)]
model_name, finetuning_type = get("top.model_name"), get("top.finetuning_type")
user_config = load_config()
......@@ -275,7 +307,7 @@ class Runner:
finetuning_type=finetuning_type,
quantization_method=get("top.quantization_method"),
template=get("top.template"),
rope_scaling=get("top.rope_scaling") if get("top.rope_scaling") in ["linear", "dynamic"] else None,
rope_scaling=get("top.rope_scaling") if get("top.rope_scaling") != "none" else None,
flash_attn="fa2" if get("top.booster") == "flashattn2" else "auto",
use_unsloth=(get("top.booster") == "unsloth"),
dataset_dir=get("eval.dataset_dir"),
......@@ -306,13 +338,17 @@ class Runner:
args["model_name_or_path"] = get_save_dir(model_name, finetuning_type, get("top.checkpoint_path"))
# quantization
if get("top.quantization_bit") in QUANTIZATION_BITS:
if get("top.quantization_bit") != "none":
args["quantization_bit"] = int(get("top.quantization_bit"))
args["quantization_method"] = get("top.quantization_method")
args["double_quantization"] = not is_torch_npu_available()
return args
def _preview(self, data: Dict["Component", Any], do_train: bool) -> Generator[Dict["Component", str], None, None]:
r"""
Previews the training commands.
"""
output_box = self.manager.get_elem_by_id("{}.output_box".format("train" if do_train else "eval"))
error = self._initialize(data, do_train, from_preview=True)
if error:
......@@ -323,6 +359,9 @@ class Runner:
yield {output_box: gen_cmd(args)}
def _launch(self, data: Dict["Component", Any], do_train: bool) -> Generator[Dict["Component", Any], None, None]:
r"""
Starts the training process.
"""
output_box = self.manager.get_elem_by_id("{}.output_box".format("train" if do_train else "eval"))
error = self._initialize(data, do_train, from_preview=False)
if error:
......@@ -333,7 +372,7 @@ class Runner:
args = self._parse_train_args(data) if do_train else self._parse_eval_args(data)
os.makedirs(args["output_dir"], exist_ok=True)
save_args(os.path.join(args["output_dir"], LLAMABOARD_CONFIG), self._form_config_dict(data))
save_args(os.path.join(args["output_dir"], LLAMABOARD_CONFIG), self._build_config_dict(data))
env = deepcopy(os.environ)
env["LLAMABOARD_ENABLED"] = "1"
......@@ -344,7 +383,10 @@ class Runner:
self.trainer = Popen(["llamafactory-cli", "train", save_cmd(args)], env=env)
yield from self.monitor()
def _form_config_dict(self, data: Dict["Component", Any]) -> Dict[str, Any]:
def _build_config_dict(self, data: Dict["Component", Any]) -> Dict[str, Any]:
r"""
Builds a dictionary containing the current training configuration.
"""
config_dict = {}
skip_ids = ["top.lang", "top.model_path", "train.output_dir", "train.config_path"]
for elem, value in data.items():
......@@ -367,6 +409,9 @@ class Runner:
yield from self._launch(data, do_train=False)
def monitor(self):
r"""
Monitors the training progress and logs.
"""
self.aborted = False
self.running = True
......@@ -378,6 +423,7 @@ class Runner:
output_box = self.manager.get_elem_by_id("{}.output_box".format("train" if self.do_train else "eval"))
progress_bar = self.manager.get_elem_by_id("{}.progress_bar".format("train" if self.do_train else "eval"))
loss_viewer = self.manager.get_elem_by_id("train.loss_viewer") if self.do_train else None
swanlab_link = self.manager.get_elem_by_id("train.swanlab_link") if self.do_train else None
running_log = ""
while self.trainer is not None:
......@@ -387,16 +433,18 @@ class Runner:
progress_bar: gr.Slider(visible=False),
}
else:
running_log, running_progress, running_loss = get_trainer_info(output_path, self.do_train)
running_log, running_progress, running_info = get_trainer_info(lang, output_path, self.do_train)
return_dict = {
output_box: running_log,
progress_bar: running_progress,
}
if running_loss is not None:
return_dict[loss_viewer] = running_loss
if "loss_viewer" in running_info:
return_dict[loss_viewer] = running_info["loss_viewer"]
yield return_dict
if "swanlab_link" in running_info:
return_dict[swanlab_link] = running_info["swanlab_link"]
yield return_dict
try:
self.trainer.wait(2)
self.trainer = None
......@@ -410,7 +458,7 @@ class Runner:
finish_info = ALERTS["err_failed"][lang]
else:
if os.path.exists(os.path.join(output_path, "all_results.json")) or use_ray():
finish_info = get_eval_results(os.path.join(output_path, "all_results.json"))
finish_info = load_eval_results(os.path.join(output_path, "all_results.json"))
else:
finish_info = ALERTS["err_failed"][lang]
......@@ -421,6 +469,9 @@ class Runner:
yield return_dict
def save_args(self, data):
r"""
Saves the training configuration to config path.
"""
output_box = self.manager.get_elem_by_id("train.output_box")
error = self._initialize(data, do_train=True, from_preview=True)
if error:
......@@ -432,10 +483,13 @@ class Runner:
os.makedirs(DEFAULT_CONFIG_DIR, exist_ok=True)
save_path = os.path.join(DEFAULT_CONFIG_DIR, config_path)
save_args(save_path, self._form_config_dict(data))
save_args(save_path, self._build_config_dict(data))
return {output_box: ALERTS["info_config_saved"][lang] + save_path}
def load_args(self, lang: str, config_path: str):
r"""
Loads the training configuration from config path.
"""
output_box = self.manager.get_elem_by_id("train.output_box")
config_dict = load_args(os.path.join(DEFAULT_CONFIG_DIR, config_path))
if config_dict is None:
......@@ -449,6 +503,9 @@ class Runner:
return output_dict
def check_output_dir(self, lang: str, model_name: str, finetuning_type: str, output_dir: str):
r"""
Restore the training status if output_dir exists.
"""
output_box = self.manager.get_elem_by_id("train.output_box")
output_dict: Dict["Component", Any] = {output_box: LOCALES["output_box"][lang]["value"]}
if model_name and output_dir and os.path.isdir(get_save_dir(model_name, finetuning_type, output_dir)):
......
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -14,12 +14,13 @@
import os
from llamafactory.extras.misc import is_env_enabled
from llamafactory.webui.interface import create_ui
def main():
gradio_ipv6 = os.getenv("GRADIO_IPV6", "0").lower() in ["true", "1"]
gradio_share = os.getenv("GRADIO_SHARE", "0").lower() in ["true", "1"]
gradio_ipv6 = is_env_enabled("GRADIO_IPV6")
gradio_share = is_env_enabled("GRADIO_SHARE")
server_name = os.getenv("GRADIO_SERVER_NAME", "[::]" if gradio_ipv6 else "0.0.0.0")
create_ui().queue().launch(share=gradio_share, server_name=server_name, inbrowser=True)
......
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -16,7 +16,7 @@ from typing import Tuple
import pytest
from llamafactory.data.processors.processor_utils import infer_seqlen
from llamafactory.data.processor.processor_utils import infer_seqlen
@pytest.mark.parametrize(
......
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......
from llamafactory.data import Role
from llamafactory.data.converter import get_dataset_converter
from llamafactory.data.parser import DatasetAttr
from llamafactory.hparams import DataArguments
def test_alpaca_converter():
dataset_attr = DatasetAttr("hf_hub", "llamafactory/tiny-supervised-dataset")
data_args = DataArguments()
example = {
"instruction": "Solve the math problem.",
"input": "3 + 4",
"output": "The answer is 7.",
}
dataset_converter = get_dataset_converter("alpaca", dataset_attr, data_args)
assert dataset_converter(example) == {
"_prompt": [{"role": Role.USER.value, "content": "Solve the math problem.\n3 + 4"}],
"_response": [{"role": Role.ASSISTANT.value, "content": "The answer is 7."}],
"_system": "",
"_tools": "",
"_images": None,
"_videos": None,
"_audios": None,
}
def test_sharegpt_converter():
dataset_attr = DatasetAttr("hf_hub", "llamafactory/tiny-supervised-dataset")
data_args = DataArguments()
example = {
"conversations": [
{"from": "system", "value": "You are a helpful assistant."},
{"from": "human", "value": "Solve the math problem.\n3 + 4"},
{"from": "gpt", "value": "The answer is 7."},
]
}
dataset_converter = get_dataset_converter("sharegpt", dataset_attr, data_args)
assert dataset_converter(example) == {
"_prompt": [{"role": Role.USER.value, "content": "Solve the math problem.\n3 + 4"}],
"_response": [{"role": Role.ASSISTANT.value, "content": "The answer is 7."}],
"_system": "You are a helpful assistant.",
"_tools": "",
"_images": None,
"_videos": None,
"_audios": None,
}
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -123,11 +123,10 @@ def test_glm4_tool_extractor():
def test_llama3_function_formatter():
formatter = FunctionFormatter(slots=["{{content}}", "<|eot_id|>"], tool_format="llama3")
formatter = FunctionFormatter(slots=["{{content}}<|eot_id|>"], tool_format="llama3")
tool_calls = json.dumps({"name": "tool_name", "arguments": {"foo": "bar", "size": 10}})
assert formatter.apply(content=tool_calls) == [
"""{"name": "tool_name", "parameters": {"foo": "bar", "size": 10}}""",
"<|eot_id|>",
"""{"name": "tool_name", "parameters": {"foo": "bar", "size": 10}}<|eot_id|>"""
]
......@@ -150,20 +149,19 @@ def test_llama3_tool_extractor():
def test_mistral_function_formatter():
formatter = FunctionFormatter(slots=["[TOOL_CALLS] ", "{{content}}", "</s>"], tool_format="mistral")
formatter = FunctionFormatter(slots=["[TOOL_CALLS] {{content}}", "</s>"], tool_format="mistral")
tool_calls = json.dumps(FUNCTION)
assert formatter.apply(content=tool_calls) == [
"[TOOL_CALLS] ",
"""[{"name": "tool_name", "arguments": {"foo": "bar", "size": 10}}]""",
"[TOOL_CALLS] " """[{"name": "tool_name", "arguments": {"foo": "bar", "size": 10}}]""",
"</s>",
]
def test_mistral_multi_function_formatter():
formatter = FunctionFormatter(slots=["[TOOL_CALLS] ", "{{content}}", "</s>"], tool_format="mistral")
formatter = FunctionFormatter(slots=["[TOOL_CALLS] {{content}}", "</s>"], tool_format="mistral")
tool_calls = json.dumps([FUNCTION] * 2)
assert formatter.apply(content=tool_calls) == [
"[TOOL_CALLS] ",
"[TOOL_CALLS] "
"""[{"name": "tool_name", "arguments": {"foo": "bar", "size": 10}}, """
"""{"name": "tool_name", "arguments": {"foo": "bar", "size": 10}}]""",
"</s>",
......@@ -197,21 +195,20 @@ def test_mistral_multi_tool_extractor():
def test_qwen_function_formatter():
formatter = FunctionFormatter(slots=["{{content}}", "<|im_end|>"], tool_format="qwen")
formatter = FunctionFormatter(slots=["{{content}}<|im_end|>\n"], tool_format="qwen")
tool_calls = json.dumps(FUNCTION)
assert formatter.apply(content=tool_calls) == [
"""<tool_call>\n{"name": "tool_name", "arguments": {"foo": "bar", "size": 10}}\n</tool_call>""",
"<|im_end|>",
"""<tool_call>\n{"name": "tool_name", "arguments": {"foo": "bar", "size": 10}}\n</tool_call><|im_end|>\n"""
]
def test_qwen_multi_function_formatter():
formatter = FunctionFormatter(slots=["{{content}}", "<|im_end|>"], tool_format="qwen")
formatter = FunctionFormatter(slots=["{{content}}<|im_end|>\n"], tool_format="qwen")
tool_calls = json.dumps([FUNCTION] * 2)
assert formatter.apply(content=tool_calls) == [
"""<tool_call>\n{"name": "tool_name", "arguments": {"foo": "bar", "size": 10}}\n</tool_call>\n"""
"""<tool_call>\n{"name": "tool_name", "arguments": {"foo": "bar", "size": 10}}\n</tool_call>""",
"<|im_end|>",
"""<tool_call>\n{"name": "tool_name", "arguments": {"foo": "bar", "size": 10}}\n</tool_call>"""
"<|im_end|>\n"
]
......@@ -224,7 +221,7 @@ def test_qwen_tool_formatter():
f"\n{json.dumps(wrapped_tool, ensure_ascii=False)}"
"\n</tools>\n\nFor each function call, return a json object with function name and arguments within "
"""<tool_call></tool_call> XML tags:\n<tool_call>\n{"name": <function-name>, """
""""arguments": <args-json-object>}\n</tool_call><|im_end|>\n"""
""""arguments": <args-json-object>}\n</tool_call>"""
]
......
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -52,12 +52,16 @@ NO_IMAGES = []
NO_VIDEOS = []
NO_AUDIOS = []
IMGLENS = [1]
NO_IMGLENS = [0]
NO_VIDLENS = [0]
NO_AUDLENS = [0]
INPUT_IDS = [0, 1, 2, 3, 4]
LABELS = [0, 1, 2, 3, 4]
......@@ -99,30 +103,34 @@ def _check_plugin(
expected_no_mm_inputs: Dict[str, Any] = {},
) -> None:
# test mm_messages
assert plugin.process_messages(MM_MESSAGES, IMAGES, NO_VIDEOS, processor) == expected_mm_messages
assert plugin.process_token_ids(INPUT_IDS, LABELS, IMAGES, NO_VIDEOS, tokenizer, processor) == (
expected_input_ids,
expected_labels,
)
_is_close(
plugin.get_mm_inputs(IMAGES, NO_VIDEOS, IMGLENS, NO_VIDLENS, BATCH_IDS, processor),
expected_mm_inputs,
)
if plugin.__class__.__name__ != "BasePlugin":
assert plugin.process_messages(MM_MESSAGES, IMAGES, NO_VIDEOS, NO_AUDIOS, processor) == expected_mm_messages
assert plugin.process_token_ids(INPUT_IDS, LABELS, IMAGES, NO_VIDEOS, NO_AUDIOS, tokenizer, processor) == (
expected_input_ids,
expected_labels,
)
_is_close(
plugin.get_mm_inputs(IMAGES, NO_VIDEOS, NO_AUDIOS, IMGLENS, NO_VIDLENS, NO_AUDLENS, BATCH_IDS, processor),
expected_mm_inputs,
)
# test text_messages
assert plugin.process_messages(TEXT_MESSAGES, NO_IMAGES, NO_VIDEOS, processor) == TEXT_MESSAGES
assert plugin.process_token_ids(INPUT_IDS, LABELS, NO_IMAGES, NO_VIDEOS, tokenizer, processor) == (
assert plugin.process_messages(TEXT_MESSAGES, NO_IMAGES, NO_VIDEOS, NO_AUDIOS, processor) == TEXT_MESSAGES
assert plugin.process_token_ids(INPUT_IDS, LABELS, NO_IMAGES, NO_VIDEOS, NO_AUDIOS, tokenizer, processor) == (
INPUT_IDS,
LABELS,
)
_is_close(
plugin.get_mm_inputs(NO_IMAGES, NO_VIDEOS, NO_IMGLENS, NO_VIDLENS, BATCH_IDS, processor),
plugin.get_mm_inputs(
NO_IMAGES, NO_VIDEOS, NO_AUDIOS, NO_IMGLENS, NO_VIDLENS, NO_AUDLENS, BATCH_IDS, processor
),
expected_no_mm_inputs,
)
def test_base_plugin():
tokenizer_module = _load_tokenizer_module(model_name_or_path=TINY_LLAMA)
base_plugin = get_mm_plugin(name="base", image_token="<image>")
base_plugin = get_mm_plugin(name="base")
check_inputs = {"plugin": base_plugin, **tokenizer_module}
_check_plugin(**check_inputs)
......
# Copyright 2024 the LlamaFactory team.
#
# 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.
import os
import random
import pytest
from datasets import load_dataset
from transformers import AutoTokenizer
from llamafactory.data import get_dataset
from llamafactory.hparams import get_train_args
from llamafactory.model import load_tokenizer
TINY_LLAMA = os.environ.get("TINY_LLAMA", "llamafactory/tiny-random-Llama-3")
TRAIN_ARGS = {
"model_name_or_path": TINY_LLAMA,
"stage": "sft",
"do_train": True,
"finetuning_type": "full",
"dataset": "llamafactory/tiny-supervised-dataset",
"dataset_dir": "ONLINE",
"template": "llama3",
"cutoff_len": 8192,
"overwrite_cache": True,
"output_dir": "dummy_dir",
"overwrite_output_dir": True,
"fp16": True,
}
@pytest.mark.parametrize("num_samples", [16])
def test_supervised(num_samples: int):
model_args, data_args, training_args, _, _ = get_train_args(TRAIN_ARGS)
tokenizer_module = load_tokenizer(model_args)
tokenizer = tokenizer_module["tokenizer"]
tokenized_data = get_dataset(model_args, data_args, training_args, stage="sft", **tokenizer_module)
ref_tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA)
original_data = load_dataset(TRAIN_ARGS["dataset"], split="train")
indexes = random.choices(range(len(original_data)), k=num_samples)
for index in indexes:
prompt = original_data[index]["instruction"]
if original_data[index]["input"]:
prompt += "\n" + original_data[index]["input"]
messages = [
{"role": "user", "content": prompt},
{"role": "assistant", "content": original_data[index]["output"]},
]
templated_result = ref_tokenizer.apply_chat_template(messages, tokenize=False)
decoded_result = tokenizer.decode(tokenized_data["input_ids"][index])
assert templated_result == decoded_result
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -19,7 +19,7 @@ import pytest
from transformers import AutoTokenizer
from llamafactory.data import get_template_and_fix_tokenizer
from llamafactory.data.template import _get_jinja_template
from llamafactory.data.template import parse_template
from llamafactory.hparams import DataArguments
......@@ -115,11 +115,28 @@ def test_jinja_template(use_fast: bool):
tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA, use_fast=use_fast)
ref_tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA, use_fast=use_fast)
template = get_template_and_fix_tokenizer(tokenizer, DataArguments(template="llama3"))
tokenizer.chat_template = _get_jinja_template(template, tokenizer) # llama3 template no replace
tokenizer.chat_template = template._get_jinja_template(tokenizer) # llama3 template no replace
assert tokenizer.chat_template != ref_tokenizer.chat_template
assert tokenizer.apply_chat_template(MESSAGES) == ref_tokenizer.apply_chat_template(MESSAGES)
def test_ollama_modelfile():
tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA)
template = get_template_and_fix_tokenizer(tokenizer, DataArguments(template="llama3"))
assert template.get_ollama_modelfile(tokenizer) == (
"# ollama modelfile auto-generated by llamafactory\n\n"
"FROM .\n\n"
'TEMPLATE """<|begin_of_text|>'
"{{ if .System }}<|start_header_id|>system<|end_header_id|>\n\n{{ .System }}<|eot_id|>{{ end }}"
'{{ range .Messages }}{{ if eq .Role "user" }}<|start_header_id|>user<|end_header_id|>\n\n{{ .Content }}'
"<|eot_id|><|start_header_id|>assistant<|end_header_id|>\n\n"
'{{ else if eq .Role "assistant" }}{{ .Content }}<|eot_id|>{{ end }}{{ end }}"""\n\n'
'PARAMETER stop "<|eom_id|>"\n'
'PARAMETER stop "<|eot_id|>"\n'
"PARAMETER num_ctx 4096\n"
)
def test_get_stop_token_ids():
tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA)
template = get_template_and_fix_tokenizer(tokenizer, DataArguments(template="llama3"))
......@@ -152,6 +169,7 @@ def test_llama3_template(use_fast: bool):
_check_template("meta-llama/Meta-Llama-3-8B-Instruct", "llama3", prompt_str, answer_str, use_fast)
@pytest.mark.skipif(not HF_TOKEN, reason="Gated model.")
@pytest.mark.parametrize(
"use_fast", [True, pytest.param(False, marks=pytest.mark.xfail(reason="Phi-4 slow tokenizer is broken."))]
)
......@@ -166,6 +184,7 @@ def test_phi4_template(use_fast: bool):
_check_template("microsoft/phi-4", "phi4", prompt_str, answer_str, use_fast)
@pytest.mark.skipif(not HF_TOKEN, reason="Gated model.") # TODO: why it is gated?
@pytest.mark.parametrize("use_fast", [True, False])
def test_qwen_template(use_fast: bool):
prompt_str = (
......@@ -190,3 +209,27 @@ def test_yi_template(use_fast: bool):
)
answer_str = "很高兴认识你!<|im_end|>\n"
_check_template("01-ai/Yi-1.5-6B-Chat", "yi", prompt_str, answer_str, use_fast)
def test_parse_template():
tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA, token=HF_TOKEN)
template = parse_template(tokenizer)
assert template.format_user.slots == [
"<|start_header_id|>user<|end_header_id|>\n\n{{content}}<|eot_id|>"
"<|start_header_id|>assistant<|end_header_id|>\n\n"
]
assert template.format_assistant.slots == ["{{content}}<|eot_id|>"]
assert template.format_system.slots == ["<|start_header_id|>system<|end_header_id|>\n\n{{content}}<|eot_id|>"]
assert template.format_prefix.slots == ["<|begin_of_text|>"]
assert template.default_system == ""
@pytest.mark.skipif(not HF_TOKEN, reason="Gated model.")
def test_parse_qwen_template():
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-7B-Instruct", token=HF_TOKEN)
template = parse_template(tokenizer)
assert template.format_user.slots == ["<|im_start|>user\n{{content}}<|im_end|>\n<|im_start|>assistant\n"]
assert template.format_assistant.slots == ["{{content}}<|im_end|>\n"]
assert template.format_system.slots == ["<|im_start|>system\n{{content}}<|im_end|>\n"]
assert template.format_prefix.slots == []
assert template.default_system == "You are a helpful assistant."
# Copyright 2024 the LlamaFactory team.
# Copyright 2025 the LlamaFactory team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment