MistralAiChatModel实现了ChatModel和StreamingChatModel接口,并使用低级MistralAiApi客户端连接到Mistral AI服务。
将spring-ai-mistral-ai依赖项添加到项目的Maven pom.xml文件中:
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mistral-ai</artifactId></dependency>
或者添加到你的Gradle build.gradle构建文件中。
dependencies { implementation 'org.springframework.ai:spring-ai-mistral-ai'}
接下来,创建一个MistralAiChatModel,并使用它进行文本生成:
var mistralAiApi = new MistralAiApi(System.getenv("MISTRAL_AI_API_KEY"));var chatModel = new MistralAiChatModel(this.mistralAiApi, MistralAiChatOptions.builder() .model(MistralAiApi.ChatModel.LARGE.getValue()) .temperature(0.4) .maxTokens(200) .build());ChatResponse response = this.chatModel.call( new Prompt("Generate the names of 5 famous pirates."));// Or with streaming responsesFlux<ChatResponse> response = this.chatModel.stream( new Prompt("Generate the names of 5 famous pirates."));
MistralAiChatOptions提供了聊天请求的配置信息。MistralAiChatOptions.Builder是一个流畅的选项构建器。
Low-level MistralAiApi客户端
MistralAiApi为Mistral AI API提供了一个轻量级的Java客户端。
以下是一个简单的代码片段,展示了如何以编程方式使用API:
MistralAiApi mistralAiApi = new MistralAiApi(System.getenv("MISTRAL_AI_API_KEY"));ChatCompletionMessage chatCompletionMessage = new ChatCompletionMessage("Hello world", Role.USER);// Sync requestResponseEntity<ChatCompletion> response = this.mistralAiApi.chatCompletionEntity( new ChatCompletionRequest(List.of(this.chatCompletionMessage), MistralAiApi.ChatModel.LARGE.getValue(), 0.8, false));// Streaming requestFlux<ChatCompletionChunk> streamResponse = this.mistralAiApi.chatCompletionStream( new ChatCompletionRequest(List.of(this.chatCompletionMessage), MistralAiApi.ChatModel.LARGE.getValue(), 0.8, true));
MistralAiApi 示例
MistralAiApiIT测试提供了一些关于如何使用该轻量级库的一般示例。
import java.util.List;import org.junit.jupiter.api.Test;import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;import reactor.core.publisher.Flux;import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletion;import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionChunk;import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionMessage;import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionMessage.Role;import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionRequest;import org.springframework.ai.mistralai.api.MistralAiApi.Embedding;import org.springframework.ai.mistralai.api.MistralAiApi.EmbeddingList;import org.springframework.http.ResponseEntity;import static org.assertj.core.api.Assertions.assertThat;/** * @author Christian Tzolov * @author Thomas Vitale * @author Jason Smith * @since 0.8.1 */@EnabledIfEnvironmentVariable(named = "MISTRAL_AI_API_KEY", matches = ".+")public class MistralAiApiIT {MistralAiApi mistralAiApi = MistralAiApi.builder().apiKey(System.getenv("MISTRAL_AI_API_KEY")).build();@Testvoid chatCompletionEntity() {ChatCompletionMessage chatCompletionMessage = new ChatCompletionMessage("Hello world", Role.USER); ResponseEntity<ChatCompletion> response = this.mistralAiApi.chatCompletionEntity(new ChatCompletionRequest( List.of(chatCompletionMessage), MistralAiApi.ChatModel.MISTRAL_SMALL.getValue(), 0.8, false)); assertThat(response).isNotNull(); assertThat(response.getBody()).isNotNull(); }@Testvoid chatCompletionEntityWithSystemMessage() {ChatCompletionMessage userMessage = new ChatCompletionMessage("Tell me about 3 famous pirates from the Golden Age of Piracy and why they did?", Role.USER);ChatCompletionMessage systemMessage = new ChatCompletionMessage(""" You are an AI assistant that helps people find information. Your name is Bob. You should reply to the user's request with your name and also in the style of a pirate. """, Role.SYSTEM); ResponseEntity<ChatCompletion> response = this.mistralAiApi.chatCompletionEntity(new ChatCompletionRequest( List.of(systemMessage, userMessage), MistralAiApi.ChatModel.MISTRAL_SMALL.getValue(), 0.8, false)); assertThat(response).isNotNull(); assertThat(response.getBody()).isNotNull(); }@Testvoid chatCompletionStream() {ChatCompletionMessage chatCompletionMessage = new ChatCompletionMessage("Hello world", Role.USER); Flux<ChatCompletionChunk> response = this.mistralAiApi.chatCompletionStream(new ChatCompletionRequest( List.of(chatCompletionMessage), MistralAiApi.ChatModel.MISTRAL_SMALL.getValue(), 0.8, true)); assertThat(response).isNotNull(); assertThat(response.collectList().block()).isNotNull(); }@Testvoid embeddings() { ResponseEntity<EmbeddingList<Embedding>> response = this.mistralAiApi .embeddings(new MistralAiApi.EmbeddingRequest<String>("Hello world")); assertThat(response).isNotNull(); assertThat(response.getBody().data()).hasSize(1); assertThat(response.getBody().data().get(0).embedding()).hasSize(1024); }}
PaymentStatusFunctionCallingIT测试展示了如何使用低级 API 来调用工具函数。该测试基于 Mistral AI 函数调用教程。
import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.function.Function;import com.fasterxml.jackson.annotation.JsonProperty;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import org.junit.jupiter.api.Test;import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.ai.mistralai.api.MistralAiApi;import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletion;import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionMessage;import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionMessage.Role;import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionMessage.ToolCall;import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionRequest;import org.springframework.ai.mistralai.api.MistralAiApi.ChatCompletionRequest.ToolChoice;import org.springframework.ai.mistralai.api.MistralAiApi.FunctionTool;import org.springframework.ai.mistralai.api.MistralAiApi.FunctionTool.Type;import org.springframework.http.ResponseEntity;import static org.assertj.core.api.Assertions.assertThat;/** * Demonstrates how to use function calling suing Mistral AI Java API: * {@link MistralAiApi}. * * It is based on the <a href="https://docs.mistral.ai/guides/function-calling/">Mistral * AI Function Calling</a> guide. * * @author Christian Tzolov * @author Jason Smith * @since 0.8.1 */// @Disabled("See https://github.com/spring-projects/spring-ai/issues/1853")@EnabledIfEnvironmentVariable(named = "MISTRAL_AI_API_KEY", matches = ".+")public class PaymentStatusFunctionCallingIT {// Assuming we have the following datapublic static final Map<String, StatusDate> DATA = Map.of("T1001", new StatusDate("Paid", "2021-10-05"), "T1002",new StatusDate("Unpaid", "2021-10-06"), "T1003", new StatusDate("Paid", "2021-10-07"), "T1004",new StatusDate("Paid", "2021-10-05"), "T1005", new StatusDate("Pending", "2021-10-08"));static Map<String, Function<Transaction, ?>> functions = Map.of("retrieve_payment_status",new RetrievePaymentStatus(), "retrieve_payment_date", new RetrievePaymentDate());private final Logger logger = LoggerFactory.getLogger(PaymentStatusFunctionCallingIT.class);private static <T> T jsonToObject(String json, Class<T> targetClass) {try {return new ObjectMapper().readValue(json, targetClass); }catch (JsonProcessingException e) {throw new RuntimeException(e); } }@Test@SuppressWarnings("null")public void toolFunctionCall() {var transactionJsonSchema = """ { "type": "object", "properties": { "transaction_id": { "type": "string", "description": "The transaction id" } }, "required": ["transaction_id"] } """;// Alternatively, generate the JSON schema using the ModelOptionsUtils helper://// var transactionJsonSchema = ModelOptionsUtils.getJsonSchema(Transaction.class,// false);var paymentStatusTool = new FunctionTool(Type.FUNCTION, new FunctionTool.Function("Get payment status of a transaction", "retrieve_payment_status", transactionJsonSchema));var paymentDateTool = new FunctionTool(Type.FUNCTION, new FunctionTool.Function("Get payment date of a transaction", "retrieve_payment_date", transactionJsonSchema)); List<ChatCompletionMessage> messages = new ArrayList<>( List.of(new ChatCompletionMessage("What's the status of my transaction with id T1001?", Role.USER)));MistralAiApi mistralApi = MistralAiApi.builder().apiKey(System.getenv("MISTRAL_AI_API_KEY")).build(); ResponseEntity<ChatCompletion> response = mistralApi .chatCompletionEntity(new ChatCompletionRequest(messages, MistralAiApi.ChatModel.MISTRAL_LARGE.getValue(), List.of(paymentStatusTool, paymentDateTool), ToolChoice.AUTO));ChatCompletionMessage responseMessage = response.getBody().choices().get(0).message(); assertThat(responseMessage.role()).isEqualTo(Role.ASSISTANT); assertThat(responseMessage.toolCalls()).isNotNull();// extend conversation with assistant's reply. messages.add(responseMessage);// Send the info for each function call and function response to the model.for (ToolCall toolCall : responseMessage.toolCalls()) {var functionName = toolCall.function().name();// Map the function, JSON arguments into a Transaction object.Transaction transaction = jsonToObject(toolCall.function().arguments(), Transaction.class);// Call the target function with the transaction object.var result = functions.get(functionName).apply(transaction);// Extend conversation with function response.// The functionName is used to identify the function response! messages.add(new ChatCompletionMessage(result.toString(), Role.TOOL, functionName, null, toolCall.id())); } response = mistralApi .chatCompletionEntity(new ChatCompletionRequest(messages, MistralAiApi.ChatModel.MISTRAL_LARGE.getValue()));var responseContent = response.getBody().choices().get(0).message().content(); logger.info("Final response: " + responseContent); assertThat(responseContent).containsIgnoringCase("T1001"); assertThat(responseContent).containsIgnoringCase("Paid"); }record StatusDate(String status, String date) { }public record Transaction(@JsonProperty(required = true, value = "transaction_id") String transactionId) { }public record Status(@JsonProperty(required = true, value = "status") String status) { }public record Date(@JsonProperty(required = true, value = "date") String date) { }private static class RetrievePaymentStatus implements Function<Transaction, Status> {@Overridepublic Status apply(Transaction paymentTransaction) {return new Status(DATA.get(paymentTransaction.transactionId).status); } }private static class RetrievePaymentDate implements Function<Transaction, Date> {@Overridepublic Date apply(Transaction paymentTransaction) {return new Date(DATA.get(paymentTransaction.transactionId).date); } }}
Mistral AI OCR
Spring AI通过Mistral AI支持光学字符识别(OCR)。这使您能够从文档中提取文本和图像数据。
前提条件
您需要使用Mistral AI创建一个API来访问Mistral AI语言模型。请在Mistral AI注册页面创建一个账户,并在API密钥页面生成令牌。
添加依赖项
要使用Mistral AI OCR API,您需要将spring-ai-mistral-ai依赖项添加到您的项目中。
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mistral-ai</artifactId></dependency>
或者添加到你的Gradle build.gradle构建文件中。
dependencies { implementation 'org.springframework.ai:spring-ai-mistral-ai'}
Low-level MistralOcrApi客户端
MistralOcrApi为Mistral AI OCR API提供了一个轻量级的Java客户端。
以下是一个简单的代码片段,展示了如何以编程方式使用API:
MistralOcrApi mistralAiApi = new MistralOcrApi(System.getenv("MISTRAL_AI_API_KEY"));String documentUrl = "https://arxiv.org/pdf/2201.04234";MistralOcrApi.OCRRequest request = new MistralOcrApi.OCRRequest( MistralOcrApi.OCRModel.MISTRAL_OCR_LATEST.getValue(), "test_id", new MistralOcrApi.OCRRequest.DocumentURLChunk(documentUrl), List.of(0, 1, 2), true, 5, 50);ResponseEntity<MistralOcrApi.OCRResponse> response = mistralAiApi.ocr(request);