> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mka1.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ajuste fino de um modelo

> Envie dados de ajuste fino, crie um job de ajuste fino, monitore o progresso do treinamento e utilize o modelo resultante com o SDK `@meetkai/mka1`.

Use o ajuste fino quando quiser adaptar um modelo base aos seus próprios exemplos de treinamento e estilo operacional.
Os endpoints de ajuste fino criam um job assíncrono a partir de arquivos JSONL enviados e retornam um ID de modelo quando o treinamento é concluído com sucesso.

Os endpoints de ajuste fino são marcados como **APENAS ADMINISTRADOR** na referência de API gerada.
Use uma chave de API com as permissões necessárias.

## Antes de começar

Prepare:

| Entrada                | Descrição                                                                                  |
| ---------------------- | ------------------------------------------------------------------------------------------ |
| Arquivo de treinamento | Um arquivo JSONL com seus exemplos de treinamento. Faça upload com `purpose: "fine-tune"`. |
| Arquivo de validação   | Dados de validação JSONL opcionais. Faça upload com `purpose: "fine-tune"`.                |
| Modelo base            | O ID do modelo que você deseja ajustar, por exemplo `meetkai:functionary-medium`.          |

Jobs de ajuste fino podem retornar estes status:

```
validating_files -> queued -> running -> succeeded
                          \-> failed
                          \-> cancelled
```

## Passo 1 - Envie seus arquivos de treinamento

Envie cada arquivo JSONL usando a API de Arquivos e `purpose: "fine-tune"`.

<CodeGroup>
  ```bash CLI theme={null}
  mka1 llm files upload \
    --file ./fine-tuning-train.jsonl \
    --purpose fine-tune \
    -H 'X-On-Behalf-Of: <end-user-id>'

  mka1 llm files upload \
    --file ./fine-tuning-validation.jsonl \
    --purpose fine-tune
  ```

  ```ts MKA1 SDK theme={null}
  import { SDK } from '@meetkai/mka1';

  const mka1 = new SDK({
    bearerAuth: 'Bearer <mka1-api-key>',
  });

  const requestOptions = {
    headers: {
      'X-On-Behalf-Of': '<end-user-id>',
    },
  };

  const trainingFile = await mka1.llm.files.upload(
    {
      file: Bun.file('./fine-tuning-train.jsonl'),
      purpose: 'fine-tune',
    },
    requestOptions
  );

  const validationFile = await mka1.llm.files.upload(
    {
      file: Bun.file('./fine-tuning-validation.jsonl'),
      purpose: 'fine-tune',
    },
    requestOptions
  );

  console.log(trainingFile.id);
  console.log(validationFile.id);
  ```

  ```csharp C# SDK theme={null}
  using System.Text;
  using MeetKai.MKA1;
  using MeetKai.MKA1.Types.Components;
  using MeetKai.MKA1.Types.Requests;

  var sdk = new SDK(bearerAuth: "Bearer YOUR_API_KEY");

  var trainingFile = await sdk.Llm.Files.UploadAsync(new UploadFileRequestBody()
  {
      File = new UploadFileFile()
      {
          FileName = "fine-tuning-train.jsonl",
          Content = File.ReadAllBytes("./fine-tuning-train.jsonl"),
      },
      Purpose = UploadFilePurpose.FineTune,
  });

  Console.WriteLine(trainingFile.File!.Id);
  ```

  ```python Python SDK theme={null}
  from mka1 import SDK

  sdk = SDK(bearer_auth="Bearer YOUR_API_KEY")

  training_file = sdk.llm.files.upload(
      file={"file_name": "fine-tuning-train.jsonl", "content": open("./fine-tuning-train.jsonl", "rb")},
      purpose="fine-tune",
  )

  validation_file = sdk.llm.files.upload(
      file={"file_name": "fine-tuning-validation.jsonl", "content": open("./fine-tuning-validation.jsonl", "rb")},
      purpose="fine-tune",
  )

  print(training_file.id)
  print(validation_file.id)
  ```

  ```bash curl theme={null}
  curl https://apigw.mka1.com/api/v1/llm/files \
    --request POST \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'X-On-Behalf-Of: <end-user-id>' \
    --form 'file=@./fine-tuning-train.jsonl;type=application/jsonl' \
    --form 'purpose=fine-tune'
  ```
</CodeGroup>

Guarde os IDs de arquivo retornados.
Você irá passá-los para a API de Ajuste Fino no próximo passo.

## Passo 2 - Crie um job de ajuste fino

Chame `mka1.llm.fineTuning.create` com o modelo base e o ID do arquivo de treinamento enviado.
Adicione um arquivo de validação, sufixo, metadados e configurações de método quando necessário.

