GPT 操作库:Box

简介

本文档为开发者构建特定应用程序的 GPT 操作提供说明和指南。在继续之前,请确保您已熟悉以下信息:

本指南提供了有关如何将 chatGPT 与 Box.com 帐户连接的详细信息,GPT 需要两个操作才能从 Box 拉取数据。GPT 将直接与 Box API 交互,但需要中间件(例如 Azure 函数)来正确格式化来自 Box 的响应,以便下载和读取文件内容。Azure 函数操作对最终用户是透明的,这意味着用户无需显式调用该操作。

  • 操作 1:Box API 操作 - 利用 Box API 从 Box 查询数据
  • 操作 2:Azure 函数 - 格式化来自 Box 的响应,使 chatGPT 能够直接从 Box 下载文件

价值 + 示例业务用例

现有的 Box 客户可以利用这些指南查询有关文件、文件内容和任何元数据的详细信息。这使得 OpenAI 能够对存储在 Box 中的任何内容进行分析,例如可视化数据集以及跨多个文件夹和文件创建摘要。此 GPT 可以访问文件夹、文件和业务流程数据,例如 Box 中的元数据。此外,Box 管理员可以使用此 GPT 操作来查看审计跟踪和运行状况检查。

应用程序信息

应用程序关键链接

在开始之前,请查看来自 Box 和 Azure 的这些链接:

Box 操作

  • 应用程序网站:https://app.box.com
  • 应用程序 API 文档:https://developer.box.com/reference/


Azure 函数

  • 应用程序网站:https://learn.microsoft.com/en-us/azure/azure-functions/
  • 应用程序 API 文档:https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference/

应用程序先决条件

