(五)Langchain PGVector 补充智能客服匹配式问答

news2024/11/22 5:05:18

文章目录

  • 资料
  • 背景
  • 目标
  • FAQ-匹配式问答
    • 安装PGVector 向量数据库
    • text2vec-large-chinese
    • Langchain-PGVector
      • 测试向量化文本
      • 写入QA问答对
      • 特别注意问题
      • langchain pgvector表和数据
      • 相识性问题匹配
  • 结论

资料

  • NLP领域五大QA问答场景总结:FQA、DOC-QA、KBQA、TableQA、TaskQA等场景概述与对比解析
  • Langchain PGVector使用文档
  • pgvector

背景

最近在做智能客服,通过 https://github.com/imClumsyPanda/langchain-ChatGLM 可以完成DOC-QA 部分智能问答

摘要项目原理说明

本项目实现原理如下图所示,过程包括加载文件 -> 读取文本 -> 文本分割 -> 文本向量化 -> 问句向量化 -> 在文本向量中匹配出与问句向量最相似的top k个 -> 匹配出的文本作为上下文和问题一起添加到prompt中 -> 提交给LLM生成回答。

在这里插入图片描述
其中注意介绍中的这一句,在文本向量中匹配出与问句向量最相似的top k个,也就是第7和第10个步骤,有几个问题在实践中需要解决

  • 测试过程中大部分答案还是满意的,但是由于原始文档切割,部分答案会丢失上下文(切割没了,top k也没匹配出来)
  • 固定的问答对很难保障,比如操作流程,这种需求内容长且要求答案文本顺序不能乱
  • 文本上下文存在复杂的内容,比如图片,音频,视频,需要处理才能让大模型呈现
  • FAISS 向量库不支持matedata过滤,在复杂度更高的场景失去灵活性
  • FAISS 不支持单条语句删除或更新

为了问答质量效果,既要保障高质量语料,也得寻求匹配式问答解决方案,这才选择了Langchain PGVector 补充智能客服匹配式问答

目标

先让用户的问题,匹配问答中的问题(多问一答),相同的问题意图需要泛化,如果问题相识度满足一定的阈值,则返回问题对应的答案,如果不满足相关度阈值,则把问题提交给文档问答库(适合有一定的业务文档积累场景)作为兜底,同样的也需要满足一定的相关度top k

FAQ-匹配式问答

安装PGVector 向量数据库

什么是 pgvector ? Postgres的开源向量相似性搜索,支持

  • 精确和近似最近邻搜索
  • L2 距离、内积和余弦距离
  • 任何带有Postgres客户端的语言

为了快速验证可行性,使用 https://github.com/pgvector/pgvector 中docker方法启动项目

FROM ankane/pgvector

LABEL maintainer="Ben M <git@bmagg.com>"

CMD ["postgres"]

EXPOSE 5432

构建启动docker

docker build -t pgvector .
docker run -itd pgvector -p 5432 -e POSTGRES_DB=default -e POSTGRES_USER=default -e POSTGRES_PASSWORD=secret

text2vec-large-chinese

因为在实践过程中,如果用大模型能力去让文本向量化,貌似速度挺慢的,所以这里先使用text2vec-large-chinese作为向量模型

huggingface下载地址,https://huggingface.co/GanymedeNil/text2vec-large-chinese

放在测试项目的·models/text2vec-large-chinese·

国内下载慢的,可以在https://github.com/imClumsyPanda/langchain-ChatGLM/blob/master/docs/FAQ.md找到百度下载地址

Langchain-PGVector

通过学习Langchain-PGVector文档,首先安装langchain环境pgvector

pip install langchain pgvector -i http://mirrors.aliyun.com/pypi/simple/

测试向量化文本

Embedding 是一个浮点数向量(列表)。两个向量之间的距离用于测量它们之间的相关性。较小距离表示高相关性,较大距离表示低相关性。

为了提高相关性,尽可能泛化问题

from langchain.embeddings import HuggingFaceEmbeddings  

embeddings = HuggingFaceEmbeddings(model_name="models/text2vec-large-chinese"
                              ,model_kwargs={'device': "cpu"})

sentence = '你是谁|介绍一下你自己|你叫什么名字'
vec = embeddings.embed_documents(sentence)
print(vec)

在这里插入图片描述

写入QA问答对

下面代码第一次是不会运行成功的,耐心往下看就知道原因

需要注意和验证的问题是

  • 问题都整合在一起效果更好还是分开?
  • 分数越低,代表匹配相关性越高
  • 向量化的是问题,答案作为metadata写入到数据库了
