ChatGPT Plugin 开发入门
FreeGuideOnline
最新
2026-07-10
bash pip install fastapi uvicorn requests python-dotenv
如果是 Node.js 项目,可初始化并安装 Express:
```bash
npm init -y
npm install express cors dotenv
构建第一个插件:天气查询示例
本示例将打造一个用于查询城市天气的插件。当用户询问“北京今天天气怎么样”时,ChatGPT 会调用我们的插件获取实时天气数据并给出回答。
创建项目结构
weather-plugin/
├── main.py # API 入口
├── ai-plugin.json # 插件清单
├── openapi.yaml # OpenAPI 规范
├── .env # 环境变量(存放 API Key 等)
└── vercel.json # 部署配置(如使用 Vercel)
编写插件清单(ai-plugin.json)
插件清单文件必须托管在 /.well-known/ai-plugin.json 路径下。以下是天气插件的清单示例:
{
"schema_version": "v1",
"name_for_human": "Weather Assistant",
"name_for_model": "weather_assistant",
"description_for_human": "Get real-time weather information for any city.",
"description_for_model": "Plugin for querying current weather conditions. Provide city name and get temperature, humidity, wind speed etc.",
"auth": {
"type": "none"
},
"api": {
"type": "openapi",
"url": "https://your-domain.com/openapi.yaml"
},
"logo_url": "https://your-domain.com/logo.png",
"contact_email": "support@example.com",
"legal_info_url": "https://your-domain.com/legal"
}
字段说明:
name_for_model:模型用来识别插件的内部名称,需要像变量名那样使用小写和连字符。description_for_model:这是决定模型何时调用插件的关键字段,应清晰说明功能与触发条件。auth:本示例设为none,生产环境建议开启认证。api.url:指向 OpenAPI 规范文件的公开地址。
编写 OpenAPI 规范(openapi.yaml)
OpenAPI 文件描述插件的 API 端点、参数和响应模式。以下是一个查询天气的接口定义:
openapi: 3.0.1
info:
title: Weather API
description: Returns current weather for a given city.
version: 'v1'
servers:
- url: https://your-domain.com
paths:
/weather:
get:
operationId: getCurrentWeather
summary: Get the current weather of a specified city
parameters:
- name: city
in: query
required: true
description: Name of the city, e.g. Beijing
schema:
type: string
responses:
'200':
description: Current weather data
content:
application/json:
schema:
type: object
properties:
city:
type: string
temperature:
type: number
humidity:
type: number
description:
type: string
模型会根据 operationId 和 description 判断何时调用此接口,并根据 parameters 自动填入用户提到的城市名。
实现 API 服务(main.py)
使用 FastAPI 创建服务,调用公开的天气接口(此处以 wttr.in 为例):
import os
import httpx
from fastapi import FastAPI, Query
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
app = FastAPI()
# 允许跨域请求,开发阶段可开放所有来源
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# 提供静态文件(插件清单、OpenAPI 文件、Logo 等)
@app.get("/.well-known/ai-plugin.json")
async def plugin_manifest():
return FileResponse("ai-plugin.json", media_type="application/json")
@app.get("/openapi.yaml")
async def openapi_spec():
return FileResponse("openapi.yaml", media_type="text/yaml")
@app.get("/logo.png")
async def logo():
return FileResponse("logo.png")
# 核心天气查询端点
@app.get("/weather")
async def get_weather(city: str = Query(..., description="城市名称")):
async with httpx.AsyncClient() as client:
resp = await client.get(f"https://wttr.in/{city}?format=j1")
data = resp.json()
current = data["current_condition"][0]
return {
"city": city,
"temperature": current["temp_C"],
"humidity": current["humidity"],
"description": current["weatherDesc"][0]["value"]
}
本地测试与调试
- 使用 uvicorn 启动服务:
uvicorn main:app --reload --port 5003
- 通过 ngrok 暴露本地端口获得公网 HTTPS 地址:
ngrok http 5003
-
将 ngrok 生成的域名(例如
https://abc123.ngrok.io)替换到ai-plugin.json和openapi.yaml中的your-domain.com。 -
在浏览器访问
https://abc123.ngrok.io/.well-known/ai-plugin.json确认清单文件可被公开访问。 -
访问
https://abc123.ngrok.io/docs可看到 FastAPI 自动生成的交互式 Swagger 页面,验证 API 是否工作。
在 ChatGPT 中安装并测试插件
- 登录 ChatGPT 并进入 “Plugins” 模式(GPT-4 模型)。
- 点击插件商店选择 “Develop your own plugin”。
- 输入你的插件域名(如
https://abc123.ngrok.io),系统会自动验证插件清单。 - 如果验证通过,插件将出现在可用列表中。启用该插件。
- 尝试提问:“北京今天天气怎么样?” ChatGPT 应能识别并调用你的天气接口,返回结构化数据并给出回答。
常见问题排查
- 插件不出现或提示错误:检查
ai-plugin.json是否可通过 HTTPS 正常访问,且 JSON 格式无误。 - 模型不调用插件:优化
description_for_model,明确说明触发词(如“天气”、“温度”)。 - API 返回超时:插件响应需在数秒内完成,避免长时间计算,可考虑引入缓存。
- 跨域问题:确保 API 正确设置 CORS 头。
进阶要点
认证与安全
生产环境务必为插件添加认证。auth 字段支持 service_http 和 oauth 两种模式。使用 service_http 时,需提供一个携带 API Key 的认证入口;oauth 则需要完整的 OAuth 2.0 流程。务必验证用户权限,并限制敏感操作。
错误处理与友好提示
API 应返回明确的错误信息,帮助模型向用户解释失败原因。例如:
{
"error": "City not found. Please provide a valid city name."
}