Implementation:Hiyouga LLaMA Factory V1 Rendering
| Knowledge Sources | |
|---|---|
| Domains | Machine Learning, Natural Language Processing, Tokenization |
| Last Updated | 2026-02-06 19:00 GMT |
Overview
Renderer is the template-based message rendering system that converts conversation messages into tokenized model inputs with labels and loss weights for both training and inference.
Description
The rendering module provides the Renderer class along with standalone helper functions render_chatml_messages and parse_chatml_message. The Renderer class applies chat templates to convert lists of Message objects into ModelInput dictionaries containing input_ids, attention_mask, labels, and loss_weights. It has built-in support for the ChatML template format and delegates to RenderingPlugin for other templates (e.g., Qwen3). The process_samples method handles both SFT samples (single message list) and DPO samples (chosen/rejected message pairs, concatenated with token_type_ids to distinguish them). Labels use IGNORE_INDEX for non-trainable tokens, and loss_weights control per-token loss scaling.
Usage
Renderer is instantiated by ModelEngine with the configured template name and processor. It is then passed to trainers and samplers. Use render_messages for converting conversation messages to model inputs, parse_message for parsing generated text back to a message, and process_samples as a batch collation function for the data loader.
Code Reference
Source Location
- Repository: Hiyouga_LLaMA_Factory
- File: src/llamafactory/v1/core/utils/rendering.py
- Lines: 1-169
Signature
def render_chatml_messages(
processor: Processor,
messages: list[Message],
tools: str | None = None,
is_generate: bool = False,
) -> ModelInput: ...
def parse_chatml_message(generated_text: str) -> Message: ...
class Renderer:
def __init__(self, template: str, processor: Processor): ...
def render_messages(
self,
messages: list[Message],
tools: str | None = None,
is_generate: bool = False,
) -> ModelInput: ...
def parse_message(self, generated_text: str) -> Message: ...
def process_samples(self, samples: list[Sample]) -> list[ModelInput]: ...
Import
from llamafactory.v1.core.utils.rendering import Renderer, render_chatml_messages, parse_chatml_message
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| template | str | Yes (init) | The chat template name (e.g., "chatml"). Non-default templates delegate to RenderingPlugin. |
| processor | Processor | Yes (init) | The HuggingFace processor/tokenizer for encoding text to token IDs. |
| messages | list[Message] | Yes (render_messages) | List of Message dicts with role, content (list of type/value dicts), and optional loss_weight. |
| tools | str or None | No | Optional JSON string of tools for tool-augmented generation. |
| is_generate | bool | No | If True, appends an assistant prompt prefix for generation (default: False). |
| samples | list[Sample] | Yes (process_samples) | List of samples containing either "messages" (SFT) or "chosen_messages"/"rejected_messages" (DPO). |
| generated_text | str | Yes (parse_message) | Raw generated text string to parse into a Message. |
Outputs
| Name | Type | Description |
|---|---|---|
| render_messages return | ModelInput | Dictionary with input_ids, attention_mask, labels, and loss_weights lists. Labels use IGNORE_INDEX (-100) for non-trainable tokens. |
| parse_message return | Message | A Message dict with role="assistant" and the parsed content. |
| process_samples return | list[ModelInput] | List of ModelInput dicts. DPO samples include token_type_ids (1 for chosen, 2 for rejected). |
Usage Examples
from llamafactory.v1.core.utils.rendering import Renderer
# Create renderer with ChatML template
renderer = Renderer(template="chatml", processor=processor)
# Render messages for training
messages = [
{"role": "user", "content": [{"type": "text", "value": "What is AI?"}], "loss_weight": 0.0},
{"role": "assistant", "content": [{"type": "text", "value": "AI is..."}], "loss_weight": 1.0},
]
model_input = renderer.render_messages(messages)
# Render for generation (adds assistant prompt)
model_input = renderer.render_messages(messages[:1], is_generate=True)
# Process a batch of SFT samples
model_inputs = renderer.process_samples([{"messages": messages}])
# Parse generated text back to message
message = renderer.parse_message("AI stands for Artificial Intelligence.")
Related Pages
- Hiyouga_LLaMA_Factory_V1_Model_Engine - Creates the Renderer during model initialization.
- Hiyouga_LLaMA_Factory_V1_Batching - Uses Renderer.process_samples as the collate function.
- Hiyouga_LLaMA_Factory_V1_Inference_Engine - Uses Renderer.render_messages for generation input preparation.
- Hiyouga_LLaMA_Factory_V1_Base_Trainer - Passes the Renderer to the BatchGenerator.