diff --git a/authors.yaml b/authors.yaml index 720beb07..78eed86f 100644 --- a/authors.yaml +++ b/authors.yaml @@ -156,3 +156,7 @@ lxing-oai: name: "Luke Xing" website: "https://www.linkedin.com/in/lukexing/" avatar: "https://avatars.githubusercontent.com/u/176698727" + +gladstone-openai: + name: "Kevin Gladstone" + avatar: "https://avatars.githubusercontent.com/u/149190645" diff --git a/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb b/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb new file mode 100644 index 00000000..49e39ebc --- /dev/null +++ b/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb @@ -0,0 +1,422 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# GPT Actions - Snowflake direct\n", + "## Introduction" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This page provides an instruction & guide for developers building a GPT Action for a specific application. Before you proceed, make sure to first familiarize yourself with the following information:\n", + "\n", + "\n", + "\n", + "* [Introduction to GPT Actions](https://platform.openai.com/docs/actions)\n", + "* [Introduction to GPT Actions Library](https://platform.openai.com/docs/actions/actions-library)\n", + "* [Example of Building a GPT Action from Scratch](https://platform.openai.com/docs/actions/getting-started)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This particular GPT Action provides an overview of how to connect to a Snowflake Data Warehouse. This Action takes a user’s question, scans the relevant tables to gather the data schema, then writes a SQL query to answer the user’s question.\n", + "\n", + "Note: This cookbook return back a [ResultSet SQL statement](https://docs.snowflake.com/en/developer-guide/sql-api/handling-responses#getting-the-data-from-the-results), rather than the full result that is not limited by GPT Actions application/json payload limit. For production and advanced use-case, a middleware is required to return back a CSV file. You can follow instructions in the [GPT Actions - Snowflake Middleware cookbook](../gpt_action_snowflake_middleware) to implement this flow instead." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Value + Example Business Use Cases" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Value: Users can now leverage ChatGPT's natural language capability to connect directly to Snowflake’s Data Warehouse..\n", + "\n", + "Example Use Cases:\n", + "\n", + "\n", + "\n", + "* Data scientists can connect to tables and run data analyses using ChatGPT's Data Analysis\n", + "* Citizen data users can ask basic questions of their transactional data\n", + "* Users gain more visibility into their data & potential anomalies" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Application Information" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Application Key Links" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Check out these links from the application before you get started:\n", + "\n", + "* Application Website: [https://app.snowflake.com/](https://app.snowflake.com/)\n", + "* Application API Documentation: [https://docs.snowflake.com/en/developer-guide/sql-api/intro](https://docs.snowflake.com/en/developer-guide/sql-api/intro)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Application Prerequisites" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before you get started, make sure you go through the following steps in your application environment:\n", + "\n", + "* Provision a Snowflake Data Warehouse\n", + "* Ensure that the user authenticating into Snowflake via ChatGPT has access to the database, schemas, and tables with the necessary role" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ChatGPT Steps" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### Custom GPT Instructions\n", + "\n", + "Once you've created a Custom GPT, copy the text below in the Instructions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "plaintext" + } + }, + "outputs": [], + "source": [ + "**Context**: You are an expert at writing Snowflake SQL queries. A user is going to ask you a question. \n", + "\n", + "**Instructions**:\n", + "1. No matter the user's question, start by running `runQuery` operation using this query: \"SELECT column_name, table_name, data_type, comment FROM `{database}.INFORMATION_SCHEMA.COLUMNS`\" \n", + "-- Assume warehouse = \"\", database = \"\", unless the user provides different values \n", + "2. Convert the user's question into a SQL statement that leverages the step above and run the `runQuery` operation on that SQL statement to confirm the query works. Add a limit of 100 rows\n", + "3. Now remove the limit of 100 rows and return back the query for the user to see\n", + "4. Use the role when querying Snowflake\n", + "5. Run each step in sequence. Explain what you are doing in a few sentences, run the action, and then explain what you learned. This will help the user understand the reason behind your workflow. \n", + "\n", + "**Additional Notes**: If the user says \"Let's get started\", explain that the user can provide a project or dataset, along with a question they want answered. If the user has no ideas, suggest that we have a sample flights dataset they can query - ask if they want you to query that" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### OpenAPI Schema\n", + "\n", + "Once you've created a Custom GPT, copy the text below in the Actions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "yaml" + } + }, + "outputs": [], + "source": [ + "openapi: 3.1.0\n", + "info:\n", + " title: Snowflake Statements API\n", + " version: 1.0.0\n", + " description: API for executing statements in Snowflake with specific warehouse and role settings.\n", + "servers:\n", + " - url: 'https://...snowflakecomputing.com/api/v2'\n", + "\n", + "\n", + "paths:\n", + " /statements:\n", + " post:\n", + " summary: Execute a SQL statement in Snowflake\n", + " description: This endpoint allows users to execute a SQL statement in Snowflake, specifying the warehouse and roles to use.\n", + " operationId: runQuery\n", + " tags:\n", + " - Statements\n", + " requestBody:\n", + " required: true\n", + " content:\n", + " application/json:\n", + " schema:\n", + " type: object\n", + " properties:\n", + " warehouse:\n", + " type: string\n", + " description: The name of the Snowflake warehouse to use for the statement execution.\n", + " role:\n", + " type: string\n", + " description: The Snowflake role to assume for the statement execution.\n", + " statement:\n", + " type: string\n", + " description: The SQL statement to execute.\n", + " required:\n", + " - warehouse\n", + " - role\n", + " - statement\n", + " responses:\n", + " '200':\n", + " description: Successful execution of the SQL statement.\n", + " content:\n", + " application/json:\n", + " schema:\n", + " type: object\n", + " properties:\n", + " status:\n", + " type: string\n", + " data:\n", + " type: object\n", + " additionalProperties: true\n", + " '400':\n", + " description: Bad request, e.g., invalid SQL statement or missing parameters.\n", + " '401':\n", + " description: Authentication error, invalid API credentials.\n", + " '500':\n", + " description: Internal server error." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Authentication Instructions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Pre-Action Steps" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before you set up authentication in ChatGPT, please take the following steps in the application." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* Review the Snowflake OAuth Overview: [https://docs.snowflake.com/en/user-guide/oauth-snowflake-overview](https://docs.snowflake.com/en/user-guide/oauth-snowflake-overview)\n", + "* Go to the Snowflake Worksheets\n", + "* Create new OAuth credentials through a [Security Integration](https://docs.snowflake.com/en/sql-reference/sql/create-security-integration-oauth-snowflake) - you will need a new one for each OAuth app/custom GPT since Snowflake Redirect URIs are 1-1 mapped to Security Integrations\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "yaml" + } + }, + "outputs": [], + "source": [ + "CREATE SECURITY INTEGRATION CHATGPT_INTEGRATION\n", + " TYPE = OAUTH\n", + " ENABLED = TRUE\n", + " OAUTH_CLIENT = CUSTOM\n", + " OAUTH_CLIENT_TYPE = 'CONFIDENTIAL'\n", + " OAUTH_REDIRECT_URI = 'https://oauth.pstmn.io/v1/callback' --- // this is a temporary value while testing your integration. You will replace this with the value your GPT provides\n", + " OAUTH_ISSUE_REFRESH_TOKENS = TRUE\n", + " OAUTH_REFRESH_TOKEN_VALIDITY = 7776000;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "* Retrieve your OAuth Client ID, Auth URL, and Token URL\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "yaml" + } + }, + "outputs": [], + "source": [ + "DESCRIBE SECURITY INTEGRATION CHATGPT_INTEGRATION;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "You’ll find the required information in these 3 columns:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "* Retrieve your OAuth Client Secret\n", + "\n", + "You’ll find the Client Secret in OAUTH_CLIENT_SECRET.\n", + "\n", + "You’re now set to test your action in Postman. Once you get a successful API response there, you can proceed with your GPT Action." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### In ChatGPT" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In ChatGPT, click on \"Authentication\" and choose \"OAuth\". Enter in the information below.\n", + "\n", + "* Client ID: use Client ID from steps above\n", + "* Client Secret: use Client Secret from steps above\n", + "* Authorization URL: use Authorization Endpoint from steps above\n", + "* Token URL: use Token Endpoint from steps above\n", + "* Scope: <empty>*\n", + "* Token: Default (POST)\n", + "\n", + "*Snowflake scopes pass the role, but you’ll notice the action itself also specifies the role as a parameter in runQuery, so the Scope is unnecessary. You may elect to pass roles in the scope instead of the action parameters if it makes more sense for your GPT." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Post-Action Steps" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "Once you've set up authentication in ChatGPT, follow the steps below in the application to finalize the Action.\n", + "\n", + "* Copy the callback URL from the GPT Action\n", + "* Update the Redirect URI in your Security Integration to the callback URL provided in ChatGPT.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "yaml" + } + }, + "outputs": [], + "source": [ + "ALTER SECURITY INTEGRATION CHATGPT_INTEGRATION_DEV SET OAUTH_REDIRECT_URI='https://chat.openai.com/aip//oauth/callback';" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### FAQ & Troubleshooting" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "* _Callback URL Error:_ If you get a callback URL error in ChatGPT, pay close attention to the Post-Action Steps above. You need to add the callback URL directly into your Security Integration for the action to authenticate correctly\n", + "* _Schema calls the wrong warehouse or database:_ If ChatGPT calls the wrong warehouse or database, consider updating your instructions to make it more explicit either (a) which warehouse / database should be called or (b) to require the user provide those exact details before it runs the query\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "_Are there integrations that you’d like us to prioritize? Are there errors in our integrations? File a PR or issue in our github, and we’ll take a look._\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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": 4 +} diff --git a/images/chatgpt/snowflake_direct_oauth.png b/images/chatgpt/snowflake_direct_oauth.png new file mode 100644 index 00000000..cc671428 Binary files /dev/null and b/images/chatgpt/snowflake_direct_oauth.png differ diff --git a/registry.yaml b/registry.yaml index 8ff8f3d2..f69e56f3 100644 --- a/registry.yaml +++ b/registry.yaml @@ -1541,3 +1541,12 @@ tags: - gpt-actions-library - chatgpt + +- title: GPT Actions library - Snowflake Direct + path: examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb + date: 2024-08-13 + authors: + - gladstone-openai + tags: + - gpt-actions-library + - chatgpt