13-Week2项目优化

4 阅读8分钟

从能用到好用,从演示到生产,这一步是很多AI应用项目的分水岭。本文通过四个版本的迭代,展示如何将一个原型级的AI代码审查服务优化为生产级应用,性能提升100倍,成本降低90%。

时间:45分钟 | 难度:⭐⭐⭐⭐ | Week 2 Day 13


📚 学习目标

  • 理解原型代码的性能瓶颈和优化方向
  • 掌握缓存策略的设计和实现,提升40000倍性能
  • 学会使用并行处理优化AI调用,提升50%效率
  • 实现生产级的错误处理、重试和熔断机制
  • 掌握AI应用的成本优化三大杠杆
  • 建立生产部署的完整检查清单

🚀 快速入门:为什么需要优化?

原型版的问题

你的v1版本已经工作了,演示效果不错,但是:

💰 成本问题
- 每次代码审查调用GPT-4:$0.03
- 每天1000次审查 = $30/天 = $900/月
- 很多是重复的代码片段

⏱️ 性能问题
- 平均响应时间:8秒
- P95响应时间:15秒
- 用户体验差

🔥 可靠性问题
- API失败率:2%(每50次就有1次失败)
- 没有重试机制
- 没有降级方案

优化后的效果

✅ v4生产版
- 平均响应时间:200ms(缓存命中)/ 4秒(未命中)
- 成本降低:90%(缓存+模型优化)
- 可用性:99.9%(重试+熔断)
- 可观测性:完整的metrics和tracing

🎯 深度讲解 - 四个版本的进化

1️⃣ v1:原型版 - 能用但慢

代码实现

package com.example.codereview.v1;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import org.springframework.stereotype.Service;

/**
 * v1版本:最简单的实现
 * 特点:能用,但慢、贵、不可靠
 */
@Service
public class CodeReviewServiceV1 {

    private final ChatLanguageModel model;

    public CodeReviewServiceV1() {
        this.model = OpenAiChatModel.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .modelName("gpt-4")  // 最贵的模型
            .build();
    }

    /**
     * 审查代码
     * 问题:每次都调用API,没有缓存
     */
    public String reviewCode(String code) {
        String prompt = String.format(
            "请审查以下Java代码,指出潜在问题:\n\n%s",
            code
        );

        // 直接调用,没有错误处理
        return model.generate(prompt);
    }
}

控制器

package com.example.codereview.v1;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/v1/review")
public class CodeReviewControllerV1 {

    private final CodeReviewServiceV1 service;

    public CodeReviewControllerV1(CodeReviewServiceV1 service) {
        this.service = service;
    }

    @PostMapping
    public String review(@RequestBody String code) {
        // 没有参数验证、异常处理
        return service.reviewCode(code);
    }
}

性能指标

📊 v1性能数据
├─ 平均响应时间:8000ms
├─ P95响应时间:15000ms
├─ 成本/请求:$0.03
├─ 失败率:2%
└─ 缓存命中率:0%

2️⃣ v2:缓存优化 - 提升40000倍

为什么需要缓存?

分析发现:
- 60%的代码审查请求是重复的
- 相同的代码片段被反复提交
- 审查结果是确定性的(相同输入→相同输出)

优化思路:
- 使用Spring Cache缓存审查结果
- Key = code的hash值
- 缓存命中时直接返回,避免API调用

缓存配置

package com.example.codereview.v2.config;

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

/**
 * 缓存配置
 * 使用Caffeine作为本地缓存
 */
@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager("code-reviews");
        cacheManager.setCaffeine(Caffeine.newBuilder()
            .maximumSize(10000)           // 最多缓存10000条
            .expireAfterWrite(24, TimeUnit.HOURS)  // 24小时过期
            .recordStats());              // 记录统计信息
        return cacheManager;
    }
}

服务实现

package com.example.codereview.v2;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * v2版本:添加缓存
 * 性能提升:40000倍(缓存命中时从8s降到0.2ms)
 */
@Service
public class CodeReviewServiceV2 {

    private final ChatLanguageModel model;

    public CodeReviewServiceV2() {
        this.model = OpenAiChatModel.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .modelName("gpt-4")
            .build();
    }