<CodeGroup>
  ```bash CLI theme={null}
  mka1 llm fine-tuning create --body '{
    "model": "meetkai:functionary-medium",
    "training_file": "file_abc123",
    "validation_file": "file_def456",
    "suffix": "support-bot",
    "seed": 42,
    "method": {
      "type": "supervised",
      "supervised": {
        "hyperparameters": {
          "n_epochs": 3
        }
      }
    },
    "metadata": {
      "experiment": "support-bot-v1"
    }
  }'
  ```

  ```ts MKA1 SDK theme={null}
  const job = await mka1.llm.fineTuning.create(
    {
      model: 'meetkai:functionary-medium',
      trainingFile: trainingFile.id,
      validationFile: validationFile.id,
      suffix: 'support-bot',
      seed: 42,
      method: {
        type: 'supervised',
        supervised: {
          hyperparameters: {
            nEpochs: 3,
          },
        },
      },
      metadata: {
        experiment: 'support-bot-v1',
      },
    },
    requestOptions
  );

  console.log(job.id);            // "ftjob_aa87e2b1112a455b8deabed784372198"
  console.log(job.status);        // "validating_files" | "queued" | "running" | ...
  console.log(job.fineTunedModel); // null até o job ser concluído com sucesso
  ```

  ```csharp C# SDK theme={null}
  using MeetKai.MKA1;
  using MeetKai.MKA1.Types.Components;

  var sdk = new SDK(bearerAuth: "Bearer YOUR_API_KEY");

  var job = await sdk.Llm.FineTuning.CreateAsync(new CreateFineTuningJobRequest()
  {
      Model = "meetkai:functionary-medium",
      TrainingFile = trainingFile.File!.Id,
      Suffix = "support-bot",
      Seed = 42,
      Method = new Method()
      {
          Type = MethodType.Supervised,
          Supervised = new Supervised()
          {
              Hyperparameters = new SupervisedHyperparameters()
              {
                  NEpochs = SupervisedHyperparametersNEpochs.CreateInteger(3),
              },
          },
      },
  });

  Console.WriteLine(job.FineTuningJob!.Id);            // "ftjob_aa87e2b1112a455b8deabed784372198"
  Console.WriteLine(job.FineTuningJob!.Status);        // "validating_files" | "queued" | "running" | ...
  ```

  ```python Python SDK theme={null}
  job = sdk.llm.fine_tuning.create(
      model="meetkai:functionary-medium",
      training_file=training_file.id,
      validation_file=validation_file.id,
      suffix="support-bot",
      seed=42,
      method={
          "type": "supervised",
          "supervised": {
              "hyperparameters": {
                  "n_epochs": 3,
              },
          },
      },
      metadata={"experiment": "support-bot-v1"},
  )

  print(job.id)                # "ftjob_aa87e2b1112a455b8deabed784372198"
  print(job.status)            # "validating_files" | "queued" | "running" | ...
  print(job.fine_tuned_model)  # None até o job ser concluído com sucesso
  ```

  ```bash curl theme={null}
  curl https://apigw.mka1.com/api/v1/llm/fine_tuning/jobs \
    --request POST \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'X-On-Behalf-Of: <end-user-id>' \
    --data '{
      "model": "meetkai:functionary-medium",
      "training_file": "file_abc123",
      "validation_file": "file_def456",
      "suffix": "support-bot",
      "seed": 42,
      "method": {
        "type": "supervised",
        "supervised": {
          "hyperparameters": {
            "n_epochs": 3
          }
        }
      },
      "metadata": {
        "experiment": "support-bot-v1"
      }
    }'
  ```
</CodeGroup>

## Passo 3 - Consulte o status do job

Recupere o job até que ele atinja o status `succeeded`, `failed` ou `cancelled`.

