using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Net.Http.Headers; using System.Net.Http.Json; using System.Text.Json; using _0_Framework.Application; using _0_Framework.Application.FaceEmbedding; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Http; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; namespace _0_Framework.Infrastructure; /// /// پیاده‌سازی سرویس ارتباط با API پایتون برای مدیریت Embeddings چهره /// public class FaceEmbeddingService : IFaceEmbeddingService { private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger _logger; private readonly IFaceEmbeddingNotificationService _notificationService; private readonly string _apiBaseUrl; public FaceEmbeddingService(IHttpClientFactory httpClientFactory, ILogger logger, IConfiguration configuration, IFaceEmbeddingNotificationService notificationService = null) { _httpClientFactory = httpClientFactory; _logger = logger; _notificationService = notificationService; _apiBaseUrl = configuration["FaceEmbeddingApi:BaseUrl"] ?? "http://localhost:8000"; } public async Task GenerateEmbeddingsAsync(long employeeId, long workshopId, string employeeFullName, string picture1Path, string picture2Path) { try { var httpClient = _httpClientFactory.CreateClient(); httpClient.BaseAddress = new Uri(_apiBaseUrl); httpClient.Timeout = TimeSpan.FromSeconds(30); using var content = new MultipartFormDataContent(); // Add form fields content.Add(new StringContent(employeeId.ToString()), "employee_id"); content.Add(new StringContent(workshopId.ToString()), "workshop_id"); content.Add(new StringContent(employeeFullName ?? ""), "employee_full_name"); // Add picture files if (File.Exists(picture1Path)) { var picture1Bytes = await File.ReadAllBytesAsync(picture1Path); var picture1Content = new ByteArrayContent(picture1Bytes); picture1Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); content.Add(picture1Content, "picture1", "1.jpg"); } else { _logger.LogWarning("Picture1 not found at path: {Path}", picture1Path); return new OperationResult { IsSuccedded = false, Message = "تصویر اول یافت نشد" }; } if (File.Exists(picture2Path)) { var picture2Bytes = await File.ReadAllBytesAsync(picture2Path); var picture2Content = new ByteArrayContent(picture2Bytes); picture2Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); content.Add(picture2Content, "picture2", "2.jpg"); } else { _logger.LogWarning("Picture2 not found at path: {Path}", picture2Path); return new OperationResult { IsSuccedded = false, Message = "تصویر دوم یافت نشد" }; } // Send request to Python API var response = await httpClient.PostAsync("embeddings", content); if (response.IsSuccessStatusCode) { var responseContent = await response.Content.ReadAsStringAsync(); _logger.LogInformation( "Embeddings generated successfully for Employee {EmployeeId}, Workshop {WorkshopId}", employeeId, workshopId); // ارسال اطلاع‌رسانی به سایر سیستم‌ها if (_notificationService != null) { await _notificationService.NotifyEmbeddingCreatedAsync(workshopId, employeeId, employeeFullName); } return new OperationResult { IsSuccedded = true, Message = "Embedding با موفقیت ایجاد شد" }; } else { var errorContent = await response.Content.ReadAsStringAsync(); _logger.LogError("Failed to generate embeddings. Status: {StatusCode}, Error: {Error}", response.StatusCode, errorContent); return new OperationResult { IsSuccedded = false, Message = $"خطا در تولید Embedding: {response.StatusCode}" }; } } catch (HttpRequestException ex) { _logger.LogError(ex, "HTTP error while calling embeddings API for Employee {EmployeeId}", employeeId); return new OperationResult { IsSuccedded = false, Message = "خطا در ارتباط با سرور Embedding" }; } catch (Exception ex) { _logger.LogError(ex, "Error while calling embeddings API for Employee {EmployeeId}", employeeId); return new OperationResult { IsSuccedded = false, Message = "خطای غیرمنتظره در تولید Embedding" }; } } public async Task GenerateEmbeddingsFromStreamAsync(long employeeId, long workshopId, string employeeFullName, Stream picture1Stream, Stream picture2Stream) { try { var httpClient = _httpClientFactory.CreateClient(); httpClient.BaseAddress = new Uri(_apiBaseUrl); httpClient.Timeout = TimeSpan.FromSeconds(30); using var content = new MultipartFormDataContent(); // Add form fields content.Add(new StringContent(employeeId.ToString()), "employee_id"); content.Add(new StringContent(workshopId.ToString()), "workshop_id"); content.Add(new StringContent(employeeFullName ?? ""), "employee_full_name"); // Add picture streams var picture1Content = new StreamContent(picture1Stream); picture1Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); content.Add(picture1Content, "picture1", "1.jpg"); var picture2Content = new StreamContent(picture2Stream); picture2Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); content.Add(picture2Content, "picture2", "2.jpg"); // Send request to Python API var response = await httpClient.PostAsync("embeddings", content); if (response.IsSuccessStatusCode) { _logger.LogInformation("Embeddings generated successfully from streams for Employee {EmployeeId}", employeeId); // ارسال اطلاع‌رسانی به سایر سیستم‌ها if (_notificationService != null) { await _notificationService.NotifyEmbeddingCreatedAsync(workshopId, employeeId, employeeFullName); } return new OperationResult { IsSuccedded = true, Message = "Embedding با موفقیت ایجاد شد" }; } else { var errorContent = await response.Content.ReadAsStringAsync(); _logger.LogError("Failed to generate embeddings from streams. Status: {StatusCode}, Error: {Error}", response.StatusCode, errorContent); return new OperationResult { IsSuccedded = false, Message = $"خطا در تولید Embedding: {response.StatusCode}" }; } } catch (Exception ex) { _logger.LogError(ex, "Error while generating embeddings from streams for Employee {EmployeeId}", employeeId); return new OperationResult { IsSuccedded = false, Message = "خطا در تولید Embedding" }; } } public async Task RefineEmbeddingAsync(long employeeId, long workshopId, float[] embedding, float confidence, Dictionary metadata = null) { try { var httpClient = _httpClientFactory.CreateClient(); httpClient.BaseAddress = new Uri(_apiBaseUrl); httpClient.Timeout = TimeSpan.FromSeconds(30); var requestBody = new { employeeId, workshopId, embedding, confidence, metadata = metadata ?? new Dictionary() }; var response = await httpClient.PostAsJsonAsync("embeddings/refine", requestBody); if (response.IsSuccessStatusCode) { _logger.LogInformation("Embedding refined successfully for Employee {EmployeeId}", employeeId); // ارسال اطلاع‌رسانی به سایر سیستم‌ها if (_notificationService != null) { await _notificationService.NotifyEmbeddingRefinedAsync(workshopId, employeeId); } return new OperationResult { IsSuccedded = true, Message = "Embedding بهبود یافت" }; } else { var errorContent = await response.Content.ReadAsStringAsync(); _logger.LogError("Failed to refine embedding. Status: {StatusCode}, Error: {Error}", response.StatusCode, errorContent); return new OperationResult { IsSuccedded = false, Message = $"خطا در بهبود Embedding: {response.StatusCode}" }; } } catch (Exception ex) { _logger.LogError(ex, "Error while refining embedding for Employee {EmployeeId}", employeeId); return new OperationResult { IsSuccedded = false, Message = "خطا در بهبود Embedding" }; } } public async Task DeleteEmbeddingAsync(long employeeId, long workshopId) { try { var httpClient = _httpClientFactory.CreateClient(); httpClient.BaseAddress = new Uri(_apiBaseUrl); httpClient.Timeout = TimeSpan.FromSeconds(30); var response = await httpClient.DeleteAsync($"embeddings/{workshopId}/{employeeId}"); if (response.IsSuccessStatusCode) { _logger.LogInformation("Embedding deleted successfully for Employee {EmployeeId}", employeeId); // ارسال اطلاع‌رسانی به سایر سیستم‌ها if (_notificationService != null) { await _notificationService.NotifyEmbeddingDeletedAsync(workshopId, employeeId); } return new OperationResult { IsSuccedded = true, Message = "Embedding حذف شد" }; } else { var errorContent = await response.Content.ReadAsStringAsync(); _logger.LogError("Failed to delete embedding. Status: {StatusCode}, Error: {Error}", response.StatusCode, errorContent); return new OperationResult { IsSuccedded = false, Message = $"خطا در حذف Embedding: {response.StatusCode}" }; } } catch (Exception ex) { _logger.LogError(ex, "Error while deleting embedding for Employee {EmployeeId}", employeeId); return new OperationResult { IsSuccedded = false, Message = "خطا در حذف Embedding" }; } } public async Task> GetEmbeddingAsync(long employeeId, long workshopId) { try { var httpClient = _httpClientFactory.CreateClient(); httpClient.BaseAddress = new Uri(_apiBaseUrl); httpClient.Timeout = TimeSpan.FromSeconds(30); var response = await httpClient.GetAsync($"embeddings/{workshopId}/{employeeId}"); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); var embeddingData = JsonSerializer.Deserialize(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); _logger.LogInformation("Embedding retrieved successfully for Employee {EmployeeId}", employeeId); return new OperationResult { IsSuccedded = true, Message = "Embedding دریافت شد", Data = embeddingData }; } else { var errorContent = await response.Content.ReadAsStringAsync(); _logger.LogError("Failed to get embedding. Status: {StatusCode}, Error: {Error}", response.StatusCode, errorContent); return new OperationResult { IsSuccedded = false, Message = $"خطا در دریافت Embedding: {response.StatusCode}" }; } } catch (Exception ex) { _logger.LogError(ex, "Error while getting embedding for Employee {EmployeeId}", employeeId); return new OperationResult { IsSuccedded = false, Message = "خطا در دریافت Embedding" }; } } public async Task UpdateEmbeddingFullNameAsync(long employeeId, long workshopId, string newFullName) { try { var httpClient = _httpClientFactory.CreateClient(); httpClient.BaseAddress = new Uri(_apiBaseUrl); httpClient.Timeout = TimeSpan.FromSeconds(30); var requestBody = new { employee_id = employeeId, workshop_id = workshopId, employee_full_name = newFullName }; var response = await httpClient.PutAsJsonAsync("embeddings/update-name", requestBody); if (response.IsSuccessStatusCode) { _logger.LogInformation("Employee Name Changed For {EmployeeId} In workshop ={WorkshopId}", employeeId, workshopId); // ارسال اطلاع‌رسانی به سایر سیستم‌ها if (_notificationService != null) { //await _notificationService.NotifyEmbeddingRefinedAsync(workshopId, employeeId); } return new OperationResult { IsSuccedded = true, Message = "عملیات با موفقیت انجام شد" }; } else { var errorContent = await response.Content.ReadAsStringAsync(); _logger.LogError("Failed to refine embedding. Status: {StatusCode}, Error: {Error}", response.StatusCode, errorContent); return new OperationResult { IsSuccedded = false, Message = $"خطا در بهبود Embedding: {response.StatusCode}" }; } } catch (Exception ex) { _logger.LogError(ex, "Error while Changing EmployeeFullName for Employee {EmployeeId}", employeeId); return new OperationResult { IsSuccedded = false, Message = "خطا در بهبود Embedding" }; } } }