正确完成检索增强生成(RAG):数据库数据
作者: 大数据杂货铺 来源: 大数据杂货铺
介绍
-
检索增强生成 (RAG) 管道正日益成为使用大型语言模型 (LLM) 和您自己的数据实现问答和聊天机器人应用程序的常用方法。
-
您的某些数据可能以 PDF 格式的文件或 MSOffice 文档的形式驻留在 S3 或 Google-Drive 上,但在许多情况下,您的数据存储在 Snowflake、Redshift 或 Postgres 等数据库的结构化表中,或存储在 MongoDB 或 CouchDB 等文档数据库中。
-
这些数据通常对您的业务至关重要,将 RAG 应用于此数据可以让您的用户以全新的方式与这些数据进行交互,例如问答、聊天机器人或摘要。最终结果是提高生产力、销售转化率或提高用户参与度。
-
如何使用此类结构化或半结构化数据构建 RAG 管道?
-
在这篇博文中,我们将介绍执行此操作的过程,并回顾一些最佳实践。我们将重点关注通常存储在 RDBMS 系统中的结构化数据,如代码中所示,但此处描述的方法也适用于文档数据库。
将 GenAI 与数据库结合使用
企业中的大多数关键业务数据都是以关系方式组织和存储的,SQL 仍然是人们查询这些数据以获取见解的主要方式。
当我们在生成式 AI 的背景下讨论数据库时,总是首先想到的问题之一是:“我不能告诉数据库我需要什么,而不必制作一个复杂(通常是多页)的 SQL 查询吗?
对于LLM来说,这是一个非常重要的用例。 事实证明,现有的 LLM 如 OpenAI 的 GPT-4 或 Anthropic 的 Claude-2 可以很好地完成简单的文本到 SQL 任务,但在更复杂的用例中往往会失败。这是很不幸的,尽管我真的希望文本到SQL在未来几年内会得到显着改善,并且我们将有一种很好的方式来使用分析,只需发出自然语言查询即可。
在这篇博文中,我将重点介绍一个不同的用例,即使用驻留在数据库中的数据构建 RAG 应用程序。
例如,考虑以下巴塞罗那市的 Airbnb 房源公开数据集,我已将其上传到 Snowflake 实例中,分为两个表:房源和评论。
房源表有75个不同的列,描述了巴塞罗那每个Airbnb房源的各个方面,例如:描述、床位数量、社区以及地理坐标——经度和纬度。
评论表只有 6 列,包括 listing-ID(将评论映射到它在列表表中引用的列表)、评论者姓名、评论日期和“评论”(主要评论文本)。
用户评论往往包含非常有价值的信息,这些信息可用于帮助未来的巴塞罗那游客。然而,众所周知,RDBMS系统和基于关键字的索引很难利用这种类型的用户生成的内容。我们将使用 Vectara 构建一个 RAG 应用程序,以允许用户提出以下问题:
·什么是最适合儿童的博物馆?
·哪个街区的小吃店最好?
·我在哪里可以找到夜总会?
您可以想象,如果用户可以在房产搜索过程中利用这些定性信息,那么 Airbnb 的转化率会变得更好。这将是Airbnb的胜利,也是其用户的胜利。
让我们开始吧。
将数据引入 Vectara
我们的第一步是将 Snowflake 中的数据摄取到 Vectara 中。
数据库表中的数据被结构化为列,在准备用于生成式 AI 的数据时,必须考虑数据架构并决定如何最好地准备它在 RAG 上下文中使用。
因此,在进行任何数据摄取之前,我们需要设计一个“文档构建计划”,据此我们决定如何将数据库中每个感兴趣的实体转换为要摄取的 Vectara JSON 文档。
例如,在我们的例子中,我们将从每个评论(即评论表中的每一行)构建这样一个JSON文档,它将包括一个标题和一些文本部分,然后添加元数据字段以支持过滤。
具体说来:
·我们将为本文档构建一个标题,如下所示:“在进行审查”
·第一部分是我们从有关属性的一些字段构造的句子:“属性,描述为”
·第二部分将包括有关该物业的实际<评论>(实际评论)。
列表数据库中有许多字段可用于元数据,我们在此演示中选择了几个字段来包含:
-
LATITUDE
-
LONGITUDE
-
DATE
-
NEIGHBORHOOD_CLEANSED
我们刚才概述的用于处理数据库表中每一列的计划演示了引入数据库表以在 RAG 应用程序中使用时的常见模式:
1.一些本质上是文本的列,例如“评论”列,是直接使用的——在这种情况下,作为其自身的一个部分。
2.可以通过从一列或多列及其值创建“人工句子”来构造文本。例如,标题和第二部分都是以这种方式构造的。
3.某些字段用作元数据(如 LONGITUDE 和 LATITUDE)。这使我们能够使用这些字段过滤结果。
4.某些字段只是被忽略,并且不会在 RAG 流中使用。
虽然我们在这里处理的是像 Snowflake 或 Redshift 这样的数据库系统,但值得一提的是,如果您的文件驻留在 CSV 文件或任何其他行为类似于数据库中的结构化数据的格式中,则遵循“文档构建计划”的策略同样适用。
为了摄取数据,我们首先在 Vectara 中创建一个新的语料库,并将元数据中的每个字段(日期、经度、纬度和邻域)定义为过滤器属性。
接下来,我们使用 Snowflake 的 Python 连接器将数据从表下载到 pandas 数据帧中:“'
con = connect(user=sf_user, password=sf_password, account=sf_account)
cursor = con.cursor()
cursor.execute("USE DATABASE AIRBNB;")
query = '''
SELECT
DATE, REVIEWER_NAME, COMMENTS, R.ID as REVIEW_ID,
LATITUDE, LONGITUDE, ROOM_TYPE, DESCRIPTION,
NEIGHBOURHOOD_CLEANSED as NEIGHBORHOOD
FROM REVIEWS AS R JOIN LISTINGS as L
ON R.LISTING_ID = L.ID
'''
cursor.execute(query)
df = cursor.fetch_pandas_all()
在这里,我们将两个表 REVIEWS 和 LISTINGS 连接起来,以获取每个评论所需的所有信息。
这就是我们为每条评论创建一个 Vectara “JSON 文档”的方式:
def add_chunk(df_chunk, bar) -> None:
"""Ingest a df into Vectara."""
session = requests.Session()
adapter = requests.adapters.HTTPAdapter(max_retries=5)
session.mount("https://", adapter)
for row in df_chunk.to_dict(orient='records'):
metadata = {
'date': row['DATE'],
'reviewer': row['REVIEWER_NAME'],
'latitude': row['LATITUDE'],
'longitude': row['LONGITUDE'],
'neighborhood': row['NEIGHBORHOOD']
}
doc = {
"documentId": f"Review {row['REVIEW_ID']}",
"metadataJson": json.dumps(metadata),
"title": f"Review by {row['REVIEWER_NAME']} on {row['DATE']}",
"section": [
{'text': f"{row['ROOM_TYPE']} property in {row['NEIGHBORHOOD']}, described as {clean_md(row['DESCRIPTION'])}"},
{'text': clean_md(row['COMMENTS'])}
],
}
res = index_doc(session, doc)
bar.update.remote(1)<code></code>
请注意,这里如何对每一行执行以下操作:df_chunk
1.创建元数据,包括日期、审阅者、纬度、经度和邻域
2.创建变量,包括 doc、documentID 、title 和 a,其中包含两部分metadata和section :上面讨论的人工句子和评论注释。
然后,该函数index_doc()通过调用索引 API 在 Vectara 中为文档编制索引 - 您可以在此处查看完整代码。
生成的 JSON 文档的示例如下:
{
"documentId": "Review 886755474280381042",
"metadataJson": '{"date": "2023-05-08", "reviewer": "Mathias", "latitude": 41.37249, "longitude": 2.13603, "neighborhood": "Sants"}',
"title": "Review by Mathias on 2023-05-08",
"section": [
{
"text": "Private room property in Sants, described as The spaceBreakfast buffet not included 24 hour ReceptionHigh-speed Wi-Fi throughout the buildingRelax ZoneLuggage storage lockersMeeting RoomTablet with tourist informationAir conditioning and heatingSmart TV in all roomsDisabled accessible roomsNon smoking hotelGuest accessComfortable, modern, functional room with its own private bathroom, hairdryer, towels, ecological shampoo and soap and a smart safe. The room is equipped with quality comfortable beds, a 28-inch Smart TV, functional wardrobe (closet), a chair and desk, as well as two bedside tables with reading lights. It has high speed Wi-Fi, individually controlled air conditioning & heating as well as daily room cleaning.Registration numberHB-004659"
},
{"text": "Veldig bra oppholf"},
],
}
Test 函数add_chunk()接收 DataFrame 中的一组行,并每行创建一个 JSON 文档。这样,我们就可以使用 Ray 轻松并行化和加速数据摄取:
ray_workers = 10 # or choose your number of cores
print(f"Using Ray with {ray_workers} workers")
ray.init(num_cpus=ray_workers, ignore_reinit_error=True)
remote_tqdm = ray.remote(tqdm_ray.tqdm)
bar = remote_tqdm.remote(total=len(df))
ray_add_chunk = ray.remote(add_chunk)
chunks = np.array_split(df, ray_workers)
futures = [ray_add_chunk.remote(chunk, bar) for chunk in chunks]
_ = ray.get(futures)
就是这样。
完成此摄取过程后,我们现在可以使用 Vectara 使用这些数据构建用于问答的应用程序或聊天机器人。
询问有关巴塞罗那的问题
好了,现在所有数据都已摄取,我们可以尝试对这些数据进行一些有趣的查询。AirBNB 评论往往不仅有对房产的评论,而且通常有很多关于社区、要做的事情等等的宝贵信息。
我们在这里提供了用于查询数据的完整代码。
让我们尝试几个问题:
第一个问题是“什么是最适合儿童的博物馆?
Vectata 的查询 API 响应:
“正如一位游客所说,巴塞罗那最适合儿童的博物馆似乎是科学博物馆。据他们 6 岁和 8 岁的孩子说,这是他们旅行的亮点。此外,还推荐 Recinte Modernista St Pau、MACBA 和毕加索博物馆。这些博物馆为儿童提供引人入胜的教育体验。此外,海滩附近还有公园和游乐场,孩子们可以在那里享受户外活动。总的来说,这些景点为巴塞罗那的儿童娱乐和教育提供了一系列选择。
当我们运行此查询时:“哪个社区的小吃店最好?
我们得到:
“强烈推荐巴塞罗那的格拉西亚(Gracia)社区,因为它拥有一流的小吃场所。游客们称赞了该地区一流的酒吧和餐馆。一些具体的小吃推荐包括 El 58 和太阳广场的一个地方。Gracia 拥有迷人而舒适的氛围,方便前往圣家堂和奎尔公园等景点。附近的Estrella市场提供新鲜水果和传统的加泰罗尼亚产品。总的来说,格拉西亚是一个充满活力的社区,拥有梦幻般的小吃选择和便利的地理位置。
这听起来很酷很美味,以至于我让 Dalle-3 生成一张它可能是什么样子的图像。结果如下:
多么有趣!
我们的最后一个问题是:“我在哪里可以找到夜总会?
回应如下:
“夜总会在不同的地方都可以找到。一个搜索结果提到了一家名为Club Pipos的夜总会,该夜总会位于公寓下方,可能会造成噪音干扰。另一个结果提到某个公寓附近的一家夜总会,直到凌晨 1-2 点左右才能听到热闹游客的噪音。此外,另一个搜索结果提到了一家名为 APOLLO 的夜总会,位于公寓附近,在周四、周五和周六凌晨 5:30 之前会造成潜在的噪音问题。然而,一篇评论指出,在窗户和百叶窗关闭的情况下,附近夜总会的噪音不是问题。重要的是要考虑夜总会与潜在住宿的接近程度以及个人喜好,以享受宁静的住宿。
当然,我们可能正在寻找大流行前的一些建议,那么如果我们添加过滤标准会怎样:
doc.date < ‘2020-01-01’
使用相同的查询,我们现在得到:
“根据搜索结果,巴塞罗那有几个地区可以找到夜总会。一种选择是住在圣安东尼,附近有商店、餐馆、小吃店和夜总会。另一个区域是示例区,距离著名的步行大道兰布拉大道有 15 分钟步行路程,提供充满活力的夜生活场景。然而,值得注意的是,这些地区附近的一些住宿提到,由于夜总会附近,晚上可能会有一些噪音。总的来说,这些地点为巴塞罗那的夜生活场所提供了便利。
结论
许多企业数据驻留在结构化数据库表中,在这篇博文中,我们研究了如何将此类数据引入 Vectara,特别是从表的每一行创建 Vectara“文档”对象的常用方法,以实现强大的语义搜索、问答和对话式 AI。
原文链接:https://vectara.com/blog/retrieval-augmented-generation-rag-done-right-database-data/
更多AI工具,参考Github-AiBard123,国内AiBard123