feat(backend): add LLM provider abstraction, contextual ranking and explanations

Add a pluggable LLM provider with an offline template fallback, prompt builder, contextual match scoring (area/location boosts, availability), per-solution explanations and in-memory request limiting for cost control.
This commit is contained in:
Rafał Tyński
2026-10-04 02:52:45 +02:00
parent 182c26d9f8
commit 03e2d66ca4
11 changed files with 385 additions and 23 deletions
@@ -0,0 +1,42 @@
using TarninaHub.Application.Matchmaking;
namespace TarninaHub.Infrastructure.Llm;
/// <summary>
/// In-memory sliding-window request limiter (per instance) for LLM cost control.
/// </summary>
public sealed class InMemoryLlmRequestLimiter : ILlmRequestLimiter
{
private readonly int _maxPerWindow;
private readonly TimeSpan _window;
private readonly Queue<DateTimeOffset> _timestamps = new();
private readonly Lock _gate = new();
public InMemoryLlmRequestLimiter(int maxRequestsPerMinute, TimeSpan? window = null)
{
_maxPerWindow = Math.Max(1, maxRequestsPerMinute);
_window = window ?? TimeSpan.FromMinutes(1);
}
public bool TryAcquire()
{
var now = DateTimeOffset.UtcNow;
lock (_gate)
{
while (_timestamps.Count > 0 && now - _timestamps.Peek() > _window)
{
_timestamps.Dequeue();
}
if (_timestamps.Count >= _maxPerWindow)
{
return false;
}
_timestamps.Enqueue(now);
return true;
}
}
}