{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ur8xi4C7S06n"
      },
      "outputs": [],
      "source": [
        "# Copyright 2025 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": {
        "id": "JAPoU8Sm5E6e"
      },
      "source": [
        "# Handling Reasoning with MaaS Models on Vertex AI using vLLM\n",
        "\n",
        "<table align=\"left\">\n",
        "  <td style=\"text-align: center\">\n",
        "    <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/generative-ai/blob/main/open-models/get_started_with_oss_maas_reasoning_open_ai_sdk.ipynb\">\n",
        "      <img width=\"32px\" src=\"https://www.gstatic.com/pantheon/images/bigquery/welcome_page/colab-logo.svg\" alt=\"Google Colaboratory logo\"><br> Open in Colab\n",
        "    </a>\n",
        "  </td>\n",
        "  <td style=\"text-align: center\">\n",
        "    <a href=\"https://console.cloud.google.com/vertex-ai/colab/import/https:%2F%2Fraw.githubusercontent.com%2FGoogleCloudPlatform%2Fgenerative-ai%2Fmain%2Fopen-models%2Fget_started_with_oss_maas_reasoning_open_ai_sdk.ipynb\">\n",
        "      <img width=\"32px\" src=\"https://lh3.googleusercontent.com/JmcxdQi-qOpctIvWKgPtrzZdJJK-J3sWE1RsfjZNwshCFgE_9fULcNpuXYTilIR2hjwN\" alt=\"Google Cloud Colab Enterprise logo\"><br> Open in Colab Enterprise\n",
        "    </a>\n",
        "  </td>\n",
        "  <td style=\"text-align: center\">\n",
        "    <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/generative-ai/main/open-models/get_started_with_oss_maas_reasoning_open_ai_sdk.ipynb\">\n",
        "      <img src=\"https://www.gstatic.com/images/branding/gcpiconscolors/vertexai/v1/32px.svg\" alt=\"Vertex AI logo\"><br> Open in Vertex AI Workbench\n",
        "    </a>\n",
        "  </td>\n",
        "  <td style=\"text-align: center\">\n",
        "    <a href=\"https://github.com/GoogleCloudPlatform/generative-ai/blob/main/open-models/get_started_with_oss_maas_reasoning_open_ai_sdk.ipynb\">\n",
        "      <img width=\"32px\" src=\"https://raw.githubusercontent.com/primer/octicons/refs/heads/main/icons/mark-github-24.svg\" alt=\"GitHub logo\"><br> View on GitHub\n",
        "    </a>\n",
        "  </td>\n",
        "</table>\n",
        "\n",
        "<div style=\"clear: both;\"></div>\n",
        "\n",
        "<b>Share to:</b>\n",
        "\n",
        "<a href=\"https://www.linkedin.com/sharing/share-offsite/?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/open-models/get_started_with_oss_maas_reasoning_open_ai_sdk.ipynb\" target=\"_blank\">\n",
        "  <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/8/81/LinkedIn_icon.svg\" alt=\"LinkedIn logo\">\n",
        "</a>\n",
        "\n",
        "<a href=\"https://bsky.app/intent/compose?text=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/open-models/get_started_with_oss_maas_reasoning_open_ai_sdk.ipynb\" target=\"_blank\">\n",
        "  <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/7/7a/Bluesky_Logo.svg\" alt=\"Bluesky logo\">\n",
        "</a>\n",
        "\n",
        "<a href=\"https://twitter.com/intent/tweet?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/open-models/get_started_with_oss_maas_reasoning_open_ai_sdk.ipynb\" target=\"_blank\">\n",
        "  <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/5/5a/X_icon_2.svg\" alt=\"X logo\">\n",
        "</a>\n",
        "\n",
        "<a href=\"https://reddit.com/submit?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/open-models/get_started_with_oss_maas_reasoning_open_ai_sdk.ipynb\" target=\"_blank\">\n",
        "  <img width=\"20px\" src=\"https://redditinc.com/hubfs/Reddit%20Inc/Brand/Reddit_Logo.png\" alt=\"Reddit logo\">\n",
        "</a>\n",
        "\n",
        "<a href=\"https://www.facebook.com/sharer/sharer.php?u=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/open-models/get_started_with_oss_maas_reasoning_open_ai_sdk.ipynb\" target=\"_blank\">\n",
        "  <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/5/51/Facebook_f_logo_%282019%29.svg\" alt=\"Facebook logo\">\n",
        "</a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "da996843f0dc"
      },
      "source": [
        "| Author |\n",
        "| --- |\n",
        "| [Ivan Nardini](https://github.com/inardini)|"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "tvgnzT1CKxrO"
      },
      "source": [
        "## Overview\n",
        "\n",
        "This tutorial explains how to use reasoning capabilities with Model-as-a-Service (MaaS) models on Google Cloud Vertex AI. These models leverage vLLM's reasoning infrastructure to provide both reasoning steps and final conclusions in their outputs."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "61RBz8LLbxCR"
      },
      "source": [
        "## What is Reasoning in LLMs?\n",
        "\n",
        "Reasoning models like DeepSeek R1 are trained to go through a \"thinking process\" before providing an answer. Depending on the inference framework you use, they usually return:\n",
        "\n",
        "- **`reasoning_content`**: The internal reasoning steps that led to the conclusion  \n",
        "- **`content`**: The final answer or conclusion"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "q3GWbxFSDTLV"
      },
      "source": [
        "## Supported MaaS Models on Vertex AI\n",
        "\n",
        "Currently, Vertex AI supports the following reasoning-capable MaaS models:\n",
        "\n",
        "| Model | Model ID | Location | Reasoning Support |\n",
        "| :---- | :---- | :---- | :---- |\n",
        "| DeepSeek R1 | `deepseek-ai/deepseek-r1-0528-maas` | us-central1 | ✅ Full reasoning |\n",
        "| DeepSeek v3.1 | `deepseek-ai/deepseek-v3.1-maas` | us-west2 | ✅ With thinking parameter |\n",
        "| GPT-OSS 20B | `openai/gpt-oss-20b-maas` | us-central1 | ✅ Full reasoning |"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "No17Cw5hgx12"
      },
      "source": [
        "### Install required packages\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "tFy3H3aPgx12"
      },
      "outputs": [],
      "source": [
        "%pip install --upgrade --quiet openai"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dmWOrTJ3gx13"
      },
      "source": [
        "### Authenticate your notebook environment (Colab only)\n",
        "\n",
        "If you're running this notebook on Google Colab, run the cell below to authenticate your environment."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "NyKGtVQjgx13"
      },
      "outputs": [],
      "source": [
        "import sys\n",
        "\n",
        "if \"google.colab\" in sys.modules:\n",
        "    from google.colab import auth\n",
        "\n",
        "    auth.authenticate_user()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "DF4l8DTdWgPY"
      },
      "source": [
        "### Set Google Cloud project information\n",
        "\n",
        "To get started using Vertex AI, you must have an existing Google Cloud project and [enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com).\n",
        "\n",
        "Learn more about [setting up a project and a development environment](https://cloud.google.com/vertex-ai/docs/start/cloud-environment)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Nqwi-5ufWp_B"
      },
      "outputs": [],
      "source": [
        "# Use the environment variable if the user doesn't provide Project ID.\n",
        "import os\n",
        "\n",
        "# fmt: off\n",
        "PROJECT_ID = \"[your-project-id]\"  # @param {type: \"string\", placeholder: \"[your-project-id]\", isTemplate: true}\n",
        "# fmt: on\n",
        "if not PROJECT_ID or PROJECT_ID == \"[your-project-id]\":\n",
        "    PROJECT_ID = str(os.environ.get(\"GOOGLE_CLOUD_PROJECT\"))\n",
        "\n",
        "LOCATION = os.environ.get(\"GOOGLE_CLOUD_REGION\", \"global\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5303c05f7aa6"
      },
      "source": [
        "### Import libraries\n",
        "\n",
        "Let's import our dependencies. We're grabbing google.auth to handle the login and, of course, the `openai` library that we'll use to actually build and send our prompts."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "6fc324893334"
      },
      "outputs": [],
      "source": [
        "import openai\n",
        "from google.auth import default\n",
        "from google.auth.transport.requests import Request"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "B19k4HYgE1m7"
      },
      "source": [
        "### Set Up Authentication\n",
        "\n",
        "Here's where we actually grab the auth token. `default()` finds the credentials you provided earlier, and `credentials.refresh()` trades them in for a fresh, ready-to-use access token.\n",
        "\n",
        "This token is our ticket for accessing the Vertex AI API."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Jdh-25I7E728"
      },
      "outputs": [],
      "source": [
        "# Get default credentials\n",
        "credentials, project = default(\n",
        "    scopes=[\"https://www.googleapis.com/auth/cloud-platform\"]\n",
        ")\n",
        "request = Request()\n",
        "credentials.refresh(request)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "BJT35G4aF0or"
      },
      "source": [
        "## Basic Usage"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "L-hPeruXF6Ev"
      },
      "source": [
        "### Initialize the OpenAI Client\n",
        "\n",
        "We're creating an instance of the `openai` client and we're setting the `base_url` to our own Vertex AI endpoint. Then, for the `api_key`, we just pass in that Google Cloud access token we just generated. And just like that, the openai SDK is now a client for Vertex AI.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "jW3ZT-7LF5RU"
      },
      "outputs": [],
      "source": [
        "MODEL_LOCATION = \"us-central1\"\n",
        "\n",
        "# Configure the Vertex AI endpoint\n",
        "vertex_endpoint_url = f\"https://{MODEL_LOCATION}-aiplatform.googleapis.com/v1beta1/projects/{PROJECT_ID}/locations/{MODEL_LOCATION}/endpoints/openapi\"\n",
        "\n",
        "# Create OpenAI client with Vertex AI endpoint\n",
        "client = openai.OpenAI(\n",
        "    base_url=vertex_endpoint_url,\n",
        "    api_key=credentials.token,\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "TGqyPKuIHcVb"
      },
      "source": [
        "### Make a Request with Reasoning\n",
        "\n",
        "Time to ask our first question! We're calling the deepseek-r1 model and asking it to \"Think step by step.\"\n",
        "\n",
        "Check out the response. The model literally shows its work inside <think> tags before giving the final answer. This is great for debugging or for building apps where you want to show users how the AI got to its conclusion."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "CUWQl7DdHcKx"
      },
      "outputs": [],
      "source": [
        "response = client.chat.completions.create(\n",
        "    model=\"deepseek-ai/deepseek-r1-0528-maas\",\n",
        "    messages=[\n",
        "        {\"role\": \"system\", \"content\": \"You are a helpful assistant\"},\n",
        "        {\n",
        "            \"role\": \"user\",\n",
        "            \"content\": \"How many r's are in strawberry? Think step by step\",\n",
        "        },\n",
        "    ],\n",
        "    stream=False,\n",
        ")\n",
        "\n",
        "response"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "OQ52-Jswe-o1"
      },
      "source": [
        "As you saw, DeepSeek model gives us everything in one big string. It is up to you to unpack that. It's just some simple Python string-slicing to pull out the text between the `<think>` tags. This lets you separate the \"behind-the-scenes\" reasoning from the clean, final answer you'd show to a user.\n",
        "\n",
        "> **Note**: You will see later that, for GPT-OSS family, reasoning & final response are populate in `reasoning_content` and `content` respectively."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "7C5nVFCoe8eL"
      },
      "outputs": [],
      "source": [
        "response_text = response.choices[0].message.content\n",
        "\n",
        "start_tag = \"<think>\"\n",
        "end_tag = \"</think>\"\n",
        "\n",
        "start_index = response_text.find(start_tag)\n",
        "end_index = response_text.find(end_tag)\n",
        "\n",
        "reasoning_content = \"\"\n",
        "if start_index != -1 and end_index != -1 and start_index < end_index:\n",
        "    reasoning_content = response_text[start_index + len(start_tag) : end_index].strip()\n",
        "    print(\"Extracted Reasoning:\\n\", reasoning_content)\n",
        "else:\n",
        "    print(\"No reasoning content found in the expected format.\")\n",
        "\n",
        "# The rest of the content after </think>\n",
        "final_answer = response_text[end_index + len(end_tag) :].strip()\n",
        "print(\"\\nExtracted Final Answer:\\n\", final_answer)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "JN0Ws9hbISra"
      },
      "source": [
        "## Advanced Features"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "lMkKweOkIW-h"
      },
      "source": [
        "### Controlling Reasoning Behavior\n",
        "\n",
        "At this point, we know how the model can think but we can be more explicit about wanting it to think.\n",
        "\n",
        "To achieve that, we pass an `extra_body` parameter with `{\"thinking\": True}`. It's a good way to be sure the model knows you want to see its thought process.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "2nAMpsBAJWp-"
      },
      "source": [
        "#### For DeepSeek Models\n",
        "\n",
        "Use the `thinking` parameter to enable/disable reasoning."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "gFJJnvGQIuOM"
      },
      "outputs": [],
      "source": [
        "MODEL_LOCATION = \"us-west2\"\n",
        "\n",
        "# Configure the Vertex AI endpoint\n",
        "vertex_endpoint_url = (\n",
        "    f\"https://{MODEL_LOCATION}-aiplatform.googleapis.com/v1beta1/\"\n",
        "    f\"projects/{PROJECT_ID}/locations/{MODEL_LOCATION}/endpoints/openapi\"\n",
        ")\n",
        "\n",
        "# Create OpenAI client with Vertex AI endpoint\n",
        "client = openai.OpenAI(\n",
        "    base_url=vertex_endpoint_url,\n",
        "    api_key=credentials.token,\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "J2_BF-TfIhVT"
      },
      "outputs": [],
      "source": [
        "# Enable reasoning explicitly\n",
        "response = client.chat.completions.create(\n",
        "    model=\"deepseek-ai/deepseek-v3.1-maas\",\n",
        "    messages=[\n",
        "        {\"role\": \"system\", \"content\": \"You are a helpful assistant\"},\n",
        "        {\n",
        "            \"role\": \"user\",\n",
        "            \"content\": \"How many r's are in strawberry? Think step by step\",\n",
        "        },\n",
        "    ],\n",
        "    extra_body={\"chat_template_kwargs\": {\"thinking\": True}},\n",
        ")\n",
        "\n",
        "\n",
        "response"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HsgIXuQMI6TU"
      },
      "source": [
        "#### For GPT-OSS Models\n",
        "\n",
        "Now let's chat with the GPT-OSS model. This one is slightly different.  It has a `reasoning_effort` parameter you can set to control reasoning depth.\n",
        "\n",
        "Also the response object returns separated thoughts into a `reasoning_content` field and the final answer into content."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "CpaCUShdI-rx"
      },
      "outputs": [],
      "source": [
        "MODEL_LOCATION = \"us-central1\"\n",
        "\n",
        "# Configure the Vertex AI endpoint\n",
        "vertex_endpoint_url = (\n",
        "    f\"https://{MODEL_LOCATION}-aiplatform.googleapis.com/v1beta1/\"\n",
        "    f\"projects/{PROJECT_ID}/locations/{MODEL_LOCATION}/endpoints/openapi\"\n",
        ")\n",
        "\n",
        "# Create OpenAI client with Vertex AI endpoint\n",
        "client = openai.OpenAI(\n",
        "    base_url=vertex_endpoint_url,\n",
        "    api_key=credentials.token,\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "YK-beET3I-rx"
      },
      "outputs": [],
      "source": [
        "# Enable reasoning explicitly\n",
        "response = client.chat.completions.create(\n",
        "    model=\"openai/gpt-oss-20b-maas\",\n",
        "    messages=[\n",
        "        {\"role\": \"system\", \"content\": \"You are a helpful assistant\"},\n",
        "        {\n",
        "            \"role\": \"user\",\n",
        "            \"content\": \"How many r's are in strawberry? Think step by step\",\n",
        "        },\n",
        "    ],\n",
        "    reasoning_effort=\"high\",  # Options: \"low\", \"medium\", \"high\"\n",
        ")\n",
        "\n",
        "\n",
        "response"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "WLpUxvtTJaLT"
      },
      "source": [
        "### Streaming Responses with Reasoning\n",
        "\n",
        "By setting `stream=True`, you get the response back token-by-token.\n",
        "\n",
        "This example below loops through the chunks as they arrive and prints them out. You can see the model \"thinking\" in real-time as the `reasoning_content` streams in, followed by the final answer."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "IvSZ_yXjJa8n"
      },
      "outputs": [],
      "source": [
        "stream = client.chat.completions.create(\n",
        "    model=\"openai/gpt-oss-20b-maas\",\n",
        "    messages=[\n",
        "        {\"role\": \"system\", \"content\": \"You are a helpful assistant\"},\n",
        "        {\n",
        "            \"role\": \"user\",\n",
        "            \"content\": \"How many r's are in strawberry? Think step by step\",\n",
        "        },\n",
        "    ],\n",
        "    stream=True,\n",
        ")\n",
        "\n",
        "reasoning_content = \"\"\n",
        "final_content = \"\"\n",
        "\n",
        "for chunk in stream:\n",
        "    # Add a check for chunk.choices and chunk.choices[0]\n",
        "    if chunk.choices and chunk.choices[0].delta:\n",
        "        # Check for reasoning content\n",
        "        if hasattr(chunk.choices[0].delta, \"reasoning_content\"):\n",
        "            reasoning_chunk = chunk.choices[0].delta.reasoning_content\n",
        "            if reasoning_chunk:\n",
        "                reasoning_content += reasoning_chunk\n",
        "                print(f\"\\nThinking: {reasoning_chunk}\", end=\"\", flush=True)\n",
        "\n",
        "        # Check for final content\n",
        "        elif hasattr(chunk.choices[0].delta, \"content\"):\n",
        "            content_chunk = chunk.choices[0].delta.content\n",
        "            if content_chunk:\n",
        "                final_content += content_chunk\n",
        "                print(f\"\\nAnswer: {content_chunk}\", end=\"\", flush=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "uuyNSfO6LkOS"
      },
      "source": [
        "### Structured Output with Reasoning\n",
        "\n",
        "How many times have you asked an LLM for JSON and gotten back a broken string? With `guided_json`, you define a Pydantic schema, pass it to the model, and it's guaranteed to return valid JSON that matches that schema.\n",
        "\n",
        "And you still get the `reasoning_content` to see how it came up with the JSON fields and values.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "M-jCttlmLmUB"
      },
      "outputs": [],
      "source": [
        "from pydantic import BaseModel\n",
        "\n",
        "class Person(BaseModel):\n",
        "    name: str\n",
        "    age: int\n",
        "\n",
        "\n",
        "json_schema = Person.model_json_schema()\n",
        "\n",
        "response = client.chat.completions.create(\n",
        "    model=\"openai/gpt-oss-20b-maas\",\n",
        "    messages=[{\"role\": \"user\", \"content\": \"Generate a JSON with a person's details\"}],\n",
        "    extra_body={\"guided_json\": json_schema},\n",
        ")\n",
        "\n",
        "print(\"Reasoning:\", response.choices[0].message.reasoning_content)\n",
        "print(\"JSON Output:\", response.choices[0].message.content)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GvlKNgCMMCbW"
      },
      "source": [
        "## Complete Example: Comparing Models\n",
        "\n",
        "Let's wrap it up with a model showdown that brings everything together. It loops through all the models we've looked at, makes sure to set up the client for the correct region for each one, and asks them all the same question.\n",
        "\n",
        "It's a perfect template for running your own model evaluations to see which one works best for your specific use case."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "mOSIiE384Hg-"
      },
      "outputs": [],
      "source": [
        "# Test different models\n",
        "models = [\n",
        "    {\"id\": \"deepseek-ai/deepseek-r1-0528-maas\", \"location\": \"us-central1\"},\n",
        "    {\"id\": \"deepseek-ai/deepseek-v3.1-maas\", \"location\": \"us-west2\"},\n",
        "    {\"id\": \"openai/gpt-oss-20b-maas\", \"location\": \"us-central1\"},\n",
        "]\n",
        "\n",
        "question = \"What is 9.11 vs 9.8? Which is greater?\"\n",
        "\n",
        "for model_info in models:\n",
        "    # Create client for each model's location\n",
        "    vertex_endpoint_url = (\n",
        "        f\"https://{model_info['location']}-aiplatform.googleapis.com/v1beta1/\"\n",
        "        f\"projects/{PROJECT_ID}/locations/{model_info['location']}/endpoints/openapi\"\n",
        "    )\n",
        "\n",
        "    client = openai.OpenAI(\n",
        "        base_url=vertex_endpoint_url,\n",
        "        api_key=credentials.token,\n",
        "    )\n",
        "\n",
        "    # Make request\n",
        "    response = client.chat.completions.create(\n",
        "        model=model_info[\"id\"],\n",
        "        messages=[\n",
        "            {\"role\": \"system\", \"content\": \"You are a helpful assistant\"},\n",
        "            {\"role\": \"user\", \"content\": question},\n",
        "        ],\n",
        "        stream=False,\n",
        "    )\n",
        "\n",
        "    print(f\"\\n{'=' * 50}\")\n",
        "    print(f\"Model: {model_info['id']}\")\n",
        "    print(f\"{'=' * 50}\")\n",
        "\n",
        "    # Check if reasoning_content exists before accessing it\n",
        "    if (\n",
        "        hasattr(response.choices[0].message, \"reasoning_content\")\n",
        "        and response.choices[0].message.reasoning_content\n",
        "    ):\n",
        "        print(f\"Reasoning: {response.choices[0].message.reasoning_content[:200]}...\")\n",
        "    print(f\"Answer: {response.choices[0].message.content}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "B26hbgJnMeIq"
      },
      "source": [
        "## Best Practices"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "IwVE0xVP-ZxP"
      },
      "source": [
        "### Token Management\n",
        "\n",
        "- Reasoning content adds to token usage  \n",
        "- Monitor `response.usage` for token counts  \n",
        "- Consider disabling reasoning for simple queries"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "EkyQ-ZlE-eFf"
      },
      "source": [
        "### Error Handling\n",
        "\n",
        "```py\n",
        "try:\n",
        "    response = client.chat.completions.create(...)\n",
        "except Exception as e:\n",
        "    # Refresh token if expired\n",
        "    credentials.refresh(request)\n",
        "    client.api_key = credentials.token\n",
        "    response = client.chat.completions.create(...)\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gg-8cKWI-hoF"
      },
      "source": [
        "### Performance Optimization\n",
        "\n",
        "- Use streaming for long reasoning chains  \n",
        "- Cache credentials to avoid repeated authentication  \n",
        "- Choose appropriate model locations for latency"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hnzZiOyf-ks-"
      },
      "source": [
        "### 4. When to Use Reasoning\n",
        "\n",
        "✅ **Use reasoning for:**\n",
        "\n",
        "- Complex problem-solving  \n",
        "- Mathematical calculations  \n",
        "- Step-by-step analysis  \n",
        "- Debugging assistance\n",
        "\n",
        "❌ **Skip reasoning for:**\n",
        "\n",
        "- Simple factual queries  \n",
        "- Quick responses  \n",
        "- High-volume requests\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XmTCXYPKMYe2"
      },
      "source": [
        "## Conclusion\n",
        "\n",
        "MaaS models on Vertex AI with vLLM reasoning provide powerful capabilities for transparent AI decision-making. By understanding how to properly configure and use these models, you can build applications that not only provide answers but also explain their reasoning process.\n",
        "\n",
        "## Additional Resources\n",
        "\n",
        "- [Vertex AI Open models documentation](https://cloud.google.com/vertex-ai/generative-ai/docs/maas/use-open-models)  \n",
        "- [vLLM Reasoning Documentation](https://docs.vllm.ai/en/latest/serving/openai_compatible_server.html#reasoning-with-llms)  \n",
        "- [OpenAI Python SDK](https://github.com/openai/openai-python)\n"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "name": "get_started_with_oss_maas_reasoning_open_ai_sdk.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
