ChatRAG/Data/30u0ddp1.org~
2025-06-21 14:20:07 -03:00

255 lines
8.1 KiB
Org Mode

using ChatRAG.Models;
using ChatRAG.Services.Contracts;
using ChatRAG.Settings.ChatRAG.Configuration;
using Microsoft.Extensions.Options;
using System.Text;
using System.Text.Json;
using Qdrant.Client;
using Qdrant.Client.Grpc;
namespace ChatRAG.Data
{
public class QdrantProjectDataRepository : IProjectDataRepository
{
private readonly HttpClient _httpClient;
private readonly string _collectionName;
private readonly ILogger<QdrantProjectDataRepository> _logger;
private readonly QdrantClient _qdrantClient;
public QdrantProjectDataRepository(
IOptions<VectorDatabaseSettings> settings,
HttpClient httpClient,
ILogger<QdrantProjectDataRepository> logger)
{
var qdrantSettings = settings.Value.Qdrant ?? throw new ArgumentNullException("Qdrant settings not configured");
_httpClient = httpClient;
_httpClient.BaseAddress = new Uri($"http://{qdrantSettings.Host}:{qdrantSettings.Port}");
_collectionName = qdrantSettings.GroupsCollectionName;
_logger = logger;
// Inicializa o QdrantClient - use GRPC (porta 6334) para melhor performance
_qdrantClient = new QdrantClient(qdrantSettings.Host, port: 6334, https: false);
InitializeAsync().GetAwaiter().GetResult();
}
private async Task InitializeAsync()
{
try
{
var exists = await _qdrantClient.CollectionExistsAsync(_collectionName);
if (!exists)
{
await CreateProjectsCollection();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Erro ao inicializar collection de projetos no Qdrant");
}
}
public async Task<List<Project>> GetAsync()
{
try
{
var scrollRequest = new ScrollPoints
{
CollectionName = _collectionName,
Filter = new Filter(), // Filtro vazio
Limit = 1000,
WithPayload = true,
WithVectors = false
};
var result = await _qdrantClient.ScrollAsync(_collectionName, scrollRequest);
return result.Select(ConvertToProject)
.Where(p => p != null)
.ToList()!;
}
catch (Exception ex)
{
_logger.LogError(ex, "Erro ao recuperar projetos do Qdrant");
return new List<Project>();
}
}
public async Task<Project?> GetAsync(string id)
{
try
{
var points = await _qdrantClient.RetrieveAsync(
_collectionName,
new[] { PointId.Parser.Parse(id) },
withPayload: true,
withVectors: false
);
var point = points.FirstOrDefault();
return point != null ? ConvertToProject(point) : null;
}
catch (Exception ex)
{
_logger.LogError(ex, "Erro ao buscar projeto {Id} no Qdrant", id);
return null;
}
}
public async Task CreateAsync(Project newProject)
{
try
{
var id = string.IsNullOrEmpty(newProject.Id) ? Guid.NewGuid().ToString() : newProject.Id;
newProject.Id = id;
var point = new PointStruct
{
Id = PointId.Parser.Parse(id),
Vectors = new float[384], // Vector dummy para projetos
Payload =
{
["id"] = newProject.Id,
["nome"] = newProject.Nome,
["descricao"] = newProject.Descricao,
["created_at"] = DateTime.UtcNow.ToString("O"),
["entity_type"] = "project"
}
};
await _qdrantClient.UpsertAsync(_collectionName, new[] { point });
}
catch (Exception ex)
{
_logger.LogError(ex, "Erro ao criar projeto no Qdrant");
throw;
}
}
public async Task UpdateAsync(string id, Project updatedProject)
{
try
{
updatedProject.Id = id;
var point = new PointStruct
{
Id = PointId.Parser.Parse(id),
Vectors = new float[384], // Vector dummy
Payload =
{
["id"] = updatedProject.Id,
["nome"] = updatedProject.Nome,
["descricao"] = updatedProject.Descricao,
["updated_at"] = DateTime.UtcNow.ToString("O"),
["entity_type"] = "project"
}
};
await _qdrantClient.UpsertAsync(_collectionName, new[] { point });
}
catch (Exception ex)
{
_logger.LogError(ex, "Erro ao atualizar projeto {Id} no Qdrant", id);
throw;
}
}
public async Task SaveAsync(Project project)
{
try
{
if (string.IsNullOrEmpty(project.Id))
{
await CreateAsync(project);
}
else
{
var existing = await GetAsync(project.Id);
if (existing == null)
{
await CreateAsync(project);
}
else
{
await UpdateAsync(project.Id, project);
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Erro ao salvar projeto no Qdrant");
throw;
}
}
public async Task RemoveAsync(string id)
{
try
{
await _qdrantClient.DeleteAsync(
_collectionName,
new[] { PointId.Parser.Parse(id) }
);
}
catch (Exception ex)
{
_logger.LogError(ex, "Erro ao remover projeto {Id} do Qdrant", id);
throw;
}
}
private async Task CreateProjectsCollection()
{
var vectorParams = new VectorParams
{
Size = 384,
Distance = Distance.Cosine
};
await _qdrantClient.CreateCollectionAsync(_collectionName, vectorParams);
_logger.LogInformation("Collection de projetos '{CollectionName}' criada no Qdrant", _collectionName);
}
private static Project? ConvertToProject(RetrievedPoint point)
{
try
{
if (point.Payload == null) return null;
return new Project
{
Id = point.Payload.TryGetValue("id", out var idValue) ? idValue.StringValue : point.Id.ToString(),
Nome = point.Payload.TryGetValue("nome", out var nomeValue) ? nomeValue.StringValue : "",
Descricao = point.Payload.TryGetValue("descricao", out var descValue) ? descValue.StringValue : ""
};
}
catch
{
return null;
}
}
}
public class QdrantScrollResult
{
public QdrantScrollData? result { get; set; }
}
public class QdrantScrollData
{
public QdrantPoint[]? points { get; set; }
}
public class QdrantPointResult
{
public QdrantPoint? result { get; set; }
}
public class QdrantPoint
{
public string? id { get; set; }
public Dictionary<string, object>? payload { get; set; }
}
}