当前位置:Java -> 使用Spring AI和PostgreSQL PGVector入门

使用Spring AI和PostgreSQL PGVector入门

Spring AI 是 Spring 生态系统的一个新项目,它简化了在Java中创建AI应用程序的过程。通过将Spring AI与PostgreSQL pgvector一起使用,您可以构建生成AI应用程序,从中获取数据洞察。

首先,本文将为您介绍使用OpenAI GPT-4模型生成用户提示推荐的Spring AI ChatClient。接下来,文章将展示如何使用Spring AI EmbeddingClient和Spring JdbcClient,部署 PostgreSQL 以及执行向量相似性搜索。

添加Spring AI依赖项

Spring AI支持许多大型语言模型 (LLM) 提供商,每个LLM都有其自己的Spring AI依赖项。

假设您更喜欢使用OpenAI模型和API。那么,您需要将以下依赖项添加到项目中:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    <version>{latest.version}</version>
</dependency>


此外,在撰写本文时,Spring AI正在积极开发中,框架构件发布在Spring Milestone和/或Snapshot存储库中。因此,如果您在https://start.spring.io/上仍然找不到Spring AI,那么请将存储库添加到pom.xml文件中:

<repositories>
    <repository>
      <id>spring-milestones</id>
      <name>Spring Milestones</name>
      <url>https://repo.spring.io/milestone</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
    <repository>
      <id>spring-snapshots</id>
      <name>Spring Snapshots</name>
      <url>https://repo.spring.io/snapshot</url>
      <releases>
        <enabled>false</enabled>
      </releases>
    </repository>
</repositories>

设置OpenAI模块

OpenAI模块带有几个配置属性,允许管理连接相关设置并微调OpenAI模型的行为。

最少需要提供您的OpenAI API密钥,Spring AI将使用该密钥来访问GPT和嵌入模型。创建密钥后,请将其添加到application.properties文件中:

spring.ai.openai.api-key=sk-...


然后,如有必要,您可以选择特定的GPT和嵌入模型:

spring.ai.openai.chat.model=gpt-4
spring.ai.openai.embedding.model=text-embedding-ada-002


最后,您可以通过实现一个使用Spring AI的ChatClient的简单助手来测试OpenAI模块是否配置正确:

// Inject the ChatClient bean
@Autowired
private ChatClient aiClient;

// Create a system message for ChatGPT explaining the task
private static final SystemMessage SYSTEM_MESSAGE = new SystemMessage(
    """
    You're an assistant who helps to find lodging in San Francisco.
    Suggest three options. Send back a JSON object in the format below.
    [{\"name\": \"<hotel name>\", \"description\": \"<hotel description>\", \"price\": <hotel price>}]
    Don't add any other text to the response. Don't add the new line or any other symbols to the response. Send back the raw JSON.
    """);

public void searchPlaces(String prompt) {
    // Create a Spring AI prompt with the system message and the user message
    Prompt chatPrompt = new Prompt(List.of(SYSTEM_MESSAGE, new UserMessage(prompt)));

    // Send the prompt to ChatGPT and get the response
    ChatResponse response = aiClient.generate(chatPrompt);

    // Get the raw JSON from the response and print it
    String rawJson = response.getGenerations().get(0).getContent();

    System.out.println(rawJson);
}


为了进行实验,如果您传递"我想留在金门大桥附近" 提示,那么searchPlaces方法可能会提供住宿建议,如下所示:

[
 {"name": "Cavallo Point", "description": "Historic hotel offering refined rooms, some with views of the Golden Gate Bridge, plus a spa & dining.", "price": 450}, 
 {"name": "Argonaut Hotel", "description": "Upscale, nautical-themed hotel offering Golden Gate Bridge views, plus a seafood restaurant.", "price": 300}, 
 {"name": "Hotel Del Sol", "description": "Colorful, retro hotel with a pool, offering complimentary breakfast & an afternoon cookies reception.", "price": 200}
]

使用PGVector启动Postgres

