聊天客戶端 API

ChatClient 提供了一個流暢的 API,用於與 AI 模型通訊。它支援同步和流式程式設計模型。

請參閱本文件底部的實現注意事項,其中涉及 ChatClient 中命令式和響應式程式設計模型的組合使用。

流暢的 API 提供了用於構建傳遞給 AI 模型作為輸入的提示的組成部分的方法。Prompt 包含指導 AI 模型輸出和行為的指令文字。從 API 的角度來看,提示由訊息集合組成。

AI 模型處理兩種主要型別的訊息:使用者訊息(直接來自使用者的輸入)和系統訊息(系統生成以引導對話)。

這些訊息通常包含佔位符,這些佔位符在執行時根據使用者輸入進行替換,以自定義 AI 模型對使用者輸入的響應。

還可以指定提示選項,例如要使用的 AI 模型的名稱以及控制生成輸出的隨機性或創造性的溫度設定。

建立 ChatClient

ChatClient 是使用 ChatClient.Builder 物件建立的。您可以獲取任何 ChatModel Spring Boot 自動配置的自動配置 ChatClient.Builder 例項,也可以透過程式設計方式建立它。

使用自動配置的 ChatClient.Builder

在最簡單的用例中,Spring AI 提供 Spring Boot 自動配置,為您建立一個原型 ChatClient.Builder bean,以便注入到您的類中。以下是一個簡單的示例,用於檢索對簡單使用者請求的 String 響應。

@RestController
class MyController {

    private final ChatClient chatClient;

    public MyController(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    @GetMapping("/ai")
    String generation(String userInput) {
        return this.chatClient.prompt()
            .user(userInput)
            .call()
            .content();
    }
}

在這個簡單的例子中,使用者輸入設定了使用者訊息的內容。call() 方法向 AI 模型傳送請求,content() 方法將 AI 模型的響應作為 String 返回。

使用多個聊天模型

在單個應用程式中,您可能需要處理多個聊天模型的幾種情況:

  • 對不同型別的任務使用不同的模型(例如,對於複雜推理使用強大的模型,對於簡單任務使用更快、更便宜的模型)

  • 在某個模型服務不可用時實現回退機制

  • 對不同的模型或配置進行 A/B 測試

  • 根據使用者的偏好為使用者提供模型選擇

  • 組合專用模型(一個用於程式碼生成,另一個用於創意內容等)

預設情況下,Spring AI 自動配置單個 ChatClient.Builder bean。但是,您可能需要在應用程式中使用多個聊天模型。以下是如何處理這種情況:

在所有情況下,您都需要透過設定屬性 spring.ai.chat.client.enabled=false 來停用 ChatClient.Builder 自動配置。

這允許您手動建立多個 ChatClient 例項。

使用單一模型型別的多個 ChatClient

本節介紹了一個常見用例,您需要建立多個 ChatClient 例項,它們都使用相同的底層模型型別,但配置不同。

// Create ChatClient instances programmatically
ChatModel myChatModel = ... // already autoconfigured by Spring Boot
ChatClient chatClient = ChatClient.create(myChatModel);

// Or use the builder for more control
ChatClient.Builder builder = ChatClient.builder(myChatModel);
ChatClient customChatClient = builder
    .defaultSystemPrompt("You are a helpful assistant.")
    .build();

不同模型型別的 ChatClient

當使用多個 AI 模型時,您可以為每個模型定義單獨的 ChatClient bean。

import org.springframework.ai.chat.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ChatClientConfig {

    @Bean
    public ChatClient openAiChatClient(OpenAiChatModel chatModel) {
        return ChatClient.create(chatModel);
    }

    @Bean
    public ChatClient anthropicChatClient(AnthropicChatModel chatModel) {
        return ChatClient.create(chatModel);
    }
}

然後,您可以使用 @Qualifier 註解將這些 bean 注入到應用程式元件中。

@Configuration
public class ChatClientExample {

