More work

This commit is contained in:
Nickk888 committed 2026-10-12 01:14:13 +02:00
1 parent c06f06c6ce
commit 8b476e6939
20 files changed
+871 -22

No files matched your search

+19
View File
@@ -0,0 +1,19 @@
using System.Net.Http.Headers;
using PaperlessAI.Models.LMStudio;
namespace PaperlessAI.Services;
public class ApiService(HttpClient client)
{
public async Task<HttpResponseMessage> Post<T>(string? requestUri, T model, CancellationToken cancellationToken = new CancellationToken())
{
var response = await client.PostAsJsonAsync(requestUri, model, cancellationToken);
return response;
}
public async Task<HttpResponseMessage> Get(string? requestUri, CancellationToken cancellationToken = new CancellationToken())
{
var response = await client.GetAsync(requestUri, cancellationToken);
return response;
}
}
+67 -8
View File
@@ -1,36 +1,46 @@
using System;
using System.Diagnostics.CodeAnalysis;
using PaperlessAI.Context;
using PaperlessAI.Enums;
using PaperlessAI.Models;
using PaperlessAI.Models.LMStudio;
using PaperlessAI.Repositories;
namespace PaperlessAI.Services;
public class DocumentProcessingService(ILogger<DocumentProcessingService> logger)
public class DocumentProcessingService(IServiceScopeFactory scopeFactory, ILogger<DocumentProcessingService> logger)
{
private Queue<PaperlessDocument> paperlessDocumentsQueue = new Queue<PaperlessDocument>();
private bool isWorking = false;
public void Enqueue(List<PaperlessDocument> paperlessDocuments)
public async Task Enqueue(List<PaperlessDocument> paperlessDocuments)
{
if(paperlessDocumentsQueue.Count != 0)
return;
foreach(var doc in paperlessDocuments)
{
Enqueue(doc);
await Enqueue(doc);
}
}
public void Enqueue(PaperlessDocument paperlessDocument)
public async Task Enqueue(PaperlessDocument paperlessDocument)
{
if(paperlessDocumentsQueue.Contains(paperlessDocument, new PaperlessDocumentSameDocument()))
return;
await using var scope = scopeFactory.CreateAsyncScope();
var repository = scope.ServiceProvider.GetRequiredService<PaperlessDocumentRepository>();
paperlessDocumentsQueue.Enqueue(paperlessDocument);
paperlessDocument.SetDocumentState(EDocumentState.Enqueued);
await repository.Update(paperlessDocument);
logger.LogInformation($"Enqueued document: {paperlessDocument}");
}
public void Process()
public async Task Process()
{
if(isWorking)
return;
@@ -41,16 +51,65 @@ public class DocumentProcessingService(ILogger<DocumentProcessingService> logger
if(paperlessDocumentsQueue.TryDequeue(out PaperlessDocument? docToProcess))
{
logger.LogInformation($"Dequeued: {docToProcess}");
ProcessDocument(docToProcess);
var llmResponse = await ProcessDocument(docToProcess);
await UpdateDocumentData(docToProcess, llmResponse);
logger.LogInformation($"Document processed: {docToProcess} | Success: {llmResponse?.Success ?? false}");
}
if(paperlessDocumentsQueue.Count == 0)
{
await UnloadModel();
}
}
private void ProcessDocument(PaperlessDocument docToProcess)
private async Task UpdateDocumentData(PaperlessDocument document, LmStudioLlmResponse llmResponse)
{
logger.LogInformation($"Processing: {docToProcess}");
await using var scope = scopeFactory.CreateAsyncScope();
var repository = scope.ServiceProvider.GetRequiredService<PaperlessDocumentRepository>();
var isSameId = document.DocumentId == llmResponse?.DocumentId;
if(!llmResponse!.IsValid || !isSameId)
{
document.SetDocumentState(EDocumentState.Failed);
document.SetLastLlmMessage("Invalid LLM Response.");
}
else
{
document.SetDocumentState(llmResponse.Success ? EDocumentState.Success : EDocumentState.Failed);
document.SetLastLlmMessage(llmResponse.Message);
}
await repository.Update(document);
}
private async Task UnloadModel()
{
await using var scope = scopeFactory.CreateAsyncScope();
var agentService = scope.ServiceProvider.GetRequiredService<LLMAgentService>();
logger.LogInformation($"Unloading Model");
isWorking = true;
await agentService.UnloadModel();
isWorking = false;
}
private async Task<LmStudioLlmResponse> ProcessDocument(PaperlessDocument docToProcess)
{
await using var scope = scopeFactory.CreateAsyncScope();
var agentService = scope.ServiceProvider.GetRequiredService<LLMAgentService>();
var repository = scope.ServiceProvider.GetRequiredService<PaperlessDocumentRepository>();
isWorking = true;
logger.LogInformation($"Processing: {docToProcess}");
docToProcess.DocumentState = EDocumentState.Started;
await repository.Update(docToProcess);
var llmResponse = await agentService.ProcessDocumentWithAI(docToProcess);
isWorking = false;
return llmResponse ?? new LmStudioLlmResponse();
}
}
+56 -3
View File
@@ -1,8 +1,61 @@
using System;
using Newtonsoft.Json;
using PaperlessAI.Models;
using PaperlessAI.Models.LMStudio;
namespace PaperlessAI.Services;
public class LLMAgentService
public class LLMAgentService(ApiService apiService, Configuration config, ILogger<LLMAgentService> logger)
{
public async Task<LmStudioLlmResponse?> ProcessDocumentWithAI(PaperlessDocument docToProcess)
{
// Prompt
var prompt = config.Prompt.Replace("{document_id}", docToProcess.DocumentId.ToString());
// Request
var content = new LmStudioChatRequest() {
Model = config.Model,
Input = prompt,
Integrations = config.IntegrationsList,
SystemPrompt = config.SystemPrompt,
ContextLength = config.ContextLength,
MaxOutputTokens = config.max_output_tokens,
Temperature = config.Temperature,
TopP = config.TopP,
Reasoning = config.Reasoning
};
var response = await apiService.Post("chat", content);
// Response
var contentMessage = await response.Content.ReadAsStringAsync();
logger.LogDebug(contentMessage);
var chatResponseJson = JsonConvert.DeserializeObject<LmStudioChatResponse>(contentMessage);
var messages = chatResponseJson?.GetOutputsByResponseType("message");
if(messages?.Count > 1)
{
logger.LogError($"To many messages received! Count: {messages?.Count}");
messages?.ForEach(x => logger.LogError(x.ToString()));
return null;
}
if(messages?.Count == 0)
{
logger.LogError($"No messages received!");
return null;
}
var message = messages!.FirstOrDefault();
var llmResponse = JsonConvert.DeserializeObject<LmStudioLlmResponse>(message!.Content ?? string.Empty);
logger.LogInformation(llmResponse?.ToString());
return llmResponse;
}
internal async Task UnloadModel()
{
var content = new LmStudioUnloadModel() {
InstanceId = config.Model
};
var response = await apiService.Post("models/unload", content);
var message = await response.Content.ReadAsStringAsync();
logger.LogInformation(message);
}
}