Files
CodeAnalizer/CodeBase/Services/CodeService.cs

103 lines
3.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using CodeBase.Models;
using CodeBase.Warehouse;
namespace CodeBase.Services
{
public class CodeService(ChunkService service,
ChunkWarehouse warehouse,
VectorizationService vectorizationService,
LlmService llmService)
{
public async Task<List<CodeChunk>> GetCodeChunksAsync(string path, string name)
{
if (!Path.Exists(path))
{
throw new Exception("Путь не найден");
}
var allChunks = new List<CodeChunk>();
// Находим все .cs файлы во всех вложенных папках
var csFiles = Directory.GetFiles(path, "*.cs", SearchOption.AllDirectories);
foreach (var filePath in csFiles)
{
var content = File.ReadAllText(filePath);
// Парсим каждый файл отдельно, сохраняя его оригинальный путь
var fileChunks = service.ChunkCSharpFile(filePath, content);
allChunks.AddRange(fileChunks);
}
var chunks = await vectorizationService.EnrichChunksWithVectorsAsync(allChunks);
warehouse.UpsertDictionary(name, allChunks);
return chunks;
}
public async Task<string> GetAnswerAsync(string name, string question)
{
var query = await vectorizationService.GetVectorAsync(question);
var answerVectors = Search(query, name, 15);
var answer = await llmService.AskQuestionAsync(question, answerVectors.Select(s => s.Chunk).ToList());
return answer;
}
// Главный метод поиска
public List<(CodeChunk Chunk, float Score)> Search(
float[] queryVector,
string name,
int topK = 3) // Возвращаем топ-3 результата
{
var memoryBase = warehouse.GetChunks(name);
var results = new List<(CodeChunk, float)>();
foreach (var chunk in memoryBase)
{
if (chunk.Vector == null || chunk.Vector.Length == 0)
continue;
// Считаем близость вектора вопроса к вектору кода
float similarity = CalculateCosineSimilarity(queryVector, chunk.Vector);
results.Add((chunk, similarity));
}
// Сортируем по убыванию сходства (чем ближе к 1, тем лучше)
return results
.OrderByDescending(x => x.Item2)
.Take(topK)
.ToList();
}
// Математика косинусного сходства
private float CalculateCosineSimilarity(float[] vectorA, float[] vectorB)
{
if (vectorA.Length != vectorB.Length)
throw new ArgumentException("Векторы должны быть одинаковой длины (например, 768).");
float dotProduct = 0;
float magnitudeA = 0;
float magnitudeB = 0;
for (int i = 0; i < vectorA.Length; i++)
{
dotProduct += vectorA[i] * vectorB[i];
magnitudeA += vectorA[i] * vectorA[i];
magnitudeB += vectorB[i] * vectorB[i];
}
// Защита от деления на ноль
if (magnitudeA == 0 || magnitudeB == 0)
return 0;
return (float)(dotProduct / (Math.Sqrt(magnitudeA) * Math.Sqrt(magnitudeB)));
}
}
}