    @Bean
    CommandLineRunner cli(
            @Qualifier("openAiChatClient") ChatClient openAiChatClient,
            @Qualifier("anthropicChatClient") ChatClient anthropicChatClient) {

        return args -> {
            var scanner = new Scanner(System.in);
            ChatClient chat;

            // Model selection
            System.out.println("\nSelect your AI model:");
            System.out.println("1. OpenAI");
            System.out.println("2. Anthropic");
            System.out.print("Enter your choice (1 or 2): ");

            String choice = scanner.nextLine().trim();

            if (choice.equals("1")) {
                chat = openAiChatClient;
                System.out.println("Using OpenAI model");
            } else {
                chat = anthropicChatClient;
                System.out.println("Using Anthropic model");
            }

            // Use the selected chat client
            System.out.print("\nEnter your question: ");
            String input = scanner.nextLine();
            String response = chat.prompt(input).call().content();
            System.out.println("ASSISTANT: " + response);

            scanner.close();
        };
    }
}

多個 OpenAI 相容 API 端點

OpenAiApiOpenAiChatModel 類提供了一個 mutate() 方法,允許您建立具有不同屬性的現有例項的變體。當您需要處理多個 OpenAI 相容 API 時,這尤其有用。

@Service
public class MultiModelService {

    private static final Logger logger = LoggerFactory.getLogger(MultiModelService.class);

    @Autowired
    private OpenAiChatModel baseChatModel;

    @Autowired
    private OpenAiApi baseOpenAiApi;

    public void multiClientFlow() {
        try {
            // Derive a new OpenAiApi for Groq (Llama3)
            OpenAiApi groqApi = baseOpenAiApi.mutate()
                .baseUrl("https://api.groq.com/openai")
                .apiKey(System.getenv("GROQ_API_KEY"))
                .build();

            // Derive a new OpenAiApi for OpenAI GPT-4
            OpenAiApi gpt4Api = baseOpenAiApi.mutate()
                .baseUrl("https://api.openai.com")
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .build();

            // Derive a new OpenAiChatModel for Groq
            OpenAiChatModel groqModel = baseChatModel.mutate()
                .openAiApi(groqApi)
                .defaultOptions(OpenAiChatOptions.builder().model("llama3-70b-8192").temperature(0.5).build())
                .build();

            // Derive a new OpenAiChatModel for GPT-4
            OpenAiChatModel gpt4Model = baseChatModel.mutate()
                .openAiApi(gpt4Api)
                .defaultOptions(OpenAiChatOptions.builder().model("gpt-4").temperature(0.7).build())
                .build();

            // Simple prompt for both models
            String prompt = "What is the capital of France?";

            String groqResponse = ChatClient.builder(groqModel).build().prompt(prompt).call().content();
            String gpt4Response = ChatClient.builder(gpt4Model).build().prompt(prompt).call().content();

            logger.info("Groq (Llama3) response: {}", groqResponse);
            logger.info("OpenAI GPT-4 response: {}", gpt4Response);
        }
        catch (Exception e) {
            logger.error("Error in multi-client flow", e);
        }
    }
}

ChatClient 流暢 API

ChatClient 流暢 API 允許您使用過載的 prompt 方法以三種不同的方式建立提示,以啟動流暢 API。

  • prompt(): 此無引數方法允許您開始使用流暢 API,從而構建使用者、系統和提示的其他部分。

  • prompt(Prompt prompt): 此方法接受一個 Prompt 引數,允許您傳入使用 Prompt 的非流暢 API 建立的 Prompt 例項。

