Spring AI 第二讲 之 Chat Model API 第八节Anthropic 3 Chat

Anthropic Claude 是一系列基础人工智能模型,可用于各种应用。对于开发人员和企业来说,您可以利用 API 访问,直接在 Anthropic 的人工智能基础架构之上进行构建。

Spring AI 支持用于同步和流式文本生成的 Anthropic 消息 API

Anthropic 的 Claude 模型也可通过 Amazon Bedrock 使用。Spring AI 还提供专用的 Amazon Bedrock Anthropic 客户端实现。

先决条件

您需要在 Anthropic 门户上创建一个 API 密钥。在Anthropic API 面板上创建账户,然后在 "获取 API 密钥 "页面上生成 API 密钥。Spring AI 项目定义了一个名为 spring.ai.anthropic.api-key 的配置属性,你应该将其设置为从 anthropic.com 获取的 API 密钥的值。导出环境变量是设置该配置属性的一种方法:

export SPRING_AI_ANTHROPIC_API_KEY=<INSERT KEY HERE>

添加资源库和 BOM

Spring AI 工件发布在 Spring Milestone 和 Snapshot 资源库中。请参阅 "资源库 "部分,将这些资源库添加到您的构建系统中。

为了帮助进行依赖性管理,Spring AI 提供了一个 BOM(物料清单),以确保在整个项目中使用一致的 Spring AI 版本。请参阅 "依赖关系管理 "部分,将 Spring AI BOM 添加到构建系统中。

自动配置

Spring AI 为 Anthropic Chat Client 提供 Spring Boot 自动配置功能。要启用该功能,请在项目的 Maven pom.xml 文件中添加以下依赖项:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-anthropic-spring-boot-starter</artifactId>
</dependency>

或 Gradle build.gradle 构建文件。

dependencies {
    implementation 'org.springframework.ai:spring-ai-anthropic-spring-boot-starter'
}

请参阅 "依赖关系管理 "部分,将 Spring AI BOM 添加到构建文件中。

聊天属性

重试属性

属性前缀 spring.ai.retry 用于配置 Anthropic 聊天模型的重试机制。 

Property Description Default

spring.ai.retry.max-attempts

重试的最大次数。

10

spring.ai.retry.backoff.initial-interval

指数后退策略的初始睡眠时间。

2 sec.

spring.ai.retry.backoff.multiplier

回退间隔倍增器。

5

spring.ai.retry.backoff.max-interval

最大回退持续时间。

3 min.

spring.ai.retry.on-client-errors

如果为假,则抛出 NonTransientAiException 异常,并且不尝试重试 4xx 客户端错误代码

false

spring.ai.retry.exclude-on-http-codes

不应触发重试(例如抛出 NonTransientAiException)的 HTTP 状态代码列表。

empty

spring.ai.retry.on-http-codes

应触发重试(例如抛出 TransientAiException)的 HTTP 状态代码列表。

empty

目前,重试策略不适用于流 API。 

连接属性

spring.ai.anthropic 前缀是用于连接 Anthropic 的属性前缀。 

Property Description Default

spring.ai.anthropic.base-url

要连接的 URL

api.anthropic.com

spring.ai.anthropic.version

人类应用程序接口版本

2023-06-01

spring.ai.anthropic.api-key

The API Key

-

配置属性

spring.ai.anthropic.chat 前缀是属性前缀,用于配置 Anthropic 的聊天模型实现。 

Property Description Default

spring.ai.anthropic.chat.enabled

启用人类聊天模式。

true

spring.ai.anthropic.chat.options.model

这是人类聊天模型。支持 claude-3-opus-20240229、claude-3-sonnet-20240229、claude-3-haiku-20240307 以及传统的 claude-2.1、claude-2.0 和 claude-instant-1.2 模型。

claude-3-opus-20240229

spring.ai.anthropic.chat.options.temperature

采样温度,用于控制生成的补间明显的创造性。取值越高,输出结果越随机,取值越低,结果越集中和确定。不建议针对同一个补全请求修改温度和 top_p,因为这两个设置之间的相互作用很难预测。

0.8

spring.ai.anthropic.chat.options.max-tokens

