Skip to content
This repository was archived by the owner on Nov 27, 2024. It is now read-only.

Commit 94a336e

Browse files
committed
Merge branch 'master' into OldBatch
2 parents 7cc7527 + a15ee18 commit 94a336e

File tree

10 files changed

+337
-1
lines changed

10 files changed

+337
-1
lines changed

.dockerignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
**/.dockerignore
2+
**/.env
3+
**/.git
4+
**/.gitignore
5+
**/.project
6+
**/.settings
7+
**/.toolstarget
8+
**/.vs
9+
**/.vscode
10+
**/.idea
11+
**/*.*proj.user
12+
**/*.dbmdl
13+
**/*.jfm
14+
**/azds.yaml
15+
**/bin
16+
**/charts
17+
**/docker-compose*
18+
**/Dockerfile*
19+
**/node_modules
20+
**/npm-debug.log
21+
**/obj
22+
**/secrets.dev.yaml
23+
**/values.dev.yaml
24+
docker-test-output/
25+
LICENSE
26+
README.md

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,4 @@ test/TensorFlowNET.Examples/mnist
344344
site/
345345

346346
/OnnxStack.WebUI/wwwroot/images/Results/*
347+
docker-test-output/*

Dockerfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
2+
WORKDIR /app
3+
4+
# Install Git and Git LFS
5+
RUN apt-get update && apt-get install -y curl
6+
RUN curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash && apt-get install -y git-lfs
7+
8+
# Clone the Stable Diffusion 1.5 base model
9+
RUN git clone https://huggingface.co/runwayml/stable-diffusion-v1-5 -b onnx
10+
11+
# Clone the LCM Dreamshaper V7 model
12+
RUN git clone https://huggingface.co/TheyCallMeHex/LCM-Dreamshaper-V7-ONNX
13+
14+
COPY . .
15+
RUN dotnet build OnnxStackCore.sln
16+
17+
ENTRYPOINT ["dotnet", "test", "OnnxStackCore.sln"]

OnnxStack.Core/OnnxStack.Core.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@
3939
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" />
4040
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
4141
<PackageReference Include="Microsoft.ML" Version="2.0.1" />
42+
<PackageReference Include="Microsoft.ML.OnnxRuntime" Version="1.16.2" />
4243
<PackageReference Include="Microsoft.ML.OnnxRuntime.Extensions" Version="0.9.0" />
43-
<PackageReference Include="Microsoft.ML.OnnxRuntime.Managed" Version="1.16.1" />
44+
<PackageReference Include="Microsoft.ML.OnnxRuntime.Managed" Version="1.16.2" />
4445
</ItemGroup>
4546

4647
<ItemGroup>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net7.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="FluentAssertions" Version="6.12.0" />
13+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
14+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
15+
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
16+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.1" />
17+
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
18+
<PackageReference Include="Microsoft.ML.OnnxRuntime" Version="1.16.2" />
19+
<PackageReference Include="Microsoft.ML.OnnxRuntime.Extensions" Version="0.9.0" />
20+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2"/>
21+
<PackageReference Include="xunit" Version="2.4.2"/>
22+
<PackageReference Include="Xunit.Extensions.Logging" Version="1.1.0" />
23+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
24+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
25+
<PrivateAssets>all</PrivateAssets>
26+
</PackageReference>
27+
<PackageReference Include="coverlet.collector" Version="3.1.2">
28+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
29+
<PrivateAssets>all</PrivateAssets>
30+
</PackageReference>
31+
</ItemGroup>
32+
33+
<ItemGroup>
34+
<ProjectReference Include="..\OnnxStack.Core\OnnxStack.Core.csproj" />
35+
<ProjectReference Include="..\OnnxStack.StableDiffusion\OnnxStack.StableDiffusion.csproj" />
36+
</ItemGroup>
37+
38+
<ItemGroup>
39+
<None Update="appsettings.json">
40+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
41+
</None>
42+
</ItemGroup>
43+
44+
</Project>
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
using System.Security.Cryptography;
2+
using FluentAssertions;
3+
using FluentAssertions.Execution;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using Microsoft.Extensions.Logging;
6+
using OnnxStack.Core;
7+
using OnnxStack.StableDiffusion.Common;
8+
using OnnxStack.StableDiffusion.Config;
9+
using OnnxStack.StableDiffusion.Enums;
10+
using SixLabors.ImageSharp;
11+
using Xunit.Abstractions;
12+
13+
namespace OnnxStack.IntegrationTests;
14+
15+
/// <summary>
16+
/// These tests just run on CPU execution provider for now, but could switch it to CUDA and run on GPU
17+
/// if the necessary work is done to setup the docker container to allow GPU passthrough to the container.
18+
/// See https://blog.roboflow.com/use-the-gpu-in-docker/ for an example of how to do this.
19+
///
20+
/// Can then also setup a self-hosted runner in Github Actions to run the tests on your own GPU as part of the CI/CD pipeline.
21+
/// Maybe something like https://www.youtube.com/watch?v=rVq-SCNyxVc
22+
/// </summary>
23+
public class StableDiffusionTests
24+
{
25+
private readonly IStableDiffusionService _stableDiffusion;
26+
private readonly ILogger<StableDiffusionTests> _logger;
27+
private const string StableDiffusionModel = "StableDiffusion 1.5";
28+
private const string LatentConsistencyModel = "LCM-Dreamshaper-V7";
29+
30+
public StableDiffusionTests(ITestOutputHelper testOutputHelper)
31+
{
32+
var services = new ServiceCollection();
33+
services.AddLogging(builder => builder.AddConsole()); //necessary for showing logs when running in docker
34+
services.AddLogging(builder => builder.AddXunit(testOutputHelper)); //necessary for showing logs when running in IDE
35+
services.AddOnnxStackStableDiffusion();
36+
var provider = services.BuildServiceProvider();
37+
_stableDiffusion = provider.GetRequiredService<IStableDiffusionService>();
38+
_logger = provider.GetRequiredService<ILogger<StableDiffusionTests>>();
39+
}
40+
41+
[Theory]
42+
[InlineData(StableDiffusionModel)]
43+
[InlineData(LatentConsistencyModel)]
44+
public async Task GivenAStableDiffusionModel_WhenLoadModel_ThenModelIsLoaded(string modelName)
45+
{
46+
//arrange
47+
var model = _stableDiffusion.Models.Single(m => m.Name == modelName);
48+
49+
//act
50+
_logger.LogInformation("Attempting to load model {0}", model.Name);
51+
var isModelLoaded = await _stableDiffusion.LoadModel(model);
52+
53+
//assert
54+
isModelLoaded.Should().BeTrue();
55+
}
56+
57+
[Theory]
58+
[InlineData(StableDiffusionModel, SchedulerType.EulerAncestral, 10, 7.0f, "E518D0E4F67CBD5E93513574D30F3FD7")]
59+
[InlineData(LatentConsistencyModel, SchedulerType.LCM, 4, 1.0f, "3554E5E1B714D936805F4C9D890B0711")]
60+
public async Task GivenTextToImage_WhenInference_ThenImageGenerated(string modelName, SchedulerType schedulerType,
61+
int inferenceSteps, float guidanceScale, string generatedImageMd5Hash)
62+
63+
{
64+
//arrange
65+
var model = _stableDiffusion.Models.Single(m => m.Name == modelName);
66+
_logger.LogInformation("Attempting to load model: {0}", model.Name);
67+
await _stableDiffusion.LoadModel(model);
68+
69+
var prompt = new PromptOptions
70+
{
71+
Prompt = "an astronaut riding a horse in space",
72+
NegativePrompt = "blurry,ugly,cartoon",
73+
BatchCount = 1,
74+
DiffuserType = DiffuserType.TextToImage
75+
};
76+
77+
var scheduler = new SchedulerOptions
78+
{
79+
Width = 512,
80+
Height = 512,
81+
SchedulerType = schedulerType,
82+
InferenceSteps = inferenceSteps,
83+
GuidanceScale = guidanceScale,
84+
Seed = 1
85+
};
86+
87+
var steps = 0;
88+
89+
//act
90+
var image = await _stableDiffusion.GenerateAsImageAsync(model, prompt, scheduler, (currentStep, totalSteps) =>
91+
{
92+
_logger.LogInformation($"Step {currentStep}/{totalSteps}");
93+
steps++;
94+
});
95+
96+
var imagesDirectory = Path.Combine(Directory.GetCurrentDirectory(), "images");
97+
if (!Directory.Exists(imagesDirectory))
98+
{
99+
_logger.LogInformation($"Creating directory {imagesDirectory}");
100+
Directory.CreateDirectory(imagesDirectory);
101+
}
102+
else
103+
{
104+
_logger.LogInformation($"Directory {imagesDirectory} already exists");
105+
}
106+
107+
var fileName =
108+
$"{imagesDirectory}/{nameof(GivenTextToImage_WhenInference_ThenImageGenerated)}-{DateTime.Now:yyyyMMddHHmmss}.png";
109+
_logger.LogInformation($"Saving generated image to {fileName}");
110+
await image.SaveAsPngAsync(fileName);
111+
112+
//assert
113+
using (new AssertionScope())
114+
{
115+
steps.Should().Be(inferenceSteps);
116+
image.Should().NotBeNull();
117+
image.Size.IsEmpty.Should().BeFalse();
118+
image.Width.Should().Be(512);
119+
image.Height.Should().Be(512);
120+
121+
File.Exists(fileName).Should().BeTrue();
122+
var md5 = MD5.Create();
123+
var hash = md5.ComputeHash(File.ReadAllBytes(fileName));
124+
var hashString = string.Join("", hash.Select(b => b.ToString("X2")));
125+
_logger.LogInformation($"MD5 Hash of generated image: {hashString}");
126+
127+
hashString.Should().Be(generatedImageMd5Hash);
128+
}
129+
}
130+
}

OnnxStack.IntegrationTests/Usings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
global using Xunit;
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information"
5+
}
6+
},
7+
"OnnxStackConfig": {
8+
"OnnxModelSets": [
9+
{
10+
"Name": "StableDiffusion 1.5",
11+
"IsEnabled": true,
12+
"PadTokenId": 49407,
13+
"BlankTokenId": 49407,
14+
"TokenizerLimit": 77,
15+
"EmbeddingsLength": 768,
16+
"ScaleFactor": 0.18215,
17+
"PipelineType": "StableDiffusion",
18+
"Diffusers": [
19+
"TextToImage",
20+
"ImageToImage",
21+
"ImageInpaintLegacy"
22+
],
23+
"DeviceId": 0,
24+
"InterOpNumThreads": 0,
25+
"IntraOpNumThreads": 0,
26+
"ExecutionMode": "ORT_SEQUENTIAL",
27+
"ExecutionProvider": "Cpu",
28+
"ModelConfigurations": [
29+
{
30+
"Type": "Tokenizer",
31+
"OnnxModelPath": "/app/OnnxStack.StableDiffusion/cliptokenizer.onnx"
32+
},
33+
{
34+
"Type": "Unet",
35+
"OnnxModelPath": "/app/stable-diffusion-v1-5/unet/model.onnx"
36+
},
37+
{
38+
"Type": "TextEncoder",
39+
"OnnxModelPath": "/app/stable-diffusion-v1-5/text_encoder/model.onnx"
40+
},
41+
{
42+
"Type": "VaeEncoder",
43+
"OnnxModelPath": "/app/stable-diffusion-v1-5/vae_encoder/model.onnx"
44+
},
45+
{
46+
"Type": "VaeDecoder",
47+
"OnnxModelPath": "/app/stable-diffusion-v1-5/vae_decoder/model.onnx"
48+
}
49+
]
50+
},
51+
{
52+
"Name": "LCM-Dreamshaper-V7",
53+
"IsEnabled": true,
54+
"PadTokenId": 49407,
55+
"BlankTokenId": 49407,
56+
"TokenizerLimit": 77,
57+
"EmbeddingsLength": 768,
58+
"ScaleFactor": 0.18215,
59+
"PipelineType": "LatentConsistency",
60+
"Diffusers": [
61+
"TextToImage",
62+
"ImageToImage"
63+
],
64+
"DeviceId": 0,
65+
"InterOpNumThreads": 0,
66+
"IntraOpNumThreads": 0,
67+
"ExecutionMode": "ORT_SEQUENTIAL",
68+
"ExecutionProvider": "Cpu",
69+
"ModelConfigurations": [
70+
{
71+
"Type": "Tokenizer",
72+
"OnnxModelPath": "/app/LCM-Dreamshaper-V7-ONNX/tokenizer/model.onnx"
73+
},
74+
{
75+
"Type": "Unet",
76+
"OnnxModelPath": "/app/LCM-Dreamshaper-V7-ONNX/unet/model.onnx"
77+
},
78+
{
79+
"Type": "TextEncoder",
80+
"OnnxModelPath": "/app/LCM-Dreamshaper-V7-ONNX/text_encoder/model.onnx"
81+
},
82+
{
83+
"Type": "VaeEncoder",
84+
"OnnxModelPath": "/app/LCM-Dreamshaper-V7-ONNX/vae_encoder/model.onnx"
85+
},
86+
{
87+
"Type": "VaeDecoder",
88+
"OnnxModelPath": "/app/LCM-Dreamshaper-V7-ONNX/vae_decoder/model.onnx"
89+
}
90+
]
91+
}
92+
]
93+
}
94+
}

OnnxStackCore.sln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnnxStack.Core", "OnnxStack
44
EndProject
55
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnnxStack.StableDiffusion", "OnnxStack.StableDiffusion\OnnxStack.StableDiffusion.csproj", "{93F03618-9D5D-40E3-A565-729D72B164BB}"
66
EndProject
7+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnnxStack.IntegrationTests", "OnnxStack.IntegrationTests\OnnxStack.IntegrationTests.csproj", "{9336EF88-5290-451F-972C-CF9550EF545D}"
8+
EndProject
9+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{556184C8-7C99-4F06-86EF-EAAF52165252}"
10+
ProjectSection(SolutionItems) = preProject
11+
Dockerfile = Dockerfile
12+
.dockerignore = .dockerignore
13+
.gitignore = .gitignore
14+
docker-compose.yml = docker-compose.yml
15+
README.md = README.md
16+
EndProjectSection
17+
EndProject
718
Global
819
GlobalSection(SolutionConfigurationPlatforms) = preSolution
920
Debug|Any CPU = Debug|Any CPU
@@ -18,5 +29,9 @@ Global
1829
{93F03618-9D5D-40E3-A565-729D72B164BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
1930
{93F03618-9D5D-40E3-A565-729D72B164BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
2031
{93F03618-9D5D-40E3-A565-729D72B164BB}.Release|Any CPU.Build.0 = Release|Any CPU
32+
{9336EF88-5290-451F-972C-CF9550EF545D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33+
{9336EF88-5290-451F-972C-CF9550EF545D}.Debug|Any CPU.Build.0 = Debug|Any CPU
34+
{9336EF88-5290-451F-972C-CF9550EF545D}.Release|Any CPU.ActiveCfg = Release|Any CPU
35+
{9336EF88-5290-451F-972C-CF9550EF545D}.Release|Any CPU.Build.0 = Release|Any CPU
2136
EndGlobalSection
2237
EndGlobal

docker-compose.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
version: '3.7'
2+
3+
services:
4+
app:
5+
build: .
6+
volumes:
7+
- "./docker-test-output:/app/OnnxStack.IntegrationTests/bin/Debug/net7.0/images"

0 commit comments

Comments
 (0)