129 lines
4.9 KiB
C#
129 lines
4.9 KiB
C#
using PerfReviewSummarizer.Api.Models;
|
|
|
|
namespace PerfReviewSummarizer.Api.Services;
|
|
|
|
public class GeminiService : IAiService
|
|
{
|
|
private readonly IConfiguration _configuration;
|
|
private readonly HttpClient _httpClient;
|
|
private readonly ILogger<GeminiService> _logger;
|
|
|
|
public GeminiService(IConfiguration configuration, HttpClient httpClient, ILogger<GeminiService> logger)
|
|
{
|
|
_logger = logger;
|
|
_logger.LogInformation("GeminiService constructor called");
|
|
_configuration = configuration;
|
|
_httpClient = httpClient;
|
|
}
|
|
|
|
private void EnsureInitialized()
|
|
{
|
|
var apiKey = _configuration["Gemini:ApiKey"];
|
|
|
|
if (string.IsNullOrEmpty(apiKey))
|
|
{
|
|
throw new InvalidOperationException("Gemini API ключ не найден в конфигурации. Добавьте 'Gemini:ApiKey' в appsettings.json");
|
|
}
|
|
}
|
|
|
|
public async Task<string> GenerateSummaryFromCommitsAsync(List<CommitInfo> commits)
|
|
{
|
|
var commitMessages = commits.Select(c => c.Message).ToList();
|
|
return await GenerateSummaryFromCommitMessagesAsync(commitMessages);
|
|
}
|
|
|
|
public async Task<string> GenerateSummaryFromCommitMessagesAsync(List<string> commitMessages)
|
|
{
|
|
EnsureInitialized();
|
|
|
|
if (!commitMessages.Any())
|
|
{
|
|
return "Нет коммитов для анализа";
|
|
}
|
|
|
|
var commitListText = string.Join("\n", commitMessages.Select((msg, idx) => $"{idx + 1}. {msg}"));
|
|
|
|
var prompt = $@"Проанализируй следующие сообщения коммитов из Git репозитория и создай краткое, информативное резюме (summary).
|
|
|
|
Сообщения коммитов:
|
|
{commitListText}
|
|
|
|
Требования:
|
|
1. Резюме должно быть на русском языке
|
|
2. Будь лаконичен, но информативен (2-4 абзаца)
|
|
3. Выделите основные темы изменений (новые функции, исправления, рефакторинг и т.д.)
|
|
4. Укажите общую направленность разработки
|
|
5. Отметьте любые важные или критичные изменения
|
|
|
|
Формат ответа - просто текст резюме без дополнительных комментариев.";
|
|
|
|
try
|
|
{
|
|
var apiKey = _configuration["Gemini:ApiKey"];
|
|
var model = _configuration["Gemini:Model"] ?? "gemini-2.5-flash";
|
|
|
|
var request = new GeminiRequest
|
|
{
|
|
Contents = new List<GeminiContent>
|
|
{
|
|
new GeminiContent
|
|
{
|
|
Parts = new List<GeminiPart>
|
|
{
|
|
new GeminiPart { Text = prompt }
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var json = System.Text.Json.JsonSerializer.Serialize(request);
|
|
var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
|
|
|
|
var url = $"https://generativelanguage.googleapis.com/v1/models/{model}:generateContent?key={apiKey}";
|
|
var response = await _httpClient.PostAsync(url, content);
|
|
|
|
if (!response.IsSuccessStatusCode)
|
|
{
|
|
var errorContent = await response.Content.ReadAsStringAsync();
|
|
Console.WriteLine($"Gemini Error ({response.StatusCode}): {errorContent}");
|
|
throw new InvalidOperationException($"Ошибка Gemini API: {response.StatusCode} - {errorContent}");
|
|
}
|
|
|
|
var responseContent = await response.Content.ReadAsStringAsync();
|
|
var result = System.Text.Json.JsonDocument.Parse(responseContent);
|
|
|
|
var text = result.RootElement
|
|
.GetProperty("candidates")[0]
|
|
.GetProperty("content")
|
|
.GetProperty("parts")[0]
|
|
.GetProperty("text")
|
|
.GetString();
|
|
|
|
return text ?? "Ошибка при генерировании резюме";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new InvalidOperationException($"Ошибка при обращении к Gemini API: {ex.Message}", ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Вспомогательные классы для сериализации Gemini API
|
|
public class GeminiRequest
|
|
{
|
|
[System.Text.Json.Serialization.JsonPropertyName("contents")]
|
|
public List<GeminiContent> Contents { get; set; } = new();
|
|
}
|
|
|
|
public class GeminiContent
|
|
{
|
|
[System.Text.Json.Serialization.JsonPropertyName("parts")]
|
|
public List<GeminiPart> Parts { get; set; } = new();
|
|
}
|
|
|
|
public class GeminiPart
|
|
{
|
|
[System.Text.Json.Serialization.JsonPropertyName("text")]
|
|
public string Text { get; set; } = string.Empty;
|
|
}
|