    /**
     * 审查代码(带缓存)
     * Key使用代码的hashCode,相同代码返回缓存结果
     */
    @Cacheable(value = "code-reviews", key = "#code.hashCode()")
    public String reviewCode(String code) {
        System.out.println("🔥 Cache miss - 调用AI模型");

        String prompt = String.format(
            "请审查以下Java代码,指出潜在问题:\n\n%s",
            code
        );

        return model.generate(prompt);
    }
}

缓存监控

package com.example.codereview.v2;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.stats.CacheStats;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.stereotype.Service;

/**
 * 缓存统计服务
 */
@Service
public class CacheStatsService {

    private final CacheManager cacheManager;

    public CacheStatsService(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    /**
     * 获取缓存统计
     */
    public CacheMetrics getMetrics() {
        CaffeineCache caffeineCache = (CaffeineCache) cacheManager.getCache("code-reviews");
        Cache<Object, Object> nativeCache = caffeineCache.getNativeCache();
        CacheStats stats = nativeCache.stats();

        long totalRequests = stats.hitCount() + stats.missCount();
        double hitRate = totalRequests == 0 ? 0 : (double) stats.hitCount() / totalRequests;

        return new CacheMetrics(
            stats.hitCount(),
            stats.missCount(),
            hitRate,
            nativeCache.estimatedSize()
        );
    }

    public record CacheMetrics(
        long hitCount,
        long missCount,
        double hitRate,
        long size
    ) {}
}

性能对比

📊 v2性能数据(60%缓存命中率)
├─ 缓存命中响应:0.2ms(提升40000倍)
├─ 缓存未命中响应:8000ms(与v1相同)
├─ 平均响应时间:3200ms(0.6*0.2 + 0.4*8000)
├─ 成本/请求:$0.012(降低60%)
└─ 缓存命中率:60%

💡 关键收益:
- 成本立即降低60%
- 60%的请求响应时间从8s降到0.2ms
- 减少了60%的API调用,降低限流风险

3️⃣ v3:并行优化 - 提升50%

问题分析

当前流程(串行):
1. 安全检查      → 3秒
2. 性能检查      → 3秒
3. 代码风格检查   → 2秒
总计:8秒

优化方案(并行):
同时执行三个检查,总时间 = max(3,3,2) = 3秒
理论提升:8s → 3s,提升62.5%

并行服务实现

package com.example.codereview.v3;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.concurrent.CompletableFuture;

/**
 * v3版本:并行优化
 * 多个检查项并行执行,提升50%性能
 */
@Service
public class CodeReviewServiceV3 {

    private final ChatLanguageModel model;

    public CodeReviewServiceV3() {
        this.model = OpenAiChatModel.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .modelName("gpt-4")
            .build();
    }

    /**
     * 并行审查代码
     */
    @Cacheable(value = "code-reviews", key = "#code.hashCode()")
    public String reviewCode(String code) {
        // 并行执行三个检查
        CompletableFuture<String> securityCheck = checkSecurity(code);
        CompletableFuture<String> performanceCheck = checkPerformance(code);
        CompletableFuture<String> styleCheck = checkStyle(code);

        // 等待所有检查完成
        CompletableFuture.allOf(securityCheck, performanceCheck, styleCheck).join();

        // 组合结果
        return formatReviewResult(
            securityCheck.join(),
            performanceCheck.join(),
            styleCheck.join()
        );
    }

    /**
     * 安全检查(异步)
     */
    @Async
    public CompletableFuture<String> checkSecurity(String code) {
        return CompletableFuture.supplyAsync(() -> {
            String prompt = String.format(
                "检查以下代码的安全问题(SQL注入、XSS等):\n\n%s",
                code
            );
            return model.generate(prompt);
        });
    }

    /**
     * 性能检查(异步)
     */
    @Async
    public CompletableFuture<String> checkPerformance(String code) {
        return CompletableFuture.supplyAsync(() -> {
            String prompt = String.format(
                "检查以下代码的性能问题(N+1查询、内存泄漏等):\n\n%s",
                code
            );
            return model.generate(prompt);
        });
    }

    /**
     * 代码风格检查(异步)
     */
    @Async
    public CompletableFuture<String> checkStyle(String code) {
        return CompletableFuture.supplyAsync(() -> {
            String prompt = String.format(
                "检查以下代码的风格问题(命名、注释、可读性等):\n\n%s",
                code
            );
            return model.generate(prompt);
        });
    }

