快速入门 调用Rerank API callrerank(query, documents, topn2) Java 适用于Spring AI框架调用Open API 支持对文本生成、图像理解、文本生成、enbedding文本向量化以及rerank重排序API的调用 环境变量配置 python spring: ai: openai: apikey: yourappkey 替换成👆自己的API KEY baseurl: chat: options: model: xirangmodelid 替换成👆自己要用的模型 embedding: options: model: xirangmodelid 替换成👆自己要用的模型 image: options: model: xirangmodelid 替换成👆自己要用的模型 rerank: option: model: xirangmodelid 替换成👆自己要用的模型 server: port: 9090 servlet: encoding: charset: UTF8 force: true enabled: true 项目依赖 python 4.0.0 org.springframework.boot springbootstarterparent 3.2.2 com.demo aitest 0.0.1SNAPSHOT aitest aitest 17 0.8.1 2023.0.0 org.springframework.boot springbootstarterweb org.springframework.ai springaiopenaispringbootstarter ${springai.version} org.springframework.cloud springcloudfunctionweb org.springframework.boot springbootstartertest test org.projectlombok lombok provided org.springframework.cloud springclouddependencies ${springcloud.version} pom import org.springframework.ai springaibom ${springai.version} pom import org.springframework.boot springbootmavenplugin springsnapshots Spring Snapshots false springmilestones Spring Milestones false 配置类 java package com.demo.aitest; import jakarta.annotation.PostConstruct; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi; @Configuration public class OpenAIConfig { @Value("${spring.ai.openai.apikey}") private String apiKey; @Value("${spring.ai.openai.baseurl}") private String baseUrl; @Value("${spring.ai.openai.chat.options.model}") private String chatModel; @Value("${spring.ai.openai.chat.options.model}") private String embeddingModel; @Autowired private OpenAIProperties openAIProperties; @Bean public OpenAiApi openAiApi(){ return new OpenAiApi(baseUrl, apiKey); } @Bean public OpenAiChatClient openAiChatClient(OpenAiApi openAiApi) { OpenAiChatOptions options new OpenAiChatOptions(); options.setModel(chatModel); options.setFrequencyPenalty(0.0f); options.setMaxTokens(2000); return new OpenAiChatClient(openAiApi, options); } public OpenAiEmbeddingClient openAiEmbeddingClient(OpenAiApi openAiApi, RetryTemplate retryTemplate){ OpenAiEmbeddingOptions options OpenAiEmbeddingOptions.builder() .withModel(embeddingModel) .build(); return new OpenAiEmbeddingClient(openAiApi, MetadataMode.INFERENCE, options, retryTemplate); } @Bean public RetryTemplate retryTemplate(){ return new RetryTemplate(); } @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } } OpenAPI Http客户端 java package com.demo.aitest.service; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.Collections; @Service @Slf4j public class HttpClientService { @Value("${spring.ai.openai.apikey}") private String apiKey; @Value("${spring.ai.openai.baseurl}") private String baseUrl; @Autowired private RestTemplate restTemplate; @Autowired private ObjectMapper mapper; public ResponseEntity callOpenAPI(String url, Object requestBody) throws JsonProcessingException { String fullUrl baseUrl + url; log.info("Calling Open API: {}", fullUrl); if(log.isDebugEnabled()){ log.debug("Request Body: {}", mapper.writeValueAsString(requestBody)); } try { HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.APPLICATIONJSON); headers.setAccept(Collections.singletonList(MediaType.APPLICATIONJSON)); headers.set("Authorization", "Bearer " + apiKey); ResponseEntity response restTemplate.exchange(fullUrl, HttpMethod.POST, new HttpEntity<>(requestBody, headers), String.class); return ResponseEntity.ok(response.getBody()); } catch (Exception e) { log.error("Open API call failed: {} Error: {}", fullUrl, e.getMessage()); return ResponseEntity.internalServerError().body(e.getMessage()); } } } ChatController 已封装对文本生成API的支持 java package com.demo.aitest.controller; import com.demo.aitest.controller.request.MultimodalRequest; import com.demo.aitest.service.HttpClientService; import com.fasterxml.jackson.core.JsonProcessingException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.openai.OpenAiChatClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.; import org.springframework.web.bind.annotation.; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.io.IOException; @RestController public class ChatController { private static final Logger logger LoggerFactory.getLogger(ChatController.class); @Autowired private OpenAiChatClient chatClient; @GetMapping("/chat") public String chat(@RequestParam String message) { try { ChatResponse response chatClient.call(new Prompt(message)); String content response.getResult().getOutput().getContent(); logger.info("Response received successfully"); return content; } catch (Exception e) { logger.error("Error processing chat request: {}", e.getMessage()); throw e; } } @GetMapping(value "/chat/stream", produces "text/eventstream;charsetUTF8") public SseEmitter streamChat(@RequestParam String message) { SseEmitter emitter new SseEmitter(1L); // 无限超时 try { // Create prompt with UserMessage Prompt prompt new Prompt(new UserMessage(message)); // Stream the response chatClient.stream(prompt).subscribe( chunk > { try { if (chunk ! null && chunk.getResult() ! null) { String content chunk.getResult().getOutput().getContent(); if (content ! null && !content.isEmpty()) { emitter.send(content); } } } catch (IOException e) { logger.error("Error sending chunk: {}", e.getMessage()); emitter.completeWithError(e); } }, error > { logger.error("Error in stream: {}", error.getMessage()); emitter.completeWithError(error); }, () > { logger.info("Stream completed successfully"); emitter.complete(); } ); } catch (Exception e) { logger.error("Error processing streaming chat request: {}", e.getMessage()); emitter.completeWithError(e); } return emitter; } } 图像理解请求 java package com.demo.aitest.controller.request; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.List; @JsonInclude(JsonInclude.Include.NONNULL) @Data public class MultimodalRequest { private String model; private List messages; @JsonProperty(value "streamoptions") private StreamOptions streamOptions; @JsonProperty(value "paralleltoolcalls") private boolean parallelToolCalls; private boolean stream; @JsonInclude(JsonInclude.Include.NONNULL) @Data public static class Message { private String role; @JsonProperty(value "content") private List content; } @JsonInclude(JsonInclude.Include.NONNULL) @Data public static class Content { @JsonProperty(value "type") private String type; @JsonProperty(value "text") private String text; @JsonProperty(value "imageurl") private ImageUrl imageUrl; } @JsonInclude(JsonInclude.Include.NONNULL) @Data public static class ImageUrl { private String url; } @JsonInclude(JsonInclude.Include.NONNULL) @Data public static class StreamOptions { @JsonProperty(value "includeusage") private boolean includeUsage; } } 文本生图请求 java package com.demo.aitest.controller.request; public class ImageGenerationRequest { private String model; private String prompt; private Integer n; private String size; } ImageController java package com.demo.aitest.controller; import com.demo.aitest.controller.request.ImageGenerationRequest; import com.demo.aitest.controller.request.MultimodalRequest; import com.demo.aitest.service.HttpClientService; import com.fasterxml.jackson.core.JsonProcessingException; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class ImageController { @Value("${spring.ai.openai.chat.options.model}") private String chatModel; @Value("${spring.ai.openai.image.options.model}") private String imageModel; @Autowired private HttpClientService httpClientService; @PostMapping("/image/understanding") public ResponseEntity multiModalChat(@RequestBody MultimodalRequest multiModalRequest) throws JsonProcessingException { if(StringUtils.isBlank(multiModalRequest.getModel())){ multiModalRequest.setModel(chatModel); } return httpClientService.callOpenAPI("/v1/chat/completions", multiModalRequest); } @PostMapping("/image/generation") public ResponseEntity multiModalChat(@RequestBody ImageGenerationRequest imageGenerationRequest) throws JsonProcessingException { if(StringUtils.isBlank(imageGenerationRequest.getModel())){ imageGenerationRequest.setModel(imageModel); } return httpClientService.callOpenAPI("/v1/images/generations", imageGenerationRequest); } } Embedding Controller java package com.demo.aitest.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.embedding.EmbeddingResponse; import org.springframework.ai.openai.OpenAiEmbeddingClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Collections; @RestController public class EmbeddingController { private static final Logger logger LoggerFactory.getLogger(EmbeddingController.class); @Autowired private OpenAiEmbeddingClient openAiEmbeddingClient; @PostMapping("/embedding") public ResponseEntity embedding(String text) { try { EmbeddingResponse embeddingResponse openAiEmbeddingClient.embedForResponse(Collections.singletonList(text)); logger.info("Response received successfully"); return ResponseEntity.ok(embeddingResponse); } catch (Exception e) { logger.error("Error processing chat request: {}", e.getMessage()); throw e; } } } Rerank请求 java package com.demo.aitest.controller.request; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @Data public class RerankRequest { private String query; private String[] documents; private String model; @JsonProperty(value "topn") private Integer topn; } Rerank Controller java package com.demo.aitest.controller; import com.demo.aitest.controller.request.RerankRequest; import com.demo.aitest.service.HttpClientService; import com.fasterxml.jackson.core.JsonProcessingException; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j public class RerankController { @Value("${spring.ai.openai.rerank.options.model}") private String rerankModel; private final HttpClientService httpClientService; @Autowired public RerankController(HttpClientService httpClientService) { this.httpClientService httpClientService; } @PostMapping("/rerank") public ResponseEntity rerank(@RequestBody RerankRequest rerankRequest) throws JsonProcessingException { if(StringUtils.isBlank(rerankRequest.getModel())){ rerankRequest.setModel(rerankModel); } return httpClientService.callOpenAPI("/v1/rerank", rerankRequest); } } java 访问地址: ●文本生成:GET ●文本生图: {"model": "xirangmodelid", "prompt": "A cute baby sea otter", "n": 1, "size": "512x512"} 图像理解:POST {"model": "88003ac1ca7a4e4e8efa7caee648323b", "messages": [{"role": "user", "content": [{"type": "text", "text": "描述下这张图"}, {"type": "imageurl", "imageurl": {"url": " "}}]}], "streamoptions": {"includeusage": true}, "paralleltoolcalls": true, "stream": false} embedding向量化:GET cute baby sea otter rerank重排序:POST {"query": "Python教程", "documents": ["Python基础语法", "Python高级特性", "Java编程入门"], "model": "xirangmodelid", "topn": 2}