Spring AI 入門與DeepSeek API融合實戰
Spring AI 作為統一的大模型接入框架,其Model API為開發者提供了多模型適配能力。無論是OpenAI、DeepSeek、Moonshot AI(月之暗面)、Perplexity AI、Google VertexAI Gemini 等若干主流云服務商模型,還是支持Ollama私有化部署的本地模型,均可通過標準化接口實現無縫集成。
本文將介紹基于Spring AI框架,分別調用云端DeepSeek API的完整對話實現方式,話不多說,搞起來。
引入依賴
第一步,先引入依賴:Springboot 3.4.5 、 Spring AI 1.0.0-M7 。因為deepseek支持open ai的標準接口,所以這里引入 open ai的依賴即可。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.5</version>
<relativePath/>
</parent>
<groupId>site.qxkd</groupId>
<artifactId>chat-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>chat-client</name>
<description>chat-client</description>
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0-M7</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
配置文件
這只是列舉一些簡單配置文件,實際上配置還是挺多的,感興趣可以去官網看一下
spring.application.name=chat-client
# 大模型相關依賴
spring.ai.openai.base-url=https://api.siliconflow.cn
spring.ai.openai.api-key=sk-你的秘鑰
#spring.ai.openai.chat.options.model=deepseek-ai/DeepSeek-V3
spring.ai.openai.chat.options.model=deepseek-ai/DeepSeek-R1
測試
上面一切準備好之后,寫兩個接口測試一下,一個是一次性輸出結果的接口,一個是流式輸出的接口。
RestController
@RequestMapping("/deepseek")
publicclass DeepseekController {
@Autowired
private OpenAiChatModel chatModel;
@GetMapping("/ai/generate")
public Map<String , String> generate(@RequestParam(value = "message") String message) {
String content = chatModel.call(message);
return Map.of("generation", content);
}
/**
* 生成流式結果
* @param message
* @return
*/
@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(@RequestParam(value = "message") String message) {
Prompt prompt = new Prompt(new UserMessage(message));
returnthis.chatModel.stream(prompt);
}
}
先測試一次性輸出結果的接口,瀏覽器訪問http://localhost:8080/deepseek/ai/generate?message=你是誰
,會輸出如下結果:
圖片
下面再來測試一下流式輸出到接口,為了實現流式輸出的效果,我讓deepseek給我寫了一個網頁,簡單修改了一下,達到了如下圖中的效果。
圖片
流式輸出返回的一段JSON是這樣的。
{
"result": {
"metadata": {
"finishReason": "",
"contentFilters": [],
"empty": true
},
"output": {
"messageType": "ASSISTANT",
"metadata": {
"refusal": "",
"finishReason": "",
"index": 0,
"id": "019684b265266dbe29ab56f75eaa75cd",
"role": "ASSISTANT",
"messageType": "ASSISTANT"
},
"toolCalls": [],
"media": [],
"text": "DeepSeek)公司開發的智能助手"
}
},
"metadata": {
"id": "019684b265266dbe29ab56f75eaa75cd",
"model": "deepseek-ai/DeepSeek-R1",
"rateLimit": {
"requestsRemaining": 0,
"requestsLimit": 0,
"tokensRemaining": 0,
"tokensReset": "PT0S",
"requestsReset": "PT0S",
"tokensLimit": 0
},
"usage": {
"promptTokens": 6,
"completionTokens": 64,
"totalTokens": 70,
"nativeUsage": {
"completion_tokens": 64,
"prompt_tokens": 6,
"total_tokens": 70,
"completion_tokens_details": {
"reasoning_tokens": 38
}
}
},
"promptMetadata": [],
"empty": false
},
"results": [{
"metadata": {
"finishReason": "",
"contentFilters": [],
"empty": true
},
"output": {
"messageType": "ASSISTANT",
"metadata": {
"refusal": "",
"finishReason": "",
"index": 0,
"id": "019684b265266dbe29ab56f75eaa75cd",
"role": "ASSISTANT",
"messageType": "ASSISTANT"
},
"toolCalls": [],
"media": [],
"text": "DeepSeek)公司開發的智能助手"
}
}]
}
至此,一個簡單的Spring AI對話就完成了。細心的同學可能會發現,這也就只能單輪對話,沒什么用呀,要連續對話才行。別急,下面就演示一下連續對話的demo。
連續對話
想要連續對話需要3個相關接口和API:
- ChatMemory : 大模型(LLM)是無狀態的,這意味著它們不會保留有關以前交互的信息。在多個交互中維護上下文或狀態時,這就變成了一種限制。為了解決這個問題,Spring AI 提供了一個存儲和檢索與大模型多次對話信息的接口
ChatMemory
。 - ChatClient :
ChatClient
提供了一個流式API(fluent API),用于與AI模型進行通信,它同時支持同步和流式兩種編程模型。該流式API提供了一系列方法,用于逐步構建**提示詞(Prompt)**的各個組成部分,這些提示詞將作為輸入傳遞給AI模型。 - Advisors API:
Advisors API
為開發者提供了一種靈活而強大的方式,用于在 Spring 應用程序中攔截、修改和增強 AI 驅動的交互。它的核心優勢包括:封裝常見的生成式 AI 模式,轉換發送給大語言模型(LLMs)的數據及處理其返回結果,以及實現跨不同模型和用例的可移植性。
話不多說,上代碼。
- 先注入
ChatClient
和ChatMemory
對象 本文使用InMemoryChatMemory
將對話記錄存放在內存中,如果想實現將對話記錄存放在數據庫可以考慮實現ChatMemory
。
@Configuration
publicclass ChatConfig {
@Bean
public ChatClient chatClient(OpenAiChatModel openAiChatModel) {
ChatClient chatClient = ChatClient.builder(openAiChatModel)
.defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory())) // 設置默認的MemoryAdvisor ,將對話記錄存放在內存中
.build();
return chatClient;
}
@Bean
public ChatMemory chatMemory(){
returnnew InMemoryChatMemory();
}
}
- 測試 測試使用流式輸出,調用接口時需要傳一個chatId ,這樣才能根據chatId到內存中查詢相關對話信息。
@Autowired
private ChatClient chatClient;
@GetMapping("/ai/chatContext")
public Flux<ChatResponse> chatContext(@RequestParam(value = "message") String message , String chatId) {
Flux<ChatResponse> chatResponseFlux = chatClient.prompt()
//連續對話的key
.advisors(advisor -> advisor.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100))
.user(message).stream().chatResponse();
return chatResponseFlux;
}
修改一下之前的聊天界面代碼進行測試:
圖片
至此,Spring AI 使用Deepseek大模型對話的簡單示例就完成了,如果使用了Ollama私有化部署了大模型也可以使用上面的流程,或者是引入Ollama的依賴。