curl https://compute.prentis.ai/v1/accounts/my-account/supervisedFineTuningJobs:estimateCost \
-H "Authorization: Bearer $PRENTIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"baseModel": "accounts/maas/models/your-base-model",
"inputDatasetVersion": "accounts/my-account/datasets/support-chats",
"config": { "outputModelId": "support-lora-v1", "epochs": 2 }
}'import requests
url = "https://compute.prentis.ai/v1/accounts/{account}/supervisedFineTuningJobs:estimateCost"
payload = {
"baseModel": "<string>",
"inputDatasetVersion": "<string>",
"config": {
"outputModelId": "<string>",
"loraRank": 123,
"learningRate": "<string>",
"epochs": 123,
"batchSize": 123,
"maxContextLength": 123,
"earlyStop": True,
"evalAutoCarveoutBasisPoints": 4999,
"lrSchedule": "<string>",
"warmupSteps": 123,
"dpoBeta": "<string>"
},
"evaluationDatasetVersion": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
baseModel: '<string>',
inputDatasetVersion: '<string>',
config: {
outputModelId: '<string>',
loraRank: 123,
learningRate: '<string>',
epochs: 123,
batchSize: 123,
maxContextLength: 123,
earlyStop: true,
evalAutoCarveoutBasisPoints: 4999,
lrSchedule: '<string>',
warmupSteps: 123,
dpoBeta: '<string>'
},
evaluationDatasetVersion: '<string>'
})
};
fetch('https://compute.prentis.ai/v1/accounts/{account}/supervisedFineTuningJobs:estimateCost', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://compute.prentis.ai/v1/accounts/{account}/supervisedFineTuningJobs:estimateCost",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'baseModel' => '<string>',
'inputDatasetVersion' => '<string>',
'config' => [
'outputModelId' => '<string>',
'loraRank' => 123,
'learningRate' => '<string>',
'epochs' => 123,
'batchSize' => 123,
'maxContextLength' => 123,
'earlyStop' => true,
'evalAutoCarveoutBasisPoints' => 4999,
'lrSchedule' => '<string>',
'warmupSteps' => 123,
'dpoBeta' => '<string>'
],
'evaluationDatasetVersion' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://compute.prentis.ai/v1/accounts/{account}/supervisedFineTuningJobs:estimateCost"
payload := strings.NewReader("{\n \"baseModel\": \"<string>\",\n \"inputDatasetVersion\": \"<string>\",\n \"config\": {\n \"outputModelId\": \"<string>\",\n \"loraRank\": 123,\n \"learningRate\": \"<string>\",\n \"epochs\": 123,\n \"batchSize\": 123,\n \"maxContextLength\": 123,\n \"earlyStop\": true,\n \"evalAutoCarveoutBasisPoints\": 4999,\n \"lrSchedule\": \"<string>\",\n \"warmupSteps\": 123,\n \"dpoBeta\": \"<string>\"\n },\n \"evaluationDatasetVersion\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://compute.prentis.ai/v1/accounts/{account}/supervisedFineTuningJobs:estimateCost")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"baseModel\": \"<string>\",\n \"inputDatasetVersion\": \"<string>\",\n \"config\": {\n \"outputModelId\": \"<string>\",\n \"loraRank\": 123,\n \"learningRate\": \"<string>\",\n \"epochs\": 123,\n \"batchSize\": 123,\n \"maxContextLength\": 123,\n \"earlyStop\": true,\n \"evalAutoCarveoutBasisPoints\": 4999,\n \"lrSchedule\": \"<string>\",\n \"warmupSteps\": 123,\n \"dpoBeta\": \"<string>\"\n },\n \"evaluationDatasetVersion\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://compute.prentis.ai/v1/accounts/{account}/supervisedFineTuningJobs:estimateCost")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"baseModel\": \"<string>\",\n \"inputDatasetVersion\": \"<string>\",\n \"config\": {\n \"outputModelId\": \"<string>\",\n \"loraRank\": 123,\n \"learningRate\": \"<string>\",\n \"epochs\": 123,\n \"batchSize\": 123,\n \"maxContextLength\": 123,\n \"earlyStop\": true,\n \"evalAutoCarveoutBasisPoints\": 4999,\n \"lrSchedule\": \"<string>\",\n \"warmupSteps\": 123,\n \"dpoBeta\": \"<string>\"\n },\n \"evaluationDatasetVersion\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"estimate": {
"exampleCount": "4000",
"avgTokensPerExample": "535",
"epochs": 2,
"tokensProcessed": "4280000",
"ratePerMillion": {
"amount": "0.45",
"currency": "USD"
},
"estimatedCost": {
"amount": "1.93",
"currency": "USD"
}
},
"egress": {
"allowed": true,
"execution": {
"thirdParty": false
},
"providerApproved": true,
"requiredAgreementVersion": "v2",
"acceptedAgreementVersion": "v2"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_REQUEST",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_REQUEST",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_REQUEST",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_REQUEST",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_REQUEST",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_REQUEST",
"param": "<string>"
}
}Estimate a supervised fine-tuning job
What the same request to create would cost, and whether it would be allowed to run — without creating anything. The estimate shows its working (examples, tokens per example, epochs, rate) so you can tell whether the number is for the job you meant. An estimate is not the bill: you are billed for the tokens actually trained on.
curl https://compute.prentis.ai/v1/accounts/my-account/supervisedFineTuningJobs:estimateCost \
-H "Authorization: Bearer $PRENTIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"baseModel": "accounts/maas/models/your-base-model",
"inputDatasetVersion": "accounts/my-account/datasets/support-chats",
"config": { "outputModelId": "support-lora-v1", "epochs": 2 }
}'import requests
url = "https://compute.prentis.ai/v1/accounts/{account}/supervisedFineTuningJobs:estimateCost"
payload = {
"baseModel": "<string>",
"inputDatasetVersion": "<string>",
"config": {
"outputModelId": "<string>",
"loraRank": 123,
"learningRate": "<string>",
"epochs": 123,
"batchSize": 123,
"maxContextLength": 123,
"earlyStop": True,
"evalAutoCarveoutBasisPoints": 4999,
"lrSchedule": "<string>",
"warmupSteps": 123,
"dpoBeta": "<string>"
},
"evaluationDatasetVersion": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
baseModel: '<string>',
inputDatasetVersion: '<string>',
config: {
outputModelId: '<string>',
loraRank: 123,
learningRate: '<string>',
epochs: 123,
batchSize: 123,
maxContextLength: 123,
earlyStop: true,
evalAutoCarveoutBasisPoints: 4999,
lrSchedule: '<string>',
warmupSteps: 123,
dpoBeta: '<string>'
},
evaluationDatasetVersion: '<string>'
})
};
fetch('https://compute.prentis.ai/v1/accounts/{account}/supervisedFineTuningJobs:estimateCost', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://compute.prentis.ai/v1/accounts/{account}/supervisedFineTuningJobs:estimateCost",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'baseModel' => '<string>',
'inputDatasetVersion' => '<string>',
'config' => [
'outputModelId' => '<string>',
'loraRank' => 123,
'learningRate' => '<string>',
'epochs' => 123,
'batchSize' => 123,
'maxContextLength' => 123,
'earlyStop' => true,
'evalAutoCarveoutBasisPoints' => 4999,
'lrSchedule' => '<string>',
'warmupSteps' => 123,
'dpoBeta' => '<string>'
],
'evaluationDatasetVersion' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://compute.prentis.ai/v1/accounts/{account}/supervisedFineTuningJobs:estimateCost"
payload := strings.NewReader("{\n \"baseModel\": \"<string>\",\n \"inputDatasetVersion\": \"<string>\",\n \"config\": {\n \"outputModelId\": \"<string>\",\n \"loraRank\": 123,\n \"learningRate\": \"<string>\",\n \"epochs\": 123,\n \"batchSize\": 123,\n \"maxContextLength\": 123,\n \"earlyStop\": true,\n \"evalAutoCarveoutBasisPoints\": 4999,\n \"lrSchedule\": \"<string>\",\n \"warmupSteps\": 123,\n \"dpoBeta\": \"<string>\"\n },\n \"evaluationDatasetVersion\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://compute.prentis.ai/v1/accounts/{account}/supervisedFineTuningJobs:estimateCost")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"baseModel\": \"<string>\",\n \"inputDatasetVersion\": \"<string>\",\n \"config\": {\n \"outputModelId\": \"<string>\",\n \"loraRank\": 123,\n \"learningRate\": \"<string>\",\n \"epochs\": 123,\n \"batchSize\": 123,\n \"maxContextLength\": 123,\n \"earlyStop\": true,\n \"evalAutoCarveoutBasisPoints\": 4999,\n \"lrSchedule\": \"<string>\",\n \"warmupSteps\": 123,\n \"dpoBeta\": \"<string>\"\n },\n \"evaluationDatasetVersion\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://compute.prentis.ai/v1/accounts/{account}/supervisedFineTuningJobs:estimateCost")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"baseModel\": \"<string>\",\n \"inputDatasetVersion\": \"<string>\",\n \"config\": {\n \"outputModelId\": \"<string>\",\n \"loraRank\": 123,\n \"learningRate\": \"<string>\",\n \"epochs\": 123,\n \"batchSize\": 123,\n \"maxContextLength\": 123,\n \"earlyStop\": true,\n \"evalAutoCarveoutBasisPoints\": 4999,\n \"lrSchedule\": \"<string>\",\n \"warmupSteps\": 123,\n \"dpoBeta\": \"<string>\"\n },\n \"evaluationDatasetVersion\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"estimate": {
"exampleCount": "4000",
"avgTokensPerExample": "535",
"epochs": 2,
"tokensProcessed": "4280000",
"ratePerMillion": {
"amount": "0.45",
"currency": "USD"
},
"estimatedCost": {
"amount": "1.93",
"currency": "USD"
}
},
"egress": {
"allowed": true,
"execution": {
"thirdParty": false
},
"providerApproved": true,
"requiredAgreementVersion": "v2",
"acceptedAgreementVersion": "v2"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_REQUEST",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_REQUEST",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_REQUEST",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_REQUEST",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_REQUEST",
"param": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "INVALID_REQUEST",
"param": "<string>"
}
}Authorizations
Authorization: Bearer <your API key> -- the same key as inference. A key reaches the account it belongs to and no other.
Path Parameters
Your account id -- the one in the console's address bar (my-account for this key). It must be the account the key belongs to.
64Body
The model to fine-tune, as a full resource name (accounts/maas/models/your-base-model). Only base models offered for training are accepted -- the console's Training page lists them.
The model to fine-tune, as a full resource name (accounts/maas/models/your-base-model). Only base models offered for training are accepted -- the console's Training page lists them.
The model to fine-tune, as a full resource name (accounts/maas/models/your-base-model). Only base models offered for training are accepted -- the console's Training page lists them.
The model to fine-tune, as a full resource name (accounts/maas/models/your-base-model). Only base models offered for training are accepted -- the console's Training page lists them.
256The training data: a dataset (accounts/{account}/datasets/{dataset}) to use its latest version, or one version (…/versions/{n}) to pin it. The dataset must be READY.
The preference data: a dataset to use its latest version, or one version to pin it. Each row needs a prompt and two answers -- see the dataset format guide. The dataset must be READY.
The training data: a dataset (accounts/{account}/datasets/{dataset}) to use its latest version, or one version (…/versions/{n}) to pin it. The dataset must be READY.
The training data: a dataset (accounts/{account}/datasets/{dataset}) to use its latest version, or one version (…/versions/{n}) to pin it. The dataset must be READY.
256How to train. outputModelId is required: the id of the model the job will create, which must not already exist in your account. The rest are optional -- loraRank, learningRate (a string, e.g. "1e-4"), epochs (1-100), batchSize, maxContextLength (longer examples are skipped and counted, never truncated), earlyStop, evalAutoCarveoutBasisPoints (0-9999, in hundredths of a percent), lrSchedule (constant, cosine or linear_decay), warmupSteps, and dpoBeta (preference jobs only; a string, default "0.1"). Fixed once the job is created.
How to train. outputModelId is required: the id of the model the job will create, which must not already exist in your account. The rest are optional -- loraRank, learningRate (a string, e.g. "1e-4"), epochs (1-100), batchSize, maxContextLength (longer examples are skipped and counted, never truncated), earlyStop, evalAutoCarveoutBasisPoints (0-9999, in hundredths of a percent), lrSchedule (constant, cosine or linear_decay), warmupSteps, and dpoBeta (preference jobs only; a string, default "0.1"). Fixed once the job is created.
How to train. outputModelId is required: the id of the model the job will create, which must not already exist in your account. The rest are optional -- loraRank, learningRate (a string, e.g. "1e-4"), epochs (1-100), batchSize, maxContextLength (longer examples are skipped and counted, never truncated), earlyStop, evalAutoCarveoutBasisPoints (0-9999, in hundredths of a percent), lrSchedule (constant, cosine or linear_decay), warmupSteps, and dpoBeta (preference jobs only; a string, default "0.1"). Fixed once the job is created.
How to train. outputModelId is required: the id of the model the job will create, which must not already exist in your account. The rest are optional -- loraRank, learningRate (a string, e.g. "1e-4"), epochs (1-100), batchSize, maxContextLength (longer examples are skipped and counted, never truncated), earlyStop, evalAutoCarveoutBasisPoints (0-9999, in hundredths of a percent), lrSchedule (constant, cosine or linear_decay), warmupSteps, and dpoBeta (preference jobs only; a string, default "0.1"). Fixed once the job is created.
Show child attributes
Show child attributes
Accepted so that the body of a create can be sent unchanged, but not used: the estimate covers the training data only.
Optional held-out data to measure evaluation loss on, in the same form as inputDatasetVersion. Leave it empty and set config.evalAutoCarveoutBasisPoints to hold out a share of the training data instead, or leave both empty for no evaluation.
Accepted so that the body of a create can be sent unchanged, but not used: the estimate covers the training data only.
Optional held-out data to measure evaluation loss on, in the same form as inputDatasetVersion. Leave it empty and set config.evalAutoCarveoutBasisPoints to hold out a share of the training data instead, or leave both empty for no evaluation.
256