LLMでプロンプト文字列を作成してFLUX.1で画像生成する
最初に言っておきますと、ごめんなさいプロンプト通りに画像が生成できていません。ちゃんと動かしたいひとは改良してね。
FLUX.1が何なのかよくわからず一応画像は生成しているようです。civitaiにあるエッチなモデルはなぜか動きませんでした。また量子化してないモデルは大きすぎてGPUメモリに載らないため、めちゃくちゃ処理に時間かかります。なので今回はflux1-devのQ8を使ってます。
Nuget情報
Stable Diffusionよりもややこしいですね、いっぱいファイルが必要です。
ファイルリンク
flux1-dev-Q8_0.gguf
clip_l.safetensors
t5xxl_fp16.safetensors
ae.safetensors
概要
日本語で命令してLLMにプロンプトに変換してもらいFlux.1を使って画像生成する。
プロンプト生成は、愛しのGemma2です。
2024/10/31 Regex($"[(.+?)]")をRegex(@"[(.+?)]")に変更
using LLama.Common;
using LLama;
using System.Text.RegularExpressions;
using HPPH;
using HPPH.System.Drawing;
using StableDiffusion.NET;
namespace ChatProgram
{
public class Program
{
static void Main(string[] args)
{
Task task = MainAsync();
task.Wait();
}
public static async Task MainAsync()
{
string strPath = Environment.GetEnvironmentVariable("LLMPATH", System.EnvironmentVariableTarget.User)+@"dahara1\gemma-2-27b-it-gguf-japanese-imatrix\gemma-2-27b-it.f16.Q6_k.gguf";
string ModelPath = Environment.GetEnvironmentVariable("LLMPATH", System.EnvironmentVariableTarget.User) + @"flux\flux1-dev-Q8_0.gguf";
string ClipPath = Environment.GetEnvironmentVariable("LLMPATH", System.EnvironmentVariableTarget.User) + @"flux\clip_l.safetensors";
string T5xxPath = Environment.GetEnvironmentVariable("LLMPATH", System.EnvironmentVariableTarget.User) + @"flux\t5xxl_fp16.safetensors";
string VaePath = Environment.GetEnvironmentVariable("LLMPATH", System.EnvironmentVariableTarget.User) + @"flux\ae.safetensors";
const int intWidth = 768;
const int intHeight = 1280;
const float fltScale = 7f;
const int intSteps = 21;
const int intMax = 3;
long lngSeed = 0;
IImage objImage;
Console.ForegroundColor = ConsoleColor.Blue;
try
{
//stable diffusion設定
DiffusionModel sdModel = await Task.Run(() => ModelBuilder.Flux(ModelPath, ClipPath, T5xxPath, VaePath).WithMultithreading().Build());
//LLMの設定
ModelParams modPara = new(strPath)
{
ContextSize = 1024,
Seed = 1337
};
using LLamaWeights llmWeit = LLamaWeights.LoadFromFile(modPara);
using LLamaContext llmContx = llmWeit.CreateContext(modPara);
InteractiveExecutor itrEx = new(llmContx);
ChatHistory chtHis;
chtHis = new ChatHistory();
chtHis.AddMessage(AuthorRole.System, "あなたは優秀なAI画像生成プロンプトエンジニアです。ユーザーが要求した内容を忠実にstable diffusion用のプロンプトに変換してください。出力の形式は、例題のようにプロンプト文字列を[]で囲ってください。 例)[(best quality, masterpiece, absurbres, super-resolution), (photorealistic,realistic:1.4)]");
ChatSession chtSess = new(itrEx, chtHis);
var varHidewd = new LLamaTransforms.KeywordTextOutputStreamTransform(["User:", "Assistant:"]);
chtSess.WithOutputTransform(varHidewd);
InferenceParams infPara = new()
{
Temperature = 0.1f,
AntiPrompts = new List<string> { "User:" }
};
while (true)
{
// ユーザーのターン
Console.ForegroundColor = ConsoleColor.White;
Console.Write("\nUser: ");
string strInput = Console.ReadLine() ?? "";
ChatHistory.Message msg = new(AuthorRole.User, strInput);
if (strInput == "exit") break; // 'exit'と入力したら終わり
// AIのターン
Console.ForegroundColor = ConsoleColor.Yellow;
string strMsg = "";
await foreach (string strAns in chtSess.ChatAsync(msg, infPara))
{
Console.Write(strAns);
strMsg += strAns;
}
var strRegex = new Regex(@"[(.+?)]").Matches(strMsg);
string strPrompt = strRegex[0].Value.Replace("[","").Replace("]","").Trim();
//string strAntiPrompt = "(worst quality:2) , (low quality:2) , (normal quality:2) , lowres, ugly face, unclear eyes, bad mouth, bad tooth, bad anatomy, extra legs, (bad fingers, bad hands, missing fingers)";
string strAntiPrompt = "(worst quality:2) , (low quality:2)";
if (strPrompt != "") //プロンプト文字が間違っていなければ
{
for (int i = 0; i < intMax; i++)
{
Console.WriteLine($"**{i+1}枚目画像生成 開始**");
//Seed Random
Random rSeed = new Random();
lngSeed = rSeed.Next(0, int.MaxValue);
DiffusionParameter parameter = sdModel.GetDefaultParameter()
.WithNegativePrompt(strAntiPrompt)
.WithSize(intWidth, intHeight)
.WithSteps(intSteps)
.WithSeed(lngSeed)
.WithSampler(Sampler.DPMPP2Mv2)
.WithGuidance(fltScale);
objImage = await Task.Run(() => sdModel?.TextToImage(strPrompt, parameter));
string savePath = Environment.GetEnvironmentVariable("TESTDATA", System.EnvironmentVariableTarget.User) + $"Sd{DateTime.Now.ToString("yyyyMMddhhmmssfff")}.png";
File.WriteAllBytes(savePath, objImage.ToPng());
Console.WriteLine($"**{i+1}枚目画像生成 終了**");
}
}
}
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex.ToString());
}
}
}
}
実行結果
ビキニって言ったよね?・・・
女性って言ったよね?
だからビキニって・・・