  • prompt(String content): 這是一個方便的方法,類似於前面的過載。它接受使用者的文字內容。

ChatClient 響應

ChatClient API 提供了多種使用流暢 API 格式化 AI 模型響應的方式。

返回 ChatResponse

AI 模型的響應是一個由型別 ChatResponse 定義的豐富結構。它包含有關響應如何生成的元資料,並且還可以包含多個響應,稱為 Generation,每個響應都有其自己的元資料。元資料包括用於建立響應的令牌數量(每個令牌大約是 3/4 個單詞)。此資訊很重要,因為託管 AI 模型根據每個請求使用的令牌數量收費。

下面透過在 call() 方法之後呼叫 chatResponse() 演示了返回包含元資料的 ChatResponse 物件的示例。

ChatResponse chatResponse = chatClient.prompt()
    .user("Tell me a joke")
    .call()
    .chatResponse();

返回實體

您經常希望返回從返回的 String 對映的實體類。entity() 方法提供了此功能。

例如,給定 Java 記錄

record ActorFilms(String actor, List<String> movies) {}

您可以使用 entity() 方法輕鬆地將 AI 模型的輸出對映到此記錄,如下所示:

ActorFilms actorFilms = chatClient.prompt()
    .user("Generate the filmography for a random actor.")
    .call()
    .entity(ActorFilms.class);

還有一個過載的 entity 方法,其簽名是 entity(ParameterizedTypeReference<T> type),它允許您指定泛型列表等型別。

List<ActorFilms> actorFilms = chatClient.prompt()
    .user("Generate the filmography of 5 movies for Tom Hanks and Bill Murray.")
    .call()
    .entity(new ParameterizedTypeReference<List<ActorFilms>>() {});

流式響應

stream() 方法允許您獲得非同步響應,如下所示:

Flux<String> output = chatClient.prompt()
    .user("Tell me a joke")
    .stream()
    .content();

您還可以使用方法 Flux<ChatResponse> chatResponse() 流式傳輸 ChatResponse

將來,我們將提供一個便捷方法,允許您使用響應式 stream() 方法返回 Java 實體。在此之前,您應該使用 結構化輸出轉換器 明確轉換聚合響應,如下所示。這也演示了在流暢 API 中使用引數,這將在文件的後面部分詳細討論。

var converter = new BeanOutputConverter<>(new ParameterizedTypeReference<List<ActorsFilms>>() {});

Flux<String> flux = this.chatClient.prompt()
    .user(u -> u.text("""
                        Generate the filmography for a random actor.
                        {format}
                      """)
            .param("format", this.converter.getFormat()))
    .stream()
    .content();

String content = this.flux.collectList().block().stream().collect(Collectors.joining());

List<ActorsFilms> actorFilms = this.converter.convert(this.content);

提示模板

ChatClient 流暢 API 允許您將使用者和系統文字作為模板提供,其中變數在執行時被替換。

String answer = ChatClient.create(chatModel).prompt()
    .user(u -> u
            .text("Tell me the names of 5 movies whose soundtrack was composed by {composer}")
            .param("composer", "John Williams"))
    .call()
    .content();

在內部,ChatClient 使用 PromptTemplate 類處理使用者和系統文字,並根據給定的 TemplateRenderer 實現,在執行時用提供的值替換變數。預設情況下,Spring AI 使用 StTemplateRenderer 實現,該實現基於 Terence Parr 開發的開源 StringTemplate 引擎。

Spring AI 還提供了一個 NoOpTemplateRenderer,用於不需要模板處理的情況。

直接在 ChatClient 上配置的 TemplateRenderer(透過 .templateRenderer())僅適用於直接在 ChatClient 構建器鏈中定義的提示內容(例如,透過 .user().system())。它影響由 Advisors(如 QuestionAnswerAdvisor)內部使用的模板,這些 Advisor 有自己的模板自定義機制(參見 自定義 Advisor 模板)。

如果您更喜歡使用不同的模板引擎,可以直接向 ChatClient 提供 TemplateRenderer 介面的自定義實現。您也可以繼續使用預設的 StTemplateRenderer,但使用自定義配置。

例如,預設情況下,模板變數由 {} 語法標識。如果您打算在提示中包含 JSON,您可能需要使用不同的語法來避免與 JSON 語法衝突。例如,您可以使用 <> 分隔符。

String answer = ChatClient.create(chatModel).prompt()
    .user(u -> u
            .text("Tell me the names of 5 movies whose soundtrack was composed by <composer>")
            .param("composer", "John Williams"))
    .templateRenderer(StTemplateRenderer.builder().startDelimiterToken('<').endDelimiterToken('>').build())
    .call()
    .content();

call() 返回值

ChatClient 上指定 call() 方法後,響應型別有幾種不同的選項。