聊天完成时要生成的最大标记数。输入词组和生成词组的总长度受模型上下文长度的限制。

500

spring.ai.anthropic.chat.options.stop-sequence

将导致模型停止生成的自定义文本序列。我们的模型通常会在自然完成其回合后停止,这将导致响应 stop_reason 为 "end_turn"。如果您希望模型在遇到自定义文本字符串时停止生成,可以使用 stop_sequences 参数。如果模型遇到其中一个自定义序列,响应 stop_reason 值将是 "stop_sequence",响应 stop_sequence 值将包含匹配的停止序列。

-

spring.ai.anthropic.chat.options.top-p

使用核抽样在核采样中,我们会按概率递减的顺序计算每个后续标记的所有选项的累积分布,并在达到 top_p 指定的特定概率时将其切断。你应该改变 temperature 或 top_p,但不能同时改变这两个参数。建议仅用于高级用例。通常只需要使用 temperature。

-

spring.ai.anthropic.chat.options.top-k

只从每个后续标记的前 K 个选项中取样。用于去除 "长尾 "低概率回复。点击此处了解更多技术细节。建议仅用于高级用例。通常只需要使用温度。

-

spring.ai.mistralai.chat.options.functions

由函数名称标识的函数列表,用于在单个提示请求中启用函数调用。具有这些名称的函数必须存在于 functionCallbacks 注册表中。

-

spring.ai.mistralai.chat.options.functionCallbacks

MistralAI 工具功能回调,用于注册 ChatModel。

-

所有以 spring.ai.anthropic.chat.options 为前缀的属性都可以通过在提示调用中添加特定于请求的运行时选项在运行时重写。

运行时选项

AnthropicChatOptions.java 提供了模型配置,如要使用的模型、温度、最大标记数等。

启动时,可使用 AnthropicChatModel(api, options) 构造函数或 spring.ai.anthropic.chat.options.* 属性配置默认选项。

运行时,您可以通过在提示调用中添加新的、针对特定请求的选项来覆盖默认选项。例如,覆盖特定请求的默认模型和温度:

ChatResponse response = chatModel.call(
    new Prompt(
        "Generate the names of 5 famous pirates.",
        AnthropicChatOptions.builder()
            .withModel("claude-2.1")
            .withTemperature(0.4)
        .build()
    ));

除了模型专用的 AnthropicChatOptions外,您还可以使用通过ChatOptionsBuilder#builder() 创建的便携式 ChatOptions实例。

函数调用

您可以在 AnthropicChatModel 中注册自定义 Java 函数,让 Anthropic Claude 模型智能地选择输出包含参数的 JSON 对象,以调用一个或多个注册函数。这是一种将 LLM 功能与外部工具和 API 相连接的强大技术。了解有关人类学函数调用的更多信息。

多模式

多模态是指模型能够同时理解和处理各种来源的信息,包括文本、图像、音频和其他数据格式。这种模式代表了人工智能模型的一大进步。

目前,Anthropic Claude 3 支持 base64 图像源类型,以及图像/jpeg、图像/png、图像/gif 和图像/webp 媒体类型。更多信息,请查看视觉指南

Spring AI 的消息接口通过引入媒体类型支持多模态 AI 模型。该类型使用 Spring 的 org.springframework.util.MimeType 和用于原始媒体数据的 java.lang.Object 来包含有关消息中媒体附件的数据和信息。

下面是从 AnthropicChatModelIT.java 中提取的一个简单代码示例,演示了用户文本与图片的结合。

byte[] imageData = new ClassPathResource("/multimodal.test.png").getContentAsByteArray();

var userMessage = new UserMessage("Explain what do you see on this picture?",
        List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageData)));

ChatResponse response = chatModel.call(new Prompt(List.of(userMessage)));

logger.info(response.getResult().getOutput().getContent());

 它的输入是 multimodal.test.png 图像:

以及文本信息 "请解释一下您在这张图片上看到了什么?

图片显示的是一个铁丝水果篮的特写,里面装着几块水果。
篮子似乎是由细金属丝编织成圆形,并带有一个高高的把手。

