Skip to main content
Export your Prem API key as API_KEY before running any script.
1

Set JSONL file path

const API_KEY = process.env.API_KEY;

// Define your JSONL dataset file
const JSONL_FILE_PATH = 'sample_data.jsonl';
2

Create project

Create a new project workspace. See Create Project for details.
const res = await fetch('https://studio.premai.io/api/v1/public/projects/create', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ name: 'Test Project', goal: 'Test finetuning' })
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
const { project_id } = await res.json();
3

Upload JSONL file

Upload a JSONL file to create a dataset. See Create Dataset from JSONL for details.
const formData = new FormData();
formData.append('project_id', project_id);
formData.append('name', 'Test Dataset');
const jsonlFile = file(JSONL_FILE_PATH);
formData.append('file', jsonlFile, JSONL_FILE_PATH);

const res = await fetch('https://studio.premai.io/api/v1/public/datasets/create-from-jsonl', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${API_KEY}` },
  body: formData
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
const { dataset_id } = await res.json();
4

Wait for processing

Poll the dataset status until uploading completes. See Get Dataset for details.
let dataset;
do {
  await sleep(2000);
  const res = await fetch(`https://studio.premai.io/api/v1/public/datasets/${dataset_id}`, {
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  dataset = await res.json();
} while (dataset.status === 'processing');
5

Create snapshot

Create a snapshot with train/validation split. See Create Snapshot for details.
const res = await fetch('https://studio.premai.io/api/v1/public/snapshots/create', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ dataset_id, split_percentage: 80 })
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
const { snapshot_id } = await res.json();
6

Get recommendations

Generate and retrieve model recommendations for your snapshot. See Generate Recommendations and Get Recommendations for details.
const res = await fetch('https://studio.premai.io/api/v1/public/recommendations/generate', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ snapshot_id })
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);

let recs;
do {
  await sleep(5000);
  const res2 = await fetch(`https://studio.premai.io/api/v1/public/recommendations/${snapshot_id}`, {
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  });
  if (!res2.ok) throw new Error(`${res2.status}: ${await res2.text()}`);
  recs = await res2.json();
} while (recs.status === 'processing');
7

Start fine-tuning

Launch a fine-tuning job with recommended experiments. See Create Fine-Tuning Job for details.
const experiments = recs.recommended_experiments
  .filter((e: any) => e.recommended)
  .map(({ recommended, reason_for_recommendation, ...experiment }: any) => experiment);

const res = await fetch('https://studio.premai.io/api/v1/public/finetuning/create', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ snapshot_id, name: 'Test Job', experiments })
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
const { job_id } = await res.json();
8

Monitor job