  • String content(): 返回響應的字串內容

  • ChatResponse chatResponse(): 返回 ChatResponse 物件,該物件包含多個生成以及有關響應的元資料,例如用於建立響應的令牌數量。

  • ChatClientResponse chatClientResponse(): 返回一個 ChatClientResponse 物件,該物件包含 ChatResponse 物件和 ChatClient 執行上下文,使您可以訪問 Advisor 執行期間使用的額外資料(例如,RAG 流中檢索到的相關文件)。

  • entity() 返回 Java 型別

    • entity(ParameterizedTypeReference<T> type): 用於返回實體型別的 Collection

    • entity(Class<T> type): 用於返回特定實體型別。

    • entity(StructuredOutputConverter<T> structuredOutputConverter): 用於指定 StructuredOutputConverter 的例項,將 String 轉換為實體型別。

  • responseEntity() 返回 ChatResponse 和 Java 型別。當您需要在一次呼叫中同時訪問完整的 AI 模型響應(帶元資料和生成)和結構化輸出實體時,這非常有用。

    • responseEntity(Class<T> type): 用於返回包含完整 ChatResponse 物件和特定實體型別的 ResponseEntity

    • responseEntity(ParameterizedTypeReference<T> type): 用於返回包含完整 ChatResponse 物件和實體型別 CollectionResponseEntity

    • responseEntity(StructuredOutputConverter<T> structuredOutputConverter): 用於返回包含完整 ChatResponse 物件和使用指定 StructuredOutputConverter 轉換的實體的 ResponseEntity

您還可以呼叫 stream() 方法而不是 call()

呼叫 call() 方法實際上不會觸發 AI 模型執行。相反,它只指示 Spring AI 是否使用同步或流式呼叫。實際的 AI 模型呼叫發生在 content()chatResponse()responseEntity() 等方法被呼叫時。

stream() 返回值

ChatClient 上指定 stream() 方法後,響應型別有幾個選項。

  • Flux<String> content(): 返回 AI 模型正在生成的字串的 Flux

  • Flux<ChatResponse> chatResponse(): 返回 ChatResponse 物件的 Flux,該物件包含有關響應的其他元資料。

  • Flux<ChatClientResponse> chatClientResponse(): 返回 ChatClientResponse 物件的 Flux,該物件包含 ChatResponse 物件和 ChatClient 執行上下文,使您可以訪問 Advisor 執行期間使用的額外資料(例如,RAG 流中檢索到的相關文件)。

訊息元資料

ChatClient 支援向用戶和系統訊息新增元資料。元資料提供了有關訊息的額外上下文和資訊,可由 AI 模型或下游處理使用。

向用戶訊息新增元資料

您可以使用 metadata() 方法向用戶訊息新增元資料。

// Adding individual metadata key-value pairs
String response = chatClient.prompt()
    .user(u -> u.text("What's the weather like?")
        .metadata("messageId", "msg-123")
        .metadata("userId", "user-456")
        .metadata("priority", "high"))
    .call()
    .content();

// Adding multiple metadata entries at once
Map<String, Object> userMetadata = Map.of(
    "messageId", "msg-123",
    "userId", "user-456",
    "timestamp", System.currentTimeMillis()
);

String response = chatClient.prompt()
    .user(u -> u.text("What's the weather like?")
        .metadata(userMetadata))
    .call()
    .content();

向系統訊息新增元資料

同樣,您可以向系統訊息新增元資料。

// Adding metadata to system messages
String response = chatClient.prompt()
    .system(s -> s.text("You are a helpful assistant.")
        .metadata("version", "1.0")
        .metadata("model", "gpt-4"))
    .user("Tell me a joke")
    .call()
    .content();

預設元資料支援

您還可以在 ChatClient 構建器級別配置預設元資料。

@Configuration
class Config {
    @Bean
    ChatClient chatClient(ChatClient.Builder builder) {
        return builder
            .defaultSystem(s -> s.text("You are a helpful assistant")
                .metadata("assistantType", "general")
                .metadata("version", "1.0"))
            .defaultUser(u -> u.text("Default user context")
                .metadata("sessionId", "default-session"))
            .build();
    }
}

元資料驗證

ChatClient 驗證元資料以確保資料完整性。

