使用 PostgreSQL pgvector 的 AI 应用程序中的多模态搜索

本文涉及的产品
性能测试 PTS,5000VUM额度
应用实时监控服务-应用监控,每月50GB免费额度
可观测可视化 Grafana 版,10个用户账号 1个月
简介: 大型语言模型(LLM)的发展已拓展至多模态领域,不仅能处理文本,还能解析图像。本文介绍如何构建一个多模态搜索应用,用户可通过上传图片或输入文本来搜索印度菜谱。该应用支持多种LLM服务,如OpenAI及Ollama本地部署模型,并运用pgvector扩展在PostgreSQL中高效存储和检索向量嵌入。我们还展示了如何生成菜谱描述的嵌入并向数据库写入这些嵌入,以及如何通过API接口结合文本和图像查询来获取最相关的菜谱结果。此外,讨论了使用分布式SQL数据库如YugabyteDB增强应用的可扩展性和健壮性。

大型语言模型 (LLM) 已经超越了生成对文本提示的文本响应的重大发展。这些模型现在经过训练,具有高级功能,例如解释图像和从视觉输入提供详细描述。这为用户提供了更大的搜索容量。

在本文中,演示如何构建具有多模式搜索功能的应用程序。此应用程序的用户可以上传图像或提供文本输入,使他们能够搜索印度食谱数据库。该应用程序旨在与多个 LLM 提供商合作,允许用户在 OpenAI 或使用 Ollama 本地运行的模型之间进行选择。然后使用 pgvector 在 PostgreSQL 中存储和查询文本嵌入。

在深入研究代码之前,让我们概述一下每个组件在构建多模式搜索应用程序时所扮演的角色。

构建多模式搜索应用程序的组件

多模态大型语言模型 (LLM):在大型数据集上训练的模型,能够处理多种类型的数据,例如文本、图像和语音
嵌入模型:一种将输入转换为固定数量维度的数值向量的模型,用于相似性搜索;例如,OpenAI 的 text-embedding-3-small 模型生成一个 1536 维向量
PostgreSQL:适用于各种应用程序的通用关系开源数据库,配备了用于存储和查询 AI 应用程序中的向量嵌入的扩展
pgvector:用于处理向量相似性搜索的 PostgreSQL 扩展
现在我们已经了解了应用程序架构和基础组件,让我们把这些部分放在一起!

生成和存储嵌入
此项目提供实用函数,用于从您选择的提供商处生成嵌入。让我们逐步了解生成和存储文本嵌入所需的步骤。

保存原始数据集的cuisines.csv文件被读取并存储在 Pandas DataFrame 中,以便进行操作。

每个配方的描述都传递给函数,以在 DataFrame 中填充新的列嵌入。然后,此数据将写入新的 output.csv 文件,其中包含用于相似性搜索的嵌入

1
import sys
2
import os
3
import pandas as pd
45
# Add the project root to sys.path
6
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
7
from backend.llm_interface import generate_embedding
89
# Load the CSV file
10
csv_path = './database/cuisines.csv'
11
df = pd.read_csv(csv_path)
1213
# Generate embeddings for each description in the CSV
14
df['embeddings'] = df['description'].apply(generate_embedding, args=(True,))
1516
# Save the DataFrame with embeddings to a new CSV file
17
output_csv_path = './database/output.csv'
18
df.to_csv(output_csv_path, index=False)
1920
print(f"Embeddings generated and saved to {output_csv_path}")


使用 pgvector,这些嵌入可以很容易地存储在 PostgreSQL 的 type 列中。embeddingsvector

SQL格式
1
CREATE EXTENSION IF NOT EXISTS vector;
23
CREATE table recipes (
4
   id SERIAL PRIMARY KEY,
5
   name text,
6
   description text,
7
   ...
8
   embeddings vector (768)
9
);
10

可以使用命令或使用 Pandas DataFrame 提供的函数将生成的 output.csv 文件复制到数据库中。COPYto_sql

