Skip to content

Conversation

jh941213
Copy link
Contributor

Purpose

  • closes Connector Implementation & Inheritance: LG AI EXAONE Connector Implementation & Inheritance: LG AI EXAONE #253
  • Implement LGConnector class that inherits from LanguageModelConnector
  • Add AppSettings dependency injection for LG AI EXAONE configuration
  • Override GetChatClient method to provide LG AI EXAONE chat client functionality
  • Enable LG AI EXAONE integration through Ollama-compatible API

Does this introduce a breaking change?

[ ] Yes
[x] No

Pull Request Type

What kind of change does this Pull Request introduce?

[ ] Bugfix
[x] New feature
[ ] Refactoring (no functional changes, no api changes)
[ ] Documentation content changes
[ ] Other... Please describe:

README updated?

The top-level readme for this repo contains a link to each sample in the repo. If you're adding a new sample did you update the readme?

[ ] Yes
[ ] No
[x] N/A

How to Test

  • Get the code
git clone https://github.com/tae0y/open-chat-playground.git
cd open-chat-playground
git checkout feature/253
  • Test the code
dotnet test test/OpenChat.PlaygroundApp.Tests/OpenChat.PlaygroundApp.Tests.csproj --filter "FullyQualifiedName~LGConnectorTests"
dotnet run --project ./src/OpenChat.PlaygroundApp/ -- --connector-type LG --base-url http://localhost:11434 --model lg-exaone-model

What to Check

Verify that the following are valid

  • LGConnector class properly inherits from LanguageModelConnector
  • AppSettings dependency injection works correctly for LG configuration
  • GetChatClientAsync method returns valid IChatClient instance
  • LG connector type is properly registered in LanguageModelConnector.CreateChatClientAsync
  • All LGConnectorTests pass successfully
  • LG connector integrates seamlessly with existing connector infrastructure

Other Information

This implementation follows the same pattern as Ollama connector implementation, using OllamaSharp library for LG AI EXAONE integration. The connector:

  • Uses Ollama-compatible API for LG AI EXAONE models
  • Requires only BaseUrl and Model configuration (no API key needed for open source models)
  • Implements proper validation for required configuration settings
  • Provides comprehensive error handling for missing or invalid configurations

Key components added:

  • LGConnector.cs - Main connector implementation
  • LGConnectorTests.cs - Comprehensive unit tests
  • Updated LanguageModelConnector.cs to include LG case in factory method

The implementation enables users to run LG AI EXAONE models through the OpenChat Playground interface using the same infrastructure as other supported connectors.

@justinyoo
Copy link
Contributor

@jh941213 머지 컨플릭도 해소해 주세요. 이번에는 리베이스 하다 망하지 마시고 차근차근...

@jh941213
Copy link
Contributor Author

453 브랜치 생성을 못하고 시작 해서, 그부분은 컨플릭트 수정하고, 이 이슈까진 253 사용하고 인지하고 있겠습니다

