mirror of
https://github.com/james-m-jordan/openai-cookbook.git
synced 2025-05-09 19:32:38 +00:00
688 lines
23 KiB
Plaintext
688 lines
23 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# GPT Action Library: Gmail"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## 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",
|
||
"- [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 GPT Action provides an overview of how to connect to Google Gmail, Google’s Private & Secure Email for Personal or Business. This Action is connected to the Google Gmail APIs that can read, send, list, and draft emails in the authorized account. "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Value + Example Business Use Cases"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"**Value**: The Gmail GPT will serve as a powerful tool to streamline communication processes, improve customer engagement, and optimize resource allocation.\n",
|
||
"\n",
|
||
"**Example Use Cases**: \n",
|
||
"- Manage internal communications by summarizing lengthy emails and drafting responses based on previous email threads.\n",
|
||
"- Support agents can provide customers with instant responses adhering to a company’s communication guidelines, tone, and style.\n",
|
||
"- Reference other GPTs , such as a data analsys GPT, and then ask for a draft/send of the consolidated analysis through email communication."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Application Information"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Application Key Links"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Check out these links from the application before you get started:\n",
|
||
"- Application Website: https://mail.google.com/mail/u/0/#inbox\n",
|
||
"- Application API Documentation: https://developers.google.com/gmail/api/guides"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Application Prerequisites"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Before you get started, make sure you’ve a Google Cloud account and that the Gmail API is enabled:\n",
|
||
"- Set up a Google Cloud project\n",
|
||
"- Enable Gmail API from Google API Library\n",
|
||
"- If application’s “Publishing Status” is “Testing”, ensure users are added to your application"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## ChatGPT Steps"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Custom GPT Instructions "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"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**\n",
|
||
"Act as an email assistant designed to enhance user interaction with emails in various ways. This GPT can assist with productivity by summarizing emails/threads, identifying next steps/follow-ups, drafting or sending pre-written responses, and programmatically interacting with third-party tools (e.g., Notion to-dos, Slack channel summaries, data extraction for responses). This GPT has full scope access to the GMAIL OAuth 2.0 API, capable of reading, composing, sending, and permanently deleting emails from Gmail.\n",
|
||
"\n",
|
||
"**Instructions**\n",
|
||
"- Always conclude an email by signing off with logged in user's name, unless otherwise stated.\n",
|
||
"- Verify that the email data is correctly encoded in the required format (e.g., base64 for the message body).\n",
|
||
"- Email Encoding Process: 1\\ Construct the email message in RFC 2822 format. 2\\ Base64 encode the email message. 3\\Send the encoded message using the API.\n",
|
||
"- If not specified, sign all emails with the user name.\n",
|
||
"- API Usage: After answering the user's question, do not call the Google API again until another question is asked.\n",
|
||
"- All emails created, draft or sent, should be in plain text.\n",
|
||
"- Ensure that the email format is clean and is formatted as if someone sent the email from their own inbox. Once a draft is created or email sent, display a message to the user confirming that the draft is ready or the email is sent.\n",
|
||
"- Check that the \"to\" email address is valid and in the correct format. It should be in the format \"recipient@example.com\". \n",
|
||
"- Only provide summaries of existing emails; do not fabricate email content.\n",
|
||
"- Professionalism: Behave professionally, providing clear and concise responses.\n",
|
||
"- Clarification: Ask for clarification when needed to ensure accuracy and completeness in fulfilling user requests.\n",
|
||
"- Privacy and Security: Respect user privacy and handle all data securely.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### OpenAPI Schema "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"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",
|
||
"\n",
|
||
"info:\n",
|
||
" title: Gmail Email API\n",
|
||
" version: 1.0.0\n",
|
||
" description: API to read, write, and send emails in a Gmail account.\n",
|
||
"\n",
|
||
"servers:\n",
|
||
" - url: https://gmail.googleapis.com\n",
|
||
"\n",
|
||
"paths:\n",
|
||
" /gmail/v1/users/{userId}/messages:\n",
|
||
" get:\n",
|
||
" summary: List All Emails\n",
|
||
" description: Lists all the emails in the user's mailbox.\n",
|
||
" operationId: listAllEmails\n",
|
||
" parameters:\n",
|
||
" - name: userId\n",
|
||
" in: path\n",
|
||
" required: true\n",
|
||
" schema:\n",
|
||
" type: string\n",
|
||
" description: The user's email address. Use \"me\" to indicate the authenticated user.\n",
|
||
" - name: q\n",
|
||
" in: query\n",
|
||
" schema:\n",
|
||
" type: string\n",
|
||
" description: Query string to filter messages (optional).\n",
|
||
" - name: pageToken\n",
|
||
" in: query\n",
|
||
" schema:\n",
|
||
" type: string\n",
|
||
" description: Token to retrieve a specific page of results in the list.\n",
|
||
" - name: maxResults\n",
|
||
" in: query\n",
|
||
" schema:\n",
|
||
" type: integer\n",
|
||
" format: int32\n",
|
||
" description: Maximum number of messages to return.\n",
|
||
" responses:\n",
|
||
" '200':\n",
|
||
" description: Successful response\n",
|
||
" content:\n",
|
||
" application/json:\n",
|
||
" schema:\n",
|
||
" $ref: '#/components/schemas/MessageList'\n",
|
||
" '400':\n",
|
||
" description: Bad Request\n",
|
||
" '401':\n",
|
||
" description: Unauthorized\n",
|
||
" '403':\n",
|
||
" description: Forbidden\n",
|
||
" '404':\n",
|
||
" description: Not Found\n",
|
||
" '500':\n",
|
||
" description: Internal Server Error\n",
|
||
"\n",
|
||
" /gmail/v1/users/{userId}/messages/send:\n",
|
||
" post:\n",
|
||
" summary: Send Email\n",
|
||
" description: Sends a new email.\n",
|
||
" operationId: sendEmail\n",
|
||
" parameters:\n",
|
||
" - name: userId\n",
|
||
" in: path\n",
|
||
" required: true\n",
|
||
" schema:\n",
|
||
" type: string\n",
|
||
" description: The user's email address. Use \"me\" to indicate the authenticated user.\n",
|
||
" requestBody:\n",
|
||
" required: true\n",
|
||
" content:\n",
|
||
" application/json:\n",
|
||
" schema:\n",
|
||
" $ref: '#/components/schemas/Message'\n",
|
||
" responses:\n",
|
||
" '200':\n",
|
||
" description: Email sent successfully\n",
|
||
" content:\n",
|
||
" application/json:\n",
|
||
" schema:\n",
|
||
" $ref: '#/components/schemas/Message'\n",
|
||
" '400':\n",
|
||
" description: Bad Request\n",
|
||
" '401':\n",
|
||
" description: Unauthorized\n",
|
||
" '403':\n",
|
||
" description: Forbidden\n",
|
||
" '500':\n",
|
||
" description: Internal Server Error\n",
|
||
"\n",
|
||
" /gmail/v1/users/{userId}/messages/{id}:\n",
|
||
" get:\n",
|
||
" summary: Read Email\n",
|
||
" description: Gets the full email content including headers and body.\n",
|
||
" operationId: readEmail\n",
|
||
" parameters:\n",
|
||
" - name: userId\n",
|
||
" in: path\n",
|
||
" required: true\n",
|
||
" schema:\n",
|
||
" type: string\n",
|
||
" description: The user's email address. Use \"me\" to indicate the authenticated user.\n",
|
||
" - name: id\n",
|
||
" in: path\n",
|
||
" required: true\n",
|
||
" schema:\n",
|
||
" type: string\n",
|
||
" description: The ID of the email to retrieve.\n",
|
||
" responses:\n",
|
||
" '200':\n",
|
||
" description: Successful response\n",
|
||
" content:\n",
|
||
" application/json:\n",
|
||
" schema:\n",
|
||
" $ref: '#/components/schemas/FullMessage'\n",
|
||
" '400':\n",
|
||
" description: Bad Request\n",
|
||
" '401':\n",
|
||
" description: Unauthorized\n",
|
||
" '403':\n",
|
||
" description: Forbidden\n",
|
||
" '404':\n",
|
||
" description: Not Found\n",
|
||
" '500':\n",
|
||
" description: Internal Server Error\n",
|
||
"\n",
|
||
" /gmail/v1/users/{userId}/messages/{id}/modify:\n",
|
||
" post:\n",
|
||
" summary: Modify Label\n",
|
||
" description: Modify labels of an email.\n",
|
||
" operationId: modifyLabels\n",
|
||
" parameters:\n",
|
||
" - name: userId\n",
|
||
" in: path\n",
|
||
" required: true\n",
|
||
" schema:\n",
|
||
" type: string\n",
|
||
" description: The user's email address. Use \"me\" to indicate the authenticated user.\n",
|
||
" - name: id\n",
|
||
" in: path\n",
|
||
" required: true\n",
|
||
" schema:\n",
|
||
" type: string\n",
|
||
" description: The ID of the email to change labels.\n",
|
||
" requestBody:\n",
|
||
" required: true\n",
|
||
" content:\n",
|
||
" application/json:\n",
|
||
" schema:\n",
|
||
" $ref: '#/components/schemas/LabelModification'\n",
|
||
" responses:\n",
|
||
" '200':\n",
|
||
" description: Labels modified successfully\n",
|
||
" content:\n",
|
||
" application/json:\n",
|
||
" schema:\n",
|
||
" $ref: '#/components/schemas/Message'\n",
|
||
" '400':\n",
|
||
" description: Bad Request\n",
|
||
" '401':\n",
|
||
" description: Unauthorized\n",
|
||
" '403':\n",
|
||
" description: Forbidden\n",
|
||
" '500':\n",
|
||
" description: Internal Server Error\n",
|
||
"\n",
|
||
" /gmail/v1/users/{userId}/drafts:\n",
|
||
" post:\n",
|
||
" summary: Create Draft\n",
|
||
" description: Creates a new email draft.\n",
|
||
" operationId: createDraft\n",
|
||
" parameters:\n",
|
||
" - name: userId\n",
|
||
" in: path\n",
|
||
" required: true\n",
|
||
" schema:\n",
|
||
" type: string\n",
|
||
" description: The user's email address. Use \"me\" to indicate the authenticated user.\n",
|
||
" requestBody:\n",
|
||
" required: true\n",
|
||
" content:\n",
|
||
" application/json:\n",
|
||
" schema:\n",
|
||
" $ref: '#/components/schemas/Draft'\n",
|
||
" responses:\n",
|
||
" '200':\n",
|
||
" description: Draft created successfully\n",
|
||
" content:\n",
|
||
" application/json:\n",
|
||
" schema:\n",
|
||
" $ref: '#/components/schemas/Draft'\n",
|
||
" '400':\n",
|
||
" description: Bad Request\n",
|
||
" '401':\n",
|
||
" description: Unauthorized\n",
|
||
" '403':\n",
|
||
" description: Forbidden\n",
|
||
" '500':\n",
|
||
" description: Internal Server Error\n",
|
||
"\n",
|
||
" /gmail/v1/users/{userId}/drafts/send:\n",
|
||
" post:\n",
|
||
" summary: Send Draft\n",
|
||
" description: Sends an existing email draft.\n",
|
||
" operationId: sendDraft\n",
|
||
" parameters:\n",
|
||
" - name: userId\n",
|
||
" in: path\n",
|
||
" required: true\n",
|
||
" schema:\n",
|
||
" type: string\n",
|
||
" description: The user's email address. Use \"me\" to indicate the authenticated user.\n",
|
||
" requestBody:\n",
|
||
" required: true\n",
|
||
" content:\n",
|
||
" application/json:\n",
|
||
" schema:\n",
|
||
" $ref: '#/components/schemas/SendDraftRequest'\n",
|
||
" responses:\n",
|
||
" '200':\n",
|
||
" description: Draft sent successfully\n",
|
||
" content:\n",
|
||
" application/json:\n",
|
||
" schema:\n",
|
||
" $ref: '#/components/schemas/Message'\n",
|
||
" '400':\n",
|
||
" description: Bad Request\n",
|
||
" '401':\n",
|
||
" description: Unauthorized\n",
|
||
" '403':\n",
|
||
" description: Forbidden\n",
|
||
" '500':\n",
|
||
" description: Internal Server Error\n",
|
||
"\n",
|
||
"components:\n",
|
||
" schemas:\n",
|
||
" MessageList:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" messages:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" $ref: '#/components/schemas/Message'\n",
|
||
" nextPageToken:\n",
|
||
" type: string\n",
|
||
"\n",
|
||
" Message:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" id:\n",
|
||
" type: string\n",
|
||
" threadId:\n",
|
||
" type: string\n",
|
||
" labelIds:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: string\n",
|
||
" addLabelIds:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: string\n",
|
||
" removeLabelIds:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: string\n",
|
||
" snippet:\n",
|
||
" type: string\n",
|
||
" raw:\n",
|
||
" type: string\n",
|
||
" format: byte\n",
|
||
" description: The entire email message in an RFC 2822 formatted and base64url encoded string.\n",
|
||
"\n",
|
||
" FullMessage:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" id:\n",
|
||
" type: string\n",
|
||
" threadId:\n",
|
||
" type: string\n",
|
||
" labelIds:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: string\n",
|
||
" snippet:\n",
|
||
" type: string\n",
|
||
" payload:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" headers:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" name:\n",
|
||
" type: string\n",
|
||
" value:\n",
|
||
" type: string\n",
|
||
" parts:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" mimeType:\n",
|
||
" type: string\n",
|
||
" body:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" data:\n",
|
||
" type: string\n",
|
||
"\n",
|
||
" LabelModification:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" addLabelIds:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: string\n",
|
||
" removeLabelIds:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: string\n",
|
||
"\n",
|
||
" Label:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" addLabelIds:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: string\n",
|
||
" removeLabelIds:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: string\n",
|
||
"\n",
|
||
" EmailDraft:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" to:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: string\n",
|
||
" cc:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: string\n",
|
||
" bcc:\n",
|
||
" type: array\n",
|
||
" items:\n",
|
||
" type: string\n",
|
||
" subject:\n",
|
||
" type: string\n",
|
||
" body:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" mimeType:\n",
|
||
" type: string\n",
|
||
" enum: [text/plain, text/html]\n",
|
||
" content:\n",
|
||
" type: string\n",
|
||
"\n",
|
||
" Draft:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" id:\n",
|
||
" type: string\n",
|
||
" message:\n",
|
||
" $ref: '#/components/schemas/Message'\n",
|
||
"\n",
|
||
" SendDraftRequest:\n",
|
||
" type: object\n",
|
||
" properties:\n",
|
||
" draftId:\n",
|
||
" type: string\n",
|
||
" description: The ID of the draft to send.\n",
|
||
" userId:\n",
|
||
" type: string\n",
|
||
" description: The user's email address. Use \"me\" to indicate the authenticated user."
|
||
]
|
||
},
|
||
{
|
||
"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.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"- Go to the Google Cloud Console\n",
|
||
"- Navigate to API & Services > Credentials"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
""
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
""
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"- Create new OAuth credentials (or use an existing one)\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"- Locate your OAuth Client ID & Client Secret and store both values securely (see screenshot below)\n",
|
||
"\n",
|
||
""
|
||
]
|
||
},
|
||
{
|
||
"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. "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"- **Client ID**: use Client ID from steps above \n",
|
||
"- **Client Secret**: use Client Secret from steps above\n",
|
||
"- **Authorization URL**: https://accounts.google.com/o/oauth2/auth\n",
|
||
"- **Token URL**: https://oauth2.googleapis.com/token \n",
|
||
"- **Scope**: https://mail.google.com/\n",
|
||
"- **Token**: Default (POST)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Post-Action Steps"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"Once you've set up authentication in ChatGPT, follow the steps below in the application to finalize the Action. "
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"- Copy the callback URL from the GPT Action\n",
|
||
"- In the “Authorized redirect URIs” (see screenshot above), add your callback URL \n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"### FAQ & Troubleshooting"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"- *Callback URL Error:* If you get a callback URL error in ChatGPT, pay close attention to the screenshot above. You need to add the callback URL directly into GCP for the action to authenticate correctly\n",
|
||
"- *Schema calls the wrong project or dataset:* If ChatGPT calls the wrong project or dataset, consider updating your instructions to make it more explicit either (a) which project / dataset should be called or (b) to require the user provide those exact details before it runs the query"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"*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": {
|
||
"language_info": {
|
||
"name": "python"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 2
|
||
}
|