Text Generation
Transformers
Safetensors
qwen3
llama-factory
full
Generated from Trainer
conversational
text-generation-inference
Instructions to use ayh015/myLightningOPD with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use ayh015/myLightningOPD with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="ayh015/myLightningOPD") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("ayh015/myLightningOPD") model = AutoModelForCausalLM.from_pretrained("ayh015/myLightningOPD", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use ayh015/myLightningOPD with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "ayh015/myLightningOPD" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ayh015/myLightningOPD", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/ayh015/myLightningOPD
- SGLang
How to use ayh015/myLightningOPD with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "ayh015/myLightningOPD" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ayh015/myLightningOPD", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "ayh015/myLightningOPD" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ayh015/myLightningOPD", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use ayh015/myLightningOPD with Docker Model Runner:
docker model run hf.co/ayh015/myLightningOPD
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # SPDX-License-Identifier: Apache-2.0 | |
| import json | |
| import logging | |
| import os | |
| import random | |
| import re | |
| import numpy as np | |
| import pandas as pd | |
| import ray | |
| from slime.utils.types import MultimodalTypes, Sample | |
| from .timer import Timer | |
| __all__ = ["Dataset", "create_dataset"] | |
| logger = logging.getLogger(__name__) | |
| def _read_single_file(path, row_slice=None): | |
| """Read a single data file (jsonl or parquet).""" | |
| if path.endswith(".jsonl"): | |
| df = pd.read_json(path, lines=True, dtype={"label": str}) | |
| elif path.endswith(".parquet"): | |
| df = pd.read_parquet(path, dtype_backend="pyarrow") | |
| else: | |
| raise ValueError(f"Unsupported file format: {path}. Supported formats are .jsonl and .parquet.") | |
| if row_slice is not None: | |
| logger.info(f"read_file path={path} slice {len(df)=} rows into {row_slice=}") | |
| df = df.iloc[row_slice] | |
| for _, row in df.iterrows(): | |
| yield row.to_dict() | |
| def _list_data_files(directory): | |
| """List all supported data files in a directory (recursively).""" | |
| supported_extensions = ('.jsonl', '.parquet') | |
| data_files = [] | |
| for root, _, files in os.walk(directory): | |
| for file in sorted(files): # Sort for deterministic order | |
| if file.endswith(supported_extensions): | |
| data_files.append(os.path.join(root, file)) | |
| return sorted(data_files) # Sort by full path for deterministic order | |
| def read_file(path): | |
| """Read data from a file or directory. | |
| Args: | |
| path: Path to a data file (.jsonl or .parquet) or a directory containing data files. | |
| If a directory is provided, all .jsonl and .parquet files in it (and subdirectories) | |
| will be read and concatenated. | |
| Supports row slicing with @[start:end] suffix, e.g., "data.jsonl@[0:1000]" | |
| Yields: | |
| dict: Each row of data as a dictionary. | |
| """ | |
| path, row_slice = _parse_generalized_path(path) | |
| if not os.path.exists(path): | |
| raise FileNotFoundError(f"Prompt dataset path '{path}' does not exist.") | |
| # Handle directory: read all data files inside | |
| if os.path.isdir(path): | |
| data_files = _list_data_files(path) | |
| if not data_files: | |
| raise ValueError(f"No .jsonl or .parquet files found in directory: {path}") | |
| logger.info(f"Found {len(data_files)} data files in directory {path}") | |
| # For directory, row_slice applies to the combined dataset | |
| if row_slice is not None: | |
| # Collect all data first, then apply slice | |
| all_rows = [] | |
| for file_path in data_files: | |
| for row in _read_single_file(file_path): | |
| all_rows.append(row) | |
| logger.info(f"read_file directory={path} slice {len(all_rows)=} rows into {row_slice=}") | |
| for row in all_rows[row_slice]: | |
| yield row | |
| else: | |
| # Stream data from each file | |
| for file_path in data_files: | |
| for row in _read_single_file(file_path): | |
| yield row | |
| else: | |
| # Handle single file | |
| for row in _read_single_file(path, row_slice): | |
| yield row | |
| def _parse_generalized_path(s: str): | |
| if (m := re.match(r"^(?P<real_path>.*)@\[(?P<start>-?\d*):(?P<end>-?\d*)\]$", s)) is not None: | |
| path = m.group("real_path") | |
| start = int(x) if (x := m.group("start")) != "" else None | |
| end = int(x) if (x := m.group("end")) != "" else None | |
| return path, slice(start, end) | |
| return s, None | |
| def _should_skip_prompt(formatted_prompt: str, tokenizer, processor, max_length, multimodal_inputs=None): | |
| if max_length is None: | |
| return False | |
| if processor: | |
| processor_output = processor(text=formatted_prompt, **multimodal_inputs) | |
| input_ids = processor_output["input_ids"][0] | |
| else: | |
| input_ids = tokenizer.encode(formatted_prompt, add_special_tokens=False) | |
| return len(input_ids) > max_length | |
| def _build_messages(data: dict, prompt_key: str, as_conversation: bool, multimodal_keys: dict = None): | |
| prompt = data.get(prompt_key) | |
| if isinstance(prompt, str): | |
| if not as_conversation: | |
| return prompt | |
| else: | |
| prompt = [{"role": "user", "content": prompt}] | |
| if multimodal_keys: | |
| assert as_conversation, "as_conversation must be True when multimodal_keys is not None" | |
| # Build mapping: placeholder -> (MultimodalType, content_list) | |
| multimodals = {} | |
| for type_name, data_key in multimodal_keys.items(): | |
| mt = MultimodalTypes.get(type_name) | |
| if mt: | |
| multimodals[mt.placeholder] = (mt, list(data.get(data_key))) | |
| pattern = "(" + "|".join(re.escape(p) for p in multimodals.keys()) + ")" | |
| for message in prompt: | |
| if isinstance(message["content"], str): | |
| content_list = [] | |
| for segment in re.split(pattern, message["content"]): | |
| if not segment: | |
| continue | |
| if segment in multimodals: | |
| mt, content = multimodals[segment] | |
| content_list.append({"type": mt.name, mt.name: content.pop(0)}) | |
| else: | |
| content_list.append({"type": "text", "text": segment}) | |
| message["content"] = content_list | |
| elif isinstance(message["content"], list): | |
| # TODO: handle more general cases. where message['content'] is a dict and contains multiple types of content. | |
| # e.g. | |
| # "content": [ | |
| # { | |
| # "type": "image", | |
| # "image": "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg", | |
| # }, | |
| # {"type": "text", "text": "Describe this image."}, | |
| # ], | |
| logger.warning("message['content'] is a list of dicts, no processing will be done.") | |
| continue | |
| else: | |
| raise ValueError( | |
| f"Unsupported content type: {type(message['content'])}, expected str or list of dicts" | |
| ) | |
| return prompt | |
| class Dataset: | |
| def __init__( | |
| self, | |
| path, | |
| tokenizer, | |
| processor, | |
| max_length, | |
| *, | |
| prompt_key="text", | |
| multimodal_keys=None, | |
| label_key=None, | |
| tool_key=None, | |
| metadata_key="metadata", | |
| seed=42, | |
| apply_chat_template=False, | |
| apply_chat_template_kwargs=None, | |
| ): | |
| self.origin_samples = [] | |
| for data in read_file(path): | |
| metadata = data.get(metadata_key) or {} | |
| prompt = _build_messages(data, prompt_key, apply_chat_template, multimodal_keys) | |
| tools = None | |
| if tool_key is not None and tool_key in data: | |
| tools = data[tool_key] | |
| if isinstance(tools, str): | |
| tools = json.loads(tools) | |
| elif isinstance(tools, np.ndarray): | |
| tools = tools.tolist() | |
| assert isinstance(tools, list), f"tools must be a list, got {type(tools)} instead" | |
| metadata["tools"] = tools | |
| if apply_chat_template: | |
| formatted_prompt = tokenizer.apply_chat_template( | |
| prompt, | |
| tools=tools, | |
| tokenize=False, | |
| add_generation_prompt=True, | |
| **(apply_chat_template_kwargs or {}), | |
| ) | |
| else: | |
| formatted_prompt = prompt | |
| if processor: | |
| # temporary solution, will write image utils for slime later | |
| from qwen_vl_utils import process_vision_info | |
| assert isinstance( | |
| prompt, list | |
| ), f"prompt must be a list when processor is not None, got {type(prompt)} instead" | |
| images, videos = process_vision_info(prompt) | |
| multimodal_inputs = {"images": images, "videos": videos} | |
| else: | |
| multimodal_inputs = None | |
| # TODO: this is slow. | |
| if _should_skip_prompt(formatted_prompt, tokenizer, processor, max_length, multimodal_inputs): | |
| continue | |
| self.origin_samples.append( | |
| Sample( | |
| prompt=formatted_prompt, | |
| label=data.get(label_key, None) if label_key is not None else None, | |
| metadata=metadata, | |
| multimodal_inputs=multimodal_inputs, | |
| ) | |
| ) | |
| logger.info(f"Dataset: Loaded {len(self.origin_samples)} samples from {path}") | |
| self.epoch_id = -1 | |
| self.seed = seed | |
| self.samples = self.origin_samples | |
| def shuffle(self, new_epoch_id): | |
| if self.epoch_id == new_epoch_id: | |
| return | |
| random.seed(self.seed + new_epoch_id) | |
| permutation = list(range(len(self.samples))) | |
| random.shuffle(permutation) | |
| self.samples = [self.origin_samples[i] for i in permutation] | |
| self.epoch_id = new_epoch_id | |
| def __getitem__(self, idx): | |
| return self.samples[idx] | |
| def __len__(self): | |
| return len(self.samples) | |
| def get_minimum_num_micro_batch_size(total_lengths, max_tokens_per_gpu): | |
| # use first fit to get the number of micro batches | |
| batches = [] | |
| for length in total_lengths: | |
| for i in range(len(batches)): | |
| if batches[i] + length <= max_tokens_per_gpu: | |
| batches[i] += length | |
| break | |
| else: | |
| batches.append(length) | |
| return len(batches) | |
| def process_rollout_data(args, rollout_data_ref, dp_rank, dp_size): | |
| assert len(rollout_data_ref) == dp_size | |
| rollout_data = ray.get(rollout_data_ref[dp_rank].inner) | |
| partition = rollout_data.pop("partition") | |
| total_lengths = rollout_data["total_lengths"] | |
| # save the seqlen of the whole rollout batch | |
| Timer().seq_lens = total_lengths | |
| rollout_data["total_lengths"] = [total_lengths[i] for i in partition] | |
| return rollout_data | |
| def create_dataset( | |
| paths, | |
| tokenizer, | |
| processor, | |
| max_length, | |
| *, | |
| prompt_key="text", | |
| multimodal_keys=None, | |
| label_key=None, | |
| tool_key=None, | |
| metadata_key="metadata", | |
| seed=42, | |
| apply_chat_template=False, | |
| apply_chat_template_kwargs=None, | |
| ): | |
| """Factory function to create a Dataset. | |
| Args: | |
| paths: A single path string, or a list with one path from --prompt-data. | |
| Other args are the same as Dataset. | |
| Returns: | |
| Dataset instance. | |
| """ | |
| if isinstance(paths, list): | |
| if len(paths) != 1: | |
| raise ValueError(f"Only single-path datasets are supported, got {len(paths)} paths.") | |
| paths = paths[0] | |
| return Dataset( | |
| path=paths, | |
| tokenizer=tokenizer, | |
| processor=processor, | |
| max_length=max_length, | |
| prompt_key=prompt_key, | |
| multimodal_keys=multimodal_keys, | |
| label_key=label_key, | |
| tool_key=tool_key, | |
| metadata_key=metadata_key, | |
| seed=seed, | |
| apply_chat_template=apply_chat_template, | |
| apply_chat_template_kwargs=apply_chat_template_kwargs, | |
| ) | |