#454 ai/generate/poem/geo

This commit is contained in:
Hamid Reza Mohammadi 2024-12-12 21:12:03 +03:30
parent e6ebc8e878
commit 72570307c4
4 changed files with 222 additions and 10 deletions

View File

@ -4493,6 +4493,22 @@ namespace RMuseum.Controllers
return Ok();
}
/// <summary>
/// geo tag poems using AI
/// </summary>
/// <param name="startFrom"></param>
/// <param name="count"></param>
/// <returns></returns>
[HttpPut("ai/generate/poem/geo")]
[Authorize(Policy = RMuseumSecurableItem.GanjoorEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public IActionResult OpenAIStartFillingGeoLocations(int startFrom = 0, int count = 0)
{
_ganjoorService.OpenAIStartFillingGeoLocations(startFrom, count);
return Ok();
}

View File

@ -2305,6 +2305,14 @@
<param name="count"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Controllers.GanjoorController.OpenAIStartFillingGeoLocations(System.Int32,System.Int32)">
<summary>
geo tag poems using AI
</summary>
<param name="startFrom"></param>
<param name="count"></param>
<returns></returns>
</member>
<member name="P:RMuseum.Controllers.GanjoorController.ReadOnlyMode">
<summary>
readonly mode
@ -4231,6 +4239,18 @@
<member name="M:RMuseum.Migrations.TajikAdditionalFields.BuildTargetModel(Microsoft.EntityFrameworkCore.ModelBuilder)">
<inheritdoc />
</member>
<member name="T:RMuseum.Migrations.GeoAIFields">
<inheritdoc />
</member>
<member name="M:RMuseum.Migrations.GeoAIFields.Up(Microsoft.EntityFrameworkCore.Migrations.MigrationBuilder)">
<inheritdoc />
</member>
<member name="M:RMuseum.Migrations.GeoAIFields.Down(Microsoft.EntityFrameworkCore.Migrations.MigrationBuilder)">
<inheritdoc />
</member>
<member name="M:RMuseum.Migrations.GeoAIFields.BuildTargetModel(Microsoft.EntityFrameworkCore.ModelBuilder)">
<inheritdoc />
</member>
<member name="T:RMuseum.Models.Accounting.DonationExpenditure">
<summary>
donation expenditures
@ -17018,6 +17038,13 @@
<param name="startFrom"></param>
<param name="count"></param>
</member>
<member name="M:RMuseum.Services.IGanjoorService.OpenAIStartFillingGeoLocations(System.Int32,System.Int32)">
<summary>
geo tag poems using AI
</summary>
<param name="startFrom"></param>
<param name="count"></param>
</member>
<member name="T:RMuseum.Services.IGanjoorTranslationService">
<summary>
translation service implementation
@ -18956,6 +18983,13 @@
<param name="startFrom"></param>
<param name="count"></param>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorService.OpenAIStartFillingGeoLocations(System.Int32,System.Int32)">
<summary>
geo tag poems using AI
</summary>
<param name="startFrom"></param>
<param name="count"></param>
</member>
<member name="M:RMuseum.Services.Implementation.GanjoorService.GetCategoryPaperSourcesAsync(System.Int32)">
<summary>
category paper sources

View File

@ -1545,5 +1545,12 @@ namespace RMuseum.Services
/// <param name="count"></param>
void OpenAIStartFillingPoemSummaries(int startFrom, int count);
/// <summary>
/// geo tag poems using AI
/// </summary>
/// <param name="startFrom"></param>
/// <param name="count"></param>
void OpenAIStartFillingGeoLocations(int startFrom, int count);
}
}

View File

