本文探讨了使用ChatGPT文本Embedding与Qdrant向量数据库构建智能问答系统的技术方法。文章首先介绍了向量数据库的概念及其在语义搜索和智能推荐中的应用。随后,详细介绍了Qdrant向量数据库的部署和操作方法,并展示了如何将文本数据量化并存储于Qdrant中。最后,通过实际示例演示了如何利用OpenAI的文本Embedding和Qdrant向量数据库实现智能问答系统,并展示了系统的运行结果。
前言
什么是向量数据库?
种特殊类型的数据库,它专门用于存储和查询向量数据。
在向量数据库中,数据以向量的形式进行表示和存储。这些向量可以是数学空间中的点,用于表示各种数据类型,如图像、文本、音频
等。向量数据库的设计旨在有效地支持相似性搜索和查询,使得可以快速找到在向量空间中相邻或相似的数据项。
向量数据库结合ChatGPT带来了什么
语义搜索: 使用向量数据库进行语义搜索,可以更准确地找到与查询相关的信息。ChatGPT可以理解用户的自然语言查询,而向量数据库可以根据语义相似性返回匹配的向量数据。
智能推荐: 结合ChatGPT的智能理解和向量数据库的相似性搜索,可以实现更智能的推荐系统。系统可以根据用户的历史行为和语境,向用户推荐相似的向量数据,如文章、产品或其他内容。
自然语言处理与向量表示结合: ChatGPT可以将自然语言转换为向量表示,这样就可以在向量数据库中进行更高效的查询。这种集成使得自然语言处理和向量数据库可以相互补充,提高整体系统的性能。
Qdrant 感谢ChatGPT对本文创作的大力支持
简介 Qdrant “是一个矢量相似性搜索引擎,它提供了一种生产就绪的服务,具有方便的应用程序接口,可以存储、搜索和管理带有附加有效载荷的点(即矢量)”。您可以将有效载荷视为附加信息,它可以帮助您调整搜索,还可以接收有用的信息提供给用户。(译至[官方文档](What is Qdrant? - Qdrant )
部署 采用最简单的Docker部署方法, 生产最佳实践请参考[官方文档](Interfaces - Qdrant )
1 2 3 docker run -itd --name dev-qdrant -p 6333:6333 \ -v $(pwd)/qdrant_storage:/qdrant/storage \ qdrant/qdrant
http://ip:6333/dashboard
向量结合OpenAI 文本量化后入库 1 pip install openai==0.28 qdrant_client
demo.txt 测试数据
1 2 3 4 5 6 7 8 9 10 11 # 创建 collection from qdrant_client import QdrantClient from qdrant_client.http.models import PointStruct from qdrant_client.http.models import Distance, VectorParams qdrant_client = QdrantClient("10.110.150.64", port=6333) qdrant_client.recreate_collection( collection_name="demo_qa", vectors_config=VectorParams(size=1536, distance=Distance.COSINE), ) print("Create collection reponse:", qdrant_client)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import openai openai.api_key = 'sk-**********' # 读取测试数据 with open('demo.txt', 'r') as f: t = '' for line in f: if '## ' in line: # 根据##判断数据开头 # 问题开头 if t != '': chunks.append(t) t = line else: t = t + line points = [] i = 1 for chunk in chunks: print("Embeddings chunk:", chunk) # 使用OpenAI Embedding 方法, 将数据 量化 response = openai.Embedding.create( input=chunk, model="text-embedding-ada-002" ) embeddings = response['data'][0]['embedding'] # 转换为points points.append(PointStruct( id=i, vector=embeddings, payload={"text": chunk})) i += 1 # time.sleep(21) # 存入 qdrant operation_info = qdrant_client.upsert( collection_name="demo_qa", wait=True, points=points )
结合OpenAI 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 def func_input(query): response = openai.Embedding.create( input=query, model="text-embedding-ada-002" ) # 将问题 embedding # 获取问题的 embedding embeddings = response['data'][0]['embedding'] print(f"embeddings: {embeddings}") search_result = qdrant_client.search( collection_name="demo_qa", query_vector=embeddings, limit=5 ) print('search_result:', search_result) prompt = "Context:\n" for result in search_result: prompt += result.payload['text'] + "\n---\n" prompt += "Question:" + query + "\n---\n" + "Answer:" print(f"Prompt: {prompt}") completion = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[ {"role": "user", "content": prompt} ] ) rsp = completion.choices[0].message.content print("Answer:", rsp) return rsp func_input("initialDelaySeconds是什么意思")
Demo 输出 1 embeddings: [-0.016704577952623367, -0.0220100749284029, 0.003106601070612669, -0.009006679989397526, -0.02137679234147072, 0.005759350024163723, -0.014495125971734524, 0.020476125180721283, 0.004974783398211002, 0.00020097914966754615, 0.012862665578722954, 0.0230936910957098, -0.011610173620283604, -0.002862083725631237, -0.010808016173541546, 0.00642429618164897, 0.02018059231340885, ...这是一个 1536 维的向量, 人类不可读, 这里直接忽略...-0.014269959181547165, 0.0006161308265291154]
1 2 # 通过问题的向量, 在qdrant查询结果 search_result: [ScoredPoint(id=2, version=0, score=0.81478095, payload={'text': '## 简述Kubernetes相关基础概念?\n\n答:\n\n**master:**\n\nk8s集群的管理节点,负责管理集群,提供集群的资源数据访问入口。拥有Etcd存储服务(可选),运行Api Server进程,Controller Manager服务进程及Scheduler服务进程;\n\n**node(worker):**\n\nNode(worker)是Kubernetes集群架构中运行Pod的服务节点,是Kubernetes集群操作的单元,用来承载被分配Pod的运行,是Pod运行的宿主机。运行docker eninge服务,守护进程kunelet及负载均衡器kube-proxy;\n\n**pod:**\n\n运行于Node节点上,若干相关容器的组合。Pod内包含的容器运行在同一宿主机上,使用相同的网络命名空间、IP地址和端口,能够通过localhost进行通信。Pod是Kurbernetes进行创建、调度和管理的最小单位,它提供了比容器更高层次的抽象,使得部署和管理更加灵活。一个Pod可以包含一个容器或者多个相关容器;\n\n**label:**\n\nKubernetes中的Label实质是一系列的Key/Value键值对,其中key与value可自定义。Label可以附加到各种资源对象上,如Node、Pod、Service、RC等。一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去。Kubernetes通过Label Selector(标签选择器)查询和筛选资源对象;\n\n**Replication Controller:**\n\nReplication Controller用来管理Pod的副本,保证集群中存在指定数量的Pod副本。\n\n集群中副本的数量大于指定数量,则会停止指定数量之外的多余容器数量。反之,则会启动少于指定数量个数的容器,保证数量不变。\n\nReplication Controller是实现弹性伸缩、动态扩容和滚动升级的核心;\n\n**Deployment:**\n\nDeployment在内部使用了RS来实现目的,Deployment相当于RC的一次升级,其最大的特色为可以随时获知当前Pod的部署进度;\n\n**HPA(Horizontal Pod Autoscaler):**\n\nPod的横向自动扩容,也是Kubernetes的一种资源,通过追踪分析RC控制的所有Pod目标的负载变化情况,来确定是否需要针对性的调整Pod副本数量;\n\n**Service:**\n\nService定义了Pod的逻辑集合和访问该集合的策略,是真实服务的抽象。\n\nService提供了一个统一的服务访问入口以及服务代理和发现机制,关联多个相同Label的Pod,用户不需要了解后台Pod是如何运行;\n\n**Volume:**\n\nVolume是Pod中能够被多个容器访问的共享目录,Kubernetes中的Volume是定义在Pod上,可以被一个或多个Pod中的容器挂载到某个目录下;\n\n**Namespace:**\n\nNamespace用于实现多租户的资源隔离,可将集群内部的资源对象分配到不同的Namespace中,形成逻辑上的不同项目、小组或用户组,便于不同的Namespace在共享使用整个集群的资源的同时还能被分别管理;\n\n'}, vector=None), ScoredPoint(id=1, version=0, score=0.79995704, payload={'text': '## k8s的组件有哪些,作用分别是什么?\n\nk8s主要由master节点和node节点构成。\n\nmaster节点负责管理集群,node节点是容器应用真正运行的地方。\n\nmaster节点包含的组件有:kube-api-server、kube-controller-manager、kube-scheduler、etcd。\n\nnode节点包含的组件有:kubelet、kube-proxy、container-runtime。\n\n**kube-api-server:**\n\n以下简称api-server,api-server是k8s最重要的核心组件之一,它是k8s集群管理的统一访问入口,提供了RESTful API接口, 实现了认证、授权和准入控制等安全功能;api-server还是其他组件之间的数据交互和通信的枢纽,其他组件彼此之间并不会直接通信,其他组件对资源对象的增、删、改、查和监听操作都是交由api-server处理后,api-server再提交给etcd数据库做持久化存储,只有api-server才能直接操作etcd数据库,其他组件都不能直接操作etcd数据库,其他组件都是通过api-server间接的读取,写入数据到etcd。\n\n**kube-controller-manager:**\n\n以下简称controller-manager,controller-manager是k8s中各种控制器的的管理者,是k8s集群内部的管理控制中心,也是k8s自动化功能的核心;controller-manager内部包含replication controller、node controller、deployment controller、endpoint controller等各种资源对象的控制器,每种控制器都负责一种特定资源的控制流程,而controller-manager正是这些controller的核心管理者。\n\n**kube-scheduler:**\n\n以下简称scheduler,scheduler负责集群资源调度,其作用是将待调度的pod通过一系列复杂的调度算法计算出最合适的node节点,然后将pod绑定到目标节点上。shceduler会根据pod的信息,全部节点信息列表,过滤掉不符合要求的节点,过滤出一批候选节点,然后给候选节点打分,选分最高的就是最佳节点,scheduler就会把目标pod安置到该节点。\n\n**Etcd:**\n\netcd是一个分布式的键值对存储数据库,主要是用于保存k8s集群状态数据,比如,pod,service等资源对象的信息;etcd可以是单个也可以有多个,多个就是etcd数据库集群,etcd通常部署奇数个实例,在大规模集群中,etcd有5个或7个节点就足够了;另外说明一点,etcd本质上可以不与master节点部署在一起,只要master节点能通过网络连接etcd数据库即可。\n\n**kubelet:**\n\n每个node节点上都有一个kubelet服务进程,kubelet作为连接master和各node之间的桥梁,负责维护pod和容器的生命周期,当监听到master下发到本节点的任务时,比如创建、更新、终止pod等任务,kubelet 即通过控制docker来创建、更新、销毁容器;\n每个kubelet进程都会在api-server上注册本节点自身的信息,用于定期向master汇报本节点资源的使用情况。\n\n**kube-proxy:**\n\nkube-proxy运行在node节点上,在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作,kube-proxy会监听api-server中从而获取service和endpoint的变化情况,创建并维护路由规则以提供服务IP和负载均衡功能。简单理解此进程是Service的透明代理兼负载均衡器,其核心功能是将到某个Service的访问请求转发到后端的多个Pod实例上。\n\ncontainer-runtime:容器运行时环境,即运行容器所需要的一系列程序,目前k8s支持的容器运行时有很多,如docker、rkt或其他,比较受欢迎的是docker,但是新版的k8s已经宣布弃用docker。\n\n'}, vector=None)]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 # qdrant rsp + query 构造的Prompt Prompt: Context: ## 简述Kubernetes相关基础概念? 答: **master:** k8s集群的管理节点,负责管理集群,提供集群的资源数据访问入口。拥有Etcd存储服务(可选),运行Api Server进程,Controller Manager服务进程及Scheduler服务进程; **node(worker):** Node(worker)是Kubernetes集群架构中运行Pod的服务节点,是Kubernetes集群操作的单元,用来承载被分配Pod的运行,是Pod运行的宿主机。运行docker eninge服务,守护进程kunelet及负载均衡器kube-proxy; **pod:** 运行于Node节点上,若干相关容器的组合。Pod内包含的容器运行在同一宿主机上,使用相同的网络命名空间、IP地址和端口,能够通过localhost进行通信。Pod是Kurbernetes进行创建、调度和管理的最小单位,它提供了比容器更高层次的抽象,使得部署和管理更加灵活。一个Pod可以包含一个容器或者多个相关容器; **label:** Kubernetes中的Label实质是一系列的Key/Value键值对,其中key与value可自定义。Label可以附加到各种资源对象上,如Node、Pod、Service、RC等。一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上去。Kubernetes通过Label Selector(标签选择器)查询和筛选资源对象; **Replication Controller:** Replication Controller用来管理Pod的副本,保证集群中存在指定数量的Pod副本。 集群中副本的数量大于指定数量,则会停止指定数量之外的多余容器数量。反之,则会启动少于指定数量个数的容器,保证数量不变。 Replication Controller是实现弹性伸缩、动态扩容和滚动升级的核心; **Deployment:** Deployment在内部使用了RS来实现目的,Deployment相当于RC的一次升级,其最大的特色为可以随时获知当前Pod的部署进度; **HPA(Horizontal Pod Autoscaler):** Pod的横向自动扩容,也是Kubernetes的一种资源,通过追踪分析RC控制的所有Pod目标的负载变化情况,来确定是否需要针对性的调整Pod副本数量; **Service:** Service定义了Pod的逻辑集合和访问该集合的策略,是真实服务的抽象。 Service提供了一个统一的服务访问入口以及服务代理和发现机制,关联多个相同Label的Pod,用户不需要了解后台Pod是如何运行; **Volume:** Volume是Pod中能够被多个容器访问的共享目录,Kubernetes中的Volume是定义在Pod上,可以被一个或多个Pod中的容器挂载到某个目录下; **Namespace:** Namespace用于实现多租户的资源隔离,可将集群内部的资源对象分配到不同的Namespace中,形成逻辑上的不同项目、小组或用户组,便于不同的Namespace在共享使用整个集群的资源的同时还能被分别管理; --- ## k8s的组件有哪些,作用分别是什么? k8s主要由master节点和node节点构成。 master节点负责管理集群,node节点是容器应用真正运行的地方。 master节点包含的组件有:kube-api-server、kube-controller-manager、kube-scheduler、etcd。 node节点包含的组件有:kubelet、kube-proxy、container-runtime。 **kube-api-server:** 以下简称api-server,api-server是k8s最重要的核心组件之一,它是k8s集群管理的统一访问入口,提供了RESTful API接口, 实现了认证、授权和准入控制等安全功能;api-server还是其他组件之间的数据交互和通信的枢纽,其他组件彼此之间并不会直接通信,其他组件对资源对象的增、删、改、查和监听操作都是交由api-server处理后,api-server再提交给etcd数据库做持久化存储,只有api-server才能直接操作etcd数据库,其他组件都不能直接操作etcd数据库,其他组件都是通过api-server间接的读取,写入数据到etcd。 **kube-controller-manager:** 以下简称controller-manager,controller-manager是k8s中各种控制器的的管理者,是k8s集群内部的管理控制中心,也是k8s自动化功能的核心;controller-manager内部包含replication controller、node controller、deployment controller、endpoint controller等各种资源对象的控制器,每种控制器都负责一种特定资源的控制流程,而controller-manager正是这些controller的核心管理者。 **kube-scheduler:** 以下简称scheduler,scheduler负责集群资源调度,其作用是将待调度的pod通过一系列复杂的调度算法计算出最合适的node节点,然后将pod绑定到目标节点上。shceduler会根据pod的信息,全部节点信息列表,过滤掉不符合要求的节点,过滤出一批候选节点,然后给候选节点打分,选分最高的就是最佳节点,scheduler就会把目标pod安置到该节点。 **Etcd:** etcd是一个分布式的键值对存储数据库,主要是用于保存k8s集群状态数据,比如,pod,service等资源对象的信息;etcd可以是单个也可以有多个,多个就是etcd数据库集群,etcd通常部署奇数个实例,在大规模集群中,etcd有5个或7个节点就足够了;另外说明一点,etcd本质上可以不与master节点部署在一起,只要master节点能通过网络连接etcd数据库即可。 **kubelet:** 每个node节点上都有一个kubelet服务进程,kubelet作为连接master和各node之间的桥梁,负责维护pod和容器的生命周期,当监听到master下发到本节点的任务时,比如创建、更新、终止pod等任务,kubelet 即通过控制docker来创建、更新、销毁容器; 每个kubelet进程都会在api-server上注册本节点自身的信息,用于定期向master汇报本节点资源的使用情况。 **kube-proxy:** kube-proxy运行在node节点上,在Node节点上实现Pod网络代理,维护网络规则和四层负载均衡工作,kube-proxy会监听api-server中从而获取service和endpoint的变化情况,创建并维护路由规则以提供服务IP和负载均衡功能。简单理解此进程是Service的透明代理兼负载均衡器,其核心功能是将到某个Service的访问请求转发到后端的多个Pod实例上。 container-runtime:容器运行时环境,即运行容器所需要的一系列程序,目前k8s支持的容器运行时有很多,如docker、rkt或其他,比较受欢迎的是docker,但是新版的k8s已经宣布弃用docker。 --- Question:replication controller是什么 ---
1 2 # OpenAI润色后结果 Answer: Replication Controller是Kubernetes中用于管理Pod副本数量的资源对象。它确保在集群中运行指定数量的Pod副本,并且会自动处理Pod的创建、删除和故障恢复等操作。当Pod的数量少于指定数量时,Replication Controller会自动创建新的Pod,反之,当Pod的数量多于指定数量时,Replication Controller会自动删除多余的Pod。通过Replication Controller,可以实现Pod的弹性伸缩、动态扩容和滚动升级等功能。