Files
ZakirovT 057e1f526b init
2026-01-22 00:45:41 +03:00

144 lines
5.2 KiB
C#

using OpenAI.Chat;
using OpenAI.Models;
using PerfReviewSummarizer.Api.Models;
namespace PerfReviewSummarizer.Api.Services;
public class OpenAiService : IOpenAiService, IAiService
{
private readonly IConfiguration _configuration;
private readonly HttpClient _httpClient;
private bool _initialized = false;
public OpenAiService(IConfiguration configuration, HttpClient httpClient)
{
_configuration = configuration;
_httpClient = httpClient;
}
private void EnsureInitialized()
{
if (_initialized) return;
var apiKey = _configuration["OpenAI:ApiKey"];
if (string.IsNullOrEmpty(apiKey))
{
throw new InvalidOperationException("OpenAI API ключ не найден в конфигурации. Добавьте 'OpenAI:ApiKey' в appsettings.json");
}
_httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", apiKey);
_initialized = true;
}
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 request = new ChatCompletionRequest
{
Model = "gpt-3.5-turbo",
Messages = new List<ChatMessage>
{
new ChatMessage
{
Role = ChatMessageRole.User,
Content = prompt
}
},
Temperature = 0.7,
MaxTokens = 1000
};
var json = System.Text.Json.JsonSerializer.Serialize(request);
var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync("https://api.openai.com/v1/chat/completions", content);
if (!response.IsSuccessStatusCode)
{
var errorContent = await response.Content.ReadAsStringAsync();
Console.WriteLine($"OpenAI Error ({response.StatusCode}): {errorContent}");
throw new InvalidOperationException($"Ошибка OpenAI API: {response.StatusCode} - {errorContent}");
}
var responseContent = await response.Content.ReadAsStringAsync();
var result = System.Text.Json.JsonDocument.Parse(responseContent);
var message = result.RootElement
.GetProperty("choices")[0]
.GetProperty("message")
.GetProperty("content")
.GetString();
return message ?? "Ошибка при генерировании резюме";
}
catch (Exception ex)
{
throw new InvalidOperationException($"Ошибка при обращении к OpenAI API: {ex.Message}", ex);
}
}
}
// Вспомогательные классы для сериализации
public class ChatCompletionRequest
{
[System.Text.Json.Serialization.JsonPropertyName("model")]
public string Model { get; set; } = "gpt-3.5-turbo";
[System.Text.Json.Serialization.JsonPropertyName("messages")]
public List<ChatMessage> Messages { get; set; } = new();
[System.Text.Json.Serialization.JsonPropertyName("temperature")]
public double Temperature { get; set; } = 0.7;
[System.Text.Json.Serialization.JsonPropertyName("max_tokens")]
public int MaxTokens { get; set; } = 1000;
}
public class ChatMessage
{
[System.Text.Json.Serialization.JsonPropertyName("role")]
public string Role { get; set; } = "user";
[System.Text.Json.Serialization.JsonPropertyName("content")]
public string Content { get; set; } = string.Empty;
}
public static class ChatMessageRole
{
public const string User = "user";
public const string Assistant = "assistant";
public const string System = "system";
}