feat: 集成 Spring AI 框架,实现基础的 AI 写作功能

This commit is contained in:
xiongxiaoyang
2025-02-19 23:44:29 +08:00
parent 295a9096b5
commit 9f71aa4a59
6 changed files with 210 additions and 22 deletions

View File

@ -0,0 +1,83 @@
package io.github.xxyopen.novel.controller.author;
import io.github.xxyopen.novel.core.common.resp.RestResp;
import io.github.xxyopen.novel.core.constant.ApiRouterConsts;
import io.github.xxyopen.novel.core.constant.SystemConfigConsts;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 作家后台-AI模块API控制器
*
* @author xiongxiaoyang
* @date 2025/2/19
*/
@Tag(name = "AiController", description = "作家后台-AI模块")
@SecurityRequirement(name = SystemConfigConsts.HTTP_AUTH_HEADER_NAME)
@RestController
@RequestMapping(ApiRouterConsts.API_AUTHOR_AI_URL_PREFIX)
@RequiredArgsConstructor
public class AuthorAiController {
private final ChatClient chatClient;
/**
* AI扩写
*/
@Operation(summary = "AI扩写接口")
@PostMapping("/expand")
public RestResp<String> expandText(@RequestParam("text") String text, @RequestParam("ratio") Double ratio) {
String prompt = "请将以下文本扩写为原长度的" + ratio/100 + "倍:" + text;
return RestResp.ok(chatClient.prompt()
.user(prompt)
.call()
.content());
}
/**
* AI缩写
*/
@Operation(summary = "AI缩写接口")
@PostMapping("/condense")
public RestResp<String> condenseText(@RequestParam("text") String text, @RequestParam("ratio") Integer ratio) {
String prompt = "请将以下文本缩写为原长度的" + 100/ratio + "分之一:" + text;
return RestResp.ok(chatClient.prompt()
.user(prompt)
.call()
.content());
}
/**
* AI续写
*/
@Operation(summary = "AI续写接口")
@PostMapping("/continue")
public RestResp<String> continueText(@RequestParam("text") String text, @RequestParam("length") Integer length) {
String prompt = "请续写以下文本,续写长度约为" + length + "字:" + text;
return RestResp.ok(chatClient.prompt()
.user(prompt)
.call()
.content());
}
/**
* AI润色
*/
@Operation(summary = "AI润色接口")
@PostMapping("/polish")
public RestResp<String> polishText(@RequestParam("text") String text) {
String prompt = "请润色优化以下文本,保持原意:" + text;
return RestResp.ok(chatClient.prompt()
.user(prompt)
.call()
.content());
}
}

View File

@ -0,0 +1,47 @@
package io.github.xxyopen.novel.core.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestClient;
/**
* Ai 相关配置
*
* @author xiongxiaoyang
* @date 2025/2/19
*/
@Configuration
@Slf4j
public class AiConfig {
/**
* 目的:配置自定义的 RestClientBuilder 对象
* <p>
* 原因Spring AI 框架的 ChatClient 内部通过 RestClientSpring Framework 6 和 Spring Boot 3 中引入) 发起 HTTP REST 请求与远程的大模型服务进行通信,
* 如果项目中没有配置自定义的 RestClientBuilder 对象, 那么在 RestClient 的自动配置类 org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration
* 中配置的 RestClientBuilder 对象会使用 Spring 容器中提供的 HttpMessageConverters 由于本项目中配置了 spring.jackson.generator.write-numbers-as-strings
* = true 所以 Spring 容器中的 HttpMessageConverters 在 RestClient 发起 HTTP REST 请求转换 Java 对象为 JSON 字符串时会自动将 Number 类型的
* Java 对象属性转换为字符串而导致请求参数错误
* <p>
* 示例:"temperature": 0.7 =》"temperature": "0.7"
* {"code":20015,"message":"The parameter is invalid. Please check again.","data":null}
*/
@Bean
public RestClient.Builder restClientBuilder() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
// 连接超时时间
factory.setConnectTimeout(5000);
// 读取超时时间
factory.setReadTimeout(60000);
return RestClient.builder().requestFactory(factory);
}
@Bean
public ChatClient chatClient(ChatClient.Builder chatClientBuilder) {
return chatClientBuilder.build();
}
}

View File

@ -62,6 +62,11 @@ public class ApiRouterConsts {
*/
public static final String SEARCH_URL_PREFIX = "/search";
/**
* AI模块请求路径前缀
*/
public static final String AI_URL_PREFIX = "/ai";
/**
* 前台门户首页API请求路径前缀
*/
@ -94,4 +99,10 @@ public class ApiRouterConsts {
public static final String API_FRONT_SEARCH_URL_PREFIX =
API_FRONT_URL_PREFIX + SEARCH_URL_PREFIX;
/**
* 作家后台AI相关API请求路径前缀
*/
public static final String API_AUTHOR_AI_URL_PREFIX = API_AUTHOR_URL_PREFIX + AI_URL_PREFIX;
}

View File

@ -34,6 +34,18 @@ server:
# 端口号
port: 8888
--- #--------------------- Spring AI 配置----------------------
spring:
ai:
openai:
api-key:
base-url: https://api.siliconflow.cn
chat:
options:
model: deepseek-ai/DeepSeek-R1-Distill-Llama-8B
--- #---------------------数据库配置---------------------------
spring:
datasource: