From 5a716e28a8394ef37c25a4dacf147661810656f3 Mon Sep 17 00:00:00 2001 From: Justin Yoo Date: Sun, 18 Aug 2024 12:33:57 +0900 Subject: [PATCH 1/7] Update GHA workflow --- .github/workflows/azure-dev.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/azure-dev.yml b/.github/workflows/azure-dev.yml index 45dc663d..569c0c35 100644 --- a/.github/workflows/azure-dev.yml +++ b/.github/workflows/azure-dev.yml @@ -24,6 +24,8 @@ jobs: AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} AZURE_OPENAI_KEYS: ${{ secrets.AZURE_OPENAI_KEYS }} + AZURE_KEYVAULT_URI: ${{ secrets.AZURE_KEYVAULT_URI }} + AZURE_KEYVAULT_SECRET_NAME: ${{ vars.AZURE_KEYVAULT_SECRET_NAME }} steps: - name: Checkout @@ -50,7 +52,9 @@ jobs: shell: pwsh run: | $appsettings = Get-Content -Path "./src/AzureOpenAIProxy.ApiApp/appsettings.json" -Raw | ConvertFrom-Json - $appsettings.Azure.OpenAI.Instances = '${{ env.AZURE_OPENAI_KEYS }}' | ConvertFrom-Json + $appsettings.Azure.OpenAI.Instances = @() + $appsettings.Azure.KeyVault.VaultUri = "${{ env.AZURE_KEYVAULT_URI }}" + $appsettings.Azure.KeyVault.SecretName = "${{ env.AZURE_KEYVAULT_SECRET_NAME }}" $appsettings | ConvertTo-Json -Depth 100 | Set-Content -Path "./src/AzureOpenAIProxy.ApiApp/appsettings.json" -Encoding UTF8 -Force - name: Restore NuGet packages From e8e5c0a723bc3f92c5f98da7b2d5fd3b488a946d Mon Sep 17 00:00:00 2001 From: yj_chun Date: Sun, 6 Oct 2024 17:52:03 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20EventRepository,=20PlaygroundServic?= =?UTF-8?q?e=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20PlaygroundEndpoint=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Directory.Build.props | 58 ++++++++--------- .../Endpoints/PlaygroundEndpoints.cs | 29 ++++++++- src/AzureOpenAIProxy.ApiApp/Program.cs | 6 ++ .../Repositories/EventRepository.cs | 65 +++++++++++++++++++ .../Services/PlaygroundService.cs | 62 ++++++++++++++++++ 5 files changed, 188 insertions(+), 32 deletions(-) create mode 100644 src/AzureOpenAIProxy.ApiApp/Repositories/EventRepository.cs create mode 100644 src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs diff --git a/Directory.Build.props b/Directory.Build.props index 1854c7b9..79fc5503 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,29 +1,29 @@ - - - - net8.0 - latest - - enable - enable - - 8.2.1 - 2.*-* - 8.* - 8.* - 1.* - 1.* - 1.* - 6.* - 8.* - 4.* - - 6.* - 6.* - 17.* - 5.* - 4.* - 1.* - 2.* - - + + + + net8.0 + latest + + enable + enable + + 8.2.1 + 2.*-* + 8.* + 8.* + 1.* + 1.* + 1.* + 6.* + 8.* + 4.* + + 6.* + 6.* + 17.* + 5.* + 4.* + 1.* + 2.* + + diff --git a/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs b/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs index 91c01b8f..ecf81179 100644 --- a/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs +++ b/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs @@ -1,3 +1,7 @@ +using Azure; + +using AzureOpenAIProxy.ApiApp.Services; + using Microsoft.AspNetCore.Mvc; namespace AzureOpenAIProxy.ApiApp.Endpoints; @@ -44,11 +48,30 @@ public static RouteHandlerBuilder AddListEvents(this WebApplication app) public static RouteHandlerBuilder AddListDeploymentModels(this WebApplication app) { // Todo: Issue #170 https://github.com/aliencube/azure-openai-sdk-proxy/issues/170 - var builder = app.MapGet(PlaygroundEndpointUrls.DeploymentModels, ( - [FromRoute] string eventId + var builder = app.MapGet(PlaygroundEndpointUrls.DeploymentModels, async ( + [FromRoute] Guid eventId, + IPlaygroundService service, + ILoggerFactory loggerFactory ) => { - return Results.Ok(); + var logger = loggerFactory.CreateLogger(nameof(AdminEventEndpoints)); + logger.LogInformation("Received request to fetch deployment models list"); + + try + { + var deploymentModelsList = await service.GetDeploymentModels(eventId); + return Results.Ok(deploymentModelsList); + } + catch (RequestFailedException ex) + { + logger.LogError(ex, "Failed to fetch deployment models list"); + return Results.Problem(ex.Message, statusCode: StatusCodes.Status500InternalServerError); + } + catch (Exception ex) + { + logger.LogError(ex, "Failed to fetch deployment models list"); + return Results.Problem(ex.Message, statusCode: StatusCodes.Status500InternalServerError); + } }) .Produces>(statusCode: StatusCodes.Status200OK, contentType: "application/json") .Produces(statusCode: StatusCodes.Status401Unauthorized) diff --git a/src/AzureOpenAIProxy.ApiApp/Program.cs b/src/AzureOpenAIProxy.ApiApp/Program.cs index f35b83ee..969e9caa 100644 --- a/src/AzureOpenAIProxy.ApiApp/Program.cs +++ b/src/AzureOpenAIProxy.ApiApp/Program.cs @@ -28,6 +28,12 @@ // Add admin repositories builder.Services.AddAdminEventRepository(); +// Add playground services +builder.Services.AddPlaygroundService(); + +// Add playground repositories +builder.Services.AddEventRepository(); + var app = builder.Build(); app.MapDefaultEndpoints(); diff --git a/src/AzureOpenAIProxy.ApiApp/Repositories/EventRepository.cs b/src/AzureOpenAIProxy.ApiApp/Repositories/EventRepository.cs new file mode 100644 index 00000000..ecaf832e --- /dev/null +++ b/src/AzureOpenAIProxy.ApiApp/Repositories/EventRepository.cs @@ -0,0 +1,65 @@ +using Azure.Data.Tables; + +using AzureOpenAIProxy.ApiApp.Configurations; + +namespace AzureOpenAIProxy.ApiApp.Repositories; + +/// +/// This provides interfaces to the class. +/// +public interface IEventRepository +{ + /// + /// Gets the list of events. + /// + /// Returns the list of events. + Task> GetEvents(); +} + +public class EventRepository(TableServiceClient tableServiceClient, StorageAccountSettings storageAccountSettings) : IEventRepository +{ + private readonly TableServiceClient _tableServiceClient = tableServiceClient ?? throw new ArgumentNullException(nameof(tableServiceClient)); + private readonly StorageAccountSettings _storageAccountSettings = storageAccountSettings ?? throw new ArgumentNullException(nameof(storageAccountSettings)); + + /// + public async Task> GetEvents() + { + TableClient tableClient = await GetTableClientAsync(); + + List events = []; + + await foreach (EventDetails eventDetails in tableClient.QueryAsync(e => e.PartitionKey.Equals(PartitionKeys.EventDetails)).ConfigureAwait(false)) + { + events.Add(eventDetails); + } + + return events; + } + + private async Task GetTableClientAsync() + { + TableClient tableClient = _tableServiceClient.GetTableClient(_storageAccountSettings.TableStorage.TableName); + + await tableClient.CreateIfNotExistsAsync().ConfigureAwait(false); + + return tableClient; + } +} + +/// +/// This represents the extension class for +/// +public static class EventRepositoryExtensions +{ + /// + /// Adds the instance to the service collection. + /// + /// instance. + /// Returns instance. + public static IServiceCollection AddEventRepository(this IServiceCollection services) + { + services.AddScoped(); + + return services; + } +} \ No newline at end of file diff --git a/src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs b/src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs new file mode 100644 index 00000000..aac15902 --- /dev/null +++ b/src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs @@ -0,0 +1,62 @@ +using AzureOpenAIProxy.ApiApp.Repositories; + +namespace AzureOpenAIProxy.ApiApp.Services; + +/// +/// This provides interfaces to class. +/// +public interface IPlaygroundService +{ + /// + /// Get the list of deployment model. + /// + /// Returns the list of deployment models. + Task> GetDeploymentModels(Guid eventId); + + /// + /// Get the list of events. + /// + /// Returns the list of events. + Task> GetEvents(); +} + +public class PlaygroundService(IEventRepository eventRepository) : IPlaygroundService +{ + private readonly IEventRepository _eventRepository = eventRepository ?? throw new ArgumentNullException(nameof(eventRepository)); + + /// + public async Task> GetDeploymentModels(Guid eventId) + { + // var result = await _eventRepository.GetDeploymentModels(eventId).ConfigureAwait(false); + + // return result; + + throw new NotImplementedException(); + } + + /// + public async Task> GetEvents() + { + var result = await _eventRepository.GetEvents().ConfigureAwait(false); + + return result; + } +} + +/// +/// This represents the extension class for +/// +public static class PlaygroundServiceExtensions +{ + /// + /// Adds the instance to the service collection. + /// + /// instance. + /// Returns instance. + public static IServiceCollection AddPlaygroundService(this IServiceCollection services) + { + services.AddScoped(); + + return services; + } +} \ No newline at end of file From 1d92e8e7adace3f636016805cf9847bdb1ca8bb5 Mon Sep 17 00:00:00 2001 From: yj_chun Date: Sun, 6 Oct 2024 17:56:38 +0900 Subject: [PATCH 3/7] =?UTF-8?q?refactor:=20PlaygroundEndpoints=20-=20Logge?= =?UTF-8?q?r=20=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs b/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs index ecf81179..77f7ceb8 100644 --- a/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs +++ b/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs @@ -54,7 +54,7 @@ public static RouteHandlerBuilder AddListDeploymentModels(this WebApplication ap ILoggerFactory loggerFactory ) => { - var logger = loggerFactory.CreateLogger(nameof(AdminEventEndpoints)); + var logger = loggerFactory.CreateLogger(nameof(PlaygroundEndpoints)); logger.LogInformation("Received request to fetch deployment models list"); try From 7a843ea7c619d1042dfc877abbb845e28c3df5b6 Mon Sep 17 00:00:00 2001 From: yj_chun Date: Sun, 6 Oct 2024 18:31:07 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20EventRepository=EC=97=90=20GetDeplo?= =?UTF-8?q?ymentModels=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 그에 따른 PlaygroundService.cs - GetDeploymentModels 업데이트 --- .../Repositories/EventRepository.cs | 22 +++++++++++++++++++ .../Services/PlaygroundService.cs | 6 ++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/AzureOpenAIProxy.ApiApp/Repositories/EventRepository.cs b/src/AzureOpenAIProxy.ApiApp/Repositories/EventRepository.cs index ecaf832e..4a730b98 100644 --- a/src/AzureOpenAIProxy.ApiApp/Repositories/EventRepository.cs +++ b/src/AzureOpenAIProxy.ApiApp/Repositories/EventRepository.cs @@ -9,6 +9,12 @@ namespace AzureOpenAIProxy.ApiApp.Repositories; /// public interface IEventRepository { + /// + /// Get the list of deployment model. + /// + /// Returns the list of deployment models. + Task> GetDeploymentModels(Guid eventId); + /// /// Gets the list of events. /// @@ -21,6 +27,22 @@ public class EventRepository(TableServiceClient tableServiceClient, StorageAccou private readonly TableServiceClient _tableServiceClient = tableServiceClient ?? throw new ArgumentNullException(nameof(tableServiceClient)); private readonly StorageAccountSettings _storageAccountSettings = storageAccountSettings ?? throw new ArgumentNullException(nameof(storageAccountSettings)); + /// + public async Task> GetDeploymentModels(Guid eventId) + { + TableClient tableClient = await GetTableClientAsync(); + + List deploymentModels = []; + + // 예. eventId로 특정 이벤트 정보 가져오기 + // var eventDetail = await tableClient.GetEntityAsync( + // rowKey: eventId.ToString(), + // partitionKey: PartitionKeys.EventDetails + // ).ConfigureAwait(false); + + return deploymentModels; + } + /// public async Task> GetEvents() { diff --git a/src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs b/src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs index aac15902..135e215f 100644 --- a/src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs +++ b/src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs @@ -27,11 +27,9 @@ public class PlaygroundService(IEventRepository eventRepository) : IPlaygroundSe /// public async Task> GetDeploymentModels(Guid eventId) { - // var result = await _eventRepository.GetDeploymentModels(eventId).ConfigureAwait(false); + var result = await _eventRepository.GetDeploymentModels(eventId).ConfigureAwait(false); - // return result; - - throw new NotImplementedException(); + return result; } /// From 4fc145086ea11c5e562532582a8c2a7800ebb45e Mon Sep 17 00:00:00 2001 From: yj_chun Date: Sun, 6 Oct 2024 18:31:40 +0900 Subject: [PATCH 5/7] =?UTF-8?q?refactor:=20PlaygroundEndpoints=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Endpoints/PlaygroundEndpoints.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs b/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs index 77f7ceb8..cd45f6a2 100644 --- a/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs +++ b/src/AzureOpenAIProxy.ApiApp/Endpoints/PlaygroundEndpoints.cs @@ -55,7 +55,7 @@ ILoggerFactory loggerFactory ) => { var logger = loggerFactory.CreateLogger(nameof(PlaygroundEndpoints)); - logger.LogInformation("Received request to fetch deployment models list"); + logger.LogInformation($"Received request to fetch deployment models list for event with ID: {eventId}"); try { @@ -64,12 +64,18 @@ ILoggerFactory loggerFactory } catch (RequestFailedException ex) { - logger.LogError(ex, "Failed to fetch deployment models list"); + if(ex.Status == 404) + { + logger.LogError($"Failed to fetch deployment models list of {eventId}"); + return Results.NotFound(); + } + + logger.LogError(ex, $"Failed to fetch deployment models list of {eventId} with status {ex.Status}"); return Results.Problem(ex.Message, statusCode: StatusCodes.Status500InternalServerError); } catch (Exception ex) { - logger.LogError(ex, "Failed to fetch deployment models list"); + logger.LogError(ex, $"Failed to fetch deployment models list of {eventId}"); return Results.Problem(ex.Message, statusCode: StatusCodes.Status500InternalServerError); } }) @@ -82,7 +88,7 @@ ILoggerFactory loggerFactory .WithOpenApi(operation => { operation.Summary = "Gets all deployment models"; - operation.Description = "This endpoint gets all deployment models avaliable"; + operation.Description = "This endpoint gets all deployment models available"; return operation; }); From 9c8c6d77fee0ff548557b3dd6c7bbb974efa0456 Mon Sep 17 00:00:00 2001 From: yj_chun Date: Wed, 16 Oct 2024 17:26:40 +0900 Subject: [PATCH 6/7] chore: PlaygroundService.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GetDeploymentModels() 메소드 NotImplementedException 처리(임시) --- src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs b/src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs index 135e215f..aac15902 100644 --- a/src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs +++ b/src/AzureOpenAIProxy.ApiApp/Services/PlaygroundService.cs @@ -27,9 +27,11 @@ public class PlaygroundService(IEventRepository eventRepository) : IPlaygroundSe /// public async Task> GetDeploymentModels(Guid eventId) { - var result = await _eventRepository.GetDeploymentModels(eventId).ConfigureAwait(false); + // var result = await _eventRepository.GetDeploymentModels(eventId).ConfigureAwait(false); - return result; + // return result; + + throw new NotImplementedException(); } /// From 8033776d0f91caa9e27906dee884806f5399dd76 Mon Sep 17 00:00:00 2001 From: yj_chun Date: Wed, 16 Oct 2024 17:41:12 +0900 Subject: [PATCH 7/7] =?UTF-8?q?test:=20PlaygroundServiceTests=20-=20GetDep?= =?UTF-8?q?loymentModels=20=EA=B4=80=EB=A0=A8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=20eventId=20Arrange=20=EC=8B=9C=20String?= =?UTF-8?q?=20->=20Guid=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/PlaygroundServiceTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/AzureOpenAIProxy.ApiApp.Tests/Services/PlaygroundServiceTests.cs b/test/AzureOpenAIProxy.ApiApp.Tests/Services/PlaygroundServiceTests.cs index 38e93879..f810a14c 100644 --- a/test/AzureOpenAIProxy.ApiApp.Tests/Services/PlaygroundServiceTests.cs +++ b/test/AzureOpenAIProxy.ApiApp.Tests/Services/PlaygroundServiceTests.cs @@ -31,7 +31,7 @@ public void Given_ServiceCollection_When_AddPlaygroundService_Invoked_Then_It_Sh public void Given_Instance_When_GetDeploymentModels_Invoked_Then_It_Should_Throw_Exception() { // Arrange - string eventId = "test-id"; + var eventId = Guid.NewGuid(); var repository = Substitute.For(); var service = new PlaygroundService(repository);