    /**
     * 格式化审查结果
     */
    private String formatReviewResult(String security, String performance, String style) {
        return String.format("""
            ## 代码审查报告

            ### 🔒 安全检查
            %s

            ### ⚡ 性能检查
            %s

            ### 📝 代码风格
            %s
            """, security, performance, style);
    }
}

线程池配置

package com.example.codereview.v3.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

/**
 * 异步任务配置
 */
@Configuration
@EnableAsync
public class AsyncConfig {

    @Bean(name = "reviewExecutor")
    public Executor reviewExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);        // 核心线程数
        executor.setMaxPoolSize(20);         // 最大线程数
        executor.setQueueCapacity(100);      // 队列容量
        executor.setThreadNamePrefix("review-");
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);
        executor.initialize();
        return executor;
    }
}

性能对比

📊 v3性能数据
├─ 缓存命中响应:0.2ms
├─ 缓存未命中响应:4000ms(并行后从8s降到4s)
├─ 平均响应时间:1600ms
├─ 成本/请求:$0.012(与v2相同,但体验更好)
└─ 性能提升:50%(未命中场景)

⚠️ 注意事项:
- 并行会增加并发API调用,注意限流
- 需要合理配置线程池大小
- Token消耗总量不变,但峰值增加

4️⃣ v4:生产级 - 完整的可靠性保障

架构图

┌─────────────────────────────────────────────────┐
│              Controller Layer                    │
│  ┌──────────────────────────────────────────┐  │
│  │ - 参数验证                                 │  │
│  │ - Rate Limiting                           │  │
│  │ - Request/Response日志                    │  │
│  └──────────────────────────────────────────┘  │
└─────────────────────────────────────────────────┘
                      ↓
┌─────────────────────────────────────────────────┐
│              Service Layer                       │
│  ┌──────────────────────────────────────────┐  │
│  │ Cache (Caffeine)                         │  │
│  │   ↓ (miss)                               │  │
│  │ Retry (指数退避)                          │  │
│  │   ↓                                      │  │
│  │ Circuit Breaker (Resilience4j)           │  │
│  │   ↓                                      │  │
│  │ Parallel Execution                       │  │
│  │   ↓                                      │  │
│  │ AI Model Call                            │  │
│  └──────────────────────────────────────────┘  │
└─────────────────────────────────────────────────┘
                      ↓
┌─────────────────────────────────────────────────┐
│          Observability Layer                     │
│  - Metrics (Micrometer)                         │
│  - Tracing (OpenTelemetry)                      │
│  - Health Check                                 │
└─────────────────────────────────────────────────┘

完整的服务实现

package com.example.codereview.v4;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.retry.Retry;
import io.github.resilience4j.retry.RetryConfig;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;

/**
 * v4版本:生产级实现
 * 特点:
 * - 缓存(性能)
 * - 并行(效率)
 * - 重试(可靠性)
 * - 熔断(容错)
 * - 监控(可观测性)
 */
@Service
public class CodeReviewServiceV4 {

    private final ChatLanguageModel model;
    private final Retry retry;
    private final CircuitBreaker circuitBreaker;
    private final Counter successCounter;
    private final Counter failureCounter;
    private final Counter cacheHitCounter;
    private final Timer reviewTimer;

    public CodeReviewServiceV4(MeterRegistry meterRegistry) {
        // 初始化AI模型
        this.model = OpenAiChatModel.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .modelName("gpt-3.5-turbo")  // 使用更便宜的模型
            .timeout(Duration.ofSeconds(30))
            .maxRetries(0)  // 我们自己处理重试
            .build();

        // 配置重试策略
        RetryConfig retryConfig = RetryConfig.custom()
            .maxAttempts(3)                    // 最多重试3次
            .waitDuration(Duration.ofSeconds(1))  // 初始等待1秒
            .intervalFunction(                 // 指数退避
                intervalFunction -> intervalFunction * 2
            )
            .retryExceptions(RuntimeException.class)
            .build();
        this.retry = Retry.of("codeReview", retryConfig);

        // 配置熔断器
        CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
            .slidingWindowSize(10)             // 滑动窗口10个请求
            .failureRateThreshold(50)          // 失败率50%触发熔断
            .waitDurationInOpenState(Duration.ofSeconds(30))  // 熔断30秒
            .permittedNumberOfCallsInHalfOpenState(3)  // 半开状态允许3个测试请求
            .build();
        this.circuitBreaker = CircuitBreaker.of("codeReview", circuitBreakerConfig);

        // 初始化监控指标
        this.successCounter = Counter.builder("code_review.success")
            .description("成功的代码审查次数")
            .register(meterRegistry);

        this.failureCounter = Counter.builder("code_review.failure")
            .description("失败的代码审查次数")
            .register(meterRegistry);

        this.cacheHitCounter = Counter.builder("code_review.cache.hit")
            .description("缓存命中次数")
            .register(meterRegistry);

        this.reviewTimer = Timer.builder("code_review.duration")
            .description("代码审查耗时")
            .register(meterRegistry);
    }

