Spring AI 中的 ChatClient Fluent API
1. 概述
在本教學中,我們將探索ChatClient
的流暢 API,這是 Spring AI 模組版本 1.0.0 M1 的功能。
Spring AI 模組中的ChatClient
介面支援與 AI 模型進行通信,讓使用者可以發送提示並接收結構化回應。它遵循建構器模式,提供類似WebClient
、 RestClient
和JdbcClient
API。
2.透過ChatClient
執行提示
我們可以將 Spring Boot 中的用戶端用作自動配置的 bean,或以程式設計方式建立實例。
首先,讓我們將[spring-ai-openai-spring-boot-starter](https://mvnrepository.com/artifact/group.springframework.ai/spring-ai-openai-spring-boot-starter)
依賴項加入 pom.xml 中:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
這樣,我們就可以將ChatClient.Builder
實例注入到 Spring 管理的元件中:
@RestController
@RequestMapping("api/articles")
class BlogsController {
private final ChatClient chatClient;
public BlogsController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
// ...
}
現在,讓我們建立一個簡單的端點,它接受問題作為查詢參數並將提示轉發給 AI:
@GetMapping("v1")
String askQuestion(@RequestParam(name = "question") String question) {
return chatClient.prompt()
.user(question)
.call()
.chatResponse()
.getResult()
.getOutput()
.getContent();
}
正如我們所看到的,流暢的ChatClient
允許我們輕鬆地從使用者輸入的String
中建立提示請求,呼叫 API,並以文字形式檢索回應內容.
此外,如果我們只對String
形式的回應主體感興趣,不需要狀態代碼或標頭等元數據,則可以透過使用content()
方法對最後四個步驟進行分組來簡化程式碼。讓我們重構程式碼並添加此改進:
@GetMapping("v1")
String askQuestion(@RequestParam(name = "question") String question) {
return chatClient.prompt()
.user(question)
.call()
.content();
}
如果我們現在發送GET
請求,我們將收到一個沒有定義結構的回應,類似於透過瀏覽器存取時 ChatGPT 的預設輸出:
3. 將回應對應到特定格式
正如我們所看到的, ChatClient
介面簡化了將使用者查詢轉發到聊天模型並發送迴響應的過程。但是,在大多數情況下,我們希望模型的輸出採用結構化格式,然後可以將其序列化為 JSON 。
API 公開了一個entity()
方法,它允許我們為模型的輸出定義特定的資料結構。讓我們修改程式碼以確保它傳回一個Article
物件列表,每個物件包含一個標題和一組標籤:
record Article(String title, Set<String> tags) {
}
@GetMapping("v2")
List<Article> askQuestionAndRetrieveArticles(@RequestParam(name = "question") String question) {
return chatClient.prompt()
.user(question)
.call()
.entity(new ParameterizedTypeReference<List<Article>>() {});
}
如果我們現在執行請求,我們將期望端點以有效的 JSON 清單返回Article
推薦:
4. 提供額外的背景信息
我們學習如何使用 Spring AI 模組建立提示、將其發送到 AI 模型以及接收結構化回應。然而,我們的 REST API 傳回的文章推薦是虛構的,在我們的網站上可能不存在。
為了解決這個問題, ChatClient
利用檢索增強生成 (RAG) 模式,將從來源獲取的資料檢索與生成模型結合,以提供更準確的回應。我們將使用向量儲存來利用 RAG 並載入與我們的用例相關的文件。
首先,我們將建立一個VectorStore
並在類別初始化期間使用本地文件中的增強資料載入它:
@RestController
@RequestMapping("api/articles")
public class BlogsController {
private final ChatClient chatClient;
private final VectorStore vectorStore;
public BlogsController(ChatClient.Builder chatClientBuilder, EmbeddingModel embeddingModel) throws IOException {
this.chatClient = chatClientBuilder.build();
this.vectorStore = new SimpleVectorStore(embeddingModel);
initContext();
}
void initContext() throws IOException {
List<Document> documents = Files.readAllLines(Path.of("src/main/resources/articles.txt"))
.stream()
.map(Document::new)
.toList();
vectorStore.add(documents);
}
// ...
}
正如我們所看到的,我們讀取了articles.txt
中的所有條目,並為此文件的每一行建立了一個新Document
。不用說,我們不必依賴文件——如果需要,我們可以使用任何資料來源。
之後,我們將透過將VectorStore
包裝在QuestionAnswerAdvisor
中來向模型提供增強資料:
@GetMapping("v3")
List<Article> askQuestionWithContext(@RequestParam(name = "question") String question) {
return chatClient.prompt()
.advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
.user(question)
.call()
.entity(new ParameterizedTypeReference<List<Article>>() {});
}
因此,我們的應用程式現在僅從增強上下文返回資料:
5. 結論
在本文中,我們探討了 Spring AI 的ChatClient
。我們首先向模型發送簡單的使用者查詢,並以純文字形式讀取其回應。然後,我們透過以特定的結構化格式檢索模型的回應來增強我們的解決方案。
最後,我們學習如何使用文檔集合載入模型的上下文,以根據我們自己的資料提供準確的回應。我們使用VectorStore
和QuestionAnswerAdvisor
實現了這一點。
完整的範例可以在 GitHub 上找到。