最近,我成功搭建了一个基于ChatGPT PLUS的Web共享服务,目的是为了方便团队成员共同使用。在众多开源项目中,我最终选择了chatgpt-web-share,主要是因为它支持API和PLUS账号两种共享方式,并且采用Python+JS+Docker架构,这对于我来说相对熟悉。虽然ChatGPT-Next-Web使用纯JS开发,操作简单,但在灵活性方面略有欠缺。
准备工作
运行环境
我的运行环境是Windows 11,借助WSL2运行Docker。同时,我还需要配置小猫咪以及无线网卡(连接互联网)和有线网卡(连接公司内网)。具体配置如下:
- Windows 11
- WSL2
- Docker
- 小猫咪
- 无线网卡DHCP(互联网)
- 有线网卡10.8.15.50(公司内网)
- WSL2
版本选择
我选择了chatgpt-web-share的最新版本0.4.0-alpha4.4,以确保使用最新的功能和修复。
配置文件详解
在开始之前,我们需要创建一系列配置文件。最终的目录结构如下图所示。需要手动创建docker-compose.yml、data目录、config目录以及config目录下的config.yaml和credentials.yaml。绿框中的目录和文件是后续自动生成的。
下面是各个配置文件的详细内容:
docker-compose.yml
services:
chatgpt-web-share:
image: ghcr.io/moeakwak/chatgpt-web-share:0.4.0-alpha4.4
container_name: cws
restart: always
ports:
- 8092:80 # 端口可调整
volumes:
- ./data:/app/backend/data
environment:
- TZ=Asia/Shanghai
- CWS_CONFIG_DIR=/app/backend/data/config
- CHATGPT_BASE_URL=http://go-chatgpt-api:8080/chatgpt/
depends_on:
- mongo
- go-chatgpt-api
mongo:
image: mongo:6.0
restart: always
volumes:
- ./mongo_data:/data/db
environment:
MONGO_INITDB_DATABASE: cws
MONGO_INITDB_ROOT_USERNAME: cws
MONGO_INITDB_ROOT_PASSWORD: password
go-chatgpt-api:
container_name: go-chatgpt-api
image: linweiyuan/go-chatgpt-api:latest
environment:
- GIN_MODE=release
- PROXY=http://10.30.48.245:7890 # 宿主机IP端口
restart: unless-stopped
config.yaml
openai_web:
is_plus_account: true
chatgpt_base_url: http://go-chatgpt-api:8080/chatgpt/backend-api/
proxy:
common_timeout: 10
ask_timeout: 600
openai_api:
openai_base_url: https://api.openai.com/v1/
proxy:
connect_timeout: 10
read_timeout: 20
common:
print_sql: false
create_initial_admin_user: true
initial_admin_user_username: admin
initial_admin_user_password: password
sync_conversations_on_startup: true
sync_conversations_regularly: false
http:
host: 127.0.0.1
port: 8000
cors_allow_origins:
- http://localhost
- http://127.0.0.1
- http://0.0.0.0
data:
data_dir: ./data
database_url: sqlite+aiosqlite:///data/database.db
mongodb_url: mongodb://cws:password@mongo:27017
run_migration: false
auth:
jwt_secret: MODIFY_THIS_TO_RANDOM_SECRET
jwt_lifetime_seconds: 86400
cookie_max_age: 86400
cookie_name: user_auth
user_secret: MODIFY_THIS_TO_RANDOM_SECRET
stats:
ask_stats_ttl: 7776000
request_stats_ttl: 2592000
request_stats_filter_keywords:
- /status
log:
console_log_level: INFO
credentials.yaml
openai_web_access_token: "eyJhbGcxxxxxxxxxxx"
openai_api_key: "sk-POxxxxxxxx"
其中,access_token的获取链接为:https://chat.openai.com/api/auth/session,api_key的生成链接为:https://platform.openai.com/account/api-keys。
网络加速配置
由于网络原因,直接从Docker Hub拉取镜像速度较慢,需要配置镜像加速。此外,为了让容器内部也能正常访问ChatGPT,需要配置代理。我通过修改docker-compose.yml文件,使go-chatgpt-api服务使用宿主机的代理。
...
go-chatgpt-api:
container_name: go-chatgpt-api
image: linweiyuan/go-chatgpt-api:latest
environment:
- GIN_MODE=release
- PROXY=http://10.30.48.245:7890 # 宿主机IP端口
restart: unless-stopped
部署步骤
完成配置后,使用以下命令启动服务:
docker compose up -d
如果部署成功,可以看到类似以下的日志信息:
此时,通过浏览器访问127.0.0.1:8092、0.0.0.0:8092或172.23.192.1:8092即可看到登录页面。使用配置文件中设置的用户名(admin)和密码(password)即可登录。
实现外部访问
如果需要让其他用户从外部访问该服务,需要进行端口映射。直接使用本机IP地址加端口号(例如:本机ip:8092)可能无法访问,需要进行额外的端口映射配置。
不建议使用以下方式:
完成上述步骤后,以管理员权限打开PowerShell,执行以下命令:
netsh interface portproxy add v4tov4 listenport=8092 listenaddress=0.0.0.0 connectport=8092 connectaddress=localhost
这条命令将0.0.0.0:8092映射到localhost:8092。这样,即使电脑有多块网卡,也可以通过任意网卡的IP地址加上端口号8092访问到localhost:8092,从而实现外部访问。更详细的解释可以参考https://zhuanlan.zhihu.com/p/425312804。
20230801更新
上述方法存在一个问题:重启后,8092端口可能无法访问。需要执行以下命令删除映射:
netsh interface portproxy delete v4tov4 listenport=8092 listenaddress=0.0.0.0
因此,我更推荐使用wsl2-auto-portproxy。
在/mnt/c/Users/microfat目录下创建.wslpp目录,并在该目录下创建config.json文件,内容如下:
{
"onlyPredefined": true,
"predefined": {
"tcp": [
"8092:8092"
]
},
"ignore": {
"tcp": [
445
]
}
}
如果在使用过程中,发现无法通过ladder连接到WSL2,可以尝试打开小猫咪的TUN Mode。
如果出现类似上图的错误,尝试重启服务:
docker compose down --rmi local
docker compose up -d
进一步优化
目前,服务已经可以实现重启后自动启动。但是,这依赖于无线网卡的IP地址不发生变化。因为代理地址被硬编码在/etc/systemd/system/docker.service.d/proxy.conf、/etc/default/docker和docker-compose.yml文件中。如果IP地址发生变化,就需要更新这些文件,并重启docker以及重新构建镜像。为了减少这部分工作量,可以考虑在WSL启动时自动更新这些文件。
首先需要解决的问题是在WSL中获取宿主机电脑的IP地址。可以使用以下命令:
NEW_IP=$(powershell.exe -Command 'Get-NetIPAddress -InterfaceAlias WLAN | Where-Object { $_.AddressFamily -match "IPv4" } | Select-Object -ExpandProperty IPAddress' | tr -d '\r')
echo $NEW_IP
然后,使用sed命令修改上述文件:
sudo sed -i -E "s/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/${NEW_IP}/g" /etc/default/docker
将修改命令添加到/etc/wsl.conf中,就可以实现在启动docker之前完成配置文件的修改。注意:不要将这些命令放在.bashrc中,因为.bashrc的执行在/etc/wsl.conf之后。