    /**
     * 审查代码(生产级)
     */
    @Cacheable(value = "code-reviews", key = "#code.hashCode()")
    public ReviewResult reviewCode(String code) {
        return reviewTimer.record(() -> {
            try {
                // 并行执行三个检查
                CompletableFuture<String> security = executeWithResilience(
                    () -> checkSecurity(code)
                );
                CompletableFuture<String> performance = executeWithResilience(
                    () -> checkPerformance(code)
                );
                CompletableFuture<String> style = executeWithResilience(
                    () -> checkStyle(code)
                );

                // 等待所有检查完成
                CompletableFuture.allOf(security, performance, style).join();

                // 记录成功
                successCounter.increment();

                return new ReviewResult(
                    true,
                    security.join(),
                    performance.join(),
                    style.join(),
                    null
                );

            } catch (Exception e) {
                // 记录失败
                failureCounter.increment();

                return new ReviewResult(
                    false,
                    null,
                    null,
                    null,
                    "审查失败: " + e.getMessage()
                );
            }
        });
    }

    /**
     * 带重试和熔断的执行
     */
    private CompletableFuture<String> executeWithResilience(Supplier<String> supplier) {
        return CompletableFuture.supplyAsync(() -> {
            // 先通过熔断器
            Supplier<String> decoratedSupplier = CircuitBreaker
                .decorateSupplier(circuitBreaker, supplier);

            // 再添加重试
            decoratedSupplier = Retry.decorateSupplier(retry, decoratedSupplier);

            return decoratedSupplier.get();
        });
    }

    /**
     * 安全检查
     */
    private String checkSecurity(String code) {
        String prompt = String.format(
            "简要检查以下代码的安全问题(限50字):\n\n%s",
            code
        );
        return model.generate(prompt);
    }

    /**
     * 性能检查
     */
    private String checkPerformance(String code) {
        String prompt = String.format(
            "简要检查以下代码的性能问题(限50字):\n\n%s",
            code
        );
        return model.generate(prompt);
    }

    /**
     * 代码风格检查
     */
    private String checkStyle(String code) {
        String prompt = String.format(
            "简要检查以下代码的风格问题(限50字):\n\n%s",
            code
        );
        return model.generate(prompt);
    }

    /**
     * 审查结果
     */
    public record ReviewResult(
        boolean success,
        String security,
        String performance,
        String style,
        String error
    ) {}
}

健康检查

package com.example.codereview.v4;

import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;

/**
 * 健康检查
 */
@Component
public class CodeReviewHealthIndicator implements HealthIndicator {

    private final CircuitBreaker circuitBreaker;

    public CodeReviewHealthIndicator(CodeReviewServiceV4 service) {
        this.circuitBreaker = service.getCircuitBreaker();
    }

    @Override
    public Health health() {
        CircuitBreaker.State state = circuitBreaker.getState();

        if (state == CircuitBreaker.State.OPEN) {
            return Health.down()
                .withDetail("circuitBreaker", "OPEN")
                .withDetail("message", "代码审查服务熔断中")
                .build();
        }

        if (state == CircuitBreaker.State.HALF_OPEN) {
            return Health.up()
                .withDetail("circuitBreaker", "HALF_OPEN")
                .withDetail("message", "代码审查服务恢复中")
                .build();
        }

        return Health.up()
            .withDetail("circuitBreaker", "CLOSED")
            .withDetail("message", "代码审查服务正常")
            .build();
    }
}

限流控制器

package com.example.codereview.v4;

import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket;
import io.github.bucket4j.Refill;
import jakarta.validation.constraints.NotBlank;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.Duration;

