最近听说全世界最好用的 Spring 生态出了一款新框架 Spring AI,这太好了啊,以前我简单尝试过 Maven 仓库中别人封装的 open ai 接口jar包,给我的感觉就是杂乱,不规范,而且学习文档写的并不好。好啦,废话不多说,让我们直接开始第一次 Spring AI 的尝试。

1 简介

官网的介绍如下:

Spring AI is an application framework for AI engineering. Its goal is to apply to the AI domain Spring ecosystem design principles such as portability and modular design and promote using POJOs as the building blocks of an application to the AI domain.

大体意思是说,希望将 Spring 的思想应用于 AI 领域(比如可移植性与模块化),并且希望推广 POJO 作为一个构建块推广到 AI。

让我们看看现在支持的大模型有哪些:

  • 聊天模型

    • OpenAI

    • Azure Open AI

    • Amazon Bedrock

      • Cohere's Command

      • AI21 Labs' Jurassic-2

      • Meta's LLama 2

      • Amazon's Titan

    • Google Vertex AI Palm

    • Google Gemini

    • HuggingFace - access thousands of models, including those from Meta such as Llama2

    • Ollama - run AI models on your local machine

    • MistralAI

  • 文本到图像模型

    • OpenAI with DALL-E

    • StabilityAI

  • 音频到文本模型

    • OpenAI

  • 嵌入模型

    • OpenAI

    • Azure OpenAI

    • Ollama

    • ONNX

    • PostgresML

    • Bedrock Cohere

    • Bedrock Titan

    • Google VertexAI

    • Mistal AI

    以上就是官网对于该框架的基本介绍

2 快速开始

官网提供了两种快速开始,一种是基于 Spring CLI ,另一种就是我们通常使用的 Spring Initializr

我们这里使用第二种方式构建,并且使用 Maven 构建工具,如果你使用的是 Gradle 请访问 入门:: Spring AI参考 --- Getting Started :: Spring AI Reference

  1. 创建项目,选择 JDK 17

    并选择 基础的 Lombok和 javaweb 依赖。

  2. 在 POM 文件中添加如下仓库:

       <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>
  3. 添加一个依赖管理器,保证版本正确

     <dependencyManagement>
         <dependencies>
             <dependency>
                 <groupId>org.springframework.ai</groupId>
                 <artifactId>spring-ai-bom</artifactId>
                 <version>0.8.1-SNAPSHOT</version>
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
         </dependencies>
     </dependencyManagement>
  4. 之后针对我们想要使用的模型,添加对应的依赖,我这里使用 openai 的聊天模型。

     <dependency>
         <groupId>org.springframework.ai</groupId>
         <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
     </dependency>
  5. 之后去properties文件中写api

    这个api自己想办法弄嗷,注册账号很麻烦,建议直接淘宝买。

  6. 来一个测试controller

     package org.arden.springaihellowordarden.controller;
     ​
     import jakarta.annotation.Resource;
     import org.springframework.ai.chat.ChatClient;
     import org.springframework.web.bind.annotation.PathVariable;
     import org.springframework.web.bind.annotation.RequestMapping;
     import org.springframework.web.bind.annotation.RestController;
     ​
     /**
      * 测试controller
      * 只用最简单的对话
      */
     @RestController
     @RequestMapping("test")
     public class TestController {
     ​
         @Resource
         private ChatClient chatClient;
     ​
         @RequestMapping("{text}")
         public String hello(@PathVariable(name = "text") String text){
             return chatClient.call(text);
         }
     }

    text就是你发出的消息,但是如果你在国内,你会发现一个问题

    org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://api.openai.com/v1/chat/completions": Connection timed out: connect

    所以我们需要自己电脑上安装一个梯子,并且提供代理端口,我这里使用Winxray,在设置中查询到 http 代理端口是 1082。

    接着去设置代理,在启动类添加代理信息:

     public static void main(String[] args) {
             System.setProperty("http.proxyHost", "127.0.0.1");
             System.setProperty("http.proxyPort", "1082");
             System.setProperty("https.proxyHost", "127.0.0.1");
             System.setProperty("https.proxyPort", "1082");
             SpringApplication.run(SpringAiHellowordArdenApplication.class, args);
         }

    这个写法不是很优雅啊感觉,以后可以优化。

    之后再去访问

成功!

这个是一个非常简单的开始,这并不能体现 gpt 的精髓,后续我会写一些进阶的操作,比如上下文一类。