译者 | 李睿
审校 | 重楼
PostgreSQL拥有丰富的扩展和解决方案生态系统,使开发人员能够将数据库用于通用人工智能应用程序。这一指南将引导他们完成使用PostgreSQL作为矢量数据库构建生成式人工智能应用程序所需的步骤。
首先从Pgvector扩展开始,它使Postgres具有特定于矢量数据库的功能。然后,将回顾在PostgreSQL上运行的人工智能应用程序如何提高性能和可扩展性的方法。最后,将使用一个功能齐全的生成式人工智能应用程序,向那些前往旧金山的旅客推荐Airbnb的住宿房源。
示例应用程序是一项住宿推荐服务。想象一下,如果旅客计划去旧金山旅游,并希望住在金门大桥附近的一个靠谱社区。当他们进入Airbnb推荐服务,输入提示,应用程序就会推荐三个最相关的住宿选择。
该应用程序支持两种不同的模式:
OpenAI聊天模式:在这一模式下,Node.js后端利用OpenAI聊天通过API和GPT-4模型根据用户的输入生成住宿推荐。虽然这一模式不是本指南的重点,但可以进行尝试。
Postgres嵌入模式:最初,后端使用OpenAI嵌入API将用户的提示转换为嵌入(文本数据的矢量化表示)。接下来,该应用程序在Postgres或YugabyteDB(分布式PostgreSQL)中进行相似性搜索,以找到与用户提示匹配的Airbnb属性。Postgres利用Pgvector扩展在数据库中进行相似性搜索。本指南将深入研究这个特定模式在应用程序中的实现。
可访问嵌入模型的OpenAI订阅。
最新的Node.js版本
最新版本的Docker
Pgvector扩展将向量数据库的所有基本功能添加到Postgres中。它允许存储和处理具有数千个维度的向量,计算向量化数据之间的欧几里得和余弦距离,并执行精确和近似的最近邻搜索。
1.在Docker中用Pgvector启动一个Postgres实例:
Shell docker run --name postgresql \ -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=password \ -p 5432:5432 \ -d ankane/pgvector:latest
2.连接到数据库容器并打开一个psql会话:
Shell docker exec -it postgresql psql -h 127.0.0.1 -p 5432 -U postgres
3.启用Pgvector扩展:
SQL create extension vector;
4.确认矢量存在于扩展列表中:SQL
1 select * from pg_extension; oid | extname | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition -------+---------+----------+--------------+----------------+------------+-----------+-------------- 13561 | plpgsql | 10 | 11 | f | 1.0 | | 16388 | vector | 10 | 2200 | t | 0.5.1 | | (2 rows)
该应用程序使用了Airbnb的数据集,该数据集包含旧金山7500多处待租房产。每个列表提供详细的属性描述,包括房间数量、设施类型、位置和其他功能。这些信息非常适合针对用户提示进行相似性搜索。
按照下面的步骤将数据集加载到已启动的Postgres实例中:
1.克隆应用程序存储库:
Shell git clone https://github.com/YugabyteDB-Samples/openai-pgvector-lodging-service.git
2.将Airbnb模式文件复制到Postgres容器中(将{app_dir}替换为应用程序目录的完整路径):
Shell docker cp {app_dir}/sql/airbnb_listings.sql postgresql:/home/airbnb_listings.sql
3.从下面的Google Drive位置下载包含Airbnb数据的文件。该文件的大小为174MB,包含了使用OpenAI嵌入模型为每个Airbnb属性描述生成的嵌入。
4.将数据集复制到Postgres容器(将{data_file_dir}替换为应用程序目录的完整路径)。
Shell docker cp {data_file_dir}/airbnb_listings_with_embeddings.csv postgresql:/home/airbnb_listings_with_embeddings.csv
5.创建Airbnb架构并将数据加载到数据库中:
Shell # Create schema docker exec -it postgresql \ psql -h 127.0.0.1 -p 5432 -U postgres \ -a -q -f /home/airbnb_listings.sql # Load data docker exec -it postgresql \ psql -h 127.0.0.1 -p 5432 -U postgres \ -c "\copy airbnb_listing from /home/airbnb_listings_with_embeddings.csv with DELIMITER '^' CSV;"
Airbnb的每个嵌入都是一个1536维的浮点数数组。这是Airbnb房产描述的数字/数学表示。
Shell docker exec -it postgresql \ psql -h 127.0.0.1 -p 5432 -U postgres \ -c "\x on" \ -c "select name, description, description_embedding from airbnb_listing limit 1" # Truncated output name | Monthly Piravte Room-Shared Bath near Downtown !3 description | In the center of the city in a very vibrant neighborhood. Great access to other parts of the city with all modes of public transportation steps away Like the general theme of San Francisco, our neighborhood is a melting pot of different people with different lifestyles ranging from homeless people to CEO''s description_embedding | [0.0064848186,-0.0030366974,-0.015895316,-0.015803888,-0.02674906,-0.0083198985,-0.0063770646,0.010318241,-0.011003947,-0.037981577,-0.008783566,-0.0005710134,-0.0028015983,-0.011519859,-0.02011404,-0.02023159,0.03325347,-0.017488765,-0.014902675,-0.006527267,-0.027820067,0.010076611,-0.019069154,-0.03239144,-0.013243919,0.02170749,0.011421901,-0.0044701495,-0.0005861153,-0.0064978795,-0.0006775427,-0.018951604,-0.027689457,-0.00033081227,0.0034317947,0.0098349815,0.0034775084,-0.016835712,-0.0013787586,-0.0041632145,-0.0058219694,-0.020584237,-0.007386032,0.012486378,0.012473317,0.005815439,-0.010990886,-0.015111651,-0.023366245,0.019069154,0.017828353,0.030249426,-0.04315376,-0.01790672,0.0047444315,-0.0053419755,-0.02195565,-0.0057338076,-0.02576948,-0.009769676,-0.016914079,-0.0035232222,...
嵌入是用OpenAI的text- embeddings -ada-002模型生成的。如果需要使用不同的模型,那么:
更新{app_dir}/backend/embeddings_generator.js和{app_dir}/backend/postgres_embeddings_service.jsfile中的模型
通过node embeddings_generator.js命令启动生成器来重新生成嵌入。
至此,Postgres已经准备好向用户推荐最相关的Airbnb住宿房源。该应用程序可以通过比较用户的提示嵌入与Airbnb描述的嵌入来获得这些推荐。
首先,启动Airbnb推荐服务的一个实例:
1.使用OpenAI API密钥更新{app_dir}/application.properties.ini:
Shell 1 OPENAI_API_KEY=<your key>
2.启动Node.js后端:
Shell cd {app_dir} npm i cd backend npm start
3.启动React前端:
Shell cd {app_dir}/frontend npm i npm start
应用程序用户界面(UI)应在默认浏览器中自动打开。否则,请在地址打开http://localhost:300 。
现在,从应用程序用户界面(UI)中选择Postgres Embeddings模式,并要求应用程序推荐一些与以下提示最相关的Airbnb住宿房源:
Shell I'm looking for an apartment near the Golden Gate Bridge with a nice view of the Bay.
该服务将推荐三种住宿选择:
在内部,应用程序执行以下步骤来生成推荐(详细信息请参见{app_dir}/backend/postgres_embeddings_service.js):
1.应用程序使用OpenAI Embeddings模型(text- Embeddings -ada-002)生成用户提示的矢量化表示:
JavaScript const embeddingResp = await this.#openai.embeddings.create( {model: "text-embedding-ada-002", input: prompt});
2.该应用程序使用生成的向量来检索存储在Postgres中的最相关的Airbnb属性:
JavaScript const res = await this.#client.query( "SELECT name, description, price, 1 - (description_embedding <=> $1) as similarity " + "FROM airbnb_listing WHERE 1 - (description_embedding <=> $1) > $2 ORDER BY description_embedding <=> $1 LIMIT $3", ['[' + embeddingResp.data[0].embedding + ']', matchThreshold, matchCnt]);
相似度计算为存储在description_embedding列中的嵌入与用户提示向量之间的余弦距离。
3.建议的Airbnb属性以JSON格式返回到React前端:
JavaScript let places = []; for (let i = 0; i < res.rows.length; i++) { const row = res.rows[i]; places.push({ "name": row.name, "description": row.description, "price": row.price, "similarity": row.similarity }); } return places;
目前,Postgres存储了超过7500处Airbnb住宅房源。通过比较用户提示和Airbnb描述的嵌入,数据库执行精确的最近邻搜索只需要几毫秒的时间。
然而,精确的最近邻搜索(全表扫描)有其局限性。随着数据集的增长,Postgres在多维向量上执行相似性搜索将花费更长的时间。
为了在不断增长的数据量和流量中保持Postgres的性能和可扩展性,可以为向量化数据使用专门的索引和/或使用分布式版本的Postgres水平扩展存储和计算资源。
Pgvector扩展支持多种索引类型,包括性能最好的HNSW索引(Hierarchical Navigable Small World)。该索引对向量化数据执行近似最近邻搜索(ANN),允许数据库即使使用大数据量也能保持低且可预测的延迟。然而,由于搜索是近似的,搜索的召回可能不是100%相关/准确的,因为索引只遍历数据的一个子集。
例如,以下是如何在Postgres中为Airbnb嵌入创建HNSW索引:
SQL CREATE INDEX ON airbnb_listing USING hnsw (description_embedding vector_cosine_ops) WITH (m = 4, ef_construction = 10);
要想更深入地了解HNSW指数是如何构建的,以及如何在Airbnb数据上执行人工神经网络搜索,请查看以下视频:
使用分布式PostgreSQL,当单个数据库服务器的容量不再足够时,可以轻松地扩展数据库存储和计算资源。虽然PostgreSQL最初是为单服务器部署而设计的,但它的生态系统包含了一些扩展和解决方案,使它能够在分布式配置中运行。其中一个解决方案是YugabyteDB,它是一个分布式SQL数据库,扩展了Postgres在分布式环境中的功能。
YugabyteDB自2.19.2版本起支持Pgvector扩展。它将数据和嵌入分布在一组节点上,促进了大规模的相似性搜索。因此,如果希望Airbnb服务在Postgres的分布式版本上运行:
1.部署一个多节点YugabyteDB集群。
2.更新{app_dir}/application.properties.ini文件中的数据库连接设置:
Properties files # Configuration for a locally running YugabyteDB instance with defaults. DATABASE_HOST=localhost DATABASE_PORT=5433 DATABASE_NAME=yugabyte DATABASE_USER=yugabyte DATABASE_PASSWORD=yugabyte
3.从头加载数据(或者使用YugabyteDB Voyager从正在运行的Postgres实例中迁移数据)并重新启动应用程序。不需要其他代码级别的更改,因为YugabyteDB与Postgres具有功能和运行时兼容性。
观看以下的视频,了解Airbnb推荐服务如何在分布式Postgres版本上运行:
使用Postgres构建可扩展的人工智能应用程序很有趣,人们可以了解更多关于Postgres作为矢量数据库的知识。
原文标题:PostgreSQL as a Vector Database: Getting Started and Scaling,作者:Denis Magda