如果您运行前面的代码片段与ChatClient,您会注意到OpenAI GPT模型通常需要超过10秒来生成响应。该模型具有广泛的深度知识库,需要时间来产生相关的响应。

除了高延迟外,GPT模型可能没有接受对您的应用工作负载相关的数据训练。因此,它可能会生成远非用户满意的响应。

然而,您可以始终加快搜索速度,并在数据的子集上生成嵌入,然后让Postgres处理这些嵌入,从而提供准确的响应给用户。

pgvector扩展允许在Postgres中存储和查询向量嵌入。使用PGVector的最简单方法是在Docker中启动带有此扩展的Postgres实例:

mkdir ~/postgres-volume/

docker run --name postgres \
    -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=password \
    -p 5432:5432 \
    -v ~/postgres-volume/:/var/lib/postgresql/data -d ankane/pgvector:latest


一旦启动,您可以连接到容器并通过执行CREATE EXTENSION向量语句启用该扩展: 

docker exec -it postgres psql -U postgres -c 'CREATE EXTENSION vector'


最后,将PostgresJDBC驱动程序依赖项添加到pom.xml文件中:

<dependency>
  <groupId>org.postgresql</groupId>
  <artifactId>postgresql</artifactId>
  <version>{latest.version}</version>
</dependency>


通过将以下设置添加到application.properties文件中,配置Spring DataSource:

spring.datasource.url = jdbc:postgresql://127.0.0.1:5432/postgres
spring.datasource.username = postgres
spring.datasource.password = password

使用Spring AI执行向量相似性搜索

最少需要两个步骤才能进行向量相似性搜索。

首先,您需要使用嵌入模型为提供的用户提示或其它文本生成一个向量/嵌入。Spring AI支持连接到OpenAI或其他提供商的嵌入模型和为文本输入生成矢量化表示的EmbeddingClient

// Inject the Spring AI Embedding client
@Autowired
private EmbeddingClient aiClient;

public List<Place> searchPlaces(String prompt) {
    // Use the Embedding client to generate a vector for the user prompt
    List<Double> promptEmbedding = aiClient.embed(prompt);
    ...
}


其次,您可以使用生成的嵌入在Postgres数据库中执行相似性搜索。例如,您可以使用Spring的JdbcClient执行此任务:

@Autowired
private JdbcClient jdbcClient;

// Inject the Spring AI Embedding client
@Autowired
private EmbeddingClient aiClient;


public List<Place> searchPlaces(String prompt) {
    // Use the Embedding client to generate a vector for the user prompt
    List<Double> promptEmbedding = aiClient.embed(prompt);

    // Perform the vector similarity search
    StatementSpec query = jdbcClient.sql(
        "SELECT name, description, price " +
        "FROM airbnb_listing WHERE 1 - (description_embedding <=> :user_promt::vector) > 0.7 " +
        "ORDER BY description_embedding <=> :user_promt::vector LIMIT 3")
        .param("user_promt", promptEmbedding.toString());

    // Return the recommended places
    return query.query(Place.class).list();
}


  • description_embedding列存储了为Airbnb列表概述预先生成的嵌入,网址:来源description列。这些Airbnb嵌入是由Spring AI的EmbeddingClient用于用户提示的相同模型产生的。
  • Postgres使用PGVector来计算Airbnb和用户提示嵌入之间的余弦距离(<=>),然后仅返回那些其描述与所提供的用户提示相似度> 0.7的Airbnb列表。相似性以0到1的范围内的值进行度量。与1的相似性越接近,向量之间的关系越相关。

接下来

Spring AI和PostgreSQL的PGVector提供了构建Java中生成式AI应用所需的所有基本功能。如果您想了解更多,请观看这个实用教程。它将指导您通过从头开始创建Java中的住宿推荐服务的过程,利用专门的索引进行相似性搜索优化,并且通过分布式Postgres(YugabyteDB)进行扩展:


推荐阅读: 32. Java的内部类

本文链接: 使用Spring AI和PostgreSQL PGVector入门