<CodeGroup>
  ```bash CLI theme={null}
  mka1 llm fine-tuning retrieve \
    --fine-tuning-job-id ftjob_aa87e2b1112a455b8deabed784372198
  ```

  ```ts MKA1 SDK theme={null}
  async function waitForFineTuningJob(
    fineTuningJobId: string,
    timeoutMs = 30 * 60_000
  ) {
    const terminalStatuses = new Set(['succeeded', 'failed', 'cancelled']);
    const start = Date.now();

    while (Date.now() - start < timeoutMs) {
      const current = await mka1.llm.fineTuning.retrieve(
        { fineTuningJobId },
        requestOptions
      );

      if (terminalStatuses.has(current.status)) {
        return current;
      }

      await new Promise((resolve) => setTimeout(resolve, 10_000));
    }

    throw new Error(`Fine-tuning job ${fineTuningJobId} did not finish in time`);
  }

  const completedJob = await waitForFineTuningJob(job.id);

  if (completedJob.status === 'succeeded') {
    console.log(completedJob.fineTunedModel);
  } else {
    console.log(completedJob.error);
  }
  ```

  ```csharp C# SDK theme={null}
  using MeetKai.MKA1;
  using MeetKai.MKA1.Types.Components;

  var sdk = new SDK(bearerAuth: "Bearer YOUR_API_KEY");

  var retrieved = await sdk.Llm.FineTuning.RetrieveAsync(jobId);
  Console.WriteLine(retrieved.FineTuningJob!.Status);
  ```

  ```python Python SDK theme={null}
  import time

  def wait_for_fine_tuning_job(sdk, job_id, timeout_ms=30 * 60_000):
      terminal = {"succeeded", "failed", "cancelled"}
      start = time.time() * 1000

      while (time.time() * 1000) - start < timeout_ms:
          current = sdk.llm.fine_tuning.retrieve(fine_tuning_job_id=job_id)
          if current.status in terminal:
              return current
          time.sleep(10)

      raise TimeoutError(f"Fine-tuning job {job_id} did not finish in time")

  completed_job = wait_for_fine_tuning_job(sdk, job.id)

  if completed_job.status == "succeeded":
      print(completed_job.fine_tuned_model)
  else:
      print(completed_job.error)
  ```

  ```bash curl theme={null}
  curl https://apigw.mka1.com/api/v1/llm/fine_tuning/jobs/ftjob_aa87e2b1112a455b8deabed784372198 \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'X-On-Behalf-Of: <end-user-id>'
  ```
</CodeGroup>

Você também pode paginar todos os jobs com `mka1.llm.fineTuning.list({ limit, after })`.

## Passo 4 - Inspecione eventos de treinamento e checkpoints

Use eventos para logs de treinamento e atualizações de métricas.
Use checkpoints para inspecionar checkpoints intermediários do modelo e suas métricas.

<CodeGroup>
  ```bash CLI theme={null}
  mka1 llm fine-tuning list-events \
    --fine-tuning-job-id ftjob_aa87e2b1112a455b8deabed784372198 \
    --limit 20

  mka1 llm fine-tuning list-checkpoints \
    --fine-tuning-job-id ftjob_aa87e2b1112a455b8deabed784372198 \
    --limit 10
  ```

  ```ts MKA1 SDK theme={null}
  const events = await mka1.llm.fineTuning.listEvents(
    {
      fineTuningJobId: job.id,
      limit: 20,
    },
    requestOptions
  );

  for (const event of events.data) {
    console.log(event.createdAt, event.level, event.message, event.data);
  }

  const checkpoints = await mka1.llm.fineTuning.listCheckpoints(
    {
      fineTuningJobId: job.id,
      limit: 10,
    },
    requestOptions
  );

  for (const checkpoint of checkpoints.data) {
    console.log(
      checkpoint.stepNumber,
      checkpoint.fineTunedModelCheckpoint,
      checkpoint.metrics
    );
  }
  ```

  ```csharp C# SDK theme={null}
  using MeetKai.MKA1;

  var sdk = new SDK(bearerAuth: "Bearer YOUR_API_KEY");

  var events = await sdk.Llm.FineTuning.ListEventsAsync(
      fineTuningJobId: jobId, limit: 20);

  var checkpoints = await sdk.Llm.FineTuning.ListCheckpointsAsync(
      fineTuningJobId: jobId, limit: 10);
  ```

  ```python Python SDK theme={null}
  events = sdk.llm.fine_tuning.list_events(
      fine_tuning_job_id=job.id,
      limit=20,
  )

  for event in events.data:
      print(event.created_at, event.level, event.message, event.data)

  checkpoints = sdk.llm.fine_tuning.list_checkpoints(
      fine_tuning_job_id=job.id,
      limit=10,
  )

  for checkpoint in checkpoints.data:
      print(checkpoint.step_number, checkpoint.fine_tuned_model_checkpoint, checkpoint.metrics)
  ```

  ```bash curl theme={null}
  curl "https://apigw.mka1.com/api/v1/llm/fine_tuning/jobs/ftjob_aa87e2b1112a455b8deabed784372198/events?limit=20" \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'X-On-Behalf-Of: <end-user-id>'

  curl "https://apigw.mka1.com/api/v1/llm/fine_tuning/jobs/ftjob_aa87e2b1112a455b8deabed784372198/checkpoints?limit=10" \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'X-On-Behalf-Of: <end-user-id>'
  ```
</CodeGroup>

As métricas dos checkpoints podem incluir `train_loss`, `train_mean_token_accuracy`, `valid_loss`, `valid_mean_token_accuracy`, `full_valid_loss` e `full_valid_mean_token_accuracy`.

## Passo 5 - Pausar, retomar ou cancelar um job

