Overview
Spring AI is an AI application development framework officially provided by Spring, which simplifies integration with various large language models (LLMs), including OpenAI, Anthropic, Azure OpenAI, and others.
Core Features
1. Project Creation
Dependencies:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
Or use Gradle:
dependencies {
implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter'
}
2. Chat Client
Configuration:
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4
temperature: 0.7
Using ChatClient:
@Service
public class ChatService {
private final ChatClient chatClient;
public ChatService(ChatClient chatClient) {
this.chatClient = chatClient;
}
public String chat(String message) {
return chatClient.call(message);
}
public String chatWithPrompt(String userMessage) {
Prompt prompt = new Prompt(new UserMessage(userMessage));
ChatResponse response = chatClient.call(prompt);
return response.getResult().getOutput().getContent();
}
}
Streaming Responses:
@Service
public class ChatService {
private final StreamingChatClient streamingChatClient;
public ChatService(StreamingChatClient streamingChatClient) {
this.streamingChatClient = streamingChatClient;
}
public Flux<String> streamChat(String message) {
return streamingChatClient.stream(message)
.map(response -> response.getResult().getOutput().getContent());
}
}
3. Prompt Template
Defining Templates:
@Service
public class PromptService {
private final PromptTemplate promptTemplate;
public PromptService() {
this.promptTemplate = new PromptTemplate(
"请用{style}风格回答以下问题:{question}"
);
}
public String generatePrompt(String style, String question) {
Map<String, Object> variables = Map.of(
"style", style,
"question", question
);
return promptTemplate.render(variables);
}
}
Using ChatClient:
@Service
public class ChatService {
private final ChatClient chatClient;
private final PromptTemplate promptTemplate;
public ChatService(ChatClient chatClient) {
this.chatClient = chatClient;
this.promptTemplate = new PromptTemplate(
"请用{style}风格回答以下问题:{question}"
);
}
public String chatWithStyle(String style, String question) {
Prompt prompt = promptTemplate.create(Map.of(
"style", style,
"question", question
));
ChatResponse response = chatClient.call(prompt);
return response.getResult().getOutput().getContent();
}
}
4. Embedding
Configuration:
spring:
ai:
openai:
embedding:
options:
model: text-embedding-ada-002
Using EmbeddingClient:
@Service
public class EmbeddingService {
private final EmbeddingClient embeddingClient;
public EmbeddingService(EmbeddingClient embeddingClient) {
this.embeddingClient = embeddingClient;
}
public List<Double> embed(String text) {
EmbeddingResponse response = embeddingClient.embedForResponse(
List.of(text)
);
return response.getResult().getOutput();
}
public List<List<Double>> embedBatch(List<String> texts) {
EmbeddingResponse response = embeddingClient.embedForResponse(texts);
return response.getResult().getOutput();
}
}
5. Vector Store
Configuration:
spring:
ai:
vectorstore:
pgvector:
index-type: HNSW
distance-type: COSINE_DISTANCE
Using VectorStore:
@Service
public class VectorStoreService {
private final VectorStore vectorStore;
private final EmbeddingClient embeddingClient;
public VectorStoreService(
VectorStore vectorStore,
EmbeddingClient embeddingClient
) {
this.vectorStore = vectorStore;
this.embeddingClient = embeddingClient;
}
public void addDocument(String id, String content) {
List<Double> embedding = embeddingClient.embed(content);
Document document = new Document(id, content, Map.of());
vectorStore.add(List.of(document));
}
public List<Document> searchSimilar(String query, int topK) {
List<Double> queryEmbedding = embeddingClient.embed(query);
return vectorStore.similaritySearch(
SearchRequest.query(query)
.withTopK(topK)
);
}
}
6. Function Calling
Defining Functions:
@Bean
public Function<WeatherRequest, WeatherResponse> weatherFunction() {
return request -> {
// 调用天气 API
WeatherResponse response = weatherService.getWeather(
request.getLocation()
);
return response;
};
}
Configuring Function Calling:
@Configuration
public class FunctionCallingConfig {
@Bean
public Function<WeatherRequest, WeatherResponse> weatherFunction() {
return request -> {
// 实现天气查询逻辑
return new WeatherResponse(/* ... */);
};
}
}
Using Function Calling:
@Service
public class ChatService {
private final ChatClient chatClient;
private final FunctionCallbackRegistry functionCallbackRegistry;
public ChatService(
ChatClient chatClient,
FunctionCallbackRegistry functionCallbackRegistry
) {
this.chatClient = chatClient;
this.functionCallbackRegistry = functionCallbackRegistry;
}
public String chatWithFunction(String message) {
Prompt prompt = new Prompt(
new UserMessage(message),
functionCallbackRegistry.getFunctionCallbacks()
);
ChatResponse response = chatClient.call(prompt);
return response.getResult().getOutput().getContent();
}
}
7. Multi-Model Support
Configuring Multiple Models:
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
anthropic:
api-key: ${ANTHROPIC_API_KEY}
azure:
openai:
api-key: ${AZURE_OPENAI_API_KEY}
endpoint: ${AZURE_OPENAI_ENDPOINT}
Using a Specific Model:
@Service
public class MultiModelService {
private final ChatClient openAiChatClient;
private final ChatClient anthropicChatClient;
public MultiModelService(
@Qualifier("openAiChatClient") ChatClient openAiChatClient,
@Qualifier("anthropicChatClient") ChatClient anthropicChatClient
) {
this.openAiChatClient = openAiChatClient;
this.anthropicChatClient = anthropicChatClient;
}
public String chatWithOpenAI(String message) {
return openAiChatClient.call(message);
}
public String chatWithAnthropic(String message) {
return anthropicChatClient.call(message);
}
}
Best Practices
1. Configuration Management
- Use environment variables to store API Keys
- Distinguish between development and production environment configurations
- Configure reasonable timeout and retry strategies
2. Error Handling
@Service
public class ChatService {
private final ChatClient chatClient;
public String chat(String message) {
try {
return chatClient.call(message);
} catch (Exception e) {
// 处理错误
log.error("Chat error", e);
return "抱歉,处理请求时出现错误";
}
}
}
3. Performance Optimization
- Use streaming responses to improve user experience
- Use caching reasonably to reduce API calls
- Process Embedding requests in batches
4. Cost Control
- Choose an appropriate model (GPT-3.5 vs GPT-4)
- Limit Token usage
- Monitor API calls
Common Dependencies
<!-- OpenAI -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<!-- Anthropic -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-anthropic-spring-boot-starter</artifactId>
</dependency>
<!-- Azure OpenAI -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId>
</dependency>
<!-- Vector Store (PGVector) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId>
</dependency>
Example Prompts
- "How do I use Spring AI to integrate OpenAI?"
- "How do I implement streaming responses in Spring AI?"
- "How do I use Embedding and Vector Store in Spring AI?"
- "How do I implement Function Calling in Spring AI?"
- "How do I configure Spring AI to support multiple models?"