This commit is contained in:
Hamid Reza Mohammadi 2024-12-13 18:30:59 +03:30
parent f1524378ae
commit 2dcefb5c34

View File

@ -15,7 +15,7 @@ using System.Drawing;
using FluentFTP;
using System.Threading.Tasks;
using RMuseum.Models.GanjoorIntegration;
using RMuseum.Models.Ganjoor;
namespace RMuseum.Services.Implementation
{
@ -36,7 +36,7 @@ namespace RMuseum.Services.Implementation
using (RMuseumDbContext context = new RMuseumDbContext(new DbContextOptions<RMuseumDbContext>())) //this is long running job, so _context might be already been freed/collected by GC
{
LongRunningJobProgressServiceEF jobProgressServiceEF = new LongRunningJobProgressServiceEF(context);
var job = (await jobProgressServiceEF.NewJob($"OpenAIStartCreatingImagesForPoems - start: {startFrom} - count: {count}", "Open AI initialization")).Result;
var job = (await jobProgressServiceEF.NewJob($"OpenAIStartCreatingImagesForPoems - start: {startFrom} - count: {count} - poet: {poetId}", "Open AI initialization")).Result;
try
{
@ -48,11 +48,33 @@ namespace RMuseum.Services.Implementation
await jobProgressServiceEF.UpdateJob(job.Id, 0, "Query data");
List<GanjoorCat> cats = poetId == 0 ? new List<GanjoorCat>() : await context.GanjoorCategories.AsNoTracking().Where(c => c.PoetId == poetId).ToListAsync();
string friendlyUrl = "ai";
RArtifactMasterRecord book = await context.Artifacts.Include(a => a.CoverImage).Where(b => b.FriendlyUrl == friendlyUrl).SingleOrDefaultAsync();
if (book == null)
{
await jobProgressServiceEF.UpdateJob(job.Id, 0, $"Creating book");
book = new RArtifactMasterRecord("فانوس خیال", "تصاویر تولید شده توسط هوش مصنوعی بر اساس متون گنجور")
{
Status = PublishStatus.Draft,
DateTime = DateTime.Now,
LastModified = DateTime.Now,
CoverItemIndex = 0,
CoverImageId = Guid.Parse("f9088a13-ea28-4e77-7c84-08dd0fdb87dc"),
FriendlyUrl = friendlyUrl,
NameInEnglish = "AI Generated images from ganjoor.net text",
ItemCount = 0,
Items = new List<RArtifactItemRecord>(),
Tags = new List<RTagValue>(),
};
await jobProgressServiceEF.UpdateJob(job.Id, 0, $"Creating book - 2");
await context.Artifacts.AddAsync(book);
await jobProgressServiceEF.UpdateJob(job.Id, 0, $"Creating book - 3");
}
await jobProgressServiceEF.UpdateJob(job.Id, 0, $"Query Poems");
var poems =
poetId != 0 ?
await context.GanjoorPoems.AsNoTracking().Where(p => cats.Any(c => c.Id == p.CatId)).ToListAsync() :
await context.GanjoorPoems.Include(p => p.Cat).AsNoTracking().Where(p => p.Cat.PoetId == poetId).ToListAsync() :
count == 0 ?
startFrom == 0 ?
await context.GanjoorPoems.AsNoTracking().ToListAsync()
@ -67,40 +89,25 @@ namespace RMuseum.Services.Implementation
.ToListAsync();
await jobProgressServiceEF.UpdateJob(job.Id, 0, $"Poems count = {poems.Count}");
string friendlyUrl = "ai";
RArtifactMasterRecord book = await context.Artifacts.Where(b => b.FriendlyUrl == friendlyUrl).SingleOrDefaultAsync();
if (book == null)
await jobProgressServiceEF.UpdateJob(job.Id, 0, $"Starting, {poems.Count}");
for (var i = 0; i < poems.Count; i++)
{
book = new RArtifactMasterRecord("فانوس خیال", "تصاویر تولید شده توسط هوش مصنوعی بر اساس متون گنجور")
var poem = poems[i];
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle}");
if (true == await context.GanjoorLinks.Where(l => l.ArtifactId == book.Id && l.GanjoorPostId == poem.Id).AnyAsync())
continue;
if (!string.IsNullOrEmpty(poem.PlainText))
{
Status = PublishStatus.Draft,
DateTime = DateTime.Now,
LastModified = DateTime.Now,
CoverItemIndex = 0,
FriendlyUrl = friendlyUrl,
NameInEnglish = "AI Generated images from ganjoor.net text",
};
context.Add(book);
await context.SaveChangesAsync();
}
using (var httpClient = new HttpClient())
for (var i = 0; i < poems.Count; i++)
{
var poem = poems[i];
if (true == await context.GanjoorLinks.Where(l => l.ArtifactId == book.Id && l.GanjoorPostId == poem.Id).AnyAsync())
continue;
if (!string.IsNullOrEmpty(poem.PlainText))
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle} - 1");
//1
bool hasStories = false;
var hasStoriesResult = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
{
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle} - 1");
//1
bool hasStories = false;
var hasStoriesResult = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
{
Messages = new List<ChatMessage>
Messages = new List<ChatMessage>
{
ChatMessage.FromSystem(
"آیا در متن زیر داستانی وجود دارد؟ اگر داستانی وجود ندارد 0 و اگر یک یا چند داستان وجود دارد 1 برگردان.."+
@ -113,24 +120,28 @@ namespace RMuseum.Services.Implementation
+ poem.PlainText
),
},
Model = Betalgo.Ranul.OpenAI.ObjectModels.Models.Gpt_4o,
});
if (hasStoriesResult.Successful)
Model = Betalgo.Ranul.OpenAI.ObjectModels.Models.Gpt_4o,
});
if (hasStoriesResult.Successful)
{
string resHasStories = hasStoriesResult.Choices.First().Message.Content;
if (resHasStories.Contains("اکتبر"))
{
string resHasStories = hasStoriesResult.Choices.First().Message.Content;
if (resHasStories.Contains("اکتبر"))
{
resHasStories = "0";
}
hasStories = resHasStories != "0";
resHasStories = "0";
}
if (!hasStories) continue;
hasStories = resHasStories != "0";
}
if (!hasStories)
{
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle} - بدون داستان");
continue;
}
//2
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle} - 2");
var storyResult = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
{
Messages = new List<ChatMessage>
//2
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle} - 2");
var storyResult = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
{
Messages = new List<ChatMessage>
{
ChatMessage.FromSystem(
"اگر در متن زیر داستانی وجود دارد آن را به نثر ساده بنویس. اگر چند داستان وجود دارد سعی کن همه را به طور خلاصه بیان کنی. متنت حالت نقل داستان داشته باشد و در آن نتیجه‌گیری نکن. اگر داستانی وجود ندارد خالی برگردان و هیچ توضیح اضافه‌ای مثل این که داستانی وجود ندارد نده."+
@ -143,27 +154,31 @@ namespace RMuseum.Services.Implementation
+ poem.PlainText
),
},
Model = Betalgo.Ranul.OpenAI.ObjectModels.Models.Gpt_4o,
});
string story = "";
if (storyResult.Successful)
Model = Betalgo.Ranul.OpenAI.ObjectModels.Models.Gpt_4o,
});
string story = "";
if (storyResult.Successful)
{
story = storyResult.Choices.First().Message.Content;
if (story.Contains("اکتبر"))
{
story = storyResult.Choices.First().Message.Content;
if (story.Contains("اکتبر"))
{
story = "";
}
story = story.Trim();
story = "";
}
story = story.Trim();
}
if (string.IsNullOrEmpty(story)) continue;
if (string.IsNullOrEmpty(story))
{
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle} - بدون متن داستان");
continue;
}
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle} - 3");
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle} - 3");
//3
var depictionResult = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
{
Messages = new List<ChatMessage>
//3
var depictionResult = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
{
Messages = new List<ChatMessage>
{
ChatMessage.FromSystem(
"Create a DALL-E propmt for depicting this story using an photorealistic image with Persian miniature style:"
@ -173,98 +188,104 @@ namespace RMuseum.Services.Implementation
story
),
},
Model = Betalgo.Ranul.OpenAI.ObjectModels.Models.Gpt_4o,
});
Model = Betalgo.Ranul.OpenAI.ObjectModels.Models.Gpt_4o,
});
string prompt = "";
if (depictionResult.Successful)
string prompt = "";
if (depictionResult.Successful)
{
prompt = depictionResult.Choices.First().Message.Content;
prompt = prompt.Trim();
}
if (string.IsNullOrEmpty(prompt))
{
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle} - بدون فرمان");
continue;
}
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle} - 4");
//4
var imageCreationResult = await openAiService.Image.CreateImage(new ImageCreateRequest
(
prompt
)
{
Model = "dall-e-3"
}
);
if (imageCreationResult.Successful)
{
string imageUrl = imageCreationResult.Results.Select(u => u.Url).First();
if (!string.IsNullOrEmpty(imageUrl))
{
prompt = depictionResult.Choices.First().Message.Content;
prompt = prompt.Trim();
}
if (string.IsNullOrEmpty(prompt)) continue;
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle} - 4");
int order = 1 + await context.Items.Where(i => i.RArtifactMasterRecordId == book.Id).CountAsync();
//4
var imageCreationResult = await openAiService.Image.CreateImage(new ImageCreateRequest
(
prompt
)
{
Model = "dall-e-3"
}
);
if (imageCreationResult.Successful)
{
string imageUrl = imageCreationResult.Results.Select(u => u.Url).First();
if (!string.IsNullOrEmpty(imageUrl))
RArtifactItemRecord page = new RArtifactItemRecord()
{
Name = $"تصویر {order} - {poem.FullTitle}",
NameInEnglish = $"Image {order} of {book.NameInEnglish}",
Description = story,
DescriptionInEnglish = prompt,
Order = order,
FriendlyUrl = $"p{$"{order}".PadLeft(7, '0')}",
LastModified = DateTime.Now,
RArtifactMasterRecordId = book.Id,
};
var promptTag = await TagHandler.PrepareAttribute(context, "AI Prompt", prompt, 1);
var ganjoorTag = await TagHandler.PrepareAttribute(context, "Ganjoor Link", poem.FullTitle, 1);
ganjoorTag.ValueSupplement = $"https://ganjoor.net{poem.FullUrl}";
var storyTag = await TagHandler.PrepareAttribute(context, "Story", story, 1);
page.Tags = [promptTag, ganjoorTag, storyTag];
int order = 1 + await context.Items.Where(i => i.RArtifactMasterRecordId == book.Id).CountAsync();
RArtifactItemRecord page = new RArtifactItemRecord()
{
Name = $"تصویر {order} - {poem.FullTitle}",
NameInEnglish = $"Image {order} of {book.NameInEnglish}",
Description = story,
DescriptionInEnglish = prompt,
Order = order,
FriendlyUrl = $"p{$"{order}".PadLeft(7, '0')}",
LastModified = DateTime.Now,
RArtifactMasterRecordId = book.Id,
};
var promptTag = await TagHandler.PrepareAttribute(context, "AI Prompt", prompt, 1);
var ganjoorTag = await TagHandler.PrepareAttribute(context, "Ganjoor Link", poem.FullTitle, 1);
ganjoorTag.ValueSupplement = poem.FullUrl;
var storyTag = await TagHandler.PrepareAttribute(context, "Story", story, 1);
page.Tags = [promptTag, ganjoorTag, storyTag];
if (
File.Exists
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "orig"), $"{order}".PadLeft(7, '0') + ".jpg")
)
if (
File.Exists
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "orig"), $"{order}".PadLeft(7, '0') + ".jpg")
)
{
File.Delete
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "orig"), $"{order}".PadLeft(7, '0') + ".jpg")
);
}
if (
File.Exists
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "norm"), $"{order}".PadLeft(7, '0') + ".jpg")
)
)
{
File.Delete
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "orig"), $"{order}".PadLeft(7, '0') + ".jpg")
);
}
if (
File.Exists
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "norm"), $"{order}".PadLeft(7, '0') + ".jpg")
)
{
File.Delete
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "norm"), $"{order}".PadLeft(7, '0') + ".jpg")
);
}
if (
File.Exists
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "thumb"), $"{order}".PadLeft(7, '0') + ".jpg")
)
)
{
File.Delete
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "norm"), $"{order}".PadLeft(7, '0') + ".jpg")
);
}
if (
File.Exists
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "thumb"), $"{order}".PadLeft(7, '0') + ".jpg")
)
{
File.Delete
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "thumb"), $"{order}".PadLeft(7, '0') + ".jpg")
);
}
)
{
File.Delete
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "thumb"), $"{order}".PadLeft(7, '0') + ".jpg")
);
}
using (var httpClient = new HttpClient())
{
var imageData = await httpClient.GetByteArrayAsync(imageUrl);
using var stream = new MemoryStream(imageData);
using var originalImage = Image.FromStream(stream);
@ -278,71 +299,82 @@ namespace RMuseum.Services.Implementation
{
throw new Exception($"_pictureFileService.Add : {picture.ExceptionString}");
}
page.Images = [picture.Result];
page.CoverImageIndex = 0;
}
context.Add(page);
await context.SaveChangesAsync();
}
if (book.CoverImage == null)
if (book.ItemCount == 0)
{
book.CoverImage = RPictureFile.Duplicate(page.Images.First());
book.Status = PublishStatus.Published;
book.ItemCount = order;
context.Update(book);
await context.SaveChangesAsync();
var resFTPUpload = await _UploadArtifactToExternalServer(book, context, false);
if (!string.IsNullOrEmpty(resFTPUpload.ExceptionString))
{
book.CoverImage = RPictureFile.Duplicate(page.Images.First());
book.Status = PublishStatus.Published;
context.Update(book);
await jobProgressServiceEF.UpdateJob(job.Id, 100, "", false, $"UploadArtifactToExternalServer: {resFTPUpload.ExceptionString}");
context.Update(job);
await context.SaveChangesAsync();
var resFTPUpload = await _UploadArtifactToExternalServer(book, context, false);
if (!string.IsNullOrEmpty(resFTPUpload.ExceptionString))
{
await jobProgressServiceEF.UpdateJob(job.Id, 100, "", false, $"UploadArtifactToExternalServer: {resFTPUpload.ExceptionString}");
context.Update(job);
await context.SaveChangesAsync();
return;
}
}
var resUpload = await _UploadArtifactPageToExternalServer(page, context, friendlyUrl, false);
if (resUpload.Result != true)
{
await jobProgressServiceEF.UpdateJob(job.Id, 100, "", false, resUpload.ExceptionString);
return;
}
File.Delete
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "orig"), $"{order}".PadLeft(7, '0') + ".jpg")
);
File.Delete
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "norm"), $"{order}".PadLeft(7, '0') + ".jpg")
);
File.Delete
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "thumb"), $"{order}".PadLeft(7, '0') + ".jpg")
);
GanjoorLink suggestion =
new GanjoorLink()
{
GanjoorPostId = poem.Id,
GanjoorTitle = poem.FullTitle,
GanjoorUrl = poem.FullUrl,
ArtifactId = book.Id,
ItemId = page.Id,
SuggestedById = systemUserId,
SuggestionDate = DateTime.Now,
ReviewResult = ReviewResult.Approved,
DisplayOnPage = true,
Synchronized = true,
};
context.GanjoorLinks.Add(suggestion);
}
else
{
book.ItemCount = order;
context.Update(book);
await context.SaveChangesAsync();
}
var resUpload = await _UploadArtifactPageToExternalServer(page, context, friendlyUrl, false);
if (resUpload.Result != true)
{
await jobProgressServiceEF.UpdateJob(job.Id, 100, "", false, resUpload.ExceptionString);
return;
}
File.Delete
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "orig"), $"{order}".PadLeft(7, '0') + ".jpg")
);
File.Delete
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "norm"), $"{order}".PadLeft(7, '0') + ".jpg")
);
File.Delete
(
Path.Combine(Path.Combine(Path.Combine(_pictureFileService.ImageStoragePath, friendlyUrl), "thumb"), $"{order}".PadLeft(7, '0') + ".jpg")
);
GanjoorLink suggestion =
new GanjoorLink()
{
GanjoorPostId = poem.Id,
GanjoorTitle = poem.FullTitle,
GanjoorUrl = $"https://ganjoor.net{poem.FullUrl}",
ArtifactId = book.Id,
ItemId = page.Id,
SuggestedById = systemUserId,
SuggestionDate = DateTime.Now,
ReviewResult = ReviewResult.Approved,
DisplayOnPage = true,
Synchronized = true,
};
context.GanjoorLinks.Add(suggestion);
await context.SaveChangesAsync();
}
}
}
}
await jobProgressServiceEF.UpdateJob(job.Id, 100, "", true);