You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring AI中如何自定义ChatClient所使用的HTTP客户端?

Spring AI中如何自定义ChatClient所使用的HTTP客户端?

我之前刚好踩过这个坑!一开始跟你一样,以为只要定义个CloseableHttpClient的Bean,Spring AI就会自动用上,结果完全没效果。后来研究了下才搞明白:Spring AI的ChatClient本身不直接处理HTTP请求,它是依赖底层的模型客户端(比如OpenAiClient、AzureOpenAiClient这类)来和AI服务通信的,而这些模型客户端默认用RestClient或者WebClient来发起请求。文档里说的“必须配置RestClient和WebClient”,其实就是要给这些模型客户端绑定你自定义的RestClient/WebClient Builder。

一、通过RestClient自定义HTTP客户端(以Apache HttpClient 5为例)

大部分AI模型默认用RestClient来通信,我们先讲这个场景的配置:

1. 配置自定义的Apache HttpClient和RestClient.Builder

首先创建一个RestClient.Builder的Bean,把自定义的Apache HttpClient绑定进去,同时可以加拦截器设置自定义请求头、超时时间这些:

@Configuration
public class SpringAiHttpConfig {

    @Bean
    public RestClient.Builder restClientBuilder() {
        // 1. 配置Apache HttpClient 5,添加自定义拦截器、超时等规则
        CloseableHttpClient customHttpClient = HttpClientBuilder.create()
                // 给所有AI请求加自定义头
                .addInterceptorFirst((HttpRequestInterceptor) (request, context) -> {
                    request.addHeader("X-Custom-Header", "my-custom-value");
                    request.addHeader("X-App-Id", "spring-ai-demo");
                })
                // 设置连接超时时间
                .setConnectTimeout(Timeout.ofSeconds(15))
                // 设置响应超时时间
                .setResponseTimeout(Timeout.ofSeconds(45))
                .build();

        // 2. 把自定义HttpClient绑定到RestClient.Builder
        return RestClient.builder()
                .requestFactory(new HttpComponentsClientHttpRequestFactory(customHttpClient));
    }
}

2. 让模型客户端使用这个自定义的RestClient.Builder

接下来要确保你的AI模型客户端(比如OpenAiClient)用上这个自定义的Builder,比如OpenAI场景的配置:

@Bean
public OpenAiClient openAiClient(RestClient.Builder restClientBuilder, OpenAiApi openAiApi) {
    // 用我们自定义的RestClient.Builder创建模型客户端
    return new OpenAiClient(openAiApi, restClientBuilder);
}

这样ChatClient依赖的OpenAiClient就会用你配置的HTTP客户端发请求,自定义的头和超时设置自然就生效了。

二、如果模型用的是WebClient(流式请求场景常用)

有些模型或者流式对话场景会用WebClient,这时候就需要配置WebClient.Builder的Bean:

@Configuration
public class SpringAiHttpConfig {

    @Bean
    public WebClient.Builder webClientBuilder() {
        // 1. 配置Reactor HttpClient,设置超时规则
        HttpClient reactorHttpClient = HttpClient.create()
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 15000)
                .doOnConnected(conn -> conn
                        .addHandlerLast(new ReadTimeoutHandler(45))
                        .addHandlerLast(new WriteTimeoutHandler(45)));

        // 2. 绑定到WebClient.Builder,同时加拦截器设置自定义头
        return WebClient.builder()
                .clientConnector(new ReactorClientHttpConnector(reactorHttpClient))
                .filter((clientRequest, exchangeFunction) -> {
                    ClientRequest modifiedRequest = ClientRequest.from(clientRequest)
                            .header("X-Custom-Header", "webclient-custom-value")
                            .build();
                    return exchangeFunction.exchange(modifiedRequest);
                });
    }

    // 对应模型客户端的配置,比如Azure OpenAI用WebClient的场景:
    @Bean
    public AzureOpenAiClient azureOpenAiClient(WebClient.Builder webClientBuilder, AzureOpenAiApi azureOpenAiApi) {
        return new AzureOpenAiClient(azureOpenAiApi, webClientBuilder);
    }
}

三、为什么直接定义CloseableHttpClient Bean没用?

这个我之前也疑惑了很久,后来才搞懂:Spring AI的模型客户端默认是自己构建RestClient/WebClient的,不会自动识别容器里单独的CloseableHttpClient。必须把你的自定义HttpClient绑定到RestClient.BuilderWebClient.Builder的Bean里,再让模型客户端使用这个Builder,才能把自定义配置传进去。

四、验证自定义是否生效

你可以把org.springframework.web.client.RestTemplate(用RestClient的场景)或者org.springframework.web.reactive.function.client.WebClient(用WebClient的场景)的日志级别设为DEBUG,就能看到请求里已经带上你加的自定义头,而且用的是你配置的Apache HttpClient了。

火山引擎 最新活动