{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Copyright 2024 Google LLC\n", "#\n", "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Fine-tuning Gemini for Domain Specificity\n", "\n", "This notebooks demonstrates how to fine-tune Gemini to perform translation tasks from multiple languages (DE,ES,FR,IT,PL,PT,RU,SV,UK,ZH) to English. \n", "It follows the steps: \n", " - Reads the dataset from a GCS bucket\n", " - Save it in the Iceberg format using Dataproc Serverless\n", " - Use Vertex AI Supervised fine-tuning job to fine-tune Gemini with the dataset\n", " - Register the model in Vertex AI Model Registry" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Environment Setup (Antigravity / Data Cloud) with BigLake Metastore for Iceberg\n", "\n", "If you are running this notebook in **Antigravity** (with the Google Data Cloud extension), the Spark session (`spark` variable) is automatically initialized once you select a remote kernel. \n", "\n", "If you are running **locally** or in another environment, you will need to manually initialize the `SparkSession` and install any missing dependencies." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this notebook we are going to create Iceberg tables, so you need to have a Kernel running PySpark with Iceberg, and you can do that using a [Serverless Apache Spark runtime template](https://docs.cloud.google.com/dataproc-serverless/docs/quickstarts/jupyterlab-sessions). This notebook uses Iceberg tables and requires a specific environment configuration to run successfully. You must run this notebook using a **Dataproc Serverless Runtime Template** that has **BigLake Metastore** configured with Iceberg support. By default the catalog name is \"biglake\", but you could change that. \n", "Follow these steps in the Google Data Cloud extension in Antigravity to create or configure your runtime correctly.\n", "\n", "**1. Navigate to Serverless Runtimes**\n", "In the extension sidebar, locate the **APACHE SPARK** section under **Google Data Cloud** and click on **Serverless**.\n", "\n", "**2. Create a New Runtime**\n", "In the main pane, click the blue **+ CREATE** button located at the top right to start configuring a new Serverless Runtime template.\n", "\n", "**3. Configure Metastore Settings**\n", "Scroll down to the **Metastore** section of the configuration form (as shown below).\n", " * **Metastore:** Select `Biglake Metastore` from the dropdown.\n", " * **Data warehousing directory:** Enter your valid Cloud Storage path where the Iceberg data will be stored.\n", "* **Catalog Name:** Here we could leave as the default `biglake` as the Catalog Name field.\n", "\n", "\"Navigation\n", "\"Serverless\n", "\"Configuration\n", "\n", "Once finished, click **Create**. Ensure you select this specific runtime template when running the notebook.\n", "\n", "In other IDEs such as JupyterLab/VSCode you would do a similar setup:\n", "- JupyterLab/VSCode Settings -> - Google Cloud Settings -> - Create Serverless Runtime Template -> - Metastore -> - Biglake Metastore -> Set a data warehouse GCS bucket and choose your ICEBERG_CATALOG name\n", "\n", "Use the created runtime as your kernel" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Imports" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from typing import List\n", "import pandas as pd\n", "import time\n", "import json\n", "\n", "from google.cloud import bigquery, storage\n", "from pyspark.sql.types import LongType, StringType, DoubleType\n", "\n", "type_mapping = {\n", " LongType: 'long',\n", " StringType: 'string',\n", " DoubleType: 'double'\n", "}" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "parameters" ] }, "outputs": [], "source": [ "PROJECT_ID = \"\" \n", "LOCATION = \"\" \n", "BUCKET_NAME = \"\"\n", "\n", "if not PROJECT_ID: PROJECT_ID = input(\"Enter project id\")\n", "if not LOCATION: LOCATION = input(\"Enter location\")\n", "if not BUCKET_NAME: BUCKET_NAME = input(\"Enter bucket name\")\n", "\n", "JSON_FILES_GCS_URI = \"gs://dataproc-metastore-public-binaries/wikipedia_translated_clusters/*\"\n", "\n", "ICEBERG_CATALOG = \"biglake\"\n", "ICEBERG_SCHEMA = \"default\"\n", "ICERBERG_TABLE = \"wikipedia_translated_docs\"\n", "ICEBERG_WAREHOURSE_GCS_PATH=f\"gs://{BUCKET_NAME}/warehouse\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make sure you have [gcloud](https://docs.cloud.google.com/sdk/docs/install-sdk) installed and authenticated in your terminal using gcloud auth application-default login" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create a GCS bucket if you do not have one" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from google.cloud import storage\n", "\n", "storage_client = storage.Client()\n", "bucket = storage_client.bucket(BUCKET_NAME)\n", "\n", "if not bucket.exists():\n", " bucket = storage_client.create_bucket(BUCKET_NAME, location=LOCATION)\n", " print(f\"Created bucket {BUCKET_NAME}\")\n", "else:\n", " print(f\"Bucket {BUCKET_NAME} already exists\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Read input dataset" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T20:54:25.574717Z", "iopub.status.busy": "2026-02-12T20:54:25.573879Z", "iopub.status.idle": "2026-02-12T20:54:37.324093Z", "shell.execute_reply": "2026-02-12T20:54:37.323255Z", "shell.execute_reply.started": "2026-02-12T20:54:25.574680Z" } }, "outputs": [], "source": [ "raw_dataset = spark.read.json(JSON_FILES_GCS_URI)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Transform the dataset" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T20:54:37.326238Z", "iopub.status.busy": "2026-02-12T20:54:37.325600Z", "iopub.status.idle": "2026-02-12T20:55:12.736694Z", "shell.execute_reply": "2026-02-12T20:55:12.735849Z", "shell.execute_reply.started": "2026-02-12T20:54:37.326197Z" } }, "outputs": [], "source": [ "from pyspark.sql.functions import explode, array, lit, col, struct, desc, concat\n", "from pyspark.sql.types import StringType\n", "\n", "# Step 1: Get all column names from the DataFrame\n", "columns = raw_dataset.columns\n", "\n", "# Step 2: Create an array of structs with the column name and its content\n", "exploded_df = raw_dataset.select(\n", " explode(\n", " array([\n", " struct(\n", " lit(column).alias(\"topic\"),\n", " col(f\"`{column}`.title\").alias(\"title\"),\n", " col(f\"`{column}`.intro\").alias(\"intro\"),\n", " col(f\"`{column}`.translated_intro\").alias(\"translated_intro\")\n", " )\n", " for column in columns\n", " ])\n", " ).alias(\"exploded\")\n", ")\n", "\n", "# Step 3: Extract the fields from the struct and add the prompt column\n", "transformed_df = exploded_df.select(\n", " col(\"exploded.title\").alias(\"title\"),\n", " lit(\"Translate this intro to english: \").alias(\"prompt\"),\n", " col(\"exploded.intro\").alias(\"intro\"),\n", " col(\"exploded.translated_intro\").alias(\"translated_intro\")\n", ")\n", "\n", "# Step 4: Drop rows where any value is null\n", "transformed_df = transformed_df.dropna(how=\"any\")\n", "\n", "# Step 5: Sort by title in descending order (Z to A)\n", "transformed_df = transformed_df.orderBy(desc(\"title\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T20:55:12.737798Z", "iopub.status.busy": "2026-02-12T20:55:12.737539Z", "iopub.status.idle": "2026-02-12T20:55:12.743748Z", "shell.execute_reply": "2026-02-12T20:55:12.742913Z", "shell.execute_reply.started": "2026-02-12T20:55:12.737777Z" } }, "outputs": [], "source": [ "transformed_df.printSchema()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Display the schema of the resulting DataFrame\n", "transformed_df.printSchema()\n", "\n", "# Show a sample of the resulting DataFrame\n", "transformed_df.show(40, 50)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Create Apache Iceberg table in catalog" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T20:56:53.541992Z", "iopub.status.busy": "2026-02-12T20:56:53.541612Z", "iopub.status.idle": "2026-02-12T20:56:54.527180Z", "shell.execute_reply": "2026-02-12T20:56:54.526102Z", "shell.execute_reply.started": "2026-02-12T20:56:53.541965Z" } }, "outputs": [], "source": [ "spark.sql(f\"USE `{ICEBERG_CATALOG}`;\")\n", "spark.sql(f\"CREATE NAMESPACE IF NOT EXISTS `{ICEBERG_SCHEMA}`;\")\n", "spark.sql(f\"USE `{ICEBERG_SCHEMA}`;\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T20:55:12.746393Z", "iopub.status.busy": "2026-02-12T20:55:12.745409Z", "iopub.status.idle": "2026-02-12T20:55:12.764115Z", "shell.execute_reply": "2026-02-12T20:55:12.763380Z", "shell.execute_reply.started": "2026-02-12T20:55:12.746354Z" } }, "outputs": [], "source": [ "dataset_schema = f\"({', '.join([f'{field.name} {type_mapping.get(type(field.dataType), str(field.dataType))}' for field in transformed_df.schema.fields])})\"\n", "dataset_schema" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T20:57:01.041239Z", "iopub.status.busy": "2026-02-12T20:57:01.040948Z", "iopub.status.idle": "2026-02-12T21:00:04.711613Z", "shell.execute_reply": "2026-02-12T21:00:04.710420Z", "shell.execute_reply.started": "2026-02-12T20:57:01.041218Z" } }, "outputs": [], "source": [ "transformed_df.write.format(\"iceberg\").save(f\"{ICEBERG_CATALOG}.{ICEBERG_SCHEMA}.{ICERBERG_TABLE}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:05:05.231741Z", "iopub.status.busy": "2026-02-12T21:05:05.230593Z", "iopub.status.idle": "2026-02-12T21:05:05.489467Z", "shell.execute_reply": "2026-02-12T21:05:05.488449Z", "shell.execute_reply.started": "2026-02-12T21:05:05.231705Z" } }, "outputs": [], "source": [ "spark.sql(f\"SHOW SCHEMAS IN {ICEBERG_CATALOG};\").show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:05:08.519999Z", "iopub.status.busy": "2026-02-12T21:05:08.519648Z", "iopub.status.idle": "2026-02-12T21:05:08.710835Z", "shell.execute_reply": "2026-02-12T21:05:08.709369Z", "shell.execute_reply.started": "2026-02-12T21:05:08.519972Z" } }, "outputs": [], "source": [ "spark.sql(f\"SHOW TABLES IN {ICEBERG_CATALOG}.{ICEBERG_SCHEMA};\").show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Read Apache Iceberg table" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:05:11.969191Z", "iopub.status.busy": "2026-02-12T21:05:11.968837Z", "iopub.status.idle": "2026-02-12T21:05:13.628962Z", "shell.execute_reply": "2026-02-12T21:05:13.627977Z", "shell.execute_reply.started": "2026-02-12T21:05:11.969164Z" } }, "outputs": [], "source": [ "iceberg_df = spark.read.table(f\"{ICEBERG_CATALOG}.{ICEBERG_SCHEMA}.{ICERBERG_TABLE}\")\n", "iceberg_df.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Generate dataset for finetuning" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:05:19.032092Z", "iopub.status.busy": "2026-02-12T21:05:19.031739Z", "iopub.status.idle": "2026-02-12T21:05:19.484150Z", "shell.execute_reply": "2026-02-12T21:05:19.482770Z", "shell.execute_reply.started": "2026-02-12T21:05:19.032065Z" } }, "outputs": [], "source": [ "from pyspark.sql.functions import concat, col\n", "\n", "finetune_dataset = iceberg_df.select(\n", " concat(col(\"prompt\"), col(\"intro\")).alias(\"input_prompt\"),\n", " col(\"translated_intro\").alias(\"expected_model_output\")\n", ")\n", "\n", "finetune_dataset.show(5, 100)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:05:22.677769Z", "iopub.status.busy": "2026-02-12T21:05:22.677086Z", "iopub.status.idle": "2026-02-12T21:05:26.464366Z", "shell.execute_reply": "2026-02-12T21:05:26.463381Z", "shell.execute_reply.started": "2026-02-12T21:05:22.677736Z" } }, "outputs": [], "source": [ "finetune_dataset_pandas = finetune_dataset.toPandas()\n", "\n", "train_set = finetune_dataset_pandas.sample(frac=0.8, random_state=42) \n", "test_set = finetune_dataset_pandas.drop(train_set.index)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:05:26.466650Z", "iopub.status.busy": "2026-02-12T21:05:26.465970Z", "iopub.status.idle": "2026-02-12T21:05:26.472207Z", "shell.execute_reply": "2026-02-12T21:05:26.471240Z", "shell.execute_reply.started": "2026-02-12T21:05:26.466612Z" } }, "outputs": [], "source": [ "def generate_records(df: pd.DataFrame) -> List:\n", " \n", " records = []\n", "\n", " for index, row in df.iterrows():\n", "\n", " input_prompt = row['input_prompt']\n", " expected_model_output = row['expected_model_output']\n", "\n", " record = {\n", " \"contents\": [\n", " { \"role\": \"user\", \"parts\": [ { \"text\": input_prompt } ] },\n", " { \"role\": \"model\", \"parts\": [ { \"text\": expected_model_output } ] } ] \n", " }\n", "\n", " records.append(record)\n", " \n", " return records" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:05:26.473336Z", "iopub.status.busy": "2026-02-12T21:05:26.473069Z", "iopub.status.idle": "2026-02-12T21:05:28.812211Z", "shell.execute_reply": "2026-02-12T21:05:28.810616Z", "shell.execute_reply.started": "2026-02-12T21:05:26.473314Z" } }, "outputs": [], "source": [ "train_records = generate_records(train_set)[:1000] # Select 1000 training records for fine tuning training\n", "val_records = generate_records(test_set)[:300] # Select 300 eval records for fine tuning evaluation" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:05:29.816207Z", "iopub.status.busy": "2026-02-12T21:05:29.815919Z", "iopub.status.idle": "2026-02-12T21:05:29.820650Z", "shell.execute_reply": "2026-02-12T21:05:29.819680Z", "shell.execute_reply.started": "2026-02-12T21:05:29.816185Z" } }, "outputs": [], "source": [ "TRAIN_FILE_NAME = \"wikipedia_translated/records/fine-tuning-train-dataset.jsonl\"\n", "VAL_FILE_NAME = \"wikipedia_translated/records/fine-tuning-val-dataset.jsonl\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:05:31.026397Z", "iopub.status.busy": "2026-02-12T21:05:31.025638Z", "iopub.status.idle": "2026-02-12T21:05:31.032004Z", "shell.execute_reply": "2026-02-12T21:05:31.030924Z", "shell.execute_reply.started": "2026-02-12T21:05:31.026360Z" } }, "outputs": [], "source": [ "def upload_gcs(records: List, file_name: str, bucket_name: str = BUCKET_NAME, project_id: str = PROJECT_ID) -> str:\n", " \n", " storage_client = storage.Client(project=project_id)\n", " bucket = storage_client.bucket(bucket_name)\n", " blob = bucket.blob(file_name)\n", "\n", " jsonl_data = \"\\n\".join(json.dumps(item) for item in records)\n", " blob.upload_from_string(jsonl_data)\n", " \n", " uri = f\"gs://{bucket_name}/{file_name}\"\n", "\n", " return uri" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:05:31.852669Z", "iopub.status.busy": "2026-02-12T21:05:31.851913Z", "iopub.status.idle": "2026-02-12T21:05:32.221536Z", "shell.execute_reply": "2026-02-12T21:05:32.220696Z", "shell.execute_reply.started": "2026-02-12T21:05:31.852638Z" } }, "outputs": [], "source": [ "uri_train = upload_gcs(train_records, TRAIN_FILE_NAME)\n", "uri_val = upload_gcs(val_records, VAL_FILE_NAME)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Run finetuning job on Vertex AI" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:06:09.857724Z", "iopub.status.busy": "2026-02-12T21:06:09.857320Z", "iopub.status.idle": "2026-02-12T21:06:10.698405Z", "shell.execute_reply": "2026-02-12T21:06:10.697456Z", "shell.execute_reply.started": "2026-02-12T21:06:09.857691Z" } }, "outputs": [], "source": [ "from google import genai\n", "from google.genai import types" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:06:15.564866Z", "iopub.status.busy": "2026-02-12T21:06:15.563751Z", "iopub.status.idle": "2026-02-12T21:06:15.623119Z", "shell.execute_reply": "2026-02-12T21:06:15.622234Z", "shell.execute_reply.started": "2026-02-12T21:06:15.564833Z" } }, "outputs": [], "source": [ "client = genai.Client(\n", " vertexai=True,\n", " project=PROJECT_ID,\n", " location=LOCATION\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:06:16.368326Z", "iopub.status.busy": "2026-02-12T21:06:16.367378Z", "iopub.status.idle": "2026-02-12T21:06:16.373050Z", "shell.execute_reply": "2026-02-12T21:06:16.371912Z", "shell.execute_reply.started": "2026-02-12T21:06:16.368288Z" } }, "outputs": [], "source": [ "GEMINI_MODEL = \"gemini-2.5-flash\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Warning**: fine tuning the model will take +1 hour" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2026-02-12T21:06:18.351689Z", "iopub.status.busy": "2026-02-12T21:06:18.351408Z", "iopub.status.idle": "2026-02-12T21:06:18.450905Z", "shell.execute_reply": "2026-02-12T21:06:18.450087Z", "shell.execute_reply.started": "2026-02-12T21:06:18.351668Z" } }, "outputs": [], "source": [ "tuned_model_name = \"tuned_gemini_translation\"\n", "\n", "tuning_job = client.tunings.tune(\n", " base_model = GEMINI_MODEL,\n", " training_dataset = types.TuningDataset(gcs_uri = uri_train),\n", " config=types.CreateTuningJobConfig(\n", " epoch_count= 8,\n", " tuned_model_display_name=tuned_model_name,\n", " adapter_size = \"ADAPTER_SIZE_FOUR\",\n", " learning_rate_multiplier = 0.8,\n", " validation_dataset = types.TuningDataset(gcs_uri=uri_val)\n", " )\n", ")\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "execution_failed": "2026-02-12T22:12:07.421Z", "iopub.execute_input": "2026-02-12T21:06:28.593809Z", "iopub.status.busy": "2026-02-12T21:06:28.593391Z" } }, "outputs": [], "source": [ "while not tuning_job.has_ended:\n", " time.sleep(30)\n", " tuning_job = client.tunings.get(name=tuning_job.name)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(tuning_job.tuned_model.model)\n", "print(tuning_job.tuned_model.endpoint)\n", "print(tuning_job.experiment)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def predict(prompt, model):\n", "\n", " contents = [\n", " types.Content(\n", " role=\"user\",\n", " parts=[\n", " types.Part.from_text(text=prompt)\n", " ]\n", " )\n", " ]\n", "\n", " generate_content_config = types.GenerateContentConfig(\n", " temperature = 0.5,\n", " max_output_tokens = 128,\n", " response_mime_type = \"text/plain\",\n", " safety_settings = [types.SafetySetting(\n", " category = 'HARM_CATEGORY_UNSPECIFIED',\n", " threshold = 'BLOCK_ONLY_HIGH',\n", " )]\n", " )\n", " \n", " response = client.models.generate_content(model=model,\n", " contents=contents,\n", " config=generate_content_config)\n", " return response.text" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "input_prompt = \"\"\"Translate this intro to english: You (Estilizado como YOU - Sendo nomeado no Brasil como Você, em Portugal como Tu) é uma série de televisão americana de suspense psicológico desenvolvida por Greg Berlanti e Sera Gamble.\n", "Produzido pela Warner Horizon Television, em associação com Alloy Entertainment e A&E Studios. A série é baseada no romance de 2014 de mesmo nome de Caroline Kepnes.\n", "A primeira temporada segue Joe Goldberg, gerente de uma livraria de Nova York e um serial killer que se apaixona por uma cliente chamada Guinevere Beck e rapidamente desenvolve uma obsessão extrema, tóxica e delirante.\n", "A segunda temporada segue Joe enquanto ele se muda para Los Angeles e se apaixona por Love Quinn, chef e sócia de uma rede de produtos naturais.\n", "A primeira temporada, que foi lançada em 2018, é estrelada por Penn Badgley, Elizabeth Lail, Luca Padovan, Zach Cherry e Shay Mitchell.\n", "Para a segunda temporada, Ambyr Childers foi promovida a regular na série, juntando-se aos recém-escalados Victoria Pedretti, James Scully, Jenna Ortega e Carmela Zumbado.\n", "A série estreou na Lifetime em 9 de setembro de 2018 nos Estados Unidos e transmitida internacionalmente pela Netflix em 26 de dezembro de 2018.\n", "A série atraiu um público limitado na Lifetime antes de se tornar mais popular e um sucesso crítico para a Netflix, com mais de 43 milhões de espectadores tendo transmitido a primeira temporada após sua estreia no serviço de streaming.\n", "A Lifetime anunciou que You foi renovada para uma segunda temporada baseada no romance seguinte de Kepnes, Hidden Bodies, em 26 de julho de 2018, antes da estreia da série.\n", "Em dezembro de 2018, foi anunciado que a série mudaria para a Netflix como um título Original Netflix.\n", "A segunda temporada foi lançada exclusivamente na Netflix em 26 de dezembro de 2019.\n", "Em janeiro de 2020, a série foi renovada para uma terceira temporada pela Netflix, que conta com Badgley e Pedretti reprisando seus papéis.\n", "No dia 30 de agosto de 2021, foi confirmado que a terceira temporada irá estrear dia 15 de outubro de 2021.\n", "Em outubro de 2021, antes da estreia da terceira temporada, a série foi renovada para uma quarta temporada.\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "predict(input_prompt, tuning_job.tuned_model.endpoint)" ] } ], "metadata": { "environment": { "kernel": "9c39b79e5d2e7072beb4bd59-runtime-iceberg", "name": "workbench-notebooks.m139", "type": "gcloud", "uri": "us-docker.pkg.dev/deeplearning-platform-release/gcr.io/workbench-notebooks:m139" }, "kernelspec": { "display_name": "runtime-iceberg on Serverless Spark", "language": "python", "name": "9c39b79e5d2e7072beb4bd59-runtime-iceberg" }, "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.12" } }, "nbformat": 4, "nbformat_minor": 2 }