/**
 * v4控制器(生产级)
 */
@RestController
@RequestMapping("/api/v4/review")
@Validated
public class CodeReviewControllerV4 {

    private final CodeReviewServiceV4 service;
    private final Bucket rateLimiter;

    public CodeReviewControllerV4(CodeReviewServiceV4 service) {
        this.service = service;

        // 限流:每分钟100个请求
        Bandwidth limit = Bandwidth.classic(
            100,
            Refill.intervally(100, Duration.ofMinutes(1))
        );
        this.rateLimiter = Bucket.builder()
            .addLimit(limit)
            .build();
    }

    /**
     * 审查代码
     */
    @PostMapping
    public ResponseEntity<?> review(
        @RequestBody @NotBlank(message = "代码不能为空") String code
    ) {
        // 限流检查
        if (!rateLimiter.tryConsume(1)) {
            return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
                .body(new ErrorResponse("请求过于频繁,请稍后重试"));
        }

        // 代码长度检查
        if (code.length() > 10000) {
            return ResponseEntity.badRequest()
                .body(new ErrorResponse("代码长度不能超过10000字符"));
        }

        // 执行审查
        CodeReviewServiceV4.ReviewResult result = service.reviewCode(code);

        if (!result.success()) {
            return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
                .body(new ErrorResponse(result.error()));
        }

        return ResponseEntity.ok(result);
    }

    private record ErrorResponse(String message) {}
}

依赖配置

<!-- pom.xml -->
<dependencies>
    <!-- Resilience4j(重试、熔断)-->
    <dependency>
        <groupId>io.github.resilience4j</groupId>
        <artifactId>resilience4j-spring-boot3</artifactId>
        <version>2.1.0</version>
    </dependency>

    <!-- Bucket4j(限流)-->
    <dependency>
        <groupId>com.bucket4j</groupId>
        <artifactId>bucket4j-core</artifactId>
        <version>8.7.0</version>
    </dependency>

    <!-- Micrometer(监控)-->
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-registry-prometheus</artifactId>
    </dependency>

    <!-- Spring Boot Actuator -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

配置文件

# application.yml
spring:
  cache:
    caffeine:
      spec: maximumSize=10000,expireAfterWrite=24h

management:
  endpoints:
    web:
      exposure:
        include: health,metrics,prometheus
  metrics:
    tags:
      application: code-review-service

💰 成本优化 - 三大杠杆

杠杆1️⃣:模型选择(10倍成本差异)

/**
 * 不同模型的成本对比
 */
public class ModelCostComparison {

    // GPT-4: $0.03/1K tokens (输入) + $0.06/1K tokens (输出)
    private static final ChatLanguageModel GPT4 = OpenAiChatModel.builder()
        .modelName("gpt-4")
        .build();

    // GPT-3.5-turbo: $0.0015/1K tokens (输入) + $0.002/1K tokens (输出)
    private static final ChatLanguageModel GPT35 = OpenAiChatModel.builder()
        .modelName("gpt-3.5-turbo")
        .build();

    // Claude 3.5 Sonnet: $0.003/1K tokens (输入) + $0.015/1K tokens (输出)
    private static final ChatLanguageModel CLAUDE = AnthropicChatModel.builder()
        .modelName("claude-3-5-sonnet-20241022")
        .build();

    /**
     * 成本对比(假设500 tokens输入,1000 tokens输出)
     */
    public void compareCost() {
        double gpt4Cost = 0.5 * 0.03 + 1.0 * 0.06 = 0.075;      // $0.075
        double gpt35Cost = 0.5 * 0.0015 + 1.0 * 0.002 = 0.00275; // $0.00275
        double claudeCost = 0.5 * 0.003 + 1.0 * 0.015 = 0.0165;  // $0.0165

        // GPT-3.5比GPT-4便宜27倍!
        System.out.printf("成本对比:GPT-4 = %.4f, GPT-3.5 = %.4f (便宜%.0f倍)\n",
            gpt4Cost, gpt35Cost, gpt4Cost / gpt35Cost);
    }
}

智能模型路由

package com.example.codereview.optimization;

import dev.langchain4j.model.chat.ChatLanguageModel;

/**
 * 根据任务复杂度选择模型
 */
@Service
public class SmartModelRouter {

    private final ChatLanguageModel gpt4;
    private final ChatLanguageModel gpt35;

