Changes
This commit is contained in:
+2
-2
@@ -210,8 +210,8 @@ try
|
||||
logger.LogInformation("Environment: {Environment}", app.Environment.EnvironmentName);
|
||||
|
||||
// Log all environment variables and configuration settings at startup
|
||||
// Can be controlled via appsettings: "Logging:LogEnvironmentOnStartup": true
|
||||
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("Logging:LogEnvironmentOnStartup", defaultValue: true);
|
||||
// Can be controlled via appsettings: "LogEnvironmentOnStartup": true
|
||||
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("LogEnvironmentOnStartup", defaultValue: true);
|
||||
if (logEnvironmentOnStartup)
|
||||
{
|
||||
LogEnvironmentSettings(logger, app.Configuration, app.Environment);
|
||||
|
||||
@@ -36,9 +36,9 @@
|
||||
"Microsoft.AspNetCore.Routing": "Warning",
|
||||
"System.Net.Http.HttpClient": "Warning",
|
||||
"Api": "Debug"
|
||||
}
|
||||
},
|
||||
"LogEnvironmentOnStartup": true
|
||||
},
|
||||
"LogEnvironmentOnStartup": true,
|
||||
"KeyVault": {
|
||||
"VaultUri": "",
|
||||
"Enabled": false
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
]
|
||||
},
|
||||
"Logging": {
|
||||
"LogEnvironmentOnStartup": true,
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
@@ -68,6 +67,7 @@
|
||||
"Api": "Information"
|
||||
}
|
||||
},
|
||||
"LogEnvironmentOnStartup": true,
|
||||
"AllowedHosts": "*",
|
||||
"KeyVault": {
|
||||
"VaultUri": "",
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace Api.Services.Contracts;
|
||||
namespace Api.Clients.Ai.Contracts;
|
||||
|
||||
public interface IMatcherAiClient
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Api.Services;
|
||||
namespace Api.Clients.Ai;
|
||||
|
||||
public static class HashHelper
|
||||
{
|
||||
+4
-3
@@ -2,11 +2,12 @@ using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Api.Services.Contracts;
|
||||
using Api.Settings;
|
||||
using Api.Clients.Ai.Contracts;
|
||||
using Api.Data.Repositories.Contracts;
|
||||
using Api.Models.Settings;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Api.Services;
|
||||
namespace Api.Clients.Ai;
|
||||
|
||||
public sealed class MatcherAiClient : IMatcherAiClient
|
||||
{
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
using Api.Requests;
|
||||
using Api.Responses;
|
||||
using Api.Models.Requests;
|
||||
using Api.Models.Responses;
|
||||
|
||||
namespace Api.Services.Contracts;
|
||||
namespace Api.Clients.Api.Contracts;
|
||||
|
||||
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 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
|
||||
{
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
using System.Text.Json;
|
||||
using Api.Data;
|
||||
using Api.Data.Entities;
|
||||
using Api.Responses;
|
||||
using Api.Services.Contracts;
|
||||
using Api.Data.Repositories.Contracts;
|
||||
using Api.Models.Responses;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Api.Services;
|
||||
namespace Api.Data.Repositories;
|
||||
|
||||
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
|
||||
{
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace Api.Requests
|
||||
namespace Api.Models.Requests
|
||||
{
|
||||
public sealed class MatchJobRequest
|
||||
{
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace Api.Requests
|
||||
namespace Api.Models.Requests
|
||||
{
|
||||
public sealed class RagSearchRequest
|
||||
{
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace Api.Responses
|
||||
namespace Api.Models.Responses
|
||||
{
|
||||
public sealed class CvUploadResponse
|
||||
{
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace Api.Responses
|
||||
namespace Api.Models.Responses
|
||||
{
|
||||
public sealed class FindJobsResponse
|
||||
{
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace Api.Responses
|
||||
namespace Api.Models.Responses
|
||||
{
|
||||
public sealed class JobMatchResponse
|
||||
{
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace Api.Responses
|
||||
namespace Api.Models.Responses
|
||||
{
|
||||
public sealed class RagIndexResponse
|
||||
{
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace Api.Responses
|
||||
namespace Api.Models.Responses
|
||||
{
|
||||
public sealed class RagSearchResponse
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Api.Settings;
|
||||
namespace Api.Models.Settings;
|
||||
|
||||
public sealed class RagApiSettings
|
||||
{
|
||||
@@ -2,11 +2,18 @@ using Azure.Identity;
|
||||
using Api.Data;
|
||||
using Api.Services;
|
||||
using Api.Services.Contracts;
|
||||
using Api.Settings;
|
||||
using Microsoft.AspNetCore.Diagnostics;
|
||||
using Serilog;
|
||||
using System.Reflection;
|
||||
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();
|
||||
|
||||
@@ -68,7 +75,19 @@ try
|
||||
builder.Services.Configure<MatcherSettings>(builder.Configuration.GetSection("Matcher"));
|
||||
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<IJobTextExtractor, JobTextExtractor>();
|
||||
builder.Services.AddDbContext<CvMatcherDbContext>(options =>
|
||||
@@ -89,8 +108,8 @@ try
|
||||
logger.LogInformation("Environment: {Environment}", app.Environment.EnvironmentName);
|
||||
|
||||
// Log all environment variables and configuration settings at startup
|
||||
// Can be controlled via appsettings: "Logging:LogEnvironmentOnStartup": true
|
||||
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("Logging:LogEnvironmentOnStartup", defaultValue: true);
|
||||
// Can be controlled via appsettings: "LogEnvironmentOnStartup": true
|
||||
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("LogEnvironmentOnStartup", defaultValue: true);
|
||||
if (logEnvironmentOnStartup)
|
||||
{
|
||||
LogEnvironmentSettings(logger, app.Configuration, app.Environment);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Api.Requests;
|
||||
using Api.Responses;
|
||||
using Api.Models.Requests;
|
||||
using Api.Models.Responses;
|
||||
|
||||
namespace Api.Services.Contracts;
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using System.Text.Json;
|
||||
using Api.Requests;
|
||||
using Api.Responses;
|
||||
using Api.Clients.Ai.Contracts;
|
||||
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.Settings;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Api.Services;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Api.Models.Settings;
|
||||
using Api.Services.Contracts;
|
||||
using Api.Settings;
|
||||
using MailKit.Net.Smtp;
|
||||
using MailKit.Security;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using Api.Models.Settings;
|
||||
using Api.Services.Contracts;
|
||||
using Api.Settings;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
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": {
|
||||
"LogEnvironmentOnStartup": true,
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
@@ -68,6 +67,7 @@
|
||||
"Api": "Information"
|
||||
}
|
||||
},
|
||||
"LogEnvironmentOnStartup": true,
|
||||
"AllowedHosts": "*",
|
||||
"KeyVault": {
|
||||
"VaultUri": "",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -59,8 +59,8 @@
|
||||
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.5.1" />
|
||||
<PackageReference Include="Azure.Identity" Version="1.21.0" />
|
||||
<PackageReference Include="DotNetEnv" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@@ -70,10 +70,6 @@
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Email" Version="4.2.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Database/schema.sql">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<PackageReference Include="Refit.HttpClientFactory" Version="10.1.6" />
|
||||
</ItemGroup>
|
||||
</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);
|
||||
|
||||
// Log all environment variables and configuration settings at startup
|
||||
// Can be controlled via appsettings: "Logging:LogEnvironmentOnStartup": true
|
||||
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("Logging:LogEnvironmentOnStartup", defaultValue: true);
|
||||
// Can be controlled via appsettings: "LogEnvironmentOnStartup": true
|
||||
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("LogEnvironmentOnStartup", defaultValue: true);
|
||||
if (logEnvironmentOnStartup)
|
||||
{
|
||||
LogEnvironmentSettings(logger, app.Configuration, app.Environment);
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
]
|
||||
},
|
||||
"Logging": {
|
||||
"LogEnvironmentOnStartup": true,
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
@@ -68,6 +67,7 @@
|
||||
"Api": "Information"
|
||||
}
|
||||
},
|
||||
"LogEnvironmentOnStartup": true,
|
||||
"AllowedHosts": "*",
|
||||
"KeyVault": {
|
||||
"VaultUri": "",
|
||||
|
||||
+50
-7
@@ -6,13 +6,61 @@
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<RootNamespace>Api</RootNamespace>
|
||||
</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>
|
||||
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.5.1" />
|
||||
<PackageReference Include="Azure.Identity" Version="1.21.0" />
|
||||
<PackageReference Include="DotNetEnv" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@@ -23,9 +71,4 @@
|
||||
<PackageReference Include="Serilog.Sinks.Email" Version="4.2.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Database/schema.sql">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user