Changes
Build and Push Docker Images / build (push) Successful in 32s

This commit is contained in:
2026-05-06 12:48:44 +03:00
parent 89cb5a10da
commit 91cdb536b1
54 changed files with 153 additions and 137 deletions
+2 -2
View File
@@ -1,11 +1,11 @@
using Api.Services.Contracts.Models; using Api.Services.Contracts.Models;
using Api.Requests;
using Api.Services.Contracts; using Api.Services.Contracts;
using Api.Settings;
using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting; using Microsoft.AspNetCore.RateLimiting;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Api.Models.Settings;
using Api.Models.Requests;
namespace Api.Controllers namespace Api.Controllers
{ {
+1 -1
View File
@@ -1,4 +1,4 @@
using Api.Requests; using Api.Models.Requests;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting; using Microsoft.AspNetCore.RateLimiting;
using System.Net.Http.Headers; using System.Net.Http.Headers;
+1 -1
View File
@@ -1,5 +1,5 @@
using Api.Models.Settings;
using Api.Services.Contracts; using Api.Services.Contracts;
using Api.Settings;
using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles; using Microsoft.AspNetCore.StaticFiles;
+1 -1
View File
@@ -1,4 +1,4 @@
using Api.Settings; using Api.Models.Settings;
using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace Api.Requests namespace Api.Models.Requests
{ {
public sealed class ContactRequest public sealed class ContactRequest
{ {
@@ -1,4 +1,4 @@
namespace Api.Requests; namespace Api.Models.Requests;
public sealed class JobMatchRequest public sealed class JobMatchRequest
{ {
@@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace Api.Requests namespace Api.Models.Requests
{ {
public sealed class SubscribeRequest public sealed class SubscribeRequest
{ {
@@ -1,4 +1,4 @@
namespace Api.Settings namespace Api.Models.Settings
{ {
public sealed class CaptchaSettings public sealed class CaptchaSettings
{ {
@@ -1,4 +1,4 @@
namespace Api.Settings namespace Api.Models.Settings
{ {
public sealed class ContactSettings public sealed class ContactSettings
{ {
@@ -1,4 +1,4 @@
namespace Api.Settings namespace Api.Models.Settings
{ {
public sealed class FileStorageSettings public sealed class FileStorageSettings
{ {
@@ -1,4 +1,4 @@
namespace Api.Settings namespace Api.Models.Settings
{ {
public sealed class GoogleSettings public sealed class GoogleSettings
{ {
@@ -1,4 +1,4 @@
namespace Api.Settings namespace Api.Models.Settings
{ {
public sealed class KeyVaultSettings public sealed class KeyVaultSettings
{ {
@@ -1,4 +1,4 @@
namespace Api.Settings namespace Api.Models.Settings
{ {
public class SmtpSettings public class SmtpSettings
{ {
@@ -1,4 +1,4 @@
namespace Api.Settings namespace Api.Models.Settings
{ {
public sealed class SubscribeSettings public sealed class SubscribeSettings
{ {
+1 -1
View File
@@ -1,6 +1,6 @@
using Api.Models.Settings;
using Api.Services; using Api.Services;
using Api.Services.Contracts; using Api.Services.Contracts;
using Api.Settings;
using Azure.Identity; using Azure.Identity;
using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.HttpOverrides;
using Serilog; using Serilog;
+1 -1
View File
@@ -1,4 +1,4 @@
using Api.Requests; using Api.Models.Requests;
namespace Api.Services.Contracts namespace Api.Services.Contracts
{ {
+1 -1
View File
@@ -1,7 +1,7 @@
using Api.Services.Contracts.Models; using Api.Services.Contracts.Models;
using Api.Services.Contracts; using Api.Services.Contracts;
using Api.Settings;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Api.Models.Settings;
namespace Api.Services namespace Api.Services
{ {
+2 -2
View File
@@ -1,10 +1,10 @@
using Api.Services.Contracts; using Api.Services.Contracts;
using Api.Requests;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using MailKit.Net.Smtp; using MailKit.Net.Smtp;
using MailKit.Security; using MailKit.Security;
using MimeKit; using MimeKit;
using Api.Settings; using Api.Models.Settings;
using Api.Models.Requests;
namespace Api.Services namespace Api.Services
{ {
@@ -0,0 +1,8 @@
namespace Api.Models.Settings;
public sealed class AiSettings
{
public string Provider { get; set; } = "OpenAI";
public OpenAiSettings OpenAI { get; set; } = new();
public OllamaSettings Ollama { get; set; } = new();
}
@@ -1,4 +1,4 @@
namespace Api.Settings; namespace Api.Models.Settings;
public sealed class InternalApiSettings public sealed class InternalApiSettings
{ {
@@ -0,0 +1,8 @@
namespace Api.Models.Settings;
public sealed class MatcherSettings
{
public int TopK { get; set; } = 10;
public int DeepScoreTopN { get; set; } = 5;
public int MaxJobTextChars { get; set; } = 60000;
}
@@ -0,0 +1,8 @@
namespace Api.Models.Settings;
public sealed class OllamaSettings
{
public string BaseUrl { get; set; } = "http://localhost:11434";
public string ChatModel { get; set; } = "llama3.1:8b";
public int TimeoutSeconds { get; set; } = 180;
}
@@ -0,0 +1,8 @@
namespace Api.Models.Settings;
public sealed class OpenAiSettings
{
public string ApiKey { get; set; } = string.Empty;
public string ChatModel { get; set; } = "gpt-4o-mini";
public int TimeoutSeconds { get; set; } = 90;
}
@@ -0,0 +1,7 @@
namespace Api.Models.Settings;
public sealed class RagApiSettings
{
public string BaseUrl { get; set; } = "http://localhost:8081";
public string InternalApiKey { get; set; } = string.Empty;
}
@@ -1,52 +0,0 @@
namespace Api.Models.Settings;
public sealed class RagApiSettings
{
public string BaseUrl { get; set; } = "http://localhost:8081";
public string InternalApiKey { get; set; } = string.Empty;
}
public sealed class InternalApiSettings
{
public string ApiKey { get; set; } = string.Empty;
public bool RequireApiKey { get; set; } = false;
}
public sealed class AiSettings
{
public string Provider { get; set; } = "OpenAI";
public OpenAiSettings OpenAI { get; set; } = new();
public OllamaSettings Ollama { get; set; } = new();
}
public sealed class OpenAiSettings
{
public string ApiKey { get; set; } = string.Empty;
public string ChatModel { get; set; } = "gpt-4o-mini";
public int TimeoutSeconds { get; set; } = 90;
}
public sealed class OllamaSettings
{
public string BaseUrl { get; set; } = "http://localhost:11434";
public string ChatModel { get; set; } = "llama3.1:8b";
public int TimeoutSeconds { get; set; } = 180;
}
public sealed class MatcherSettings
{
public int TopK { get; set; } = 10;
public int DeepScoreTopN { get; set; } = 5;
public int MaxJobTextChars { get; set; } = 60000;
}
public sealed class SmtpSettings
{
public string Host { get; set; } = string.Empty;
public int Port { get; set; } = 587;
public string Username { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public bool UseStartTls { get; set; } = true;
public string FromEmail { get; set; } = "noreply@myai.ro";
public string ToEmail { get; set; } = string.Empty;
}
@@ -0,0 +1,12 @@
namespace Api.Models.Settings;
public sealed class SmtpSettings
{
public string Host { get; set; } = string.Empty;
public int Port { get; set; } = 587;
public string Username { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public bool UseStartTls { get; set; } = true;
public string FromEmail { get; set; } = "noreply@myai.ro";
public string ToEmail { get; set; } = string.Empty;
}
@@ -1,8 +1,9 @@
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Api.Services.Contracts; using Api.Models.Settings;
using Api.Settings; using Api.Data.Repositories.Contracts;
using Api.Clients.Ai.Contracts;
namespace Api.Services; namespace Api.Clients.Ai;
public sealed class CachedAiClient : IAiClient public sealed class CachedAiClient : IAiClient
{ {
@@ -1,4 +1,4 @@
namespace Api.Services.Contracts; namespace Api.Clients.Ai.Contracts;
public interface IAiClient public interface IAiClient
{ {
@@ -1,7 +1,7 @@
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
namespace Api.Services; namespace Api.Clients.Ai;
public static class HashHelper public static class HashHelper
{ {
@@ -3,10 +3,10 @@ using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Api.Services.Contracts; using Api.Models.Settings;
using Api.Settings; using Api.Clients.Ai.Contracts;
namespace Api.Services; namespace Api.Clients.Ai;
public sealed class RawAiClient : IAiClient public sealed class RawAiClient : IAiClient
{ {
+2 -2
View File
@@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Api.Services.Contracts; using Api.Services.Contracts;
using Api.Requests; using Api.Models.Requests;
namespace Api.Controllers; namespace Api.Controllers;
@@ -83,7 +83,7 @@ public sealed class RagController : ControllerBase
try try
{ {
_logger.LogInformation("Semantic search request received. TargetTypes={TargetTypes}, TopK={TopK}", _logger.LogInformation("Semantic search request received. TargetTypes={TargetTypes}, TopK={TopK}",
string.Join(',', request.TargetDocumentTypes ?? []), request.TopK); string.Join(',', request.TargetDocumentTypes ?? System.Array.Empty<string>()), request.TopK);
var result = await _ragService.SearchAsync(request, ct); var result = await _ragService.SearchAsync(request, ct);
_logger.LogInformation("Semantic search completed. ResultCount={ResultCount}", result.Results.Count); _logger.LogInformation("Semantic search completed. ResultCount={ResultCount}", result.Results.Count);
return Ok(result); return Ok(result);
@@ -1,6 +1,6 @@
using Api.Services.Contracts.Models; using Api.Models;
namespace Api.Services.Contracts; namespace Api.Data.Repositories.Contracts;
public interface IRagRepository public interface IRagRepository
{ {
@@ -1,10 +1,10 @@
using Api.Data; using Api.Data;
using Api.Data.Entities; using Api.Data.Entities;
using Api.Services.Contracts;
using Api.Services.Contracts.Models;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Api.Data.Repositories.Contracts;
using Api.Models;
namespace Api.Services; namespace Api.Data.Repositories;
public sealed class EfRagRepository : IRagRepository public sealed class EfRagRepository : IRagRepository
{ {
@@ -94,7 +94,7 @@ public sealed class EfRagRepository : IRagRepository
.Where(x => !string.IsNullOrWhiteSpace(x)) .Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => x.Trim().ToLowerInvariant()) .Select(x => x.Trim().ToLowerInvariant())
.Distinct() .Distinct()
.ToArray() ?? []; .ToArray() ?? System.Array.Empty<string>();
var query = _db.RagChunks var query = _db.RagChunks
.AsNoTracking() .AsNoTracking()
@@ -1,4 +1,4 @@
namespace Api.Services; namespace Api.Data.Repositories;
public static class VectorSerializer public static class VectorSerializer
{ {
@@ -1,10 +1,10 @@
namespace Api.Services.Contracts.Models namespace Api.Models
{ {
public sealed class DocumentClassification public sealed class DocumentClassification
{ {
public required string DocumentType { get; init; } public required string DocumentType { get; init; }
public double Confidence { get; init; } public double Confidence { get; init; }
public required string Title { get; init; } public required string Title { get; init; }
public Dictionary<string, string> Metadata { get; init; } = []; public Dictionary<string, string> Metadata { get; init; } = new Dictionary<string, string>();
} }
} }
@@ -1,4 +1,4 @@
namespace Api.Services.Contracts.Models namespace Api.Models
{ {
public sealed class RagChunkRecord public sealed class RagChunkRecord
{ {
@@ -1,4 +1,4 @@
namespace Api.Services.Contracts.Models namespace Api.Models
{ {
public sealed class RagDocumentDetails public sealed class RagDocumentDetails
{ {
@@ -1,4 +1,4 @@
namespace Api.Services.Contracts.Models namespace Api.Models
{ {
public sealed class RagDocumentRecord public sealed class RagDocumentRecord
{ {
@@ -1,4 +1,4 @@
namespace Api.Requests namespace Api.Models.Requests
{ {
public sealed class IndexDocumentRequest public sealed class IndexDocumentRequest
{ {
@@ -1,4 +1,4 @@
namespace Api.Requests namespace Api.Models.Requests
{ {
public sealed class SearchRequest public sealed class SearchRequest
{ {
@@ -1,4 +1,4 @@
namespace Api.Responses namespace Api.Models.Responses
{ {
public sealed class IndexDocumentResponse public sealed class IndexDocumentResponse
{ {
@@ -1,8 +1,8 @@
namespace Api.Responses namespace Api.Models.Responses
{ {
public sealed class SearchResponse public sealed class SearchResponse
{ {
public IReadOnlyList<SearchDocumentResult> Results { get; init; } = []; public IReadOnlyList<SearchDocumentResult> Results { get; init; } = System.Array.Empty<SearchDocumentResult>();
} }
public sealed class SearchDocumentResult public sealed class SearchDocumentResult
@@ -12,7 +12,7 @@
public required string Title { get; init; } public required string Title { get; init; }
public string? SourceUrl { get; init; } public string? SourceUrl { get; init; }
public double Score { get; init; } public double Score { get; init; }
public IReadOnlyList<SearchChunkResult> MatchedChunks { get; init; } = []; public IReadOnlyList<SearchChunkResult> MatchedChunks { get; init; } = System.Array.Empty<SearchChunkResult>();
} }
public sealed class SearchChunkResult public sealed class SearchChunkResult
@@ -1,4 +1,4 @@
namespace Api.Services.Contracts.Models namespace Api.Models
{ {
public sealed class SearchCandidateChunk public sealed class SearchCandidateChunk
{ {
+8
View File
@@ -0,0 +1,8 @@
namespace Api.Models.Settings;
public sealed class AiSettings
{
public string Provider { get; set; } = "OpenAI";
public OpenAiProviderSettings OpenAI { get; set; } = new();
public OllamaProviderSettings Ollama { get; set; } = new();
}
@@ -0,0 +1,7 @@
namespace Api.Models.Settings;
public sealed class InternalApiSettings
{
public string ApiKey { get; set; } = string.Empty;
public bool RequireApiKey { get; set; } = false;
}
@@ -0,0 +1,9 @@
namespace Api.Models.Settings;
public sealed class OllamaProviderSettings
{
public string BaseUrl { get; set; } = "http://localhost:11434";
public string ChatModel { get; set; } = "llama3.1:8b";
public string EmbeddingModel { get; set; } = "nomic-embed-text";
public int TimeoutSeconds { get; set; } = 180;
}
@@ -0,0 +1,9 @@
namespace Api.Models.Settings;
public sealed class OpenAiProviderSettings
{
public string ApiKey { get; set; } = string.Empty;
public string ChatModel { get; set; } = "gpt-4o-mini";
public string EmbeddingModel { get; set; } = "text-embedding-3-small";
public int TimeoutSeconds { get; set; } = 90;
}
@@ -1,4 +1,4 @@
namespace Api.Settings; namespace Api.Models.Settings;
public sealed class RagSettings public sealed class RagSettings
{ {
+5 -1
View File
@@ -3,10 +3,14 @@ using Microsoft.AspNetCore.Diagnostics;
using Api.Data; using Api.Data;
using Api.Services; using Api.Services;
using Api.Services.Contracts; using Api.Services.Contracts;
using Api.Settings;
using Serilog; using Serilog;
using System.Reflection; using System.Reflection;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Api.Models.Settings;
using Api.Data.Repositories.Contracts;
using Api.Data.Repositories;
using Api.Clients.Ai.Contracts;
using Api.Clients.Ai;
DotNetEnv.Env.Load(); DotNetEnv.Env.Load();
@@ -1,4 +1,4 @@
using Api.Services.Contracts.Models; using Api.Models;
namespace Api.Services.Contracts; namespace Api.Services.Contracts;
+3 -3
View File
@@ -1,6 +1,6 @@
using Api.Requests; using Api.Models;
using Api.Responses; using Api.Models.Requests;
using Api.Services.Contracts.Models; using Api.Models.Responses;
namespace Api.Services.Contracts; namespace Api.Services.Contracts;
+1 -1
View File
@@ -1,6 +1,6 @@
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Api.Services.Contracts; using Api.Services.Contracts;
using Api.Services.Contracts.Models; using Api.Models;
namespace Api.Services; namespace Api.Services;
+7 -4
View File
@@ -1,10 +1,13 @@
using System.Text.Json; using System.Text.Json;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Api.Services.Contracts; using Api.Services.Contracts;
using Api.Settings; using Api.Models.Requests;
using Api.Responses; using Api.Models.Responses;
using Api.Requests; using Api.Models.Settings;
using Api.Services.Contracts.Models; using Api.Data.Repositories.Contracts;
using Api.Clients.Ai.Contracts;
using Api.Clients.Ai;
using Api.Models;
namespace Api.Services; namespace Api.Services;
-24
View File
@@ -1,24 +0,0 @@
namespace Api.Settings;
public sealed class AiSettings
{
public string Provider { get; set; } = "OpenAI";
public OpenAiProviderSettings OpenAI { get; set; } = new();
public OllamaProviderSettings Ollama { get; set; } = new();
}
public sealed class OpenAiProviderSettings
{
public string ApiKey { get; set; } = string.Empty;
public string ChatModel { get; set; } = "gpt-4o-mini";
public string EmbeddingModel { get; set; } = "text-embedding-3-small";
public int TimeoutSeconds { get; set; } = 90;
}
public sealed class OllamaProviderSettings
{
public string BaseUrl { get; set; } = "http://localhost:11434";
public string ChatModel { get; set; } = "llama3.1:8b";
public string EmbeddingModel { get; set; } = "nomic-embed-text";
public int TimeoutSeconds { get; set; } = 180;
}