篮子里有几根黄色的香蕉和几个红色的苹果,也可能是西红柿。
水果鲜艳的颜色与金属丝篮子的金属色调形成了鲜明的对比。

照片的景深较浅,焦点集中在前景的水果上,而向上延伸的篮子手柄则略显模糊,在背景中营造出悦目的虚化效果。

构图和光线使画面呈现出一种简洁、极简的美感,突出了这个优雅的铁丝篮中水果的自然美和新鲜感。

示例Controller

创建一个新的 Spring Boot 项目,并将 spring-ai-anthropic-spring-boot-starter 添加到你的 pom(或 gradle)依赖项中。

在 src/main/resources 目录下添加 application.properties 文件,以启用和配置 Anthropic 聊天模型:

spring.ai.anthropic.api-key=YOUR_API_KEY
spring.ai.anthropic.chat.options.model=claude-3-opus-20240229
spring.ai.anthropic.chat.options.temperature=0.7
spring.ai.anthropic.chat.options.max-tokens=450

 将 api-key 替换为您的 Anthropic 证书。

这将创建一个 AnthropicChatModel 实现,您可以将其注入到您的类中。下面是一个使用聊天模型生成文本的简单 @Controller 类的示例。

@RestController
public class ChatController {

    private final AnthropicChatModel chatModel;

    @Autowired
    public ChatController(AnthropicChatModel chatModel) {
        this.chatModel = chatModel;
    }

    @GetMapping("/ai/generate")
    public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        return Map.of("generation", chatModel.call(message));
    }

    @GetMapping("/ai/generateStream")
	public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        Prompt prompt = new Prompt(new UserMessage(message));
        return chatModel.stream(prompt);
    }
}

手动配置

AnthropicChatModel实现了 ChatModel 和 StreamingChatModel,并使用底层 AnthropicApi客户端连接到 Anthropic 服务。

在项目的 Maven pom.xml 文件中添加 Spring-ai-anthropic 依赖关系:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-anthropic</artifactId>
</dependency>

或 Gradle build.gradle 构建文件。

dependencies {
    implementation 'org.springframework.ai:spring-ai-anthropic'
}

请参阅 "依赖关系管理 "部分,将 Spring AI BOM 添加到构建文件中。
接下来,创建 AnthropicChatModel 并将其用于文本生成:

var anthropicApi = new AnthropicApi(System.getenv("ANTHROPIC_API_KEY"));

var chatModel = new AnthropicChatModel(anthropicApi,
        AnthropicChatOptions.builder()
            .withModel("claude-3-opus-20240229")
            .withTemperature(0.4)
            .withMaxTokens(200)
        .build());

ChatResponse response = chatModel.call(
    new Prompt("Generate the names of 5 famous pirates."));

// Or with streaming responses
Flux<ChatResponse> response = chatModel.stream(
    new Prompt("Generate the names of 5 famous pirates."));

AnthropicChatOptions 为聊天请求提供配置信息。AnthropicChatOptions.Builder 是流畅的选项生成器。

底层 AnthropicApi 客户端

AnthropicApiAnthropic Message API的轻量级 Java 客户端。

下面的类图说明了 AnthropicApi 聊天接口和构建模块:

下面是一个如何以编程方式使用 api 的简单片段:

 

AnthropicApi anthropicApi =
    new AnthropicApi(System.getenv("ANTHROPIC_API_KEY"));

RequestMessage chatCompletionMessage = new RequestMessage(
        List.of(new MediaContent("Tell me a Joke?")), Role.USER);

// Sync request
ResponseEntity<ChatCompletion> response = anthropicApi
    .chatCompletionEntity(new ChatCompletionRequest(AnthropicApi.ChatModel.CLAUDE_3_OPUS.getValue(),
            List.of(chatCompletionMessage), null, 100, 0.8f, false));

// Streaming request
Flux<StreamResponse> response = anthropicApi
    .chatCompletionStream(new ChatCompletionRequest(AnthropicApi.ChatModel.CLAUDE_3_OPUS.getValue(),
            List.of(chatCompletionMessage), null, 100, 0.8f, true));

