墨语灵犀Java开发实战:集成SpringBoot构建智能问答API

张开发
2026/4/13 11:51:31 15 分钟阅读

分享文章

墨语灵犀Java开发实战:集成SpringBoot构建智能问答API
墨语灵犀Java开发实战集成SpringBoot构建智能问答API最近在做一个内部知识库项目需要给系统加上智能问答的能力。团队评估了几种方案最终决定基于墨语灵犀大模型用我们最熟悉的Java和SpringBoot来构建API服务。整个过程走下来发现把大模型能力集成到企业级Java应用里其实没有想象中那么复杂但确实有一些关键点需要注意。这篇文章我就结合这次实战经验聊聊怎么用SpringBoot快速搭建一个稳定、高效的智能问答API。我会从项目搭建、核心接口调用一直讲到异步处理、结果缓存这些提升体验和性能的细节并提供可以直接运行的代码示例。如果你也在考虑为你的Java应用增加AI能力希望这篇内容能给你一些实用的参考。1. 项目环境与依赖准备首先我们得把项目架子搭起来。这里假设你已经有一个可访问的墨语灵犀模型服务它提供了标准的HTTP API接口。我们的SpringBoot应用将作为客户端去调用这个服务。1.1 创建SpringBoot项目你可以通过 Spring Initializr 网站或者直接用IDE如IntelliJ IDEA来快速生成一个项目。核心依赖选择Spring Web: 用于构建RESTful API。Spring Boot DevTools: 开发工具支持热加载。Lombok: 简化Java Bean的代码编写。生成的pom.xml文件基础部分如下我们还需要手动添加几个关键的依赖。?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.1.5/version !-- 建议使用较新稳定版本 -- relativePath/ /parent groupIdcom.example/groupId artifactIdmoyu-lingxi-api/artifactId version0.0.1-SNAPSHOT/version namemoyu-lingxi-api/name descriptionDemo project for Moyu Lingxi API/description properties java.version17/java.version /properties dependencies !-- Spring Boot 核心依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-devtools/artifactId scoperuntime/scope optionaltrue/optional /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency !-- HTTP客户端推荐使用OkHttp或Apache HttpClient -- dependency groupIdcom.squareup.okhttp3/groupId artifactIdokhttp/artifactId version4.11.0/version /dependency !-- JSON处理Spring Boot默认使用Jackson确保其存在 -- dependency groupIdcom.fasterxml.jackson.core/groupId artifactIdjackson-databind/artifactId /dependency !-- 缓存支持 (可选用于后续缓存章节) -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-cache/artifactId /dependency dependency groupIdcom.github.ben-manes.caffeine/groupId artifactIdcaffeine/artifactId /dependency /dependencies !-- ... 构建插件等配置 ... -- /project这里我选择了OkHttp作为HTTP客户端它的API比较简洁直观。当然你也可以使用Spring自带的RestTemplate或者新的WebClient。1.2 配置模型服务连接信息接下来我们需要在application.yml(或application.properties) 中配置墨语灵犀服务的地址、密钥等信息。这样便于在不同环境开发、测试、生产中切换配置。# application.yml server: port: 8080 moyu: lingxi: # 墨语灵犀模型服务的API基础地址 base-url: http://your-moyu-lingxi-server-host:port/v1 # API调用密钥 (如果服务需要认证) api-key: your-api-key-here # 默认使用的模型名称 default-model: moyu-lingxi-latest # 请求超时时间毫秒 timeout: 30000然后我们创建一个配置类来读取这些属性并注入一个配置好的OkHttpClientBean。package com.example.moyulingxiapi.config; import lombok.Data; import okhttp3.OkHttpClient; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.TimeUnit; Configuration ConfigurationProperties(prefix moyu.lingxi) Data public class MoYuLingXiConfig { private String baseUrl; private String apiKey; private String defaultModel; private Integer timeout; Bean public OkHttpClient okHttpClient() { return new OkHttpClient.Builder() .connectTimeout(timeout, TimeUnit.MILLISECONDS) .readTimeout(timeout, TimeUnit.MILLISECONDS) .writeTimeout(timeout, TimeUnit.MILLISECONDS) .build(); } }2. 核心服务层封装模型调用这是最核心的部分我们将封装对墨语灵犀HTTP API的调用。通常大模型服务会提供“对话补全”Chat Completion接口我们以此为例。2.1 定义请求与响应数据结构首先定义调用API时需要的请求体Request和接收的响应体Response。这能让我们用对象的方式操作数据更清晰也更安全。package com.example.moyulingxiapi.dto.request; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.List; Data public class ChatCompletionRequest { // 指定使用的模型 private String model; // 消息列表包含用户输入和可能的上下文 private ListMessage messages; // 控制生成随机性的温度参数0-2之间越高越随机 private Float temperature 0.7f; // 最大生成token数 JsonProperty(max_tokens) private Integer maxTokens; Data public static class Message { // 角色system, user, assistant private String role; // 消息内容 private String content; } }package com.example.moyulingxiapi.dto.response; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.List; Data public class ChatCompletionResponse { private String id; private String object; private Long created; private String model; private ListChoice choices; private Usage usage; Data public static class Choice { private Integer index; private Message message; JsonProperty(finish_reason) private String finishReason; Data public static class Message { private String role; private String content; } } Data public static class Usage { JsonProperty(prompt_tokens) private Integer promptTokens; JsonProperty(completion_tokens) private Integer completionTokens; JsonProperty(total_tokens) private Integer totalTokens; } }2.2 实现服务调用逻辑创建一个服务类MoYuLingXiService它负责构造请求、调用HTTP接口、处理响应和异常。package com.example.moyulingxiapi.service; import com.example.moyulingxiapi.config.MoYuLingXiConfig; import com.example.moyulingxiapi.dto.request.ChatCompletionRequest; import com.example.moyulingxiapi.dto.response.ChatCompletionResponse; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import okhttp3.*; import org.springframework.stereotype.Service; import java.io.IOException; import java.util.Collections; Slf4j Service RequiredArgsConstructor public class MoYuLingXiService { private final MoYuLingXiConfig config; private final OkHttpClient okHttpClient; private final ObjectMapper objectMapper; // Spring Boot会自动注入 // 基础对话生成方法 public String generateChatResponse(String userMessage) throws IOException { // 1. 构建请求消息 ChatCompletionRequest.Message userMsg new ChatCompletionRequest.Message(); userMsg.setRole(user); userMsg.setContent(userMessage); ChatCompletionRequest request new ChatCompletionRequest(); request.setModel(config.getDefaultModel()); request.setMessages(Collections.singletonList(userMsg)); request.setTemperature(0.8f); request.setMaxTokens(1024); // 2. 调用API ChatCompletionResponse response callChatCompletionApi(request); // 3. 提取并返回助理的回复 if (response ! null response.getChoices() ! null !response.getChoices().isEmpty()) { return response.getChoices().get(0).getMessage().getContent(); } else { throw new RuntimeException(未能从模型服务获取有效回复。); } } // 封装HTTP调用 private ChatCompletionResponse callChatCompletionApi(ChatCompletionRequest request) throws IOException { String url config.getBaseUrl() /chat/completions; // 假设接口路径 String requestBody objectMapper.writeValueAsString(request); RequestBody body RequestBody.create( requestBody, MediaType.get(application/json; charsetutf-8) ); Request httpRequest new Request.Builder() .url(url) .post(body) .addHeader(Authorization, Bearer config.getApiKey()) // 如果需要认证 .addHeader(Content-Type, application/json) .build(); try (Response response okHttpClient.newCall(httpRequest).execute()) { if (!response.isSuccessful()) { String errorBody response.body() ! null ? response.body().string() : null; log.error(调用墨语灵犀API失败。状态码: {}, 响应体: {}, response.code(), errorBody); throw new IOException(API调用失败状态码: response.code()); } if (response.body() null) { throw new IOException(API响应体为空。); } String responseBody response.body().string(); return objectMapper.readValue(responseBody, ChatCompletionResponse.class); } } // 扩展方法带系统指令的对话 public String generateChatResponseWithSystem(String systemInstruction, String userMessage) throws IOException { ChatCompletionRequest.Message systemMsg new ChatCompletionRequest.Message(); systemMsg.setRole(system); systemMsg.setContent(systemInstruction); ChatCompletionRequest.Message userMsg new ChatCompletionRequest.Message(); userMsg.setRole(user); userMsg.setContent(userMessage); ChatCompletionRequest request new ChatCompletionRequest(); request.setModel(config.getDefaultModel()); request.setMessages(List.of(systemMsg, userMsg)); request.setTemperature(0.7f); ChatCompletionResponse response callChatCompletionApi(request); // ... 提取回复逻辑同上 return extractResponseContent(response); } private String extractResponseContent(ChatCompletionResponse response) { // 提取回复内容的通用方法 if (response ! null response.getChoices() ! null !response.getChoices().isEmpty()) { return response.getChoices().get(0).getMessage().getContent(); } return null; } }这个服务类已经具备了最基础的调用能力。你可以看到我们通过Service注解将其声明为Spring Bean并通过构造函数注入配置和HTTP客户端。generateChatResponse方法对外提供了一个简单的问答入口。3. 构建RESTful API控制器有了服务层我们就可以构建Web API了。创建一个ChatController提供对外的HTTP接口。package com.example.moyulingxiapi.controller; import com.example.moyulingxiapi.service.MoYuLingXiService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.util.Map; Slf4j RestController RequestMapping(/api/v1/chat) RequiredArgsConstructor public class ChatController { private final MoYuLingXiService chatService; PostMapping(/completions) public ResponseEntity? chatCompletion(RequestBody MapString, String request) { String message request.get(message); if (message null || message.trim().isEmpty()) { return ResponseEntity.badRequest().body(Map.of(error, 消息内容不能为空)); } try { String response chatService.generateChatResponse(message); return ResponseEntity.ok(Map.of(reply, response)); } catch (IOException e) { log.error(调用AI服务时发生IO异常, e); return ResponseEntity.internalServerError().body(Map.of(error, 服务暂时不可用请稍后重试)); } catch (Exception e) { log.error(处理聊天请求时发生未知异常, e); return ResponseEntity.internalServerError().body(Map.of(error, 处理请求时出错)); } } // 另一个接口示例文本摘要 PostMapping(/summarize) public ResponseEntity? summarizeText(RequestBody MapString, String request) { String text request.get(text); if (text null || text.trim().isEmpty()) { return ResponseEntity.badRequest().body(Map.of(error, 待摘要文本不能为空)); } // 构造一个特定的系统指令让模型进行摘要 String systemInstruction 你是一个专业的文本摘要助手。请将用户提供的文本内容用简洁清晰的语言进行总结保留核心信息。; String userMessage 请总结以下文本\n text; try { // 这里可以调用服务层扩展的方法或者直接复用基础方法 String summary chatService.generateChatResponseWithSystem(systemInstruction, userMessage); return ResponseEntity.ok(Map.of(summary, summary)); } catch (IOException e) { log.error(摘要生成失败, e); return ResponseEntity.internalServerError().body(Map.of(error, 摘要生成服务异常)); } } }现在启动你的SpringBoot应用就可以通过POST /api/v1/chat/completions和POST /api/v1/chat/summarize来调用智能问答和文本摘要功能了。4. 进阶优化提升性能与体验基础功能跑通后我们可以考虑一些优化措施让API更健壮、更高效。4.1 异步处理与超时控制大模型生成回答可能需要几秒甚至更长时间。如果同步处理会长时间占用一个HTTP线程影响服务器并发能力。我们可以使用Spring的Async注解实现异步调用。首先在主应用类或配置类上启用异步支持SpringBootApplication EnableAsync // 启用异步支持 public class MoyuLingxiApiApplication { public static void main(String[] args) { SpringApplication.run(MoyuLingxiApiApplication.class, args); } }然后在服务层创建一个异步方法并修改控制器// 在 MoYuLingXiService 中添加 Async public CompletableFutureString generateChatResponseAsync(String userMessage) { try { String response generateChatResponse(userMessage); return CompletableFuture.completedFuture(response); } catch (Exception e) { CompletableFutureString future new CompletableFuture(); future.completeExceptionally(e); return future; } }// 在 ChatController 中添加新的异步接口 PostMapping(/completions/async) public CompletableFutureResponseEntity? chatCompletionAsync(RequestBody MapString, String request) { String message request.get(message); if (message null || message.trim().isEmpty()) { return CompletableFuture.completedFuture( ResponseEntity.badRequest().body(Map.of(error, 消息内容不能为空)) ); } return chatService.generateChatResponseAsync(message) .thenApply(reply - ResponseEntity.ok(Map.of(reply, reply))) .exceptionally(e - { log.error(异步处理聊天请求失败, e); return ResponseEntity.internalServerError() .body(Map.of(error, 异步处理请求时出错)); }); }这样请求会立即返回一个CompletableFuture实际处理在后台线程池中进行。前端可以通过轮询或其他机制如WebSocket来获取最终结果。4.2 结果缓存对于相同或相似的提问重复调用模型既浪费资源也增加响应时间。我们可以引入缓存。这里使用Spring Cache和Caffeine。首先在配置类中配置Caffeine缓存Configuration EnableCaching // 启用缓存 public class CacheConfig { Bean public CacheManager cacheManager() { CaffeineCacheManager cacheManager new CaffeineCacheManager(); // 配置一个名为“chatCache”的缓存最大100条过期时间10分钟 cacheManager.setCaffeine(Caffeine.newBuilder() .maximumSize(100) .expireAfterWrite(10, TimeUnit.MINUTES) .recordStats()); return cacheManager; } }然后在服务方法上添加Cacheable注解。注意缓存的Key需要精心设计通常基于请求内容。// 在 MoYuLingXiService 中 Cacheable(value chatCache, key #userMessage.hashCode()) // 简单示例实际可用更复杂的Key public String generateChatResponseCached(String userMessage) throws IOException { log.info(缓存未命中实际调用模型API。问题{}, userMessage); return generateChatResponse(userMessage); }4.3 全局异常处理与监控为了给API调用方提供更友好的错误信息我们可以定义全局异常处理器。package com.example.moyulingxiapi.handler; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.context.request.WebRequest; import java.io.IOException; import java.util.Date; import java.util.LinkedHashMap; import java.util.Map; Slf4j RestControllerAdvice public class GlobalExceptionHandler { ExceptionHandler(IOException.class) public ResponseEntityObject handleIOException(IOException ex, WebRequest request) { log.error(IO异常: , ex); MapString, Object body new LinkedHashMap(); body.put(timestamp, new Date()); body.put(status, HttpStatus.SERVICE_UNAVAILABLE.value()); body.put(error, Service Unavailable); body.put(message, 上游AI服务通信异常请稍后重试。); body.put(path, request.getDescription(false)); return new ResponseEntity(body, HttpStatus.SERVICE_UNAVAILABLE); } ExceptionHandler(Exception.class) public ResponseEntityObject handleGlobalException(Exception ex, WebRequest request) { log.error(未捕获的异常: , ex); MapString, Object body new LinkedHashMap(); body.put(timestamp, new Date()); body.put(status, HttpStatus.INTERNAL_SERVER_ERROR.value()); body.put(error, Internal Server Error); body.put(message, 服务器内部错误请联系管理员。); body.put(path, request.getDescription(false)); return new ResponseEntity(body, HttpStatus.INTERNAL_SERVER_ERROR); } }此外可以集成Micrometer等工具对API调用次数、延迟、错误率等进行监控便于后续运维和优化。5. 总结通过上面这些步骤我们基本上就完成了一个集成墨语灵犀大模型的SpringBoot智能问答API。从项目搭建、核心服务封装到提供REST接口再到异步、缓存等优化整个流程走下来感觉核心难点不在于SpringBoot本身而在于如何设计一个稳定、高效且易于维护的调用架构。实际开发中可能还会遇到更多细节问题比如如何设计更灵活的提示词Prompt模板、如何实现多轮对话的上下文管理、如何对生成内容进行安全过滤、如何做限流和降级等等。这些都可以在现有的框架上逐步扩展。这次实践给我的感受是用Java生态来做AI应用集成优势在于工程化成熟、工具链完善、团队熟悉度高。虽然Python在AI原型开发上更快捷但当需要构建一个高可用、易维护的企业级服务时SpringBoot这套组合拳还是非常给力的。如果你正在为你的Java项目寻找AI能力集成方案不妨就从这样一个简单的API服务开始尝试。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

更多文章