使用 Amazon Titan 和 Supabase Vector 实现语义图像搜索

Amazon Bedrock 是一项完全托管的服务,提供来自 AI21 Labs、Anthropic、Cohere、Meta、Mistral AI、Stability AI 和 Amazon 等领先 AI 公司的高性能基础模型 (FM) 选项。每个模型都可以通过一个通用的 API 访问,该 API 实现了一组广泛的功能,以帮助构建具有安全性、隐私性和负责任的 AI 的生成式 AI 应用程序。

Amazon Titan 是一系列基础模型 (FM),用于文本和图像生成、摘要、分类、开放式问答、信息提取以及文本或图像搜索。

在这篇文章中,我们将了解如何使用 Amazon Titan 多模态模型和 vecs客户端在 Python 中开始使用 Amazon Bedrock 和Supabase Vector。

您可以在 GitHub上以 Python Poetry 项目的形式找到完整的应用程序代码。

使用 Poetry 创建新的 Python 项目

Poetry为 Python 提供打包和依赖项管理。如果您还没有,请通过 pip 安装poetry :

pip install poetry

然后初始化一个新项目:

arduino 复制代码
poetry new aws_bedrock_image_search

使用 pgvector 启动 Postgres 数据库

如果您还没有,请转到 database.new 并创建一个新项目。每个 Supabase 项目都带有一个完整的 Postgres 数据库和预先配置的 pgvector 扩展

创建项目时,请务必记下数据库密码,因为在下一步中构造DB_URL将需要它。

您可以在 Supabase Dashboard 数据库设置中找到数据库连接字符串。选择"使用连接池"和"模式:会话"以直接连接到 Postgres 数据库。它看起来像这样:

ini 复制代码
postgresql://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@aws-0-[REGION].pooler.supabase.com:5432/postgres

安装依赖项

我们需要将以下依赖项添加到我们的项目中:

  • vecs:Supabase Vector Python 客户端。
  • boto3:适用于 Python 的 AWS 开发工具包。
  • matplotlib:用于显示我们的图像结果。
csharp 复制代码
poetry add vecs boto3 matplotlib

导入必要的依赖项

在主 python 脚本的顶部,导入依赖项并将上面的数据库 URL 存储在一个变量中:

python 复制代码
import sys
import boto3
import vecs
import json
import base64
from matplotlib import pyplot as plt
from matplotlib import image as mpimg
from typing import Optional

DB_CONNECTION = "postgresql://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@aws-0-[REGION].pooler.supabase.com:5432/postgres"

接下来,获取 AWS 账户的凭证并实例化 boto3 客户端:

ini 复制代码
bedrock_client = boto3.client(
    'bedrock-runtime',
    region_name='us-west-2',
    # Credentials from your AWS account
    aws_access_key_id='<replace_your_own_credentials>',
    aws_secret_access_key='<replace_your_own_credentials>',
    aws_session_token='<replace_your_own_credentials>',
)

为图像创建嵌入

在项目的根目录中,创建一个名为 images 的新文件夹并添加一些图像。您可以在 GitHub上使用示例项目中的图像,也可以在 unsplash上找到免许可图像。

要将图像发送到 Amazon Bedrock API,我们需要将它们编码为 base64 字符串。创建以下帮助程序方法:

python 复制代码
def readFileAsBase64(file_path):
    """Encode image as base64 string."""
    try:
        with open(file_path, "rb") as image_file:
            input_image = base64.b64encode(image_file.read()).decode("utf8")
        return input_image
    except:
        print("bad file name")
        sys.exit(0)


def construct_bedrock_image_body(base64_string):
    """Construct the request body.

    https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-titan-embed-mm.html
    """
    return json.dumps(
        {
            "inputImage": base64_string,
            "embeddingConfig": {"outputEmbeddingLength": 1024},
        }
    )


def get_embedding_from_titan_multimodal(body):
    """Invoke the Amazon Titan Model via API request."""
    response = bedrock_client.invoke_model(
        body=body,
        modelId="amazon.titan-embed-image-v1",
        accept="application/json",
        contentType="application/json",
    )

    response_body = json.loads(response.get("body").read())
    print(response_body)
    return response_body["embedding"]