更多信息请参阅 AnthropicApi.java 的 JavaDoc。

低级应用程序接口示例


AnthropicApiIT.java 测试提供了一些如何使用轻量级库的一般示例。


Anthropic 功能调用

您可以向 AnthropicChatModel 注册自定义 Java 函数,并让 Anthropic 模型智能地选择输出包含参数的 JSON 对象,以调用一个或多个已注册函数。这样,您就可以将 LLM 功能与外部工具和 API 相连接。claude-3-opus、claude-3-sonnet 和 claude-3-haiku 模型经过训练,可以检测函数何时应被调用,并根据函数签名响应 JSON。

Anthropic API 不会直接调用函数;相反,模型会生成 JSON,您可以用它在代码中调用函数,并将结果返回给模型以完成对话。

截至 2024 年 4 月 4 日,第三方平台(如 Vertex AI 或 AWS Bedrock)尚未支持流式函数调用和工具使用,但即将推出。

Spring AI 提供了灵活且用户友好的注册和调用自定义函数的方法。一般来说,自定义函数需要提供函数名称、描述和函数调用签名(作为 JSON 模式),以便让模型知道函数期望使用哪些参数。描述有助于模型了解何时调用该函数。

作为开发人员,您需要实现一个函数,接收人工智能模型发送的函数调用参数,并将结果反馈给模型。您的函数可以反过来调用其他第三方服务来提供结果。

Spring AI 可以轻松实现这一点,只需定义一个 @Bean 定义,返回 java.util.Function 并将 bean 名称作为调用 ChatModel 时的一个选项即可。

在引擎盖下,Spring 会用适当的适配器代码封装您的 POJO(函数),从而实现与 AI 模型的交互,使您无需编写繁琐的模板代码。底层基础架构的基础是 FunctionCallback.java 接口和配套的 FunctionCallbackWrapper.java 实用程序类,用于简化 Java 回调函数的实现和注册。

工作原理

假设我们想让人工智能模型响应它所不具备的信息,例如某个地点的当前温度。

我们可以为人工智能模型提供有关我们自身功能的元数据,让它在处理您的提示时可以用来检索这些信息。

例如,如果在处理提示时,人工智能模型确定它需要有关给定地点温度的额外信息,它就会启动服务器端生成的请求/响应交互。人工智能模型会调用客户端函数。人工智能模型以 JSON 格式提供方法调用详情,客户端负责执行该函数并返回响应。

Spring AI 大大简化了为支持函数调用而编写的代码。它为您提供函数调用对话的中介。您只需以 @Bean 的形式提供函数定义,然后在提示选项中提供函数的 Bean 名称即可。您还可以在提示中引用多个函数 Bean 名称。

 

快速入门


让我们创建一个聊天机器人,通过调用自己的函数来回答问题。为了支持聊天机器人的回答,我们将注册自己的函数,该函数接收一个地点并返回该地点的当前天气。

当需要回答诸如 "波士顿的天气如何?"这样的问题时,人工智能模型将调用客户端,提供位置值作为参数传递给函数。这种类似 RPC 的数据以 JSON 格式传递。

我们的函数可以使用基于 SaaS 的天气服务 API,并将天气响应返回给模型,以完成对话。在本示例中,我们将使用一个名为 MockWeatherService 的简单实现,对不同地点的温度进行硬编码。

下面的 MockWeatherService.java 表示天气服务 API:

public class MockWeatherService implements Function<Request, 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(30.0, Unit.C);
	}
}

将函数注册为 Bean

有了 AnthropicChatModel Auto-Configuration,您就有多种方法在 Spring 上下文中将自定义函数注册为 Bean。

我们首先介绍对 POJO 最友好的选项。

普通 Java 函数
在这种方法中,您可以在应用程序上下文中定义 @Beans,就像定义任何其他 Spring 托管对象一样。

在内部,Spring AI ChatModel 将创建一个 FunctionCallbackWrapper 封装器实例,该封装器将添加通过 AI 模型调用该函数的逻辑。@Bean 的名称将作为 ChatOption 传递。

@Configuration
static class Config {

