利用PostgreSQL向量数据库和负责任的AI知识库在亚马逊云科技上构建商品推荐机器人

news2024/11/16 7:39:14

项目简介:

小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案,帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践,并应用到自己的日常工作里。

本次介绍的是如何在亚马逊云科技利用PostgreSQL向量数据库和大模型托管服务Amazon Bedrock,开发一个人工智能对话机器人。本架构使用了RAG技术,机器人从大语言AI模型获得的对话内容只基于向量数据库内的文档内容生成,使对话机器人为用户生成可靠的、负责任的的内容。本架构设计全部采用了云原生Serverless架构,提供可扩展和安全的AI解决方案。本方案的解决方案架构图如下:

方案所需基础知识 

什么是 Amazon Bedrock?

Amazon Bedrock 是亚马逊云科技提供的一项服务,旨在帮助开发者轻松构建和扩展生成式 AI 应用。Bedrock 提供了访问多种强大的基础模型(Foundation Models)的能力,支持多种不同大模型厂商的模型,如AI21 Labs, Anthropic, Cohere, Meta, Mistral AI, Stability AI, 和Amazon,用户可以使用这些模型来创建、定制和部署各种生成式 AI 应用程序,而无需从头开始训练模型。Bedrock 支持多个生成式 AI 模型,包括文本生成、图像生成、代码生成等,简化了开发流程,加速了创新。

什么是 Amazon Aurora PostgreSQL 向量数据库?

Amazon Aurora PostgreSQL 是亚马逊云科技提供的一种高性能、可扩展的关系型数据库,结合了 PostgreSQL 的灵活性和 Aurora 的企业级性能。Aurora PostgreSQL 现在支持向量数据库功能,使得用户可以在数据库中高效存储和检索高维向量数据,这对于处理和查询复杂数据类型(如图像、文本嵌入)非常有用。

应用 RAG 到对话机器人中的好处

将检索增强生成(RAG)技术应用到对话机器人中,能够显著提升生成内容的准确性和可靠性。RAG 通过结合实时检索和生成式 AI 模型,确保对话机器人在提供答案时,能够利用最新的、高相关性的知识库进行响应。这样不仅提高了对话的质量,还能有效减少错误信息的生成,增强用户的信任和满意度。

本方案包括的内容

1. 创建Amazon Aurora PostgreSQL向量数据库

2. 利用Amazon Bedrock创建和配置知识库

3. 将S3内的文档向量化,并同步到向量数据库中

4. 对聊天机器人进行测试,提问知识库中包含和不包含的内容

项目搭建具体步骤:

1. 进入亚马逊云科技控制台,创建一台EC2,命名为“DBBastion”,用于PostgreSQL数据库的管理和维护。接下来我们通过SSH连接进入到Linux服务器中。

2.  创建一个SQL脚本文件“vector_config.sql”,复制以下SQL命令。该SQL脚本安装了vector扩展,创建了一个新的Schema和表,并创建了索引。

/*
The below SQL statements check if the PostgreSQL extension named 'vector' is installed, and if not, it installs it. Then, it creates a schema called 'bedr
ock_integration' and a table named 'bedrock_kb' within that schema, which includes columns for storing UUID, vector embeddings, text chunks, JSON metadata
, country, variety, points, and price.

Finally, it creates an index on the 'embedding' column using the HNSW (Hierarchical Navigable Small World) algorithm for efficient vector similarity searc
hes.
*/

SELECT extversion FROM pg_extension WHERE extname='vector';
CREATE EXTENSION IF NOT EXISTS vector;
SELECT extversion FROM pg_extension WHERE extname='vector';
CREATE SCHEMA IF NOT EXISTS bedrock_integration;
CREATE TABLE bedrock_integration.bedrock_kb (id uuid PRIMARY KEY, embedding vector(1024), chunks text, metadata json, country text, variety text, points s
mallint, price numeric);
CREATE INDEX on bedrock_integration.bedrock_kb USING hnsw (embedding vector_cosine_ops);

在命令行运行该脚本,将cluster_endpoint替换为数据库集群URL写入节点。


psql -h <cluster_endpoint> -U postgres -d vector -w -f vector_config.sql

3. 接下来我们创建一个新的S3存储桶“wine-knowledgebase-07a0da60”,用于保存对话机器人知识库的源文档。

4. 接下来我们进入到亚马逊云科技密码管理服务Secret Manager,创建一个新的Secret保存数据库账户和密码,secret类型为“Credentials for Amazon RDS database”。

5. 选择我们将账户密码匹配到对应的数据库。

