基于spring-ai生成教学目标
This commit is contained in:
parent
9b90abf8e8
commit
3e1e89c213
@ -15,7 +15,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@EnableFeignClients(basePackages = "com.seer.teach.*.api")
|
@EnableFeignClients(basePackages = "com.seer.teach.*.api")
|
||||||
@SpringBootApplication(scanBasePackages = "com.seer",exclude = QuartzAutoConfiguration.class)
|
@SpringBootApplication(scanBasePackages = "com.seer",exclude = {QuartzAutoConfiguration.class})
|
||||||
@EnableTransactionManagement
|
@EnableTransactionManagement
|
||||||
@EnableAspectJAutoProxy
|
@EnableAspectJAutoProxy
|
||||||
@EnableAsync
|
@EnableAsync
|
||||||
|
|||||||
@ -11,13 +11,8 @@ spring:
|
|||||||
main:
|
main:
|
||||||
allow-bean-definition-overriding: true
|
allow-bean-definition-overriding: true
|
||||||
allow-circular-references: true
|
allow-circular-references: true
|
||||||
mvc:
|
|
||||||
|
|
||||||
profiles:
|
profiles:
|
||||||
active: dev
|
active: dev
|
||||||
mvc:
|
|
||||||
pathmatch:
|
|
||||||
matching-strategy: ant_path_matcher
|
|
||||||
flyway:
|
flyway:
|
||||||
enabled: true
|
enabled: true
|
||||||
locations: classpath:db/mysql
|
locations: classpath:db/mysql
|
||||||
@ -39,6 +34,7 @@ spring:
|
|||||||
server-addr: 192.168.0.39:8848 # 配置中心地址
|
server-addr: 192.168.0.39:8848 # 配置中心地址
|
||||||
file-extension: yaml # 配置文件后缀(yaml/properties)
|
file-extension: yaml # 配置文件后缀(yaml/properties)
|
||||||
namespace: ${spring.profiles.active}
|
namespace: ${spring.profiles.active}
|
||||||
|
|
||||||
#日志
|
#日志
|
||||||
logging:
|
logging:
|
||||||
config: classpath:logback-${spring.profiles.active}.xml
|
config: classpath:logback-${spring.profiles.active}.xml
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
<spring-cloud-alibaba.version>2025.0.0.0</spring-cloud-alibaba.version>
|
<spring-cloud-alibaba.version>2025.0.0.0</spring-cloud-alibaba.version>
|
||||||
|
|
||||||
<spring-ai.version>1.1.2</spring-ai.version>
|
<spring-ai.version>1.1.2</spring-ai.version>
|
||||||
<spring-ai-alibaba.version>1.1.0.0-M5</spring-ai-alibaba.version>
|
<spring-ai-alibaba.version>1.1.0.0-RC2</spring-ai-alibaba.version>
|
||||||
|
|
||||||
|
|
||||||
<!-- 认证 -->
|
<!-- 认证 -->
|
||||||
@ -660,6 +660,12 @@
|
|||||||
<version>${spring-ai-alibaba.version}</version>
|
<version>${spring-ai-alibaba.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud.ai</groupId>
|
||||||
|
<artifactId>spring-ai-alibaba-dashscope</artifactId>
|
||||||
|
<version>${spring-ai-alibaba.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-starter-model-deepseek</artifactId>
|
<artifactId>spring-ai-starter-model-deepseek</artifactId>
|
||||||
@ -668,8 +674,17 @@
|
|||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-starter-model-deepseek</artifactId>
|
<artifactId>spring-ai-deepseek</artifactId>
|
||||||
<version>${spring-ai.version}</version>
|
<version>${spring-ai.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.ai</groupId>
|
||||||
|
<artifactId>spring-ai-openai</artifactId>
|
||||||
|
<version>${spring-ai.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@ -26,17 +26,18 @@
|
|||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.cloud.ai</groupId>
|
<groupId>com.alibaba.cloud.ai</groupId>
|
||||||
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
|
<artifactId>spring-ai-alibaba-dashscope</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-starter-model-openai</artifactId>
|
<artifactId>spring-ai-openai</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-starter-model-deepseek</artifactId>
|
<artifactId>spring-ai-deepseek</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.ai.model.tool.DefaultToolExecutionEligibilityPredicate;
|
import org.springframework.ai.model.tool.DefaultToolExecutionEligibilityPredicate;
|
||||||
import org.springframework.ai.model.tool.ToolCallingManager;
|
import org.springframework.ai.model.tool.ToolCallingManager;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.retry.support.RetryTemplate;
|
import org.springframework.retry.support.RetryTemplate;
|
||||||
import org.springframework.web.client.ResponseErrorHandler;
|
import org.springframework.web.client.ResponseErrorHandler;
|
||||||
import org.springframework.web.client.RestClient;
|
import org.springframework.web.client.RestClient;
|
||||||
@ -24,9 +25,11 @@ public abstract class AbstractAiModelClient implements AiModelClient {
|
|||||||
protected ResponseErrorHandler responseErrorHandler;
|
protected ResponseErrorHandler responseErrorHandler;
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
|
@Qualifier("aiRestClient")
|
||||||
protected RestClient.Builder restClientBuilder;
|
protected RestClient.Builder restClientBuilder;
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
|
@Qualifier("aiWebClient")
|
||||||
protected WebClient.Builder webClientBuilder;
|
protected WebClient.Builder webClientBuilder;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -35,8 +38,7 @@ public abstract class AbstractAiModelClient implements AiModelClient {
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected ToolCallingManager toolCallingManager;
|
protected ToolCallingManager toolCallingManager;
|
||||||
|
|
||||||
@Autowired(required = false)
|
protected ObservationRegistry observationRegistry = ObservationRegistry.create();
|
||||||
protected ObservationRegistry observationRegistry;
|
|
||||||
|
|
||||||
protected final DefaultToolExecutionEligibilityPredicate toolExecutionEligibilityPredicate = new DefaultToolExecutionEligibilityPredicate();
|
protected final DefaultToolExecutionEligibilityPredicate toolExecutionEligibilityPredicate = new DefaultToolExecutionEligibilityPredicate();
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package com.seer.teach.ai.client.model;
|
package com.seer.teach.ai.client.model;
|
||||||
|
|
||||||
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisModel;
|
|
||||||
import com.seer.teach.ai.client.model.config.ModelConfig;
|
import com.seer.teach.ai.client.model.config.ModelConfig;
|
||||||
import org.springframework.ai.audio.tts.TextToSpeechModel;
|
import org.springframework.ai.audio.tts.TextToSpeechModel;
|
||||||
import org.springframework.ai.chat.model.ChatModel;
|
import org.springframework.ai.chat.model.ChatModel;
|
||||||
@ -43,17 +42,6 @@ public interface AiModelClient {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取语音合成模型(Speech Synthesis Model)
|
|
||||||
* 用于将文本转换为语音音频,仅dashscope平台支持
|
|
||||||
*
|
|
||||||
* @param modelConfig 模型配置
|
|
||||||
* @return 语音合成模型实例的Optional包装
|
|
||||||
*/
|
|
||||||
default Optional<SpeechSynthesisModel> createSpeechSynthesisModel(ModelConfig modelConfig) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取文本转语音模型(Text To Speech Model)
|
* 获取文本转语音模型(Text To Speech Model)
|
||||||
* 用于将文本转换为语音输出,支持多种平台
|
* 用于将文本转换为语音输出,支持多种平台
|
||||||
|
|||||||
@ -0,0 +1,99 @@
|
|||||||
|
package com.seer.teach.ai.client.model.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.HttpRequest;
|
||||||
|
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||||
|
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||||
|
import org.springframework.http.client.ClientHttpResponse;
|
||||||
|
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||||
|
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||||
|
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||||
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
|
import org.springframework.web.client.RestClient;
|
||||||
|
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DashScope API 配置类
|
||||||
|
* 用于配置restClient以正确处理聊天完成请求
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
public class DashScopeClientConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建用于DashScope API的RestClient
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public RestClient aiRestClient() {
|
||||||
|
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json()
|
||||||
|
.modules(new JavaTimeModule())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(objectMapper);
|
||||||
|
|
||||||
|
return RestClient.builder()
|
||||||
|
.requestInterceptor(new LoggingInterceptor())
|
||||||
|
.messageConverters(converters -> converters.add(converter))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建用于DashScope API的WebClient并启用日志
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public WebClient aiWebClient() {
|
||||||
|
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json()
|
||||||
|
.modules(new JavaTimeModule())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return WebClient.builder()
|
||||||
|
.codecs(configurer -> configurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper)))
|
||||||
|
.codecs(configurer -> configurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(objectMapper)))
|
||||||
|
.filter(ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
|
||||||
|
log.info("Request: {} {}", clientRequest.method(), clientRequest.url());
|
||||||
|
clientRequest.headers().forEach((name, values) ->
|
||||||
|
values.forEach(value -> log.info("{}={}", name, value)));
|
||||||
|
return Mono.just(clientRequest);
|
||||||
|
}))
|
||||||
|
.filter(ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
|
||||||
|
log.info("Response Status: {}", clientResponse.statusCode());
|
||||||
|
clientResponse.headers().asHttpHeaders().forEach((name, values) ->
|
||||||
|
values.forEach(value -> log.info("{}={}", name, value)));
|
||||||
|
return Mono.just(clientResponse);
|
||||||
|
}))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class LoggingInterceptor implements ClientHttpRequestInterceptor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientHttpResponse intercept(
|
||||||
|
HttpRequest request,
|
||||||
|
byte[] body,
|
||||||
|
ClientHttpRequestExecution execution) throws IOException {
|
||||||
|
|
||||||
|
// 记录请求信息
|
||||||
|
log.info("HTTP请求方法: {}", request.getMethod());
|
||||||
|
log.info("HTTP请求URL: {}", request.getURI());
|
||||||
|
log.info("HTTP请求头: {}", request.getHeaders());
|
||||||
|
if (body.length > 0) {
|
||||||
|
log.info("HTTP请求体: {}", new String(body, StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行请求
|
||||||
|
ClientHttpResponse response = execution.execute(request, body);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,14 +1,10 @@
|
|||||||
package com.seer.teach.ai.client.model.dashscope;
|
package com.seer.teach.ai.client.model.dashscope;
|
||||||
|
|
||||||
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeChatProperties;
|
|
||||||
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeConnectionProperties;
|
|
||||||
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeEmbeddingProperties;
|
|
||||||
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
|
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
|
||||||
import com.alibaba.cloud.ai.dashscope.api.DashScopeAudioSpeechApi;
|
import com.alibaba.cloud.ai.dashscope.api.DashScopeAudioSpeechApi;
|
||||||
import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi;
|
import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi;
|
||||||
import com.alibaba.cloud.ai.dashscope.audio.DashScopeAudioSpeechModel;
|
import com.alibaba.cloud.ai.dashscope.audio.DashScopeAudioSpeechModel;
|
||||||
import com.alibaba.cloud.ai.dashscope.audio.DashScopeAudioSpeechOptions;
|
import com.alibaba.cloud.ai.dashscope.audio.DashScopeAudioSpeechOptions;
|
||||||
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisModel;
|
|
||||||
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
|
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
|
||||||
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
|
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
|
||||||
import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel;
|
import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel;
|
||||||
@ -17,12 +13,11 @@ import com.alibaba.cloud.ai.dashscope.image.DashScopeImageOptions;
|
|||||||
import com.seer.teach.ai.client.model.AbstractAiModelClient;
|
import com.seer.teach.ai.client.model.AbstractAiModelClient;
|
||||||
import com.seer.teach.ai.client.model.config.ModelConfig;
|
import com.seer.teach.ai.client.model.config.ModelConfig;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.ai.audio.tts.TextToSpeechModel;
|
||||||
import org.springframework.ai.chat.model.ChatModel;
|
import org.springframework.ai.chat.model.ChatModel;
|
||||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||||
import org.springframework.ai.document.MetadataMode;
|
|
||||||
import org.springframework.ai.embedding.EmbeddingModel;
|
import org.springframework.ai.embedding.EmbeddingModel;
|
||||||
import org.springframework.ai.image.ImageModel;
|
import org.springframework.ai.image.ImageModel;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -40,14 +35,9 @@ import java.util.Optional;
|
|||||||
@Component
|
@Component
|
||||||
public class DashScopeModelClient extends AbstractAiModelClient {
|
public class DashScopeModelClient extends AbstractAiModelClient {
|
||||||
|
|
||||||
private DashScopeConnectionProperties connectionProperties;
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private DashScopeChatProperties chatProperties;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPlatformName() {
|
public String getPlatformName() {
|
||||||
return "dashscope";
|
return "aliyun_bailian";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -125,17 +115,15 @@ public class DashScopeModelClient extends AbstractAiModelClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<SpeechSynthesisModel> createSpeechSynthesisModel(ModelConfig modelConfig) {
|
public Optional<TextToSpeechModel> createTextToSpeechModel(ModelConfig modelConfig) {
|
||||||
try {
|
try {
|
||||||
DashScopeAudioSpeechApi audioSpeechApi = new DashScopeAudioSpeechApi(modelConfig.getApiKey(), modelConfig.getUrl());
|
DashScopeAudioSpeechApi audioSpeechApi = new DashScopeAudioSpeechApi(modelConfig.getApiKey(), modelConfig.getUrl());
|
||||||
|
|
||||||
DashScopeAudioSpeechOptions options = DashScopeAudioSpeechOptions.builder()
|
DashScopeAudioSpeechOptions options = DashScopeAudioSpeechOptions.builder()
|
||||||
.model(modelConfig.getModel())
|
.model(modelConfig.getModel())
|
||||||
.requestText(DashScopeAudioSpeechApi.RequestTextType.PLAIN_TEXT)
|
|
||||||
.voice("longyingxiao")
|
.voice("longyingxiao")
|
||||||
.build();
|
.build();
|
||||||
DashScopeAudioSpeechModel speechSynthesisModel = new DashScopeAudioSpeechModel(audioSpeechApi, options, retryTemplate);
|
DashScopeAudioSpeechModel speechSynthesisModel = new DashScopeAudioSpeechModel(audioSpeechApi, options, retryTemplate);
|
||||||
|
|
||||||
return Optional.of(speechSynthesisModel);
|
return Optional.of(speechSynthesisModel);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("创建DashScope语音合成模型失败", e);
|
log.error("创建DashScope语音合成模型失败", e);
|
||||||
@ -147,10 +135,9 @@ public class DashScopeModelClient extends AbstractAiModelClient {
|
|||||||
@Override
|
@Override
|
||||||
public Optional<EmbeddingModel> createEmbeddingModel(ModelConfig modelConfig) {
|
public Optional<EmbeddingModel> createEmbeddingModel(ModelConfig modelConfig) {
|
||||||
try {
|
try {
|
||||||
DashScopeEmbeddingProperties embeddingProperties = new DashScopeEmbeddingProperties();
|
|
||||||
DashScopeApi dashScopeApi = createDashScopeApi(modelConfig.getApiKey(), modelConfig.getUrl());
|
DashScopeApi dashScopeApi = createDashScopeApi(modelConfig.getApiKey(), modelConfig.getUrl());
|
||||||
|
|
||||||
DashScopeEmbeddingModel embeddingModel = new DashScopeEmbeddingModel(dashScopeApi, MetadataMode.EMBED, embeddingProperties.getOptions(), retryTemplate, observationRegistry);
|
DashScopeEmbeddingModel embeddingModel = new DashScopeEmbeddingModel(dashScopeApi);
|
||||||
|
|
||||||
return Optional.of(embeddingModel);
|
return Optional.of(embeddingModel);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -162,11 +149,10 @@ public class DashScopeModelClient extends AbstractAiModelClient {
|
|||||||
/**
|
/**
|
||||||
* 创建DashScope API实例
|
* 创建DashScope API实例
|
||||||
*/
|
*/
|
||||||
private DashScopeApi createDashScopeApi(String apiKey, String baseUrl) {
|
private DashScopeApi createDashScopeApi(String apiKey, String completionsPath) {
|
||||||
DashScopeApi.Builder builder = DashScopeApi.builder()
|
DashScopeApi.Builder builder = DashScopeApi.builder()
|
||||||
.apiKey(apiKey)
|
.apiKey(apiKey)
|
||||||
.baseUrl(baseUrl);
|
.baseUrl("https://dashscope.aliyuncs.com");
|
||||||
|
|
||||||
// 如果有可用的客户端构建器,添加它们
|
// 如果有可用的客户端构建器,添加它们
|
||||||
if (webClientBuilder != null) {
|
if (webClientBuilder != null) {
|
||||||
builder.webClientBuilder(webClientBuilder);
|
builder.webClientBuilder(webClientBuilder);
|
||||||
|
|||||||
@ -6,13 +6,9 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.ai.audio.tts.TextToSpeechModel;
|
import org.springframework.ai.audio.tts.TextToSpeechModel;
|
||||||
import org.springframework.ai.chat.model.ChatModel;
|
import org.springframework.ai.chat.model.ChatModel;
|
||||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||||
import org.springframework.ai.document.MetadataMode;
|
|
||||||
import org.springframework.ai.embedding.EmbeddingModel;
|
import org.springframework.ai.embedding.EmbeddingModel;
|
||||||
import org.springframework.ai.image.ImageModel;
|
import org.springframework.ai.image.ImageModel;
|
||||||
import org.springframework.ai.model.SimpleApiKey;
|
import org.springframework.ai.model.SimpleApiKey;
|
||||||
import org.springframework.ai.model.openai.autoconfigure.OpenAiAudioSpeechProperties;
|
|
||||||
import org.springframework.ai.model.openai.autoconfigure.OpenAiChatProperties;
|
|
||||||
import org.springframework.ai.model.openai.autoconfigure.OpenAiEmbeddingProperties;
|
|
||||||
import org.springframework.ai.openai.OpenAiAudioSpeechModel;
|
import org.springframework.ai.openai.OpenAiAudioSpeechModel;
|
||||||
import org.springframework.ai.openai.OpenAiChatModel;
|
import org.springframework.ai.openai.OpenAiChatModel;
|
||||||
import org.springframework.ai.openai.OpenAiChatOptions;
|
import org.springframework.ai.openai.OpenAiChatOptions;
|
||||||
@ -131,8 +127,7 @@ public class OpenAIModelClient extends AbstractAiModelClient {
|
|||||||
.responseErrorHandler(responseErrorHandler)
|
.responseErrorHandler(responseErrorHandler)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
OpenAiAudioSpeechProperties properties = new OpenAiAudioSpeechProperties();
|
TextToSpeechModel textToSpeechModel = new OpenAiAudioSpeechModel(audioApi);
|
||||||
TextToSpeechModel textToSpeechModel = new OpenAiAudioSpeechModel(audioApi, properties.getOptions(), retryTemplate);
|
|
||||||
return Optional.of(textToSpeechModel);
|
return Optional.of(textToSpeechModel);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("创建OpenAI文本转语音模型失败", e);
|
log.error("创建OpenAI文本转语音模型失败", e);
|
||||||
@ -144,8 +139,7 @@ public class OpenAIModelClient extends AbstractAiModelClient {
|
|||||||
public Optional<EmbeddingModel> createEmbeddingModel(ModelConfig modelConfig) {
|
public Optional<EmbeddingModel> createEmbeddingModel(ModelConfig modelConfig) {
|
||||||
try {
|
try {
|
||||||
OpenAiApi openAiApi = createOpenAiApi(modelConfig.getApiKey(), modelConfig.getUrl());
|
OpenAiApi openAiApi = createOpenAiApi(modelConfig.getApiKey(), modelConfig.getUrl());
|
||||||
OpenAiEmbeddingProperties properties = new OpenAiEmbeddingProperties();
|
EmbeddingModel embeddingModel = new OpenAiEmbeddingModel(openAiApi);
|
||||||
EmbeddingModel embeddingModel = new OpenAiEmbeddingModel(openAiApi, MetadataMode.EMBED,properties.getOptions(), retryTemplate);
|
|
||||||
return Optional.of(embeddingModel);
|
return Optional.of(embeddingModel);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("创建OpenAI嵌入模型失败", e);
|
log.error("创建OpenAI嵌入模型失败", e);
|
||||||
@ -157,8 +151,6 @@ public class OpenAIModelClient extends AbstractAiModelClient {
|
|||||||
return OpenAiApi.builder()
|
return OpenAiApi.builder()
|
||||||
.baseUrl(baseUrl)
|
.baseUrl(baseUrl)
|
||||||
.apiKey(new SimpleApiKey(apiKey))
|
.apiKey(new SimpleApiKey(apiKey))
|
||||||
.completionsPath(OpenAiChatProperties.DEFAULT_COMPLETIONS_PATH)
|
|
||||||
.embeddingsPath(OpenAiEmbeddingProperties.DEFAULT_EMBEDDINGS_PATH)
|
|
||||||
.restClientBuilder(restClientBuilder)
|
.restClientBuilder(restClientBuilder)
|
||||||
.webClientBuilder(webClientBuilder).build();
|
.webClientBuilder(webClientBuilder).build();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,6 +38,12 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>seer-teacher-ai</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
<artifactId>okhttp</artifactId>
|
<artifactId>okhttp</artifactId>
|
||||||
|
|||||||
@ -2,11 +2,14 @@ package com.seer.teach.admin.service.impl;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.seer.teach.ai.service.AiChatModelService;
|
||||||
import com.seer.teach.common.constants.CommonConstant;
|
import com.seer.teach.common.constants.CommonConstant;
|
||||||
import com.seer.teach.common.entity.BaseEntity;
|
import com.seer.teach.common.entity.BaseEntity;
|
||||||
import com.seer.teach.teacher.service.AiModelCallService;
|
import com.seer.teach.teacher.service.AiModelCallService;
|
||||||
import com.seer.teach.teacher.service.platform.LlmResponse;
|
import com.seer.teach.teacher.service.platform.LlmResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.ai.chat.model.ChatResponse;
|
||||||
|
import org.springframework.ai.chat.model.Generation;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
@ -16,6 +19,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,6 +45,9 @@ public abstract class AbstractGenerationService<T, R, E extends BaseEntity> {
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected TransactionTemplate transactionTemplate;
|
protected TransactionTemplate transactionTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected AiChatModelService chatModelService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查当前线程是否被中断
|
* 检查当前线程是否被中断
|
||||||
*
|
*
|
||||||
@ -78,6 +85,10 @@ public abstract class AbstractGenerationService<T, R, E extends BaseEntity> {
|
|||||||
*/
|
*/
|
||||||
protected LlmResponse callLLM(String scenarioCode, String prompt, Map<String, Object> params, Integer userId) {
|
protected LlmResponse callLLM(String scenarioCode, String prompt, Map<String, Object> params, Integer userId) {
|
||||||
log.info("调用大模型,场景编码: {}, 提示词长度: {}", scenarioCode, prompt.length());
|
log.info("调用大模型,场景编码: {}, 提示词长度: {}", scenarioCode, prompt.length());
|
||||||
|
//ChatResponse chatResponse = chatModelService.chatMessage(scenarioCode, prompt);
|
||||||
|
LlmResponse response = new LlmResponse();
|
||||||
|
//Generation result = chatResponse.getResult();
|
||||||
|
|
||||||
return aiModelCallService.callModel(scenarioCode, prompt, params, userId);
|
return aiModelCallService.callModel(scenarioCode, prompt, params, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user