@ -47,8 +47,8 @@ namespace RMuseum.Services.Implementation
count == 0 ?
startFrom == 0 ?
await context.GanjoorVerses.AsNoTracking()
.Where(v =>
(
.Where(v =>
(
v.VersePosition == VersePosition.Right
||
v.VersePosition == VersePosition.CenteredVerse1
@ -98,7 +98,7 @@ namespace RMuseum.Services.Implementation
;
await jobProgressServiceEF.UpdateJob(job.Id, 0, $"Verse count = {verses.Count}");
for ( var i = 0; i < verses.Count; i++ )
for (var i = 0; i < verses.Count; i++)
{
var verse = verses[i];
var editableVerse = await context.GanjoorVerses.Where(v => v.Id == verse.Id).SingleAsync();
@ -117,7 +117,7 @@ namespace RMuseum.Services.Implementation
{
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {verses.Count} - {couplet}");
string command = "این بیت را به فارسی روان معنی کن، در متن اشاره نکن که این معنی این بیت است:";
if(verse.VersePosition == VersePosition.Paragraph)
if (verse.VersePosition == VersePosition.Paragraph)
{
command = "این پاراگراف را به فارسی روان معنی کن، در متن اشاره نکن که این معنی این پاراگراف است:";
}
@ -137,14 +137,14 @@ namespace RMuseum.Services.Implementation
if (completionResult.Successful)
{
string summary = completionResult.Choices.First().Message.Content;
if(summary.Contains("اکتبر"))
if (summary.Contains("اکتبر"))
{
summary = "";
}
if (!string.IsNullOrEmpty(summary))
{
summary = "هوش مصنوعی: " + summary;
editableVerse.CoupletSummary = summary;
context.Update(editableVerse);
await context.SaveChangesAsync();
@ -222,14 +222,14 @@ namespace RMuseum.Services.Implementation
for (var i = 0; i < poems.Count; i++)
{
var poem = poems[i];
if (!string.IsNullOrEmpty(poem.PlainText))
{
var editablePoem = await context.GanjoorPoems.Where(p => p.Id == poem.Id).SingleAsync();
if(!string.IsNullOrEmpty(editablePoem.PoemSummary))
if (!string.IsNullOrEmpty(editablePoem.PoemSummary))
continue;
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle}");
string command = "به فارسی روان خلاصه کن:";
var completionResult = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
@ -255,7 +255,7 @@ namespace RMuseum.Services.Implementation
if (!string.IsNullOrEmpty(summary))
{
summary = "هوش مصنوعی: " + summary;
editablePoem.PoemSummary = summary;
context.Update(editablePoem);
await context.SaveChangesAsync();
@ -277,5 +277,160 @@ namespace RMuseum.Services.Implementation
});
}
/// <summary>
/// geo tag poems using AI
/// </summary>
/// <param name="startFrom"></param>
/// <param name="count"></param>
public void OpenAIStartFillingGeoLocations(int startFrom, int count)
{
_backgroundTaskQueue.QueueBackgroundWorkItem
(
async token =>
{
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($"OpenAIStartFillingGeoLocations - start: {startFrom} - count: {count}", "Open AI initialization")).Result;
try
{
var openAiService = new OpenAIService(new OpenAIOptions()
{
ApiKey = Configuration["OpenAIAPIKey"],
BaseDomain = Configuration["OpenAIBaseUrl"]
});
await jobProgressServiceEF.UpdateJob(job.Id, 0, "Query data");
var poems =
count == 0 ?
startFrom == 0 ?
await context.GanjoorPoems.AsNoTracking()
.Where(
p => string.IsNullOrEmpty(p.PoemSummary)
)
.ToListAsync()
:
await context.GanjoorPoems.AsNoTracking()
.Where(
p => string.IsNullOrEmpty(p.PoemSummary)
)
.Skip(startFrom)
.ToListAsync()
:
await context.GanjoorPoems.AsNoTracking()
.Where(
p => string.IsNullOrEmpty(p.PoemSummary)
)
.Skip(startFrom)
.Take(count)
.ToListAsync();
await jobProgressServiceEF.UpdateJob(job.Id, 0, $"Poems count = {poems.Count}");
for (var i = 0; i < poems.Count; i++)
{
var poem = poems[i];
if (true == await context.PoemGeoDateTags.AsNoTracking().Where(p => p.PoemId == poem.Id && p.MachineGenerated == false).AnyAsync())
{
continue;
}
if (!string.IsNullOrEmpty(poem.PlainText))
{
await jobProgressServiceEF.UpdateJob(job.Id, i, $"{i} از {poems.Count} - {poem.FullTitle}");
string command = "نام شهرها یا مکانهای جغرافیایی که در این متن آمده است را بده.اگر هیچ شهر یا مکان جغرافیایی در متن نیست جواب خالی برگردان." + Environment.NewLine +
"اگر نام مکان واقعاً اشاره به آن مکان نیست مثلاً در مورد مردی از اهالی آن شهر صحبت می‌کند یا در این متن آن کلمه معنی اسم مکان مورد نظر را نمی‌دهد آن را حذف کن." + Environment.NewLine +
"اگر هست به ازای هر مورد در یک خط ابتدا نام مکان، سپس یک سمی کالن، سپس عرض جغرافیایی سپس یک سمی کالن سپس طول جغرافیایی را بده." + Environment.NewLine +
"نمونهٔ جواب:" + Environment.NewLine +
"شیراز;29.5926;52.5836" + Environment.NewLine +
"برای پایان خط از استاندارد ویندوز استفاده کن.";
var completionResult = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
{
Messages = new List<ChatMessage>
{
ChatMessage.FromSystem(command
+
Environment.NewLine
+
poem.Title +
Environment.NewLine +
poem.PlainText
),
},
Model = Betalgo.Ranul.OpenAI.ObjectModels.Models.Gpt_4o_mini,
});
if (completionResult.Successful)
{
string aiResponse = completionResult.Choices.First().Message.Content;
if (aiResponse.Contains("اکتبر"))
{
aiResponse = "";
}
if (!string.IsNullOrEmpty(aiResponse))
{
var lines = aiResponse.Split(new[] { '\r', '\n' });
foreach (var line in lines)
{
var parts = line.Split(';');
if (parts.Length == 3)
{
var locationName = parts[0];
if (!double.TryParse(parts[1], out double latitude))
continue;
if (!double.TryParse(parts[2], out double longitude))
continue;
GanjoorGeoLocation geoLocation = await context.GanjoorGeoLocations.AsNoTracking().Where(g => g.Name == locationName).FirstOrDefaultAsync();
if (geoLocation == null)
{
geoLocation = new GanjoorGeoLocation()
{
Name = locationName,
Latitude = latitude,
Longitude = longitude,
MachineGenerated = true,
};
context.Add(geoLocation);
await context.SaveChangesAsync();
}
if (true == await context.PoemGeoDateTags.AsNoTracking().Where(p => p.PoemId == poem.Id && p.LocationId == geoLocation.Id && p.CoupletIndex == 0).AnyAsync())
{
continue;
}
PoemGeoDateTag poemGeoDateTag = new PoemGeoDateTag()
{
PoemId = poem.Id,
CoupletIndex = 0,
LocationId = geoLocation.Id,
MachineGenerated = true,
};
context.Add(poemGeoDateTag);
await context.SaveChangesAsync();
}
}
}
}
}
}
await jobProgressServiceEF.UpdateJob(job.Id, 100, "", true);
}
catch (Exception exp)
{
await jobProgressServiceEF.UpdateJob(job.Id, 100, "", false, exp.ToString());
}
}
});
}
}
}