6. 为Secret起名“vectordb-secret”,点击Next到下一步

 7. 在亚马逊云科技上,我们可以通过以下代码调用Secret Manager API取出账户和密码。

# Use this code snippet in your app.
# If you need more information about configurations
# or implementing the sample code, visit the AWS docs:
# https://aws.amazon.com/developer/language/python/

import boto3
from botocore.exceptions import ClientError


def get_secret():

    secret_name = "vectordb-secret"
    region_name = "us-east-1"

    # Create a Secrets Manager client
    session = boto3.session.Session()
    client = session.client(
        service_name='secretsmanager',
        region_name=region_name
    )

    try:
        get_secret_value_response = client.get_secret_value(
            SecretId=secret_name
        )
    except ClientError as e:
        # For a list of exceptions thrown, see
        # https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
        raise e

    secret = get_secret_value_response['SecretString']

    # Your code goes here.

8. 接下来我们进入到AI大模型托管服务Amazon Bedrock托管服务中,确保“Titan Text G1 - Premier”和“Titan Text Embeddings V2”模型是开启状态。

9. 接下来我们在Amazon Bedrock主页左边栏点击“Knowledge base”并点击创建一个新的Knowledge base知识库。

10. 为知识库起名“wine-kb”,并创建一个新的IAM role权限,用于授权Bedrock访问其他服务,如读取S3存储桶中的文档内容。

11. 选择S3为知识库数据源

12. 接下来我们配置S3数据源,为数据源命名为“wine-kb-data-source”,并选择我们保存文件的S3存储桶。

13. 接下来我们选择知识库向量模型为“Titan Text Embeddings v2”,这里的向量维度Vector dimensions我们选择为1024。

14. 将我们创建的Amazon Aurora添加为向量数据库

15. 添加保存向量的向量数据库具体参数,如ARN ID、数据库名、表名、保存数据库账户密码的Secret ARN ID等。

16. 接下来配置索引信息,指明在数据库表中存储向量、文本、元数据的索引字段和主键,最后点击创建。

17. 接下来我们点击我们刚刚创建的S3数据源,并点击SYNC将S3中的文件进行向量化,同步到知识库的向量数据库中。

18. 接下来我们回到EC2服务器中,创建一个Python代码依赖信息txt文件,复制以下内容。

aiohttp==3.8.4
aiosignal==1.3.1
altair==5.0.1
async-timeout==4.0.2
attrs==23.1.0
blinker==1.6.2
boto3==1.34.120
botocore==1.34.120
cachetools==5.3.1
certifi==2023.5.7
charset-normalizer==3.1.0
click==8.1.3
dataclasses-json==0.5.7
decorator==5.1.1
frozenlist==1.3.3
gitdb==4.0.10
GitPython==3.1.31
idna==3.4
importlib-metadata==6.6.0
Jinja2==3.1.2
jmespath==1.0.1
jsonschema==4.17.3
langchain==0.0.195
langchainplus-sdk==0.0.8
markdown-it-py==2.2.0
MarkupSafe==2.1.3
marshmallow==3.19.0
marshmallow-enum==1.5.1
mdurl==0.1.2
multidict==6.0.4
mypy-extensions==1.0.0
numexpr==2.8.4
numpy==1.24.3
openapi-schema-pydantic==1.2.4
packaging==23.1
pandas==2.0.2
Pillow==9.5.0
protobuf==4.23.2
pyarrow==12.0.0
pydantic==1.10.9
pydeck==0.8.1b0
Pygments==2.15.1
Pympler==1.0.1
pyrsistent==0.19.3
python-dateutil==2.8.2
pytz==2023.3
pytz-deprecation-shim==0.1.0.post0
PyYAML==6.0
requests==2.31.0
rich==12.6.0
rich-cli==1.8.0
s3transfer==0.10.0
six==1.16.0
smmap==5.0.0
SQLAlchemy==2.0.15
streamlit==1.35.0
streamlit-chat==0.0.2.2
tenacity==8.2.2
toml==0.10.2
toolz==0.12.0
tornado==6.3.2
typing-inspect==0.9.0
typing_extensions==4.6.3
tzdata==2023.3
tzlocal==4.3
urllib3==1.26.16
validators==0.20.0
yarl==1.9.2
zipp==3.15.0
unstructured==0.8.1
transformers~=4.30.2

19. 再创建一个Python文件“winebot-kb.py”,复制以下代码。该Python文件中,我们使用Streamlit 构建了一个 Web 应用程序,基于知识库内的葡萄酒相关的文档,调用Amazon Bedrock上的大语言,在对话机器人中为用户回答葡萄酒相关问题。

