本页面为开发者构建特定应用程序的 GPT Action 提供说明和指南。在继续之前,请务必先熟悉以下信息
本指南详细介绍了如何将 chatGPT 与 Box.com 帐户连接,GPT 需要两个操作才能从 Box 中提取数据。GPT 将直接与 Box API 交互,但需要中间件(即 Azure 函数)来正确格式化来自 Box 的响应,以便下载和读取文件内容。azure 函数操作对最终用户是透明的,这意味着用户无需显式调用该操作。
现有的 Box 客户可以利用这些指南来查询有关文件、文件内容和任何相关元数据的详细信息。这支持对 Box 中存储的任何内容进行 OpenAI 驱动的分析,例如可视化数据集以及创建跨多个文件夹和文件的摘要。此 GPT 可以访问 Box 中的文件夹、文件和业务流程数据(例如元数据)。此外,Box 管理员可以使用此 GPT 操作来了解审计跟踪和运行状况检查。
在开始之前,请查看来自 Box 和 Azure 的这些链接
Box 操作
Azure 函数
在开始之前,请确保在您的 Box 环境中完成以下步骤
您将需要保持此窗口打开,重定向 URI 需要从 gpt 配置中填写。
确保在您的 Azure 环境中完成以下步骤
创建自定义 GPT 后,将下面的文本复制到“指令”面板中。有疑问?请查看入门示例,以了解此步骤如何更详细地工作。
**context**
This GPT will connect to your Box.com account to search files and folders, providing accurate and helpful responses based on the user's queries. It will assist with finding, organizing, and retrieving information stored in Box.com. Ensure secure and private handling of any accessed data. Avoid performing any actions that could modify or delete files unless explicitly instructed. Prioritize clarity and efficiency in responses. Use simple language for ease of understanding. Ask for clarification if a request is ambiguous or if additional details are needed to perform a search. Maintain a professional and friendly tone, ensuring users feel comfortable and supported.
Please use this website for instructions using the box API : https://developer.box.com/reference/ each endpoint can be found from this reference documentation
Users can search with the Box search endpoint or Box metadata search endpoint
**instructions**
When retrieving file information from Box provide as much details as possible and format into a table when more than one file is returned, include the modified date, created date and any other headers you might find valuable
Provide insights to files and suggest patterns for users, gives example queries and suggestions when appropriate
When a user wants to compare files retrieve the file for the user with out asking
创建自定义 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": "Get Folder Items",
"operationId": "getFolderItems",
"parameters": [
{
"name": "folder_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "The ID of the folder"
}
],
"responses": {
"200": {
"description": "A list of items in the folder",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FolderItems"
}
}
}
}
},
"security": [
{
"OAuth2": [
"read:folders"
]
}
]
}
},
"/files/{file_id}": {
"get": {
"summary": "Get File Information",
"operationId": "getFileInfo",
"parameters": [
{
"name": "file_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "The ID of the file"
}
],
"responses": {
"200": {
"description": "File information",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FileInfo"
}
}
}
}
},
"security": [
{
"OAuth2": [
"read:files"
]
}
]
}
},
"/folders": {
"get": {
"summary": "List All Folders",
"operationId": "listAllFolders",
"responses": {
"200": {
"description": "A list of all folders",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FoldersList"
}
}
}
}
},
"security": [
{
"OAuth2": [
"read:folders"
]
}
]
}
},
"/events": {
"get": {
"summary": "Get User Events",
"operationId": "getUserEvents",
"parameters": [
{
"name": "stream_type",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "The type of stream"
}
],
"responses": {
"200": {
"description": "User events",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserEvents"
}
}
}
}
},
"security": [
{
"OAuth2": [
"read:events"
]
}
]
}
},
"/admin_events": {
"get": {
"summary": "Get Admin Events",
"operationId": "getAdminEvents",
"responses": {
"200": {
"description": "Admin events",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AdminEvents"
}
}
}
}
},
"security": [
{
"OAuth2": [
"read:events"
]
}
]
}
},
"/search": {
"get": {
"summary": "Search",
"operationId": "search",
"parameters": [
{
"name": "query",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "Search query"
}
],
"responses": {
"200": {
"description": "Search results",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SearchResults"
}
}
}
}
},
"security": [
{
"OAuth2": [
"search:items"
]
}
]
}
},
"/metadata_templates": {
"get": {
"summary": "Get Metadata Templates",
"operationId": "getMetadataTemplates",
"responses": {
"200": {
"description": "Metadata templates",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MetadataTemplates"
}
}
}
}
},
"security": [
{
"OAuth2": [
"read:metadata_templates"
]
}
]
}
},
"/metadata_templates/enterprise": {
"get": {
"summary": "Get Enterprise Metadata Templates",
"operationId": "getEnterpriseMetadataTemplates",
"responses": {
"200": {
"description": "Enterprise metadata templates",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MetadataTemplates"
}
}
}
}
},
"security": [
{
"OAuth2": [
"read:metadata_templates"
]
}
]
}
},
"/files/{file_id}/metadata": {
"get": {
"summary": "Get All Metadata for a File",
"operationId": "getAllMetadataForFile",
"parameters": [
{
"name": "file_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "The ID of the file"
}
],
"responses": {
"200": {
"description": "All metadata instances for the file",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MetadataInstances"
}
}
}
}
},
"security": [
{
"OAuth2": [
"read:metadata"
]
}
]
}
}
},
"components": {
"schemas": {
"FolderItems": {
"type": "object",
"properties": {
"total_count": {
"type": "integer",
"description": "The total number of items in the folder"
},
"entries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "The type of the item (e.g., file, folder)"
},
"id": {
"type": "string",
"description": "The ID of the item"
},
"name": {
"type": "string",
"description": "The name of the item"
}
}
}
}
}
},
"FileInfo": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the file"
},
"name": {
"type": "string",
"description": "The name of the file"
},
"size": {
"type": "integer",
"description": "The size of the file in bytes"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "The creation time of the file"
},
"modified_at": {
"type": "string",
"format": "date-time",
"description": "The last modification time of the file"
}
}
},
"FoldersList": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the folder"
},
"name": {
"type": "string",
"description": "The name of the folder"
}
}
}
},
"UserEvents": {
"type": "object",
"properties": {
"entries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"event_id": {
"type": "string",
"description": "The ID of the event"
},
"event_type": {
"type": "string",
"description": "The type of the event"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "The time the event occurred"
}
}
}
}
}
},
"AdminEvents": {
"type": "object",
"properties": {
"entries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"event_id": {
"type": "string",
"description": "The ID of the event"
},
"event_type": {
"type": "string",
"description": "The type of the event"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "The time the event occurred"
}
}
}
}
}
},
"SearchResults": {
"type": "object",
"properties": {
"total_count": {
"type": "integer",
"description": "The total number of search results"
},
"entries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "The type of the item (e.g., file, folder)"
},
"id": {
"type": "string",
"description": "The ID of the item"
},
"name": {
"type": "string",
"description": "The name of the item"
}
}
}
}
}
},
"MetadataTemplates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"templateKey": {
"type": "string",
"description": "The key of the metadata template"
},
"displayName": {
"type": "string",
"description": "The display name of the metadata template"
},
"scope": {
"type": "string",
"description": "The scope of the metadata template"
}
}
}
},
"MetadataInstances": {
"type": "array",
"items": {
"type": "object",
"properties": {
"templateKey": {
"type": "string",
"description": "The key of the metadata template"
},
"type": {
"type": "string",
"description": "The type of the metadata instance"
},
"attributes": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Attributes of the metadata instance"
}
}
}
}
},
"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 folders",
"read:files": "Read files",
"search:items": "Search items",
"read:metadata": "Read metadata",
"read:metadata_templates": "Read metadata templates",
"read:events": "Read events"
}
}
}
}
}
}
}
注意:上面的架构不包含所有可能的 API 端点,请务必编辑架构以从Box 开发者文档中生成适当的操作
以下是有关使用此第三方应用程序设置身份验证的说明。有疑问?请查看入门示例,以了解此步骤如何更详细地工作。
在 ChatGPT 中,单击“身份验证”并选择 OAuth
OAuth 连接
更新 Box.com 自定义应用程序
现在我们已经创建了 GPT 并针对 Box.com 进行了身份验证,我们可以创建 azure 函数来处理响应格式化,使 GPT 能够从 Box 下载文件。
请按照此Azure Cookbook 指南了解有关部署 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 Cookbook 指南
您希望我们优先考虑哪些集成?我们的集成中是否存在错误?在我们的 github 中提交 PR 或 issue,我们会查看。