人工智能训练是资源密集型的。要教会一个模型如何理解语言、图像或音频,需要大量的数据集、先进的算法和专用硬件(如:昂贵的 GPU)。但即使在训练完成后,运行推理(生成输出的过程)也同样耗费大量资源。
为每个用户请求实时查询 LLM 不仅昂贵,而且效率低下。尤其是在答案可能已经存在的情况下。为了解决这一难题,开发团队转向了矢量数据库。
与依赖精确关键词匹配的传统数据库不同,矢量数据库将信息存储为高维嵌入,如文本、图像或声音等数据的数字表示。这使得执行语义搜索成为可能。因此,您要寻找的不是精确的词语,而是意义。
这种区别在以下使用案例中至关重要:
- 检索增强生成(RAG)
- 推荐引擎
- 答疑系统
- 语义搜索
有了向量数据库,当答案已经存在于向量索引中时,人工智能系统就可以跳过不必要的推理调用,从而更快、更高效地检索相关信息。有许多不同的向量数据库解决方案,但今天我将谈谈pgvector,这是一个开源的 PostgreSQL 扩展,我个人使用并推荐使用它。我们将详细介绍为什么我认为它是如此出色的工具,以及如何开始使用它。
为什么说 pgvector 是开发人员的绝佳工具?
首先,pgvector 将矢量搜索功能直接集成到 PostgreSQL 中,PostgreSQL 是世界上应用最广泛的关系数据库之一。对于已经在基于 PostgreSQL 的环境中工作的开发人员和团队来说,这为构建智能应用程序提供了一个无缝、低摩擦的选择。
pgvector 允许团队在一个地方存储和查询关系数据和矢量数据,而不是引入一个新的、单独的堆栈进行管理。这种统一消除了同步不同数据库的复杂性,使开发生命周期更加简单。pgvector 本机支持这种混合搜索模式,允许开发人员将矢量相似性评分与基于 SQL 的筛选器和连接相结合。这样,您不仅可以通过关键词搜索文档语料库,还可以通过语义进行搜索,同时在单个 SQL 查询中应用文档类别或用户权限等过滤器。
pgvector 专为现实世界的可扩展性和性能而设计。对于需要快速提供数百万嵌入结果的应用,pgvector 通过 IVFFlat 索引方法支持近似近邻(ANN)搜索。这使得对延迟敏感的应用(如人工智能驱动的搜索栏或推荐系统)能够快速响应,同时在准确性和速度之间保持良好的平衡。对于使用Python 开发的团队来说,pgvector 可以与流行的 PostgreSQL 客户端库(如psycopg2、asyncpg 和SQLAlchemy)顺利集成,使其可以轻松地插入到现有的数据管道和 ML 工作流中。
事实证明,pgvector 的多功能性在各行各业都很有价值。我们看到电子商务企业使用它来提供个性化推荐,以提高转化率。大型媒体平台利用它来展示相关内容,让用户保持参与。医疗保健和生命科学团队依靠它来加快研究、化合物发现和诊断洞察。在许多科技公司,它实现了由 LLM 驱动的支持和更智能的内部工具。
将pgvector部署在Akamai云这样的平台上,可以使其功能更加强大。Akamai的云解决方案为团队提供了生产级工作负载所需的托管基础架构、可扩展性和全球性能优势。Akamai上的托管PostgreSQL允许开发人员部署pgvector支持的应用程序,而无需担心运营开销。通过自动备份、内置安全性和自动扩展选项,您的堆栈可以保持弹性,而您的团队则可以专注于建设。此外,由于Akamai的计算和网络基础架构针对全球分发进行了优化,因此依赖于快速推理或实时推荐引擎的应用程序可以从更低的延迟和更高的可靠性中获益。
如果你已经在使用 PostgreSQL,或者正在寻找一个无需彻底改造堆栈就能使用的人工智能矢量搜索引擎,我将在下一节介绍如何开始使用 pgvector。
在 Akamai 上开始使用 pgvector
- 使用Akamai的数据库管理控制面板配置PostgreSQL集群。
- 登录云管理器。
- 从主菜单中选择数据库。
- 单击创建数据库群集。
- 在 "群组标签 "字段中,输入一个标签,以便轻松识别账户中的群组。标签必须是字母数字,字符数在 3 到 32 之间。
- 为新数据库选择数据库引擎。
- 选择数据库群集所在的区域。
- 数据库群集的每个节点都建立在自己的 Linode 上。在 "选择计划 "部分,选择节点将使用的 Linode 类型和计划。
- 点击 创建数据库群集.完全配置群集大约需要 10 到 15 分钟。您可以通过查看 现状 列。
注:您也可以使用应用程序接口进行配置
- 登录群集
要从命令行直接连接数据库,可以使用 psql 工具。大多数 PostgreSQL 服务器的安装都包含这个工具,不过在大多数操作系统上也可以单独安装。
使用下面的 psql 命令连接数据库,替换为[host]
和[username]
中的相应值。psql --host=[host] --username=[username] --password --dbname=postgres
- 安装扩展
要在数据库中安装一个可用扩展,请使用 CREATE EXTENSION 命令,将 [extension_name] 替换为要安装的扩展名称。在本例中,扩展名为vector
.CREATE EXTENSION vector;
- 定义向量列
安装向量扩展后,你就可以访问一种名为向量的新数据类型。向量的大小(用括号表示)代表存储在该向量中的维数。在本例中,我们将使用 13 维,但在实际用例中,它将达到数千维。CREATE TABLE items ( id serial PRIMARY KEY, description text, embedding vector(13) );
- 插入 ML 模型的嵌入(如 OpenAI 的 或 拥抱的脸).要收集嵌入样本,可以使用下面的Python 脚本,该脚本改编自 Hugging Face 演示。您需要获得一个 "拥抱的脸 "标记才能使用此示例。
import requests
import psycopg2
import os
# Hugging Face Configuration
model_id = "sentence-transformers/all-MiniLM-L6-v2"
hf_token = os.environ.get("HF_TOKEN") # Set an environmental variable called HF_TOKEN with your Hugging Face token
api_url = f"https://router.huggingface.co/hf-inference/models/{model_id}"
headers = {"Authorization": f"Bearer {hf_token}"}
# Database Configuration
db_conn_string = os.environ.get("DB_CONN_STRING") # Replace with your connection string or set an env var
# Source for Embeddings
source_sentence = "How do I get Medicare?"
sentences = [
"How do I get a replacement Medicare card?",
"What is the monthly premium for Medicare Part B?",
"How do I terminate my Medicare Part B (medical insurance)?",
"How do I sign up for Medicare?",
"Can I sign up for Medicare Part B if I am working and have health insurance through an employer?",
"How do I sign up for Medicare Part B if I already have Part A?",
"What are Medicare late enrollment penalties?",
"What is Medicare and who can get it?",
"How can I get help with my Medicare Part A and Part B premiums?",
"What are the different parts of Medicare?",
"Will my Medicare premiums be higher because of my higher income?",
"What is TRICARE ?",
"Should I sign up for Medicare Part B if I have Veterans' Benefits?"
]
# Hugging Face API Query Function
def get_embeddings(source_sentence, sentences):
"""Queries the Hugging Face API to get sentence embeddings."""
try:
response = requests.post(
Api_url,
headers=headers,
json={"inputs": { "source_sentence": source_sentence, "sentences": sentences }, "options": {"wait_for_model": True}}
)
response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error querying Hugging Face API: {e}")
return None
# Main Execution
print("Fetching embeddings from Hugging Face...")
embeddings = get_embeddings(source_sentence, sentences)
if embeddings:
print(f"Successfully fetched {len(embeddings)} embeddings.")
conn = None
Try:
# Establish connection to the database
print("Connecting to the PostgreSQL database...")
conn = psycopg2.connect(db_conn_string)
cur = conn.cursor()
print("Connection successful.")
# Insert descriptions and embeddings into the database
print("Inserting data into the 'items' table...")
for description, embedding in zip(sentences, embeddings):
# The pgvector extension expects the vector as a string representation of a list
cur.execute(
"INSERT INTO items (description, embedding) VALUES (%s, %s)",
(description, embeddings)
)
# Commit the transaction to make the changes permanent
conn.commit()
print(f"Successfully inserted {cur.rowcount} records into the database.")
except psycopg2.Error as e:
print(f"Database error: {e}")
if conn:
conn.rollback() # Rollback the transaction on error
Finally:
# Ensure the connection is closed
if conn:
cur.close()
conn.close()
print("Database connection closed.") - 使用 pgvector 的索引和搜索功能
Create the index after the table has some data
CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops);
SELECT *, embedding <-> query_embedding AS similarity FROM items ORDER BY similarity LIMIT 5;
矢量数据库正在帮助团队优化性能、降低推理成本,并提供更智能、更快速的用户体验,而像pgvector这样的扩展功能则可以更轻松地将语义搜索和混合查询引入 PostgreSQL 等熟悉的环境中,而无需彻底改造架构。
注释