Use `pause` quando precisar pausar temporariamente um job em execução.
Use `resume` para continuar.
Use `cancel` para interromper permanentemente.

<CodeGroup>
  ```bash CLI theme={null}
  mka1 llm fine-tuning pause \
    --fine-tuning-job-id ftjob_aa87e2b1112a455b8deabed784372198

  mka1 llm fine-tuning resume \
    --fine-tuning-job-id ftjob_aa87e2b1112a455b8deabed784372198

  mka1 llm fine-tuning cancel \
    --fine-tuning-job-id ftjob_aa87e2b1112a455b8deabed784372198
  ```

  ```ts MKA1 SDK theme={null}
  await mka1.llm.fineTuning.pause(
    { fineTuningJobId: job.id },
    requestOptions
  );

  await mka1.llm.fineTuning.resume(
    { fineTuningJobId: job.id },
    requestOptions
  );

  await mka1.llm.fineTuning.cancel(
    { fineTuningJobId: job.id },
    requestOptions
  );
  ```

  ```csharp C# SDK theme={null}
  using MeetKai.MKA1;

  var sdk = new SDK(bearerAuth: "Bearer YOUR_API_KEY");

  // Pause
  await sdk.Llm.FineTuning.PauseAsync(jobId);

  // Resume
  await sdk.Llm.FineTuning.ResumeAsync(jobId);

  // Cancel
  var cancelled = await sdk.Llm.FineTuning.CancelAsync(jobId);
  Console.WriteLine(cancelled.FineTuningJob!.Status);
  ```

  ```python Python SDK theme={null}
  # Pause
  sdk.llm.fine_tuning.pause(fine_tuning_job_id=job.id)

  # Resume
  sdk.llm.fine_tuning.resume(fine_tuning_job_id=job.id)

  # Cancel
  sdk.llm.fine_tuning.cancel(fine_tuning_job_id=job.id)
  ```

  ```bash curl theme={null}
  curl https://apigw.mka1.com/api/v1/llm/fine_tuning/jobs/ftjob_aa87e2b1112a455b8deabed784372198/pause \
    --request POST \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'X-On-Behalf-Of: <end-user-id>'

  curl https://apigw.mka1.com/api/v1/llm/fine_tuning/jobs/ftjob_aa87e2b1112a455b8deabed784372198/resume \
    --request POST \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'X-On-Behalf-Of: <end-user-id>'

  curl https://apigw.mka1.com/api/v1/llm/fine_tuning/jobs/ftjob_aa87e2b1112a455b8deabed784372198/cancel \
    --request POST \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'X-On-Behalf-Of: <end-user-id>'
  ```
</CodeGroup>

## Passo 6 - Use o modelo ajustado

Quando o job atingir `succeeded`, `job.fineTunedModel` conterá o novo ID do modelo.
Passe esse ID de modelo para uma requisição de Respostas.

<CodeGroup>
  ```bash CLI theme={null}
  mka1 llm responses create \
    --model ft:meetkai:functionary-medium:support-bot \
    --input '"Write a support reply for a delayed shipment."'
  ```

  ```ts MKA1 SDK theme={null}
  const response = await mka1.llm.responses.create(
    {
      model: completedJob.fineTunedModel!,
      input: 'Write a support reply for a delayed shipment.',
    },
    requestOptions
  );

  console.log(response.outputText);
  ```

  ```csharp C# SDK theme={null}
  using MeetKai.MKA1;
  using MeetKai.MKA1.Types.Components;

  var sdk = new SDK(bearerAuth: "Bearer YOUR_API_KEY");

  var response = await sdk.Llm.Responses.CreateAsync(new ResponsesCreateRequest()
  {
      Model = completedJob.FineTuningJob!.FineTunedModel!,
      Input = ResponsesCreateRequestInput.CreateStr(
          "Write a support reply for a delayed shipment."),
  });
  ```

  ```python Python SDK theme={null}
  response = sdk.llm.responses.create(
      model=completed_job.fine_tuned_model,
      input="Write a support reply for a delayed shipment.",
  )

  print(response.output_text)
  ```

  ```bash curl theme={null}
  curl https://apigw.mka1.com/api/v1/llm/responses \
    --request POST \
    --header 'Content-Type: application/json' \
    --header 'Authorization: Bearer <mka1-api-key>' \
    --header 'X-On-Behalf-Of: <end-user-id>' \
    --data '{
      "model": "ft:meetkai:functionary-medium:support-bot",
      "input": "Write a support reply for a delayed shipment."
    }'
  ```
</CodeGroup>

## Referência da API

Para o esquema completo de requisição e resposta, abra o grupo de Ajuste Fino na [Referência de API](/pt/api-reference/introduction).
