mcpField
S
spring-ai

spring-ai

github.com/claude-dev-suite开发4648 次安装6 天前更新
代码仓库

关于 spring-ai

面向 Spring 应用开发者的 Spring AI 参考技能,涵盖聊天、结构化输出、流式响应、函数调用、嵌入和向量存储,可用于构建生成式 AI 功能。

主要功能

  1. 01ChatClient 聊天调用
  2. 02结构化输出与流式响应
  3. 03函数调用
  4. 04文本嵌入
  5. 05向量存储与 RAG

适用场景

  1. 01在 Spring 服务中接入聊天模型
  2. 02生成结构化的模型响应
  3. 03实现长响应的流式处理
  4. 04基于向量存储构建 RAG 查询

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill spring-ai

安装后在 Claude Code 中输入/spring-ai确认已加载。

附带文件advanced.md

详细介绍

Spring AI - 快速参考

完整参考:有关图像生成、多模态/视觉、顾问/中间件、测试模式和提示词模板,请参阅 advanced.md。

深入了解:使用 mcp__documentation__fetch_docs,并将技术指定为:spring-ai,获取全面的文档。

依赖项


<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>


<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId>
</dependency>


<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>


<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId>
</dependency>

配置

OpenAI
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      chat:
        options:
          model: gpt-4o
          temperature: 0.7
          max-tokens: 1000
      embedding:
        options:
          model: text-embedding-3-small
Azure OpenAI
spring:
  ai:
    azure:
      openai:
        api-key: ${AZURE_OPENAI_KEY}
        endpoint: ${AZURE_OPENAI_ENDPOINT}
        chat:
          options:
            deployment-name: gpt-4o
            temperature: 0.7
Ollama(本地)
spring:
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        options:
          model: llama3
          temperature: 0.7

基本聊天

@Service
@RequiredArgsConstructor
public class ChatService {

    private final ChatClient chatClient;

    public String chat(String message) {
        return chatClient.prompt()
            .user(message)
            .call()
            .content();
    }

    // With system prompt
    public String chatWithContext(String message) {
        return chatClient.prompt()
            .system("You are a helpful assistant specialized in Spring Boot.")
            .user(message)
            .call()
            .content();
    }

    // With parameters
    public String chatWithParams(String message, String topic) {
        return chatClient.prompt()
            .system(s -> s.text("You are an expert in {topic}.")
                .param("topic", topic))
            .user(message)
            .call()
            .content();
    }
}
ChatClient 构建器
@Configuration
public class ChatClientConfig {

    @Bean
    public ChatClient chatClient(ChatClient.Builder builder) {
        return builder
            .defaultSystem("You are a helpful AI assistant.")
            .defaultOptions(ChatOptionsBuilder.builder()
                .withTemperature(0.7)
                .withMaxTokens(1000)
                .build())
            .build();
    }
}

结构化输出

public record BookRecommendation(
    String title,
    String author,
    String genre,
    String summary,
    int rating
) {}

@Service
public class BookService {

    private final ChatClient chatClient;

    public BookRecommendation getRecommendation(String preferences) {
        return chatClient.prompt()
            .user("Recommend a book based on: " + preferences)
            .call()
            .entity(BookRecommendation.class);
    }

    public List<BookRecommendation> getRecommendations(String preferences, int count) {
        return chatClient.prompt()
            .user("Recommend " + count + " books based on: " + preferences)
            .call()
            .entity(new ParameterizedTypeReference<List<BookRecommendation>>() {});
    }
}

流式处理

@Service
public class StreamingChatService {

    private final ChatClient chatClient;

    public Flux<String> streamChat(String message) {
        return chatClient.prompt()
            .user(message)
            .stream()
            .content();
    }

    // WebFlux controller
    @GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamResponse(@RequestParam String message) {
        return streamChat(message);
    }
}

函数调用

@Configuration
public class FunctionConfig {

    @Bean
    @Description("Get current weather for a location")
    public Function<WeatherRequest, WeatherResponse> currentWeather() {
        return request -> weatherService.getWeather(request.location());
    }

    @Bean
    @Description("Search for products by name")
    public Function<ProductSearchRequest, List<Product>> searchProducts() {
        return request -> productService.search(request.query(), request.maxResults());
    }
}