1
# Copy to recipes table running in Docker
2
docker exec -it postgres bin/psql -U postgres -c "\COPY recipes(name,description,...,embeddings) from '/home/database/output.csv' DELIMITER ',' CSV HEADER;"
1
# Write the DataFrame to the recipes table table
2
engine = create_engine('postgresql+psycopg2://username:password@hostname/postgres')
34
df.to_sql('recipes', engine, if_exists='replace', index=False)

借助存储配方描述的向量嵌入的 PostgreSQL 实例,我们已准备好运行应用程序并执行查询。

多模态搜索应用程序
让我们将应用程序连接到数据库,开始对配方描述嵌入执行查询。

搜索端点通过多部分表单接受文本和图像。

1
# server.py
2
from llm_interface import describe_image, generate_embedding
34
...
56
@app.route('/api/search', methods=['POST'])
7
def search():
8
   image_description = None
9
   query = None
10
   # multipart form data payload
11
   if 'image' in request.files:
12
       image_file = request.files['image']
13
       image_description = describe_image(image_file)
1415
   data = request.form.get('data')
16
   if data and 'query' in data:
17
       try:
18
           data = json.loads(data)
19
           query = data['query']
20
       except ValueError:
21
           return jsonify({
   'error': 'Invalid JSON data'}), 400
2223
   if not image_description and not query:
24
       return jsonify({
   'error': 'No search query or image provided'}), 400
2526
   embedding_query = (query or '') + " " + (image_description or '')
2728
   embedding = generate_embedding(embedding_query)
2930
   try:
31
       conn = get_db_connection()
32
       cursor = conn.cursor()
33
       cursor.execute("SELECT id, name, description, instructions, image_url FROM recipes ORDER BY embeddings <=> %s::vector  LIMIT 10", (embedding,))
34
       results = cursor.fetchall()
35
       cursor.close()
36
       conn.close()
3738
       return jsonify({
   'results': results, 'image_description': image_description or None})
3940
   except Exception as e:
41
       return jsonify({
   'error': str(e)}), 500

虽然此 API 非常简单,但有两个有趣的辅助函数:和 。让我们更详细地了解一下它们是如何工作的。describe_imagegenerate_embedding


# llm_interface.py

# Function to generate a description from an image file

def describe_image(file_path):

   image_b64 = b64_encode_image(file_path)

   custom_prompt = """You are an expert in identifying Indian cuisines.

   Describe the most likely ingredients in the food pictured, taking into account the colors identified.

   Only provide ingredients and adjectives to describe the food, including a guess as to the name of the dish.

   Output this as a single paragraph of 2-3 sentences."""

   if(LLM_ECOSYSTEM == 'ollama'):

       response = ollama.generate(model=LLM_MULTIMODAL_MODEL, prompt=custom_prompt, images=[image_b64])

       return response['response']

   elif(LLM_ECOSYSTEM == 'openai'):    

       response = client.chat.completions.create(messages=[

           {
   "role": "system", "content": custom_prompt},

           {
   "role": "user", "content": [

           {
   

               "type": "image_url",

               "image_url": {
   "url": f"data:image/jpeg;base64,{image_b64}"},

           }]}

       ], model=LLM_MULTIMODAL_MODEL)

       return response.choices[0].message.content

  else:

       return "No Model Provided"

该函数采用图像文件路径,并将 base64 编码发送到用户首选的 LLM。describe_image

为简单起见,该应用程序目前支持在 Ollama 中本地运行的模型,或通过 OpenAI 提供的模型。这个 base64 图像表示伴随着一个自定义提示,告诉 LLM 充当印度菜专家,以便准确描述上传的图像。在使用 LLM 时,清晰的提示构建对于产生预期的结果至关重要。

从函数返回图像的简短描述,然后可以将该描述传递给函数以生成要存储在数据库中的向量表示。generate_embedding

