ChatGPTNextWeb / ChatGPT-Next-Web

A cross-platform ChatGPT/Gemini UI (Web / PWA / Linux / Win / MacOS). 一键拥有你自己的跨平台 ChatGPT/Gemini 应用。
https://app.nextchat.dev/
MIT License
76.54k stars 59.14k forks source link

[Feature Request] GPTs插件导入增加对Apifox API Hub 导出的openapi.json支持 以实现GPTs插件对现有数百个开放平台的API支持 #5525

Closed Endlessworld closed 1 month ago

Endlessworld commented 1 month ago

🥰 Feature Description

如果GPTs插件导入可以支持通用openapi.json ,那么就可以通过Apifox API Hub 导出的openapi.json 实现将现有的数百个开放平台的API导入为GPTs插件。并且通过 GO、.NET、Java + swagger-ui 写的接口也能直接导入为GPTs直接使用!但是目前直接导入Apifox API Hub 的开放api 调用是报错的。 image

需求清单:

  1. GPTs插件导入增加对通用openapi.json支持 以实现GPTs插件对现有数百个开放平台的API支持。
  2. 考虑到openapi.json 导入的接口过多时会导致 token消耗过多、超出调用限制导致调用失败、以及一般项目开发中 一般使用 swagger注解 @Api(tags = "xxxx管理") 对Controller进行注释。导入的openapi.json 如果有多个tag需要根据tag标签对接口进行自动分组、并可手动进行分组划分 每个导入为一个插件、每个分组为一个Agent,一个Agent 即包含一组接口调用
  3. 考虑菜单 面具改为 预制角色/应用市场/应用商店/Agents
  4. 每个【角色/应用/Agents】可选关联一个插件、对插件中的所有分组接口进行禁用/启用设置(有些接口可能不需要)
  5. 增加@角色/@应用/@Agents功能 : 使用@唤起 Agents列表 展示Icon 头像 Title 名称 subTitle 描述 选中 Agents 后 仅下一次请求使用其角色预设设置、并使其包含的所有接口附加到当前tools 列表(覆盖当前应用),以实现Agents的组合使用、不使用@Agents时 默认使用当前Agents的默认设置
  6. 参考智谱清言的 创建智能体 》 插件市场 接入github 开源仓库 构建内置插件市场

🧐 Proposed Solution

image 3ffe8a926f5bf358689fce9381b11072 image

📝 Additional Information

微信截图_20240925111849 微信截图_20240925111947 微信截图_20240925112034 微信截图_20240925112053 微信截图_20240925112112 微信截图_20240925112132 新的聊天

Issues-translate-bot commented 1 month ago

Bot detected the issue body's language is not English, translate it automatically.


Title: [Feature Request] GPTs plug-in import adds support for openapi.json exported by Apifox API Hub to realize GPTs plug-in’s API support for hundreds of existing open platforms

🥰 Feature Description

If the GPTs plug-in import can support universal openapi.json, then hundreds of open platform APIs can be imported as GPTs plug-ins through the openapi.json exported by Apifox API Hub. And interfaces written through GO, .NET, Java + swagger-ui can also be directly imported into GPTs and used directly! However, at present, when directly importing the open api call of Apifox API Hub, an error occurs. image

Requirements list:

  1. The GPTs plug-in import adds support for the universal openapi.json to enable the GPTs plug-in to support the API of hundreds of existing open platforms.
  2. Group the interfaces according to the tag of swaggerui. Each group is an Agent. Each plug-in contains multiple Agents. An Agent contains multiple interface calls and can be associated with a role.
  3. Add the @Agent function to use @ to evoke the Agents list. The tools calls corresponding to all the interfaces contained in the selected Agent are appended to the current tools list (overwriting the original list). This not only saves tokens, but also allows the combined use of all plug-ins. All Agents

🧐 Proposed Solution

image

📝 Additional Information

WeChat screenshot_20240925111849 WeChat screenshot_20240925111947 WeChat screenshot_20240925112034 WeChat screenshot_20240925112053 WeChat screenshot_20240925112112 WeChat screenshot_20240925112132 New Chat

Endlessworld commented 1 month ago