def encode_image(file_path):
    """Generate embedding for the image at file_path."""
    base64_string = readFileAsBase64(file_path)
    body = construct_bedrock_image_body(base64_string)
    emb = get_embedding_from_titan_multimodal(body)
    return emb

接下来,创建一个种子方法,该方法将创建一个新的 Supabase Vector Collection,为您的图像生成嵌入,并将嵌入更新到您的数据库中:

ini 复制代码
def seed():
    # create vector store client
    vx = vecs.create_client(DB_CONNECTION)

    # get or create a collection of vectors with 1024 dimensions
    images = vx.get_or_create_collection(name="image_vectors", dimension=1024)

    # Generate image embeddings with Amazon Titan Model
    img_emb1 = encode_image('./images/one.jpg')
    img_emb2 = encode_image('./images/two.jpg')
    img_emb3 = encode_image('./images/three.jpg')
    img_emb4 = encode_image('./images/four.jpg')

    # add records to the *images* collection
    images.upsert(
        records=[
            (
                "one.jpg",       # the vector's identifier
                img_emb1,        # the vector. list or np.array
                {"type": "jpg"}  # associated  metadata
            ), (
                "two.jpg",
                img_emb2,
                {"type": "jpg"}
            ), (
                "three.jpg",
                img_emb3,
                {"type": "jpg"}
            ), (
                "four.jpg",
                img_emb4,
                {"type": "jpg"}
            )
        ]
    )
    print("Inserted images")

    # index the collection for fast search performance
    images.create_index()
    print("Created index")

将此方法添加为 pyproject.toml 文件中的脚本:

ini 复制代码
[tool.poetry.scripts]
seed = "image_search.main:seed"
search = "image_search.main:search"

使用 poetry shell 激活虚拟环境后,您现在可以通过 poetry run seed 运行您的种子脚本。您可以通过访问表编辑器、选择 vecs 模式和 image_vectors 表来检查 Supabase 仪表板中生成的嵌入。

从文本查询执行图像搜索

使用 Supabase Vector,我们可以轻松查询我们的嵌入。我们可以使用图像作为搜索输入,也可以从字符串输入生成嵌入并将其用作查询输入:

ini 复制代码
def search(query_term: Optional[str] = None):
    if query_term is None:
        query_term = sys.argv[1]

    # create vector store client
    vx = vecs.create_client(DB_CONNECTION)
    images = vx.get_or_create_collection(name="image_vectors", dimension=1024)

    # Encode text query
    text_emb = get_embedding_from_titan_multimodal(json.dumps(
        {
            "inputText": query_term,
            "embeddingConfig": {"outputEmbeddingLength": 1024},
        }
    ))

    # query the collection filtering metadata for "type" = "jpg"
    results = images.query(
        data=text_emb,                      # required
        limit=1,                            # number of records to return
        filters={"type": {"$eq": "jpg"}},   # metadata filters
    )
    result = results[0]
    print(result)
    plt.title(result)
    image = mpimg.imread('./images/' + result)
    plt.imshow(image)
    plt.show()

通过将查询限制为一个结果,我们可以向用户显示最相关的图像。最后,我们使用 matplotlib 向用户显示图像结果。

就是这样,继续通过poetry run search搜索来测试它,您将看到"红砖墙前的自行车"的图像。

结论

只需几行 Python,您就可以使用 Amazon Titan 多模态模型和 Supabase Vector 实现图像搜索和反向图像搜索。

更多

Amazon Bedrock 和 vecs 入门

国内版supabase

相关推荐
AskHarries几秒前
Java字节码增强库ByteBuddy
java·后端
前端啊龙2 分钟前
用vue3封装丶高仿element-plus里面的日期联级选择器,日期选择器
前端·javascript·vue.js
一颗松鼠6 分钟前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
小远yyds26 分钟前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
吕彬-前端1 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱1 小时前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
许野平1 小时前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
guai_guai_guai2 小时前
uniapp
前端·javascript·vue.js·uni-app
bysking2 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓3 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js