0
点赞
收藏
分享

微信扫一扫

调用AI模型时,如何处理请求超时和错误?

在Spring AI中调用AI模型时,处理请求超时和错误需要结合Spring的异常处理机制和Spring AI自身的配置选项。以下是具体的实现方法和最佳实践:

1. 超时配置(预防超时)

首先通过配置避免无限制等待,Spring AI支持对不同AI服务设置超时参数:

全局超时配置

application.propertiesapplication.yml中设置:

# OpenAI 超时配置(毫秒)
spring.ai.openai.timeout=30000  # 30秒

# 更精细的超时控制(部分服务支持)
spring.ai.openai.chat.timeout=20000  # 聊天模型单独设置超时
spring.ai.openai.image.timeout=60000  # 图像生成超时更长

代码中动态设置超时

对个别请求需要特殊超时设置时,可通过RequestOptions实现:

import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.stereotype.Service;

@Service
public class AIService {
    private final ChatClient chatClient;

    public AIService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    public String generateWithTimeout(String prompt) {
        // 为当前请求设置单独的超时(10秒)
        OpenAiChatOptions options = OpenAiChatOptions.builder()
                .withTimeout(10000)
                .build();

        return chatClient.prompt(
                new Prompt(prompt, options)  // 将选项传入prompt
            ).call()
            .content();
    }
}

2. 异常处理(捕获和处理错误)

Spring AI会抛出特定异常,可通过try-catch捕获并处理:

常见异常类型
  • AiException:所有Spring AI相关异常的父类
  • AiTimeoutException:超时异常
  • AiServiceException:AI服务返回错误(如API密钥无效、模型不存在)
  • AiResponseException:响应格式错误或解析失败
同步调用的异常处理

import org.springframework.ai.AiException;
import org.springframework.ai.AiTimeoutException;
import org.springframework.ai.chat.ChatClient;
import org.springframework.stereotype.Service;

@Service
public class AIService {
    private final ChatClient chatClient;

    public AIService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    public String safeGenerate(String userInput) {
        try {
            return chatClient.prompt()
                    .user(userInput)
                    .call()
                    .content();
        } catch (AiTimeoutException e) {
            // 处理超时:返回友好提示或执行重试
            return "请求超时,请稍后再试";
        } catch (AiException e) {
            // 处理其他AI相关错误(如API密钥无效、模型错误)
            log.error("AI调用失败: {}", e.getMessage());
            return "服务暂时不可用,请稍后尝试";
        } catch (Exception e) {
            // 处理其他未知错误
            log.error("未知错误: {}", e.getMessage());
            return "系统错误,请联系管理员";
        }
    }
}

流式调用的异常处理(响应式)

流式调用返回Flux,需通过响应式操作符处理错误:

import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

@Service
public class StreamAIService {
    private final ChatClient chatClient;

    public StreamAIService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    public Flux<String> safeStreamGenerate(String userInput) {
        return chatClient.stream(new UserMessage(userInput))
                .map(response -> response.getResult().getOutput().getContent())
                // 响应式错误处理
                .onErrorResume(AiTimeoutException.class, e -> {
                    // 超时后返回错误提示
                    return Flux.just("请求超时,请稍后再试");
                })
                .onErrorResume(AiException.class, e -> {
                    log.error("AI流式调用失败: {}", e.getMessage());
                    return Flux.just("服务异常,请稍后尝试");
                })
                .onErrorResume(e -> {
                    log.error("未知错误: {}", e.getMessage());
                    return Flux.just("系统错误,请联系管理员");
                });
    }
}

3. 高级策略:重试机制

结合Spring的@Retryable实现失败重试(需添加spring-retry依赖):

步骤1:添加依赖

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

步骤2:启用重试

在启动类添加@EnableRetry

import org.springframework.retry.annotation.EnableRetry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableRetry
public class AiApplication {
    public static void main(String[] args) {
        SpringApplication.run(AiApplication.class, args);
    }
}

步骤3:在服务方法上使用重试

import org.springframework.retry.annotation.Retryable;
import org.springframework.retry.annotation.Backoff;
import org.springframework.stereotype.Service;

@Service
public class RetryAIService {
    private final ChatClient chatClient;

    public RetryAIService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    // 对超时和服务异常进行重试,最多3次,每次间隔1秒
    @Retryable(
        value = {AiTimeoutException.class, AiServiceException.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 1000)  // 重试间隔1秒
    )
    public String generateWithRetry(String input) {
        return chatClient.prompt()
                .user(input)
                .call()
                .content();
    }

    // 重试耗尽后执行的方法(可选)
    @Recover
    public String recover(AiException e, String input) {
        log.error("重试耗尽,最终失败: {}", e.getMessage());
        return "多次尝试失败,请稍后再试";
    }
}

4. 错误日志与监控

建议记录详细错误日志,便于排查问题:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
public class AIService {
    private static final Logger log = LoggerFactory.getLogger(AIService.class);

    public String generate(String input) {
        try {
            // 调用逻辑
        } catch (AiException e) {
            // 记录错误详情(包括请求参数,注意脱敏)
            log.error("AI调用失败,输入: {}, 错误: {}", 
                    input.substring(0, 50),  // 只记录部分输入,避免敏感信息
                    e.getMessage(), 
                    e);  // 打印完整堆栈
            return "服务异常";
        }
    }
}

总结

处理超时和错误的核心流程:

  1. 预防:通过配置合理的超时参数,避免无限等待
  2. 捕获:使用try-catch(同步)或onErrorResume(流式)捕获异常
  3. 恢复:返回友好提示,或通过重试机制尝试恢复
  4. 监控:记录详细日志,便于问题排查

根据业务场景调整策略,例如:

  • 对实时性要求高的场景(如聊天):缩短超时时间,不重试
  • 对成功率要求高的场景(如批量处理):延长超时,增加重试次数
举报

相关推荐

0 条评论