-
Notifications
You must be signed in to change notification settings - Fork 23
feat: add Google Vertex AI connector implementation #493
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 10 commits
448aa7f
389481a
12d2bd6
0be2a59
4c28c4c
319f6be
4d05176
2dff61a
274a22a
d2e7f6d
148ba33
282cc6f
e87a218
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
using System.ClientModel; | ||
|
||
using Microsoft.Extensions.AI; | ||
|
||
using Mscc.GenerativeAI.Microsoft; | ||
|
||
using OpenChat.PlaygroundApp.Abstractions; | ||
using OpenChat.PlaygroundApp.Configurations; | ||
|
||
namespace OpenChat.PlaygroundApp.Connectors; | ||
|
||
/// <summary> | ||
/// This represents the connector entity for Google Vertex AI. | ||
/// </summary> | ||
public class GoogleVertexAIConnector(AppSettings settings) : LanguageModelConnector(settings.GoogleVertexAI) | ||
{ | ||
/// <inheritdoc/> | ||
public override bool EnsureLanguageModelSettingsValid() | ||
{ | ||
var settings = this.Settings as GoogleVertexAISettings; | ||
if (settings is null) | ||
{ | ||
throw new InvalidOperationException("Missing configuration: GoogleVertexAI."); | ||
} | ||
|
||
if (string.IsNullOrWhiteSpace(settings.ApiKey?.Trim()) == true) | ||
{ | ||
throw new InvalidOperationException("Missing configuration: GoogleVertexAI:ApiKey."); | ||
} | ||
|
||
if (string.IsNullOrWhiteSpace(settings.Model?.Trim()) == true) | ||
{ | ||
throw new InvalidOperationException("Missing configuration: GoogleVertexAI:Model."); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override async Task<IChatClient> GetChatClientAsync() | ||
{ | ||
var settings = this.Settings as GoogleVertexAISettings; | ||
|
||
var apiKey = settings?.ApiKey ?? throw new InvalidOperationException("Missing configuration: GoogleVertexAI:ApiKey."); | ||
var model = settings?.Model ?? throw new InvalidOperationException("Missing configuration: GoogleVertexAI:Model."); | ||
|
||
var chatClient = new GeminiChatClient(apiKey, model); | ||
|
||
return await Task.FromResult(chatClient).ConfigureAwait(false); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
using Microsoft.Extensions.AI; | ||
|
||
using OpenChat.PlaygroundApp.Abstractions; | ||
using OpenChat.PlaygroundApp.Configurations; | ||
using OpenChat.PlaygroundApp.Connectors; | ||
|
||
namespace OpenChat.PlaygroundApp.Tests.Connectors; | ||
|
||
public class GoogleVertexAIConnectorTests | ||
{ | ||
private const string ApiKey = "AIzaSyA1234567890abcdefgHIJKLMNOpqrstuv"; | ||
private const string Model = "test-model"; | ||
private static AppSettings BuildAppSettings(string? apiKey = ApiKey, string? model = Model) | ||
{ | ||
return new AppSettings | ||
{ | ||
ConnectorType = ConnectorType.GoogleVertexAI, | ||
GoogleVertexAI = new GoogleVertexAISettings | ||
{ | ||
ApiKey = apiKey, | ||
Model = model | ||
} | ||
}; | ||
} | ||
|
||
[Trait("Category", "UnitTest")] | ||
[Fact] | ||
public void Given_Settings_Is_Null_When_EnsureLanguageModelSettingsValid_Invoked_Then_It_Should_Throw() | ||
{ | ||
// Arrange | ||
var appSettings = new AppSettings { ConnectorType = ConnectorType.GoogleVertexAI, GoogleVertexAI = null }; | ||
var connector = new GoogleVertexAIConnector(appSettings); | ||
|
||
// Act | ||
Action action = () => connector.EnsureLanguageModelSettingsValid(); | ||
|
||
// Assert | ||
action.ShouldThrow<InvalidOperationException>() | ||
.Message.ShouldContain("GoogleVertexAI"); | ||
} | ||
|
||
[Trait("Category", "UnitTest")] | ||
[Theory] | ||
[InlineData(null, typeof(InvalidOperationException), "GoogleVertexAI:ApiKey")] | ||
[InlineData("", typeof(InvalidOperationException), "GoogleVertexAI:ApiKey")] | ||
[InlineData(" ", typeof(InvalidOperationException), "GoogleVertexAI:ApiKey")] | ||
public void Given_Invalid_ApiKey_When_EnsureLanguageModelSettingsValid_Invoked_Then_It_Should_Throw(string? apiKey, Type expectedType, string expectedMessage) | ||
Check warning on line 47 in test/OpenChat.PlaygroundApp.Tests/Connectors/GoogleVertexAIConnectorTests.cs
|
||
{ | ||
// Arrange | ||
var appSettings = BuildAppSettings(apiKey: apiKey); | ||
var connector = new GoogleVertexAIConnector(appSettings); | ||
|
||
// Act | ||
Action action = () => connector.EnsureLanguageModelSettingsValid(); | ||
|
||
// Assert | ||
action.ShouldThrow<InvalidOperationException>() | ||
.Message.ShouldContain(expectedMessage); | ||
} | ||
|
||
[Trait("Category", "UnitTest")] | ||
[Theory] | ||
[InlineData(null, typeof(InvalidOperationException), "GoogleVertexAI:Model")] | ||
[InlineData("", typeof(InvalidOperationException), "GoogleVertexAI:Model")] | ||
[InlineData(" ", typeof(InvalidOperationException), "GoogleVertexAI:Model")] | ||
public void Given_Invalid_Model_When_EnsureLanguageModelSettingsValid_Invoked_Then_It_Should_Throw(string? model, Type expectedType, string expectedMessage) | ||
Check warning on line 66 in test/OpenChat.PlaygroundApp.Tests/Connectors/GoogleVertexAIConnectorTests.cs
|
||
{ | ||
// Arrange | ||
var appSettings = BuildAppSettings(apiKey: "valid-key", model: model); | ||
var connector = new GoogleVertexAIConnector(appSettings); | ||
|
||
// Act | ||
Action action = () => connector.EnsureLanguageModelSettingsValid(); | ||
|
||
// Assert | ||
action.ShouldThrow<InvalidOperationException>() | ||
.Message.ShouldContain(expectedMessage); | ||
} | ||
|
||
[Trait("Category", "UnitTest")] | ||
[Fact] | ||
public void Given_Valid_Settings_When_EnsureLanguageModelSettingsValid_Invoked_Then_It_Should_Return_True() | ||
{ | ||
// Arrange | ||
var appSettings = BuildAppSettings(); | ||
var connector = new GoogleVertexAIConnector(appSettings); | ||
|
||
// Act | ||
var result = connector.EnsureLanguageModelSettingsValid(); | ||
|
||
// Assert | ||
result.ShouldBeTrue(); | ||
} | ||
|
||
[Trait("Category", "UnitTest")] | ||
[Fact] | ||
public async Task Given_Valid_Settings_When_GetChatClient_Invoked_Then_It_Should_Return_ChatClient() | ||
{ | ||
var settings = BuildAppSettings(); | ||
var connector = new GoogleVertexAIConnector(settings); | ||
|
||
var client = await connector.GetChatClientAsync(); | ||
|
||
client.ShouldNotBeNull(); | ||
} | ||
|
||
[Trait("Category", "UnitTest")] | ||
[Fact] | ||
public void Given_Settings_Is_Null_When_GetChatClientAsync_Invoked_Then_It_Should_Throw() | ||
{ | ||
// Arrange | ||
var appSettings = new AppSettings { ConnectorType = ConnectorType.GoogleVertexAI, GoogleVertexAI = null }; | ||
var connector = new GoogleVertexAIConnector(appSettings); | ||
|
||
// Act | ||
Func<Task> func = async () => await connector.GetChatClientAsync(); | ||
|
||
// Assert | ||
func.ShouldThrow<InvalidOperationException>(); | ||
} | ||
|
||
[Trait("Category", "UnitTest")] | ||
[Theory] | ||
[InlineData(null, typeof(InvalidOperationException), "GoogleVertexAI:ApiKey")] | ||
[InlineData("", typeof(ArgumentException), "key")] | ||
public async Task Given_Missing_ApiKey_When_GetChatClient_Invoked_Then_It_Should_Throw(string? apiKey, Type expected, string message) | ||
Check warning on line 126 in test/OpenChat.PlaygroundApp.Tests/Connectors/GoogleVertexAIConnectorTests.cs
|
||
{ | ||
// Arrange | ||
var settings = BuildAppSettings(apiKey: apiKey); | ||
var connector = new GoogleVertexAIConnector(settings); | ||
|
||
// Act | ||
Func<Task> func = async () => await connector.GetChatClientAsync(); | ||
|
||
// Assert | ||
func.ShouldThrow(expected) | ||
.Message.ShouldContain(message); | ||
} | ||
|
||
[Trait("Category", "UnitTest")] | ||
[Theory] | ||
[InlineData(null, typeof(InvalidOperationException), "model")] | ||
public async Task Given_Missing_Model_When_GetChatClient_Invoked_Then_It_Should_Throw(string? model, Type expected, string message) | ||
Check warning on line 143 in test/OpenChat.PlaygroundApp.Tests/Connectors/GoogleVertexAIConnectorTests.cs
|
||
{ | ||
// Arrange | ||
var settings = BuildAppSettings(model: model); | ||
var connector = new GoogleVertexAIConnector(settings); | ||
|
||
// Act | ||
Func<Task> func = async () => await connector.GetChatClientAsync(); | ||
|
||
// Assert | ||
func.ShouldThrow(expected) | ||
.Message.ShouldContain(message); | ||
} | ||
|
||
[Trait("Category", "UnitTest")] | ||
[Fact] | ||
public async Task Given_Valid_Settings_When_CreateChatClientAsync_Invoked_Then_It_Should_Return_ChatClient() | ||
{ | ||
// Arrange | ||
var settings = BuildAppSettings(); | ||
|
||
// Act | ||
var result = await LanguageModelConnector.CreateChatClientAsync(settings); | ||
|
||
// Assert | ||
result.ShouldNotBeNull(); | ||
result.ShouldBeAssignableTo<IChatClient>(); | ||
} | ||
|
||
[Trait("Category", "UnitTest")] | ||
[Fact] | ||
public void Given_Invalid_Settings_When_CreateChatClientAsync_Invoked_Then_It_Should_Throw() | ||
{ | ||
// Arrange | ||
var settings = new AppSettings | ||
{ | ||
ConnectorType = ConnectorType.GoogleVertexAI, | ||
GoogleVertexAI = new GoogleVertexAISettings | ||
{ | ||
ApiKey = null, | ||
Model = "test-model" | ||
} | ||
}; | ||
|
||
// Act | ||
Func<Task> func = async () => await LanguageModelConnector.CreateChatClientAsync(settings); | ||
|
||
// Assert | ||
func.ShouldThrow<InvalidOperationException>(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type expectedType
매개인자는 사용하지 않으니 모두 제거해주세요다른 테스트 메서드도 모두 동일합니다 ~