    /**
     * 智能选择模型
     */
    public ChatLanguageModel selectModel(String code) {
        // 简单任务用GPT-3.5(成本低)
        if (isSimpleTask(code)) {
            return gpt35;
        }

        // 复杂任务用GPT-4(效果好)
        return gpt4;
    }

    private boolean isSimpleTask(String code) {
        // 代码短、逻辑简单 → 用便宜模型
        return code.length() < 500 && !code.contains("async") && !code.contains("lambda");
    }
}

杠杆2️⃣:历史压缩(5倍Token节省)

package com.example.codereview.optimization;

import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.UserMessage;

import java.util.ArrayList;
import java.util.List;

/**
 * 对话历史压缩
 * 问题:每次请求都带上完整历史,Token消耗线性增长
 * 解决:只保留最近N轮对话 + 摘要
 */
public class ConversationCompressor {

    private static final int MAX_HISTORY = 5;  // 最多保留5轮

    /**
     * 压缩对话历史
     */
    public List<ChatMessage> compress(List<ChatMessage> history) {
        if (history.size() <= MAX_HISTORY * 2) {
            return history;  // 无需压缩
        }

        List<ChatMessage> compressed = new ArrayList<>();

        // 1. 添加摘要(用AI总结前面的对话)
        String summary = summarizeHistory(history.subList(0, history.size() - MAX_HISTORY * 2));
        compressed.add(new UserMessage("之前的讨论摘要:" + summary));

        // 2. 保留最近N轮完整对话
        compressed.addAll(history.subList(history.size() - MAX_HISTORY * 2, history.size()));

        return compressed;
    }

    private String summarizeHistory(List<ChatMessage> messages) {
        // 用便宜的模型生成摘要
        return "讨论了代码安全问题和性能优化建议";
    }
}

Token使用对比

❌ 不压缩(第10轮对话)
├─ 历史消息:10轮 × 200 tokens = 2000 tokens
├─ 新问题:500 tokens
├─ 总输入:2500 tokens
└─ 成本:$0.075

✅ 压缩后
├─ 摘要:100 tokens
├─ 最近5轮:5 × 200 = 1000 tokens
├─ 新问题:500 tokens
├─ 总输入:1600 tokens
└─ 成本:$0.048(节省36%)

杠杆3️⃣:Prompt优化(2倍效率提升)

/**
 * Prompt优化对比
 */
public class PromptOptimization {

    /**
     * ❌ 低效Prompt(输出冗长)
     */
    public String inefficientPrompt(String code) {
        return String.format("""
            你是一个资深的Java开发专家,拥有20年的开发经验。
            请仔细审查以下代码,从多个维度进行深入分析:
            1. 安全性方面,包括但不限于SQL注入、XSS攻击、CSRF等
            2. 性能方面,包括但不限于算法复杂度、数据库查询优化等
            3. 可维护性方面,包括但不限于代码结构、命名规范等
            请给出详细的分析报告,每个问题都要说明原因和解决方案。

            代码:
            %s

            请开始你的详细分析:
            """, code);

        // 预计输出:1500 tokens
        // 成本:$0.09
    }

    /**
     * ✅ 高效Prompt(输出简洁)
     */
    public String efficientPrompt(String code) {
        return String.format("""
            检查代码问题(每项限30字):
            1. 安全
            2. 性能
            3. 风格

            %s
            """, code);

        // 预计输出:300 tokens
        // 成本:$0.018(节省80%)
    }
}

Few-Shot优化

/**
 * 使用Few-Shot减少输出Token
 */
public String fewShotPrompt(String code) {
    return String.format("""
        参考示例回答:

        示例1:
        输入:public void delete(int id) { sql = "DELETE FROM users WHERE id=" + id; }
        输出:SQL注入风险 | 缺少事务 | 无异常处理

        示例2:
        输入:for (User u : users) { db.save(u); }
        输出:N+1查询 | 应批量保存 | 缺少null检查

        现在检查:
        %s

        输出:
        """, code);

    // AI会模仿示例,输出简洁格式
}

📋 生产部署Checklist

可靠性

  • 错误处理:所有AI调用都有try-catch
  • 重试机制:使用Resilience4j,指数退避
  • 熔断器:失败率超过50%自动熔断
  • 超时设置:所有API调用都有timeout
  • 降级方案:AI服务不可用时返回默认结果
  • 限流保护:防止恶意调用和成本失控