public record WeatherRequest(String location) {}
public record WeatherResponse(String location, double temperature, String conditions) {}

@Service
public class AssistantService {

    private final ChatClient chatClient;

    public String assistWithFunctions(String message) {
        return chatClient.prompt()
            .user(message)
            .functions("currentWeather", "searchProducts")
            .call()
            .content();
    }
}

嵌入

@Service
@RequiredArgsConstructor
public class EmbeddingService {

    private final EmbeddingModel embeddingModel;

    public float[] getEmbedding(String text) {
        EmbeddingResponse response = embeddingModel.embedForResponse(List.of(text));
        return response.getResult().getOutput();
    }

    public List<float[]> getEmbeddings(List<String> texts) {
        EmbeddingResponse response = embeddingModel.embedForResponse(texts);
        return response.getResults().stream()
            .map(e -> e.getOutput())
            .toList();
    }
}

向量存储(RAG)

配置
spring:
  ai:
    vectorstore:
      pgvector:
        dimensions: 1536
        index-type: HNSW
        distance-type: COSINE_DISTANCE
RAG 查询
@Service
@RequiredArgsConstructor
public class RagService {

    private final VectorStore vectorStore;
    private final ChatClient chatClient;

    public String queryWithContext(String question) {
        // Retrieve relevant documents
        List<Document> relevantDocs = vectorStore.similaritySearch(
            SearchRequest.query(question)
                .withTopK(5)
                .withSimilarityThreshold(0.7)
        );

        // Build context
        String context = relevantDocs.stream()
            .map(Document::getContent)
            .collect(Collectors.joining("\n\n"));

        // Generate response with context
        return chatClient.prompt()
            .system("""
                You are a helpful assistant. Answer questions based on the provided context.
                If the answer is not in the context, say "I don't have information about that."

                Context:
                {context}
                """)
            .user(question)
            .call()
            .content();
    }
}
QuestionAnswerAdvisor
@Configuration
public class RagConfig {

    @Bean
    public ChatClient ragChatClient(ChatClient.Builder builder, VectorStore vectorStore) {
        return builder
            .defaultAdvisors(new QuestionAnswerAdvisor(vectorStore))
            .build();
    }
}

// Usage is simple - advisor handles RAG automatically
@Service
public class SimpleRagService {

    private final ChatClient ragChatClient;

    public String answer(String question) {
        return ragChatClient.prompt()
            .user(question)
            .call()
            .content();
    }
}

最佳实践

应做不应做
使用结构化输出,获得可预测的结果手动解析自由格式文本
实现完善的错误处理忽略 API 故障
对较长的响应使用流式处理等待大型内容生成完成
尽可能缓存嵌入反复重新生成嵌入
设置合适的令牌上限使用无限令牌

生产环境检查清单

  • 妥善保护 API 密钥(环境变量)
  • 实施速率限制
  • 错误处理与重试
  • 监控令牌用量
  • 在适当情况下缓存响应
  • 为向量存储建立正确的索引
  • 确保嵌入维度一致
  • 防范提示词注入
  • 监控成本并设置警报
  • 配置备用模型

不应使用此技能的情况

  • 直接调用 OpenAI/Anthropic API - 直接使用相应的 SDK
  • 训练 ML 模型 - 使用 Python 框架(PyTorch、TensorFlow)
  • 非 Spring 应用 - 使用 LangChain 或原生 SDK
  • 简单文本生成 - 对于简单用例,这可能过于复杂

反模式

反模式问题解决方案
硬编码 API 密钥安全风险使用环境变量
未设置令牌上限成本激增适当设置 max-tokens
长请求使用同步处理线程阻塞使用流式处理
忽略速率限制API 错误、封禁实现带退避的重试
不缓存嵌入成本高昂在本地缓存嵌入
存在提示词注入漏洞安全风险清理用户输入

快速故障排除

问题诊断修复方法
API 密钥无效检查错误消息验证 OPENAI_API_KEY 环境变量
超出速率限制429 错误添加重试逻辑,减少请求
较长提示词导致超时连接超时使用流式处理,延长超时时间
嵌入维度不匹配向量存储错误匹配嵌入模型的维度
结构化输出失败JSON 解析错误简化架构,添加示例

参考文档

评论

支持 Markdown