	@Bean
	@Description("Get the weather in location") // function description
	public Function<MockWeatherService.Request, MockWeatherService.Response> weatherFunction1() {
		return new MockWeatherService();
	}
	...
}

@Description 注解是可选的,它提供了一个函数描述 (2),帮助模型理解何时调用函数。这是一个重要的属性,可以帮助人工智能模型确定要调用的客户端函数。

另一种提供函数说明的方法是在 MockWeatherService.Request 上使用 @JsonClassDescription 注解来提供函数说明:

@Configuration
static class Config {

	@Bean
	public Function<Request, Response> currentWeather3() { // (1) Bean 名称作为函数名称。
		return new MockWeatherService();
	}
	...
}

@JsonClassDescription("Get the weather in location") // (2) 功能描述
public record Request(String location, Unit unit) {}

最佳做法是在请求对象中注释信息,使生成的函数 JSON 模式尽可能具有描述性,以帮助人工智能模型选择要调用的正确函数。

FunctionCallWithFunctionBeanIT.java 演示了这种方法。

函数回调封装器
注册函数的另一种方法是创建一个 FunctionCallbackWrapper 封装器,如下所示:

@Configuration
static class Config {

	@Bean
	public FunctionCallback weatherFunctionInfo() {

		return new FunctionCallbackWrapper<>("CurrentWeather", // (1) function name
				"Get the weather in location", // (2) function description
				(response) -> "" + response.temp() + response.unit(), // (3) Response Converter
				new MockWeatherService()); // function code
	}
	...
}

 

它封装了第三方 MockWeatherService 函数,并将其注册为 AnthropicChatModel 的 CurrentWeather 函数。它还提供了一个说明 (2) 和一个可选的响应转换器 (3),用于将响应转换成模型所期望的文本。

默认情况下,响应转换器会对响应对象进行 JSON 序列化。

FunctionCallbackWrapper 内部根据 MockWeatherService.Request 类解析函数调用签名。

在聊天选项中指定函数

要让模型知道并调用您的 CurrentWeather 功能,您需要在提示请求中启用该功能:

AnthropicChatModel chatModel = ...

UserMessage userMessage = new UserMessage("What's the weather like in Paris?");

ChatResponse response = chatModel.call(new Prompt(List.of(userMessage),
		AnthropicChatOptions.builder().withFunction("CurrentWeather").build())); // (1) Enable the function

logger.info("Response: {}", response);

 

上述用户问题将触发对 CurrentWeather 函数的 3 次调用(每个城市一次),并产生最终回复。

使用提示选项注册/调用函数

除了自动配置外,您还可以通过 Prompt 请求动态注册回调函数:

AnthropicChatModel chatModel = ...

UserMessage userMessage = new UserMessage("What's the weather like in Paris?");

var promptOptions = AnthropicChatOptions.builder()
	.withFunctionCallbacks(List.of(new FunctionCallbackWrapper<>(
		"CurrentWeather", // name
		"Get the weather in location", // function description
		new MockWeatherService()))) // function code
	.build();

ChatResponse response = chatModel.call(new Prompt(List.of(userMessage), promptOptions));

在该请求的持续时间内,提示中注册的功能默认为启用。

 

这种方法可以根据用户输入动态地选择要调用的不同函数。

FunctionCallWithPromptFunctionIT.java 集成测试提供了一个完整示例,说明如何在 AnthropicChatModel 中注册函数并在提示请求中使用该函数。

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-06-08 05:18:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-08 05:18:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-08 05:18:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-08 05:18:01       18 阅读

热门阅读

  1. C++ 变量的声明和初始化方式

    2024-06-08 05:18:01       9 阅读
  2. Nginx介绍

    2024-06-08 05:18:01       7 阅读
  3. OCP学习笔记-007 SQL语言之一:DQL

    2024-06-08 05:18:01       8 阅读
  4. openresty lua修改响应体内容

    2024-06-08 05:18:01       9 阅读
  5. Always语句和assign的用法

    2024-06-08 05:18:01       9 阅读
  6. spring-boot 2.7.18整合sharding-jdbc-spring-boot-starter 4.1.1

    2024-06-08 05:18:01       12 阅读