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 配置中填写。
中间件信息:操作 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
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
操作 2:Azure 函数
现在我们已经创建了 GPT 并对 Box.com 进行了身份验证,我们可以创建 Azure 函数来处理响应格式化,使 GPT 能够从 Box 下载文件。
有关部署 Azure 函数的更多详细信息,请遵循此Azure 食谱指南。您将在下面找到要添加到函数中的示例代码。
此代码仅供参考 - 虽然它可以直接使用,但它旨在根据您的需求进行自定义。
数据流
现在您已经创建了 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,我们将进行查看。