Skip to content

Commit

Permalink
Code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
ronnygunawan committed Dec 2, 2023
1 parent 1e9e62c commit 16b8ffc
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 161 deletions.
6 changes: 3 additions & 3 deletions BotNet.Services/BMKG/LatestEarthQuake.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
using System.Threading.Tasks;

namespace BotNet.Services.BMKG {
public class LatestEarthQuake : BMKG {
public LatestEarthQuake(HttpClient client) : base(client) {}
public class LatestEarthQuake(HttpClient client) : BMKG(client) {
private static readonly JsonSerializerOptions JSON_SERIALIZER_OPTIONS = new() { PropertyNameCaseInsensitive = true };

public async Task<(string Text, string ShakemapUrl)> GetLatestAsync() {
string url = string.Format(uriTemplate, "autogempa");
Expand All @@ -19,7 +19,7 @@ public LatestEarthQuake(HttpClient client) : base(client) {}

Stream bodyContent = await response.Content.ReadAsStreamAsync();

EarthQuake? bodyResponse = await JsonSerializer.DeserializeAsync<EarthQuake>(bodyContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
EarthQuake? bodyResponse = await JsonSerializer.DeserializeAsync<EarthQuake>(bodyContent, JSON_SERIALIZER_OPTIONS);

if (bodyResponse is null) {
throw new JsonException("Failed to parse body");
Expand Down
17 changes: 8 additions & 9 deletions BotNet.Services/OpenAI/AttachmentGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,11 @@
using Microsoft.Extensions.Options;

namespace BotNet.Services.OpenAI {
public class AttachmentGenerator {
private static readonly Regex HEX_COLOR_CODE_PATTERN = new Regex("#[a-fA-F0-9]{6}\\b");
private readonly HostingOptions _hostingOptions;

public AttachmentGenerator(
IOptions<HostingOptions> hostingOptionsAccessor
) {
_hostingOptions = hostingOptionsAccessor.Value;
}
public partial class AttachmentGenerator(
IOptions<HostingOptions> hostingOptionsAccessor
) {
private static readonly Regex HEX_COLOR_CODE_PATTERN = HexColorCodeRegex();
private readonly HostingOptions _hostingOptions = hostingOptionsAccessor.Value;

public ImmutableList<Uri> GenerateAttachments(string message) {
ImmutableList<Uri>.Builder builder = ImmutableList<Uri>.Empty.ToBuilder();
Expand All @@ -27,5 +23,8 @@ public ImmutableList<Uri> GenerateAttachments(string message) {

return builder.ToImmutable();
}

[GeneratedRegex("#[a-fA-F0-9]{6}\\b")]
private static partial Regex HexColorCodeRegex();
}
}
24 changes: 10 additions & 14 deletions BotNet.Services/OpenAI/FriendlyBot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@
using BotNet.Services.OpenAI.Models;

namespace BotNet.Services.OpenAI {
public class FriendlyBot {
private readonly OpenAIClient _openAIClient;

public FriendlyBot(
OpenAIClient openAIClient
) {
_openAIClient = openAIClient;
}
public class FriendlyBot(
OpenAIClient openAIClient
) {
private readonly OpenAIClient _openAIClient = openAIClient;

public Task<string> ChatAsync(string callSign, string name, string question, CancellationToken cancellationToken) {
string prompt = $"The following is a conversation with an AI assistant. The assistant is helpful, creative, clever, and very friendly.\n\n"
Expand All @@ -24,7 +20,7 @@ public Task<string> ChatAsync(string callSign, string name, string question, Can
return _openAIClient.AutocompleteAsync(
engine: "text-davinci-003",
prompt: prompt,
stop: new[] { $"{name}:" },
stop: [$"{name}:"],
maxTokens: 128,
frequencyPenalty: 0.5,
presencePenalty: 0.6,
Expand All @@ -48,7 +44,7 @@ public Task<string> RespondToThreadAsync(string callSign, string name, string qu
return _openAIClient.AutocompleteAsync(
engine: "text-davinci-003",
prompt: prompt,
stop: new[] { $"{name}:" },
stop: [$"{name}:"],
maxTokens: 128,
frequencyPenalty: 0.5,
presencePenalty: 0.6,
Expand All @@ -59,13 +55,13 @@ public Task<string> RespondToThreadAsync(string callSign, string name, string qu
}

public Task<string> ChatAsync(string message, CancellationToken cancellationToken) {
List<ChatMessage> messages = new() {
List<ChatMessage> messages = [
new("system", "The following is a conversation with an AI assistant. The assistant is helpful, creative, clever, and very friendly."),
new("user", message)
};
];

return _openAIClient.ChatAsync(
model: "gpt-3.5-turbo",
model: "gpt-4-1106-preview",
messages: messages,
maxTokens: 512,
cancellationToken: cancellationToken
Expand All @@ -89,7 +85,7 @@ from tuple in thread
};

return _openAIClient.ChatAsync(
model: "gpt-3.5-turbo",
model: "gpt-4-1106-preview",
messages: messages,
maxTokens: 512,
cancellationToken: cancellationToken
Expand Down
188 changes: 91 additions & 97 deletions BotNet.Services/OpenAI/OpenAIClient.cs
Original file line number Diff line number Diff line change
@@ -1,98 +1,92 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using BotNet.Services.Json;
using BotNet.Services.OpenAI.Models;
using Microsoft.Extensions.Options;
using RG.Ninja;

namespace BotNet.Services.OpenAI {
public class OpenAIClient {
private const string COMPLETION_URL_TEMPLATE = "https://api.openai.com/v1/engines/{0}/completions";
private const string CHAT_URL = "https://api.openai.com/v1/chat/completions";
private static readonly JsonSerializerOptions JSON_SERIALIZER_OPTIONS = new() {
PropertyNamingPolicy = new SnakeCaseNamingPolicy()
};
private readonly HttpClient _httpClient;
private readonly string _apiKey;

public OpenAIClient(
HttpClient httpClient,
IOptions<OpenAIOptions> openAIOptionsAccessor
) {
_httpClient = httpClient;
_apiKey = openAIOptionsAccessor.Value.ApiKey!;
}

public async Task<string> AutocompleteAsync(string engine, string prompt, string[]? stop, int maxTokens, double frequencyPenalty, double presencePenalty, double temperature, double topP, CancellationToken cancellationToken) {
using HttpRequestMessage request = new(HttpMethod.Post, string.Format(COMPLETION_URL_TEMPLATE, engine)) {
Headers = {
{ "Authorization", $"Bearer {_apiKey}" },
{ "Accept", "text/event-stream" }
},
Content = JsonContent.Create(
inputValue: new {
Prompt = prompt,
Temperature = temperature,
MaxTokens = maxTokens,
Stream = true,
TopP = topP,
FrequencyPenalty = frequencyPenalty,
PresencePenalty = presencePenalty,
Stop = stop
},
options: JSON_SERIALIZER_OPTIONS
)
};
using HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken);
response.EnsureSuccessStatusCode();

StringBuilder result = new();
using Stream stream = await response.Content.ReadAsStreamAsync(cancellationToken);
using StreamReader streamReader = new(stream);
while (!streamReader.EndOfStream) {
string? line = await streamReader.ReadLineAsync();
if (line == null) break;
if (line == "") continue;
if (!line.StartsWith("data: ", out string? json)) break;
if (json == "[DONE]") break;
CompletionResult? completionResult = JsonSerializer.Deserialize<CompletionResult>(json, JSON_SERIALIZER_OPTIONS);
if (completionResult == null) break;
if (completionResult.Choices.Count == 0) break;
result.Append(completionResult.Choices[0].Text);
if (completionResult.Choices[0].FinishReason == "stop") break;
}

return result.ToString();
}

public async Task<string> ChatAsync(string model, IEnumerable<ChatMessage> messages, int maxTokens, CancellationToken cancellationToken) {
using HttpRequestMessage request = new(HttpMethod.Post, CHAT_URL) {
Headers = {
{ "Authorization", $"Bearer {_apiKey}" },
},
Content = JsonContent.Create(
inputValue: new {
Model = model,
MaxTokens = maxTokens,
Messages = messages
},
options: JSON_SERIALIZER_OPTIONS
)
};
using HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken);
response.EnsureSuccessStatusCode();

CompletionResult? completionResult = await response.Content.ReadFromJsonAsync<CompletionResult>(JSON_SERIALIZER_OPTIONS, cancellationToken);
if (completionResult == null) return "";
if (completionResult.Choices.Count == 0) return "";
return completionResult.Choices[0].Message?.Content!;
}
}
}
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using BotNet.Services.Json;
using BotNet.Services.OpenAI.Models;
using Microsoft.Extensions.Options;
using RG.Ninja;

namespace BotNet.Services.OpenAI {
public class OpenAIClient(
HttpClient httpClient,
IOptions<OpenAIOptions> openAIOptionsAccessor
) {
private const string COMPLETION_URL_TEMPLATE = "https://api.openai.com/v1/engines/{0}/completions";
private const string CHAT_URL = "https://api.openai.com/v1/chat/completions";
private static readonly JsonSerializerOptions JSON_SERIALIZER_OPTIONS = new() {
PropertyNamingPolicy = new SnakeCaseNamingPolicy()
};
private readonly HttpClient _httpClient = httpClient;
private readonly string _apiKey = openAIOptionsAccessor.Value.ApiKey!;

public async Task<string> AutocompleteAsync(string engine, string prompt, string[]? stop, int maxTokens, double frequencyPenalty, double presencePenalty, double temperature, double topP, CancellationToken cancellationToken) {
using HttpRequestMessage request = new(HttpMethod.Post, string.Format(COMPLETION_URL_TEMPLATE, engine)) {
Headers = {
{ "Authorization", $"Bearer {_apiKey}" },
{ "Accept", "text/event-stream" }
},
Content = JsonContent.Create(
inputValue: new {
Prompt = prompt,
Temperature = temperature,
MaxTokens = maxTokens,
Stream = true,
TopP = topP,
FrequencyPenalty = frequencyPenalty,
PresencePenalty = presencePenalty,
Stop = stop
},
options: JSON_SERIALIZER_OPTIONS
)
};
using HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken);
response.EnsureSuccessStatusCode();

StringBuilder result = new();
using Stream stream = await response.Content.ReadAsStreamAsync(cancellationToken);
using StreamReader streamReader = new(stream);
while (!streamReader.EndOfStream) {
string? line = await streamReader.ReadLineAsync(cancellationToken);
if (line == null) break;
if (line == "") continue;
if (!line.StartsWith("data: ", out string? json)) break;
if (json == "[DONE]") break;
CompletionResult? completionResult = JsonSerializer.Deserialize<CompletionResult>(json, JSON_SERIALIZER_OPTIONS);
if (completionResult == null) break;
if (completionResult.Choices.Count == 0) break;
result.Append(completionResult.Choices[0].Text);
if (completionResult.Choices[0].FinishReason == "stop") break;
}

return result.ToString();
}

public async Task<string> ChatAsync(string model, IEnumerable<ChatMessage> messages, int maxTokens, CancellationToken cancellationToken) {
using HttpRequestMessage request = new(HttpMethod.Post, CHAT_URL) {
Headers = {
{ "Authorization", $"Bearer {_apiKey}" },
},
Content = JsonContent.Create(
inputValue: new {
Model = model,
MaxTokens = maxTokens,
Messages = messages
},
options: JSON_SERIALIZER_OPTIONS
)
};
using HttpResponseMessage response = await _httpClient.SendAsync(request, cancellationToken);
response.EnsureSuccessStatusCode();

CompletionResult? completionResult = await response.Content.ReadFromJsonAsync<CompletionResult>(JSON_SERIALIZER_OPTIONS, cancellationToken);
if (completionResult == null) return "";
if (completionResult.Choices.Count == 0) return "";
return completionResult.Choices[0].Message?.Content!;
}
}
}
12 changes: 4 additions & 8 deletions BotNet.Services/OpenAI/ThreadTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@
using Microsoft.Extensions.Caching.Memory;

namespace BotNet.Services.OpenAI {
public sealed class ThreadTracker {
private readonly IMemoryCache _memoryCache;

public ThreadTracker(
IMemoryCache memoryCache
) {
_memoryCache = memoryCache;
}
public sealed class ThreadTracker(
IMemoryCache memoryCache
) {
private readonly IMemoryCache _memoryCache = memoryCache;

public void TrackMessage(
long messageId,
Expand Down
11 changes: 0 additions & 11 deletions BotNet.Tests/Grains/InlineQueryGrainTests.cs

This file was deleted.

30 changes: 11 additions & 19 deletions BotNet/Bot/BotService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,19 @@

namespace BotNet.Bot;

public class BotService : IHostedService {
private readonly ITelegramBotClient _telegramBotClient;
private readonly UpdateHandler _updateHandler;
private readonly string _botToken;
private readonly string _hostName;
private readonly bool _useLongPolling;
public class BotService(
ITelegramBotClient telegramBotClient,
IOptions<BotOptions> botOptionsAccessor,
IOptions<HostingOptions> hostingOptionsAccessor,
UpdateHandler updateHandler
) : IHostedService {
private readonly ITelegramBotClient _telegramBotClient = telegramBotClient;
private readonly UpdateHandler _updateHandler = updateHandler;
private readonly string _botToken = botOptionsAccessor.Value.AccessToken!;
private readonly string _hostName = hostingOptionsAccessor.Value.HostName!;
private readonly bool _useLongPolling = hostingOptionsAccessor.Value.UseLongPolling;
private CancellationTokenSource? _cancellationTokenSource;

public BotService(
ITelegramBotClient telegramBotClient,
IOptions<BotOptions> botOptionsAccessor,
IOptions<HostingOptions> hostingOptionsAccessor,
UpdateHandler updateHandler
) {
_telegramBotClient = telegramBotClient;
_botToken = botOptionsAccessor.Value.AccessToken!;
_hostName = hostingOptionsAccessor.Value.HostName!;
_useLongPolling = hostingOptionsAccessor.Value.UseLongPolling;
_updateHandler = updateHandler;
}

public Task StartAsync(CancellationToken cancellationToken) {
_cancellationTokenSource = new();
if (_useLongPolling) {
Expand Down

0 comments on commit 16b8ffc

Please sign in to comment.