1、前语
-
3、惊讶,竟然能够在ChatGPT的GPT-4模型让它扮演Linux服务器 建立K8s和docker环境
-
2、从零开始构建根据ChatGPT的嵌入式(Embedding)本地医疗客服问答机器人模型(看完就会,看到最终有惊喜)
-
1、GPT-4凌晨已发布赶紧恳求,前端小白用最近用刚学的golang对接了GPT-3.5的6个接口
代码全部开源,GitHub地址为: github.com/aehyok/go-o…
前端彻底也能建立, 前端彻底也能建立, 前端彻底也能建立, 本文中我运用的是后端言语golang,来调用的一切外部接口,但它们均是restful api,所以假如你运用的是其他言语,那么是彻底能够替换的,包含nodejs或许直接运用前端恳求都是能够实现我的功能的。后边有机会会运用vue3来添加一个页面,现在首要经过postman或许apifox来调试接口,首要为了验证逻辑想法。
接下来首先来看看embeddings到底是什么吧
1.1、 官网的介绍是这样的
能够被使用于以下几种状况
- 查找(根据查询字符串的相关性对成果进行排名)
- 聚类(根据类似性对文本字符串进行分组)
- 引荐(具有相关文本字符串的项目被引荐)
- 反常检测(辨认关联度小的反常值)
- 多样性丈量(对类似性分布进行分析)
- 分类(文本串按其最类似的标签进行分类)
本文将首要学习第一种状况:查找,根据相关性进行排名。也能够了解成查找完必定会有成果,可是相关性有或许很低,有或许需求用户加以鉴别。出来的信息或许不是用户需求的答案。
1.2、 而chatgpt是这样跟我说的
1.3、最终我的一句话了解就是:它能够将文本转化为固定长度的接连向量。
比方我下面运用的
text-embedding-ada-002
模型输出的向量维度就是1536,这个在官网是有描述的,大家能够仔细看看), 同时它是能够将任意的文本转化为向量。
那么接下来我会根据我的思路把我整个的建立流程和调试思路都展现出来,便利自己后边进行温习查阅,也便利或许需求的你。
2、架构流程图介绍
从上图能够比较明晰明晰的知道大致要干什么了
- 预备测验数据:测验数据或许许多一个很大的数组,慢慢经过调用ChatGPT接口进行转化数据,然后将转化后的向量数据存储到qdrant云数据库中,相当于本地数据了。
- 根据查询回来成果:首先仍是将要查询的字符串调用ChatGPT接口转化为向量数据,然后再将向量数据与向量数据库中的进行匹配类似度,匹配结束能够再经过GPT-3.5或许GPT-4的模型接口进行进一步的优化数据处理。
接下来就根据如下过程一步步进行建立
- Qdrant云数据库的建立
- 预备测验数据并写入云数据库
- 进行查询并回来成果
3、Qdrant云数据库的建立
3.1、初识Qdrant
说白一点就是为了存储我自己的测验数据,不过它的要点是存储向量数据。
来到github上看了一下:github.com/qdrant/qdra… , 有点牛逼 并且是Rust写的。那就来试试玩玩呗。
3.2、创立云数据库
经过github能够直接到云官网: Vector Search Database | Qdrant Cloud
能够看到能免费创立一个免费套餐,拿来做个测验仍是十分便利的。
针对图示的装备,能够永久免费运用,所以根本的测验是没问题了,能够好好的愉快玩耍。
找到左边菜单Clusters
然后右侧点击 Create
,输入一个cluster
名称(是不是能够翻译为集群名称??)。创立后等候一瞬间在进行初始化。
点击上面的api-key
或许左边 Access
都能够创立访问云数据库的链接和api-key。
记得仿制好哟,这个跟ChatGPT生成的API-Key一样,只能看到一次,所以要保存好。
3.3、经过curl 接口访问
Swagger UI (qdrant.tech) 这个就是官方供给给咱们的Swagger。可视化 RESTful Web Api
我是经过这个首要看接口以及接口参数,首要仍是经过postman或许apifox等东西来测验接口,swagger这儿如同没有装备api-key的当地?
ok能够看到我之前创立的 collect
还在,其实这个时分本来是要创立一个collect
集合(在联系型数据库中能够叫做table表)。
4、写入测验数据
4.1、预备测验数据
留意:以上数据来源于ChatGPT,仅供参阅和测验运用
然而我想要的数据结构是json数组的,那么继续运用ChatGPT进行装逼
能够发现预备这一组测验数据,有一点不费吹灰之力的感觉,真是太爽了。
这儿就是预备的json数组,一共13条简略的记载而已,首要是为了看一下作用
[ { "title": "伤风", "text": "伤风是一种由病毒引起的呼吸道感染。典型症状包含喉咙痛、流鼻涕、咳嗽、打喷嚏、头痛和发热。" }, { "title": "流感", "text": "流感(Influenza)是一种由流感病毒引起的呼吸道感染。症状与伤风类似,但一般更严重,包含高热、寒战、喉咙痛、咳嗽、鼻塞、肌肉痛和乏力。" }, { "title": "肠胃炎", "text": "肠胃炎是胃和肠道的炎症,一般由病毒、细菌或寄生虫感染引起。症状包含腹泻、呕吐、腹痛、厌恶、发热和脱水。" }, { "title": "常见皮肤病", "text": "如湿疹、皮炎、脓疱疮、疱疹等。症状或许包含红肿、瘙痒、枯燥、脱皮和痛苦。" }, { "title": "头痛", "text": "头痛有许多原因,如压力、严重、缺水、缺乏睡眠等。头痛或许表现为钝痛、搏动痛、集中在头的某个部位等。" }, { "title": "过敏", "text": "过敏是免疫系统对外来物质(过敏原)的反常反响。症状包含打喷嚏、流鼻涕、鼻塞、喉咙痛、眼睛痒、红肿和喘息。" }, { "title": "高血压", "text": "高血压是血压继续升高的病状。许多高血压患者没有显着症状,但或许会引发头痛、眩晕、心悸和呼吸困难。" }, { "title": "糖尿病", "text": "糖尿病是一种因为胰岛素排泄不足或细胞对胰岛素反响不良导致的血糖水平过高的疾病。症状包含频繁的小便、口渴、饥饿、疲惫、视力含糊、感染和创伤愈合缓慢。" }, { "title": "哮喘", "text": "哮喘是一种缓慢呼吸道炎症疾病,表现为气道对刺激物的过度反响。症状包含喘息、呼吸困难、胸闷和咳嗽。" }, { "title": "背痛", "text": "背痛或许是因为肌肉拉伤、韧带损害、关节炎、椎间盘问题等原因引起的。症状包含继续或间歇性的背部痛苦、生硬和肌肉痉挛。" }, { "title": "关节炎", "text": "关节炎是关节炎症的一个通用术语,或许是因为多种原因引起的,如磨损性关节炎、类风湿性关节炎等。症状包含关节痛苦、肿胀、生硬和活动受限。" }, { "title": "痔疮", "text": "痔疮是肛门或直肠血管的炎症或肿胀。症状包含肛门痛苦、瘙痒、肿胀、出血和或许的肛门突出物。" }, { "title": "眼疾", "text": "如干眼症、结膜炎和近视等。症状或许包含眼睛枯燥、瘙痒、红肿、排泄物和视力含糊。" }]
4.2、go代码将测验数据转化为向量数据
这儿暂时就要用到ChatGPT的接口了
看官网接口恳求首要就两个参数,一个就是model
选择模型,我这儿运用的是text-embedding-ada-002
,另外一个input
就是咱们要转化的数据字符串了,好了直接上代码看看
func GetEmbeddings(ctx *gin.Context) dto.ResponseResult {
// 装备日志
data, _ := ctx.GetRawData()
var parameters map[string]interface{}
// 包装成json 数据
_ = json.Unmarshal(data, ¶meters)
input := parameters["input"].(string)
// n := m["n"].(int)
// size := m["size"].(string)
var response = GetEmbeddingApi(input)
var obj map[string]interface{}
if err := json.Unmarshal(response, &obj); err != nil {
panic(err)
}
fmt.Println("Body:", obj)
return dto.SetResponseData(obj)
}
func GetEmbeddingApi(input string) []byte {
// 界说恳求参数
embeddingModel := EmbeddingModel{
Model: "text-embedding-ada-002",
Input: input,
}
// 界说恳求地址
url := utils.OpenAIUrl + `/v1/embeddings`
// 将恳求参数转化为json格式
bytes, err := json.Marshal(embeddingModel)
if err != nil {
fmt.Println("Error:", err)
// return dto.SetResponseFailure("调用openai产生过错")
}
// 界说恳求
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req)
req.SetRequestURI(url)
req.Header.SetMethod("POST")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+utils.OpenAIAuthToken)
req.SetBody(bytes)
// 界说响应
resp := fasthttp.AcquireResponse()
defer fasthttp.ReleaseResponse(resp)
if err := fasthttp.Do(req, resp); err != nil {
fmt.Println("Error:", err)
// return dto.SetResponseFailure("调用openai产生过错")
}
fmt.Println("Status:", resp.StatusCode())
return resp.Body()
}
我在代码里添加了详细的注释,对照代码看一下应该仍是比较好了解的。
这儿其实就是经过go言语调用restful 接口
https://api.openai.com/v1/embeddings
恳求,因为下面查询的时分还需求将查询字符串转化为向量数据,所以我单独进行了封装能够在两个当地调用
4.3、循环上述办法将预预备的json测验数据全部转化为向量数据
// 解析恳求参数
var jsonData []map[string]string
if err := c.Bind(&jsonData); err != nil {
return dto.SetResponseFailure("error")
}
if len(jsonData) == 0 {
return dto.SetResponseFailure("json is empty")
}
// 数据向量化
points := make([]Point, 0)
for _, v := range jsonData {
// 获取文本内容
input := v["text"]
// 获取文本内容的向量
response := GetEmbeddingApi(input)
fmt.Println(response, "response----response")
var embeddingResponse EmbeddingResponse
json.Unmarshal(response, &embeddingResponse)
points = append(points, Point{
ID: uuid.New().String(),
Payload: v,
Vector: embeddingResponse.Data[0].Embedding,
})
}
4.4、将上面预备好的向量数据数组全部写入向量数据库
现在向量数据经过ChatGPT接口转化好了,现在就需求将向量数据写入到Qdrant云数据库中。 下面首要是调用了CreatePoints办法,同样能够看看
pr := PointRequest{
Points: points,
}
//存储
err := CreatePoints(utils.QdrantCollectName, pr)
if err != nil {
// common.Logger.Error(err.Error())
// c.JSON(http.StatusOK, common.Error(err.Error()))
// return
return dto.SetResponseFailure("数据上传产生过错")
}
// c.JSON(http.StatusOK, common.Success(nil))
return dto.SetResponseSuccess("数据上传成功")
其实相对来说我前面也写过的,就是来调用Restful api写入到云数据库。
func CreatePoints(collectionName string, pointRequest PointRequest) (err error) {
response := &CommonResponse{}
var reqBytes []byte
reqBytes, err = json.Marshal(pointRequest)
if err != nil {
return
}
body, err := middleware.Send(http.MethodPut, collectionApi+"/"+collectionName+pointsApi+"?wait=true", reqBytes)
if err != nil {
return
}
err = json.Unmarshal(body, &response)
if err != nil {
return
}
if response.Result == nil {
return errors.New(response.Status.(map[string]interface{})["error"].(string))
}
return
}
这儿其实就是经过go言语调用restful 接口
https://ui.qdrant.tech/#/points/upsert_points
(点击检查详细的接口概况) 恳求
现在测验数据有了,向量数据库也有了,上一末节将测验数据转化为了向量数据,这儿上面刚刚又写好了向量数据写入云数据库的接口。那么写入数据的根本完成了。
经过运行接口来调试一下吧
5、开始查询数据
预备好查询数据,先经过##3.2
将字符串转化为向量数据(也就是为什么进行封装上面的办法的原因),然后经过向量数据去查询云数据库,去查询类似度了
5.1、将查询字符串转化为向量数据
那么这儿就先预备一下查询云数据库的接口
var message ChatMeMessage
if err := c.Bind(&message); err != nil {
// c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
// return
}
response := GetEmbeddingApi(message.Text)
json.Unmarshal(response, &response)
fmt.Println(response, "response----response")
var embeddingResponse EmbeddingResponse
json.Unmarshal(response, &embeddingResponse)
这儿其实就是经过go言语调用restful 接口
https://api.openai.com/v1/embeddings
恳求
这儿留意一下,我了解的正常的话只要云数据库有数据,就会回来数据的,无非类似度低一些而已。
5.2、根据向量来查询匹配相关性高的前三条记载
预备查询参数数据,然后到Qdrant云数据库进行查询
params := make(map[string]interface{})
params["exact"] = false
params["hnsw_ef"] = 128
sr := PointSearchRequest{
Params: params,
Vector: embeddingResponse.Data[0].Embedding,
Limit: 3,
WithPayload: true,
}
//查询类似的
res, err := SearchPoints(utils.QdrantCollectName, sr)
if err != nil {
// common.Logger.Error(err.Error())
// c.JSON(http.StatusOK, common.Error(err.Error()))
// return
}
这儿其实就是经过go言语调用restful接口
https://ui.qdrant.tech/#/points/search_points
(点击检查详细的接口概况) 恳求
5.3、经过chatGPT对查询的相关性数据进行优化
其实上面查询出来数据列出来就完事了,可是我上面也说了相关性的问题,那么这儿咱们能够经过ChatGPT关于查询回来的数据加工一下。
//拼装本地数据
localData := ""
for i, v := range res {
re := v.Payload.(map[string]interface{})
localData += "\n"
localData += strconv.Itoa(i + 1)
localData += "."
localData += re["title"].(string)
localData += ":"
localData += re["text"].(string)
}
messages := make([]ChatCompletionMessage, 0)
q := "运用以下段落来回答问题,假如段落内容与\"" + message.Text + "\"不相关就经过查询回来信息。"
q += localData
system := ChatCompletionMessage{
Role: "system",
Content: "你是一个医院问诊客服机器人",
}
user := ChatCompletionMessage{
Role: "user",
Content: q,
}
messages = append(messages, system)
messages = append(messages, user)
var chatResponse = GetChatCompletionsApi(messages)
var obj map[string]interface{}
if err := json.Unmarshal(chatResponse, &obj); err != nil {
panic(err)
}
fmt.Println("Body:", obj)
// 最终我经过一个办法进行一致回来参数处理
return dto.SetResponseData(obj)
5.4、调试作用
这是我经过GPT-3.5模型的接口调试其回来成果并不是十分理想。可是假如经过GPT-4.0就彻底能够达到我想要的成果了
当然了我这儿演示的数据较少,仅用作演示作用,可是这种简略的问答形式加上最终GPT来润饰优化有点好用了。并且还能够进行优化,比方问的问题是本地没有的,经过GPT回答后,能够进行操作,将当前问答回写到本地云数据库,这样下次再有类似的问答,就能够直接运用本地的数据了,这儿仅仅供给一点点的我思考的逻辑,不必定是对的。
6、总结
这个关于我来说,了解起来仍是蛮费劲的,首要是一开始没有抓到要点,其实现在把思路捋顺了,从使用的层面来看也就那么回事,当然了现在我的了解仍是比较粗浅的,有待机会进一步深入探索,大数据练习模型。是不是能够考虑练习一个自己的AI虚拟人。当然还有另外一个Fine-Tunes 跟Embedding有没有联系,我得继续研讨研讨了,感觉上仍是十分好玩的。
再次声明本文一切代码都已上传github github.com/aehyok/go-o…
本文首要参阅:github.com/coderabbit2…, 也感谢大佬的及时回复解答我的疑问。
我的个人博客:vue.tuokecat.com/blog
我的个人github:github.com/aehyok
我的前端项目:pnpm + monorepo + qiankun + vue3 + vite3 + 东西库、组件库 + 工程化 + 自动化
不断完善中,全体结构都有了
在线预览:vue.tuokecat.com
github源码:github.com/aehyok/vue-…
7、惊喜多多
当然有或许许多巨佬比我知道的还早
惊喜就是: Cursor | Build Fast一个现在免费运用GPT-4模型的生成代码,学习代码,修改代码,发现bug,处理bug的东西,可直接翻开项目文件进行实操
惊喜就是:www.steamship.com假如你想调用GPT-4的接口,但苦于恳求还在等候列表,那么你能够测验一下这个,留意现在也是免费哟
惊喜就是:假如你想调用官方openai.com的接口,那么能够考虑一下这个第三方平台 api2d.com/r/186083,现在…
本文正在参与「金石方案」