  • 元資料鍵不能為 null 或空。

  • 元資料值不能為 null。

  • 傳遞 Map 時,鍵和值都不能包含 null 元素。

// This will throw an IllegalArgumentException
chatClient.prompt()
    .user(u -> u.text("Hello")
        .metadata(null, "value"))  // Invalid: null key
    .call()
    .content();

// This will also throw an IllegalArgumentException
chatClient.prompt()
    .user(u -> u.text("Hello")
        .metadata("key", null))    // Invalid: null value
    .call()
    .content();

訪問元資料

元資料包含在生成的 UserMessage 和 SystemMessage 物件中,可以透過訊息的 getMetadata() 方法訪問。這在 Advisor 中處理訊息或檢查對話歷史記錄時特別有用。

使用預設值

@Configuration 類中建立具有預設系統文字的 ChatClient 可簡化執行時程式碼。透過設定預設值,您在呼叫 ChatClient 時只需指定使用者文字,無需在執行時程式碼路徑中為每個請求設定系統文字。

預設系統文字

在下面的示例中,我們將配置系統文字始終以海盜的語氣回覆。為了避免在執行時程式碼中重複系統文字,我們將在 @Configuration 類中建立一個 ChatClient 例項。

@Configuration
class Config {

    @Bean
    ChatClient chatClient(ChatClient.Builder builder) {
        return builder.defaultSystem("You are a friendly chat bot that answers question in the voice of a Pirate")
                .build();
    }

}

以及一個 @RestController 來呼叫它。

@RestController
class AIController {

	private final ChatClient chatClient;

	AIController(ChatClient chatClient) {
		this.chatClient = chatClient;
	}

	@GetMapping("/ai/simple")
	public Map<String, String> completion(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
		return Map.of("completion", this.chatClient.prompt().user(message).call().content());
	}
}

透過 curl 呼叫應用程式端點時,結果如下:

❯ curl localhost:8080/ai/simple
{"completion":"Why did the pirate go to the comedy club? To hear some arrr-rated jokes! Arrr, matey!"}

帶引數的預設系統文字

在下面的示例中,我們將在系統文字中使用佔位符,以便在執行時而不是設計時指定完成的語氣。

@Configuration
class Config {

    @Bean
    ChatClient chatClient(ChatClient.Builder builder) {
        return builder.defaultSystem("You are a friendly chat bot that answers question in the voice of a {voice}")
                .build();
    }

}
@RestController
class AIController {
	private final ChatClient chatClient;

	AIController(ChatClient chatClient) {
		this.chatClient = chatClient;
	}

	@GetMapping("/ai")
	Map<String, String> completion(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message, String voice) {
		return Map.of("completion",
				this.chatClient.prompt()
						.system(sp -> sp.param("voice", voice))
						.user(message)
						.call()
						.content());
	}

}

透過 httpie 呼叫應用程式端點時,結果如下:

http localhost:8080/ai voice=='Robert DeNiro'
{
    "completion": "You talkin' to me? Okay, here's a joke for ya: Why couldn't the bicycle stand up by itself? Because it was two tired! Classic, right?"
}

其他預設值

ChatClient.Builder 級別,您可以指定預設提示配置。

  • defaultOptions(ChatOptions chatOptions): 傳入在 ChatOptions 類中定義的行動式選項或模型特定選項,例如 OpenAiChatOptions 中的選項。有關模型特定的 ChatOptions 實現的更多資訊,請參閱 JavaDocs。