from langchain.embeddings import HuggingFaceEmbeddings  
from langchain.vectorstores.pgvector import PGVector
from langchain.vectorstores.pgvector import DistanceStrategy
from langchain.docstore.document import Document
from typing import List, Tuple


embeddings = HuggingFaceEmbeddings(model_name="models/text2vec-large-chinese"
                              ,model_kwargs={'device': "cpu"})


# sentence = '你是谁|介绍一下你自己|你叫什么名字'
# vec = embeddings.embed_documents(sentence)
# print(vec)


import os
PGVECTOR_CONNECTION_STRING = PGVector.connection_string_from_db_params(
    driver=os.environ.get("PGVECTOR_DRIVER", "psycopg2"),
    host=os.environ.get("PGVECTOR_HOST", "localhost"),
    port=int(os.environ.get("PGVECTOR_PORT", "5432")),
    database=os.environ.get("PGVECTOR_DATABASE", "default"),
    user=os.environ.get("PGVECTOR_USER", "default"),
    password=os.environ.get("PGVECTOR_PASSWORD", "secret"),
)


print(f"=====>{PGVECTOR_CONNECTION_STRING}")


data = [
    "你是谁|介绍一下你自己|你叫什么名字?", 
    "商品支持退货吗?",
    "购物车可以添加多少商品?"
    ]

metadatas = [{"answer":"是智能助手, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。让我们一步步思考,并且尽可能用分点叙述的形式输出。我们开始聊天吧"},
             {"answer":"15天内商品支持退换货"},
             {"answer":"购物车可以添加100件商品"}
             ]

PGVector.from_texts(texts = data,
                    embedding=embeddings,
                    collection_name="custom_qa",
                    connection_string=PGVECTOR_CONNECTION_STRING,
                    metadatas = metadatas
                    )

运行代码报错了,不用着急

PGVector.from_texts 方法会自动创建表(langchain_pg_embeddinglangchain_pg_collection),并录入数据(多次录入是新增逻辑)

在这里插入图片描述

第一次langchain为我们自动创建

CREATE TABLE "public"."langchain_pg_collection" (
	"uuid" uuid NOT NULL,
	"name" varchar,
	"cmetadata" json,
	CONSTRAINT "langchain_pg_collection_pkey" PRIMARY KEY ("uuid")
);

CREATE TABLE "public"."langchain_pg_embedding" (
	"uuid" uuid NOT NULL,
	"collection_id" uuid,
	"embedding" vector(1536),
	"document" varchar,
	"cmetadata" json,
	"custom_id" varchar,
	CONSTRAINT "langchain_pg_embedding_pkey" PRIMARY KEY ("uuid")
);

特别注意问题

langchain pgvector源码包使用的是openai的第二代text-embedding-ada-002模型,输出向量维度是1536,默认创建的表也是"embedding" vector(1536), 感兴趣的可以看 https://zhuanlan.zhihu.com/p/619233637

在这里插入图片描述
这里和我们模型text2vec-large-chinese输出向量维度是1024, 数据存不进去,因为向量维度不同

修改 langchain.vectorstores.pgvector

ADA_TOKEN_COUNT = 1024 # openai 1536

在这里插入图片描述
删除创建的pg表,我们重新运行代码即可,会重新创建表

langchain pgvector表和数据

  • langchain_pg_collection
    在这里插入图片描述

  • langchain_pg_embedding
    在这里插入图片描述

相识性问题匹配


from langchain.embeddings import HuggingFaceEmbeddings  
from langchain.vectorstores.pgvector import PGVector
from langchain.vectorstores.pgvector import DistanceStrategy
from langchain.docstore.document import Document
from typing import List, Tuple
import os

embeddings = HuggingFaceEmbeddings(model_name="models/text2vec-large-chinese"
                              ,model_kwargs={'device': "cpu"})

PGVECTOR_CONNECTION_STRING = PGVector.connection_string_from_db_params(
    driver=os.environ.get("PGVECTOR_DRIVER", "psycopg2"),
    host=os.environ.get("PGVECTOR_HOST", "localhost"),
    port=int(os.environ.get("PGVECTOR_PORT", "5432")),
    database=os.environ.get("PGVECTOR_DATABASE", "default"),
    user=os.environ.get("PGVECTOR_USER", "default"),
    password=os.environ.get("PGVECTOR_PASSWORD", "secret"),
)

print(f"=====>{PGVECTOR_CONNECTION_STRING}")


query = "你们的购物车可以添加几个商品"

store = PGVector(
    connection_string=PGVECTOR_CONNECTION_STRING, 
    embedding_function=embeddings, 
    collection_name="custom_qa",
    distance_strategy=DistanceStrategy.COSINE
)

