diff --git a/CodeBase/CodeBase.csproj b/CodeBase/CodeBase.csproj
index dba28e0..b41a6e1 100644
--- a/CodeBase/CodeBase.csproj
+++ b/CodeBase/CodeBase.csproj
@@ -12,6 +12,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
+
diff --git a/CodeBase/Controllers/CodeController.cs b/CodeBase/Controllers/CodeController.cs
index deaf857..55fabb2 100644
--- a/CodeBase/Controllers/CodeController.cs
+++ b/CodeBase/Controllers/CodeController.cs
@@ -11,12 +11,6 @@ namespace CodeBase.Controllers
public class CodeController(CodeService service,
ScipProcessingService scipProcessingService) : ControllerBase
{
- [HttpPost("analyze")]
- public async Task AnalyzeRepository(string path, string name)
- {
- var chunks = await service.GetCodeChunksAsync(path, name);
- return chunks[0];
- }
[HttpPost("answer")]
public async Task GetAnswer(string question, string name)
{
@@ -25,9 +19,9 @@ namespace CodeBase.Controllers
}
[HttpPost("parser")]
- public async Task ParserProject(string path, string name, string lang)
+ public async Task ParserProject(string path, string name, Language language)
{
- await scipProcessingService.ProcessAndSaveProjectAsync(path, lang, name);
+ await scipProcessingService.ProcessAndSaveProjectAsync(path, language.ToString(), name);
return "Проект добавлен в базу";
}
}
diff --git a/CodeBase/Models/Enums.cs b/CodeBase/Models/Enums.cs
new file mode 100644
index 0000000..72f111f
--- /dev/null
+++ b/CodeBase/Models/Enums.cs
@@ -0,0 +1,14 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+
+namespace CodeBase.Models
+{
+ [JsonConverter(typeof(StringEnumConverter))]
+ public enum Language
+ {
+ csharp,
+ python,
+ typescript,
+ go
+ }
+}
diff --git a/CodeBase/Models/GraphNodeContext.cs b/CodeBase/Models/GraphNodeContext.cs
deleted file mode 100644
index 6c3fa76..0000000
--- a/CodeBase/Models/GraphNodeContext.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace CodeBase.Models
-{
- public class GraphNodeContext
- {
- public string MethodName { get; set; }
- public string FilePath { get; set; }
- public string Content { get; set; }
-
- // Графовые связи, которые мы вытащим из Neo4j
-
- // Кого вызывает этот метод (и какие классы/енумы использует)
- public List OutgoingDependencies { get; set; } = new();
-
- // Кто вызывает этот метод (кто от него зависит)
- public List IncomingDependencies { get; set; } = new();
- }
-}
diff --git a/CodeBase/Program.cs b/CodeBase/Program.cs
index f4a37c4..3c9ca29 100644
--- a/CodeBase/Program.cs
+++ b/CodeBase/Program.cs
@@ -4,6 +4,7 @@ using CodeBase.Repositories;
using CodeBase.Services;
using Microsoft.Build.Locator;
using Neo4j.Driver;
+using System.Text.Json.Serialization;
if (!MSBuildLocator.IsRegistered)
{
@@ -28,12 +29,14 @@ builder.Services.AddTransient();
builder.Services.AddTransient();
builder.Services.AddTransient();
builder.Services.AddScoped();
-builder.Services.AddTransient();
builder.Services.AddTransient();
-builder.Services.AddTransient();
builder.Services.AddTransient();
-builder.Services.AddControllers();
+builder.Services.AddControllers().AddJsonOptions(options =>
+{
+ // Добавляем конвертер строковых енумов глобально
+ options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
+}); ;
builder.Services.AddSwaggerGen();
var app = builder.Build();
@@ -58,12 +61,4 @@ app.UseAuthorization();
app.MapControllers();
-using (var scope = app.Services.CreateScope())
-{
- var graphRepo = scope.ServiceProvider.GetRequiredService();
- Console.WriteLine("Проверяем и создаем векторный индекс в Neo4j...");
- await graphRepo.InitializeDbAsync();
- Console.WriteLine("Индекс готов!");
-}
-
app.Run();
diff --git a/CodeBase/Repositories/GraphRepository.cs b/CodeBase/Repositories/GraphRepository.cs
deleted file mode 100644
index b736855..0000000
--- a/CodeBase/Repositories/GraphRepository.cs
+++ /dev/null
@@ -1,139 +0,0 @@
-using CodeBase.Models;
-using Neo4j.Driver;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
-public class GraphRepository
-{
- private readonly IDriver _driver;
-
- public GraphRepository(IDriver driver)
- {
- _driver = driver;
- }
-
- // ==========================================
- // 0. ИНИЦИАЛИЗАЦИЯ (Создаем пространство для векторов)
- // ==========================================
- public async Task InitializeDbAsync()
- {
- await using var session = _driver.AsyncSession();
-
- await session.ExecuteWriteAsync(async tx =>
- {
- // Говорим базе: "Создай индекс для поиска по сходству, если его еще нет.
- // Размер вектора 768 (GraphCodeBERT), алгоритм - косинусное расстояние"
- await tx.RunAsync(@"
- CREATE VECTOR INDEX code_vectors IF NOT EXISTS
- FOR (c:CodeChunk) ON (c.vector)
- OPTIONS { indexConfig: {
- `vector.dimensions`: 768,
- `vector.similarity_function`: 'cosine'
- }}"
- );
- });
- }
-
- // ==========================================
- // 1. СОХРАНЕНИЕ УЗЛОВ И ВЕКТОРОВ
- // ==========================================
- public async Task SaveChunksAsync(string projectName, List chunks)
- {
- await using var session = _driver.AsyncSession();
-
- // 1. Делаем данные "безопасными" для базы
- var parameters = chunks.Where(c => c.Embedding != null).Select(chunk => new
- {
- id = Guid.NewGuid().ToString(),
- projectName = projectName,
- filePath = chunk.FilePath,
- methodName = chunk.EntityName,
- content = chunk.Content,
- vector = chunk.Embedding,
- // Защита от null и пустых строк (база их не переварит в цикле FOREACH)
- outgoingCalls = chunk.OutgoingCalls != null
- ? chunk.OutgoingCalls.Where(x => !string.IsNullOrWhiteSpace(x)).ToList()
- : new List()
- }).ToList();
-
- await session.ExecuteWriteAsync(async tx =>
- {
- await tx.RunAsync(@"
- UNWIND $batch AS chunk
-
- // Создаем или обновляем основной метод
- MERGE (c:CodeChunk { methodName: chunk.methodName })
- SET c.id = chunk.id,
- c.projectName = chunk.projectName,
- c.filePath = chunk.filePath,
- c.content = chunk.content,
- c.vector = chunk.vector
-
- // Рисуем связи только для валидных вызовов
- FOREACH (calledMethod IN chunk.outgoingCalls |
- MERGE (target:CodeChunk { methodName: calledMethod })
- MERGE (c)-[:CALLS]->(target)
- )
- ", new { batch = parameters });
- });
- }
-
- // ==========================================
- // 2. ПОИСК (Пока только по вектору, связи добавим позже)
- // ==========================================
- public async Task> SearchAsync(string projectName, float[] queryVector, int topK = 15)
- {
- await using var session = _driver.AsyncSession();
-
- return await session.ExecuteReadAsync(async tx =>
- {
- var cursor = await tx.RunAsync(@"
- // 1. Ищем самые подходящие узлы по векторному сходству
- CALL db.index.vector.queryNodes('code_vectors', $topK, $queryVector)
- YIELD node AS c, score
- WHERE c.projectName = $projectName
-
- // 2. Ищем стрелочки ВНИЗ (Кого вызывает этот метод?)
- // OPTIONAL MATCH гарантирует, что мы не потеряем узел, если связей нет
- OPTIONAL MATCH (c)-[:CALLS]->(out:CodeChunk)
- // Собираем имена вызываемых методов в массив
- WITH c, score, collect(DISTINCT out.methodName) AS outgoingDependencies
-
- // 3. Ищем стрелочки ВВЕРХ (Кто вызывает этот метод?)
- OPTIONAL MATCH (in:CodeChunk)-[:CALLS]->(c)
- WITH c, score, outgoingDependencies, collect(DISTINCT in.methodName) AS incomingDependencies
-
- // 4. Возвращаем готовую структуру для C#
- RETURN
- c.methodName AS methodName,
- c.filePath AS filePath,
- c.content AS content,
- outgoingDependencies,
- incomingDependencies,
- score
- ORDER BY score DESC
- ", new { topK, queryVector, projectName });
-
- var results = new List();
-
- while (await cursor.FetchAsync())
- {
- var record = cursor.Current;
- results.Add(new GraphNodeContext
- {
- MethodName = record["methodName"].As(),
- FilePath = record["filePath"].As(),
- Content = record["content"].As(),
-
- // Драйвер Neo4j возвращает массивы как IList