You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chatclient.adoc
+102-1Lines changed: 102 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -379,6 +379,107 @@ After specifying the `stream()` method on `ChatClient`, there are a few options
379
379
* `Flux<ChatResponse> chatResponse()`: Returns a `Flux` of the `ChatResponse` object, which contains additional metadata about the response.
380
380
* `Flux<ChatClientResponse> chatClientResponse()`: returns a `Flux` of the `ChatClientResponse` object that contains the `ChatResponse` object and the ChatClient execution context, giving you access to additional data used during the execution of advisors (e.g. the relevant documents retrieved in a RAG flow).
381
381
382
+
== Message Metadata
383
+
384
+
The ChatClient supports adding metadata to both user and system messages.
385
+
Metadata provides additional context and information about messages that can be used by the AI model or downstream processing.
386
+
387
+
=== Adding Metadata to User Messages
388
+
389
+
You can add metadata to user messages using the `metadata()` methods:
390
+
391
+
[source,java]
392
+
----
393
+
// Adding individual metadata key-value pairs
394
+
String response = chatClient.prompt()
395
+
.user(u -> u.text("What's the weather like?")
396
+
.metadata("messageId", "msg-123")
397
+
.metadata("userId", "user-456")
398
+
.metadata("priority", "high"))
399
+
.call()
400
+
.content();
401
+
402
+
// Adding multiple metadata entries at once
403
+
Map<String, Object> userMetadata = Map.of(
404
+
"messageId", "msg-123",
405
+
"userId", "user-456",
406
+
"timestamp", System.currentTimeMillis()
407
+
);
408
+
409
+
String response = chatClient.prompt()
410
+
.user(u -> u.text("What's the weather like?")
411
+
.metadata(userMetadata))
412
+
.call()
413
+
.content();
414
+
----
415
+
416
+
=== Adding Metadata to System Messages
417
+
418
+
Similarly, you can add metadata to system messages:
419
+
420
+
[source,java]
421
+
----
422
+
// Adding metadata to system messages
423
+
String response = chatClient.prompt()
424
+
.system(s -> s.text("You are a helpful assistant.")
425
+
.metadata("version", "1.0")
426
+
.metadata("model", "gpt-4"))
427
+
.user("Tell me a joke")
428
+
.call()
429
+
.content();
430
+
----
431
+
432
+
=== Default Metadata Support
433
+
434
+
You can also configure default metadata at the ChatClient builder level:
.defaultSystem(s -> s.text("You are a helpful assistant")
444
+
.metadata("assistantType", "general")
445
+
.metadata("version", "1.0"))
446
+
.defaultUser(u -> u.text("Default user context")
447
+
.metadata("sessionId", "default-session"))
448
+
.build();
449
+
}
450
+
}
451
+
----
452
+
453
+
=== Metadata Validation
454
+
455
+
The ChatClient validates metadata to ensure data integrity:
456
+
457
+
* Metadata keys cannot be null or empty
458
+
* Metadata values cannot be null
459
+
* When passing a Map, neither keys nor values can contain null elements
460
+
461
+
[source,java]
462
+
----
463
+
// This will throw an IllegalArgumentException
464
+
chatClient.prompt()
465
+
.user(u -> u.text("Hello")
466
+
.metadata(null, "value")) // Invalid: null key
467
+
.call()
468
+
.content();
469
+
470
+
// This will also throw an IllegalArgumentException
471
+
chatClient.prompt()
472
+
.user(u -> u.text("Hello")
473
+
.metadata("key", null)) // Invalid: null value
474
+
.call()
475
+
.content();
476
+
----
477
+
478
+
=== Accessing Metadata
479
+
480
+
The metadata is included in the generated UserMessage and SystemMessage objects and can be accessed through the message's `getMetadata()` method.
481
+
This is particularly useful when processing messages in advisors or when examining the conversation history.
482
+
382
483
== Using Defaults
383
484
384
485
Creating a `ChatClient` with a default system text in an `@Configuration` class simplifies runtime code.
@@ -645,4 +746,4 @@ Due to a bug in Spring Boot 3.4, the "spring.http.client.factory=jdk" property m
645
746
* Streaming is only supported via the Reactive stack. Imperative applications must include the Reactive stack for this reason (e.g. spring-boot-starter-webflux).
646
747
* Non-streaming is only supportive via the Servlet stack. Reactive applications must include the Servlet stack for this reason (e.g. spring-boot-starter-web) and expect some calls to be blocking.
647
748
* Tool calling is imperative, leading to blocking workflows. This also results in partial/interrupted Micrometer observations (e.g. the ChatClient spans and the tool calling spans are not connected, with the first one remaining incomplete for that reason).
648
-
* The built-in advisors perform blocking operations for standards calls, and non-blocking operations for streaming calls. The Reactor Scheduler used for the advisor streaming calls can be configured via the Builder on each Advisor class.
749
+
* The built-in advisors perform blocking operations for standards calls, and non-blocking operations for streaming calls. The Reactor Scheduler used for the advisor streaming calls can be configured via the Builder on each Advisor class.
0 commit comments