文章目录
- 认识向量知识库
- 向量
- Embeddings
- 向量数据库
- 向量数据库的作用
- 向量数据库与传统数据库的区别
- Embedding API
- 使用公有Embedding API
- 自定义一个Embeedding API
- 常见文本数据的预处理
- 搭建并使用向量数据库
- 思考
- 向量数据库在LLM中的价值体现
- 向量的妙用,可行???(待验证
- 总结
参考文章
一文带你从零开始理解向量数据库
什么是向量数据库
文本嵌入模型 text-embedding-model
基于LLM+向量库的文档对话痛点及解决方案
百亿级向量检索的向量数据库是如何构建的
认识向量知识库
向量
向量是一个数值数组,用于表示浮点在几个维度上的位置。
在更日常的语言中,向量是一串数字,如:{12, 13, 19, 8, 9}。这些数字表示空间中的某个位置,就像电子表格中的行和列编号表示某个单元格一样(例如:“B7”)。
Embeddings
当我们处理文本数据时,通常需要将文本转换为机器可理解的形式。嵌入(Embeddings)是一种常见的表示文本的方法,它将离散的文本对象(例如单词、句子或文档)映射到具有连续值的向量空间中。
嵌入的目的是为了捕捉文本的语义和语法信息,以便在后续的任务中能够更好地使用。通过使用嵌入,我们可以在文本数据上进行更多的数值计算和机器学习任务,例如文本分类、聚类、情感分析等。
词嵌入模型会用密集数字向量表示一个词语。这些向量的目的是采集词语的语义属性;如果词语的向量相近,则它们在语义意义上应该相似。在良好的嵌入实践中,向量空间的方向与词语意义的不同方面密切相关。举例说明,“加拿大”的向量可能在一个方向上与“法国”相近,而在另一个方向上则与“多伦多”相近。
Embeddings就相当于一个“桥梁” —— 翻译:把图片,文字,视频以及音频全部转换为数字,并且包含了数据的信息,使得大模型都能”懂“,能利用这些数字去做训练和推理
向量数据库
向量数据库是以数学形式存储的数据集合。向量数据库使机器学习模型更容易记住以前的输入,从而使机器学习能够用于支持搜索、推荐和生成文本等使用案例。可以根据相似性指标而不是精确匹配来识别数据,从而使计算机模型能够理解数据的上下文。
当顾客逛鞋店时,售货员可能会向顾客推荐与顾客喜欢的那双鞋相似的鞋子。同样,在电子商务商店中购物时,商店可能会在诸如“客户还购买了…”之类的标题下推荐类似的商品。向量数据库使机器学习模型能够识别相似的对象,就像售货员可以找到相似的鞋子一样,电子商务商店可以推荐相关的产品。(事实上,电子商务商店可能会使用此类机器学习模型来完成这项工作)。
总之,向量数据库使计算机程序能够进行比较、识别关系和理解上下文。这使得创建大型语言模型 (LLM) 等先进的人工智能 (AI) 程序成为可能。
向量数据库的作用
- 相似度和语义搜索:向量数据库允许应用程序将相关项目连接在一起。聚类在一起的向量是相似的,很可能彼此相关。这不仅能帮助用户搜索相关信息(如图像搜索),还能帮助应用程序执行以下操作:推荐类似产品、推荐歌曲、电影或节目、推荐图像或视频
- 机器学习和深度学习:将信息的相关项目连接起来的能力使得构建能够完成复杂认知任务的机器学习(和深度学习)模型成为可能。
- 大型语言模型 (LLM) 和生成式 AI:LLM(如 ChatGPT 和 Bard 所基于的 LLM)依赖向量数据库来对文本进行上下文分析。通过将单词、句子和观点相互关联,LLM 可以理解人类的自然语言,甚至可以生成文本。
向量数据库与传统数据库的区别
1)数据规模超过传统的关系型数据库,
传统的关系型数据库管理1亿条数据已经是拥有很大的业务流量,而在向量数据库需求中,一张表千亿数据是底线,并且原始的向量通常比较大,例如512个float=2k,千亿数据需要保存的向量就需要200T的存储空间(不算多副本),单机显然不具备这种能力,可线性扩展的分布式系统才是正确的道路,这对系统的可扩展性,可靠性,低成本提出非常大的挑战。
2)查询方式不同,计算密集型
传统的数据库查询通常可以归结为点查和范围查,而无论是点查和范围查都是一种精确查找,即查询得到的结果要么符合条件要么不符合条件,而向量数据库的向量查询通常是近似查找,即查找与查询条件相近的结果,即查询得到的结果是与输入条件最相似的,而近视比较对计算能力要求非常高。
3)低时延与高并发
Embedding API
使用公有Embedding API
DataWhale提供了以下三种公有Embedding API的调用介绍
- 使用OpenAI API
- 使用文心千帆API
- 使用智谱API
自定义一个Embeedding API
在此列出一些公开的embeedding_model,Langchain原生支持加载embeedding_model,动手能力强的小伙伴可以根据文档动手实现一个embeedding api.
文本嵌入模型 text-embedding-model
- nghuyong/ernie-3.0-nano-zh
- nghuyong/ernie-3.0-base-zh
- shibing624/text2vec-base-chinese
- GanymedeNil/text2vec-large-chinese
常见文本数据的预处理
-
采集数据
采集数据主要是通过爬虫等手段获取大量目标数据,相关数据越多,构建的知识库越健全。 -
读取数据
langchain包已经实现了多种类型(.md、.pdf、.txt …)文档的加载方法,以下路径的代码可供参考
langchain/document_loaders:
/anaconda3/envs/skgb/lib/python3.9/site-packages/langchain/document_loaders/blob_loaders
-
清洗数据
清洗数据是为了方便后一步文档分割所做的预处理,将容易影响向量收缩的符号去除,如两个换行符组成的分段符号。 -
文档分割
文章的切分及关键信息抽取
关键信息: 为各语义段的关键信息集合,或者是各个子标题语义扩充之后的集合(pdf多级标题识别及提取见下一篇文章)语义切分方法1:利用NLP的篇章分析(discourse parsing)工具,提取出段落之间的主要关系,譬如上述极端情况2展示的段落之间就有从属关系。把所有包含主从关系的段落合并成一段。 这样对文章切分完之后保证每一段在说同一件事情.
语义切分方法2:除了discourse parsing的工具外,还可以写一个简单算法利用BERT等模型来实现语义分割。BERT等模型在预训练的时候采用了NSP(next sentence prediction)的训练任务,因此BERT完全可以判断两个句子(段落)是否具有语义衔接关系。这里我们可以设置相似度阈值t,从前往后依次判断相邻两个段落的相似度分数是否大于t,如果大于则合并,否则断开。当然算法为了效率,可以采用二分法并行判定,模型也不用很大,笔者用BERT-base-Chinese在中文场景中就取得了不错的效果。
def is_nextsent(sent, next_sent):encoding = tokenizer(sent, next_sent, return_tensors="pt",truncation=True, padding=False)with torch.no_grad():outputs = model(**encoding, labels=torch.LongTensor([1]))logits = outputs.logitsprobs = torch.softmax(logits/TEMPERATURE, dim=1)next_sentence_prob = probs[:, 0].item()if next_sentence_prob <= MERGE_RATIO:return Falseelse:return True
语义段的切分及段落(句子)关键信息抽取
如果向量检索效率很高,获取语义段之后完全可以按照真实段落及句号切分,以缓解细粒度知识点检索时大语块噪声多的场景。当然,关键信息抽取笔者还有其他思路。
方法1:利用NLP中的成分句法分析(constituency parsing)工具和命名实体识别(NER)工具提取,前者可以提取核心部分(名词短语、动词短语……),后者可以提取重要实体(货币名、人名、企业名……)。譬如说:
原始文本:MM团队的成员都是精英,核心成员是前谷歌高级产品经理张三,前meta首席技术官李四……
关键信息:(MM团队,核心成员,张三,李四)
方法2:可以用语义角色标注(Semantic Role Labeling)来分析句子的谓词论元结构,提取“谁对谁做了什么”的信息作为关键信息。类似的方向还有依存分析(dependency parsing),依存分析可以对一个句子构建一棵树,我们只需要去除树的最后几层,即可得到一个句子的关键信息。有一个又快又好的方法biaffine,推荐开源实现SuPar。
方法3:直接法。其实NLP的研究中本来就有关键词提取工作(Keyphrase Extraction)。也有一个成熟工具可以使用。一个工具是 HanLP ,中文效果好,但是付费,免费版调用次数有限。还有一个开源工具是KeyBERT,英文效果好,但是中文效果差。
方法4:垂直领域建议的方法。以上两个方法在垂直领域都有准确度低的缺陷,垂直领域可以仿照ChatLaw的做法,即:训练一个生成关键词的模型。ChatLaw就是训练了一个KeyLLM。
搭建并使用向量数据库
之前写过加载text2vec-large-chinese 模型的api,并录入qdrant数据库中,在此贴出一些参考代码
# 加载embedding_modelembedding_model = SentenceTransformer(settings.model_path, device=settings.device)# 使用embedding_model对text进行向量化vectors = self.embedding_model.encode(texts, show_progress_bar=False, batch_size=128).tolist()# 组装doc。设计metainfo,便于后续业务过滤搜索points=createpoints(ids=ids,vectors=vectors,payloads=payloads)# 录入qdrant
qdrantDao.batchSavePoints(points)
思考
向量数据库在LLM中的价值体现
1、成本相对较低
将私域知识录入向量数据库,作为大模型的外部知识库,不需要去训练模型,比常见的大模型微调地方法成本更低、速度更快也能通过更新数据库保证AI大模型知识的实时更新。
2、隐私性更高
私域信息没有落地互联网,而是存在本地环境,减小了隐私信息泄漏的风险。
3、查询速度更快、并发能力更强
相对传统关系型数据库如pgsql、结构化数据库es都加入了向量搜索的支持:
- pgvector 是一个基于 PostgreSQL 的扩展,为用户提供了一套强大的功能,用于高效地存储、查询和处理向量数据。
- 从 7.3 开始,Elasticsearch 在其原生脚本语言中提供了一个 cosineSimilarity(余弦相似度)函数。
鉴于本人对PostgreSQL和es的了解未深入到源码层面,在此引用百度智能云大数据技术负责人 李莅的回答。
以下回答摘自百亿级向量检索的向量数据库是如何构建的
InfoQ:虽然您认为它是刚需,但也有人认为我可能不是需要一款企业级的向量数据库,而是需要一个向量引擎。我可以在传统的数据库上加一个向量引擎,然后它就变成了一款向量数据库,您觉得他们这样的想法是可行的吗?
李莅:单从场景和功能出发,我觉得在传统的数据库,或者是一些 NoSQL 的数据库上去加上向量能力是完全行得通的。
但是,当业务的规模发展得很大之后,那传统的数据库加上向量引擎就不一定能搞得定了。这时可能就需要一个更加跟向量检索耦合的技术实现,来保证向量检索这一部分的性能需求。比如一款大模型应用,要支持上亿用户访问量,这个量级肯定就不是一个传统的数据库可以搞定的,它上面就肯定要做各种架构考量,比如存算分离之类的技术去保证它的规模能够扩展。
向量的妙用,可行???(待验证
今天学习向量数据库时候想到了一个idea:大模型的聊天受token限制,如果超过指定token长度,会将最先的聊天给忘记。那么对于一个长连接沟通的模型,如个人管家助手,受token长度限制会影响用户体验。
用户:我想要训练OCR模型,识别钢琴谱子的音符。LLM:训练一个OCR(Optical Character Recognition)模型来识别钢琴谱子的音符是一个有趣且具有挑战性的项目。以下是一些步骤和建议,可以帮助你开始这个项目:1. 数据收集首先,你需要收集钢琴谱子的图像数据作为训练集。这些图像可以是现有的公开数据集,或者你自己拍摄或扫描的钢琴谱子图像。2. 数据预处理对收集到的图像进行预处理,以便模型更好地学习。预处理步骤可能包括:XXXXX用户:明天我要8点起床,麻烦帮我定制闹钟LLM:好的,闹钟已经为你设置。--- 经过一系列对话(LLM已经忘记最开始训练OCR模型的对话) ---用户:我需要继续昨天的OCR训练模型工作,来一起讨论接下来的数据预处理和模型选择吧LLM:(此刻因为没有提供较多思考时间给大模型,回答可能会脱离实际,出现幻读)
为解决token长度限制,优化用户体验,可以考虑将历史近一个月的对话数据进行切分处理,录入数据库,等到用户输入question时,先对questiion向量化,通过向量匹配出向量数据库中最相似的几段对话记录,将结果和用户的question结合成最新的Prompt进行提问。这样模型回答会更贴近用户需求(最起码模型知道用户是想训练有关钢琴谱子的OCR model)
总结
本节了解了什么是向量、向量的生成、向量的存储和向量的应用,同时对比了向量数据库和常见非向量数据库的区别。动手设计了一个加载text2vec-large-chinese embedding model的api接口,并且将生成的向量录入到向量数据库中。在本节的学习中,本人思考了向量数据库在LLM中的价值体现,同时提出了一种通过向量检索优化prompt的方法(待验证)