生成式人工智能(AI)正迎来又一个快速发展期,引起了开发者们的广泛关注。将生成式能力集成到商业服务和解决方案中变得非常重要。当前的生成式AI解决方案是机器学习和深度学习模型逐步进化迭代的结果。从深度学习到生成式AI的质变飞跃主要是由基础模型(FMs)推动的。亚马逊云科技Bedrock提供了对各种基础模型的便捷访问,并极大地简化了整体开发体验。
尽管这些通用模型功能非常强大,但它们无法单独作为特定场景的AI解决方案。要模型生成更具针对性和实用性,需要给AI提供额外的上下文信息。检索增强生成(Retrieval Augmented Generation,RAG)是一种广受欢迎的技术,可用于提供上下文信息。RAG的核心是向量嵌入(vector embeddings),它通过基础模型将非结构化数据转换为多维数值表示。同一维度下向量值越接近,表示数据项之间的相似度越高,这也是当前向量相似性搜索应用的基础。
亚马逊云科技Relational Database Service(RDS)for SQL Server是一项完全托管的持久性数据库服务,全球各大大厂都正在使用它。对于许多客户而言,存储企业业务数据的数据库已托管在RDS for SQL Server上,这些数据就可以作为基于RAG的生成式AI应用的领域上下文。因此该数据库服务成为了向量数据存储的理想选择,原因包括:
- RDS for SQL Server是一项成熟、高扩展性、可靠且高效的关系型数据库服务,同时也是易于管理的向量数据。
- 向量数据可以建模为SQL Server数据库中的关系表。
- SQL Server的列存储索引(Columnstore Index)提供了包括SIMD和AVX-512在内的优化技术,加速了向量运算。
- 目前广泛使用的余弦相似度(Cosine Similarity)计算可在SQL Server数据库中通过用户自定义函数(UDF)创建。
本方案将介绍如何使用RDS for SQL Server作为向量数据存储,以实现基于相似性搜索的生成式AI应用。在本场景中,业务数据存储和向量数据存储均在同一个RDS for SQL Server实例中。将嵌入数据存储在靠近业务数据的位置,使其能够结合额外的元数据,而无需依赖外部数据源。此外随着数据的不断变化,嵌入数据存储在源业务数据附近还能简化嵌入数据的更新过程。
在本方案中,我们使用相同的RDS for SQL Server实例同时存储业务数据和向量数据。具体场景是创建一个典型的聊天机器人,该机器人使用RAG增强基础模型,为用户提供领域相关的响应。以下图示展示了本文实现的生成式AI工作流的高级架构。
我们假设源数据的向量嵌入已存储在向量数据存储中。本文的将介绍如何把聊天输入问题转换成向量嵌入,并将其与向量库中的数据源存储进行比较,以执行相似性搜索并返回相关结果。本方案的数据来自维基百科的公开内容,包括四个字段:id、URL、标题(title)和文本(text)。如何在RDS for SQL Server中生成向量数据嵌入,并将其存入向量数据库的完整流程,将在我们的下一篇文章中详细介绍。
本方案不涉及基于大型语言模型(LLM)为用户提供对话式响应的UI前端实现细节,而是专注于解决方案的数据库部分,即如何从向量数据存储中检索相关结果集,通过相似性语义搜索获取数据响应请求。
解决方案架构概览
本文所述的RAG聊天机器人方案涉及RDS for SQL Server、亚马逊云科技SageMaker和Bedrock,方案具体使用了亚马逊云科技Titan G1文本嵌入模型(Amazon Titan G1 Text Embedding Model)。整个工作流程如下:
- 用户的问题(Prompt)通过调用Bedrock API,在SageMaker Notebook中使用Amazon Titan模型转换为向量嵌入(步骤1-3)。
- 由用户问题生成的向量被传递至向量数据存储中的余弦相似度函数,该函数对数据库中存储的向量嵌入数据执行相似性搜索,并将结果集返回至SageMaker(步骤4-5),分发给用户。
项目实操准备
本文假设大家已经熟悉如何操作亚马逊云科技管理控制台。此外本实践需要大家在亚马逊云科技账户中启用以下资源和服务:
- Amazon RDS for SQL Server数据库实例(用于向量数据存储)
- Amazon SageMaker Notebook示例代码
- 创建Amazon Bedrock访问客户端的Python脚本
- Amazon Bedrock上的Amazon Titan Embeddings G1 – Text模型
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
"""Helper utilities for working with Amazon Bedrock from Python notebooks"""
# Python Built-Ins:
import os
from typing import Optional
# External Dependencies:
import boto3
from botocore.config import Config
def get_bedrock_client(
assumed_role: Optional[str] = None,
region: Optional[str] = None,
runtime: Optional[bool] = True,
):
"""Create a boto3 client for Amazon Bedrock, with optional configuration overrides
Parameters
----------
assumed_role :
Optional ARN of an AWS IAM role to assume for calling the Bedrock service. If not
specified, the current active credentials will be used.
region :
Optional name of the AWS Region in which the service should be called (e.g. "us-east-1").
If not specified, AWS_REGION or AWS_DEFAULT_REGION environment variable will be used.
runtime :
Optional choice of getting different client to perform operations with the Amazon Bedrock service.
"""
if region is None:
target_region = os.environ.get("AWS_REGION", os.environ.get("AWS_DEFAULT_REGION"))
else:
target_region = region
print(f"Create new client\n Using region: {target_region}")
session_kwargs = {"region_name": target_region}
client_kwargs = {**session_kwargs}
profile_name = os.environ.get("AWS_PROFILE")
if profile_name:
print(f" Using profile: {profile_name}")
session_kwargs["profile_name"] = profile_name
retry_config = Config(
region_name=target_region,
retries={
"max_attempts": 10,
"mode": "standard",
},
)
session = boto3.Session(**session_kwargs)
if assumed_role:
print(f" Using role: {assumed_role}", end='')
sts = session.client("sts")
response = sts.assume_role(
RoleArn=str(assumed_role),
RoleSessionName="langchain-llm-1"
)
print(" ... successful!")
client_kwargs["aws_access_key_id"] = response["Credentials"]["AccessKeyId"]
client_kwargs["aws_secret_access_key"] = response["Credentials"]["SecretAccessKey"]
client_kwargs["aws_session_token"] = response["Credentials"]["SessionToken"]
if runtime:
service_name='bedrock-runtime'
else:
service_name='bedrock'
bedrock_client = session.client(
service_name=service_name,
config=retry_config,
**client_kwargs
)
print("boto3 Bedrock client successfully created!")
print(bedrock_client._endpoint)
return bedrock_client
创建Amazon RDS for SQL Server向量数据存储
Amazon RDS for SQL Server的是部署在RDS数据库实例中,我们需要提前创建并连接到数据库中。确保创建时选择以下选项:
- 引擎选项(Engine Options): 选择Microsoft SQL Server
- 引擎版本(Engine Version): 选择SQL Server 2019 15.00.4345.5.v1
- 版本(Edition): 选择SQL Server Standard Edition
- 数据库实例类型(DB Instance Class): 选择db.t3.xlarge
- 存储类型(Storage Type): 选择GP3
- 公共访问(Public Access): 选择Yes,这样大家可以直接从本地工作站连接到 RDS for SQL Server 实例
- 选项组(Option Group): 选择包含SQLSERVER_BACKUP_RESTORE选项的选项组。这是还原本文提供的SQL Server原生备份的前提条件。
完成Amazon RDS for SQL Server实例的创建,并还原本文提供的向量数据库备份后,大家应该可以浏览到[vector_db_wiki]
数据库,如下所示:
[vector_db_wiki]
数据库结构
该数据库包含以下三个表:
wikipedia_articles
(用于本方案中的原始业务数据)wikipedia_articles_embedding_bedrock
(存储Bedrock生成的向量嵌入数据)wikipedia_articles_content_vector
(将被执行向量化的文章内容数据)
此外本数据库中还包含一个用户自定义函数(UDF),用于实现余弦相似度(Cosine Similarity)计算逻辑:
Bedrock_SearchSimilarContentArticles
(用于执行基于相似度搜索的查询)
在本系列下篇的文章中,我们将继续介绍如何使用RDS for SQL Server、Bedrock和SageMaker,通过动手实践在云平台上搭建该解决方案架构,并详细讲解我们的聊天机器人应用如何与Bedrock基础模型交互,以及如何在向量数据存储中运行余弦距离计算搜索并输出相似性的内容。欢迎大家继续关注小李哥的生成式AI应用安全系列,了解国际前沿的亚马逊云科技解决方案,关注我不要错过未来更多的干货内容!