import streamlit as st
import boto3
import json

# Initialize AWS clients
aws_region = 'us-east-1'

client = boto3.client("bedrock-runtime", region_name=aws_region,
)
kb_client = boto3.client('bedrock-agent-runtime', region_name=aws_region,
)


def get_kb_id():
    bedrock_agent_client = boto3.client("bedrock-agent","us-east-1",
    )

    response = bedrock_agent_client.list_knowledge_bases(maxResults=1)
    if len(response["knowledgeBaseSummaries"]) == 1:
        return response["knowledgeBaseSummaries"][0]["knowledgeBaseId"]
    else:
        return "None"


# Streamlit page configuration
st.set_page_config(page_title="A Sommelier LLM chatbot with KB", page_icon=":robot:")

# Display the wine image
st.image("winebot.png", use_column_width=True)

# Application title
st.write("""
# Sammy the Sommelier

An LLM based wine expert!
""")

kb_on = st.radio("**Enable Knowledge Base:**", ["No", "Yes"])
if kb_on == "Yes":
    kb_id = get_kb_id()
    country_in = st.selectbox("**Choose a Country:**", ["India", "Georgia", "Romania", "Uruguay", "Brazil"])
    points_in = st.slider("**Choose a minimum wine point score:**", min_value=0, max_value=100, step=5, value=50)
    price_in = st.slider("**Choose a maximum price:**", min_value=0, max_value=1000, step=10, value=1000)
# Initialize chat history
if 'chat_history' not in st.session_state:
    st.session_state.chat_history = []

# Display chat history
for message in st.session_state.chat_history:
    with st.chat_message(message['role']):
        st.markdown(message['text'])


def invoke_llm_with_history(user_query, chat_history, kb_flag):
    body = {}

    parameters = {
        "maxTokenCount": 1000,
        "stopSequences": [],
        "temperature": 0,
        "topP": 1
    }
    conversation = "\n".join([f"{msg['role']}: {msg['text']}" for msg in chat_history])

    if kb_flag == "Yes":
        print("KbYes")
        kb_response, kb_source = invoke_kb(user_query, country_in, points_in, price_in)
        if kb_response:
            st.session_state.chat_history.append({"role": 'user', "text": user_query})
            st.session_state.chat_history.append({"role": 'kb', "text": kb_response})

        prompt = f"""
        You are a wine expert. You enjoy discussing wine in general as well as giving detailed wine recommendations .

        You are given the following query from the user:
        {user_query}

        You also have access to previous conversation history:
        {conversation}

        Take into account the following information retrieved from a knowledge base when making your recommendation:
        {kb_response}
        {price_in}
        {points_in}
        {country_in}

        End your response with, The source for my recommendation comes from:
        {kb_source}
        """

        body = json.dumps({
            "inputText": prompt,
            "textGenerationConfig": parameters
        }).encode()

        try:
            response = client.invoke_model(
                body=body,
                modelId="amazon.titan-text-premier-v1:0",
                accept="application/json",
                contentType="application/json",
            )
            return json.loads(response["body"].read())["results"][0]["outputText"]
        except Exception as e:
            st.error(f"Error invoking LLM: {e}")
            return ""
    else:
        print("KbNo")
        prompt = f"""
        You are a wine expert. You enjoy discussing wine in general as well as giving detailed wine recommendations.


        Your previous conversation history with the human is:
        {conversation}


        Based on the question or statement below you need to recommend a wine including a brief description and price:
        {user_query}

        """

        body = json.dumps({
            "inputText": prompt,
            "textGenerationConfig": parameters
        }).encode()

        try:
            response = client.invoke_model(
                body=body,
                modelId="amazon.titan-text-premier-v1:0",
                accept="application/json",
                contentType="application/json",
            )
            return json.loads(response["body"].read())["results"][0]["outputText"]
        except Exception as e:
            st.error(f"Error invoking LLM: {e}")
            return ""


def invoke_kb(query, country, points, price):
    try:
        response = kb_client.retrieve(
            knowledgeBaseId=kb_id,
            retrievalQuery={
                'text': query
            },
            retrievalConfiguration={
                "vectorSearchConfiguration": {
                    "numberOfResults": 2,
                    "filter": {
                        "andAll": [
                            {
                                "equals": {"key": "country", "value": country}
                            },
                            {
                                "greaterThan": {"key": "points", "value": points}
                            },
                            {
                                "lessThan": {"key": "price", "value": price}
                            }

                        ]
                    }
                }
            }
        )

        contents = response["retrievalResults"]
        print(contents)

        wine_recommendations = ""
        source_docs = ""
        for content in contents:
            print(content['content']['text'])
            print("-------------------------------------------------------------------------------")
            print(content['location']['s3Location']['uri'])
            wine_recommendations = wine_recommendations + content['content']['text'] + "\n"
            source_docs = source_docs + content['location']['s3Location']['uri'] + "\n"
        return wine_recommendations, source_docs

    except Exception as e:
        st.error(f"Error retrieving from knowledge base: {e}")
        return ""


