AI szopás

This commit is contained in:
Loretta 2025-11-01 19:43:21 +01:00
parent 538dba5773
commit f048b999cf
3 changed files with 195 additions and 35 deletions

View File

@ -15,9 +15,11 @@ using Nop.Web.Framework;
using Nop.Web.Framework.Mvc.Filters;
using System.Text;
using System.Text.Json;
//using AutoGen.Core;
using AyCode.Core.Consts;
using UglyToad.PdfPig.DocumentLayoutAnalysis.TextExtractor;
using AyCode.Core.Extensions;
//using AutoGen.Gemini;
namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
{
@ -309,8 +311,8 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
try
{
// ✅ Use the service we implemented earlier
//pdfText = await _openAIApiService.AnalyzePdfAsync(stream, currentFile.FileName, "Please extract all readable text from this PDF.");
pdfText = await _openAIApiService.AnalyzePdfAsync(stream, currentFile.FileName, DefaultFullPrompt);
pdfText = await _openAIApiService.AnalyzePdfAsync(stream, currentFile.FileName, "Please extract all readable text from this PDF.");
//pdfText = await _openAIApiService.AnalyzePdfAsync(stream, currentFile.FileName, DefaultFullPrompt);
}
catch (Exception aiEx)
{
@ -365,35 +367,87 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
shippingDocumentAnalysisResult = await ProcessRawText(shippingDocumentId, partnerId, pdfText, shippingDocumentAnalysisResult, filesList, dbFile);
await SaveDocumentToFileSystem(currentFile, shippingDocumentId, $"{Guid.NewGuid()}_{currentFile.FileName}");//shippingDocumentAnalysisResult.Partner.Name);
//Ez rész a catch végéig nekem teszt! - J
//try
//{
// responseRawPdfTexts += $"{AcEnv.NL}{AcEnv.NL}{currentFile.Name}:{AcEnv.NL}{pdfText}";
return Ok($"Files for Shipping Document ID {shippingDocumentId} were uploaded successfully!{AcEnv.NL}{AcEnv.NL}{responseRawPdfTexts}");
// var transactionSuccess = await SaveFileInfoToDb(shippingDocumentId, shippingDocumentAnalysisResult, filesList, dbFile, pdfText);
// if (!transactionSuccess)
// {
// _logger.Error($"(transactionSuccess == false)");
// return BadRequest($"Error saving file! RawText:{AcEnv.NL}{pdfText}");
// }
//Ez rész a catch végéig nekem teszt! - J.
try
{
//responseRawPdfTexts += $"{AcEnv.NL}{AcEnv.NL}{currentFile.Name}:{AcEnv.NL}{pdfText}";
// if (await SaveDocumentToFileSystem(currentFile, shippingDocumentId, $"{Guid.NewGuid()}_{currentFile.FileName}"))
// {
// //var partnerResponse = await _aiCalculationService.GetOpenAIPDFAnalysisFromText(
// // pdfText,
// // $"{DefaultFullPrompt}"
// //);
var transactionSuccess = await SaveFileInfoToDb(shippingDocumentId, shippingDocumentAnalysisResult, filesList, dbFile, pdfText);
if (!transactionSuccess)
{
_logger.Error($"(transactionSuccess == false)");
return BadRequest($"Error saving file! RawText:{AcEnv.NL}{pdfText}");
}
// //responseRawPdfTexts += $"{AcEnv.NL}{AcEnv.NL}{AcEnv.NL}Response json:{AcEnv.NL}{partnerResponse}";
// }
// //return Ok(shippingDocumentAnalysisResult);
//}
//catch (Exception ex)
//{
// _logger.Error($"Error saving file: {ex.Message}", ex);
// //return Json(new { success = false, errorMessage = ex.Message });
// return BadRequest("No files were uploaded.");
//}
if (await SaveDocumentToFileSystem(currentFile, shippingDocumentId, $"{Guid.NewGuid()}_{currentFile.FileName}"))
{
await using var stream = currentFile.OpenReadStream();
try
{
await _openAIApiService.CleanupAllVectorStoresAsync();
await _openAIApiService.CleanupAllAssistantsAsync();
pdfText = await _openAIApiService.AnalyzePdfAsync(stream, currentFile.FileName, "nyerd ki az összes adatot könnyen értelmezhető .txt formátumba!");
var projectID = "864202751803"; //"AIzaSyBAk5dyHnFrt8Upvqb2ICZmxws0Cf1de9M";//Environment.GetEnvironmentVariable("AIzaSyBAk5dyHnFrt8Upvqb2ICZmxws0Cf1de9M");
var apiKey = "AIzaSyBAk5dyHnFrt8Upvqb2ICZmxws0Cf1de9M";
if (projectID is not null)
{
//var geminiAgent = new GeminiChatAgent(
// name: "gemini",
// model: "gemini-2.5-flash",
// //location: "us-east4",
// //project: projectID,
// apiKey: apiKey,
// systemMessage: "Fruitbank egy zöldséges nagyker, ahol a bejövő szállítmányokat kezelik.")
// .RegisterMessageConnector()
// .RegisterPrintMessage();
////var imagePath = Path.Combine("resource", "images", "background.png");
////var image = await File.ReadAllBytesAsync(imagePath);
//var imageMessage = new ImageMessage(Role.User, BinaryData.FromStream(stream, "application/pdf"));
//var reply = await geminiAgent.SendAsync(DefaultFullPrompt, [imageMessage]);
//pdfText = reply.From;
//pdfText = "Feladó (Expediteur): Victor i Merce, S.L., Mercabarna, Pab.F-6035-6036, 08040 Barcelona, Spanyolország, CIF: ESB61478095.\r\n- Szállítmányozó (Transporteur): FRUIT BANK KFT, Rippl-Rónai utca 18, 1068 Budapest, Magyarország, CIF: HU14902170.\r\n- Címzett (Destinataire): FRUIT BANK KFT, Rippl-Rónai utca 18, 1068 Budapest, Magyarország, CIF: HU14902170.\r\n- Szállítás helye és ideje (Lugar y fecha de carga): 08040 Barcelona, Barcelona (Spanyolország), 2025. október 30.\r\n- Áru részletei (Mercancia): 140 TTE.MADURO G, összesen 840,00 kg bruttó tömeg.\r\n- Szállítás kifizetése a célállomáson (Transporte a payer par): TRANSPORTE A PAGAR EN DESTINO.\r\n\r\n\r\n\r\n";
responseRawPdfTexts += $"{AcEnv.NL}{AcEnv.NL}{currentFile.Name}:{AcEnv.NL}{pdfText}";
//pdfText = await _openAIApiService.GetSimpleResponseAsync("You are an assistant of FRUITBANK that extracts data from text. The user provides a text, and asks you questions about it. You extract the information without futher explanation.",
pdfText = await _openAIApiService.GetSimpleResponseAsync(DefaultFullPrompt, pdfText);
responseRawPdfTexts += $"{AcEnv.NL}{AcEnv.NL}{currentFile.Name}:{AcEnv.NL}{pdfText}";
}
else
{
Console.WriteLine("Please set GCP_VERTEX_PROJECT_ID environment variable.");
}
}
catch (Exception aiEx)
{
Console.Error.WriteLine($"OpenAI Assistants API failed: {aiEx.Message}");
return StatusCode(500, $"Failed to process PDF: {aiEx.Message}");
}
//var partnerResponse = await _aiCalculationService.GetOpenAIPDFAnalysisFromText(
// pdfText,
// $"{DefaultFullPrompt}"
//);
//responseRawPdfTexts += $"{AcEnv.NL}{AcEnv.NL}{AcEnv.NL}Response json:{AcEnv.NL}{partnerResponse}";
}
//return Ok(shippingDocumentAnalysisResult);
}
catch (Exception ex)
{
_logger.Error($"Error saving file: {ex.Message}", ex);
//return Json(new { success = false, errorMessage = ex.Message });
return BadRequest("No files were uploaded.");
}
}
//iteration 2: iterate documents again
@ -945,9 +999,9 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
}
private const string DefaultFullPrompt = $"Role:\r\nYou are an AI data extraction assistant for Fruitbank, a " +
$"fruit and vegetable wholesale company. Your task is to analyze a list of extracted pdf " +
$"documents (delivery notes, invoices, or order confirmations) and extract structured information about " +
$"the shipment and its items.\r\n\r\n🎯 Goal:\r\nRead the provided extracted pdf text and extract all shipment " +
$"fruit and vegetable wholesale company. Your task is to analyze a " +
$"provided text (delivery notes, invoices, or order confirmations) and extract structured information about " +
$"the shipment and its items.\r\n\r\n🎯 Goal:\r\nRead the provided text and extract all shipment " +
$"details and items according to the data model below.\r\n Generate the complete JSON output following this " +
$"structure.\r\n\r\n🧩 Data Models:\r\n\r\npublic " +
$"class Partner\r\n{{\r\n " +
@ -1005,7 +1059,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
$"(e.g. sequential: 1, 2, 3…).\r\n\r\n- When a field is missing or unclear, return it as an empty " +
$"string or 0 (depending on type).\r\nDo not omit any fields.\r\n\r\n- " +
$"All dates must be in ISO 8601 format (yyyy-MM-dd).\r\n\r\n🧭 Instructions to the AI\r\n" +
$"1. Analyze the provided PDF files one by one carefully.\r\n" +
$"1. Analyze the provided text one by one carefully.\r\n" +
$"2. Identify the Partner/Company details, " +
$"document identifiers, and each shipment item.\r\n" +
$"3. FruitBank is not a partner! Always look for THE OTHER partner on the document. \r\n " +
@ -1016,7 +1070,83 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
$"és a zöldség vagy gyümölcs nevét fordítsd le magyarra!\r\n" +
$"7. A ShippingDocument-et tedd bele a Partner entitásba!\r\n" +
$"8. ShippingItem-eket tedd bele a ShippingDocument-be!\r\n" +
$"9. Do not assume or modify any data, if you don't find a value, return null, if you find a value, keep it unmodified.";
$"9. Do not assume or modify any data, if you don't find a value, return null, if you find a value, keep it unmodified.\r\n" +
$"10. Magyarázat nélkül válaszolj!";
//+ $"\r\n\r\n" + $"***POVIDED TEXT***:";
//private const string DefaultFullPrompt = $"Role:\r\nYou are an AI data extraction assistant for Fruitbank, a " +
// $"fruit and vegetable wholesale company. Your task is to analyze a list of extracted pdf " +
// $"documents (delivery notes, invoices, or order confirmations) and extract structured information about " +
// $"the shipment and its items.\r\n\r\n🎯 Goal:\r\nRead the provided extracted pdf text and extract all shipment " +
// $"details and items according to the data model below.\r\n Generate the complete JSON output following this " +
// $"structure.\r\n\r\n🧩 Data Models:\r\n\r\npublic " +
// $"class Partner\r\n{{\r\n " +
// $"/// <summary>\r\n /// Partner entity primary key\r\n /// </summary>\r\n " +
// $"public int Id {{ get; set; }}\r\n " +
// $"/// <summary>\r\n /// Partner company name\r\n /// </summary>\r\n " +
// $"public string Name {{ get; set; }}\r\n " +
// $"/// <summary>\r\n /// Partner company TaxId\r\n /// </summary>\r\n " +
// $"public string TaxId {{ get; set; }}\r\n /// <summary>\r\n " +
// $"/// Partner company Certification if exists\r\n /// </summary>\r\n " +
// $"public string CertificationNumber {{ get; set; }}\r\n /// <summary>\r\n " +
// $"/// Partner company address PostalCode\r\n /// </summary>\r\n " +
// $"public string PostalCode {{ get; set; }}\r\n /// <summary>\r\n " +
// $"/// Partner company address Country\r\n /// </summary>\r\n " +
// $"public string Country {{ get; set; }}\r\n /// <summary>\r\n " +
// $"/// Partner company address State if exists\r\n /// </summary>\r\n " +
// $"public string State {{ get; set; }}\r\n /// <summary>\r\n " +
// $"/// Partner company address County if exists\r\n /// </summary>\r\n " +
// $"public string County {{ get; set; }}\r\n /// <summary>\r\n " +
// $"/// Partner company address City\r\n /// </summary>\r\n " +
// $"public string City {{ get; set; }}\r\n /// <summary>\r\n " +
// $"/// Partner company address Street\r\n /// </summary>\r\n " +
// $"public string Street {{ get; set; }}\r\n\t/// <summary>\r\n " +
// $"/// Entities of ShippingDocument\r\n /// </summary>\r\n\tpublic List<ShippingDocument> " +
// $"ShippingDocuments {{ get; set; }}\t\r\n}}\r\n\r\npublic class ShippingDocument\r\n{{\r\n " +
// $"/// <summary>\r\n /// ShippingItem entity primary key\r\n /// </summary>\r\n " +
// $"public int Id {{ get; set; }}\r\n /// <summary>\r\n /// Partner entity primary key\r\n " +
// $"/// </summary>\r\n public int PartnerId {{ get; set; }}\t\r\n\t/// <summary>\r\n " +
// $"/// Entities of ShippingItem\r\n /// </summary>\r\n\t" +
// $"public List<ShippingItem> ShippingItems {{ get; set; }}\r\n /// <summary>\r\n " +
// $"/// DocumentIdNumber if exists\r\n /// </summary>\r\n public string DocumentIdNumber {{ get; set; }}\r\n " +
// $"/// <summary>\r\n /// \r\n /// </summary>\r\n public DateTime ShippingDate {{ get; set; }}\r\n " +
// $"/// <summary>\r\n /// Shipping pickup Contry of origin\r\n /// </summary>\r\n " +
// $"public string Country {{ get; set; }}\r\n\t/// <summary>\r\n /// Sum of ShippingItem pallets\r\n " +
// $"/// </summary>\r\n public int TotalPallets {{ get; set; }}\r\n\t/// <summary>\r\n " +
// $"/// Filename of pdf\r\n /// </summary>\r\n\tpublic string PdfFileName {{ get; set; }}\r\n}}\r\n\r\n" +
// $"public class ShippingItem\r\n{{\r\n /// <summary>\r\n /// ShippingItem entity primary key\r\n /// " +
// $"</summary>\r\n public int Id {{ get; set; }}\r\n /// <summary>\r\n /// " +
// $"ShippingDocument entity primary key\r\n /// </summary>\r\n " +
// $"public int ShippingDocumentId {{ get; set; }}\r\n /// " +
// $"<summary>\r\n /// Name of the fruit or vegitable\r\n /// </summary>\r\n " +
// $"public string Name {{ get; set; }}\r\n\t/// <summary>\r\n /// Translated Name to Hungarian\r\n " +
// $"/// </summary>\r\n public string HungarianName {{ get; set; }}\r\n /// <summary>\r\n " +
// $"/// Pallets of fruit or vegitable item\r\n /// </summary>\r\n " +
// $"public int PalletsOnDocument {{ get; set; }}\r\n /// <summary>\r\n " +
// $"/// Quantity of fruit or vegitable item\r\n /// </summary>\r\n " +
// $"public int QuantityOnDocument {{ get; set; }}\r\n /// <summary>\r\n " +
// $"/// Net weight in kg. of fruit or vegitable item\r\n /// </summary>\r\n " +
// $"public double NetWeightOnDocument {{ get; set; }}\r\n /// <summary>\r\n " +
// $"/// Gross weight in kg. of fruit or vegitable item\r\n /// </summary>\r\n " +
// $"public double GrossWeightOnDocument {{ get; set; }}\r\n}}\r\n\r\n🧾 Output Requirements\r\n- " +
// $"Output must be a single valid JSON object containing:\r\n- One Partner object\r\n- " +
// $"One ShippingDocument object\r\n- A list of all related ShippingItem objects\r\n\r\n- " +
// $"Primary keys (Partner.Id, ShippingDocument.Id, ShippingItem.Id) should be auto-generated integers " +
// $"(e.g. sequential: 1, 2, 3…).\r\n\r\n- When a field is missing or unclear, return it as an empty " +
// $"string or 0 (depending on type).\r\nDo not omit any fields.\r\n\r\n- " +
// $"All dates must be in ISO 8601 format (yyyy-MM-dd).\r\n\r\n🧭 Instructions to the AI\r\n" +
// $"1. Analyze the provided PDF files one by one carefully.\r\n" +
// $"2. Identify the Partner/Company details, " +
// $"document identifiers, and each shipment item.\r\n" +
// $"3. FruitBank is not a partner! Always look for THE OTHER partner on the document. \r\n " +
// $"4. Generate a complete hierarchical JSON of ALL received documents in ONE JSON structure according to the " +
// $"data model above.\r\n5. Do not include any explanations or text outside the JSON output. " +
// $"Only return the structured JSON.\r\n" +
// $"6. A teljes ShippingItem.Name-et tedd bele a ShippingItem.HungarianName-be " +
// $"és a zöldség vagy gyümölcs nevét fordítsd le magyarra!\r\n" +
// $"7. A ShippingDocument-et tedd bele a Partner entitásba!\r\n" +
// $"8. ShippingItem-eket tedd bele a ShippingDocument-be!\r\n" +
// $"9. Do not assume or modify any data, if you don't find a value, return null, if you find a value, keep it unmodified.";
}
public class UploadModel