# llm_interface.py

# Function to generate embeddings for a given text

def generate_embedding(text):

   if LLM_ECOSYSTEM == 'ollama':

       embedding = ollama.embeddings(model=LLM_EMBEDDING_MODEL, prompt=text)

       return embedding['embedding']

   elif LLM_ECOSYSTEM == 'openai':

       response = client.embeddings.create(model=LLM_EMBEDDING_MODEL, input=text)

       embedding = response.data[0].embedding

       return embedding

   else:

       return "No Model Provided"

该函数依赖于 AI 生态系统中一类不同的模型,这些模型从文本生成向量嵌入。这些模型也可以通过 Ollama 和 OpenAI 轻松获得,分别返回 768 和 1536 维度。generate_embedding

通过生成从 LLM 返回的每个图像描述的嵌入(以及选择性地通过表单输入提供其他文本),API 端点可以使用 pgvector 中的余弦距离进行查询,以提供准确的结果。


cursor.execute("SELECT id, name, description, instructions, image_url FROM recipes ORDER BY embeddings <=> %s::vector  LIMIT 10", (embedding,))

results = cursor.fetchall()

通过连接 UI 并通过图像和简短的文本描述进行搜索,应用程序可以利用 pgvector 对数据集执行相似性搜索。

分布式 SQL 在 AI 应用中的应用案例
让我们来探讨一下如何利用分布式 SQL 来使我们的应用程序更具可扩展性和弹性。

以下是使用 pgvector 的 AI 应用程序受益于分布式 PostgreSQL 数据库的一些关键原因:

