構(gòu)建 JavaScript ChatGPT 插件,你學(xué)會(huì)了嗎?
聊天插件系統(tǒng)是一種令人興奮的新方式,可以擴(kuò)展ChatGPT的功能,納入您自己的業(yè)務(wù)數(shù)據(jù),并為客戶與您的業(yè)務(wù)互動(dòng)增加另一個(gè)渠道。在這篇文章中,我將解釋什么是聊天插件,它們能做什么,以及你如何用JavaScript建立你自己的聊天插件。
這篇文章(或OpenAI所稱的"訓(xùn)練數(shù)據(jù)")提供了一個(gè)快速入門指南,來建立你的第一個(gè)ChatGPT插件,并將其與ChatGPT界面整合。
聊天插件是否會(huì)成為改變生活的賈維斯般的體驗(yàn),或者只是一個(gè)昂貴的Alexa-for-your-browser,目前還沒有定論。讓我們通過看看插件能提供什么,需要注意什么,以及如何制作你自己的插件,來決定我們自己的想法。
目錄
- 什么是聊天插件?
插件組成部分
聊天插件生態(tài)系統(tǒng)的新機(jī)遇
插件開發(fā)的考量和局限
- 設(shè)置項(xiàng)目
- 添加OpenAI清單和API規(guī)范
- 創(chuàng)建服務(wù)器
- 設(shè)置強(qiáng)制性的插件路由
- 設(shè)置Todo路由
- 驗(yàn)證和測(cè)試插件
- (可選)將該服務(wù)器作為代理
- 下一步
什么是聊天插件?
"聊天插件"允許ChatGPT模型使用并與第三方應(yīng)用程序互動(dòng)。從本質(zhì)上講,它是一套指令和規(guī)范,語(yǔ)言模型可以遵循這些指令和規(guī)范在聊天對(duì)話中創(chuàng)建API的調(diào)用和操作。與第三方系統(tǒng)的整合為ChatGPT的用戶提供了一系列新的功能:
- 創(chuàng)建、更新和修改我們自己的業(yè)務(wù)數(shù)據(jù)和數(shù)據(jù)庫(kù)(如銷售、營(yíng)銷系統(tǒng))
- 從外部服務(wù)中獲取信息(如金融、天氣API)
- 執(zhí)行操作(例如,發(fā)送Slack消息)
插件組成部分
建立一個(gè)能與AI互動(dòng)的應(yīng)用程序似乎是一個(gè)令人生畏的復(fù)雜系統(tǒng),然而,一旦你開始做,你會(huì)發(fā)現(xiàn)它非常簡(jiǎn)單。一個(gè)"插件"是一套簡(jiǎn)單的指令,它告訴ChatGPT模型你的API是做什么的,以及如何和何時(shí)訪問它。
這可以歸結(jié)為兩個(gè)重要文件:
- ai-plugin.json:插件清單,包含插件的基本元數(shù)據(jù)。這包括名稱、作者、描述、認(rèn)證和聯(lián)系等細(xì)節(jié)。該清單被ChatGPT用來理解插件的作用。
- openapi.yaml:在OpenAPI規(guī)范中,你的API路由和模式的規(guī)范。也可以以json文件的形式提供。這將告訴ChatGPT可以使用哪些API,出于什么原因,以及請(qǐng)求和響應(yīng)會(huì)是什么樣子。
插件服務(wù)的基礎(chǔ)功能和托管由你決定。你的API可以托管在任何地方,使用任何REST API或編程語(yǔ)言。
聊天插件生態(tài)系統(tǒng)的新機(jī)遇
聊天插件的到來為開發(fā)者、設(shè)計(jì)師、企業(yè)和企業(yè)家?guī)砹艘幌盗械臋C(jī)會(huì):
- 「交互可以更"聰明"和更"流暢"」 :插件引入了人性化、假設(shè)和上下文的能力,并結(jié)合請(qǐng)求提供這些能力。這為互動(dòng)增加了一個(gè)流動(dòng)性的元素,而這是一個(gè)死板的GUI或結(jié)構(gòu)化的數(shù)據(jù)API所不能滿足的。例如,"我今天應(yīng)該穿外套嗎?"這個(gè)提示將導(dǎo)致API調(diào)用一個(gè)基于你的位置的天氣服務(wù),對(duì)天氣的解釋,以及對(duì)原始問題的回答:"是的,你應(yīng)該穿一件夾克。今天的溫度是12度,有80%的機(jī)會(huì)下雨。"。
- 「新的客戶渠道」:ChatGPT在2023年4月以1.73億活躍用戶創(chuàng)造了增長(zhǎng)最快的用戶記錄。毫無疑問,在這個(gè)平臺(tái)上占有一席之地,為你提供了接觸大量潛在客戶的機(jī)會(huì)。它還提供了一種潛在的更容易、更直觀、更容易與使用它的現(xiàn)有客戶互動(dòng)的方式。
- 「人工智能界面(A.I.I.)的崛起」:用戶現(xiàn)在無需點(diǎn)擊"按鈕"就可以執(zhí)行復(fù)雜的操作。從理論上講,一個(gè)插件可以提供一個(gè)驚人的服務(wù),而不需要像傳統(tǒng)的用戶界面那樣需要關(guān)注界面才行(或根本不需要)。一個(gè)直觀的規(guī)范可能變得和一個(gè)直觀的網(wǎng)絡(luò)應(yīng)用一樣重要。
- 「新的商業(yè)機(jī)會(huì)」:人工智能在提供工作的同時(shí)也會(huì)帶走工作。如果成功的話,插件生態(tài)系統(tǒng)將為插件開發(fā)者、人工智能API開發(fā)者,以及為企業(yè)托管、認(rèn)證和管理插件的全新垂直業(yè)務(wù)創(chuàng)造新的機(jī)會(huì)和空間。
插件開發(fā)的考量和局限
直觀和無代碼界面的好處帶來了一系列挑戰(zhàn)。承認(rèn)生態(tài)系統(tǒng)、邏輯和界面會(huì)隨著時(shí)間的推移而發(fā)展,在構(gòu)建插件時(shí),我們?nèi)匀恍枰涀∫恍┦虑?。特別是如果你想把它們作為一項(xiàng)業(yè)務(wù)來建立。
- 「響應(yīng)速度慢」:解釋自然語(yǔ)言、選擇插件、建立請(qǐng)求和解釋響應(yīng)都需要時(shí)間。對(duì)于簡(jiǎn)單的信息請(qǐng)求或操作,自己做就可以更快。根據(jù)上面的例子,我看一下我的手機(jī)主屏幕比等待15秒讓ChatGPT解釋天氣并寫給我要快得多。
- 「成本高」:用戶將花費(fèi)token來與任何插件互動(dòng)。這增加了潛在的成本,即使你是免費(fèi)提供給他們的東西。你還必須為托管和運(yùn)營(yíng)這些API的基礎(chǔ)設(shè)施付費(fèi)。
- 「不同方式」:在內(nèi)部,與插件的互動(dòng)仍然是REST API,只能執(zhí)行我們與其他客戶端相同的操作。插件更像是一個(gè)與企業(yè)互動(dòng)的新渠道,而不是目前讓人工智能為我們服務(wù)的新范式。
- 「可操縱性」:由于用戶在默認(rèn)情況下看不到API響應(yīng),誤導(dǎo)性信息和其他惡意策略可能會(huì)被插件制造商用來歪曲答案。
- 「不可預(yù)測(cè)性」:讓生成模型負(fù)責(zé)決策是有風(fēng)險(xiǎn)的,行為是不可靠的。有很多推理和猜測(cè)工作在幕后發(fā)生,以根據(jù)人類書面聊天提示創(chuàng)建API請(qǐng)求。打字不規(guī)范的信息或含糊不清的描述可能會(huì)導(dǎo)致調(diào)用錯(cuò)誤的API或做出錯(cuò)誤的行動(dòng)。
構(gòu)建第一個(gè)JavaScript ChatGPT 插件
我們將為我們的聊天插件建立自己的express服務(wù)器。這不僅是一個(gè)容易上手的方法,而且express可以被擴(kuò)展到包括中間件、認(rèn)證和所有其他你想要的生產(chǎn)級(jí)的東西。
以下是我們將在下列步驟中創(chuàng)建和添加代碼的所有文件。如果你感到困惑,可以回到這里,或者克隆這里的源碼[1]。
my-chat-plugin/
├─ .well-known/
│ ├─ ai-plugin.json <- 插件元數(shù)據(jù)
├─ routes/
│ ├─ todos.js <- 處理Todo請(qǐng)求的路由
│ ├─ openai.js <- 處理openAI請(qǐng)求的路由
openapi.yaml <- Open API規(guī)范
index.js <- 插件入口
「先決條件」
- 「OpenAI賬號(hào)」:在這里注冊(cè)[2]
- 「ChatGPT插件訪問」:如果你還沒有通過付費(fèi)賬戶訪問,你可以在這里[3]加入等待名單。
設(shè)置項(xiàng)目
創(chuàng)建一個(gè)名為my-chat-plugin的文件夾,執(zhí)行下面的命令來開始:
## 1. Create the directory and open it
mkdir my-chat-plugin && cd my-chat-plugin
## 2. Initialize a project with the default values
npm init --yes
## 3. Install our dependencies
npm install axios express cors js-yaml
添加OpenAI清單和API規(guī)范
現(xiàn)在,我們要?jiǎng)?chuàng)建所需的聊天插件清單和OpenAPI規(guī)范。ChatGPT會(huì)在你服務(wù)器的特定路由上請(qǐng)求這些文件,所以我們要把它們放在:
- /.well-known/ai-plugin.json
- /openapi.yaml
這些文件中的描述是非常重要的!如果你在summary和description_for_model字段中的語(yǔ)言含糊不清,你可能會(huì)讓ChatGPT對(duì)何時(shí)和如何使用你的插件感到困惑。請(qǐng)遵循以下步驟:
- 創(chuàng)建一個(gè)名為.well-known的文件夾,并在其中添加一個(gè)名為ai-plugin.json的文件。通過終端進(jìn)行操作:
mkdir .well-known && touch .well-known/ai-plugin.json
粘貼下面代碼到ai-plugin.json中:
{
"schema_version": "v1",
"name_for_human": "My ChatGPT To Do Plugin",
"name_for_model": "todo",
"description_for_human": "Plugin for managing a To Do list. You can add, remove and view your To Dos.",
"description_for_model": "Plugin for managing a To Do list. You can add, remove and view your ToDos.",
"auth": {
"type": "none"
},
"api": {
"type": "openapi",
"url": "<http://localhost:3000/openapi.yaml>",
"is_user_authenticated": false
},
"logo_url": "<http://localhost:3000/logo.png>",
"contact_email": "support@yourdomain.com",
"legal_info_url": "<http://www.yourdomain.com/legal>"
}
- 在項(xiàng)目根路徑下創(chuàng)建一個(gè)名為openapi.yaml,并且添加下列代碼到文件中。
這是OpenAPI規(guī)范,ChatGPT會(huì)用它來理解您的API路由的作用(注意每個(gè)路由的summary)以及請(qǐng)求和響應(yīng)的格式。如果ChatGPT在使用您的API時(shí)遇到問題,十有八九是因?yàn)檫@個(gè)規(guī)范與您的API的響應(yīng)不一致。
openapi: 3.0.1
info:
title: TODO Plugin
description: A plugin that allows the user to create and manage a To Do list using ChatGPT.
version: 'v1'
servers:
- url: <http://localhost:3000>
paths:
/todos:
get:
operationId: getTodos
summary: Get the list of todos
responses:
"200":
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Todo'
post:
operationId: addTodo
summary: Add a todo to the list
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Todo'
responses:
"201":
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/Todo'
/todos/{id}:
delete:
operationId: removeTodo
summary: Delete a todo from the list when it is complete, or no longer required.
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
"204":
description: No Content
components:
schemas:
Todo:
type: object
properties:
id:
type: integer
format: int64
task:
type: string
required:
- id
- task
創(chuàng)建服務(wù)器
我們的下一步是創(chuàng)建我們的主文件,也就是我們插件的入口。在項(xiàng)目根目錄下,添加一個(gè)名為index.js的文件,并添加以下代碼。
注意:ChatGPT文檔顯示openapi.yaml和openapi.json都有一個(gè)路由。本地測(cè)試顯示只有yaml文件被請(qǐng)求,但值得把它們都放在那里,因?yàn)橐院罂赡軙?huì)用到。
粘貼下面代碼到index.js中:
const express = require('express');
const cors = require('cors');
const todoRouter = require('./routes/todos');
const openaiRoutes = require('./routes/openai');
const app = express();
const PORT = 3000;
// Setting CORS to allow chat.openapi.com is required for ChatGPT to access your plugin
app.use(cors({ origin: [`http://localhost:${PORT}`, '<https://chat.openai.com>'] }));
app.use(express.json());
// Simple request logging to see if your plugin is being called by ChatGPT
app.use((req, res, next) => {
console.log(`Request received: ${req.method}: ${req.path}`)
next()
})
// OpenAI Required Routes
app.use(openaiRoutes);
// The dummy todos API
app.use('/todos', todoRouter);
app.listen(PORT, () => {
console.log(`Plugin server listening on port ${PORT}`);
});
上述代碼做了下列事情:
- 導(dǎo)入express和cors所需的庫(kù)
- 導(dǎo)入我們的路由特定邏輯,在下一步添加
- 添加日志中間件,將任何傳入的請(qǐng)求打印到控制臺(tái)中
- 提供一個(gè)通用的轉(zhuǎn)發(fā)函數(shù),如果你已經(jīng)有一個(gè)API服務(wù)就可以使用
設(shè)置強(qiáng)制性的插件路由
在這一步中,我們將為OpenAI / ChatGPT添加強(qiáng)制性的路由,來獲取所需文件。我們將把所有具體的路由邏輯放在一個(gè)"routes"目錄中。這就是我們將存儲(chǔ)插件路由以及其他自定義路由的地方。
(你可能希望用額外的文件夾(控制器、中間件、服務(wù)等)擴(kuò)展這個(gè)結(jié)構(gòu),或者創(chuàng)建你自己的結(jié)構(gòu))。
- 創(chuàng)建/routes文件夾
- 創(chuàng)建名為openai.js的文件
- 粘貼下列代碼到routes/openai.js中:
const express = require('express');
const router = express.Router();
const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
router.get('/openapi.yaml', async function(req, res) {
try {
const yamlData = fs.readFileSync(path.join(process.cwd(), 'openapi.yaml'), 'utf8');
const jsonData = yaml.load(yamlData);
res.json(jsonData);
} catch(e) {
console.log(e.message)
res.status(500).send({ error: 'Unable to fetch manifest.' });
}
});
router.get('/.well-known/ai-plugin.json', function(req, res) {
res.sendFile(path.join(process.cwd(), '/.well-known/ai-plugin.json'));
});
router.get('/logo.png', function(req, res) {
res.sendFile(path.join(process.cwd(), 'logo.png'));
})
module.exports = router;
上述代碼做了下列事情:
- 定義了兩個(gè)路由,供插件檢索你的清單和API規(guī)范。
- 定義了一個(gè)路由,讓插件在聊天中檢索并顯示你的插件標(biāo)識(shí)。
- 導(dǎo)出所有的路由,以便我們可以在index.js中導(dǎo)入它們。
設(shè)置Todo路由
現(xiàn)在我們將創(chuàng)建一些簡(jiǎn)單的路由來模擬一個(gè)簡(jiǎn)單的創(chuàng)建、更新、刪除功能。我們通常避免使用todo教程,但考慮到文檔中使用這個(gè)作為指南,我們希望盡可能保持它的可轉(zhuǎn)移性。
- 在你的路由文件夾中,創(chuàng)建一個(gè)名為todos.js的新文件
- 將以下代碼粘貼到routes/todos.js中:
const express = require('express');
const router = express.Router();
let todos = [
{ id: 1, task: 'Wake up' },
{ id: 2, task: 'Grab a brush'},
{ id: 3, task: 'Put a little makeup'},
{ id: 4, task: 'Build a Chat Plugin'}
]; // placeholder todos
let currentId = 5; // to assign unique ids to new todos
getTodos = async function(req, res) {
res.json(todos);
}
addTodo = async function(req, res) {
const { task } = req.body;
const newTodo = { id: currentId, task };
todos.push(newTodo);
currentId++;
res.json(newTodo);
}
removeTodo = async function(req, res) {
const { id } = req.params;
todos = todos.filter(todo => todo.id !== Number(id));
res.json({ "message" : "Todo successfully deleted" });
}
router.get('/', getTodos);
router.post('/', addTodo);
router.delete('/:id', removeTodo);
module.exports = router;
上述代碼做了下列事情:
- 創(chuàng)建3條路由,從一個(gè)簡(jiǎn)單的todo項(xiàng)目列表中獲取、創(chuàng)建和刪除。
- 將這些路由導(dǎo)出,導(dǎo)入到我們的index.js文件。
驗(yàn)證和測(cè)試插件
現(xiàn)在,有趣的部分來了。我們已經(jīng)有了所有必要的代碼和設(shè)置,可以在ChatGPT上手動(dòng)建立和運(yùn)行一個(gè)本地插件了!我們開始吧:
- 「開啟服務(wù)」
在終端中輸入node index.js。這會(huì)在終端中開啟服務(wù)并打印’Plugin server listening on port 3000’。
- 「將其連接到ChatGPT本地插件」
進(jìn)入chat.openai.com[4],在你的賬戶中打開一個(gè)新的聊天窗口。點(diǎn)擊GPT-4下拉菜單,Plugins > Plugin Store > 點(diǎn)擊Develop Your Own Plugin > 輸入localhost:3000 > 點(diǎn)擊「Find manifest file」。
- 「測(cè)試插件」
你應(yīng)該看到一條驗(yàn)證信息,即ChatGPT能夠獲得你的清單文件,這樣你就可以開始了。如果沒有,請(qǐng)檢查你的終端,服務(wù)器正在運(yùn)行,并且正在接收傳入的請(qǐng)求。
試試下面的一些命令:
- "what are my todos?"
- I have woken up(你不需要說出確切的Todo任務(wù),它就能理解你指的是什么)
(可選)將該服務(wù)器作為代理
如果你已經(jīng)有一個(gè)在本地或外部運(yùn)行的API來發(fā)送請(qǐng)求,你可以把這個(gè)服務(wù)器作為一個(gè)代理,把請(qǐng)求轉(zhuǎn)發(fā)給它。這是一個(gè)值得推薦的選項(xiàng),因?yàn)樗鼓隳軌蚩焖贉y(cè)試和迭代如何處理清單和規(guī)范文件,而不必重新部署或更新你現(xiàn)有的代碼庫(kù)。
在你創(chuàng)建的路由下的index.js中添加以下代碼:
// PASTE IN BEFORE app.listen(...
// Proxy server to an existing API
const api_url = '<http://localhost>';
app.all('/:path', async (req, res) => {
const { path } = req.params;
const url = `${api_url}/${path}`;
console.log(`Forwarding call: ${req.method} ${path} -> ${url}`);
const headers = {
'Content-Type': 'application/json',
};
try {
const response = await axios({
method: req.method,
url,
headers,
params: req.query,
data: req.body,
});
res.send(response.data);
} catch (error) {
console.error(`Error in forwarding call: ${error}`);
res.status(500).send('Error in forwarding call');
}
});
下一步
這個(gè)基本教程應(yīng)該是你開始建立自己的基于JavaScript的成熟聊天插件所需要的。將你的應(yīng)用程序部署到生產(chǎn)環(huán)境中,需要一些額外的認(rèn)證和部署步驟。教程中沒有提到這些,但我推薦以下資源來完成這些工作:
- 官方插件實(shí)例[5]:服務(wù)水平認(rèn)證,和檢索插件。
- 生產(chǎn)你的應(yīng)用程序[6]:在Plugin store中出現(xiàn)的主機(jī)、安全和性能要求有關(guān)的官方指南。
本文譯自:https://www.sitepoint.com/javascript-chatgpt-plugin/[7]
以上就是本文的全部?jī)?nèi)容,感謝閱讀。
參考資料
[1]源碼:https://github.com/sitepoint-editors/chatgpt-plugin-quickstart-js
[2]注冊(cè):https://platform.openai.com/signup?launch
[3]這里:https://openai.com/waitlist/plugins
[4]chat.openai.com:https://chat.openai.com/
[5]官方插件實(shí)例:https://platform.openai.com/docs/plugins/examples
[6]生產(chǎn)你的應(yīng)用程序:https://platform.openai.com/docs/plugins/production/domain-verification-and-security
[7]https://www.sitepoint.com/javascript-chatgpt-plugin/:https://www.sitepoint.com/javascript-chatgpt-plugin/