真寻 Bot 的插件库最近出现了一个 ChatGPT 插件(chatgpt),但是 OpenAI 的 API api.openai.com 在国内并不可用……

Request timed out: HTTPSConnectionPool(host='api.openai.com', port=443): Max retries exceeded with url: /v1/chat/completions (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x0000008EC81AE050>, 'Connection to api.openai.com timed out. (connect timeout=600)'))

Nginx 反向代理

我们需要配置 location 块

插件用到的 API 是 https://api.openai.com/v1/chat/completions

我们可以直接在 server 块中插入一个 location 块

server 块中 server_name 的值设为你的域名

location 块在这里有两种写法:

location /v1/ {
    proxy_pass https://api.openai.com/v1/;
}
location /v1/ {
    proxy_pass https://api.openai.com;
}

如果目标服务器设置有根据 HTTP 请求头中的 Host 字段来进行路由或判断功能的话,Nginx 不重写请求头中的 Host 字段,将会导致请求失败,这里可以直接把 Host 字段设为 proxy_pass 指令设置的服务器

经过反向代理后,由于在客户端和 Web 服务器之间增加了中间层,因此 Web 服务器无法直接拿到客户端的 IP,通过 $remote_addr 变量拿到的将是反向代理服务器的 IP 地址。
—— 《实战 Nginx》

Nginx 是可以使用 $remote_addr 获得用户的真实 IP 的,所以就可以设置 X-Real-IP$remote_addr 发送给目标服务器

最后完整的配置是下面的样子,这里使用了第二种写法同时还设置了 SSL

server {
    listen 443 ssl http2;
    server_name yourapidomain.com;

    location /v1/ {
        proxy_pass https://api.openai.com;
        proxy_set_header Host api.openai.com;
        proxy_set_header X-Real-IP $remote_addr;
    }

    ssl_certificate /cert/yourapidomain.com/fullchain.pem;
    ssl_certificate_key /cert/yourapidomain.com/privkey.pem;
}

修改插件

插件使用了 openai Python 库(openai/openai-python),openai 提供了修改 API HOST 的方法

import openai
openai.api_base = "https://example-endpoint.openai.azure.com"

直接修改插件代码,在其中加入一句:

openai.api_base = "https://yourapidomain.com"

其他(4月1日更新)

关于 502:类似的 Nginx 错误日志如下

[error] 4642#0: *71 SSL_do_handshake() failed (SSL: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:SSL alert number 40) while SSL handshaking to upstream, client: 42.*.*.212, server: yourapidomain.com, request: "GET /v1/chat/completions HTTP/2.0", upstream: "https://104.18.6.192:443/v1/chat/completions", host: "yourapidomain.com"

修改 Nginx 配置文件添加下面一行即可解决

proxy_ssl_server_name on;