finetuning/finetuning_on_bedrock.ipynb (264 lines of code) (raw):

{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Finetuning Claude 3 Haiku on Bedrock\n", "In this notebook, we'll walk you through the process of finetuning Claude 3 Haiku on Amazon Bedrock\n", "\n", "## What You'll Need\n", "- An AWS account with access to Bedrock\n", "- A dataset (or you can use the sample dataset provided here)\n", "- [A service role capable of accessing the s3 bucket where you save your training data](https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-iam-role.html)\n", "\n", "## Install Dependencies" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!pip install boto3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import boto3 " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prep a Dataset\n", "Your dataset for bedrock finetuning needs to be a JSONL file (i.e. a file with a json object on each line).\n", "\n", "Each line in the JSONL file should be a JSON object with the following structure:\n", "\n", "```\n", "{\n", " \"system\": \"<optional_system_message>\",\n", " \"messages\": [\n", " {\"role\": \"user\", \"content\": \"user message\"},\n", " {\"role\": \"assistant\", \"content\": \"assistant response\"},\n", " ...\n", " ]\n", "}\n", "```\n", "\n", "- The `system` field is optional.\n", "- There must be at least two messages.\n", "- The first message must be from the \"user\".\n", "- The last message must be from the \"assistant\".\n", "- User and assistant messages must alternate.\n", "- No extraneous keys are allowed.\n", "\n", "\n", "## Sample Dataset - JSON Mode\n", "We've included a sample dataset that teaches a model to respond to all questions with JSON. Here's what that dataset looks like:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import json\n", "\n", "sample_dataset = []\n", "dataset_path = 'datasets/json_mode_dataset.jsonl'\n", "with open(dataset_path, 'r') as f:\n", " for line in f:\n", " sample_dataset.append(json.loads(line))\n", "\n", "print(json.dumps(sample_dataset[0], indent=2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Upload your dataset to S3\n", "Your dataset for finetuning should be available on s3; for this demo we'll write the sample dataset to an s3 bucket you control" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bucket_name = \"YOUR_BUCKET_NAME\"\n", "s3_path = \"json_mode_dataset.jsonl\"\n", "\n", "s3 = boto3.client('s3')\n", "s3.upload_file(dataset_path, bucket_name, s3_path)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Launch Bedrock Finetuning Job\n", "\n", "Now that you have your dataset ready, you can launch a finetuning job using `boto3`. First we'll configure a few parameters for the job:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Configuration\n", "job_name = \"anthropic-finetuning-cookbook-training\"\n", "custom_model_name = \"anthropic_finetuning_cookbook\"\n", "role = \"YOUR_AWS_SERVICE_ROLE_ARN\"\n", "output_path = f\"s3://{bucket_name}/finetuning_example_results/\"\n", "base_model_id = \"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-haiku-20240307-v1:0:200k\"\n", "\n", "# Hyperparameters\n", "epoch_count = 5\n", "batch_size = 4\n", "learning_rate_multiplier = 1.0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then we can launch the job with `boto3`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bedrock = boto3.client(service_name=\"bedrock\")\n", "bedrock_runtime = boto3.client(service_name=\"bedrock-runtime\")\n", "\n", "bedrock.create_model_customization_job(\n", " customizationType=\"FINE_TUNING\",\n", " jobName=job_name,\n", " customModelName=custom_model_name,\n", " roleArn=role,\n", " baseModelIdentifier=base_model_id,\n", " hyperParameters = {\n", " \"epochCount\": f\"{epoch_count}\",\n", " \"batchSize\": f\"{batch_size}\",\n", " \"learningRateMultiplier\": f\"{learning_rate_multiplier}\",\n", " },\n", " trainingDataConfig={\"s3Uri\": f\"s3://{bucket_name}/{s3_path}\"},\n", " outputDataConfig={\"s3Uri\": output_path},\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can use this to check the status of your job while its training:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Check for the job status\n", "status = bedrock.get_model_customization_job(jobIdentifier=job_name)[\"status\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Use your finetuned model!\n", "\n", "To use your finetuned model, [you'll need to host it using Provisioned Throughput in Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-use.html). Once your model is ready with Provisioned Throughput, you can invoked your model via the Bedrock API." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "provisioned_throughput_arn = \"YOUR_PROVISIONED_THROUGHPUT_ARN\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bedrock = boto3.client('bedrock-runtime', region_name = \"us-east-1\")\n", "body = json.dumps(\n", " {\n", " \"anthropic_version\": \"bedrock-2023-05-31\",\n", " \"max_tokens\": 1000,\n", " \"system\": \"JSON Mode: Enabled\",\n", " \"messages\": [\n", " {\n", " \"role\": \"user\",\n", " \"content\": [\n", " {\n", " \"type\": \"text\",\n", " \"text\":\"What is a large language model?\"\n", " }\n", " ]\n", " }\n", " ]\n", " }\n", ")\n", "response = bedrock_runtime.invoke_model(\n", "\tmodelId=provisioned_throughput_arn,\n", " body=body\n", ")\n", "body = json.loads(response['body'].read().decode('utf-8'))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(body['content'][0]['text'])" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.6" } }, "nbformat": 4, "nbformat_minor": 2 }