llm-vertexai-agent/llm_vertexai_agent.ipynb (510 lines of code) (raw):

{ "cells": [ { "cell_type": "markdown", "id": "_KqUrITrkw5S", "metadata": { "id": "_KqUrITrkw5S" }, "source": [ "## Vertex Agent Builder with Apigee\n", "\n", "<table align=\"left\">\n", " <td style=\"text-align: center\">\n", " <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/apigee-samples/blob/main/llm-vertexai-agent/llm_vertexai_agent.ipynb\">\n", " <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" 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%3A%2F%2Fraw.githubusercontent.com%2FGoogleCloudPlatform%2Fapigee-samples%2Fmain%2Fllm-vertexai-agent%2Fllm_vertexai_agent.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/apigee-samples/main/llm-vertexai-agent/llm_vertexai_agent.ipynb\">\n", " <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\"><br> Open in Workbench\n", " </a>\n", " </td>\n", " <td style=\"text-align: center\">\n", " <a href=\"https://github.com/GoogleCloudPlatform/apigee-samples/blob/main/llm-vertexai-agent/llm_vertexai_agent.ipynb\">\n", " <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\"><br> View on GitHub\n", " </a>\n", " </td>\n", "</table>\n", "<br />\n", "<br />\n", "<br />\n", "<br />\n", "\n", "This is a sample on how to deploy a sample Apigee proxy and configure it as a tool in Conversational Agents.\n", "\n", "![architecture](https://github.com/GoogleCloudPlatform/apigee-samples/blob/main/llm-vertexai-agent/images/arch.png?raw=1)\n", "\n", "## Setup\n", "\n", "Use the following GCP CloudShell tutorial. Follow the instructions to deploy the sample.\n", "\n", "[![Open in Cloud Shell](https://gstatic.com/cloudssh/images/open-btn.png)](https://ssh.cloud.google.com/cloudshell/open?cloudshell_git_repo=https://github.com/GoogleCloudPlatform/apigee-samples&cloudshell_git_branch=main&cloudshell_workspace=.&cloudshell_tutorial=llm-vertexai-agent/docs/cloudshell-tutorial.md)" ] }, { "cell_type": "markdown", "id": "3eccd5a5", "metadata": {}, "source": [ "### Pre-Requisites\n", "\n", "- In your GCP console, open [Vertex Agent Builder](https://console.cloud.google.com/gen-app-builder/start)\n", "- You must activate the Vertex AI Agent Builder service and accept the [Discovery Solutions data use terms](https://cloud.google.com/retail/data-use-terms)" ] }, { "cell_type": "markdown", "id": "79714ad3", "metadata": {}, "source": [ "### Install Dependencies" ] }, { "cell_type": "code", "execution_count": null, "id": "E1aMG7gl9McN", "metadata": { "id": "E1aMG7gl9McN", "tags": [] }, "outputs": [], "source": [ "#If you haven't already, make sure you install the `dfcx-scrapi` library\n", "!pip install dfcx-scrapi" ] }, { "cell_type": "markdown", "id": "3fd8953d", "metadata": {}, "source": [ "### Authenticate your notebook environment (Colab only)\n", "If you are running this notebook on Google Colab, run the following cell to authenticate your environment. This step is not required if you are using Vertex AI Workbench." ] }, { "cell_type": "code", "execution_count": null, "id": "c1c82574", "metadata": {}, "outputs": [], "source": [ "import sys\n", "\n", "# Colab Auth needed to call Client Endpoints (i.e. vertexai)\n", "if \"google.colab\" in sys.modules:\n", " # Authenticate user to Google Cloud\n", " from google.colab import auth as google_auth\n", " google_auth.authenticate_user()" ] }, { "cell_type": "markdown", "id": "2Do-9w7Pk5G1", "metadata": { "id": "2Do-9w7Pk5G1" }, "source": [ "### Initialize Variables" ] }, { "cell_type": "code", "execution_count": 3, "id": "AMz0hBjsfC7u", "metadata": { "id": "AMz0hBjsfC7u" }, "outputs": [], "source": [ "PROJECT_ID = \"\" # @param {type:\"string\"}\n", "REGION = \"global\" # @param {type:\"string\"}\n", "APIGEE_HOST = \"\" # @param {type:\"string\"}\n", "APIKEY = \"\" # @param {type:\"string\"}" ] }, { "cell_type": "markdown", "id": "XEE4QtmXk_WB", "metadata": { "id": "XEE4QtmXk_WB" }, "source": [ "## Create the agent" ] }, { "cell_type": "code", "execution_count": null, "id": "zh2IYoG8fHhU", "metadata": { "id": "zh2IYoG8fHhU" }, "outputs": [], "source": [ "from dfcx_scrapi.core.agents import Agents\n", "from dfcx_scrapi.core.sessions import Sessions\n", "\n", "AGENT_NAME = \"Apigee AI AGENT\"\n", "\n", "a = Agents()\n", "agent = a.create_agent(\n", " project_id=PROJECT_ID,\n", " display_name=AGENT_NAME,\n", " gcp_region=REGION,\n", " playbook_agent=True\n", ")\n", "\n", "panel = \"(playbooks/00000000-0000-0000-0000-000000000000/basics//right-panel:simulator)\"\n", "print(f\"AGENT LINK: https://vertexaiconversation.cloud.google.com/{agent.name}/{panel}\")\n", "\n", "s = Sessions()\n", "\n", "session_id = s.build_session_id(agent.name)\n", "session_id" ] }, { "cell_type": "markdown", "id": "JY2-UXBSlQKZ", "metadata": { "id": "JY2-UXBSlQKZ" }, "source": [ "### Check for default playbook" ] }, { "cell_type": "code", "execution_count": null, "id": "xfq8LS9ggVzn", "metadata": { "id": "xfq8LS9ggVzn" }, "outputs": [], "source": [ "from dfcx_scrapi.core.playbooks import Playbooks\n", "\n", "p = Playbooks(agent.name)\n", "\n", "playbooks_map = p.get_playbooks_map(agent.name, reverse=True)\n", "playbook = p.get_playbook(playbooks_map[\"Default Generative Playbook\"])\n", "print(f\"GOAL: {playbook.goal}\")\n", "print(f\"INSTRUCTIONS: {playbook.instruction}\")\n" ] }, { "cell_type": "markdown", "id": "V5w8yuVvlpRv", "metadata": { "id": "V5w8yuVvlpRv" }, "source": [ "## Create Tool" ] }, { "cell_type": "code", "execution_count": 6, "id": "FV21dUEQpU_S", "metadata": { "id": "FV21dUEQpU_S" }, "outputs": [], "source": [ "get_products = f\"\"\"\n", "openapi: 3.0.1\n", "info:\n", " title: Cymbal Products Catalog\n", " description: Product service\n", "\n", " termsOfService: https://cymbal.com/terms\n", " contact:\n", " email: someteam@cymbal.com\n", " license:\n", " name: Apache 2.0\n", " url: http://www.apache.org/licenses/LICENSE-2.0.html\n", " version: 1.0.0\n", "servers:\n", " - url: https://{APIGEE_HOST}/v1/samples/llm-vertexai-agent\n", "tags:\n", " - name: products\n", " description: Products\n", "paths:\n", " '/products':\n", " get:\n", " tags:\n", " - products\n", " summary: Get Products\n", " description: Get Products\n", " operationId: get-all-products\n", " responses:\n", " '200':\n", " description: successful operation\n", " content:\n", " application/json:\n", " schema:\n", " $ref: '#/components/schemas/Products'\n", " '400':\n", " description: Invalid request supplied\n", " content:\n", " application/json:\n", " schema:\n", " $ref: '#/components/schemas/ErrorResponse'\n", " '401':\n", " description: Unauthorized\n", " content:\n", " application/json:\n", " schema:\n", " $ref: '#/components/schemas/ErrorResponse'\n", " '403':\n", " description: Forbidden\n", " content:\n", " application/json:\n", " schema:\n", " $ref: '#/components/schemas/ErrorResponse'\n", " '404':\n", " description: Not Found\n", " content:\n", " application/json:\n", " schema:\n", " $ref: '#/components/schemas/ErrorResponse'\n", " '429':\n", " description: Not Found\n", " content:\n", " application/json:\n", " schema:\n", " $ref: '#/components/schemas/ErrorResponse'\n", " security:\n", " - api_key: []\n", " '/products/{{id}}':\n", " get:\n", " tags:\n", " - products\n", " summary: Get a Product\n", " description: Get a Product\n", " operationId: get-product\n", " parameters:\n", " - name: id\n", " in: path\n", " description: ProductId\n", " required: true\n", " schema:\n", " type: integer\n", " example: 1\n", " responses:\n", " '200':\n", " description: successful operation\n", " content:\n", " application/json:\n", " schema:\n", " $ref: '#/components/schemas/Products'\n", " '400':\n", " description: Invalid request supplied\n", " content:\n", " application/json:\n", " schema:\n", " $ref: '#/components/schemas/ErrorResponse'\n", " '401':\n", " description: Unauthorized\n", " content:\n", " application/json:\n", " schema:\n", " $ref: '#/components/schemas/ErrorResponse'\n", " '403':\n", " description: Forbidden\n", " content:\n", " application/json:\n", " schema:\n", " $ref: '#/components/schemas/ErrorResponse'\n", " '404':\n", " description: Not Found\n", " content:\n", " application/json:\n", " schema:\n", " $ref: '#/components/schemas/ErrorResponse'\n", " '429':\n", " description: Not Found\n", " content:\n", " application/json:\n", " schema:\n", " $ref: '#/components/schemas/ErrorResponse'\n", " security:\n", " - api_key: []\n", "components:\n", " schemas:\n", " Products:\n", " type: object\n", " properties:\n", " products:\n", " type: array\n", " items:\n", " $ref: '#/components/schemas/Product'\n", " Product:\n", " type: object\n", " properties:\n", " id:\n", " type: integer\n", " example: 1\n", " name:\n", " type: string\n", " example: Daily Sunglasses\n", " description:\n", " type: string\n", " example: \"Seriously coolMen's Daily Sunglasses for only $19.90\"\n", " categories:\n", " type: array\n", " items:\n", " type: string\n", " example: \"Style\"\n", " price:\n", " type: number\n", " example: 19\n", " ErrorResponse:\n", " type: object\n", " properties:\n", " status:\n", " type: string\n", " example: Forbidden\n", " message:\n", " type: string\n", " example: Forbidden\n", " securitySchemes:\n", " api_key:\n", " type: apiKey\n", " name: x-apikey\n", " in: header\n", "\"\"\"" ] }, { "cell_type": "code", "execution_count": 7, "id": "wMsyWh8lmLhB", "metadata": { "id": "wMsyWh8lmLhB" }, "outputs": [], "source": [ "from dfcx_scrapi.core.tools import Tools\n", "\n", "t = Tools()\n", "TOOL_NAME = \"cymbal-products-catalog\"\n", "# get_products\n", "get_products_tool = t.build_open_api_tool(\n", " display_name = TOOL_NAME,\n", " spec = get_products,\n", " description = \"Cymbal Products Catalog\",\n", " )\n", "\n", "get_products_tool.open_api_spec.authentication.api_key_config.key_name=\"x-apikey\"\n", "get_products_tool.open_api_spec.authentication.api_key_config.api_key=APIKEY\n", "get_products_tool.open_api_spec.authentication.api_key_config.request_location=\"HEADER\"\n", "\n", "products_tool = t.create_tool(agent.name, get_products_tool)" ] }, { "cell_type": "markdown", "id": "jNaRTQAQAJS_", "metadata": { "id": "jNaRTQAQAJS_" }, "source": [ "## Update playbook" ] }, { "cell_type": "code", "execution_count": null, "id": "G7ZlNZBzANCJ", "metadata": { "id": "G7ZlNZBzANCJ" }, "outputs": [], "source": [ "playbook = p.update_playbook(\n", " playbooks_map[\"Default Generative Playbook\"],\n", " referenced_tools=[products_tool.name],\n", " goal=\"You are a friendly online boutique service center agent.\\nYour job is to answer any product related questions\",\n", " instructions=[\"Greet the users, then ask how you can help them today.\",\n", " \"If the user asks about products or to list them, use the ${TOOL:\"+TOOL_NAME+\"} to fetch the products\",\n", " \"If the user requests help looking for something, query the ${TOOL:\"+TOOL_NAME+\"} to answer the product questions\"]\n", " )\n", "\n", "print(f\"GOAL: {playbook.goal}\")\n", "print(f\"INSTRUCTIONS: {playbook.instruction}\")" ] }, { "cell_type": "markdown", "id": "g-QnqbhbBs9F", "metadata": { "id": "g-QnqbhbBs9F" }, "source": [ "## Test the Agent\n", "\n", "Lets ask the agent some questions about the product to see if it is able to fetch the information from the API" ] }, { "cell_type": "code", "execution_count": null, "id": "L2ufKdwFBv_l", "metadata": { "id": "L2ufKdwFBv_l" }, "outputs": [], "source": [ "session_id = s.build_session_id(agent.name)\n", "\n", "conversation = [\n", " \"List all products\",\n", " \"Tell me more about the sunglasses.\",\n", " \"How much is the mug?\",\n", " \"What are the product categories?\",\n", " \"What color is the interior of the mug?\"]\n", "\n", "i = 1\n", "for utterance in conversation:\n", " print(f\"\\n--- TURN {i} --- \\n\")\n", " res = s.detect_intent(agent.name, session_id, utterance)\n", " s.parse_result(res)\n", " i+=1" ] } ], "metadata": { "colab": { "name": "llm-agent", "provenance": [] }, "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.10.10" } }, "nbformat": 4, "nbformat_minor": 5 }