package jnpf.config; import com.unfbx.chatgpt.OpenAiClient; import com.unfbx.chatgpt.function.KeyRandomStrategy; import com.unfbx.chatgpt.function.KeyStrategyFunction; import com.unfbx.chatgpt.interceptor.DefaultOpenAiAuthInterceptor; import com.unfbx.chatgpt.interceptor.OpenAiAuthInterceptor; import jnpf.constants.AiConstants; import jnpf.service.OpenAiService; import jnpf.service.impl.DefaultOpenAiServiceImpl; import jnpf.service.impl.DisabledOpenAiServiceImpl; import jnpf.util.AiLimitUtil; import jnpf.util.StringUtil; import okhttp3.Authenticator; import okhttp3.OkHttpClient; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.net.InetSocketAddress; import java.net.PasswordAuthentication; import java.net.Proxy; import java.util.concurrent.TimeUnit; /** * AI客户端 自动配置 * * @author JNPF开发平台组 * @copyright 引迈信息技术有限公司 * @date 2024/10/9 14:03 */ @Configuration(proxyBeanMethods = false) public class AiAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnProperty(prefix = AiConstants.CONFIGURATION_PREFIX, name = "enabled", havingValue = "false", matchIfMissing = true) public OpenAiService getDisabledOpenAiService() { return new DisabledOpenAiServiceImpl(); } @Configuration(proxyBeanMethods = false) @ConditionalOnProperty(prefix = AiConstants.CONFIGURATION_PREFIX, name = "enabled", havingValue = "true") public static class AiEnabledConfiguration{ @Bean @ConfigurationProperties(prefix = AiConstants.CONFIGURATION_PREFIX) public AiProperties getAiProperties() { return new AiProperties(); } @Bean public OpenAiService getDefaultOpenAiService(OpenAiClient openAiClient, AiProperties aiProperties) { return new DefaultOpenAiServiceImpl(openAiClient, aiProperties); } @Bean public AiLimitUtil getAiLimitUtil(AiProperties aiProperties) { return new AiLimitUtil(aiProperties); } @Bean @ConditionalOnMissingBean public OpenAiClient getOpenAiClient(@Qualifier(AiConstants.DEFAULT_HTTP_CLIENT_BEAN_NAME) OkHttpClient okHttpClient , KeyStrategyFunction keyStrategyFunction, OpenAiAuthInterceptor authInterceptor, AiProperties aiProperties) { String apiHost = aiProperties.getApiHost(); // 需要以 / 结尾 if(!apiHost.isEmpty() && !apiHost.endsWith("/")){ apiHost +="/"; } // 构造openAiClient return OpenAiClient.builder() .apiHost(apiHost) .apiKey(aiProperties.getApiKey()) .keyStrategy(keyStrategyFunction) .authInterceptor(authInterceptor) .okHttpClient(okHttpClient) .build(); } /*@Bean @ConditionalOnMissingBean public OpenAiStreamClient getOpenAiStreamClient(@Qualifier(AiConstants.DEFAULT_HTTP_CLIENT_BEAN_NAME) OkHttpClient okHttpClient , KeyStrategyFunction keyStrategyFunction, OpenAiAuthInterceptor authInterceptor, AiProperties aiProperties) { String apiHost = aiProperties.getApiHost(); // 需要以 / 结尾 if(!apiHost.isEmpty() && !apiHost.endsWith("/")){ apiHost +="/"; } // 构造openAiClient return OpenAiStreamClient.builder() .apiHost(apiHost) .apiKey(aiProperties.getApiKey()) .keyStrategy(keyStrategyFunction) .authInterceptor(authInterceptor) .okHttpClient(okHttpClient) .build(); }*/ /** * 多Key选择策略 */ @Bean @ConditionalOnMissingBean public KeyStrategyFunction getDefaultOpenAiKeyStrategyFunction() { return new KeyRandomStrategy(); } /** * 认证拦截器 * @see com.unfbx.chatgpt.interceptor.DynamicKeyOpenAiAuthInterceptor 动态移除无效Key */ @Bean @ConditionalOnMissingBean public OpenAiAuthInterceptor getDefaultOpenAiAuthInterceptor() { return new DefaultOpenAiAuthInterceptor(); } /** * 默认okhttpclient */ @Bean(name = AiConstants.DEFAULT_HTTP_CLIENT_BEAN_NAME) @ConditionalOnMissingBean(name = AiConstants.DEFAULT_HTTP_CLIENT_BEAN_NAME) public OkHttpClient getDefaultOpenAiOkHttpClient(AiProperties aiProperties) { OkHttpClient.Builder builder = new OkHttpClient .Builder(); if(aiProperties.getProxy() != null && StringUtil.isNotEmpty(aiProperties.getProxy().getHost()) && aiProperties.getProxy().getPort() != null){ // 设置代理 builder.proxy(new Proxy(aiProperties.getProxy().getType(), new InetSocketAddress(aiProperties.getProxy().getHost(), aiProperties.getProxy().getPort()))); // 设置代理认证 if(StringUtil.isNotEmpty(aiProperties.getProxy().getUsername()) && StringUtil.isNotEmpty(aiProperties.getProxy().getPassword())){ builder.proxyAuthenticator(Authenticator.JAVA_NET_AUTHENTICATOR); java.net.Authenticator.setDefault(new java.net.Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { // 返回代理的用户名和密码 return new PasswordAuthentication(aiProperties.getProxy().getUsername(), aiProperties.getProxy().getPassword().toCharArray()); } }); } } /*try { // 创建一个信任所有证书的 TrustManager final TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } } }; // 安装所有信任管理器 final SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); // 创建 OkHttpClient 并配置 SSL socket factory 和 hostname verifier final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); // 信任所有证书 builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]); builder.hostnameVerifier((hostname, session) -> true); } catch (Exception e) { throw new RuntimeException(e); }*/ return builder .callTimeout(aiProperties.getTimeout(), TimeUnit.SECONDS) .connectTimeout(aiProperties.getTimeout(), TimeUnit.SECONDS) .writeTimeout(aiProperties.getTimeout(), TimeUnit.SECONDS) .readTimeout(aiProperties.getTimeout(), TimeUnit.SECONDS) .build(); } } }