使用Amazon Titan实现语义图像搜索
使用Amazon Titan和Supabase Vector在Python中实现语义图像搜索
Amazon Bedrock 是一项全托管服务,提供来自领先AI公司(如AI21 Labs、Anthropic、Cohere、Meta、Mistral AI、Stability AI和亚马逊)的高性能基础模型(FMs)选择。每个模型都通过统一的API访问,该API实现了广泛的功能集,旨在帮助构建具有安全性、隐私性和负责任AI考虑的生成式AI应用。
Amazon Titan 是一个基础模型(FMs)系列,支持文本和图像生成、摘要、分类、开放式问答、信息提取以及文本或图像搜索。
本指南将介绍如何通过Python使用Amazon Titan多模态模型和vecs客户端开始结合Amazon Bedrock与Supabase Vector。
您可以在GitHub上找到完整的应用代码,这是一个基于Python Poetry的项目。
使用Poetry创建新Python项目
Poetry 为Python提供打包和依赖管理功能。如果尚未安装,请通过pip安装poetry:
1pip install poetry
然后初始化新项目:
1poetry new aws_bedrock_image_search
快速启动带 pgvector 的 Postgres 数据库
如果尚未创建项目,请前往 database.new 创建一个新项目。每个 Supabase 项目都附带完整的 Postgres 数据库和预配置的 pgvector 扩展。
创建项目时,请务必记下数据库密码,因为在下一步构建 DB_URL
时需要用到。
您可以在项目仪表板中找到数据库连接字符串,点击 Connect。使用会话池连接字符串,格式如下:
1postgresql://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@aws-0-[REGION].pooler.supabase.com:5432/postgres
安装依赖项
我们需要为项目添加以下依赖项:
vecs
: Supabase 向量 Python 客户端boto3
: AWS Python SDKmatplotlib
: 用于显示图像结果
1poetry add vecs boto3 matplotlib
导入必要的依赖项
在您的 Python 主脚本顶部,导入依赖项并将上述 DB URL
存储在变量中:
12345678910import sysimport boto3import vecsimport jsonimport base64from matplotlib import pyplot as pltfrom matplotlib import image as mpimgfrom typing import OptionalDB_CONNECTION = "postgresql://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@aws-0-[REGION].pooler.supabase.com:5432/postgres"
接下来,获取 AWS 账户凭证 并实例化 boto3
客户端:
12345678bedrock_client = boto3.client( 'bedrock-runtime', region_name='us-west-2', # 来自您 AWS 账户的凭证 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
字符串。创建以下辅助方法:
1234567891011121314151617181920212223242526272829303132333435363738394041424344def readFileAsBase64(file_path): """将图片编码为base64字符串""" try: with open(file_path, "rb") as image_file: input_image = base64.b64encode(image_file.read()).decode("utf8") return input_image except: print("无效文件名") sys.exit(0)def construct_bedrock_image_body(base64_string): """构造请求体 参考文档: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): """通过API请求调用Amazon Titan模型""" 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): """为指定路径的图片生成嵌入向量""" base64_string = readFileAsBase64(file_path) body = construct_bedrock_image_body(base64_string) emb = get_embedding_from_titan_multimodal(body) return emb
接下来,创建一个seed
方法,该方法将创建一个新的Supabase向量集合,为您的图片生成嵌入向量,并将这些向量插入数据库:
12345678910111213141516171819202122232425262728293031323334353637383940def seed(): # 创建向量存储客户端 vx = vecs.create_client(DB_CONNECTION) # 获取或创建一个1024维的向量集合 images = vx.get_or_create_collection(name="image_vectors", dimension=1024) # 使用Amazon Titan模型生成图片嵌入向量 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') # 向images集合添加记录 images.upsert( records=[ ( "one.jpg", # 向量标识符 img_emb1, # 向量值,可以是列表或np.array {"type": "jpg"} # 关联的元数据 ), ( "two.jpg", img_emb2, {"type": "jpg"} ), ( "three.jpg", img_emb3, {"type": "jpg"} ), ( "four.jpg", img_emb4, {"type": "jpg"} ) ] ) print("已插入图片") # 为集合创建索引以提高搜索性能 images.create_index() print("已创建索引")
在pyproject.toml
文件中添加这个方法作为脚本:
123[tool.poetry.scripts]seed = "image_search.main:seed"search = "image_search.main:search"
通过poetry shell
激活虚拟环境后,您现在可以通过poetry run seed
运行种子脚本。您可以在Supabase仪表板的Table Editor中查看生成的嵌入向量,选择vecs
模式和image_vectors
表。
通过文本查询执行图像搜索
我们可以使用 Supabase Vector 来查询我们的嵌入向量。既可以使用图像作为搜索输入,也可以从字符串输入生成嵌入向量:
12345678910111213141516171819202122232425262728def search(query_term: Optional[str] = None): if query_term is None: query_term = sys.argv[1] # 创建向量存储客户端 vx = vecs.create_client(DB_CONNECTION) images = vx.get_or_create_collection(name="image_vectors", dimension=1024) # 编码文本查询 text_emb = get_embedding_from_titan_multimodal(json.dumps( { "inputText": query_term, "embeddingConfig": {"outputEmbeddingLength": 1024}, } )) # 查询集合,筛选元数据中"type"为"jpg"的记录 results = images.query( data=text_emb, # 必需参数 limit=1, # 返回记录数量 filters={"type": {"$eq": "jpg"}}, # 元数据筛选器 ) 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 实现图像搜索和反向图像搜索功能。