Skip to content

Commit 83f3ebb

Browse files
authored
Manually add chat interaction (#101)
2 parents 8db82f4 + 2299cc6 commit 83f3ebb

File tree

19 files changed

+145
-48
lines changed

19 files changed

+145
-48
lines changed

README.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,15 @@ If necessary, it is possibile to provide a custom Cache by implementing the [ICh
8080
```csharp
8181
public class LocalMessageCache : IChatGptCache
8282
{
83-
private readonly Dictionary<Guid, List<ChatGptMessage>> localCache = new();
83+
private readonly Dictionary<Guid, IEnumerable<ChatGptMessage>> localCache = new();
8484

8585
public Task SetAsync(Guid conversationId, IEnumerable<ChatGptMessage> messages, TimeSpan expiration, CancellationToken cancellationToken = default)
8686
{
8787
localCache[conversationId] = messages.ToList();
8888
return Task.CompletedTask;
8989
}
9090

91-
public Task<List<ChatGptMessage>?> GetAsync(Guid conversationId, CancellationToken cancellationToken = default)
91+
public Task<IEnumerable<ChatGptMessage>?> GetAsync(Guid conversationId, CancellationToken cancellationToken = default)
9292
{
9393
localCache.TryGetValue(conversationId, out var messages);
9494
return Task.FromResult(messages);
@@ -211,14 +211,23 @@ var message = response.GetMessage();
211211
The **AskAsync** and **AskStreamAsync** (see below) methods provides overloads that require a *conversationId* parameter. If we pass an empty value, a random one is generated and returned.
212212
We can pass this value in subsequent invocations of **AskAsync** or **AskStreamAsync**, so that the library automatically retrieves previous messages of the current conversation (according to *MessageLimit* and *MessageExpiration* settings) and send them to chat completion API.
213213

214-
This is the default behavior for all the chat interactions. If you want to exlude a particular interaction from the conversation history, you can set the *addToChatHistory* argument to *false*:
214+
This is the default behavior for all the chat interactions. If you want to exlude a particular interaction from the conversation history, you can set the *addToConversationHistory* argument to *false*:
215215

216216
```csharp
217-
var response = await chatGptClient.AskAsync(conversationId, message, addToChatHistory: false);
217+
var response = await chatGptClient.AskAsync(conversationId, message, addToConversationHistory: false);
218218
```
219219

220220
In this way, the message will be sent to the chat completion API, but it and the corresponding answer from ChatGPT will not be added to the conversation history.
221221

222+
On the other hand, in some scenarios, it could be useful to manually add a chat interaction (i.e., a question followed by an answer) to the conversation history. For example, we may want to add a message that was generated by a bot. In this case, we can use the **AddInteractionAsync** method:
223+
224+
```csharp
225+
await chatGptClient.AskInteractionAsync(conversationId, question: "What is the weather like in Taggia?",
226+
answer: "It's Always Sunny in Taggia");
227+
```
228+
229+
The question will be added as *user* message and the answer will be added as *assistant* message in the conversation history. As always, these new messages (respecting the *MessageLimit* option) will be used in subsequent invocations of **AskAsync** or **AskStreamAsync**.
230+
222231
### Response streaming
223232

224233
Chat completion API supports response streaming. When using this feature, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only server-sent events as they become available. **ChatGptNet** provides response streaming using the **AskStreamAsync** method:

docs/ChatGptNet.Models/ChatGptResponse/Usage.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ Gets or sets information about token usage.
66
public ChatGptUsage? Usage { get; set; }
77
```
88

9+
## Remarks
10+
11+
The `Usage` property is always `null` when requesting response streaming with CancellationToken).
12+
913
## See Also
1014

1115
* class [ChatGptUsage](../ChatGptUsage.md)

docs/ChatGptNet/IChatGptCache/GetAsync.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Gets the list of messages for the given *conversationId*.
44

55
```csharp
6-
public Task<List<ChatGptMessage>?> GetAsync(Guid conversationId,
6+
public Task<IEnumerable<ChatGptMessage>?> GetAsync(Guid conversationId,
77
CancellationToken cancellationToken = default)
88
```
99

docs/ChatGptNet/IChatGptClient.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public interface IChatGptClient
1111
| name | description |
1212
| --- | --- |
1313
| [AddFunctionResponseAsync](IChatGptClient/AddFunctionResponseAsync.md)(…) | Adds a function response to the conversation history. |
14+
| [AddInteractionAsync](IChatGptClient/AddInteractionAsync.md)(…) | Explicitly adds a new interaction (a question and the corresponding answer) to the conversation history. |
1415
| [AskAsync](IChatGptClient/AskAsync.md)(…) | Requests a new chat interaction using the default completion model specified in the [`DefaultModel`](./ChatGptOptions/DefaultModel.md) property. (4 methods) |
1516
| [AskStreamAsync](IChatGptClient/AskStreamAsync.md)(…) | Requests a new chat interaction (using the default completion model specified in the [`DefaultModel`](./ChatGptOptions/DefaultModel.md) property) with streaming response, like in ChatGPT. (2 methods) |
1617
| [ConversationExistsAsync](IChatGptClient/ConversationExistsAsync.md)(…) | Determines if a chat conversation exists. |

docs/ChatGptNet/IChatGptClient/AddFunctionResponseAsync.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ The Task corresponding to the asynchronous operation.
2727
## See Also
2828

2929
* method [AskAsync](./AskAsync.md)
30+
* method [AskStreamAsync](./AskStreamAsync.md)
3031
* class [ChatGptFunctionCall](../../ChatGptNet.Models/ChatGptFunctionCall.md)
3132
* interface [IChatGptClient](../IChatGptClient.md)
3233
* namespace [ChatGptNet](../../ChatGptNet.md)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# IChatGptClient.AddInteractionAsync method
2+
3+
Explicitly adds a new interaction (a question and the corresponding answer) to the conversation history.
4+
5+
```csharp
6+
public Task AddInteractionAsync(Guid conversationId, string question, string answer,
7+
CancellationToken cancellationToken = default)
8+
```
9+
10+
| parameter | description |
11+
| --- | --- |
12+
| conversationId | The unique identifier of the conversation. |
13+
| question | The question. |
14+
| answer | The answer. |
15+
| cancellationToken | The token to monitor for cancellation requests. |
16+
17+
## Return Value
18+
19+
The Task corresponding to the asynchronous operation.
20+
21+
## Exceptions
22+
23+
| exception | condition |
24+
| --- | --- |
25+
| ArgumentNullException | *question* or *answer* are `null`. |
26+
27+
## See Also
28+
29+
* interface [IChatGptClient](../IChatGptClient.md)
30+
* namespace [ChatGptNet](../../ChatGptNet.md)
31+
32+
<!-- DO NOT EDIT: generated by xmldocmd for ChatGptNet.dll -->

docs/ChatGptNet/IChatGptClient/AskAsync.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ Requests a new chat interaction using the default completion model specified in
44

55
```csharp
66
public Task<ChatGptResponse> AskAsync(string message, ChatGptParameters? parameters = null,
7-
CancellationToken cancellationToken = default)
7+
bool addToConversationHistory = true, CancellationToken cancellationToken = default)
88
```
99

1010
| parameter | description |
1111
| --- | --- |
1212
| message | The message. |
1313
| parameters | A [`ChatGptParameters`](../../ChatGptNet.Models/ChatGptParameters.md) object used to override the default completion parameters in the [`DefaultParameters`](../ChatGptOptions/DefaultParameters.md) property. |
14+
| addToConversationHistory | Set to `true` to add the current chat interaction to the conversation history. |
1415
| cancellationToken | The token to monitor for cancellation requests. |
1516

1617
## Return Value
@@ -45,14 +46,15 @@ Requests a new chat interaction using the default completion model specified in
4546
```csharp
4647
public Task<ChatGptResponse> AskAsync(string message,
4748
ChatGptFunctionParameters? functionParameters, ChatGptParameters? parameters = null,
48-
CancellationToken cancellationToken = default)
49+
bool addToConversationHistory = true, CancellationToken cancellationToken = default)
4950
```
5051

5152
| parameter | description |
5253
| --- | --- |
5354
| message | The message. |
5455
| functionParameters | A [`ChatGptFunctionParameters`](../../ChatGptNet.Models/ChatGptFunctionParameters.md) object that contains the list of available functions for calling. |
5556
| parameters | A [`ChatGptParameters`](../../ChatGptNet.Models/ChatGptParameters.md) object used to override the default completion parameters in the [`DefaultParameters`](../ChatGptOptions/DefaultParameters.md) property. |
57+
| addToConversationHistory | Set to `true` to add the current chat interaction to the conversation history. |
5658
| cancellationToken | The token to monitor for cancellation requests. |
5759

5860
## Return Value
@@ -90,7 +92,7 @@ Requests a chat interaction.
9092
```csharp
9193
public Task<ChatGptResponse> AskAsync(Guid conversationId, string message,
9294
ChatGptParameters? parameters = null, string? model = null,
93-
CancellationToken cancellationToken = default)
95+
bool addToConversationHistory = true, CancellationToken cancellationToken = default)
9496
```
9597

9698
| parameter | description |
@@ -99,6 +101,7 @@ public Task<ChatGptResponse> AskAsync(Guid conversationId, string message,
99101
| message | The message. |
100102
| parameters | A object used to override the default completion parameters in the [`DefaultParameters`](../ChatGptOptions/DefaultParameters.md) property. |
101103
| model | The chat completion model to use. If model is `null`, then the one specified in the [`DefaultModel`](../ChatGptOptions/DefaultModel.md) property will be used. |
104+
| addToConversationHistory | Set to `true` to add the current chat interaction to the conversation history. |
102105
| cancellationToken | The token to monitor for cancellation requests. |
103106

104107
## Return Value
@@ -128,7 +131,8 @@ Requests a chat interaction.
128131
```csharp
129132
public Task<ChatGptResponse> AskAsync(Guid conversationId, string message,
130133
ChatGptFunctionParameters? functionParameters, ChatGptParameters? parameters = null,
131-
string? model = null, CancellationToken cancellationToken = default)
134+
string? model = null, bool addToConversationHistory = true,
135+
CancellationToken cancellationToken = default)
132136
```
133137

134138
| parameter | description |
@@ -138,6 +142,7 @@ public Task<ChatGptResponse> AskAsync(Guid conversationId, string message,
138142
| functionParameters | A [`ChatGptFunctionParameters`](../../ChatGptNet.Models/ChatGptFunctionParameters.md) object that contains the list of available functions for calling. |
139143
| parameters | A object used to override the default completion parameters in the [`DefaultParameters`](../ChatGptOptions/DefaultParameters.md) property. |
140144
| model | The chat completion model to use. If model is `null`, then the one specified in the [`DefaultModel`](../ChatGptOptions/DefaultModel.md) property will be used. |
145+
| addToConversationHistory | Set to `true` to add the current chat interaction to the conversation history. |
141146
| cancellationToken | The token to monitor for cancellation requests. |
142147

143148
## Return Value

docs/ChatGptNet/IChatGptClient/AskStreamAsync.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ Requests a new chat interaction (using the default completion model specified in
44

55
```csharp
66
public IAsyncEnumerable<ChatGptResponse> AskStreamAsync(string message,
7-
ChatGptParameters? parameters = null, CancellationToken cancellationToken = default)
7+
ChatGptParameters? parameters = null, bool addToConversationHistory = true,
8+
CancellationToken cancellationToken = default)
89
```
910

1011
| parameter | description |
1112
| --- | --- |
1213
| message | The message. |
1314
| parameters | A [`ChatGptParameters`](../../ChatGptNet.Models/ChatGptParameters.md) object used to override the default completion parameters in the [`DefaultParameters`](../ChatGptOptions/DefaultParameters.md) property. |
15+
| addToConversationHistory | Set to `true` to add the current chat interaction to the conversation history. |
1416
| cancellationToken | The token to monitor for cancellation requests. |
1517

1618
## Return Value
@@ -44,7 +46,7 @@ Requests a chat interaction with streaming response, like in ChatGPT.
4446
```csharp
4547
public IAsyncEnumerable<ChatGptResponse> AskStreamAsync(Guid conversationId, string message,
4648
ChatGptParameters? parameters = null, string? model = null,
47-
CancellationToken cancellationToken = default)
49+
bool addToConversationHistory = true, CancellationToken cancellationToken = default)
4850
```
4951

5052
| parameter | description |
@@ -53,6 +55,7 @@ public IAsyncEnumerable<ChatGptResponse> AskStreamAsync(Guid conversationId, str
5355
| message | The message. |
5456
| parameters | A [`ChatGptParameters`](../../ChatGptNet.Models/ChatGptParameters.md) object used to override the default completion parameters in the [`DefaultParameters`](../ChatGptOptions/DefaultParameters.md) property. |
5557
| model | The chat completion model to use. If model is `null`, then the one specified in the [`DefaultModel`](../ChatGptOptions/DefaultModel.md) property will be used. |
58+
| addToConversationHistory | Set to `true` to add the current chat interaction to the conversation history. |
5659
| cancellationToken | The token to monitor for cancellation requests. |
5760

5861
## Return Value

docs/ChatGptNet/IChatGptClient/LoadConversationAsync.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ The unique identifier of the new conversation.
2424

2525
## Remarks
2626

27-
This method creates a new conversation with a random Conversation Id. Then, call [`AskAsync`](./AskAsync.md) with this Id to start the actual conversation.
27+
This method creates a new conversation with a random Conversation Id. Then, call [`AskAsync`](./AskAsync.md) or [`AskStreamAsync`](./AskStreamAsync.md) with this Id to start the actual conversation.
2828

2929
The total number of messages never exceeds the message limit defined in [`MessageLimit`](../ChatGptOptions/MessageLimit.md). If *messages* contains more, only the latest ones are loaded.
3030

3131
## See Also
3232

3333
* property [MessageLimit](../ChatGptOptions/MessageLimit.md)
34+
* method [AskAsync](./AskAsync.md)
3435
* method [AskStreamAsync](./AskStreamAsync.md)
3536
* class [ChatGptMessage](../../ChatGptNet.Models/ChatGptMessage.md)
3637
* interface [IChatGptClient](../IChatGptClient.md)

samples/ChatGptApi/ChatGptApi.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.9" />
10+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.10" />
1111
<PackageReference Include="MinimalHelpers.OpenApi" Version="1.0.4" />
1212
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
1313
</ItemGroup>

samples/ChatGptApi/Program.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ async IAsyncEnumerable<string> Stream()
118118
})
119119
.WithOpenApi();
120120

121-
app.MapDelete("/api/chat/{conversationId:guid}", async (Guid conversationId, IChatGptClient chatGptClient) =>
121+
app.MapDelete("/api/chat/{conversationId:guid}", async (Guid conversationId, bool? preserveSetup, IChatGptClient chatGptClient) =>
122122
{
123-
await chatGptClient.DeleteConversationAsync(conversationId);
123+
await chatGptClient.DeleteConversationAsync(conversationId, preserveSetup.GetValueOrDefault());
124124
return TypedResults.NoContent();
125125
})
126126
.WithOpenApi();

samples/ChatGptBlazor.Wasm/ChatGptBlazor.Wasm.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11-
<PackageReference Include="Markdig" Version="0.31.0" />
12-
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.9" />
13-
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.9" PrivateAssets="all" />
11+
<PackageReference Include="Markdig" Version="0.32.0" />
12+
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.10" />
13+
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.10" PrivateAssets="all" />
1414
</ItemGroup>
1515

1616
<ItemGroup>

samples/ChatGptConsole/Program.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ static void ConfigureServices(HostBuilderContext context, IServiceCollection ser
4545

4646
public class LocalMessageCache : IChatGptCache
4747
{
48-
private readonly Dictionary<Guid, List<ChatGptMessage>> localCache = new();
48+
private readonly Dictionary<Guid, IEnumerable<ChatGptMessage>> localCache = new();
4949

5050
public Task SetAsync(Guid conversationId, IEnumerable<ChatGptMessage> messages, TimeSpan expiration, CancellationToken cancellationToken = default)
5151
{
5252
localCache[conversationId] = messages.ToList();
5353
return Task.CompletedTask;
5454
}
55-
public Task<List<ChatGptMessage>?> GetAsync(Guid conversationId, CancellationToken cancellationToken = default)
55+
public Task<IEnumerable<ChatGptMessage>?> GetAsync(Guid conversationId, CancellationToken cancellationToken = default)
5656
{
5757
localCache.TryGetValue(conversationId, out var messages);
5858
return Task.FromResult(messages);

samples/ChatGptFunctionCallingConsole/Program.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ static void ConfigureServices(HostBuilderContext context, IServiceCollection ser
4545

4646
public class LocalMessageCache : IChatGptCache
4747
{
48-
private readonly Dictionary<Guid, List<ChatGptMessage>> localCache = new();
48+
private readonly Dictionary<Guid, IEnumerable<ChatGptMessage>> localCache = new();
4949

5050
public Task SetAsync(Guid conversationId, IEnumerable<ChatGptMessage> messages, TimeSpan expiration, CancellationToken cancellationToken = default)
5151
{
5252
localCache[conversationId] = messages.ToList();
5353
return Task.CompletedTask;
5454
}
55-
public Task<List<ChatGptMessage>?> GetAsync(Guid conversationId, CancellationToken cancellationToken = default)
55+
public Task<IEnumerable<ChatGptMessage>?> GetAsync(Guid conversationId, CancellationToken cancellationToken = default)
5656
{
5757
localCache.TryGetValue(conversationId, out var messages);
5858
return Task.FromResult(messages);

0 commit comments

Comments
 (0)