在开始之前,请确保在您的 Box 环境中完成以下步骤:

  • 这需要一个 Box 开发人员帐户才能开始:https://developer.box.com/
  • 按照 Box 开发人员站点创建具有 OAuth 2.0 身份验证类型的自定义应用程序:https://developer.box.com/guides/getting-started/first-application/
  • 导航到以下值的“配置”选项卡
    • OAuth 2.0 凭据(客户端 ID / 客户端密钥)您都需要这些值才能进行 chatGPT 配置
    • OAuth 2.0 重定向 URI:您将在下面的 chatGPT 操作配置中填写此值
    • 应用程序范围(读取 Box 中的所有文件和文件夹管理企业属性

您应该保持此窗口打开,重定向 URI 需要从 gpt 配置中填写。

gpt_actions_box_boxconfig1.png.png


中间件信息:操作 2 所需

请确保在您的 Azure 环境中完成以下步骤:

  • 具有创建 Azure 函数应用和 Azure Entra 应用注册的访问权限的 Azure 门户
  • 本指南中有一个详细的部分与部署和设计包装 Box 响应以查看文件内容所需的函数相关。没有该函数,GPT 将只能查询有关文件的信息,而不能查询文件内容。请务必在创建第一个操作后阅读此部分。

ChatGPT 步骤

自定义 GPT 说明

创建自定义 GPT 后,请将以下文本复制到“说明”面板中。有疑问吗?请查看入门示例,了解此步骤的详细信息。

**context**

此 GPT 将连接到您的 Box.com 帐户以搜索文件和文件夹,根据用户的查询提供准确有用的响应。它将协助查找、组织和检索存储在 Box.com 中的信息。确保安全私密地处理任何访问的数据。除非明确指示,否则避免执行任何可能修改或删除文件的操作。优先考虑响应的清晰度和效率。使用简单的语言以便于理解。如果请求不明确或需要其他详细信息来执行搜索,请寻求澄清。保持专业友好的语气,确保用户感到舒适和受到支持。


请使用此网站获取使用 Box API 的说明:https://developer.box.com/reference/ 此处可以找到每个端点
用户可以使用 Box 搜索端点或 Box 元数据搜索端点

**instructions**
在从 Box 检索文件信息时,请提供尽可能多的详细信息,并在返回多个文件时将其格式化为表格,包括修改日期、创建日期和您认为有价值的任何其他标题

提供对文件的见解并为用户建议模式,在适当时提供示例查询和建议

当用户想要比较文件时,请在不询问的情况下为用户检索文件

操作 1:Box API 操作

创建自定义 GPT 后,您需要创建 2 个操作。将以下文本复制到第一个操作面板中,这将是 Box 操作。有疑问吗?请查看入门示例,了解此步骤的详细信息。

{
  "openapi": "3.1.0",
  "info": {
    "title": "Box.com API",
    "description": "API for Box.com services",
    "version": "v1.0.0"
  },
  "servers": [
    {
      "url": "https://api.box.com/2.0"
    }
  ],
  "paths": {
    "/folders/{folder_id}": {
      "get": {
        "summary": "获取文件夹项目",
        "operationId": "getFolderItems",
        "parameters": [
          {
            "name": "folder_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "文件夹的 ID"
          }
        ],
        "responses": {
          "200": {
            "description": "文件夹中的项目列表",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderItems"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:folders"
            ]
          }
        ]
      }
    },
    "/files/{file_id}": {
      "get": {
        "summary": "获取文件信息",
        "operationId": "getFileInfo",
        "parameters": [
          {
            "name": "file_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "文件的 ID"
          }
        ],
        "responses": {
          "200": {
            "description": "文件信息",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileInfo"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:files"
            ]
          }
        ]
      }
    },
    "/folders": {
      "get": {
        "summary": "列出所有文件夹",
        "operationId": "listAllFolders",
        "responses": {
          "200": {
            "description": "所有文件夹的列表",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FoldersList"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:folders"
            ]
          }
        ]
      }
    },
    "/events": {
      "get": {
        "summary": "获取用户事件",
        "operationId": "getUserEvents",
        "parameters": [
          {
            "name": "stream_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "流的类型"
          }
        ],
        "responses": {
          "200": {
            "description": "用户事件",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserEvents"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:events"
            ]
          }
        ]
      }
    },
    "/admin_events": {
      "get": {
        "summary": "获取管理员事件",
        "operationId": "getAdminEvents",
        "responses": {
          "200": {
            "description": "管理员事件",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminEvents"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:events"
            ]
          }
        ]
      }
    },
    "/search": {
      "get": {
        "summary": "搜索",
        "operationId": "search",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "搜索查询"
          }
        ],
        "responses": {
          "200": {
            "description": "搜索结果",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResults"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "search:items"
            ]
          }
        ]
      }
    },
    "/metadata_templates": {
      "get": {
        "summary": "获取元数据模板",
        "operationId": "getMetadataTemplates",
        "responses": {
          "200": {
            "description": "元数据模板",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetadataTemplates"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:metadata_templates"
            ]
          }
        ]
      }
    },
    "/metadata_templates/enterprise": {
      "get": {
        "summary": "获取企业元数据模板",
        "operationId": "getEnterpriseMetadataTemplates",
        "responses": {
          "200": {
            "description": "企业元数据模板",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetadataTemplates"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:metadata_templates"
            ]
          }
        ]
      }
    },
    "/files/{file_id}/metadata": {
      "get": {
        "summary": "获取文件的所有元数据",
        "operationId": "getAllMetadataForFile",
        "parameters": [
          {
            "name": "file_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "文件的 ID"
          }
        ],
        "responses": {
          "200": {
            "description": "文件的所有元数据实例",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetadataInstances"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:metadata"
            ]
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "FolderItems": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "integer",
            "description": "文件夹中的项目总数"
          },
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "description": "项目的类型(例如,文件、文件夹)"
                },
                "id": {
                  "type": "string",
                  "description": "项目的 ID"
                },
                "name": {
                  "type": "string",
                  "description": "项目的名称"
                }
              }
            }
          }
        }
      },
      "FileInfo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "文件的 ID"
          },
          "name": {
            "type": "string",
            "description": "文件的名称"
          },
          "size": {
            "type": "integer",
            "description": "文件大小(字节)"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "文件的创建时间"
          },
          "modified_at": {
            "type": "string",
            "format": "date-time",
            "description": "文件的最后修改时间"
          }
        }
      },
      "FoldersList": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "description": "文件夹的 ID"
            },
            "name": {
              "type": "string",
              "description": "文件夹的名称"
            }
          }
        }
      },
      "UserEvents": {
        "type": "object",
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "event_id": {
                  "type": "string",
                  "description": "事件的 ID"
                },
                "event_type": {
                  "type": "string",
                  "description": "事件的类型"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "事件发生的时间"
                }
              }
            }
          }
        }
      },
      "AdminEvents": {
        "type": "object",
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "event_id": {
                  "type": "string",
                  "description": "事件的 ID"
                },
                "event_type": {
                  "type": "string",
                  "description": "事件的类型"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "事件发生的时间"
                }
              }
            }
          }
        }
      },
      "SearchResults": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "integer",
            "description": "搜索结果的总数"
          },
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "description": "项目的类型(例如,文件、文件夹)"
                },
                "id": {
                  "type": "string",
                  "description": "项目的 ID"
                },
                "name": {
                  "type": "string",
                  "description": "项目的名称"
                }
              }
            }
          }
        }
      },
      "MetadataTemplates": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "templateKey": {
              "type": "string",
              "description": "元数据模板的键"
            },
            "displayName": {
              "type": "string",
              "description": "元数据模板的显示名称"
            },
            "scope": {
              "type": "string",
              "description": "元数据模板的范围"
            }
          }
        }
      },
      "MetadataInstances": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "templateKey": {
              "type": "string",
              "description": "元数据模板的键"
            },
            "type": {
              "type": "string",
              "description": "元数据实例的类型"
            },
            "attributes": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              },
              "description": "元数据实例的属性"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "OAuth2": {
        "type": "oauth2",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://account.box.com/api/oauth2/authorize",
            "tokenUrl": "https://api.box.com/oauth2/token",
            "scopes": {
              "read:folders": "读取文件夹",
              "read:files": "读取文件",
              "search:items": "搜索项目",
              "read:metadata": "读取元数据",
              "read:metadata_templates": "读取元数据模板",
              "read:events": "读取事件"
            }
          }
        }
      }
    }
  }
}