以下是一个可用的 GPTs openapi.json 其与apifox API Hub 导出 的json多了俩字段 增加以下俩字段后即可直接将apifox API Hub上的接口直接导入为 插件

image



{
  "openapi": "3.1.0",
  "info": {
    "title": "每日热搜",
    "description": "",
    "version": "1.0.0"
  },
  "tags": [],
  "paths": {
    "/bilibili": {
      "get": {
        "operationId": "bilibili_hot_search",
        "x-openai-isConsequential": false,
        "summary": "Bilibili",
        "deprecated": false,
        "description": "",
        "tags": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "subtitle": {
                      "type": "string"
                    },
                    "from": {
                      "type": "string"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "updateTime": {
                      "type": "string"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "desc": {
                            "type": "string"
                          },
                          "pic": {
                            "type": "string"
                          },
                          "owner": {
                            "type": "object",
                            "properties": {
                              "mid": {
                                "type": "integer"
                              },
                              "name": {
                                "type": "string"
                              },
                              "face": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "mid",
                              "name",
                              "face"
                            ]
                          },
                          "data": {
                            "type": "object",
                            "properties": {
                              "aid": {
                                "type": "integer"
                              },
                              "view": {
                                "type": "integer"
                              },
                              "danmaku": {
                                "type": "integer"
                              },
                              "reply": {
                                "type": "integer"
                              },
                              "favorite": {
                                "type": "integer"
                              },
                              "coin": {
                                "type": "integer"
                              },
                              "share": {
                                "type": "integer"
                              },
                              "now_rank": {
                                "type": "integer"
                              },
                              "his_rank": {
                                "type": "integer"
                              },
                              "like": {
                                "type": "integer"
                              },
                              "dislike": {
                                "type": "integer"
                              },
                              "vt": {
                                "type": "integer"
                              },
                              "vv": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "aid",
                              "view",
                              "danmaku",
                              "reply",
                              "favorite",
                              "coin",
                              "share",
                              "now_rank",
                              "his_rank",
                              "like",
                              "dislike",
                              "vt",
                              "vv"
                            ]
                          },
                          "hot": {
                            "type": "integer"
                          },
                          "url": {
                            "type": "string"
                          },
                          "mobileUrl": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "title",
                          "desc",
                          "pic",
                          "owner",
                          "data",
                          "hot",
                          "url",
                          "mobileUrl"
                        ]
                      }
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "name",
                    "title",
                    "subtitle",
                    "from",
                    "total",
                    "updateTime",
                    "data"
                  ]
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/weibo": {
      "get": {
        "operationId": "WeiboHotSearch",
        "x-openai-isConsequential": false,
        "summary": "微博",
        "deprecated": false,
        "description": "",
        "tags": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "subtitle": {
                      "type": "string"
                    },
                    "from": {
                      "type": "string"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "updateTime": {
                      "type": "string"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "title": {
                            "type": "string"
                          },
                          "desc": {
                            "type": "string"
                          },
                          "hot": {
                            "type": "integer"
                          },
                          "url": {
                            "type": "string"
                          },
                          "mobileUrl": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "title",
                          "desc",
                          "hot",
                          "url",
                          "mobileUrl"
                        ]
                      }
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "name",
                    "title",
                    "subtitle",
                    "from",
                    "total",
                    "updateTime",
                    "data"
                  ]
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/zhihu": {
      "get": {
        "operationId": "ZhihuHotSearch",
        "x-openai-isConsequential": false,
        "summary": "知乎",
        "deprecated": false,
        "description": "",
        "tags": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "subtitle": {
                      "type": "string"
                    },
                    "from": {
                      "type": "string"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "updateTime": {
                      "type": "string"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "title": {
                            "type": "string"
                          },
                          "desc": {
                            "type": "string"
                          },
                          "pic": {
                            "type": "string"
                          },
                          "hot": {
                            "type": "integer"
                          },
                          "url": {
                            "type": "string"
                          },
                          "mobileUrl": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "title",
                          "desc",
                          "pic",
                          "hot",
                          "url",
                          "mobileUrl"
                        ]
                      }
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "title",
                    "subtitle",
                    "from",
                    "total",
                    "updateTime",
                    "data"
                  ]
                }
              }
            }
          }
        },
        "security": []
      }
    },

    "/douban_group": {
      "get": {
        "operationId": "DoubanDiscussionList",
        "x-openai-isConsequential": false,
        "summary": "豆瓣讨论榜",
        "deprecated": false,
        "description": "",
        "tags": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "subtitle": {
                      "type": "string"
                    },
                    "from": {
                      "type": "string"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "updateTime": {
                      "type": "string"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "title": {
                            "type": "string"
                          },
                          "desc": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string"
                          },
                          "mobileUrl": {
                            "type": "string"
                          },
                          "hot": {
                            "type": "string"
                          },
                          "source": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "title",
                          "desc",
                          "url",
                          "mobileUrl",
                          "hot",
                          "source"
                        ]
                      }
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "name",
                    "title",
                    "subtitle",
                    "from",
                    "total",
                    "updateTime",
                    "data"
                  ]
                }
              }
            }
          }
        },
        "security": []
      }
    },

    "/weread": {
      "get": {
        "operationId": "WeChatReading",
        "x-openai-isConsequential": false,
        "summary": "微信读书",
        "deprecated": false,
        "description": "",
        "tags": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          }
        },
        "security": []
      }
    },

    "/netease_music_toplist": {
      "get": {
        "operationId": "NetEaseCloudMusic",
        "x-openai-isConsequential": false,
        "summary": "网易云音乐",
        "deprecated": false,
        "description": "",
        "tags": [],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "description": "type \t1 \t飙升榜\ntype \t2 \t新歌榜\ntype \t3 \t原创榜\ntype \t4 \t热歌榜",
            "required": false,
            "example": "1",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/qq_music_toplist": {
      "get": {
        "operationId": "QQMusic",
        "x-openai-isConsequential": false,
        "summary": "QQ音乐",
        "deprecated": false,
        "description": "",
        "tags": [],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "description": "type \t1 \t飙升榜\ntype \t2 \t热歌榜\ntype \t3 \t新歌榜\ntype \t4 \t流行指数榜\ntype \t5 \t腾讯音乐人原创榜\ntype \t6 \t听歌识曲榜",
            "required": false,
            "example": "1",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          }
        },
        "security": []
      }
    },

    "/github": {
      "get": {
        "operationId": "Github",
        "x-openai-isConsequential": false,
        "summary": "Github",
        "deprecated": false,
        "description": "",
        "tags": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          }
        },
        "security": []
      }
    },

    "/calendar/date": {
      "get": {
        "operationId": "TodayInHistory",
        "x-openai-isConsequential": false,
        "summary": "历史上的今天",
        "deprecated": false,
        "description": "",
        "tags": [],
        "parameters": [
          {
            "name": "month",
            "in": "query",
            "description": "月份",
            "required": false,
            "example": "01",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "day",
            "in": "query",
            "description": "日期",
            "required": false,
            "example": "01",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          }
        },
        "security": []
      }
    }
  },
  "components": {
    "schemas": {},
    "securitySchemes": {}
  },
  "servers": [
    {
      "url": "https://hot.cigh.cn",
      "description": "正式环境"
    }
  ]
}

`
lloydzhou commented 1 month ago

主要是缺少 operationId字段,这里需要一个唯一的key用来区别不同的接口。

可以考虑,缺少这个字段的时候,尝试使用<METHOD>/<path>这种方式替代。 这样,既不会重复,名字也会比较与意义

Issues-translate-bot commented 1 month ago

Bot detected the issue body's language is not English, translate it automatically.


The main reason is the lack of the operationId field, which requires a unique key to distinguish different interfaces.

It can be considered that when this field is missing, try to use <METHOD>/<path> instead. In this way, there will be no duplication and the name will be compared with the meaning.

lloydzhou commented 1 month ago

在 #5547 处理了一下:

  1. 没有operationId字段的时候可以
  2. 只是method和path组成的名字,openai的api那边会做校验,只能是大小写字母加上下划线
Issues-translate-bot commented 1 month ago

Bot detected the issue body's language is not English, translate it automatically.


Fixed it in #5547:

  1. It can be used when there is no operationId field
  2. It is just a name composed of method and path. Openai’s API will do verification. It can only be uppercase and lowercase letters plus underlines.