Skip to content

Commit

Permalink
Add prompt(String) method to ChatClient
Browse files Browse the repository at this point in the history
This commit introduces a new overloaded method prompt(String content)
to the ChatClient API. It provides a convenient way to create prompts
using only a string of user content, simplifying the process for basic
chat interactions.

Fixes spring-projectsgh-1286

Signed-off-by: Thomas Vitale <[email protected]>
  • Loading branch information
ThomasVitale authored and Mark Pollack committed Sep 23, 2024
1 parent c67442d commit acb31e7
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ static Builder builder(ChatModel chatModel, ObservationRegistry observationRegis

ChatClientRequestSpec prompt();

ChatClientPromptRequestSpec prompt(String content);

ChatClientPromptRequestSpec prompt(Prompt prompt);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ public ChatClientRequestSpec prompt() {
return new DefaultChatClientRequestSpec(this.defaultChatClientRequest);
}

@Override
public ChatClientPromptRequestSpec prompt(String content) {
return new DefaultChatClientPromptRequestSpec(this.chatModel, new Prompt(content));
}

@Override
public ChatClientPromptRequestSpec prompt(Prompt prompt) {
return new DefaultChatClientPromptRequestSpec(this.chatModel, prompt);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,19 @@ public void defaultUserText() {
assertThat(userMessage.getMessageType()).isEqualTo(MessageType.USER);
}

@Test
public void simpleUserPromptAsString() {
when(chatModel.call(promptCaptor.capture()))
.thenReturn(new ChatResponse(List.of(new Generation(new AssistantMessage("response")))));

assertThat(ChatClient.builder(chatModel).build().prompt("User prompt").call().content())
.isEqualTo("response");

Message userMessage = promptCaptor.getValue().getInstructions().get(0);
assertThat(userMessage.getContent()).isEqualTo("User prompt");
assertThat(userMessage.getMessageType()).isEqualTo(MessageType.USER);
}

@Test
public void simpleUserPrompt() {
when(chatModel.call(promptCaptor.capture()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,20 @@ ChatClient.Builder builder = ChatClient.builder(myChatModel);
ChatClient chatClient = ChatClient.create(myChatModel);
----

== ChatClient Fluent API

The `ChatClient` fluent API allows you to create a prompt in three distinct ways using an overloaded `prompt` method to initiate the fluent API.

* `prompt()`: This method with no arguments is the most flexible, allowing you to build up user, system, and other parts of the prompt using the fluent API.

* `prompt(Prompt prompt)`: This method accepts a `Prompt` argument, letting you pass in a `Prompt` instance that you have created using the Prompt's non-fluent APIs. The prompt passed to the model is 'sealed', meaning you can't modify it using fluent API methods.

* `prompt(String content)`: This is a convenience method similar to the previous overload. It takes the user's text content and creates a `Prompt` instance internally via `new Prompt(content)`.


== ChatClient Responses

The `ChatClient` API offers several ways to format the response from the AI Model.
The `ChatClient` API offers several ways to format the response from the AI Model using the fluent API.

=== Returning a ChatResponse

Expand All @@ -85,6 +96,7 @@ ChatResponse chatResponse = chatClient.prompt()
.chatResponse();
----


=== Returning an Entity

You often want to return an entity class that is mapped from the returned `String`.
Expand Down Expand Up @@ -318,6 +330,39 @@ This contextual data can be of different types. Common types include:

* **Conversational history**: The chat model's API is stateless. If you tell the AI model your name, it won't remember it in subsequent interactions. Conversational history must be sent with each request to ensure previous interactions are considered when generating a response.


=== Advisor Configuration in ChatClient

The ChatClient fluent API provides an `AdvisorSpec` interface for configuring advisors. This interface offers methods to add parameters, set multiple parameters at once, and add one or more advisors to the chain.

[source,java]
----
interface AdvisorSpec {
AdvisorSpec param(String k, Object v);
AdvisorSpec params(Map<String, Object> p);
AdvisorSpec advisors(Advisor... advisors);
AdvisorSpec advisors(List<Advisor> advisors);
}
----

IMPORTANT: The order in which advisors are added to the chain is crucial, as it determines the sequence of their execution. Each advisor modifies the prompt or the context in some way, and the changes made by one advisor are passed on to the next in the chain.

[source,java]
----
ChatClient.builder(chatModel)
.build()
.prompt()
.advisors(
new ChatMemoryAdvisor(chatMemory),
new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults())
)
.user(userText)
.call();
----

In this configuration, the `ChatMemoryAdvisor` will be executed first, adding the conversation history to the prompt. Then, the `QuestionAnswerAdvisor` will perform its search based on the user's question and the added conversation history, potentially providing more relevant results.


=== Retrieval Augmented Generation

A vector database stores data that the AI model is unaware of.
Expand Down Expand Up @@ -427,6 +472,8 @@ public class CustomerSupportAssistant {
}
----



=== Logging

The `SimpleLoggerAdvisor` is an advisor that logs the `request` and `response` data of the `ChatClient`.
Expand Down

0 comments on commit acb31e7

Please sign in to comment.