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.
43 lines
1.1 KiB
C#
43 lines
1.1 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|