官方文档地址: https://docs.spring.io/spring-ai/reference/index.html
Spring AI 可以方便 Java 开发者在代码中集成 AI 的功能,通过 Spring 提供的抽象,可以方便的切换不同的AI提供商,Spring AI 是对 AI 的使用,并不涉及 AI 的训练。
特别注意: Spring AI 目前还很不稳定,官方文档还有大量错误,API 也会变动导致不兼容,当前文章示例使用的 0.8.1 版本。
创建初始项目
可以通过 https://start.spring.io/ 创建一个包含 Spring AI 的初始项目:
上图所示,我们添加最常见的 OpenAI 依赖,Spring AI 主要添加了下面的 BOM:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>0.8.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
还有我们选择的 OpenAI:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
示例代码
为了更清楚的了解 Spring AI,本文使用更底层的代码来演示 Spring AI 的功能。
由于可能无法直接访问 OpenAI,在Java中进行调用时,可以通过下面的方式设置代理:
System.setProperty("https.proxyHost", "localhost");
System.setProperty("https.proxyPort", "7890");
除了上面方式外,如果你部署过 ChatGPT-Next-Web ,还可以通过间接的方式调用 OpenAI,可以使用类似下面形式的URL和TOKEN:
- URL:
https://你的域名/api/openai/
- TOKEN:
nk-你的CODE
我们可以通过下面的方式创建 OpenAiApi:
var openAiApi = new OpenAiApi("token");
//为了避免泄漏token,还可以配置环境变量后使用下面方式
//注意使用IDEA时,配置环境变量后需要完全关闭IDEA重启才能生效
var openAiApi = new OpenAiApi(System.getenv("OPENAI_API_KEY"));
如果使用 ChatGPT-Next-Web 代理的接口,可以使用带有 baseUrl
构造参数的方法。
var openAiApi = new OpenAiApi("https://你的域名/api/openai/", "nk-你的CODE");
//为了避免泄漏token,还可以配置环境变量后使用下面方式
//注意使用IDEA时,配置环境变量后需要完全关闭IDEA重启才能生效
var openAiApi = new OpenAiApi(
System.getenv("OPENAI_BASE_URL"),
System.getenv("OPENAI_API_KEY"));
上面代码使用了具体的 OpenAiApi,这一层是具体的实现,一般通过 starter 的配置来动态创建,接下来是更通用的 ChatClient
接口(这里特地指定了类型,没有使用 var
):
ChatClient chatClient = new OpenAiChatClient(openAiApi, OpenAiChatOptions.builder()
.withModel("gpt-3.5-turbo")
.withTemperature(0.4F)
.withMaxTokens(200)
.withFunctionCallbacks(List.of(
FunctionCallbackWrapper.builder(new MockWeatherService())
.withName("CurrentWeather")
.withDescription("Get the weather in location").build()
))
.build());
在上面的客户端中指定了 openAiApi,指定了模型名和其他参数,还特地增加了一个函数回调,增加了一个函数 CurrentWeather
,通过这个函数提供的实现 MockWeatherService
可以让 ChatGPT 拥有获取实时温度的功能,这里只是演示,所以没有对接真实的 API,直接返回的随机数:
public static class MockWeatherService
implements Function<MockWeatherService.Request, MockWeatherService.Response> {
public enum Unit { C, F }
public record Request(String location, Unit unit) {}
public record Response(double temp, Unit unit) {}
public Response apply(Request request) {
return new Response(Math.random() * 40, Unit.C);
}
}
ChatClient
最简单的接口是 default String call(String message)
方法,输入提示词返回结果,我们这里为了演示函数功能,使用复杂的接口方法 ChatResponse call(Prompt prompt)
:
ChatResponse response = chatClient.call(
new Prompt("北京、石家庄的天气怎么样,适合穿什么衣服?温度保留1位小数。",
OpenAiChatOptions.builder().withFunction("CurrentWeather").build()));
System.out.println(response.getResult().getOutput().getContent());
目前使用的 Function
功能只有 OpenAI 支持,这里只能使用 OpenAiChatOptions
指定要使用什么函数,这里要注意,前面定义的时候是在注册函数,在提示词中需要指定要使用的函数,如果不指定函数就不会生效。上面示例执行的结果如下:
北京目前气温为28.8°C,石家庄目前气温为11.8°C。
根据当前天气情况,建议穿着清凉舒适的夏季衣服在北京,而在石家庄则建议穿着春秋过渡季节的衣服。
目前的 Spring AI 还不适合用于生产,接口变化比较大,而且提供者无关的抽象还不够完善,官方文档中示例代码落后,有很多都无法执行。希望 Spring AI 越来越强大,成为 Java 开发中的 LangChain 和 LlamaIndex。