  • defaultFunction(String name, String description, java.util.function.Function<I, O> function): name 用於在使用者文字中引用函式。description 解釋函式目的並幫助 AI 模型選擇正確的函式以獲得準確的響應。function 引數是模型在必要時將執行的 Java 函式例項。

  • defaultFunctions(String…​ functionNames): 應用程式上下文中定義的 `java.util.Function` 的 bean 名稱。

  • defaultUser(String text), defaultUser(Resource text), defaultUser(Consumer<UserSpec> userSpecConsumer): 這些方法允許您定義使用者文字。Consumer<UserSpec> 允許您使用 lambda 來指定使用者文字和任何預設引數。

  • defaultAdvisors(Advisor…​ advisor): Advisor 允許修改用於建立 Prompt 的資料。QuestionAnswerAdvisor 實現透過將提示附加與使用者文字相關的上下文資訊來啟用 檢索增強生成 模式。

  • defaultAdvisors(Consumer<AdvisorSpec> advisorSpecConsumer): 此方法允許您定義一個 Consumer,以使用 AdvisorSpec 配置多個 Advisor。Advisor 可以修改用於建立最終 Prompt 的資料。Consumer<AdvisorSpec> 允許您指定一個 lambda 來新增 Advisor,例如 QuestionAnswerAdvisor,它透過根據使用者文字附加相關的上下文資訊來支援 檢索增強生成

您可以使用不帶 default 字首的相應方法在執行時覆蓋這些預設值。

  • options(ChatOptions chatOptions)

  • function(String name, String description, java.util.function.Function<I, O> function)

  • functions(String…​ functionNames)

  • user(String text), user(Resource text), user(Consumer<UserSpec> userSpecConsumer)

  • advisors(Advisor…​ advisor)

  • advisors(Consumer<AdvisorSpec> advisorSpecConsumer)

Advisor

Advisors API 提供了一種靈活而強大的方式來攔截、修改和增強 Spring 應用程式中 AI 驅動的互動。

當使用使用者文字呼叫 AI 模型時,常見的模式是用上下文資料附加或增強提示。

此上下文資料可以是不同型別。常見型別包括:

  • 您自己的資料:這是 AI 模型尚未訓練的資料。即使模型看到了類似的資料,附加的上下文資料在生成響應時也具有優先權。

