Skip to content

Commit

Permalink
Added tools to generate images from prompt �via -use image
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomasz Juszczak committed Oct 13, 2024
1 parent b5d8a56 commit f148356
Show file tree
Hide file tree
Showing 30 changed files with 1,557 additions and 85 deletions.
12 changes: 12 additions & 0 deletions .idea/.idea.Slack-GPT-Socket/.idea/dataSources.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Slack-GPT-Socket.sln
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Slack-GPT-Socket", "Slack-G
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Slack-GPT-Tests", "Slack-GPT-Tests\Slack-GPT-Tests.csproj", "{8513CAC6-F4FB-4821-B229-7B2E31E1DA66}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Slack-Gpt-Source-Generator", "Slack-Gpt-Source-Generator\Slack-Gpt-Source-Generator\Slack-Gpt-Source-Generator.csproj", "{DB1A83EB-8250-4974-B6FF-A7FC72D5F793}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -18,5 +20,9 @@ Global
{8513CAC6-F4FB-4821-B229-7B2E31E1DA66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8513CAC6-F4FB-4821-B229-7B2E31E1DA66}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8513CAC6-F4FB-4821-B229-7B2E31E1DA66}.Release|Any CPU.Build.0 = Release|Any CPU
{DB1A83EB-8250-4974-B6FF-A7FC72D5F793}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DB1A83EB-8250-4974-B6FF-A7FC72D5F793}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB1A83EB-8250-4974-B6FF-A7FC72D5F793}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB1A83EB-8250-4974-B6FF-A7FC72D5F793}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
41 changes: 2 additions & 39 deletions Slack-GPT-Socket.sln.DotSettings.user
Original file line number Diff line number Diff line change
@@ -1,43 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=518a87a3_002D49c7_002D40fb_002Dbec1_002D478ce2091847/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="GptClientEdgeCasesTests_1" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=2635d6bc_002Dcf49_002D4263_002D8299_002Df4a2606fe890/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="TestGptTool_Json" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;TestAncestor&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.GptApi.GptClientEdgeCasesTests.GptClientEdgeCasesTests_1&lt;/TestId&gt;&#xD;
&lt;/TestAncestor&gt;&#xD;
&lt;/SessionState&gt;</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=7a21a381_002D1bd7_002D4190_002Daea7_002D60bbc3080eac/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="GptClientEdgeCasesTests_1 #3" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;TestAncestor&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.GptApi.GptClientEdgeCasesTests.GptClientEdgeCasesTests_1&lt;/TestId&gt;&#xD;
&lt;/TestAncestor&gt;&#xD;
&lt;/SessionState&gt;</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=bc0f8e87_002D43a6_002D4830_002D802e_002Db69debc2f54b/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="GptClientEdgeCasesTests_1 #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;TestAncestor&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.GptApi.GptClientEdgeCasesTests.GptClientEdgeCasesTests_1&lt;/TestId&gt;&#xD;
&lt;/TestAncestor&gt;&#xD;
&lt;/SessionState&gt;</s:String>


<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=e72966db_002D060a_002D4577_002D858b_002D3601c1cb06de/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="ContextBlockSanitation_OK" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;TestAncestor&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.TestContextBlockSanitation.ContextBlockSanitation_OK&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.TestApplicationClass.TestApplicationVersion_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.GptApi.GptClientResolverTests&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.GptApi.GptClientUserCommandsTests.ResolveParameters_UserCommand_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.GptApi.GptClientUserCommandsTests.ResolveParameters_UserCommand_AddMultiple_Test_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.GptApi.GptClientUserCommandsTests.ResolveParameters_UserCommand_Remove_NotFound_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.GptApi.GptClientUserCommandsTests.ResolveParameters_UserCommand_Exists_NotFound_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.Handlers.CommandHandlerTests.ExecuteCommand_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.Handlers.CommandHandlerTests.HelpCommand_CustomGlobal_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.Handlers.CommandHandlerTests.CommandsCommand_List_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.Handlers.CommandHandlerTests.CommandsCommand_Add_And_List_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.Handlers.CommandHandlerTests.CommandsCommand_AddRemove_And_List_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.Handlers.CommandHandlerTests.CommandsCommand_AddRemove_And_List_CannotRemove&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.Handlers.CommandHandlerTests.CommandsCommand_AddSameCommand_MultipleUsers_CannotRemove&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.Handlers.CommandHandlerTests.WhatsNewCommand_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.Handlers.CommandHandlerTests.WhatsNewCommand_Error&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.TestLiteDB.TestNullConnectionString_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.Handlers.CommandHandlerTests.CommandsCommand_AddOverwrite_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.Handlers.CommandHandlerTests.CommandsCommand_RemoveSingle_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.GptApi.GptClientEdgeCasesTests.GptClientEdgeCasesTests_1&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net7.0::Slack_GPT_Tests.GptApi.GptClientEdgeCasesTests.GptClientEdgeCases_Ok&lt;/TestId&gt;&#xD;
&lt;TestId&gt;NUnit3x::8513CAC6-F4FB-4821-B229-7B2E31E1DA66::net8.0::Slack_GPT_Tests.GptApi.GptToolJsonTests.TestGptTool_Json&lt;/TestId&gt;&#xD;
&lt;/TestAncestor&gt;&#xD;
&lt;/SessionState&gt;</s:String></wpf:ResourceDictionary>
132 changes: 132 additions & 0 deletions Slack-GPT-Socket/Functions/GenerateImageTool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using System.Runtime.Serialization;
using Humanizer;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using OpenAI;
using OpenAI.Images;
using Slack_GPT_Socket.GptApi;