注意:以上 schema 不包含所有可能的 API 端点,请务必根据 Box Developer 文档 编辑 schema 以生成适当的操作

身份验证说明

以下是有关使用此第三方应用程序设置身份验证的说明。有疑问吗?请查看入门示例,了解此步骤的详细信息。

在 ChatGPT 中

在 ChatGPT 中,单击“身份验证”并选择 OAuth


gptactions_box_gptauth.png

OAuth 连接

  • 客户端 ID - 来自您之前创建的 Box 自定义应用的价值
  • 客户端密钥 - 来自您之前创建的 Box 自定义应用的价值
  • 授权 URL - : https://account.box.com/api/oauth2/authorize?response_type=code&client_id=[来自上面的客户端 ID]&redirect_uri=[暂时使用占位符,如 chat.openai.com/aip//oauth/callback,稍后在 ChatGPT 中创建操作时更新]
  • Token URL : https:api.box.com/oauth2/token

    您需要保存配置并返回到 gpt 配置选项卡以复制回调 URL,编辑 Box 操作授权 URL 的配置,并将 URL 格式化为 https://account.box.com/api/oauth2/authorize?response_type=code&client_id=[client_ID]&redirect_uri=[callBack URL]

后续操作步骤

更新 Box.com 自定义应用程序

  • 从 gpt 复制 CallBack URL,并在 Box.com 中添加 OAuth 2.0 重定向 URI

    gpt_actions_box_boxconfig1.png.png


操作 2:Azure 函数