  • 對話歷史記錄:聊天模型的 API 是無狀態的。如果您告訴 AI 模型您的名字,它在後續互動中不會記住它。每次請求都必須傳送對話歷史記錄,以確保在生成響應時考慮先前的互動。

ChatClient 中的 Advisor 配置

ChatClient 流暢 API 提供了一個 AdvisorSpec 介面用於配置 Advisor。此介面提供了新增引數、一次設定多個引數以及向鏈中新增一個或多個 Advisor 的方法。

interface AdvisorSpec {
    AdvisorSpec param(String k, Object v);
    AdvisorSpec params(Map<String, Object> p);
    AdvisorSpec advisors(Advisor... advisors);
    AdvisorSpec advisors(List<Advisor> advisors);
}
Advisor 新增到鏈中的順序至關重要,因為它決定了它們的執行順序。每個 Advisor 都以某種方式修改提示或上下文,一個 Advisor 所做的更改將傳遞給鏈中的下一個 Advisor。
ChatClient.builder(chatModel)
    .build()
    .prompt()
    .advisors(
        MessageChatMemoryAdvisor.builder(chatMemory).build(),
        QuestionAnswerAdvisor.builder(vectorStore).build()
    )
    .user(userText)
    .call()
    .content();

在此配置中,MessageChatMemoryAdvisor 將首先執行,將對話歷史記錄新增到提示中。然後,QuestionAnswerAdvisor 將根據使用者的問題和新增的對話歷史記錄執行其搜尋,可能會提供更相關的結果。

檢索增強生成

請參閱檢索增強生成指南。

日誌記錄

SimpleLoggerAdvisor 是一個 Advisor,它記錄 ChatClientrequestresponse 資料。這對於除錯和監控您的 AI 互動非常有用。

Spring AI 支援 LLM 和向量儲存互動的可觀測性。有關更多資訊,請參閱可觀測性指南。

要啟用日誌記錄,請在建立 ChatClient 時將 SimpleLoggerAdvisor 新增到 Advisor 鏈中。建議將其新增到鏈的末尾。

ChatResponse response = ChatClient.create(chatModel).prompt()
        .advisors(new SimpleLoggerAdvisor())
        .user("Tell me a joke?")
        .call()
        .chatResponse();

要檢視日誌,請將 Advisor 包的日誌級別設定為 DEBUG

logging.level.org.springframework.ai.chat.client.advisor=DEBUG

將其新增到您的 application.propertiesapplication.yaml 檔案中。

您可以使用以下建構函式自定義從 AdvisedRequestChatResponse 記錄的資料:

SimpleLoggerAdvisor(
    Function<ChatClientRequest, String> requestToString,
    Function<ChatResponse, String> responseToString,
    int order
)

用法示例:

SimpleLoggerAdvisor customLogger = new SimpleLoggerAdvisor(
    request -> "Custom request: " + request.prompt().getUserMessage(),
    response -> "Custom response: " + response.getResult(),
    0
);

這允許您根據您的特定需求調整記錄的資訊。

在生產環境中記錄敏感資訊時要小心。

聊天記憶

介面 ChatMemory 表示聊天對話記憶的儲存。它提供將訊息新增到對話、從對話中檢索訊息和清除對話歷史記錄的方法。

目前有一個內建實現:MessageWindowChatMemory

MessageWindowChatMemory 是一種聊天記憶實現,它維護一個訊息視窗,最大大小為指定值(預設值:20 條訊息)。當訊息數量超過此限制時,較舊的訊息將被逐出,但系統訊息會保留。如果新增新的系統訊息,所有以前的系統訊息都將從記憶中移除。這確保了對話始終可用最新的上下文,同時保持記憶體使用量受限。

MessageWindowChatMemoryChatMemoryRepository 抽象支援,該抽象為聊天對話記憶提供儲存實現。有多種實現可用,包括 InMemoryChatMemoryRepositoryJdbcChatMemoryRepositoryCassandraChatMemoryRepositoryNeo4jChatMemoryRepository

有關更多詳細資訊和使用示例,請參見聊天記憶文件。

實現注意事項

ChatClient 中命令式和響應式程式設計模型的組合使用是 API 的一個獨特方面。通常,應用程式要麼是響應式的,要麼是命令式的,但不會兩者兼而有之。

  • 在自定義模型實現的 HTTP 客戶端互動時,必須同時配置 RestClient 和 WebClient。

由於 Spring Boot 3.4 中的一個錯誤,必須設定“spring.http.client.factory=jdk”屬性。否則,它預設設定為“reactor”,這會破壞某些 AI 工作流,例如 ImageModel。

  • 流式傳輸僅透過響應式堆疊支援。因此,命令式應用程式必須包含響應式堆疊(例如 spring-boot-starter-webflux)。

  • 非流式傳輸僅透過 Servlet 堆疊支援。因此,響應式應用程式必須包含 Servlet 堆疊(例如 spring-boot-starter-web),並期望某些呼叫是阻塞的。

  • 工具呼叫是命令式的,導致阻塞工作流。這還會導致 Micrometer 觀察結果不完整/中斷(例如,ChatClient 跨度和工具呼叫跨度未連線,因此第一個跨度不完整)。

  • 內建 Advisor 對標準呼叫執行阻塞操作,對流式呼叫執行非阻塞操作。用於 Advisor 流式呼叫的 Reactor Scheduler 可以透過每個 Advisor 類上的 Builder 進行配置。

© . This site is unofficial and not affiliated with VMware.