Skip to content

Commit

Permalink
Merge pull request #54 from pavel-zhur/feature/dragon-images-direct
Browse files Browse the repository at this point in the history
Feature/dragon images direct
  • Loading branch information
pavel-zhur authored Sep 14, 2024
2 parents 1908178 + 8e015f7 commit 26c997a
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 38 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/microservices.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ jobs:
run: dotnet publish OneShelf.Sources/OneShelf.Sources.Self.Api/OneShelf.Sources.Self.Api.csproj --no-restore
- name: Publish 11
run: dotnet publish OneShelf.OneDragon/OneShelf.OneDragon.Runner.Functions/OneShelf.OneDragon.Runner.Functions.csproj --no-restore
- name: Publish 12
run: dotnet publish OneShelf.Videos/OneShelf.Videos.Telegram.Functions/OneShelf.Videos.Telegram.Functions.csproj --no-restore
# - name: Publish 12
# run: dotnet publish OneShelf.Videos/OneShelf.Videos.Telegram.Functions/OneShelf.Videos.Telegram.Functions.csproj --no-restore

# - uses: actions/upload-artifact@v4
# with:
Expand Down Expand Up @@ -116,7 +116,7 @@ jobs:
- run: Compress-Archive -Path OneShelf.Collectives/OneShelf.Collectives.Api/bin/Release/net8.0/publish/* -Destination OneShelf.Collectives.Api.zip
- run: Compress-Archive -Path OneShelf.Sources/OneShelf.Sources.Self.Api/bin/Release/net8.0/publish/* -Destination OneShelf.Sources.Self.Api.zip
- run: Compress-Archive -Path OneShelf.OneDragon/OneShelf.OneDragon.Runner.Functions/bin/Release/net8.0/publish/* -Destination OneShelf.OneDragon.Runner.Functions.zip
- run: Compress-Archive -Path OneShelf.Videos/OneShelf.Videos.Telegram.Functions/bin/Release/net8.0/publish/* -Destination OneShelf.Videos.Telegram.Functions.zip
# - run: Compress-Archive -Path OneShelf.Videos/OneShelf.Videos.Telegram.Functions/bin/Release/net8.0/publish/* -Destination OneShelf.Videos.Telegram.Functions.zip

# - name: Test
# run: dotnet test --no-build --verbosity normal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ public enum InteractionType
AiMemoryPoint,
AiResetDialog,
AiImagesLimit,
AiImagesSuccess
AiImagesSuccess,

DirectImagesSuccess,
DirectImagesLimit,
}
100 changes: 100 additions & 0 deletions OneShelf.OneDragon/OneShelf.OneDragon.Processor/Commands/Images.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using OneShelf.Common.OpenAi.Services;
using OneShelf.OneDragon.Database;
using OneShelf.OneDragon.Database.Model.Enums;
using OneShelf.OneDragon.Processor.Model;
using OneShelf.OneDragon.Processor.Services;
using OneShelf.Telegram.Model.CommandAttributes;
using OneShelf.Telegram.Model.Ios;
using OneShelf.Telegram.Services.Base;
using Telegram.BotAPI;
using Telegram.BotAPI.AvailableMethods;
using Telegram.BotAPI.AvailableTypes;

namespace OneShelf.OneDragon.Processor.Commands;

[AdminCommand("images", "Картинки", "Сделать картинки по текстовому описанию")]
public class Images : Command
{
private readonly DragonDatabase _dragonDatabase;
private readonly DragonScope _scope;
private readonly Availability _availability;
private readonly DialogRunner _dialogRunner;
private readonly TelegramBotClient _api;

public Images(Io io, DragonDatabase dragonDatabase, DragonScope scope, Availability availability, DialogRunner dialogRunner, IOptions<TelegramOptions> options)
: base(io)
{
_dragonDatabase = dragonDatabase;
_scope = scope;
_availability = availability;
_dialogRunner = dialogRunner;
_api = new(options.Value.Token);
}

protected override async Task ExecuteQuickly()
{
var imagesUnavailableUntil = await _availability.GetImagesUnavailableUntil(DateTime.Now);
if (imagesUnavailableUntil != null)
{
Io.WriteLine($"Картинок нет до {imagesUnavailableUntil.Value:g} UTC");

_dragonDatabase.Interactions.Add(new()
{
CreatedOn = DateTime.Now,
ChatId = _scope.ChatId,
UserId = Io.UserId,
UpdateId = _scope.UpdateId,
InteractionType = InteractionType.DirectImagesLimit,
Serialized = "reset",
});

return;
}

var query = Io.FreeChoice("Подробное описание:");
var count = Io.StrictChoice("Сколько?", int.Parse, new[] { "1", "2", "3", "4", "5" });

if (count is not (>= 1 and <= 5))
{
Io.WriteLine("Многовато или маловато.");
return;
}

Io.WriteLine("Рисую...");

Scheduled(Background(query, count));
}

private async Task Background(string query, int count)
{
var aiParameters = await _dragonDatabase.AiParameters.SingleAsync();
var images = await _dialogRunner.GenerateImages(Enumerable.Repeat(query, count).ToList(), new()
{
ImagesVersion = aiParameters.DalleVersion,
UserId = _scope.UserId,
DomainId = -1,
Version = aiParameters.GptVersion,
ChatId = _scope.ChatId,
UseCase = "direct images",
AdditionalBillingInfo = "one dragon",
SystemMessage = "no message",
});

_dragonDatabase.Interactions.Add(new()
{
CreatedOn = DateTime.Now,
ChatId = _scope.ChatId,
UserId = Io.UserId,
UpdateId = _scope.UpdateId,
InteractionType = InteractionType.DirectImagesSuccess,
Serialized = count.ToString(),
ShortInfoSerialized = query,
});

await _dragonDatabase.SaveChangesAsync();

await _api.SendMediaGroupAsync(new(_scope.ChatId, images.Select(x => new InputMediaPhoto(x.ToString()) {Caption = "1"})));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using OneShelf.OneDragon.Database;
using OneShelf.OneDragon.Database.Model;
using OneShelf.OneDragon.Database.Model.Enums;
using OneShelf.OneDragon.Processor.Model;
using OneShelf.OneDragon.Processor.Services;
using OneShelf.Telegram.Ai.Model;
using OneShelf.Telegram.Ai.PipelineHandlers;
Expand All @@ -18,23 +19,32 @@ public class AiDialogHandler : AiDialogHandlerBase<InteractionType>
{
private readonly DragonDatabase _dragonDatabase;
private readonly DragonScope _dragonScope;
private readonly Availability _availability;
private readonly IOptions<TelegramOptions> _options;

public AiDialogHandler(
IScopedAbstractions scopedAbstractions,
ILogger<AiDialogHandlerBase<InteractionType>> logger,
DialogRunner dialogRunner,
DragonDatabase dragonDatabase, DragonScope dragonScope)
DragonDatabase dragonDatabase,
DragonScope dragonScope,
Availability availability,
IOptions<TelegramOptions> options)
: base(scopedAbstractions, logger, dragonDatabase, dialogRunner)
{
_dragonDatabase = dragonDatabase;
_dragonScope = dragonScope;
_availability = availability;
_options = options;
}

protected override void OnInitializing(Update update)
{
_dragonDatabase.InitializeInteractionsRepositoryScope(update.Message!.From!.Id, update.Message.Chat.Id);
}

protected override bool TraceImages => _options.Value.IsAdmin(_dragonScope.UserId);

protected override IInteraction<InteractionType> CreateInteraction(Update update) => new Interaction
{
ChatId = update.Message!.Chat.Id,
Expand All @@ -50,37 +60,7 @@ protected override bool CheckRelevant(Update update)
}

protected override async Task<DateTime?> GetImagesUnavailableUntil(DateTime now)
{
var user = await _dragonDatabase.Users.SingleAsync(x => x.Id == _dragonScope.UserId);
if (!user.UseLimits) return null;

var limits = await _dragonDatabase.Limits.Where(x => x.Images.HasValue).ToListAsync();
if (!limits.Any()) return null;

DateTime Since(TimeSpan window) => now.Add(-window);

var imagesSince = Since(limits.Max(x => x.Window));
var images = (await _dragonDatabase.Interactions
.Where(x => x.UserId == _dragonScope.UserId && x.ChatId == _dragonScope.ChatId)
.Where(x => x.InteractionType == InteractionType.AiImagesSuccess)
.Where(x => x.CreatedOn >= imagesSince)
.ToListAsync())
.Select(x => (x.CreatedOn, count: int.Parse(x.Serialized)))
.ToList();

DateTime? imagesUnavailableUntil = null;
foreach (var limit in limits)
{
if (images.Where(x => x.CreatedOn >= Since(limit.Window)).Sum(x => x.count) >= limit.Images!.Value)
{
imagesUnavailableUntil ??= DateTime.MinValue;
var value = images.Min(x => x.CreatedOn).Add(limit.Window);
imagesUnavailableUntil = imagesUnavailableUntil > value ? imagesUnavailableUntil : value;
}
}

return imagesUnavailableUntil;
}
=> await _availability.GetImagesUnavailableUntil(now);

protected override async Task<DateTime?> GetChatUnavailableUntil()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public static IServiceCollection AddProcessor(this IServiceCollection services,
.AddCommand<UpdateCommands>()
.AddCommand<ViewBilling>()
.AddCommand<Amnesia>()
.AddCommand<Images>()

.AddPipelineHandlerInOrder<UpdatesCollector>()
.AddPipelineHandlerInOrder<UsersCollector>()
Expand All @@ -38,6 +39,7 @@ public static IServiceCollection AddProcessor(this IServiceCollection services,
services
.AddDragonDatabase()
.AddOpenAi(configuration)
.AddScoped<Availability>()
.AddScoped<DragonScope>();

return services;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Microsoft.EntityFrameworkCore;
using OneShelf.OneDragon.Database;
using OneShelf.OneDragon.Database.Model.Enums;

namespace OneShelf.OneDragon.Processor.Services;

public class Availability(DragonDatabase dragonDatabase, DragonScope dragonScope)
{
public async Task<DateTime?> GetImagesUnavailableUntil(DateTime now)
{
var user = await dragonDatabase.Users.SingleAsync(x => x.Id == dragonScope.UserId);
if (!user.UseLimits) return null;

var limits = await dragonDatabase.Limits.Where(x => x.Images.HasValue).ToListAsync();
if (!limits.Any()) return null;

DateTime Since(TimeSpan window) => now.Add(-window);

var imagesSince = Since(limits.Max(x => x.Window));
var images = (await dragonDatabase.Interactions
.Where(x => x.UserId == dragonScope.UserId && x.ChatId == dragonScope.ChatId)
.Where(x => x.InteractionType == InteractionType.AiImagesSuccess)
.Where(x => x.CreatedOn >= imagesSince)
.ToListAsync())
.Select(x => (x.CreatedOn, count: int.Parse(x.Serialized)))
.ToList();

DateTime? imagesUnavailableUntil = null;
foreach (var limit in limits)
{
if (images.Where(x => x.CreatedOn >= Since(limit.Window)).Sum(x => x.count) >= limit.Images!.Value)
{
imagesUnavailableUntil ??= DateTime.MinValue;
var value = images.Min(x => x.CreatedOn).Add(limit.Window);
imagesUnavailableUntil = imagesUnavailableUntil > value ? imagesUnavailableUntil : value;
}
}

return imagesUnavailableUntil;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@ public class SingletonAbstractions : ISingletonAbstractions
{
public List<List<Type>> GetCommandsGrid() => [
[
typeof(Start),
typeof(Images),
],
[
typeof(Help),
typeof(ViewBilling),
typeof(Amnesia)
],
[
typeof(Start),
],
[
typeof(UpdateCommands),
]
],
];

public Type? GetDefaultCommand() => null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ protected virtual void OnInitializing(Update update)
{
}

protected virtual bool TraceImages => false;

protected async Task Respond(Update update)
{
var now = DateTime.Now;
Expand Down Expand Up @@ -352,6 +354,18 @@ protected async Task Respond(Update update)
{
try
{
if (TraceImages)
{
try
{
await SendMessage(update, string.Join(Environment.NewLine, newMessagePoint.ImageTraces.Select(x => $"- {x}").Prepend(string.Empty).Prepend("Traces:")), false);
}
catch (Exception e)
{
_logger.LogError(e, "Error writing the traces.");
}
}

if (!string.IsNullOrWhiteSpace(text))
{
await SendMessage(update, text, result.Images, false);
Expand Down

0 comments on commit 26c997a

Please sign in to comment.