嵌入会消耗大量的存储和内存。具有 1536 个维度的 OpenAI 模型占用 ~57GB 的空间,用于 1000 万条记录。水平缩放提供了存储向量所需的空间。
向量相似性搜索是非常耗费计算量的。通过横向扩展到多个节点,应用程序可以访问未绑定的 CPU 和 GPU 限制。
避免服务中断。该数据库对节点、数据中心和区域性中断具有弹性,因此 AI 应用程序永远不会因数据库层而停机。
YugabyteDB 是一个基于 PostgreSQL 构建的分布式 SQL 数据库,与 Postgres 在功能和运行时兼容。它允许您重用为 Postgres 标准版本创建的库、驱动程序、工具和框架。YugabyteDB 具有 pgvector 兼容性,并提供原生 PostgreSQL 中的所有功能。这使其成为那些希望提升其 AI 应用程序水平的人的理想选择。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
1天前
|
人工智能 API
MMedAgent:专为医疗领域设计的多模态 AI 智能体,支持医学影像处理、报告生成等多种医疗任务
MMedAgent 是专为医疗领域设计的多模态AI智能体,支持多种医疗任务,包括医学影像处理、报告生成等,性能优于现有开源方法。
36 19
MMedAgent:专为医疗领域设计的多模态 AI 智能体,支持医学影像处理、报告生成等多种医疗任务
|
1天前
|
人工智能 自然语言处理 开发工具
Languine:专为开发者设计的 AI 多语言翻译工具,快速生成100+种语言的准确翻译,简化应用程序的 i18n 国际化配置
Languine 是一款面向开发者的 AI 翻译工具,支持 100+ 种语言,自动化翻译流程,提升多语言应用开发效率。
26 15
Languine:专为开发者设计的 AI 多语言翻译工具,快速生成100+种语言的准确翻译,简化应用程序的 i18n 国际化配置
|
5天前
|
数据采集 人工智能 运维
从企业级 RAG 到 AI Assistant,阿里云Elasticsearch AI 搜索技术实践
本文介绍了阿里云 Elasticsearch 推出的创新型 AI 搜索方案
从企业级 RAG 到 AI Assistant,阿里云Elasticsearch AI 搜索技术实践
|
7天前
|
人工智能 自然语言处理 测试技术
DeepSeek V3:DeepSeek 开源的最新多模态 AI 模型,编程能力超越Claude,生成速度提升至 60 TPS
DeepSeek V3 是深度求索公司开源的最新 AI 模型,采用混合专家架构,具备强大的编程和多语言处理能力,性能超越多个竞争对手。
161 4
DeepSeek V3:DeepSeek 开源的最新多模态 AI 模型,编程能力超越Claude,生成速度提升至 60 TPS
|
24天前
|
机器学习/深度学习 人工智能 自然语言处理
Gemini 2.0:谷歌推出的原生多模态输入输出 + Agent 为核心的 AI 模型
谷歌最新推出的Gemini 2.0是一款原生多模态输入输出的AI模型,以Agent技术为核心,支持多种数据类型的输入与输出,具备强大的性能和多语言音频输出能力。本文将详细介绍Gemini 2.0的主要功能、技术原理及其在多个领域的应用场景。
134 20
Gemini 2.0:谷歌推出的原生多模态输入输出 + Agent 为核心的 AI 模型
|
24天前
|
人工智能 API 语音技术
TEN Agent:开源的实时多模态 AI 代理框架,支持语音、文本和图像的实时通信交互
TEN Agent 是一个开源的实时多模态 AI 代理框架,集成了 OpenAI Realtime API 和 RTC 技术,支持语音、文本和图像的多模态交互,具备实时通信、模块化设计和多语言支持等功能,适用于智能客服、实时语音助手等多种场景。
132 15
TEN Agent:开源的实时多模态 AI 代理框架,支持语音、文本和图像的实时通信交互
|
3天前
|
人工智能 关系型数据库 分布式数据库
PolarDB-PG AI最佳实践3 :PolarDB AI多模态相似性搜索最佳实践
本文介绍了如何利用PolarDB结合多模态大模型(如CLIP)实现数据库内的多模态数据分析和查询。通过POLAR_AI插件,可以直接在数据库中调用AI模型服务,无需移动数据或额外的工具,简化了多模态数据的处理流程。具体应用场景包括图像识别与分类、图像到文本检索和基于文本的图像检索。文章详细说明了技术实现、配置建议、实战步骤及多模态检索示例,展示了如何在PolarDB中创建模型、生成embedding并进行相似性检索
|
17天前
|
机器学习/深度学习 人工智能 运维
阿里云技术公开课直播预告:基于阿里云 Elasticsearch 构建 AI 搜索和可观测 Chatbot
阿里云技术公开课预告:Elastic和阿里云搜索技术专家将深入解读阿里云Elasticsearch Enterprise版的AI功能及其在实际应用。
117 2
阿里云技术公开课直播预告:基于阿里云 Elasticsearch 构建 AI 搜索和可观测 Chatbot
|
25天前
|
人工智能 自然语言处理 前端开发
Director:构建视频智能体的 AI 框架,用自然语言执行搜索、编辑、合成和生成等复杂视频任务
Director 是一个构建视频智能体的 AI 框架,用户可以通过自然语言命令执行复杂的视频任务,如搜索、编辑、合成和生成视频内容。该框架基于 VideoDB 的“视频即数据”基础设施,集成了多个预构建的视频代理和 AI API,支持高度定制化,适用于开发者和创作者。
85 9
Director:构建视频智能体的 AI 框架,用自然语言执行搜索、编辑、合成和生成等复杂视频任务
|
24天前
|
数据采集 人工智能 编解码
书生·万象InternVL 2.5:上海 AI Lab 开源的多模态大语言模型,超越了目前许多商业模型
书生·万象InternVL 2.5是由上海AI实验室OpenGVLab团队推出的开源多模态大语言模型系列。该模型在多模态理解基准(MMMU)上表现优异,超越了许多商业模型,适用于图像和视频分析、视觉问答、文档理解和多语言处理等多个领域。
76 7
书生·万象InternVL 2.5:上海 AI Lab 开源的多模态大语言模型,超越了目前许多商业模型