相关文章推荐
玩足球的爆米花  ·  vector push_back ...·  2 周前    · 
刚毅的打火机  ·  python - ImportError: ...·  1 年前    · 
傲视众生的伤疤  ·  openssh - SSH Error ...·  1 年前    · 

尝试使用Chinese-LLaMA-Alpaca-知识库篇

27 天前

上周写完了 量化篇 ,基本上从模型精调到部署使用,我们已经讲完了如何利用现有的Chinese-LLaMA-Alpaca库训练自己的领域模型,实施部署,最终整合到业务系统里的整体流程。综合使用文章中的脚本和工具,完全可以实现模型自由。

但是就像ChatGPT要引入插件机制一样,我们可以和AI聊天,但是单纯的聊天无法满足所有的需求,聊天中,AI也可能出现虚构信息,幻觉回答等问题,这时如果辅助一个知识库就可以很好的解决这个问题。也就是将整体框架补全成这样:

对于更为详细的领域资料,他们可能无法整合到对话里,我们需要把他们做成资料,资料进行向量化,存储到向量数据库中,再通过向量数据库的匹配搜索功能,和AI提供的对话结果进行整合,实现真正的领域服务。

今天要介绍我们使用Milvus向量数据库建设知识库的一些工作,仅介绍搭建和基础的使用,详细的优化工作目前我们还没开始。

几点介绍

什么是Milvus Vector DB?

Milvus 是一个用于向量(Vector)存储和检索的特殊数据库,由国内的创业公司 Zilliz 开发。

什么是向量数据库?

我们在用图片搜索图片,或者语音搜索语音的时候,在数据库中存储和对比的并不是图片和语音片段,而是通过DL等算法提取出来的“特征”,一般是256/512个float数组,可以用数学中的向量来表示。
向量数据库就是用来存储,检索,分析向量的数据库。

为什么做对话服务需要向量数据库?

这段是我自己的理解了,AI生成模型,目前看还是有很多的问题,我们可以看到人提到ChatGPT“撒谎”的问题,愿意在于生成模型只能做语言层面的思考,生成结果是思考得到的结论,而结论是否确实和现实情况一致,还需要进一步的和资料进行验证,这种验证就是靠在向量数据库中查找相似内容,并完成最佳匹配进行的。

Milvus安装

参考 主页面 教程,下载docker-compose.yml文件,使用docker-compose启动即可在本机部署一个单机版本。单机版本内存要求较高,需要16G以上的内存,加之其单独无法服务,还需要额外的服务,因此对机器性能要求还是比较高的。

需要注意的是,官方指引是使用下面的命令启动,如果你启动之后,发现无法访问通信端口,请尝试去掉最后的“-d”让他前台执行,以便发现错误。

sudo docker-compose up -d

我们遇到的问题

我们在执行中出现了因为系统http代理造成milvus和依赖的etcd服务无法通信的问题,后来解决办法是修改了docker配置文件中的http proxy选项才得以顺利完成。

Milvus使用

创建数据库

如果正常完成和数据库的连接,我们就可以开始规划我们的数据库了,和普通数据库一样,我们需要规划表结构,

创建可以参考官方文档:

官方文档的一些没有说明的问题,这里我补充一下:

1)String对应的是Varchar,需要指定一个最大长度。

2)每个表对应有一个主键,用PrimaryKey:true参数指定(GO,其他语言略有不同),如果该主键没有指定值的话,可以另行指定AutoID:true来指定自动生成ID

3)这是所有支持的字段类型:

// Match schema definition
const (
	// FieldTypeNone zero value place holder
	FieldTypeNone FieldType = 0 // zero value place holder
	// FieldTypeBool field type boolean
	FieldTypeBool FieldType = 1
	// FieldTypeInt8 field type int8
	FieldTypeInt8 FieldType = 2
	// FieldTypeInt16 field type int16
	FieldTypeInt16 FieldType = 3
	// FieldTypeInt32 field type int32
	FieldTypeInt32 FieldType = 4
	// FieldTypeInt64 field type int64
	FieldTypeInt64 FieldType = 5
	// FieldTypeFloat field type float
	FieldTypeFloat FieldType = 10
	// FieldTypeDouble field type double
	FieldTypeDouble FieldType = 11
	// FieldTypeString field type string
	FieldTypeString FieldType = 20
	// FieldTypeVarChar field type varchar
	FieldTypeVarChar FieldType = 21 // variable-length strings with a specified maximum length
	// FieldTypeBinaryVector field type binary vector
	FieldTypeBinaryVector FieldType = 100
	// FieldTypeFloatVector field type float vector
	FieldTypeFloatVector FieldType = 101

注意,如果要用向量相似搜索,对应的向量字段要用最下面两类

4)每个表至多有一个向量类型

5)Vector字段需要有一个dim参数,例子中是2,实际使用中看你用哪个embedding,我们用llama的embedding,维度是4096。(embedding是什么?下一章讲)

6)有一点需要提醒的是,vector字段是处理后的向量数据,无法表征原始数据,如果一个字段既用来搜索,又需要显示,需要创建一个vector字段和一个原始字段。

7)记得创建一个索引,索引是和vector字段配套的相似度计算方法,不同的索引适合不同的数据类型和不同的搜索需求,这里搜到一篇比较文章:

我们暂时是用的基础的IvfFlat,深入的性能比较还没完成,有做过的小伙伴记得说一声,和大语言模型配套哪个合适。

添加和搜索数据

添加数据没有特别可以讲的,参考官方文档即可: Insert Entities Milvus documentation ,只是其中vector字段的构建,我们放到最后一起讲。

搜索讲一下他支持的搜索方式,前面我们讲到字段分为两类,一类是原始数据,一个是vector向量数据,对应的搜索方式有query和search

query对应原始数据搜索,这个类比普通数据库的搜索,具体条件通过一个表达式传递,官方文档见 这里 ,和一般sql仍有差距。

search对应向量搜索,会根据匹配算法搜索最相似的数据。每个返回结果有一个相似度打分,分数越小,表示越相近。

返回结果这块官方文档讲的少,是个比较大的槽点。

返回结果首先是一个数组,但是数组的内容并不是一条数据,而是按列存储的多条返回结果,目前暂不清楚第一级的数组到底表示什么意思,我们的单机版第一级数量一直是1,分享一下我们处理结果的代码

//返回的结果数组一直都是1长度
	fmt.Println("searchResult:", len(searchResult))
	for _, sr := range searchResult {
		briefs = make([]Brief, sr.ResultCount)
//每个result包含多个Scores,对应这个结果里多个具体结果的分数
		fmt.Println(sr.Scores)
//每个resuult又包含多个Fields,对应搜索时要求返回的每一个字段
		for _, field := range sr.Fields {
//需要按名称对应到结果的每一个字段里
			switch field.Name() {
			case "command_name":
				for k, v := range field.FieldData().GetScalars().GetStringData().Data {