namespace Slack_GPT_Socket.Functions;

[JsonConverter(typeof(StringEnumConverter))]
public enum QualityEnum
{
[EnumMember(Value = "standard")] Standard,
[EnumMember(Value = "hd")] HighDefinition
}

[JsonConverter(typeof(StringEnumConverter))]
public enum SizeEnum
{
Square,
Portrait,
Landscape
}

[JsonConverter(typeof(StringEnumConverter))]
public enum StyleEnum
{
[EnumMember(Value = "vivid")] Vivid,
[EnumMember(Value = "natural")] Natural
}

/// <summary>
/// Generate an image based on the given prompt, returns the URL of the generated image.
/// </summary>
public partial class GenerateImageTool : BaseGptTool, IExpressionGptTool<string, string, QualityEnum?, SizeEnum?, StyleEnum?>
{
private readonly OpenAIClient _api;

public override string[] Aliases { get; } =
{
"image",
"generate-image",
};

public GenerateImageTool(OpenAIClient api) : this()
{
_api = api;
}

/// <summary>
/// Generate an image based on the given prompt, returns the byte array of the generated image, that is then
/// attached AUTOMATICALLY to the response message. Do not mention the image in the response message.
/// </summary>
/// <param name="prompt">
/// Prompt field guides the AI in generating images by providing a clear, concise description of the desired
/// scene or subject, including specific details like the setting, style, and mood. Use descriptive language to specify
/// key elements, context, and artistic styles to ensure the resulting image closely aligns with your vision.
/// </param>
/// <param name="name">
/// Short image name that will be used as file name. Use hyphen and leave out extension format. Use
/// hyphens to mark words
/// </param>
/// <param name="quality">
/// The quality of the image that will be generated. hd creates images with finer details and greater
/// consistency across the image.
/// </param>
/// <param name="size">The size of the generated images, default is square</param>
/// <param name="style">
/// The style of the generated images. Vivid causes the model to lean towards generating hyper-real and
/// dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. Defaults to
/// vivid
/// </param>
/// <returns></returns>
public async Task<CallExpressionResult> CallExpression(string prompt, string name, QualityEnum? quality,
SizeEnum? size, StyleEnum? style)
{
var client = _api.GetImageClient("dall-e-3");

GeneratedImageQuality? generatedImageQuality = quality switch
{
QualityEnum.Standard => GeneratedImageQuality.Standard,
QualityEnum.HighDefinition => GeneratedImageQuality.High,
_ => default
};

GeneratedImageSize? generatedImageSize = size switch
{
SizeEnum.Square => GeneratedImageSize.W1024xH1024,
SizeEnum.Portrait => GeneratedImageSize.W1024xH1792,
SizeEnum.Landscape => GeneratedImageSize.W1792xH1024,
_ => default
};

GeneratedImageStyle? generatedImageStyle = style switch
{
StyleEnum.Vivid => GeneratedImageStyle.Vivid,
StyleEnum.Natural => GeneratedImageStyle.Natural,
_ => default
};

var generateImageAsync = await client.GenerateImageAsync(prompt, new ImageGenerationOptions
{
Quality = generatedImageQuality,
Size = generatedImageSize,
Style = generatedImageStyle,
ResponseFormat = GeneratedImageFormat.Bytes
});

var imageBytes = generateImageAsync.Value.ImageBytes;
var revisedPrompt = generateImageAsync.Value.RevisedPrompt;

using var memoryStream = new MemoryStream();
await imageBytes.ToStream().CopyToAsync(memoryStream);
var bytes = memoryStream.ToArray();

return new CallExpressionResult
{
TextResponse = "Generated using prompt: " + revisedPrompt + ". Image data is part of the message, do not embed it in the message.",
Files = new List<FileAttachment>
{
new()
{
MimeType = "image/png",
Data = bytes,
Name = $"{name}.png",
Title = name.Humanize()
}
}
};
}
}
Loading

0 comments on commit f148356

Please sign in to comment.