现在我们已经创建了 GPT 并对 Box.com 进行了身份验证,我们可以创建 Azure 函数来处理响应格式化,使 GPT 能够从 Box 下载文件。

有关部署 Azure 函数的更多详细信息,请遵循此Azure 食谱指南。您将在下面找到要添加到函数中的示例代码。

此代码仅供参考 - 虽然它可以直接使用,但它旨在根据您的需求进行自定义。


数据流

gpt_actions_box_azureflow.png



现在您已经创建了 Azure 函数,请添加下面的示例代码:

function_app.py

import azure.functions as func
from boxsdk import Client, JWTAuth

import requests
import base64
import json
import jwt
import logging

app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

@app.route(route="box_retrieval")
def box_retrieval(req: func.HttpRequest) -> func.HttpResponse:
    logger.info('Starting box_retrieval function')
    file_ids = req.params.get('file_ids')
    auth_header = req.headers.get('Authorization')

    if not file_ids or not auth_header:
        logger.error('Missing file_ids or Authorization header')
        return func.HttpResponse(
            "Missing file_id or Authorization header.",
            status_code=400
        )

    file_ids = file_ids.split(",")  # Assuming file_ids are passed as a comma-separated string
    if len(file_ids) == 0 or len(file_ids) > 10:
        logger.error('file_ids list is empty or contains more than 10 IDs')
        return func.HttpResponse(
            "file_ids list is empty or contains more than 10 IDs.",
            status_code=400
        )

    try:
        # Decode JWT to extract the email
        token = auth_header.split(" ")[1]
        decoded_token = jwt.decode(token, options={"verify_signature": False})
        upn = decoded_token['upn']
        user_email = get_user_mapping(upn)
        logger.info(f'User email extracted: {user_email}')

        config = JWTAuth.from_settings_file('jwt_config.json')
        sdk = Client(config)
        logger.info('Authenticated with Box API')

        # Use the user email to get the user ID
        users = sdk.users(filter_term=user_email)
        user = next(users)
        user_id = user.id
        logger.info(f'User ID obtained: {user_id}')

        openai_file_responses = []
        for file_id in file_ids:
            # Perform as_user call to get the file representation
            my_file = sdk.as_user(user).file(file_id).get()
            file_url = my_file.get_download_url()
            openai_file_responses.append(file_url)

        response_body = json.dumps({'openaiFileResponse': openai_file_responses})

        return func.HttpResponse(
            response_body,
            status_code=200,
            mimetype="application/json"
        )

    except Exception as e:
        return func.HttpResponse(
            f"An error occurred: {str(e)}",
            status_code=500
        )

def get_user_mapping(upn):
    # In our case, the user's authentication email into Azure AD is the same as their email in Box
    # If that is not the case, map the email in Box to the email in Azure AD
    return upn

jwt_config.json.sample

{
    "boxAppSettings": {
      "clientID": "12345",
      "clientSecret": "abcde",
      "appAuth": {
        "publicKeyID": "123",
        "privateKey": "-----BEGIN ENCRYPTED PRIVATE KEY-----\nvwxyz==\n-----END ENCRYPTED PRIVATE KEY-----\n",
        "passphrase": "lmnop"
      }
    },
    "enterpriseID": "09876"
  }

requirements.txt

boxsdk[jwt]
azure-functions
requests
pyjwt

请务必遵循 Azure 指南的其余部分,了解身份验证后的步骤和 chatGPT 配置:Azure 食谱指南

常见问题解答和故障排除

  • Schema 调用了错误的项目或数据集: 如果 ChatGPT 调用了错误的项目或数据集,请考虑更新您的说明,使其更明确地(a)调用哪个项目/数据集或(b)要求用户在运行查询前提供这些确切的详细信息。
  • Box 可以在事件流中返回大量数据,这可能导致错误。

您希望我们优先处理哪些集成?我们的集成中是否存在错误?在我们的 GitHub 中提交 PR 或 issue,我们将进行查看。