# retriever = store.as_retriever()
print("=" * 80)
docs_with_score: List[Tuple[Document, float]] = store.similarity_search_with_score(query)
for doc, score in docs_with_score:
    print("-" * 80)
    print("Score: ", score)
    print(doc.page_content)
    print(doc.metadata)
    print("-" * 80)

在这里插入图片描述
通过验证,如果将问题都糅合在一起,相关度score的值变大了(不那么相关),所以设计的时候,应该将泛化的问题单独一行
在这里插入图片描述

索引性能优化部分不在本次探讨范围

结论

问题要泛化,答案尽可能多样化

  • 可以使用pgvector完成FQA问答场景,doc-qa作为兜底方案
  • 一个问题一行保存到pg,让socre尽可能的小,到时候可以结合业务设置相关度阈值,决定是否检索doc-qa
  • 为了答案的多样性,可以写入多个答案,或者写入外键表id获取答案(answer写答案的id)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/609974.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

html+css+js实现的web小案例

上完了Web开发基础的课程之后&#xff0c;做了这么一个小案例作为课程的大作业。这个案例是静态页面&#xff0c;使用的技术有htmlcssjs&#xff0c;主要的知识点有页面的打开关闭、页面跳转、超链接、图片和音频的使用、轮播图、js函数等等。本案例的主要内容是注册、登陆之后…

PostgreSQL清理dead tuples(vacuum和vacuum full)

前言 PostgreSQL的并发控制&#xff0c;采用MVCC&#xff08;多版本并发控制&#xff09;进行处理。这种机制有一个缺点&#xff1a;随着时间的推移&#xff0c;数据文件中积累的dead tuples&#xff08;死数据/死元组&#xff09;会越来越多。 在清理dead tuples时&#xff…

redis第五第六章-redis并发缓存架构和性能优化

一、缓存设计 1.缓存穿透 缓存穿透是指查询一个根本不存在的数据&#xff0c; 缓存层和存储层都不会命中&#xff0c; 通常出于容错的考虑&#xff0c; 如果从存储层查不到数据则不写入缓存层。 缓存穿透将导致不存在的数据每次请求都要到存储层去查询&#xff0c; 失去了缓存…

高通 Camera HAL3:添加一个Feature

一.概述 以HDR Feature为例&#xff0c;在CamX中添加一个新的Feature 从上游stream(upstream) feature获取格式P010的多帧数据作为inputpipeline(SWMFMergeYuv)运行算法生成同样格式的单帧数据作为输出&#xff0c;发送给下游stream(down stream) feature 二.添加 2.1 从Feat…

自动计算图片的宽度和高度拉伸至全屏附CSS及VUE简单实现

1、简介 场景&#xff1a;比如说APP封面等特点&#xff1a;能够自动适应设备的宽高&#xff0c;保证图片100%显示&#xff0c;不会缺失或者留边&#xff0c;但有可能会变形。 2、实现 注意以下代码尽管是在Vue环境下实现的&#xff0c;但与Vue关系不大&#xff0c;代码本身也足…

