client.files.upload() is what you pass as training_file to a fine-tuning job.
Pick a data format
Each line of a JSONL file is one training example, formatted to match your task.| Format | When to use | Key fields |
|---|---|---|
| Conversational | Multi-turn chat or single-turn chat. | messages |
| Instruction | Prompt and completion pairs. | prompt, completion |
| Preference | Paired preferred and dispreferred outputs for DPO. | input, preferred_output, non_preferred_output |
| Generic text | Free-form text completion. | text |
text and messages), the server rejects it. Trim unused fields before upload to speed up data transfer.
Conversational data
Conversations are represented using amessages array. Each message has a role (system, user, or assistant) and content. The conversation must start with system or user and alternate user and assistant afterwards.
assistant messages. Pass train_on_inputs=True to include the rest. To mask or weight individual messages, see Data weights.
The dataset is automatically formatted into the model’s chat template if one is defined. Instruction-tuned models always have a chat template; base models usually don’t.
Example datasets:
Instruction data
Each line carries aprompt and a completion field.
completion. Pass train_on_inputs=True to include prompt. To scale a sample’s contribution to the loss, see Data weights.
Example datasets:
Generic text data
Each line carries a singletext field. Use this for plain text completions.
Preference data
Used for preference fine-tuning with DPO. Each line carries:input.messages: a context in conversational format.preferred_output: a single assistant message representing the ideal response.non_preferred_output: a single assistant message representing the suboptimal response.
Tool-calling data
For training a model to invoke tools, the line carries atools array listing the available tools. Assistant messages can include tool_calls instead of content, and tool-role messages carry call results. See function-calling fine-tuning for the end-to-end workflow.
tools field nests inside input:
Reasoning data
For fine-tuning reasoning models, assistant messages support areasoning or reasoning_content field that carries the chain of thought. See reasoning fine-tuning for the full workflow.
reasoning:
Data weights
Two independent controls adjust how much each part of your data contributes to the training loss. You can use either one on its own or both together in the same file.Per-message weights
Set aweight on an individual message to control whether it contributes to the loss. Only 0 and 1 are supported: a message with weight=0 is masked, and weight=1 includes it. This is a finer-grained version of train_on_inputs, letting you mask or include specific messages rather than whole roles.
Per-message weights are only available for conversational data, since they weight individual messages.
Sample weights
Set a root-levelweight on a line to scale that entire sample’s contribution to the loss. It’s a non-negative floating-point multiplier applied to the sample’s tokens, and it works with every JSONL format and training method, including instruction data.
Combining weights
You can set per-message weights and a sample weight in the same conversational file. The sample weight scales the loss for the whole line, and the per-message weights determine which messages within it contribute.Packing
For JSONL training data, Together uses sample packing: multiple short examples are concatenated up tomax_seq_length so each training window uses the full context length instead of being padded out. Packing is enabled by default and makes the effective batch size larger than the batch_size you set, which significantly reduces the total number of training steps and overall training time.
To control packing, either set the packing flag to false for JSONL input, or supply a pre-tokenized Parquet file. The packing flag applies only to JSONL input; it has no effect on Parquet data.
Tokenized (Parquet) data
Use Parquet when you want to skip tokenization on every job, customize attention masks or labels, or run with a tokenizer that differs from the base model’s. The file must be.parquet and under 100 GB.
Allowed fields:
| Field | Required | Description |
|---|---|---|
input_ids | Yes | Token IDs fed to the model. |
attention_mask | Yes | 1 for tokens the model should attend to, 0 for padding. |
labels | No | Target token IDs. Use -100 to mask a position from the loss. Defaults to input_ids. |
position_ids | No | Position IDs. Reset to 0 at each example boundary inside a packed sequence and increment by 1. Padding tokens also receive 0. |
You don’t need to shift
labels relative to input_ids. The trainer shifts them internally for next-token prediction.--packing is passed, the script concatenates multiple short sequences into each max_seq_length window to reduce wasted compute, matching the packing training applies by default. Otherwise, each example is padded to its own window.
Loading the resulting Parquet:
Python
Validate and upload
Run a local data validation check before uploading to avoid unnecessary charges. The client-side check verifies the file is UTF-8, each non-empty line parses as JSON, the line count exceeds the minimum, and the file is under the maximum size. Full schema validation (conversation roles, tool calls, and other dataset requirements) runs on the server during ingestion after upload, and is reported through the file’sprocessing_status.
check_file() returns a report you can inspect before uploading. A passing file looks like:
id field. Save the ID—you’ll pass it as training_file to client.fine_tuning.create(). See the quickstart for the full fine-tuning lifecycle.
If you upload a file whose contents already exist on Together AI,
client.files.upload() doesn’t create a duplicate. It returns the existing file’s metadata, including its id, so you can reuse it directly. To force a re-upload, delete the existing file first with client.files.delete(<file_id>).Wait for server-side validation
Upload returns before ingestion finishes, so poll the Files API untilprocessing_status reaches COMPLETED before you use the file. If the dataset doesn’t meet fine-tuning requirements, processing_status becomes INVALID_FORMAT and validation_report.error carries a user-facing description of the problem.
validation_report schema may evolve, so treat processing_status as the authoritative readiness signal.
Split into train and validation
To carve a validation set out of a single JSONL file:n_evals above 0:
Python
wandb_api_key is set) on your W&B dashboard.