4 Commits

Author SHA1 Message Date
Karunanidhi Mishra
76a0391ddd [misc] fix ray initialization comment typo (#10628)
Co-authored-by: Karunanidhi Mishra <11963379+kmishra1204@users.noreply.github.com>
2026-07-07 17:30:58 +08:00
Karunanidhi Mishra
445163ab5e [misc] fix typos in comments and help text (#10633)
Co-authored-by: Karunanidhi Mishra <11963379+kmishra1204@users.noreply.github.com>
2026-07-07 17:30:34 +08:00
Karunanidhi Mishra
d58ec6a0bc [deps] exclude broken transformers release (#10634)
Co-authored-by: Karunanidhi Mishra <11963379+kmishra1204@users.noreply.github.com>
2026-07-07 17:30:26 +08:00
Karunanidhi Mishra
5987a8dd68 [webui] add seed controls for reproducibility (#10629)
Co-authored-by: Karunanidhi Mishra <11963379+kmishra1204@users.noreply.github.com>
2026-07-07 17:30:09 +08:00
17 changed files with 117 additions and 16 deletions

View File

@@ -40,7 +40,7 @@ dependencies = [
"torch>=2.4.0",
"torchvision>=0.19.0",
"torchaudio>=2.4.0",
"transformers>=4.55.0,<=5.6.0,!=4.57.0",
"transformers>=4.55.0,<=5.7.0,!=4.57.0,!=5.6.0",
"datasets>=2.16.0,<=4.0.0",
"accelerate>=1.3.0,<=1.11.0",
"peft>=0.18.0,<=0.18.1",

View File

@@ -19,7 +19,7 @@ from threading import Thread
from typing import TYPE_CHECKING, Any, Optional, Union
import torch
from transformers import GenerationConfig, TextIteratorStreamer
from transformers import GenerationConfig, TextIteratorStreamer, set_seed
from typing_extensions import override
from ..data import get_template_and_fix_tokenizer
@@ -128,6 +128,7 @@ class HuggingfaceEngine(BaseEngine):
skip_special_tokens: Optional[bool] = input_kwargs.pop("skip_special_tokens", None)
max_length: Optional[int] = input_kwargs.pop("max_length", None)
max_new_tokens: Optional[int] = input_kwargs.pop("max_new_tokens", None)
seed: Optional[int] = input_kwargs.pop("seed", None)
stop: Optional[Union[str, list[str]]] = input_kwargs.pop("stop", None)
if stop is not None:
@@ -177,6 +178,8 @@ class HuggingfaceEngine(BaseEngine):
attention_mask=attention_mask,
generation_config=GenerationConfig(**generating_args),
)
if seed is not None:
gen_kwargs["_seed"] = seed
mm_inputs = template.mm_plugin.get_mm_inputs(**mm_input_dict, batch_ids=[prompt_ids], processor=processor)
for key, value in mm_inputs.items():
@@ -237,6 +240,10 @@ class HuggingfaceEngine(BaseEngine):
audios,
input_kwargs,
)
seed = gen_kwargs.pop("_seed", None)
if seed is not None:
set_seed(seed)
generate_output = model.generate(**gen_kwargs)
if isinstance(generate_output, tuple):
generate_output = generate_output[1][0] # post-process the minicpm_o output
@@ -292,6 +299,10 @@ class HuggingfaceEngine(BaseEngine):
audios,
input_kwargs,
)
seed = gen_kwargs.pop("_seed", None)
if seed is not None:
set_seed(seed)
streamer = TextIteratorStreamer(
tokenizer,
skip_prompt=True,

View File

@@ -171,6 +171,7 @@ class SGLangEngine(BaseEngine):
skip_special_tokens: Optional[bool] = input_kwargs.pop("skip_special_tokens", None)
max_length: Optional[int] = input_kwargs.pop("max_length", None)
max_new_tokens: Optional[int] = input_kwargs.pop("max_new_tokens", None)
seed: Optional[int] = input_kwargs.pop("seed", None)
stop: Optional[Union[str, list[str]]] = input_kwargs.pop("stop", None)
if num_return_sequences != 1:
@@ -205,6 +206,8 @@ class SGLangEngine(BaseEngine):
if skip_special_tokens is not None
else self.generating_args["skip_special_tokens"],
}
if seed is not None:
sampling_params["seed"] = seed
def stream_request():
json_data = {

View File

@@ -144,6 +144,7 @@ class VllmEngine(BaseEngine):
skip_special_tokens: Optional[bool] = input_kwargs.pop("skip_special_tokens", None)
max_length: Optional[int] = input_kwargs.pop("max_length", None)
max_new_tokens: Optional[int] = input_kwargs.pop("max_new_tokens", None)
seed: Optional[int] = input_kwargs.pop("seed", None)
stop: Optional[Union[str, list[str]]] = input_kwargs.pop("stop", None)
if length_penalty is not None:
@@ -163,7 +164,7 @@ class VllmEngine(BaseEngine):
if max_new_tokens:
max_tokens = max_new_tokens
sampling_params = SamplingParams(
sampling_kwargs = dict(
n=num_return_sequences,
repetition_penalty=(
repetition_penalty if repetition_penalty is not None else self.generating_args["repetition_penalty"]
@@ -179,6 +180,10 @@ class VllmEngine(BaseEngine):
if skip_special_tokens is not None
else self.generating_args["skip_special_tokens"],
)
if seed is not None:
sampling_kwargs["seed"] = seed
sampling_params = SamplingParams(**sampling_kwargs)
multi_modal_data = {}
if images is not None: # add image features

View File

@@ -929,7 +929,7 @@ class InternVLPlugin(BasePlugin):
messages = deepcopy(messages)
mm_inputs = self._get_mm_inputs(images, videos, audios, processor)
image_pixel_patch_list = mm_inputs.get("image_num_patches") # pathes of images
image_pixel_patch_list = mm_inputs.get("image_num_patches") # patches of images
video_num_patches = mm_inputs.get("video_num_patches") # all patches for frames of videos
video_patch_indices = mm_inputs.get("video_patch_indices") # num frames of per video
@@ -2667,7 +2667,7 @@ class Qwen2OmniPlugin(Qwen2VLPlugin):
if (
use_audio_in_video and len(audios) and len(videos)
): # if use the audio of video # deal video token and audio token togather
): # if use the audio of video # deal video token and audio token together
if len(videos) != len(audios):
raise ValueError(
f"Number of videos ({len(videos)}) must match number of audios ({len(audios)}) when using audio in video."

View File

@@ -1035,7 +1035,7 @@ register_template(
format_assistant=StringFormatter(slots=["{{content}}<turn|>\n"]),
format_system=StringFormatter(
slots=["<|turn>system\n<|think|>{{content}}<turn|>\n"]
), # default thought singal contained
), # default thought signal contained
format_observation=StringFormatter(
slots=["<|turn>tool\n{{content}}<turn|>\n<|turn>model\n"]
), # seem not consistent with the chattemplate
@@ -1061,7 +1061,7 @@ register_template(
format_assistant=StringFormatter(slots=["{{content}}<turn|>\n"]),
format_system=StringFormatter(
slots=["<|turn>system\n<|think|>{{content}}<turn|>\n"]
), # default thought singal contained
), # default thought signal contained
format_observation=StringFormatter(slots=["<|turn>tool\n{{content}}<turn|>\n<|turn>model\n"]),
format_tools=ToolFormatter(tool_format="gemma4"),
format_function=FunctionFormatter(slots=["<|tool>{{content}}<tool|>"], tool_format="gemma4"),

View File

@@ -94,7 +94,9 @@ def check_version(requirement: str, mandatory: bool = False) -> None:
def check_dependencies() -> None:
r"""Check the version of the required packages."""
check_version("transformers>=4.55.0,<=5.6.0")
check_version("transformers>=4.55.0,<=5.7.0")
check_version("transformers!=4.57.0")
check_version("transformers!=5.6.0")
check_version("datasets>=2.16.0,<=4.0.0")
check_version("accelerate>=1.3.0,<=1.15.0")
check_version("peft>=0.18.0,<=0.20.0")

View File

@@ -44,7 +44,7 @@ class EvaluationArguments:
)
n_shot: int = field(
default=5,
metadata={"help": "Number of examplars for few-shot learning."},
metadata={"help": "Number of exemplars for few-shot learning."},
)
save_dir: str | None = field(
default=None,

View File

@@ -385,7 +385,7 @@ class BAdamArgument:
"help": (
"The mode of the mask for BAdam optimizer. "
"`adjacent` means that the trainable parameters are adjacent to each other, "
"`scatter` means that trainable parameters are randomly choosed from the weight."
"`scatter` means that trainable parameters are randomly chosen from the weight."
)
},
)
@@ -530,7 +530,7 @@ class FinetuningArguments(
)
freeze_vision_tower: bool = field(
default=True,
metadata={"help": "Whether ot not to freeze the vision tower in MLLM training."},
metadata={"help": "Whether or not to freeze the vision tower in MLLM training."},
)
freeze_multi_modal_projector: bool = field(
default=True,

View File

@@ -134,7 +134,7 @@ def _training_function(config: dict[str, Any]) -> None:
raise ValueError(f"Unknown task: {finetuning_args.stage}.")
if is_ray_available() and ray.is_initialized():
return # if ray is intialized it will destroy the process group on return
return # if ray is initialized it will destroy the process group on return
try:
if dist.is_initialized():

View File

@@ -203,6 +203,7 @@ class WebChatModel(ChatModel):
max_new_tokens: int,
top_p: float,
temperature: float,
seed: float | int,
skip_special_tokens: bool,
escape_html: bool,
enable_thinking: bool,
@@ -225,6 +226,7 @@ class WebChatModel(ChatModel):
max_new_tokens=max_new_tokens,
top_p=top_p,
temperature=temperature,
seed=None if seed is None or int(seed) < 0 else int(seed),
skip_special_tokens=skip_special_tokens,
):
response += new_text

View File

@@ -85,6 +85,7 @@ def create_chat_box(
max_new_tokens = gr.Slider(minimum=8, maximum=8192, value=1024, step=1)
top_p = gr.Slider(minimum=0.01, maximum=1.0, value=0.7, step=0.01)
temperature = gr.Slider(minimum=0.01, maximum=1.5, value=0.95, step=0.01)
seed = gr.Number(value=-1, precision=0)
skip_special_tokens = gr.Checkbox(value=True)
escape_html = gr.Checkbox(value=True)
enable_thinking = gr.Checkbox(value=True)
@@ -110,6 +111,7 @@ def create_chat_box(
max_new_tokens,
top_p,
temperature,
seed,
skip_special_tokens,
escape_html,
enable_thinking,
@@ -135,6 +137,7 @@ def create_chat_box(
max_new_tokens=max_new_tokens,
top_p=top_p,
temperature=temperature,
seed=seed,
skip_special_tokens=skip_special_tokens,
escape_html=escape_html,
enable_thinking=enable_thinking,

View File

@@ -55,10 +55,13 @@ def create_eval_tab(engine: "Engine") -> dict[str, "Component"]:
max_new_tokens = gr.Slider(minimum=8, maximum=4096, value=512, step=1)
top_p = gr.Slider(minimum=0.01, maximum=1, value=0.7, step=0.01)
temperature = gr.Slider(minimum=0.01, maximum=1.5, value=0.95, step=0.01)
eval_seed = gr.Textbox(value="42")
output_dir = gr.Textbox()
input_elems.update({max_new_tokens, top_p, temperature, output_dir})
elem_dict.update(dict(max_new_tokens=max_new_tokens, top_p=top_p, temperature=temperature, output_dir=output_dir))
input_elems.update({max_new_tokens, top_p, temperature, eval_seed, output_dir})
elem_dict.update(
dict(max_new_tokens=max_new_tokens, top_p=top_p, temperature=temperature, eval_seed=eval_seed, output_dir=output_dir)
)
with gr.Row():
cmd_preview_btn = gr.Button()

View File

@@ -52,15 +52,17 @@ def create_train_tab(engine: "Engine") -> dict[str, "Component"]:
learning_rate = gr.Textbox(value="5e-5")
num_train_epochs = gr.Textbox(value="3.0")
max_grad_norm = gr.Textbox(value="1.0")
train_seed = gr.Textbox(value="42")
max_samples = gr.Textbox(value="100000")
compute_type = gr.Dropdown(choices=["bf16", "fp16", "fp32", "pure_bf16"], value="bf16")
input_elems.update({learning_rate, num_train_epochs, max_grad_norm, max_samples, compute_type})
input_elems.update({learning_rate, num_train_epochs, max_grad_norm, train_seed, max_samples, compute_type})
elem_dict.update(
dict(
learning_rate=learning_rate,
num_train_epochs=num_train_epochs,
max_grad_norm=max_grad_norm,
train_seed=train_seed,
max_samples=max_samples,
compute_type=compute_type,
)

View File

@@ -105,7 +105,7 @@ def check_template(lang: str, template: str) -> None:
def get_trainer_info(lang: str, output_path: os.PathLike, do_train: bool) -> tuple[str, "gr.Slider", dict[str, Any]]:
r"""Get training infomation for monitor.
r"""Get training information for monitor.
If do_train is True:
Inputs: top.lang, train.output_path

View File

@@ -539,6 +539,28 @@ LOCALES = {
"info": "勾配クリッピングのためのノルム。",
},
},
"train_seed": {
"en": {
"label": "Seed",
"info": "Random seed for training.",
},
"ru": {
"label": "Seed",
"info": "Random seed for training.",
},
"zh": {
"label": "随机种子",
"info": "训练使用的随机种子。",
},
"ko": {
"label": "Seed",
"info": "Random seed for training.",
},
"ja": {
"label": "Seed",
"info": "Random seed for training.",
},
},
"max_samples": {
"en": {
"label": "Max samples",
@@ -2708,6 +2730,45 @@ LOCALES = {
"label": "温度",
},
},
"seed": {
"en": {
"label": "Generation seed (-1 for random)",
},
"ru": {
"label": "Generation seed (-1 = random)",
},
"zh": {
"label": "生成随机种子(-1 表示随机)",
},
"ko": {
"label": "Generation seed (-1 = random)",
},
"ja": {
"label": "Generation seed (-1 = random)",
},
},
"eval_seed": {
"en": {
"label": "Seed",
"info": "Random seed for evaluation and prediction.",
},
"ru": {
"label": "Seed",
"info": "Random seed for evaluation and prediction.",
},
"zh": {
"label": "随机种子",
"info": "评估和预测使用的随机种子。",
},
"ko": {
"label": "Seed",
"info": "Random seed for evaluation and prediction.",
},
"ja": {
"label": "Seed",
"info": "Random seed for evaluation and prediction.",
},
},
"skip_special_tokens": {
"en": {
"label": "Skip special tokens",

View File

@@ -51,6 +51,13 @@ if TYPE_CHECKING:
from .manager import Manager
def _parse_seed(value: Any, default: int = 42) -> int:
try:
return int(value)
except (TypeError, ValueError):
return default
class Runner:
r"""A class to manage the running status of the trainers."""
@@ -147,6 +154,7 @@ class Runner:
learning_rate=float(get("train.learning_rate")),
num_train_epochs=float(get("train.num_train_epochs")),
max_samples=int(get("train.max_samples")),
seed=_parse_seed(get("train.train_seed")),
per_device_train_batch_size=get("train.batch_size"),
gradient_accumulation_steps=get("train.gradient_accumulation_steps"),
lr_scheduler_type=get("train.lr_scheduler_type"),
@@ -316,6 +324,7 @@ class Runner:
max_new_tokens=get("eval.max_new_tokens"),
top_p=get("eval.top_p"),
temperature=get("eval.temperature"),
seed=_parse_seed(get("eval.eval_seed")),
output_dir=get_save_dir(model_name, finetuning_type, get("eval.output_dir")),
trust_remote_code=True,
ddp_timeout=180000000,