def main():
    user_query = st.chat_input("What kind of wine are you looking for?")
    if user_query:
        with st.chat_message('user'):
            st.markdown(user_query)

        response = invoke_llm_with_history(user_query, st.session_state.chat_history, kb_on)
        if response:
            with st.chat_message('assistant'):
                st.markdown(response)
            st.session_state.chat_history.append({"role": 'assistant', "text": response})


if __name__ == "__main__":
    main()

20. 接下来在Linux命令行中运行以下命令,启动streamlit Web服务器。

python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
streamlit run winebot-kb.py

21. 启动服务器后命令行会返回一个网页URL:“External URL”,我们在浏览器中打开该网页。

22. 我们登入到葡萄酒对话机器人网页中,配置葡萄酒原产地区,设置葡萄酒评分和价格区间,让大模型根据我们的设置参数进行更精准的回复。我们在问题框中提问:我想要一个轻柔并且有果香的葡萄酒。

23. 最终我们可以得到葡萄酒对话机器人基于知识库中的葡萄酒文档得出的最终回复。

以上就是在亚马逊云科技上利用Amazon Bedrock上的AI大模型和Amazon Aurora PostgreSQL向量数据库,开发生成可靠、负责任内容的聊天机器人服务的全部步骤。欢迎大家未来与我一起,未来获取更多国际前沿的生成式AI开发方案。

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

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

相关文章

软件需求规格说明书编写规范(Doc原件)

软件需求规格说明书编写规范&#xff08;Word原件&#xff09; 1.项目背景 2.项目目标 3.系统架构 4.总体流程 5.名称解释 6.功能模块 软件全套资料部分文档清单&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明…

WPF MvvmLight

关于 停止更新 官网&#xff1a;http://www.mvvmlight.net/ 源码地址&#xff1a;GitHub - lbugnion/mvvmlight: The main purpose of the toolkit is to accelerate the creation and development of MVVM applications in Xamarin.Android, Xamarin.iOS, Xamarin.Forms, Wi…

C++ //练习 17.17 更新你的程序,令它查找输入序列中所有违反“ei“语法规则的单词。

C Primer&#xff08;第5版&#xff09; 练习 17.17 练习 17.17 更新你的程序&#xff0c;令它查找输入序列中所有违反"ei"语法规则的单词。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块&#xff1a; /**********…

定制开发AI智能名片O2O商城小程序:基于限量策略与个性化追求的营销创新

摘要:随着科技的飞速发展和消费者需求的日益多元化&#xff0c;传统商业模式正经历着前所未有的变革。在数字化转型的大潮中&#xff0c;定制开发AI智能名片O2O商城小程序作为一种新兴的商业模式&#xff0c;凭借其独特的个性化定制能力、高效的线上线下融合&#xff08;O2O&am…

居住证申报系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;群众用户管理&#xff0c;警方管理&#xff0c;居住证登记管理&#xff0c;回执单管理&#xff0c;领证信息管理&#xff0c;公告栏管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页…

MySQL数据库专栏(四)数据库操作

1、创建数据库 create database if not exists [数据库名称] character set [字符集] COLLATE [排序规则]; 例如&#xff1a;create database if not exists db_demo character set utf8mb4 COLLATE utf8mb4_general_ci; if not exists&#xff1a;判断数据库是否存在&#x…

Ubuntu20, Windows10 双系统安装

