
完成通过langchain框架使用大模型后,我们学习golang操作向量数据库,qdrant向量数据库支持http协议和grpc协议。grpc协议有个客户端库
github.com/qdrant/go-client/qdrant
首先看下如何使用这个库连接qdrant
package main
import (
"fmt"
"github.com/qdrant/go-client/qdrant"
)
func main() {
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
if err!= nil {
panic(err)
}
fmt.Println(client)
}需要注意的是这里的grpc端口是6334,如果使用6333的话会报如下错误,因为6333是http协议端口
2025/04/05 16:08:22 WARN Unable to get server version, use default err="rpc error: code = Unavailable desc = connection error: desc = \"error reading server preface: http2: frame too large\"" default=Unknown
2025/04/05 16:08:22 WARN Failed to obtain server version. Unable to check client-server compatibility. Set SkipCompatibilityCheck=true to skip version check.接着可以使用对应的函数来进行向量的增删改查,CreateCollection来创建集合,需要指定的参数是向量的大小,和计算距离的函数,这里使用的是cos函数,然后使用Upsert向集合里添加点,每个点包含三个元素,ID、向量、和负载。最后通过Query函数来进行查询,查询的时候需要传入一个向量。并且可以添加查询过滤条件,对负载进行过滤,并决定是否要返回负载内容:
package main
import (
"context"
"fmt"
"github.com/qdrant/go-client/qdrant"
)
func main() {
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
if err!= nil {
panic(err)
}
fmt.Println(client)
err=client.CreateCollection(context.Background(), &qdrant.CreateCollection{
CollectionName: "example_collection",
VectorsConfig: qdrant.NewVectorsConfig(&qdrant.VectorParams{
Size: 4,
Distance: qdrant.Distance_Cosine,
}),
})
if err!= nil {
panic(err)
}
operationInfo, err := client.Upsert(context.Background(), &qdrant.UpsertPoints{
CollectionName: "example_collection",
Points: []*qdrant.PointStruct{
{
Id: qdrant.NewIDNum(1),
Vectors: qdrant.NewVectors(0.05, 0.61, 0.76, 0.74),
Payload: qdrant.NewValueMap(map[string]any{"city": "London"}),
},
{
Id: qdrant.NewIDNum(2),
Vectors: qdrant.NewVectors(0.19, 0.81, 0.75, 0.11),
Payload: qdrant.NewValueMap(map[string]any{"age": 32}),
},
{
Id: qdrant.NewIDNum(3),
Vectors: qdrant.NewVectors(0.36, 0.55, 0.47, 0.94),
Payload: qdrant.NewValueMap(map[string]any{"vegan": true}),
},
},
})
if err != nil {
panic(err)
}
fmt.Println(operationInfo)
searchResult, err := client.Query(context.Background(), &qdrant.QueryPoints{
CollectionName: "example_collection",
Query: qdrant.NewQuery(0.2, 0.1, 0.9, 0.7),
})
if err != nil {
panic(err)
}
fmt.Println(searchResult)
searchResult, err = client.Query(context.Background(), &qdrant.QueryPoints{
CollectionName: "example_collection",
Query: qdrant.NewQuery(0.2, 0.1, 0.9, 0.7),
Filter: &qdrant.Filter{
Must: []*qdrant.Condition{
qdrant.NewMatch("city", "London"),
},
},
WithPayload: qdrant.NewWithPayload(true),
})
if err != nil {
panic(err)
}
fmt.Println(searchResult)
}
如果条件不适合使用grpc,也可以自己手写http请求,走http协议,下面是一个简单的例子:
package main
import(
"net/http"
"bytes"
"encoding/json"
"io/ioutil"
"fmt"
)
func main() {
createCollection()
addData()
}
func createCollection() {
data := Payload {
// fill struct
Vectors {
Size: 768,
Distance: "Dot",
},
}
payloadBytes, err := json.Marshal(data)
if err != nil {
// handle err
}
body := bytes.NewReader(payloadBytes)
req, err := http.NewRequest(http.MethodPut, "http://localhost:6333/collections/romeo", body)
if err != nil {
// handle err
}
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
// handle err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
// handle err
}
// handle response
responseBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
// handle err
}
responseData := Payload{}
err = json.Unmarshal(responseBytes, &responseData)
if err != nil {
// handle err
}
fmt.Println(string(responseBytes))
}
func addData() {
data := AddReq{
// fill struct
Points: []Points{
Points{
ID: 1,
Vector: []float64{0.05, 0.61, 0.76, 0.74},
Payload: AddPayload{
Colony: "Mars",
},
},
Points{
ID: 2,
Vector: []float64{0.19, 0.81, 0.75, 0.11},
Payload: AddPayload{
Colony: "Jupiter",
},
},
Points{
ID: 3,
Vector: []float64{0.36, 0.55, 0.47, 0.94},
Payload: AddPayload{
Colony: "Venus",
},
},
Points{
ID: 4,
Vector: []float64{0.18, 0.01, 0.85, 0.80},
Payload: AddPayload{
Colony: "Moon",
},
},
Points{
ID: 5,
Vector: []float64{0.24, 0.18, 0.22, 0.44},
Payload: AddPayload{
Colony: "Pluto",
},
},
},
}
payloadBytes, err := json.Marshal(data)
if err != nil {
// handle err
}
body := bytes.NewReader(payloadBytes)
req, err := http.NewRequest(http.MethodPut, "http://localhost:6333/collections/star_charts/points", body)
if err != nil {
// handle err
}
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
// handle err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
// handle err
}
// handle response
responseBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
// handle err
}
responseData := Payload{}
err = json.Unmarshal(responseBytes, &responseData)
if err != nil {
// handle err
}
fmt.Println(string(responseBytes))
}
type Payload struct {
Vectors Vectors `json:"vectors"`
}
type Vectors struct {
Size int `json:"size"`
Distance string `json:"distance"`
}
type AddReq struct {
Points []Points `json:"points"`
}
type AddPayload struct {
Colony string `json:"colony"`
}
type Points struct {
ID int `json:"id"`
Vector []float64 `json:"vector"`
Payload AddPayload `json:"payload"`
}创建collection的路径是 http://localhost:6333/collections/{collection_name},保存数据的路径是
http://localhost:6333/collections/{collection_name}/points,返回值如下:
{"status":{"error":"Wrong input: Collection `romeo` already exists!"},"time":0.00016268}
{"result":{"operation_id":2,"status":"acknowledged"},"status":"ok","time":0.010663987}本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!