LanguageModelConnector connector = settings.ConnectorType switch
{
ConnectorType.GitHubModels => new GitHubModelsConnector(settings),
ConnectorType.LG => new LGConnector(settings),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#155 보시고 순서 맞춰 넣어주세요.

ConnectorType.GitHubModels => new GitHubModelsConnector(settings),
ConnectorType.LG => new LGConnector(settings),
ConnectorType.HuggingFace => new HuggingFaceConnector(settings),

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기에는 빈 줄이 필요 없습니다.

Comment on lines 34 to 43
// Validate LG model format: should be HuggingFace format, LG model, or GGUF format
var model = settings.Model.Trim();
var isHuggingFaceFormat = model.StartsWith("hf.co/") || model.Contains("/");
var isLGModel = model.ToLowerInvariant().Contains("exaone") || model.ToLowerInvariant().Contains("lg");
var isGGUFFormat = model.ToLowerInvariant().EndsWith(".gguf") || model.ToLowerInvariant().Contains("gguf");

if (!isHuggingFaceFormat && !isLGModel && !isGGUFFormat)
{
throw new InvalidOperationException("Invalid LG model format. Model should be HuggingFace format (hf.co/...), LG model (containing 'exaone' or 'lg'), or GGUF format (containing 'gguf').");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 메소드 하나에서 이 모든 것을 다 validation 하는 것이 좋을까요, 아니면 이 로직은 별도의 private bool 메소드로 빼는 것이 좋을까요? 허깅페이스 커넥터 로직 한 번 보실랍니까?

private static bool IsValidModel(string model)
{
var segments = model.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if (segments.Length != 3)
{
return false;
}
if (segments.First().Equals(HuggingFaceHost, StringComparison.InvariantCultureIgnoreCase) == false)
{
return false;
}
if (segments.Last().EndsWith(ModelSuffix, StringComparison.InvariantCultureIgnoreCase) == false)
{
return false;
}
return true;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

비효율적인거 같습니다 참고하겠습니다

Comment on lines 115 to 120
[InlineData("hf.co/LGAI-EXAONE/EXAONE-4.0-1.2B-GGUF")]
[InlineData("LGAI-EXAONE/EXAONE-4.0-1.2B")]
[InlineData("lg-exaone-model")]
[InlineData("exaone-3.0")]
[InlineData("model.gguf")]
[InlineData("exaone-gguf-model")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기 있는 모델들이 다 LG 모델 맞나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Fact] 를 활용해서 단일 엘지 커넥트로 수정하겠습니다

Comment on lines +75 to +111
[Trait("Category", "UnitTest")]
[Theory]
[InlineData(null, typeof(NullReferenceException), "Object reference not set to an instance of an object")]
[InlineData("", typeof(InvalidOperationException), "LG:Model")]
[InlineData(" ", typeof(InvalidOperationException), "LG:Model")]
public void Given_Invalid_Model_When_EnsureLanguageModelSettingsValid_Invoked_Then_It_Should_Throw(string? model, Type expectedType, string expectedMessage)
{
// Arrange
var appSettings = BuildAppSettings(model: model);
var connector = new LGConnector(appSettings);

// Act
Action action = () => connector.EnsureLanguageModelSettingsValid();

// Assert
action.ShouldThrow(expectedType)
.Message.ShouldContain(expectedMessage);
}

[Trait("Category", "UnitTest")]
[Theory]
[InlineData("invalid-model", typeof(InvalidOperationException), "Invalid LG model format")]
[InlineData("random-name", typeof(InvalidOperationException), "Invalid LG model format")]
[InlineData("test-model", typeof(InvalidOperationException), "Invalid LG model format")]
public void Given_Invalid_Model_Format_When_EnsureLanguageModelSettingsValid_Invoked_Then_It_Should_Throw(string model, Type expectedType, string expectedMessage)
{
// Arrange
var appSettings = BuildAppSettings(model: model);
var connector = new LGConnector(appSettings);

// Act
Action action = () => connector.EnsureLanguageModelSettingsValid();

// Assert
action.ShouldThrow(expectedType)
.Message.ShouldContain(expectedMessage);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 테스트 두 개를 따로 놓는 대신 합치면 안되나요?

Comment on lines +164 to +179
[Trait("Category", "UnitTest")]
[Theory]
[InlineData(null, typeof(ArgumentNullException))]
[InlineData("", typeof(UriFormatException))]
public void Given_Missing_BaseUrl_When_GetChatClient_Invoked_Then_It_Should_Throw(string? baseUrl, Type expected)
{
// Arrange
var settings = BuildAppSettings(baseUrl: baseUrl);
var connector = new LGConnector(settings);

// Act
Func<Task> func = async () => await connector.GetChatClientAsync();

// Assert
func.ShouldThrow(expected);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Base URL 값만 테스트했는데, 모델 값도 테스트를 추가해야 합니다.

Comment on lines 197 to 217
[Trait("Category", "UnitTest")]
[Fact]
public void Given_Invalid_Settings_When_CreateChatClientAsync_Invoked_Then_It_Should_Throw()
{
// Arrange
var settings = new AppSettings
{
ConnectorType = ConnectorType.LG,
LG = new LGSettings
{
BaseUrl = null,
Model = "lg-exaone-model"
}
};

// Act
Func<Task> func = async () => await LanguageModelConnector.CreateChatClientAsync(settings);

// Assert
func.ShouldThrow<NullReferenceException>();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invalid 세팅을 테스트하는데, base URL 값과 모델 값을 테스트하려면 [Fact] 대신 [Theory]를 써서 [InlineData(...)]를 추가해 보세요.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Connector Implementation & Inheritance: LG AI EXAONE
3 participants