1. 制作启动盘 1.1 下载 Ubuntu 系统镜像 ISO 文件 从 Ubuntu 官网下载 (https://cn.ubuntu.com/download/desktop)。官网访问慢的&#xff0c;从国内镜像点下。 1.2 烧录 Ubuntu ISO 镜像 下载 Rufus&#xff1a;从Rufus官网下载 Rufus 工具。 插入U 盘&#xff1a;将U盘插…

详解语义安全(semantically secure)

目录 一. 引入 二. 密文与明文 2.1 通俗性理解 2.2 定理 2.3 定理理解 三. 语义安全的第一个版本 3.1 基本理解 3.2 定理 3.3 定理理解 四. 语义安全的第二个版本 4.1 直观解释 4.2 小结 一. 引入 密码学中安全加密要求&#xff1a;敌手&#xff08;adversary&…

“百板齐发“ — 一个拥有上百个独特看板的代码

精选100套AXURE可视化数据大屏看板 产品经理高效工具 高保真原型模板 赋能智慧城市 元件库 AXURE9.0版本&#xff0c;所有页面均可编辑&#xff0c;部分地图与实现放大缩小&#xff0c;拖拉拽的功能。 01.水质情况实时监测预警系统 02.全国停车云实时数据监测系统 03.中国移…

【系统分析师】-综合知识-补充知识

1、在软件设计中&#xff0c;通常由着眼于“宏观的”软件架构开始&#xff0c;由着眼于“微观的”构件模块结束。 即测试应该从“微观”开始&#xff0c;逐步转向“宏观”。 2、数据备份是信息系统运行管理时保护数据的重要措施。增量备份可针对上次任何一种备份进行&#xf…

海康VisionMaster使用学习笔记7-Group模块

Group模块的使用 1. 添加图像源&#xff0c;导入图片 2. 添加快速匹配 对匹配框区域进行顶点检测 并循环10次(匹配框个数 从而检测出所有顶点)。 3. 添加Group工具 拖一个Group模块 点击设置 输入设置 添加图像源输入数据 添加快速匹配的匹配框 4. 双击Group工具块进入 添加…

网络原理知识总结

一、网络模型 1.1 osi七层参考模型 物理层&#xff1a;连接通信链路、传输比特流数据链路层&#xff1a;数据封装成帧&#xff0c;在节点与节点间实现可靠物理地址寻址&#xff0c;进行差错校验、流量控制网络层&#xff1a;逻辑地址寻址&#xff0c;路由选择 IP(IPV4IPV6) I…

Oracle start with connect by prior 递归查询

基本语法 select … from tablename where 条件1 start with 条件2 connect by 条件3(PRIOR);条件1&#xff1a;相当于基本的筛选数据 条件2&#xff1a;递归查询起始条件 条件3&#xff1a;连接条件&#xff0c;其中用PRIOR表示上一条记录的结果作为本次查询的条件&#xff0…

后端开发刷题 | 二叉树的前序遍历

描述 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 数据范围&#xff1a;二叉树的节点数量满足 1≤n≤100 &#xff0c;二叉树节点的值满足 1≤val≤100&#xff0c;树的各节点的值各不相同 示例 1&#xff1a; 示例1 输入&#xff1a; {1,#,2,3} 返…

攻击实现摄像头、gvm、openvas安装

网络安全 前言1、kali 发现主机2、[mac地址](https://mac.bmcx.com/#google_vignette)查询3、openvas 安装openvas使用1、添加主机目标2、新建扫描任务3、开始扫描4、查看扫描信息。如果有cve那说明可用 前言 全国网络安全标准化技术委员会&#xff1a;https://www.tc260.org.…

【hot100篇-python刷题记录】【移动零】

R5-双指针 要用双指针来实现&#xff0c;想到一个办法&#xff0c;左右两边双指针&#xff0c;当左边指针找到0就和右指针交换值&#xff0c;要减少操作次数的话&#xff0c;就顺便判断一下右指针是否为0即可&#xff0c;最后肯定是双指针碰撞的。 不对&#xff0c;不能交换值…

普通人如何让AI应用于我们的办公?

最强小说推文——AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频百万播放量https://aitools.jurilu.com/ 当你学会用好AI&#xff0c;真的可以帮助你提高工作效率&#xff0c;把更多的时间放在摸鱼上&#xff01; 想要AI应用…

Emacs25.x版本之重要特性及用法实例(一百五十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列…

探索Jinja2的神秘力量:Python模板引擎的魔法之旅

文章目录 探索Jinja2的神秘力量&#xff1a;Python模板引擎的魔法之旅1. 背景&#xff1a;为何选择Jinja2&#xff1f;2. 什么是Jinja2&#xff1f;3. 安装Jinja2&#xff1a;一键启程4. 基础用法&#xff1a;Jinja2的五大法宝5. 实战演练&#xff1a;Jinja2在场景中的应用6. 常…

xssnote

XSS漏洞: 文章目录 XSS漏洞:反射型&#xff1a;第一个例子&#xff1a; 实体&#xff0c;url&#xff0c;和js的Unicode编码img——重要标签浏览器解析机制&#xff1a;容纳字符实体&#xff1a;字符引用&#xff1a;RCDATA状态中的字符引用&#xff1a; URL解析&#xff1a;解…