性能

  • 缓存策略:合理的缓存Key和过期时间
  • 并行优化:独立任务并行执行
  • 连接池:HTTP client使用连接池
  • 异步处理:长时间任务异步化
  • 资源限制:线程池、内存、Token上限

成本

  • 模型选择:根据任务选择合适的模型
  • Prompt优化:简洁的Prompt,限制输出长度
  • 历史压缩:多轮对话场景压缩历史
  • 成本监控:每日/每月成本告警
  • 配额管理:设置每个用户的调用限额

可观测性

  • 日志记录:关键操作记录日志
  • Metrics监控:成功率、延迟、成本等指标
  • Tracing追踪:分布式链路追踪
  • 健康检查:/actuator/health端点
  • 告警配置:失败率、延迟、成本告警

安全

  • API密钥保护:密钥存储在环境变量/密钥管理服务
  • 参数验证:严格的输入验证
  • 输出过滤:防止敏感信息泄露
  • 访问控制:API需要认证授权
  • 审计日志:记录谁在何时调用了什么

📊 性能对比总结

指标v1原型v2缓存v3并行v4生产
平均延迟8000ms3200ms1600ms800ms
P95延迟15000ms8000ms4000ms2000ms
成本/请求$0.03$0.012$0.012$0.003
失败率2%2%2%0.1%
缓存命中率0%60%60%60%
可用性98%98%98%99.9%
监控
熔断
限流

综合提升

🚀 v1 → v4 提升总结

性能提升:
├─ 平均延迟:8000ms → 800ms(提升10倍)
└─ P95延迟:15000ms → 2000ms(提升7.5倍)

成本降低:
├─ 每请求:$0.03 → $0.003(降低90%)
└─ 每月(10万请求):$3000$300(节省$2700)

可靠性提升:
├─ 失败率:2% → 0.1%(提升20倍)
└─ 可用性:98% → 99.9%(提升1.9%)

运维能力:
├─ 监控:无 → 完整的Metrics + Tracing
├─ 告警:无 → 多维度告警
└─ 健康检查:无 → /actuator/health

💡 练习题

练习1:缓存策略设计

场景:你的代码审查服务有以下特点:
- 70%的请求是重复代码
- 代码会更新,旧版本的审查结果应失效
- 需要支持"强制刷新"功能

问题:
1. 如何设计Cache Key?(提示:不能只用hashCode)
2. 如何处理代码更新的缓存失效?
3. 如何实现"强制刷新"?

请实现一个改进的缓存策略。

练习2:成本优化

场景:你的服务每天处理10000次代码审查
- 当前成本:$300/天
- 目标成本:$100/天

数据分析:
- 40%是简单问题(<100行代码)
- 30%是中等复杂度(100-500行)
- 30%是复杂问题(>500行)

任务:
1. 设计一个模型路由策略
2. 计算每个场景的成本
3. 验证是否能达到目标成本

提示:GPT-4 ($0.03/1K), GPT-3.5 ($0.001/1K), Claude Haiku ($0.00025/1K)

练习3:可靠性设计

场景:OpenAI API的实际表现
- 平均成功率:98%
- 偶发性故障(1-2分钟)
- 限流:3500 RPM

问题:
1. 如何配置重试策略?(重试次数、间隔)
2. 如何配置熔断器?(窗口大小、阈值、恢复时间)
3. 如何设计降级方案?

请实现一个完整的容错方案,目标可用性99.9%。

🎯 下一步

恭喜你完成了Week 2的最后一课!从原型到生产,你学会了:

  • ✅ 缓存优化(40000倍提升)
  • ✅ 并行优化(50%提升)
  • ✅ 成本优化(90%降低)
  • ✅ 可靠性保障(99.9%可用性)

下一篇:[[14-Week2完整总结和周发布]]

  • Week 2完整知识图谱
  • 三个项目的最佳实践
  • 周发布准备清单
  • Week 3预告

学习路径

Week 2进度:13/14Day 8-9:项目1 - 智能文档问答 ✅
Day 10-11:项目2 - AI代码审查助手 ✅
Day 12-13:项目3 - 智能客服系统 ✅
Day 14:Week 2总结 → 下一篇

最后更新:2026-03-08