【Python】列表 List ④ ( 插入操作 / 追加操作 | 列表插入操作 List#insert | 列表追加元素操作 List#append )

文章目录 一、列表插入操作1、List#insert 函数简介2、代码示例 - 列表插入元素 二、列表追加元素操作1、List#append 函数简介2、代码示例 - 列表追加元素 一、列表插入操作 1、List#insert 函数简介 Python 列表 通过调用 List#insert 函数 插入元素 , 该函数需要传入两个参数…

chatgpt赋能python:Python商场打折问题详解

Python商场打折问题详解 在商场营销策略中&#xff0c;打折是一种常见的手段。而Python作为一种广泛应用于数据科学和机器学习的编程语言&#xff0c;也可以用来解决商场打折问题。本文将介绍Python实现商场打折的方法和步骤&#xff0c;希望能对广大商场营销人员和数据科学家…

C语言——数据在内存中的存储(未完待续)

文章目录 一、数据类型的介绍1.0、有符号跟无符号计算原理在这里插入图片描述1.1、数据类型的基本分类 二、整形与浮点型在内存中的存储1.整型1.0、大小端的介绍 2.原码、反码、补码2.0、原码2.1、反码2.2、补码2.3、补码转原码第二种方法 三 、浮点型3.0、浮点数存储的例题&am…

20230604给coolpi4b开发板刷机的LOG

20230604给coolpi4b开发板刷机的LOG 2023/6/4 23:49 IMG I:\BaiduNetdiskDownload\20230317[在线刷机]-RKDevTool专用镜像 I:\BaiduNetdiskDownload\20230317[在线刷机]-RKDevTool专用镜像\Windows驱动程序\DriverAssitant_v5.12.zip I:\BaiduNetdiskDownload\20230317[在线…

WGCNA | 不止一个组的WGCNA怎么分析嘞!?~(三)(共识网络分析-第三步-共识模块与特异模块相关联)

1写在前面 有小伙伴子留言问最近介绍的WGCNA共识网络的意义是什么&#xff0c;保守性吗&#xff01;&#xff1f;&#x1f9d0; 与把雄性小鼠和雌性小鼠的数据merge在一起&#xff0c;一起构建网络、确定模块的方式有什么区别呢&#xff01;&#xff1f;&#x1f617; 其实区别…

JavaSE进阶(day13,复习自用)

单元测试、反射、注解、动态代理 单元测试单元测试概述单元测试快速入门单元测试常用注解 反射反射概述反射获取类对象反射获取构造器对象反射获取成员变量对象反射获取方法对象反射的作用-绕过编译阶段为集合添加数据反射的作用-通用框架的底层原理 注解注解概述自定义注解元注…

数据在内存中存储的现象

&#x1f929;本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 &#x1f970;内容专栏&#xff1a;这里是《C知识系统分享》专栏&#xff0c;笔者用重金(时间和精力)打造&#xff0c;基础知识一网打尽&#xff0c…

chatgpt赋能python:Python图片合成:背景设计的新方案

Python 图片合成&#xff1a;背景设计的新方案 简介 图像合成是一项艺术性和创新性的工作&#xff0c;它涉及到多个过程&#xff0c;包括图像处理、透明度和滤镜应用。Python 我们可以使用其各种库快速、可靠地进行图像合成。在这篇文章中&#xff0c;我们将介绍如何使用 Pyt…

chatgpt赋能python:Python在线模拟器:让编程变得更加轻松

Python 在线模拟器&#xff1a;让编程变得更加轻松 介绍 Python 在线模拟器是一个非常实用的工具&#xff0c;它可以帮助用户直接在浏览器中测试和运行 Python 代码。在线模拟器的出现简化了编程过程&#xff0c;不需要安装 Python IDE 等软件&#xff0c;只需要有一台连接互…

LSM零知识学习三、插桩原理实现细节(1)

本文内容参考&#xff1a; LSM(Linux Security Modules)框架原理解析_lsm框架_pwl999的博客-CSDN博客 Linux LSM(Linux Security Modules) Hook Technology_weixin_30929011的博客-CSDN博客 特此致谢&#xff01; 一、插桩具体实现 前文介绍了插桩原理&#xff0c;本文来详…

chatgpt赋能python:Python图片大小怎么算?

Python图片大小怎么算&#xff1f; 在Web开发中&#xff0c;经常需要展示图片&#xff0c;但是为了让网页加载速度更快&#xff0c;我们需要对图片进行压缩和优化&#xff0c;其中一个重要的参数就是图片的大小。那么在Python中&#xff0c;如何计算图片大小呢&#xff1f; 图…

包扫描工具实现(详解)

文章目录 前言包扫描实现思路&#xff08;需求分析&#xff09;&#xff1a; 具体实现完整代码 前言 注解在 Java 是一个非常重要的存在&#xff0c;而且它出现的非常频繁。 在一个工程下可能有许多的包或者Jar包&#xff0c;为了结合注解可以准确的定位到一个需要的类上&…

代码随想录算法训练营第四十六天|139.单词拆分

LeetCode139.单词拆分 动态规划五部曲&#xff1a; 1&#xff0c;确定dp数组以及下标的含义&#xff1a; dp[i] : 字符串长度为i的话&#xff0c;dp[i]为true&#xff0c;表示可以拆分为一个或多个在字典中出现的单词。 2&#xff0c;确定递推公式&#xff1a; 如果确定dp[j…

javascript基础二十:说说你对DOM的理解,常见的操作有哪些?

一、DOM 文档对象模型 (DOM) 是 HTML 和 XML 文档的编程接口 它提供了对文档的结构化的表述&#xff0c;并定义了一种方式可以使从程序中对该结构进行访问&#xff0c;从而改变文档的结构&#xff0c;样式和内容 任何 HTML或XML文档都可以用 DOM表示为一个由节点构成的层级结构…

交通物流模型 | Python建模实现动态交通分配优化问题求解

文章目录 效果一览文章概述研究内容程序设计参考资料效果一览 文章概述 交通物流模型 | Pyomo建模框架实现动态交通分配优化问题求解,DTA 交通分配问题通常需要考虑许多因素,例如道路容量、交通需求、速度限制、车辆类型、交通信号灯等,在城市规划和交通管理领域中具有重要的…