for (let i = 0; i < 30; i++) {
  await sleep(10000);
  const res = await fetch(`https://studio.premai.io/api/v1/public/finetuning/${job_id}`, {
    headers: { 'Authorization': `Bearer ${API_KEY}` }
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  const job = await res.json();
  console.log(`Status: ${job.status}`);
  job.experiments.forEach((e: any) => {
    console.log(`  - Exp #${e.experiment_number}: ${e.status} ${e.model_id || ''}`);
  });
  if (job.status !== 'processing') break;
}
Monitor fine-tuning job progress and status. See Get Fine-Tuning Job for details.

Full Example

#!/usr/bin/env bun

/**
 * Example 1: JSONL dataset workflow
 * 1. Create project → 2. Upload JSONL → 3. Create snapshot → 4. Get recommendations → 5. Run finetuning
 */

import { file } from 'bun';

const API_KEY = process.env.API_KEY;
const JSONL_FILE_PATH = 'sample_data.jsonl';

if (!API_KEY) {
	console.error('Error: API_KEY environment variable is required');
	console.error('Please create a .env file based on .env.example');
	process.exit(1);
}

function sleep(ms: number) {
	return new Promise((r) => setTimeout(r, ms));
}

async function main() {
	console.log('\n=== JSONL Workflow ===\n');

	// 1. Create project
	console.log('1. Creating project...');
	const res1 = await fetch('https://studio.premai.io/api/v1/public/projects/create', {
		method: 'POST',
		headers: {
			'Authorization': `Bearer ${API_KEY}`,
			'Content-Type': 'application/json'
		},
		body: JSON.stringify({ name: 'Test Project', goal: 'Test finetuning' }),
	});
	if (!res1.ok) throw new Error(`${res1.status}: ${await res1.text()}`);
	const { project_id } = await res1.json();
	console.log(`   ✓ Project: ${project_id}\n`);

	// 2. Upload JSONL
	console.log('2. Uploading JSONL dataset...');
	const formData = new FormData();
	formData.append('project_id', project_id);
	formData.append('name', 'Test Dataset');
	const jsonlFile = file(JSONL_FILE_PATH);
	formData.append('file', jsonlFile, JSONL_FILE_PATH);

	const res2 = await fetch('https://studio.premai.io/api/v1/public/datasets/create-from-jsonl', {
		method: 'POST',
		headers: { 'Authorization': `Bearer ${API_KEY}` },
		body: formData,
	});
	if (!res2.ok) throw new Error(`${res2.status}: ${await res2.text()}`);
	const { dataset_id } = await res2.json();
	console.log(`   ✓ Dataset: ${dataset_id}`);

	// Wait for dataset
	console.log('   Waiting for dataset...');
	let dataset;
	do {
		await sleep(2000);
		const res = await fetch(`https://studio.premai.io/api/v1/public/datasets/${dataset_id}`, {
			headers: { 'Authorization': `Bearer ${API_KEY}` }
		});
		if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
		dataset = await res.json();
	} while (dataset.status === 'processing');
	console.log(`   ✓ Ready: ${dataset.datapoints_count} datapoints\n`);

	// 3. Create snapshot
	console.log('3. Creating snapshot...');
	const res3 = await fetch('https://studio.premai.io/api/v1/public/snapshots/create', {
		method: 'POST',
		headers: {
			'Authorization': `Bearer ${API_KEY}`,
			'Content-Type': 'application/json'
		},
		body: JSON.stringify({ dataset_id, split_percentage: 80 }),
	});
	if (!res3.ok) throw new Error(`${res3.status}: ${await res3.text()}`);
	const { snapshot_id } = await res3.json();
	console.log(`   ✓ Snapshot: ${snapshot_id}\n`);

	// 4. Generate recommendations
	console.log('4. Generating recommendations...');
	const res4 = await fetch('https://studio.premai.io/api/v1/public/recommendations/generate', {
		method: 'POST',
		headers: {
			'Authorization': `Bearer ${API_KEY}`,
			'Content-Type': 'application/json'
		},
		body: JSON.stringify({ snapshot_id }),
	});
	if (!res4.ok) throw new Error(`${res4.status}: ${await res4.text()}`);

	let recs;
	do {
		await sleep(5000);
		const res = await fetch(`https://studio.premai.io/api/v1/public/recommendations/${snapshot_id}`, {
			headers: { 'Authorization': `Bearer ${API_KEY}` }
		});
		if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
		recs = await res.json();
	} while (recs.status === 'processing');

	console.log(`   ✓ Recommended experiments:`);
	const recommendedCount = recs.recommended_experiments.filter((e: any) => e.recommended).length;
	console.log(`   Total experiments: ${recs.recommended_experiments.length}, Recommended: ${recommendedCount}`);
	recs.recommended_experiments.forEach((e: any) => {
		if (e.recommended) console.log(`     - ${e.base_model_id} (LoRA: ${e.lora})`);
	});
	console.log();

	// 5. Create finetuning job
	console.log('5. Creating finetuning job...');
	const experiments = recs.recommended_experiments
		.filter((e: any) => e.recommended)
		.map(({ recommended, reason_for_recommendation, ...experiment }: any) => experiment);

	if (experiments.length === 0) {
		console.error('\n✗ Error: No recommended experiments found. Cannot create finetuning job.');
		process.exit(1);
	}

	const res5 = await fetch('https://studio.premai.io/api/v1/public/finetuning/create', {
		method: 'POST',
		headers: {
			'Authorization': `Bearer ${API_KEY}`,
			'Content-Type': 'application/json'
		},
		body: JSON.stringify({ snapshot_id, name: 'Test Job', experiments }),
	});
	if (!res5.ok) throw new Error(`${res5.status}: ${await res5.text()}`);
	const { job_id } = await res5.json();
	console.log(`   ✓ Job: ${job_id}\n`);

	// 6. Monitor (5 minutes max)
	console.log('6. Monitoring job...');
	for (let i = 0; i < 30; i++) {
		await sleep(10000);
		const res = await fetch(`https://studio.premai.io/api/v1/public/finetuning/${job_id}`, {
			headers: { 'Authorization': `Bearer ${API_KEY}` }
		});
		if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
		const job = await res.json();
		console.log(`   Status: ${job.status}`);
		job.experiments.forEach((e: any) => {
			console.log(`     - Exp #${e.experiment_number}: ${e.status} ${e.model_id || ''}`);
		});
		if (job.status !== 'processing') break;
	}

	console.log('\n✓ Done!\n');
}

main().catch((err) => {
	console.error('\n✗ Error:', err.message);
	process.exit(1);
});