feat(rag): implement KM-RAG retrieval read-path, endpoints, query handlers, global Q&A panel, and unit tests
This commit is contained in:
@@ -12,6 +12,7 @@ public interface IKnowledgeService
|
||||
Task<Result<List<RelevantContext>>> GetRelevantContextAsync(string query, string tenantId, CancellationToken cancellationToken = default);
|
||||
Task<Result<GroundednessResult>> VerifyGroundednessAsync(string answer, string context, string tenantId, CancellationToken cancellationToken = default);
|
||||
Task<Result<List<SemanticSearchResultDto>>> SearchLibrarySemanticallyAsync(string queryText, string tenantId, int limit, CancellationToken cancellationToken = default);
|
||||
Task<Result<GroundedResponseDto>> AskQuestionAsync(string question, string tenantId, Guid? ebookId = null, int limit = 5, CancellationToken cancellationToken = default);
|
||||
Task<Result> ClearCacheAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NexusReader.Application.DTOs.AI;
|
||||
|
||||
public class GroundedResponseDto
|
||||
{
|
||||
public string Answer { get; set; } = string.Empty;
|
||||
public List<CitationDto> Citations { get; set; } = new();
|
||||
}
|
||||
|
||||
public class CitationDto
|
||||
{
|
||||
public string CitationId { get; set; } = string.Empty; // e.g., chunk hash/ID
|
||||
public string Snippet { get; set; } = string.Empty; // Verified text snippet from context
|
||||
public string SourceBook { get; set; } = string.Empty; // Book title or description
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FluentResults;
|
||||
using MediatR;
|
||||
using NexusReader.Application.Abstractions.Services;
|
||||
using NexusReader.Application.DTOs.AI;
|
||||
|
||||
namespace NexusReader.Application.Queries.Library;
|
||||
|
||||
public record AskLibraryQuestionQuery(string Question, string TenantId, Guid? EbookId = null, int Limit = 5)
|
||||
: IRequest<Result<GroundedResponseDto>>;
|
||||
|
||||
public class AskLibraryQuestionQueryHandler : IRequestHandler<AskLibraryQuestionQuery, Result<GroundedResponseDto>>
|
||||
{
|
||||
private readonly IKnowledgeService _knowledgeService;
|
||||
|
||||
public AskLibraryQuestionQueryHandler(IKnowledgeService knowledgeService)
|
||||
{
|
||||
_knowledgeService = knowledgeService;
|
||||
}
|
||||
|
||||
public async Task<Result<GroundedResponseDto>> Handle(AskLibraryQuestionQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(request.Question))
|
||||
{
|
||||
return Result.Fail("Question cannot be empty.");
|
||||
}
|
||||
|
||||
return await _knowledgeService.AskQuestionAsync(
|
||||
request.Question,
|
||||
request.TenantId,
|
||||
request.EbookId,
|
||||
request.Limit,
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user