Skip to content

Commit 6cc79d8

Browse files
committed
Add Fody.ConfigureAwait to modules; Fix Disposable pattern in OpenAiClient; Update to 2.7.1
1 parent af47f30 commit 6cc79d8

File tree

18 files changed

+341
-72
lines changed

18 files changed

+341
-72
lines changed

Directory.Build.props

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<Project>
2+
<PropertyGroup>
3+
<Version>2.7.1</Version>
4+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
5+
</PropertyGroup>
6+
</Project>

OpenAI.ChatGpt.AspNetCore/OpenAI.ChatGpt.AspNetCore.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
<PackageId>OpenAI.ChatGPT.AspNetCore</PackageId>
99
<PackageProjectUrl>https://github.com/rodion-m/ChatGPT_API_dotnet</PackageProjectUrl>
1010
<Product>OpenAI ChatGPT integration for .NET with DI</Product>
11-
<Version>2.7.0</Version>
1211
<Description>OpenAI Chat Completions API (ChatGPT) integration with easy DI supporting (Microsoft.Extensions.DependencyInjection). It allows you to use the API in your .NET applications. Also, the client supports streaming responses (like ChatGPT) via async streams.</Description>
1312
<RepositoryUrl>https://github.com/rodion-m/ChatGPT_API_dotnet</RepositoryUrl>
1413
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
@@ -24,6 +23,8 @@
2423
</ItemGroup>
2524

2625
<ItemGroup>
26+
<ProjectReference Include="..\OpenAI.ChatGpt.Modules.StructuredResponse\OpenAI.ChatGpt.Modules.StructuredResponse.csproj" />
27+
<ProjectReference Include="..\OpenAI.ChatGpt.Modules.Translator\OpenAI.ChatGpt.Modules.Translator.csproj" />
2728
<ProjectReference Include="..\OpenAI.ChatGpt\OpenAI.ChatGpt.csproj"/>
2829
</ItemGroup>
2930

OpenAI.ChatGpt.EntityFrameworkCore/OpenAI.ChatGpt.EntityFrameworkCore.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
<PackageId>OpenAI.ChatGPT.EntityFrameworkCore</PackageId>
1010
<PackageProjectUrl>https://github.com/rodion-m/ChatGPT_API_dotnet</PackageProjectUrl>
1111
<Product>OpenAI ChatGPT integration for .NET with EF Core storage</Product>
12-
<Version>2.7.0</Version>
1312
<Description>OpenAI Chat Completions API (ChatGPT) integration with DI and EF Core supporting. It allows you to use the API in your .NET applications. Also, the client supports streaming responses (like ChatGPT) via async streams.</Description>
1413
<RepositoryUrl>https://github.com/rodion-m/ChatGPT_API_dotnet</RepositoryUrl>
1514
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
2+
<ConfigureAwait />
3+
</Weavers>

OpenAI.ChatGpt.Modules.StructuredResponse/OpenAI.ChatGpt.Modules.StructuredResponse.csproj

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
<PackageId>OpenAI.ChatGPT.Modules.StructuredResponse</PackageId>
99
<PackageProjectUrl>https://github.com/rodion-m/ChatGPT_API_dotnet</PackageProjectUrl>
1010
<Product>OpenAI ChatGPT structured response module</Product>
11-
<Version>2.7.0</Version>
1211
<Description>The module for OpenAI ChatGPT that allows to retrive a structured response from ChatGPT.</Description>
1312
<RepositoryUrl>https://github.com/rodion-m/ChatGPT_API_dotnet</RepositoryUrl>
1413
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
@@ -25,6 +24,13 @@
2524
</PropertyGroup>
2625

2726
<ItemGroup>
27+
<PackageReference Include="ConfigureAwait.Fody" Version="3.3.2">
28+
<PrivateAssets>all</PrivateAssets>
29+
</PackageReference>
30+
<PackageReference Include="Fody" Version="6.6.4">
31+
<PrivateAssets>all</PrivateAssets>
32+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
33+
</PackageReference>
2834
<PackageReference Include="JsonSchema.Net.Generation" Version="3.3.0" />
2935
</ItemGroup>
3036

