让 OpenAI 更 Open,在 ChatGPT 里自由接入数据源(openaiapi修改默许域名)
怎么修改OpenAI API默许域名,实现自由接入数据源
OpenAI API的默许使用官方域名:https://api.openai.com,但在中国地区没法访问,可以尝试以下方法来修改默许域名:
-
使用Cloudflare Workers代理OpenAI
可使用Cloudflare Workers来代理OpenAI,以下是具体步骤:
- 参考使用Cloudflare Workers解决OpenAI和ChatGPT的API没法访问的问题。
-
替换官方域名为自定义域名
可以将官方域名api.openai.com替换为自己的域名,以下是示例代码:
import openai import os openai.api_base = "https://yourdomain.com/v1" openai.api_key = 'your_api_key' model_engine_id = "text-davinci..."
通过以上方法修改OpenAI API的默许域名,可以实现自由接入数据源。在国内没法访问官方域名时,可以通过Cloudflare Workers代理或替换为自定义域名来解决访问限制的问题。
例如,没法访问官方域名https://api.openai.com时,可以将默许域名替换为自己的域名,如https://yourdomain.com,然后依照相应的方法设置API访问参数。
这样,就能够顺利地访问OpenAI API并自由接入自己的数据源。
openaiapi修改默许域名的进一步展开说明
怎样在 ChatGPT 中自由接入和使用各种数据源
在本篇文章中,我们将扼要讨论怎样在 OpenAI 的 ChatGPT Web 客户端中接入和使用各种数据源,和如何通过自定义数据源来进行一些有趣的实现。
引言
在过去的几个月中,我一直在探索并分享 OpenAI 的 ChatGPT 官方客户端。我也在网上发布了一些有趣的折腾项目,并引发了一些朋友的兴趣。一些人对其中的实现方式感到好奇,另外一些人认为 ChatGPT Web 客户端是一个棒极了的载体,具有良好的交互情势,并希望能够使用这类方式进行开发,从而节省大量的系统开发本钱。而且,他们也期待能够一起开源共建。
最近,受一名合作火伴的推动,从五一假期开始,我们陆续进行了 ChatGPT 后端服务的代码重写,并进行了部份敏感信息的剥离。我们将 ChatGPT 的前端封装成了一个独立的Docker容器,并重写了一套与 ChatGPT 客户端兼容的后端服务。
通过这个项目,任何人都可以在本地启动一个与官方交互体验一致的 ChatGPT 客户端,并根据自己的需求接入合适的信息源。这些信息源可以是通过 API 调用的模型接口,不但限于 OpenAI 的3.5或4版本,还可以接入 HuggingFace 或国内的大模型,乃至是托管在私有环境中的服务。例如,在 ChatGPT 中乃至可以调用 Claude、国内的通义千问和图片生成模型。另外,还可使用搜索引擎以对话的方式进行信息搜索,并通过模型的生成能力来调剂和优化返回的结果。还可使用固定的数据源或数据库,如指定的内容、长文、乃至是预设的固定答案,可以存储在文本文件或 Excel 表格中。还可使用 RSS 信息源或任意你希望对接的 API、网站等等,不论 ChatGPT 官方会不会支持,也不论你会不会具有权限。
目前,这两个项目已在 GitHub 上开放:
– Docker ChatGPT:一个小巧的 ChatGPT Web 客户端,可以一键启动,允许接入各种数据源和非OpenAI模型。
– Sparrow:ChatGPT 后端服务的开源实现。
或许在后端更加完善后,我会重写一个完全开源的前端客户端,使全部项目变得更加完全。
基础使用:OpenAI API
在项目的示例目录中,我们可以找到一些示例代码,让我们先来看看如何最简单地接入 OpenAI API。下面是一个配置示例:
“`
version : ‘3’
services :
# ChatGPT Web 客户端
chatgpt-client :
image : soulteary/chatgpt
restart : always
ports :
– 8090 : 8090
environment :
# 容器中的服务使用的端口
APP_PORT : 8090
# 前端使用的 ChatGPT 客户端域名,需要和 `sparrow` 中的 `WEB_CLIENT_HOSTNAME` 中的设置保持一致
APP_HOSTNAME : “http://localhost:8090”
# 客户端使用的服务端地址,如果你使用这个配置文件,可以保持下面的数值,否则需要调剂为 `sparrow` 部署的实际地址
APP_UPSTREAM : “http://sparrow:8091”
# 开源实现的后端服务
sparrow :
image : soulteary/sparrow
restart : always
environment :
# [基础设置]
# => ChatGPT Web 客户端使用的域名,需要和 `chatgpt-client` 的 `APP_HOSTNAME` 保持一致
WEB_CLIENT_HOSTNAME : “http://localhost:8090”
# => 服务端口,默许端口: 8091
# APP_PORT: 8091
# [私有使用 OpenAI API 服务设置]
*可选配置
# => 启用 OpenAI API
ENABLE_OPENAI_API : “on”
# => OpenAI API Key,填写你自己的 KEY
OPENAI_API_KEY : “sk⑴23456789012345678901234567890123456789012345678”
# => 启用访问 API 的代理,如果你不是在国外服务器使用
# OPENAI_API_PROXY_ENABLE: “on”
# => 设置 API 代理地址, eg: `”http://127.0.0.1:1234″` or “”
# OPENAI_API_PROXY_ADDR: “http://127.0.0.1:1234”
logging :
driver : “json-file”
options :
max-size : “10m”
“`
将上面的内容保存为docker-compose.yml,然后访问 OpenAI 的 API Key 管理页面,将自己的 API Key 更新到配置中。接下来,在终端中使用`docker-compose up`命令启动程序,可以看到类似下面的日志输出:
“`
# docker-compose down && docker-compose up
[ + ] Running 9/9
[ ⣿⣿ ] 0B/0B ▸ sparrow
[ ⣿⣿⣿⣿⣿ ] 0B/0B ▸ chatgpt-client
[profile] 0.0s ▸ 2408cc74d12b Already exists
[fcb446fdb6d6] 0.0s ▸ 53e036a1e5c8 Pull complete
[80f6c46103f1] 0.0s ▸ b6a24d60453c Pull complete
[0b3684f6a486] 0.0s ▸ a5072006fa7c Pull complete
[4218f6930c8b] 0.0s ▸ 8a30712078cf Pull complete
[ + ] Running 3/1
[ + ] Network chatgpt_default Created 0.1s
[ + ] Container chatgpt-sparrow⑴ Created 0.0s
[ + ] Container chatgpt-chatgpt-client⑴ Created 0.0s
Attaching to chatgpt-chatgpt-client⑴, chatgpt-sparrow⑴
chatgpt-sparrow⑴ | Sparrow vv0.10.1
chatgpt-sparrow⑴ | Sparrow Service has been launched
chatgpt-chatgpt-client⑴ | [ OpenAI Chat Client ] http://localhost:8090
chatgpt-chatgpt-client⑴ | – Project: https://github.com/soulteary/docker-chatgpt
chatgpt-chatgpt-client⑴ | – Release: 2023.05.19 v1
“`
等待服务启动完成后,在浏览器中打开http://localhost:8090(或你自定义的地址),就可以够使用自己搭建的 ChatGPT 服务了。
自定义数据源:Flag Studio
接下来,我们将讨论怎样在 ChatGPT 中使用一种官方本来不支持的数据源或模型。比如,我们先来尝试接入智源研究院推出的 Flag Studio 图文大模型,该模型支持在线申请不要钱API使用。
使用 Flag Studio 的配置文件与使用 OpenAI API 类似:
“`
version : ‘3’
services :
# ChatGPT Web 客户端
chatgpt-client :
image : soulteary/chatgpt
restart : always
ports :
– 8090 : 8090
environment :
# 容器中的服务使用的端口
APP_PORT : 8090
# 前端使用的 ChatGPT 客户端域名,需要和 `sparrow` 中的 `WEB_CLIENT_HOSTNAME` 中的设置保持一致
APP_HOSTNAME : “http://localhost:8090”
# 客户端使用的服务端地址,如果你使用这个配置文件,可以保持下面的数值,否则需要调剂为 `sparrow` 部署的实际地址
APP_UPSTREAM : “http://sparrow:8091”
# 开源实现的后端服务
sparrow :
image : soulteary/sparrow
restart : always
environment :
# [基础设置]
# => ChatGPT Web 客户端使用的域名,需要和 `chatgpt-client` 的 `APP_HOSTNAME` 保持一致
WEB_CLIENT_HOSTNAME : “http://localhost:8090”
# => 服务端口,默许端口: 8091
# APP_PORT: 8091
# [私有实现的 FlagStudio 服务] *可选
# => 启用 FlagStudio
ENABLE_FLAGSTUDIO : “on”
# => 只启用 FlagStudio 数据源
ENABLE_FLAGSTUDIO_ONLY : “off”
# => FlagStudio API Key
FLAGSTUDIO_API_KEY : “填写你自己的 API KEY”
logging :
driver : “json-file”
options :
max-size : “10m”
“`
将上述内容保存为docker-compose.yml,并先注册一个FlagStudio账号,然后访问官方文档页面获得你自己的API Key,并将其更新到配置中的FLAGSTUDIO_API_KEY。
使用 Flag Studio 的 ChatGPT
接下来,我们来聊聊如何封装这样一个简单的数据源,让 ChatGPT 能够输出一些区别寻常的内容。
Flag Studio 数据源的实现寄存在后端项目sparrow中的`connectors/flag-studio`目录下,其中关键的实现代码总共不到200行。
根据官方文档,使用 FlagStudio 进行完全的图片生成进程,需要先根据我们申请的 API Key 来获得一个 Token,然后再使用该 Token 来调用生成图片的接口。
我们先来实现根据 API Key 获得 Token 的逻辑:
“`
// package FlagStudio
import (
“encoding/json”
“fmt”
“io”
“net/http”
)
const API_GET_TOKEN = “https://flagopen.baai.ac.cn/flagStudio/auth/getToken”
type ResponseToken struct {
Code int `json:”code”`
Data struct {
Token string `json:”token”`
} `json:”data”`
}
// parseToken parses the token from the response body
func parseToken(buf []byte) (string, error) {
var data ResponseToken
err := json.Unmarshal(buf, &data)
if err != nil {
return “”, err
}
if data.Code != 200 || data.Data.Token == “” {
return “”, fmt.Errorf(“FlagStudio API, Get Token error, Code %d
, Token: %s”, data.Code, data.Data.Token)
}
return data.Data.Token, nil
}
// get token from the API
func GetToken(apikey string) (string, error) {
req, err := http.NewRequest(“GET”, API_GET_TOKEN, nil)
if err != nil {
return “”, fmt.Errorf(“FlagStudio API, Error initializing network components, err: %v”, err)
}
req.Header.Set(“Accept”, “application/json”)
req.Header.Set(“Content-Type”, “application/json”)
q := req.URL.Query()
q.Add(“apikey”, apikey)
req.URL.RawQuery = q.Encode()
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return “”, fmt.Errorf(“FlagStudio API, Error sending request, err: %v”, err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return “”, fmt.Errorf(“FlagStudio API, Error reading response, err: %v”, err)
}
token, err := parseToken(body)
if err != nil {
return “”, fmt.Errorf(“FlagStudio API, Error parsing response, err: %v”, err)
}
return token, nil
}
“`
上述代码实现了一个简单的 HTTP 调用,将服务端返回的 JSON 内容解析后得到生成图片所需的 Token。在没有异常的情况下,函数运行结束后就可以得到 Token。
接下来,我们来实现生成图片接口的调用:
“`
// package FlagStudio
import (
“encoding/json”
“fmt”
“io”
“net/http”
“strings”
“github.com/soulteary/sparrow/internal/define”
)
type TextToImage struct {
Prompt string `json:”prompt”`
GuidanceScale float64 `json:”guidance_scale”`
Height int `json:”height”`
NegativePrompts string `json:”negative_prompts”`
Sampler string `json:”sampler”`
Seed int `json:”seed”`
Steps int `json:”steps”`
Style string `json:”style”`
Upsample int `json:”upsample”`
Width int `json:”width”`
}
const API_TEXT_TO_IMAGE = “https://flagopen.baai.ac.cn/flagStudio/v1/text2img”
var FS_STYLES = []string{“国画”, “写实主义”, “虚幻引擎”, “黑白插画”, …}
func GetRandomStyle() string {
return FS_STYLES[define.GetRandomNumber(0, len(FS_STYLES)⑴)]
}
func GenerateImageByText(s string) string {
data := TextToImage{
Prompt: s,
GuidanceScale: 7.5,
Width: 512,
Height: 512,
NegativePrompts: “”,
Sampler: “ddim”,
Seed: 1024,
Steps: 50,
Style: GetRandomStyle(),
Upsample: 1,
}
payload, err := define.MakeJSON(data)
if err != nil {
return fmt.Sprintf(“FlagStudio API, An error occurred while preparing to enter data: %v”, err)
}
token, err := GetToken(define.FLAGSTUDIO_API_KEY)
if err != nil {
return fmt.Sprintf(“FlagStudio API, An error occurred while getting the token: %v”, err)
}
req, err := http.NewRequest(“POST”, API_TEXT_TO_IMAGE, strings.NewReader(payload))
if err != nil {
return fmt.Sprintf(“FlagStudio API, An error occurred while initializing network components: %v”, err)
}
req.Header.Set(“Accept”, “application/json”)
req.Header.Set(“Content-Type”, “application/json”)
req.Header.Add(“token”, token)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Sprintf(“FlagStudio API, An error occurred while sending request: %v”, err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Sprintf(“FlagStudio API, An error occurred while reading response: %v”, err)
}
base64Image, err := parseTextToImage(body)
if err != nil {
return fmt.Sprintf(“FlagStudio API, An error occurred while parsing response: %v”, err)
}
return `![](data:image/png;base64,` + base64Image + `)`
}
type ResponseTextToImage struct {
Code int `json:”code”`
Data string `json:”data”`
Nsfw int `json:”nsfw”`
}
func parseTextToImage(buf []byte) (string, error) {
var data ResponseTextToImage
err := json.Unmarshal(buf, &data)
if err != nil {
return “”, err
}
if data.Code != 200 || data.Data == “” {
return “”, fmt.Errorf(“FlagStudio API, Get Result error, Code %d”, data.Code)
}
if data.Nsfw != 0 {
return “”, fmt.Errorf(“FlagStudio API, Get Token error, Code %d
, NSFW: %d”, data.Code, data.Nsfw)
}
return data.Data, nil
}
“`
与调用 Token 的逻辑类似,这里我们需要使用 POST 方法发送要求,并携带适当的要求参数。
关于图片风格的定义,我们实现了一个随机选择的方法,更好的实现方式是根据用户的 Prompt 内容自动选择适合的模型风格。如果你有兴趣,可以在项目中提交你的代码实现,让更多人受益。
好了,上面的代码就是我们的关键实现。但为了使其生效,我们还需要进行一些边角调剂。
首先,我们需要在流式响应组件`components/stream-responser/stream_builder.go`中添加一段代码,以便在响应要求时将用户提交的 Prompt 传递给我们刚刚封装好的程序。
“`go
// package StreamResponser
func StreamBuilder(parentMessageID string, conversationID string, modelSlug string, broker *eb.Broker, input string, mode StreamMessageMode) bool {
…
switch modelSlug {
…
case datatypes.MODEL_FLAGSTUDIO.Slug:
if define.ENABLE_FLAGSTUDIO {
sequences = MakeStreamingMessage(FlagStudio.GenerateImageByText(input), modelSlug, conversationID, messageID, mode)
quickMode = true
}
…
}
…
}
“`
接下来,在程序功能开关中添加一些定义。如果不需要按需启用FlagStudio,可以不进行实现。
“`go
// package define
var (
ENABLE_FLAGSTUDIO = GetBool(“ENABLE_FLAGSTUDIO”, false) // Enable Flagstudio
ENABLE_FLAGSTUDIO_ONLY = GetBool(“ENABLE_FLAGSTUDIO_ONLY”, false) // Enable Flagstudio only
FLAGSTUDIO_API_KEY = GetSecret(“FLAGSTUDIO_API_KEY”, “YOUR_FLAGSTUDIO_SECRET”) // Flagstudio API Token
)
“`
为了实现多个模型数据源之间的切换,我们还需要对每一个模型定义一些数据预设。在模型列表目录中创建一个新程叙文件`internal/datatypes/models.go`,并在其中添加我们自定义的模型类型:
“`go
// package datatypes
var MODEL_FLAGSTUDIO = ModelListItem{
Slug: “flag-studio”,
MaxTokens: 1000,
Title: “FlagStudio”,
Description: “FlagStudio is a text-to-image platform developed by BAAI’s z-lab and FlagAI team. It supports 18-language text-to-image generation including Chinese and English, and aims to provide advanced AI art creation experience.”,
Tags: []string{},
QualitativeProperties: ModelListQualitativeProperties{
Reasoning: []int{4, 5},
Speed: []int{4, 5},
Conciseness: []int{3, 5},
},
}
“`
为了让 ChatGPT 能够正常调用模型,还需要在`internal/api/models/models.go`中实现获得模型列表的一些逻辑,以便 ChatGPT 调用模型列表时能够访问到我们的自定义模型或数据源。
“`go
// package models
import (
“net/http”
“github.com/gin-gonic/gin”
“github.com/soulteary/sparrow/internal/datatypes”
“github.com/soulteary/sparrow/internal/define”
)
// Get models
func GetModels(c *gin.Context) {
…
if define.ENABLE_FLAGSTUDIO {
model := GetFlagStudioModel()
if define.ENABLE_FLAGSTUDIO_ONLY {
c.JSON(http.StatusOK, datatypes.Models{Models: model})
}
modelList = append(modelList, model…)
}
…
}
“`
至此,我们已实现了 Flag Studio 数据源的调用。你可以根据自己的需求进行修改和扩大。
总结
在这篇文章中,我们探讨了怎样在 OpenAI 的 ChatGPT Web 客户端中自由接入和使用各种数据源。我们首先介绍了基于 OpenAI API 的基本使用,并提供了相应的配置示例。
以后,我们讨论了怎样在 ChatGPT 中使用官方不支持的数据源或模型,以 Flag Studio 为例,通过封装自定义的数据源代码,我们可以实现 ChatGPT 中输出区别的内容。
通过这些方法,我们可以更好地自由使用 ChatGPT,并扩大其功能。未来还可以进行更多有趣的实现,敬请期待。
参考链接:
[1] 例子 1: https://www.zhihu.com/zvideo/1615679760738250752
[2] 例子 2: https://www.zhihu.com/pin/1636158221214887936
[3] 例子 3: https://www.zhihu.com/pin/1637642465724325890
[4] 示例目录: https://github.com/soulteary/docker-chatgpt/blob/main/examples
[5] 接入 OpenAI API 的配置示例: https://github.com/soulteary/docker-chatgpt/tree/main/examples/01.use-OpenAI-API
[6] OpenAI 的 API Key 管理页面: https://platform.openai.com/account/api-keys
[7] OpenAI API 数据源: https://github.com/soulteary/sparrow/blob/main/connectors/openai-api/openai.go
[8] 官方文档页面: https://flagstudio.baai.ac.cn/document
[9] connectors/flag-studio: https://github.com/soulteary/sparrow/tree/main/connectors/flag-studio
[10] 项目中提交你的代码实现: https://github.com/soulteary/sparrow
[11] components/stream-responser/stream_builder.go: https://github.com/soulteary/sparrow/blob/main/components/stream-responser/stream_builder.go
[12] 程序功能开关中: https://github.com/soulteary/sparrow/blob/main/internal/define/define.go
[13] internal/datatypes/models.go: https://github.com/soulteary/sparrow/blob/main/internal/datatypes/models.go
[14] internal/api/models/flagstudio.go: https://github.com/soulteary/sparrow/blob/main/internal/api/models/flagstudio.go
[15] internal/api/models/models.go: https://github.com/soulteary/sparrow/blob/main/internal/api/models/models.go
[16] 关于“交友”的一些建议和看法: https://zhuanlan.zhihu.com/p/557928933
[17] 关于折腾群入群的那些事: https://zhuanlan.zhihu.com/p/56159997
[18] 署名 4.0 国际 (CC BY 4.0): https://creativecommons.org/licenses/by/4.0/deed.zh
如果你觉得这篇文章实用,请点赞并分享给你的朋友。感谢浏览!
本文使用署名 4.0 国际 (CC BY 4.0) 许可协议,欢迎转载、修改和使用,但需要注明来源。
openaiapi修改默许域名的常见问答Q&A
问题1:怎样设置 ChatGPT Web 客户真个域名和 API Key?
答案:你可以依照以下步骤来设置 ChatGPT Web 客户真个域名和 API Key:
- 打开ChatGPT Web客户真个设置界面。
- 找到设置中的”域名”选项,并点击进行编辑。
- 输入你希望设置的域名,并保存更改。
- 回到设置界面,找到”API Key”选项,并点击进行编辑。
- 输入你的 OpenAI API Key,并保存更改。