View File

@ -27,10 +27,12 @@
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="9.0.10" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="9.0.10" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="9.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.10" />
<!--<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.10" />-->
<PackageReference Include="PdfPig" Version="0.1.11" />
<PackageReference Include="PdfPig.Rendering.Skia" Version="0.1.11.5" />
<PackageReference Include="SendGrid" Version="9.29.3" />
<PackageReference Include="System.Memory.Data" Version="9.0.10" />
<PackageReference Include="Tesseract" Version="5.2.0" />
<PackageReference Include="TesseractOCR" Version="5.5.1" />
</ItemGroup>

View File

@ -312,6 +312,34 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
_assistantId ??= await FindOrCreateAssistantAsync("PDF and Image Analyzer Assistant");
}
public async Task CleanupAllVectorStoresAsync()
{
Console.WriteLine("Cleaning up all existing vector stores...");
var listRequest = new HttpRequestMessage(HttpMethod.Get, $"{BaseUrl}/vector_stores");
listRequest.Headers.Add("OpenAI-Beta", "assistants=v2");
var response = await _httpClient.SendAsync(listRequest);
if (response.IsSuccessStatusCode)
{
using var json = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
var vectorStores = json.RootElement.GetProperty("data");
foreach (var vectorStore in vectorStores.EnumerateArray())
{
var id = vectorStore.GetProperty("id").GetString();
var name = vectorStore.TryGetProperty("name", out var nameElement) && nameElement.ValueKind != JsonValueKind.Null
? nameElement.GetString()
: "Unnamed";
var deleteRequest = new HttpRequestMessage(HttpMethod.Delete, $"{BaseUrl}/vector_stores/{id}");
deleteRequest.Headers.Add("OpenAI-Beta", "assistants=v2");
await _httpClient.SendAsync(deleteRequest);
Console.WriteLine($"Deleted vector store: {name} ({id})");
}
Console.WriteLine("Vector store cleanup complete!");
}
}
//TEMPORARY: Cleanup all assistants (for testing purposes) - A.
public async Task CleanupAllAssistantsAsync()
{
@ -347,8 +375,8 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
public async Task<string?> AnalyzePdfAsync(Stream file, string fileName, string userPrompt)
{
await EnsureAssistantAndVectorStoreAsync();
var fileId = await UploadFileAsync(file, fileName);
var isImage = IsImageFile(fileName);
@ -640,7 +668,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
var assistantBody = new
{
name = name,
instructions = "You are an assistant that analyzes uploaded files. When you receive an image, analyze and describe what you see in the image in detail. When you receive a PDF or text document, use the file_search tool to find and analyze relevant information. Always respond directly to the user's question about the file they uploaded.",
instructions = "You are an assistant that analyzes uploaded files. When you receive an image, analyze and describe what you see in the image in detail. When you receive a PDF or text document, use the file_search tool to find and analyze relevant information. Always respond directly according to the user's instructions about the current file they upload.",
model = "gpt-4o",
tools = new[] { new { type = "file_search" } }
};