Changes
This commit is contained in:
+2
-2
@@ -210,8 +210,8 @@ try
|
|||||||
logger.LogInformation("Environment: {Environment}", app.Environment.EnvironmentName);
|
logger.LogInformation("Environment: {Environment}", app.Environment.EnvironmentName);
|
||||||
|
|
||||||
// Log all environment variables and configuration settings at startup
|
// Log all environment variables and configuration settings at startup
|
||||||
// Can be controlled via appsettings: "Logging:LogEnvironmentOnStartup": true
|
// Can be controlled via appsettings: "LogEnvironmentOnStartup": true
|
||||||
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("Logging:LogEnvironmentOnStartup", defaultValue: true);
|
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("LogEnvironmentOnStartup", defaultValue: true);
|
||||||
if (logEnvironmentOnStartup)
|
if (logEnvironmentOnStartup)
|
||||||
{
|
{
|
||||||
LogEnvironmentSettings(logger, app.Configuration, app.Environment);
|
LogEnvironmentSettings(logger, app.Configuration, app.Environment);
|
||||||
|
|||||||
@@ -36,9 +36,9 @@
|
|||||||
"Microsoft.AspNetCore.Routing": "Warning",
|
"Microsoft.AspNetCore.Routing": "Warning",
|
||||||
"System.Net.Http.HttpClient": "Warning",
|
"System.Net.Http.HttpClient": "Warning",
|
||||||
"Api": "Debug"
|
"Api": "Debug"
|
||||||
},
|
}
|
||||||
"LogEnvironmentOnStartup": true
|
|
||||||
},
|
},
|
||||||
|
"LogEnvironmentOnStartup": true,
|
||||||
"KeyVault": {
|
"KeyVault": {
|
||||||
"VaultUri": "",
|
"VaultUri": "",
|
||||||
"Enabled": false
|
"Enabled": false
|
||||||
|
|||||||
@@ -58,7 +58,6 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogEnvironmentOnStartup": true,
|
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning",
|
"Microsoft.AspNetCore": "Warning",
|
||||||
@@ -68,6 +67,7 @@
|
|||||||
"Api": "Information"
|
"Api": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"LogEnvironmentOnStartup": true,
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"KeyVault": {
|
"KeyVault": {
|
||||||
"VaultUri": "",
|
"VaultUri": "",
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Api.Services.Contracts;
|
namespace Api.Clients.Ai.Contracts;
|
||||||
|
|
||||||
public interface IMatcherAiClient
|
public interface IMatcherAiClient
|
||||||
{
|
{
|
||||||
@@ -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
|
||||||
{
|
{
|
||||||
+4
-3
@@ -2,11 +2,12 @@ using System.Net.Http.Headers;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using Api.Services.Contracts;
|
using Api.Clients.Ai.Contracts;
|
||||||
using Api.Settings;
|
using Api.Data.Repositories.Contracts;
|
||||||
|
using Api.Models.Settings;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Api.Services;
|
namespace Api.Clients.Ai;
|
||||||
|
|
||||||
public sealed class MatcherAiClient : IMatcherAiClient
|
public sealed class MatcherAiClient : IMatcherAiClient
|
||||||
{
|
{
|
||||||
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
using Api.Requests;
|
using Api.Models.Requests;
|
||||||
using Api.Responses;
|
using Api.Models.Responses;
|
||||||
|
|
||||||
namespace Api.Services.Contracts;
|
namespace Api.Clients.Api.Contracts;
|
||||||
|
|
||||||
public interface IRagApiClient
|
public interface IRagApiClient
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using Refit;
|
||||||
|
using Api.Models.Responses;
|
||||||
|
using Api.Models.Requests;
|
||||||
|
|
||||||
|
namespace Api.Clients.Api.Contracts;
|
||||||
|
|
||||||
|
[Headers("Accept: application/json")]
|
||||||
|
public interface IRefitRagApi
|
||||||
|
{
|
||||||
|
[Multipart]
|
||||||
|
[Post("/api/rag/documents")]
|
||||||
|
Task<RagIndexResponse> IndexDocumentAsync([AliasAs("file")] StreamPart file,
|
||||||
|
[AliasAs("documentType")] string documentType,
|
||||||
|
[AliasAs("title")] string title,
|
||||||
|
CancellationToken ct = default);
|
||||||
|
|
||||||
|
[Multipart]
|
||||||
|
[Post("/api/rag/documents")]
|
||||||
|
Task<RagIndexResponse> IndexDocumentWithTextAsync([AliasAs("text")] string text,
|
||||||
|
[AliasAs("documentType")] string documentType,
|
||||||
|
[AliasAs("title")] string title,
|
||||||
|
[AliasAs("sourceUrl")] string? sourceUrl = null,
|
||||||
|
CancellationToken ct = default);
|
||||||
|
|
||||||
|
[Get("/api/rag/documents/{documentId}")]
|
||||||
|
Task<RagDocumentDetails> GetDocumentAsync(string documentId, CancellationToken ct = default);
|
||||||
|
|
||||||
|
[Post("/api/rag/search")]
|
||||||
|
Task<RagSearchResponse> SearchAsync([Body] RagSearchRequest request, CancellationToken ct = default);
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
using System.Net;
|
||||||
|
using Refit;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Api.Clients.Api.Contracts;
|
||||||
|
using Api.Models.Responses;
|
||||||
|
using Api.Models.Settings;
|
||||||
|
using Api.Models.Requests;
|
||||||
|
|
||||||
|
namespace Api.Clients.Api;
|
||||||
|
|
||||||
|
public sealed class RagApiClient : IRagApiClient
|
||||||
|
{
|
||||||
|
private readonly IRefitRagApi _refit;
|
||||||
|
|
||||||
|
public RagApiClient(IRefitRagApi refit, IOptions<RagApiSettings> options)
|
||||||
|
{
|
||||||
|
_refit = refit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RagIndexResponse> IndexCvPdfAsync(IFormFile file, CancellationToken ct)
|
||||||
|
{
|
||||||
|
await using var stream = file.OpenReadStream();
|
||||||
|
var part = new StreamPart(stream, file.FileName, "application/pdf");
|
||||||
|
return await _refit.IndexDocumentAsync(part, "cv", file.FileName, ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RagIndexResponse> IndexJobTextAsync(string text, string? url, string? title, CancellationToken ct)
|
||||||
|
{
|
||||||
|
return await _refit.IndexDocumentWithTextAsync(text, "job", title ?? "Job description", url, ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RagDocumentDetails?> GetDocumentAsync(string documentId, CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await _refit.GetDocumentAsync(documentId, ct);
|
||||||
|
}
|
||||||
|
catch (ApiException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RagSearchResponse> SearchAsync(RagSearchRequest request, CancellationToken ct)
|
||||||
|
{
|
||||||
|
return await _refit.SearchAsync(request, ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using Api.Requests;
|
using Api.Models.Requests;
|
||||||
using Api.Services.Contracts;
|
using Api.Services.Contracts;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
using Api.Responses;
|
using Api.Models.Responses;
|
||||||
|
|
||||||
namespace Api.Services.Contracts;
|
namespace Api.Data.Repositories.Contracts;
|
||||||
|
|
||||||
public interface IMatcherRepository
|
public interface IMatcherRepository
|
||||||
{
|
{
|
||||||
+3
-3
@@ -1,11 +1,11 @@
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Api.Data;
|
using Api.Data;
|
||||||
using Api.Data.Entities;
|
using Api.Data.Entities;
|
||||||
using Api.Responses;
|
using Api.Data.Repositories.Contracts;
|
||||||
using Api.Services.Contracts;
|
using Api.Models.Responses;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Api.Services;
|
namespace Api.Data.Repositories;
|
||||||
|
|
||||||
public sealed class EfMatcherRepository : IMatcherRepository
|
public sealed class EfMatcherRepository : IMatcherRepository
|
||||||
{
|
{
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
IF OBJECT_ID('dbo.CvMatchResults', 'U') IS NULL
|
|
||||||
BEGIN
|
|
||||||
CREATE TABLE dbo.CvMatchResults (
|
|
||||||
Id NVARCHAR(64) NOT NULL CONSTRAINT PK_CvMatchResults PRIMARY KEY,
|
|
||||||
CvDocumentId NVARCHAR(64) NOT NULL,
|
|
||||||
JobDocumentId NVARCHAR(64) NOT NULL,
|
|
||||||
ResultJson NVARCHAR(MAX) NOT NULL,
|
|
||||||
Score INT NOT NULL,
|
|
||||||
CreatedAt DATETIME2 NOT NULL CONSTRAINT DF_CvMatchResults_CreatedAt DEFAULT SYSUTCDATETIME()
|
|
||||||
);
|
|
||||||
CREATE UNIQUE INDEX UX_CvMatchResults_CvJob ON dbo.CvMatchResults(CvDocumentId, JobDocumentId);
|
|
||||||
END
|
|
||||||
GO
|
|
||||||
|
|
||||||
IF OBJECT_ID('dbo.CvMatcherChatCache', 'U') IS NULL
|
|
||||||
BEGIN
|
|
||||||
CREATE TABLE dbo.CvMatcherChatCache (
|
|
||||||
CacheKey NVARCHAR(64) NOT NULL CONSTRAINT PK_CvMatcherChatCache PRIMARY KEY,
|
|
||||||
Model NVARCHAR(120) NOT NULL,
|
|
||||||
Temperature DECIMAL(4,2) NOT NULL,
|
|
||||||
ResponseText NVARCHAR(MAX) NOT NULL,
|
|
||||||
CreatedAt DATETIME2 NOT NULL CONSTRAINT DF_CvMatcherChatCache_CreatedAt DEFAULT SYSUTCDATETIME()
|
|
||||||
);
|
|
||||||
END
|
|
||||||
GO
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Api.Requests
|
namespace Api.Models.Requests
|
||||||
{
|
{
|
||||||
public sealed class FindJobsRequest
|
public sealed class FindJobsRequest
|
||||||
{
|
{
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Api.Requests
|
namespace Api.Models.Requests
|
||||||
{
|
{
|
||||||
public sealed class MatchJobRequest
|
public sealed class MatchJobRequest
|
||||||
{
|
{
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Api.Requests
|
namespace Api.Models.Requests
|
||||||
{
|
{
|
||||||
public sealed class RagSearchRequest
|
public sealed class RagSearchRequest
|
||||||
{
|
{
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Api.Responses
|
namespace Api.Models.Responses
|
||||||
{
|
{
|
||||||
public sealed class CvUploadResponse
|
public sealed class CvUploadResponse
|
||||||
{
|
{
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Api.Responses
|
namespace Api.Models.Responses
|
||||||
{
|
{
|
||||||
public sealed class FindJobsResponse
|
public sealed class FindJobsResponse
|
||||||
{
|
{
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Api.Responses
|
namespace Api.Models.Responses
|
||||||
{
|
{
|
||||||
public sealed class JobMatchResponse
|
public sealed class JobMatchResponse
|
||||||
{
|
{
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Api.Responses
|
namespace Api.Models.Responses
|
||||||
{
|
{
|
||||||
public sealed class RagIndexResponse
|
public sealed class RagIndexResponse
|
||||||
{
|
{
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace Api.Responses
|
namespace Api.Models.Responses
|
||||||
{
|
{
|
||||||
public sealed class RagSearchResponse
|
public sealed class RagSearchResponse
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Api.Settings;
|
namespace Api.Models.Settings;
|
||||||
|
|
||||||
public sealed class RagApiSettings
|
public sealed class RagApiSettings
|
||||||
{
|
{
|
||||||
@@ -2,11 +2,18 @@ using Azure.Identity;
|
|||||||
using Api.Data;
|
using Api.Data;
|
||||||
using Api.Services;
|
using Api.Services;
|
||||||
using Api.Services.Contracts;
|
using Api.Services.Contracts;
|
||||||
using Api.Settings;
|
|
||||||
using Microsoft.AspNetCore.Diagnostics;
|
using Microsoft.AspNetCore.Diagnostics;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Refit;
|
||||||
|
using Api.Data.Repositories;
|
||||||
|
using Api.Data.Repositories.Contracts;
|
||||||
|
using Api.Clients.Api;
|
||||||
|
using Api.Clients.Api.Contracts;
|
||||||
|
using Api.Clients.Ai;
|
||||||
|
using Api.Clients.Ai.Contracts;
|
||||||
|
using Api.Models.Settings;
|
||||||
|
|
||||||
DotNetEnv.Env.Load();
|
DotNetEnv.Env.Load();
|
||||||
|
|
||||||
@@ -68,7 +75,19 @@ try
|
|||||||
builder.Services.Configure<MatcherSettings>(builder.Configuration.GetSection("Matcher"));
|
builder.Services.Configure<MatcherSettings>(builder.Configuration.GetSection("Matcher"));
|
||||||
builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("Smtp"));
|
builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("Smtp"));
|
||||||
|
|
||||||
builder.Services.AddHttpClient<IRagApiClient, RagApiClient>();
|
// Register Refit client for the external RAG API and a thin wrapper that implements IRagApiClient
|
||||||
|
builder.Services.AddRefitClient<IRefitRagApi>()
|
||||||
|
.ConfigureHttpClient((sp, c) =>
|
||||||
|
{
|
||||||
|
var settings = sp.GetRequiredService<Microsoft.Extensions.Options.IOptions<RagApiSettings>>().Value;
|
||||||
|
c.BaseAddress = new Uri(settings.BaseUrl.TrimEnd('/') + "/");
|
||||||
|
if (!string.IsNullOrWhiteSpace(settings.InternalApiKey))
|
||||||
|
{
|
||||||
|
c.DefaultRequestHeaders.Add("X-Internal-Api-Key", settings.InternalApiKey);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Services.AddScoped<IRagApiClient, RagApiClient>();
|
||||||
builder.Services.AddHttpClient<IMatcherAiClient, MatcherAiClient>();
|
builder.Services.AddHttpClient<IMatcherAiClient, MatcherAiClient>();
|
||||||
builder.Services.AddHttpClient<IJobTextExtractor, JobTextExtractor>();
|
builder.Services.AddHttpClient<IJobTextExtractor, JobTextExtractor>();
|
||||||
builder.Services.AddDbContext<CvMatcherDbContext>(options =>
|
builder.Services.AddDbContext<CvMatcherDbContext>(options =>
|
||||||
@@ -89,8 +108,8 @@ try
|
|||||||
logger.LogInformation("Environment: {Environment}", app.Environment.EnvironmentName);
|
logger.LogInformation("Environment: {Environment}", app.Environment.EnvironmentName);
|
||||||
|
|
||||||
// Log all environment variables and configuration settings at startup
|
// Log all environment variables and configuration settings at startup
|
||||||
// Can be controlled via appsettings: "Logging:LogEnvironmentOnStartup": true
|
// Can be controlled via appsettings: "LogEnvironmentOnStartup": true
|
||||||
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("Logging:LogEnvironmentOnStartup", defaultValue: true);
|
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("LogEnvironmentOnStartup", defaultValue: true);
|
||||||
if (logEnvironmentOnStartup)
|
if (logEnvironmentOnStartup)
|
||||||
{
|
{
|
||||||
LogEnvironmentSettings(logger, app.Configuration, app.Environment);
|
LogEnvironmentSettings(logger, app.Configuration, app.Environment);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Api.Requests;
|
using Api.Models.Requests;
|
||||||
using Api.Responses;
|
using Api.Models.Responses;
|
||||||
|
|
||||||
namespace Api.Services.Contracts;
|
namespace Api.Services.Contracts;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Api.Requests;
|
using Api.Clients.Ai.Contracts;
|
||||||
using Api.Responses;
|
using Api.Clients.Api.Contracts;
|
||||||
|
using Api.Data.Repositories.Contracts;
|
||||||
|
using Api.Models.Requests;
|
||||||
|
using Api.Models.Responses;
|
||||||
|
using Api.Models.Settings;
|
||||||
using Api.Services.Contracts;
|
using Api.Services.Contracts;
|
||||||
using Api.Settings;
|
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Api.Services;
|
namespace Api.Services;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
using Api.Models.Settings;
|
||||||
using Api.Services.Contracts;
|
using Api.Services.Contracts;
|
||||||
using Api.Settings;
|
|
||||||
using MailKit.Net.Smtp;
|
using MailKit.Net.Smtp;
|
||||||
using MailKit.Security;
|
using MailKit.Security;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using Api.Models.Settings;
|
||||||
using Api.Services.Contracts;
|
using Api.Services.Contracts;
|
||||||
using Api.Settings;
|
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Api.Services;
|
namespace Api.Services;
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
using Api.Requests;
|
|
||||||
using Api.Responses;
|
|
||||||
using Api.Services.Contracts;
|
|
||||||
using Api.Settings;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
|
|
||||||
namespace Api.Services;
|
|
||||||
|
|
||||||
public sealed class RagApiClient : IRagApiClient
|
|
||||||
{
|
|
||||||
private readonly HttpClient _http;
|
|
||||||
private readonly RagApiSettings _settings;
|
|
||||||
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);
|
|
||||||
|
|
||||||
public RagApiClient(HttpClient http, IOptions<RagApiSettings> options)
|
|
||||||
{
|
|
||||||
_http = http;
|
|
||||||
_settings = options.Value;
|
|
||||||
_http.BaseAddress = new Uri(_settings.BaseUrl.TrimEnd('/') + "/");
|
|
||||||
if (!string.IsNullOrWhiteSpace(_settings.InternalApiKey))
|
|
||||||
{
|
|
||||||
_http.DefaultRequestHeaders.Add("X-Internal-Api-Key", _settings.InternalApiKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<RagIndexResponse> IndexCvPdfAsync(IFormFile file, CancellationToken ct)
|
|
||||||
{
|
|
||||||
using var content = new MultipartFormDataContent();
|
|
||||||
await using var stream = file.OpenReadStream();
|
|
||||||
using var fileContent = new StreamContent(stream);
|
|
||||||
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
|
|
||||||
content.Add(fileContent, "file", file.FileName);
|
|
||||||
content.Add(new StringContent("cv"), "documentType");
|
|
||||||
content.Add(new StringContent(file.FileName), "title");
|
|
||||||
using var response = await _http.PostAsync("api/rag/documents", content, ct);
|
|
||||||
return await ReadJsonAsync<RagIndexResponse>(response, ct);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<RagIndexResponse> IndexJobTextAsync(string text, string? url, string? title, CancellationToken ct)
|
|
||||||
{
|
|
||||||
using var content = new MultipartFormDataContent
|
|
||||||
{
|
|
||||||
{ new StringContent(text), "text" },
|
|
||||||
{ new StringContent("job"), "documentType" },
|
|
||||||
{ new StringContent(title ?? "Job description"), "title" }
|
|
||||||
};
|
|
||||||
if (!string.IsNullOrWhiteSpace(url)) content.Add(new StringContent(url), "sourceUrl");
|
|
||||||
using var response = await _http.PostAsync("api/rag/documents", content, ct);
|
|
||||||
return await ReadJsonAsync<RagIndexResponse>(response, ct);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<RagDocumentDetails?> GetDocumentAsync(string documentId, CancellationToken ct)
|
|
||||||
{
|
|
||||||
using var response = await _http.GetAsync($"api/rag/documents/{Uri.EscapeDataString(documentId)}", ct);
|
|
||||||
if (response.StatusCode == System.Net.HttpStatusCode.NotFound) return null;
|
|
||||||
return await ReadJsonAsync<RagDocumentDetails>(response, ct);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<RagSearchResponse> SearchAsync(RagSearchRequest request, CancellationToken ct)
|
|
||||||
{
|
|
||||||
using var response = await _http.PostAsync(
|
|
||||||
"api/rag/search",
|
|
||||||
new StringContent(JsonSerializer.Serialize(request, JsonOptions), Encoding.UTF8, "application/json"),
|
|
||||||
ct);
|
|
||||||
return await ReadJsonAsync<RagSearchResponse>(response, ct);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<T> ReadJsonAsync<T>(HttpResponseMessage response, CancellationToken ct)
|
|
||||||
{
|
|
||||||
var json = await response.Content.ReadAsStringAsync(ct);
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"RAG API failed: {(int)response.StatusCode} {json}");
|
|
||||||
}
|
|
||||||
return JsonSerializer.Deserialize<T>(json, JsonOptions) ?? throw new InvalidOperationException("RAG API returned invalid JSON.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -58,7 +58,6 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogEnvironmentOnStartup": true,
|
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning",
|
"Microsoft.AspNetCore": "Warning",
|
||||||
@@ -68,6 +67,7 @@
|
|||||||
"Api": "Information"
|
"Api": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"LogEnvironmentOnStartup": true,
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"KeyVault": {
|
"KeyVault": {
|
||||||
"VaultUri": "",
|
"VaultUri": "",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
@@ -59,8 +59,8 @@
|
|||||||
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.5.1" />
|
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.5.1" />
|
||||||
<PackageReference Include="Azure.Identity" Version="1.21.0" />
|
<PackageReference Include="Azure.Identity" Version="1.21.0" />
|
||||||
<PackageReference Include="DotNetEnv" Version="3.2.0" />
|
<PackageReference Include="DotNetEnv" Version="3.2.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.7" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@@ -70,10 +70,6 @@
|
|||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.Email" Version="4.2.1" />
|
<PackageReference Include="Serilog.Sinks.Email" Version="4.2.1" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" />
|
||||||
</ItemGroup>
|
<PackageReference Include="Refit.HttpClientFactory" Version="10.1.6" />
|
||||||
<ItemGroup>
|
|
||||||
<None Update="Database/schema.sql">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
IF OBJECT_ID('dbo.RagChunks', 'U') IS NULL
|
|
||||||
BEGIN
|
|
||||||
CREATE TABLE dbo.RagChunks (
|
|
||||||
Id NVARCHAR(64) NOT NULL CONSTRAINT PK_RagChunks PRIMARY KEY,
|
|
||||||
DocumentId NVARCHAR(64) NOT NULL,
|
|
||||||
ChunkIndex INT NOT NULL,
|
|
||||||
Text NVARCHAR(MAX) NOT NULL,
|
|
||||||
Embedding VARBINARY(MAX) NOT NULL
|
|
||||||
);
|
|
||||||
END
|
|
||||||
GO
|
|
||||||
|
|
||||||
IF OBJECT_ID('dbo.RagDocuments', 'U') IS NULL
|
|
||||||
BEGIN
|
|
||||||
CREATE TABLE dbo.RagDocuments (
|
|
||||||
Id NVARCHAR(64) NOT NULL CONSTRAINT PK_RagDocuments PRIMARY KEY,
|
|
||||||
DocumentType NVARCHAR(80) NOT NULL,
|
|
||||||
Title NVARCHAR(300) NOT NULL,
|
|
||||||
SourceUrl NVARCHAR(1200) NULL,
|
|
||||||
RawText NVARCHAR(MAX) NOT NULL,
|
|
||||||
TextHash NVARCHAR(64) NOT NULL,
|
|
||||||
TypeConfidence FLOAT NOT NULL,
|
|
||||||
MetadataJson NVARCHAR(MAX) NOT NULL CONSTRAINT DF_RagDocuments_MetadataJson DEFAULT '{}',
|
|
||||||
CreatedAt DATETIME2 NOT NULL CONSTRAINT DF_RagDocuments_CreatedAt DEFAULT SYSUTCDATETIME()
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX IX_RagDocuments_TextHash ON dbo.RagDocuments(TextHash);
|
|
||||||
CREATE INDEX IX_RagDocuments_DocumentType ON dbo.RagDocuments(DocumentType);
|
|
||||||
END
|
|
||||||
GO
|
|
||||||
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = 'FK_RagChunks_RagDocuments')
|
|
||||||
BEGIN
|
|
||||||
ALTER TABLE dbo.RagChunks
|
|
||||||
ADD CONSTRAINT FK_RagChunks_RagDocuments FOREIGN KEY (DocumentId) REFERENCES dbo.RagDocuments(Id) ON DELETE CASCADE;
|
|
||||||
END
|
|
||||||
GO
|
|
||||||
|
|
||||||
IF OBJECT_ID('dbo.RagEmbeddingCache', 'U') IS NULL
|
|
||||||
BEGIN
|
|
||||||
CREATE TABLE dbo.RagEmbeddingCache (
|
|
||||||
CacheKey NVARCHAR(64) NOT NULL CONSTRAINT PK_RagEmbeddingCache PRIMARY KEY,
|
|
||||||
Model NVARCHAR(120) NOT NULL,
|
|
||||||
TextHash NVARCHAR(64) NOT NULL,
|
|
||||||
Vector VARBINARY(MAX) NOT NULL,
|
|
||||||
CreatedAt DATETIME2 NOT NULL CONSTRAINT DF_RagEmbeddingCache_CreatedAt DEFAULT SYSUTCDATETIME()
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX IX_RagEmbeddingCache_TextHash ON dbo.RagEmbeddingCache(TextHash);
|
|
||||||
END
|
|
||||||
GO
|
|
||||||
|
|
||||||
IF OBJECT_ID('dbo.RagChatCompletionCache', 'U') IS NULL
|
|
||||||
BEGIN
|
|
||||||
CREATE TABLE dbo.RagChatCompletionCache (
|
|
||||||
CacheKey NVARCHAR(64) NOT NULL CONSTRAINT PK_RagChatCompletionCache PRIMARY KEY,
|
|
||||||
Model NVARCHAR(120) NOT NULL,
|
|
||||||
Temperature DECIMAL(4,2) NOT NULL,
|
|
||||||
ResponseText NVARCHAR(MAX) NOT NULL,
|
|
||||||
CreatedAt DATETIME2 NOT NULL CONSTRAINT DF_RagChatCompletionCache_CreatedAt DEFAULT SYSUTCDATETIME()
|
|
||||||
);
|
|
||||||
END
|
|
||||||
GO
|
|
||||||
+2
-2
@@ -89,8 +89,8 @@ try
|
|||||||
logger.LogInformation("Environment: {Environment}", app.Environment.EnvironmentName);
|
logger.LogInformation("Environment: {Environment}", app.Environment.EnvironmentName);
|
||||||
|
|
||||||
// Log all environment variables and configuration settings at startup
|
// Log all environment variables and configuration settings at startup
|
||||||
// Can be controlled via appsettings: "Logging:LogEnvironmentOnStartup": true
|
// Can be controlled via appsettings: "LogEnvironmentOnStartup": true
|
||||||
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("Logging:LogEnvironmentOnStartup", defaultValue: true);
|
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("LogEnvironmentOnStartup", defaultValue: true);
|
||||||
if (logEnvironmentOnStartup)
|
if (logEnvironmentOnStartup)
|
||||||
{
|
{
|
||||||
LogEnvironmentSettings(logger, app.Configuration, app.Environment);
|
LogEnvironmentSettings(logger, app.Configuration, app.Environment);
|
||||||
|
|||||||
@@ -58,7 +58,6 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogEnvironmentOnStartup": true,
|
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning",
|
"Microsoft.AspNetCore": "Warning",
|
||||||
@@ -68,6 +67,7 @@
|
|||||||
"Api": "Information"
|
"Api": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"LogEnvironmentOnStartup": true,
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"KeyVault": {
|
"KeyVault": {
|
||||||
"VaultUri": "",
|
"VaultUri": "",
|
||||||
|
|||||||
+50
-7
@@ -6,13 +6,61 @@
|
|||||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
<RootNamespace>Api</RootNamespace>
|
<RootNamespace>Api</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\cs\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\de\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\es\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\fr\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\it\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\ja\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\ko\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Microsoft.Build.Locator.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.exe" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.exe.config" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Microsoft.IO.Redist.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Newtonsoft.Json.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\pl\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\pt-BR\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\ru\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Buffers.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Collections.Immutable.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.CommandLine.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Memory.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Numerics.Vectors.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Runtime.CompilerServices.Unsafe.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Threading.Tasks.Extensions.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\tr\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\zh-Hans\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\zh-Hant\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\cs\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\de\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\es\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\fr\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\it\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\ja\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\ko\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.Build.Locator.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.deps.json" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll.config" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.runtimeconfig.json" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Newtonsoft.Json.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\pl\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\pt-BR\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\ru\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\System.Collections.Immutable.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\System.CommandLine.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\tr\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\zh-Hans\System.CommandLine.resources.dll" />
|
||||||
|
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\zh-Hant\System.CommandLine.resources.dll" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.5.1" />
|
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.5.1" />
|
||||||
<PackageReference Include="Azure.Identity" Version="1.21.0" />
|
<PackageReference Include="Azure.Identity" Version="1.21.0" />
|
||||||
<PackageReference Include="DotNetEnv" Version="3.2.0" />
|
<PackageReference Include="DotNetEnv" Version="3.2.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.7" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@@ -23,9 +71,4 @@
|
|||||||
<PackageReference Include="Serilog.Sinks.Email" Version="4.2.1" />
|
<PackageReference Include="Serilog.Sinks.Email" Version="4.2.1" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<None Update="Database/schema.sql">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Reference in New Issue
Block a user