OpenAI.ChatGpt.Modules.StructuredResponse/OpenAiClientExtensions.GetAsObjectAsync.cs renamed to OpenAI.ChatGpt.Modules.StructuredResponse/OpenAiClientExtensions.GetStructuredResponse.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace OpenAI.ChatGpt.Modules.StructuredResponse;
99

10+
[Fody.ConfigureAwait(false)]
1011
public static class OpenAiClientExtensions
1112
{
1213
/// <summary>
@@ -98,6 +99,11 @@ internal static async Task<TObject> GetStructuredResponse<TObject>(
9899
rawResponseGetter,
99100
cancellationToken);
100101

102+
response = response.Trim();
103+
if(response.StartsWith("```") && response.EndsWith("```"))
104+
{
105+
response = response[3..^3];
106+
}
101107
jsonDeserializerOptions ??= new JsonSerializerOptions
102108
{
103109
PropertyNameCaseInsensitive = true,
@@ -120,7 +126,8 @@ internal static async Task<TObject> GetStructuredResponse<TObject>(
120126

121127
private static string GetAdditionalJsonResponsePrompt(string responseFormat)
122128
{
123-
return$"\n\nWrite your response in JSON format. The response structure is enclosed within double backticks (JSON Schema) ``{responseFormat}``";
129+
return$"\n\nWrite your response in compact JSON format with escaped strings. " +
130+
$"Here is the response structure, it is enclosed within double backticks (JSON Schema) ``{responseFormat}``";
124131
}
125132

126133
internal static string CreateResponseFormatJson<TObject>()

OpenAI.ChatGpt.Modules.Translator/ChatGPTTranslatorService.cs

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
using OpenAI.ChatGpt.Models.ChatCompletion;
1+
using System.Text.Json;
2+
using System.Text.Json.Serialization;
3+
using OpenAI.ChatGpt.Models.ChatCompletion;
4+
using OpenAI.ChatGpt.Models.ChatCompletion.Messaging;
5+
using OpenAI.ChatGpt.Modules.StructuredResponse;
26

37
namespace OpenAI.ChatGpt.Modules.Translator;
48

9+
[Fody.ConfigureAwait(false)]
10+
// ReSharper disable once InconsistentNaming
511
public class ChatGPTTranslatorService : IDisposable
612
{
713
private readonly IOpenAiClient _client;
@@ -45,14 +51,19 @@ public void Dispose()
4551
}
4652
}
4753

48-
public async Task<string> Translate(
54+
public async Task<string> TranslateText(
4955
string text,
5056
string? sourceLanguage = null,
5157
string? targetLanguage = null,
58+
int? maxTokens = null,
59+
string? model = null,
60+
float temperature = ChatCompletionTemperatures.Default,
61+
string? user = null,
5262
Action<ChatCompletionRequest>? requestModifier = null,
63+
Action<ChatCompletionResponse>? rawResponseGetter = null,
5364
CancellationToken cancellationToken = default)
5465
{
55-
if (text == null) throw new ArgumentNullException(nameof(text));
66+
ArgumentNullException.ThrowIfNull(text);
5667
var sourceLanguageOrDefault = sourceLanguage ?? _defaultSourceLanguage;
5768
var targetLanguageOrDefault = targetLanguage ?? _defaultTargetLanguage;
5869
if (sourceLanguageOrDefault is null)
@@ -63,21 +74,84 @@ public async Task<string> Translate(
6374
{
6475
throw new ArgumentNullException(nameof(targetLanguage), "Target language is not specified");
6576
}
66-
var prompt = GetPrompt(sourceLanguageOrDefault, targetLanguageOrDefault);
77+
78+
var prompt = CreateTextTranslationPrompt(sourceLanguageOrDefault, targetLanguageOrDefault);
79+
var messages = Dialog.StartAsSystem(prompt).ThenUser(text).GetMessages().ToArray();
80+
(model, maxTokens) = ChatCompletionMessage.FindOptimalModelAndMaxToken(messages, model, maxTokens);
6781
var response = await _client.GetChatCompletions(
68-
Dialog.StartAsSystem(prompt).ThenUser(text),
69-
user: null,
70-
requestModifier: requestModifier,
71-
cancellationToken: cancellationToken
72-
);
82+
messages,
83+
maxTokens.Value,
84+
model,
85+
temperature,
86+
user,
87+
requestModifier,
88+
rawResponseGetter,
89+
cancellationToken);
7390
return response;
91+
92+
string CreateTextTranslationPrompt(string sourceLanguage, string targetLanguage)
93+
{
94+
ArgumentNullException.ThrowIfNull(sourceLanguage);
95+
ArgumentNullException.ThrowIfNull(targetLanguage);
96+
return $"I want you to act as a translator from {sourceLanguage} to {targetLanguage}. " +
97+
"The user provides with a sentence and you translate it. " +
98+
"In the response write ONLY translated text." +
99+
(_extraPrompt is not null ? "\n" + _extraPrompt : "");
100+
}
74101
}
75-
76-
private string GetPrompt(string sourceLanguage, string targetLanguage)
102+
103+
public async Task<TObject> TranslateObject<TObject>(
104+
TObject objectToTranslate,
105+
string? sourceLanguage = null,
106+
string? targetLanguage = null,
107+
int? maxTokens = null,
108+
string? model = null,
109+
float temperature = ChatCompletionTemperatures.Default,
110+
string? user = null,
111+
Action<ChatCompletionRequest>? requestModifier = null,
112+
Action<ChatCompletionResponse>? rawResponseGetter = null,
113+
JsonSerializerOptions? jsonSerializerOptions = null,
114+
JsonSerializerOptions? jsonDeserializerOptions = null,
115+
CancellationToken cancellationToken = default) where TObject : class
77116
{
78-
return $"I want you to act as a translator from {sourceLanguage} to {targetLanguage}. " +
79-
"I will provide you with an English sentence and you will translate it into Russian. " +
80-
"In the response write ONLY translated text."
81-
+ (_extraPrompt is not null ? "\n" + _extraPrompt : "");
117+
ArgumentNullException.ThrowIfNull(objectToTranslate);
118+
var sourceLanguageOrDefault = sourceLanguage ?? _defaultSourceLanguage;
119+
var targetLanguageOrDefault = targetLanguage ?? _defaultTargetLanguage;
120+
if (sourceLanguageOrDefault is null)
121+
{
122+
throw new ArgumentNullException(nameof(sourceLanguage), "Source language is not specified");
123+
}
124+
if (targetLanguageOrDefault is null)
125+
{
126+
throw new ArgumentNullException(nameof(targetLanguage), "Target language is not specified");
127+
}
128+
129+
var prompt = CreateObjectTranslationPrompt(sourceLanguageOrDefault, targetLanguageOrDefault);
130+
jsonSerializerOptions ??= new JsonSerializerOptions() {DefaultIgnoreCondition = JsonIgnoreCondition.Never};
131+
var objectJson = JsonSerializer.Serialize(objectToTranslate, jsonSerializerOptions);
132+
var dialog = Dialog.StartAsSystem(prompt).ThenUser(objectJson);
133+
var messages = dialog.GetMessages().ToArray();
134+
(model, maxTokens) = ChatCompletionMessage.FindOptimalModelAndMaxToken(messages, model, maxTokens);
135+
var response = await _client.GetStructuredResponse<TObject>(
136+
dialog,
137+
maxTokens.Value,
138+
model,
139+
temperature,
140+
user,
141+
requestModifier,
142+
rawResponseGetter,
143+
jsonDeserializerOptions,
144+
cancellationToken
145+
);
146+
return response;
147+
148+
string CreateObjectTranslationPrompt(string sourceLanguage, string targetLanguage)
149+
{
150+
ArgumentNullException.ThrowIfNull(sourceLanguage);
151+
ArgumentNullException.ThrowIfNull(targetLanguage);
152+
return $"I want you to act as a translator from {sourceLanguage} to {targetLanguage}. " +
153+
"The user provides you with an object in json. You translate only the text fields that need to be translated. " +
154+
(_extraPrompt is not null ? "\n" + _extraPrompt : "");
155+
}
82156
}
83157
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
2+
<ConfigureAwait />
3+
</Weavers>

OpenAI.ChatGpt.Modules.Translator/OpenAI.ChatGpt.Modules.Translator.csproj

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
<PackageId>OpenAI.ChatGPT.Modules.Translator</PackageId>
1010
<PackageProjectUrl>https://github.com/rodion-m/ChatGPT_API_dotnet</PackageProjectUrl>
1111
<Product>OpenAI ChatGPT based language translator</Product>
12-
<Version>2.7.0</Version>
1312
<Description>OpenAI ChatGPT based language translator.</Description>
1413
<RepositoryUrl>https://github.com/rodion-m/ChatGPT_API_dotnet</RepositoryUrl>
1514
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
@@ -26,7 +25,18 @@
2625
</PropertyGroup>
2726

2827
<ItemGroup>
29-
<ProjectReference Include="..\OpenAI.ChatGpt\OpenAI.ChatGpt.csproj" />
28+
<PackageReference Include="ConfigureAwait.Fody" Version="3.3.2">
29+
<PrivateAssets>all</PrivateAssets>
30+
</PackageReference>
31+
<PackageReference Include="Fody" Version="6.6.4">
32+
<PrivateAssets>all</PrivateAssets>
33+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
34+
</PackageReference>
35+
</ItemGroup>
36+
37+
<ItemGroup>
38+
<ProjectReference Include="..\OpenAI.ChatGpt.Modules.StructuredResponse\OpenAI.ChatGpt.Modules.StructuredResponse.csproj"/>
39+
<ProjectReference Include="..\OpenAI.ChatGpt\OpenAI.ChatGpt.csproj"/>
3040
</ItemGroup>
3141

3242
</Project>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System.Text.Json;
2+
using OpenAI.ChatGpt.Models.ChatCompletion;
3+
4+
namespace OpenAI.ChatGpt.Modules.Translator;
5+
6+
[Fody.ConfigureAwait(false)]
7+
public static class OpenAiClientExtensions
8+
{
9+
public static Task<string> TranslateText(
10+
this IOpenAiClient client,
11+
string text,
12+
string sourceLanguage,
13+
string targetLanguage,
14+
string? extraPrompt = null,
15+
int? maxTokens = null,
16+
string? model = null,
17+
float temperature = ChatCompletionTemperatures.Default,
18+
string? user = null,
19+
Action<ChatCompletionRequest>? requestModifier = null,
20+
Action<ChatCompletionResponse>? rawResponseGetter = null,
21+
CancellationToken cancellationToken = default)
22+
{
23+
ArgumentNullException.ThrowIfNull(client);
24+
ArgumentNullException.ThrowIfNull(text);
25+
ArgumentNullException.ThrowIfNull(sourceLanguage);
26+
ArgumentNullException.ThrowIfNull(targetLanguage);
27+
28+
var translator = new ChatGPTTranslatorService(client, extraPrompt: extraPrompt);
29+
return translator.TranslateText(
30+
text,
31+
sourceLanguage,
32+
targetLanguage,
33+
maxTokens,
34+
model,
35+
temperature,
36+
user,
37+
requestModifier,
38+
rawResponseGetter,
39+
cancellationToken);
40+
}
41+
42+
public static Task<TObject> TranslateObject<TObject>(
43+
this IOpenAiClient client,
44+
TObject objectToTranslate,
45+
string sourceLanguage,
46+
string targetLanguage,
47+
string? extraPrompt = null,
48+
int? maxTokens = null,
49+
string? model = null,
50+
float temperature = ChatCompletionTemperatures.Default,
51+
string? user = null,
52+
Action<ChatCompletionRequest>? requestModifier = null,
53+
Action<ChatCompletionResponse>? rawResponseGetter = null,
54+
JsonSerializerOptions? jsonSerializerOptions = null,
55+
JsonSerializerOptions? jsonDeserializerOptions = null,
56+
CancellationToken cancellationToken = default) where TObject: class
57+
{
58+
ArgumentNullException.ThrowIfNull(client);
59+
ArgumentNullException.ThrowIfNull(objectToTranslate);
60+
ArgumentNullException.ThrowIfNull(sourceLanguage);
61+
ArgumentNullException.ThrowIfNull(targetLanguage);
62+
63+
var translator = new ChatGPTTranslatorService(client, extraPrompt: extraPrompt);
64+
return translator.TranslateObject(
65+
objectToTranslate,
66+
sourceLanguage,
67+
targetLanguage,
68+
maxTokens,
69+
model,
70+
temperature,
71+
user,
72+
requestModifier,
73+
rawResponseGetter,
74+
jsonSerializerOptions,
75+
jsonDeserializerOptions,
76+
cancellationToken
77+
);
78+
}
79+
}

0 commit comments

Comments
 (0)