Skip to content

Conversation

gremh97
Copy link
Contributor

@gremh97 gremh97 commented Sep 23, 2025

Purpose

  • Implements the Upstage connector using the OpenAI SDK, enabling support for Upstage AI models in the playground.
  • Adds comprehensive unit tests for configuration validation, error handling, and ChatClient creation.
  • Improves configuration management with clear priority: CLI arguments > environment variables > appsettings.json.
  • Updates documentation to include architecture analysis and implementation guide for the new connector

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
[x] No
[ ] N/A

How to Test

  • Get the code
git clone https://github.com/gremh97/open-chat-playground.git
cd open-chat-playground
git checkout feature/235-connector-implementation-inheritance-upstage
  • Test the code
# Build and run the application
dotnet build
dotnet run --project src/OpenChat.PlaygroundApp -- --help

# Run Upstage-specific tests
dotnet test --filter "Upstage" --verbosity normal

# Run Upstage connector tests
dotnet test --filter "FullyQualifiedName~UpstageConnectorTests" --verbosity normal

What to Check

  • Verify that the following are valid
  • All unit tests pass successfully
  • Application builds without errors
  • Upstage connector works as expected with CLI and environment variable configuration
  • No regression in existing features
  • Code follows project conventions and standards
  • Documentation is clear and accurate

Other Information

  • Include any additional context about the implementation
  • Mention any dependencies or prerequisites
  • Note any breaking changes or migration steps required
  • Reference related issues or discussions

Resolves #235

- Add UpstageConnector class inheriting from LanguageModelConnector
- Implement EnsureLanguageModelSettingsValid() with BaseUrl, ApiKey, Model validation
- Implement GetChatClientAsync() using OpenAI SDK with custom endpoint for Upstage API
- Add Upstage case to LanguageModelConnector.CreateChatClientAsync() factory method
- Leverage OpenAI SDK compatibility since Upstage API follows OpenAI format
- Enable connection to Upstage Solar AI models through the application

Partially resolves aliencube#235
- Added test/OpenChat.PlaygroundApp.Tests/Connectors/UpstageConnectorTests.cs
- Covers configuration validation, error handling, and ChatClient creation for Upstage connector
- Ensures reliability and correct behavior for Upstage integration
Copy link
Contributor

@sikutisa sikutisa left a comment

Choose a reason for hiding this comment

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

  1. 일단 Connector와 테스트 코드 먼저 리뷰하겠습니다.
  2. 테스트가 더 추가돼야 합니다.
  • UpstageConnectorLanguageModelConnector를 상속하는지에 대한 테스트
  • 테스트해야 하는 메소드는 총 3개입니다.
    • EnsureLanguageModelSettingsValid()
    • GetChatClientAsync()
    • LanguageModelConnector.CreateChatClientAsync()

이 내용 한 번 봐보시죠.
#447 (comment)

…rTests

- Add private const fields for BaseUrl, ApiKey, and Model
- Replace hardcoded strings in BuildAppSettings method with constants
- Improve code maintainability and consistency
…ouldly pattern

- Replace Assert.Throws<T>() with Action.ShouldThrow<T>() for sync methods
- Replace Assert.ThrowsAsync<T>() with Func<Task>.ShouldThrow<T>() for async methods
- Remove async/await keywords from test methods using Shouldly pattern
- Improve test readability with fluent API and method chaining
- Ensure tests actually execute methods instead of just checking exceptions

This addresses the bug where tests were not properly testing method execution
and aligns with best practices for exception testing using Shouldly framework.
…ance-upstage

- Merge latest changes from upstream repository
- Includes HuggingFace connector implementation
- UI improvements for ChatInput and ChatMessageItem components
- Documentation updates and new connector guides
- E2E tests for ChatInput IME functionality
- Infrastructure updates for Azure deployment
- Add test to verify UpstageConnector inherits from LanguageModelConnector
- Add using statement for OpenChat.PlaygroundApp.Abstractions namespace
- Implement Theory test with InlineData for both inheritance directions:
  - LanguageModelConnector.IsAssignableFrom(UpstageConnector) should be true
  - UpstageConnector.IsAssignableFrom(LanguageModelConnector) should be false
- Ensures proper polymorphism and type safety in connector architecture
- Validates adherence to Liskov Substitution Principle
@gremh97
Copy link
Contributor Author

gremh97 commented Sep 28, 2025

UpstageConnector가 LanguageModelConnector를 상속하는지에 대한 테스트가 ae18a9b에서 추가되었습니다

Copy link
Contributor

@sikutisa sikutisa left a comment

Choose a reason for hiding this comment

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

Exception 테스트 관련 수정 내용을 봤는데, Act & Assert로 묶은 이유가 있나요?
아래 처럼 분리할 수 있을 것 같은데요.

// Act
Action action = () => MethodToTest();

// Assert
action.ShouldThrow<SomethingException>()
      .Message.ShouldContain("something message");

@sikutisa
Copy link
Contributor

  1. 테스트가 더 추가돼야 합니다.
  • UpstageConnectorLanguageModelConnector를 상속하는지에 대한 테스트

  • 테스트해야 하는 메소드는 총 3개입니다.

    • EnsureLanguageModelSettingsValid()
    • GetChatClientAsync()
    • LanguageModelConnector.CreateChatClientAsync()

이 내용 한 번 봐보시죠. #447 (comment)

이 부분도 더 보완돼야 합니다.

@gremh97
Copy link
Contributor Author

gremh97 commented Sep 29, 2025

@sikutisa 기간이 지나서 없어졌는데 appsettings쪽 변수명 settings로 되어 있는건 그대로 유지하면 되는건가요?

@sikutisa
Copy link
Contributor

@sikutisa 기간이 지나서 없어졌는데 appsettings쪽 변수명 settings로 되어 있는건 그대로 유지하면 되는건가요?

네. 일단 다른 커넥터랑 맞추시죠.

- Add test for GetChatClientAsync() with null settings scenario
- Add test for LanguageModelConnector.CreateChatClientAsync() success case
- Add test for LanguageModelConnector.CreateChatClientAsync() failure case
- Complete test coverage for all public methods:
  * EnsureLanguageModelSettingsValid() - 5 test cases
  * GetChatClientAsync() - 5 test cases
  * CreateChatClientAsync() - 2 test cases
  * Inheritance relationship - 1 test case
- Ensure proper exception handling and validation logic
- Use Shouldly pattern for consistent and readable assertions
…ions

- Separate combined '// Act & Assert' comments into individual sections
- Improve test readability following AAA (Arrange-Act-Assert) pattern
- Apply changes to 9 test methods across all test categories:
  * EnsureLanguageModelSettingsValid() tests (4 methods)
  * GetChatClientAsync() tests (4 methods)
  * CreateChatClientAsync() tests (1 method)
- Maintain existing test logic while enhancing code structure
- Better alignment with unit testing best practices
@gremh97
Copy link
Contributor Author

gremh97 commented Sep 30, 2025

Exception 테스트 관련 수정 내용을 봤는데, Act & Assert로 묶은 이유가 있나요? 아래 처럼 분리할 수 있을 것 같은데요.

// Act
Action action = () => MethodToTest();

// Assert
action.ShouldThrow<SomethingException>()
      .Message.ShouldContain("something message");

넵 분리하였습니다

…nException

- Change expected exception type from NullReferenceException to InvalidOperationException in GetChatClientAsync test
- Fix test to match actual exception behavior when Upstage settings is null
- All UpstageConnector tests now pass (23/23 successful)
@gremh97
Copy link
Contributor Author

gremh97 commented Sep 30, 2025

  1. 테스트가 더 추가돼야 합니다.
  • UpstageConnectorLanguageModelConnector를 상속하는지에 대한 테스트

  • 테스트해야 하는 메소드는 총 3개입니다.

    • EnsureLanguageModelSettingsValid()
    • GetChatClientAsync()
    • LanguageModelConnector.CreateChatClientAsync()

이 내용 한 번 봐보시죠. #447 (comment)

이 부분도 더 보완돼야 합니다.

  • Given_Settings_Is_Null_When_GetChatClientAsync_Invoked_Then_It_Should_Throw
  • Given_Valid_Settings_When_CreateChatClientAsync_Invoked_Then_It_Should_Return_ChatClient
  • Given_Invalid_Settings_When_CreateChatClientAsync_Invoked_Then_It_Should_Throw
    이렇게 세개의 테스트 케이스를 추가하였습니다.

UpstageConnector 테스트 케이스 정리 (총 13개)


1. 상속 관계 테스트 (1개)

  • Given_BaseType_Then_It_Should_Be_AssignableFrom_DerivedType
    • 목적: UpstageConnectorLanguageModelConnector를 올바르게 상속하는지 확인합니다.
    • 테스트 메서드: Type.IsAssignableFrom()
    • 예상 결과:
      LanguageModelConnector.IsAssignableFrom(UpstageConnector) // → true
      UpstageConnector.IsAssignableFrom(LanguageModelConnector) // → false

2. EnsureLanguageModelSettingsValid() 테스트 (5개)

  • Given_Settings_Is_Null_When_EnsureLanguageModelSettingsValid_Invoked_Then_It_Should_Throw

    • 목적: Upstage 설정이 null일 때 예외 발생을 확인합니다.
    • 예상 결과: InvalidOperationException 발생 (메시지에 "Upstage" 포함)
  • Given_Invalid_BaseUrl_When_EnsureLanguageModelSettingsValid_Invoked_Then_It_Should_Throw

    • 목적: BaseUrlnull, "", " "일 때 예외 발생을 확인합니다.
    • 예상 결과: InvalidOperationException 발생 (메시지에 "Upstage:BaseUrl" 포함)
  • Given_Invalid_ApiKey_When_EnsureLanguageModelSettingsValid_Invoked_Then_It_Should_Throw

    • 목적: ApiKeynull, "", " "일 때 예외 발생을 확인합니다.
    • 예상 결과: InvalidOperationException 발생 (메시지에 "Upstage:ApiKey" 포함)
  • Given_Invalid_Model_When_EnsureLanguageModelSettingsValid_Invoked_Then_It_Should_Throw

    • 목적: Modelnull, "", " "일 때 예외 발생을 확인합니다.
    • 예상 결과: InvalidOperationException 발생 (메시지에 "Upstage:Model" 포함)
  • Given_Valid_Settings_When_EnsureLanguageModelSettingsValid_Invoked_Then_It_Should_Return_True

    • 목적: 모든 설정이 유효할 때 정상 동작을 확인합니다.
    • 예상 결과: true 반환

3. GetChatClientAsync() 테스트 (5개)

  • Given_Valid_Settings_When_GetChatClient_Invoked_Then_It_Should_Return_ChatClient

    • 목적: 유효한 설정으로 ChatClient 생성을 확인합니다.
    • 예상 결과: ChatClient 객체가 null이 아님
  • Given_Settings_Is_Null_When_GetChatClientAsync_Invoked_Then_It_Should_Throw

    • 목적: Upstage 설정이 null일 때 예외 발생을 확인합니다.
    • 예상 결과: NullReferenceException 발생
  • Given_Missing_ApiKey_When_GetChatClient_Invoked_Then_It_Should_Throw

    • 목적: ApiKey 누락 시 OpenAI SDK 예외 발생을 확인합니다.
    • 예상 결과:
      • nullInvalidOperationException (메시지에 "Upstage:ApiKey" 포함)
      • ""ArgumentException (메시지에 "key" 포함)
  • Given_Missing_BaseUrl_When_GetChatClient_Invoked_Then_It_Should_Throw

    • 목적: BaseUrl 누락 시 URI 관련 예외 발생을 확인합니다.
    • 예상 결과:
      • nullInvalidOperationException (메시지에 "Upstage:BaseUrl" 포함)
      • ""UriFormatException (메시지에 "empty" 포함)
  • Given_Missing_Model_When_GetChatClient_Invoked_Then_It_Should_Throw

    • 목적: Model 누락 시 OpenAI SDK 예외 발생을 확인합니다.
    • 예상 결과:
      • nullArgumentNullException (메시지에 "model" 포함)
      • ""ArgumentException (메시지에 "model" 포함)

4. CreateChatClientAsync() 테스트 (2개)

  • Given_Valid_Settings_When_CreateChatClientAsync_Invoked_Then_It_Should_Return_ChatClient

    • 테스트 메서드: LanguageModelConnector.CreateChatClientAsync()
    • 목적: 팩토리 메서드로 정상적인 ChatClient 생성을 확인합니다.
    • 예상 결과: ChatClient 객체가 null이 아님
  • Given_Invalid_Settings_When_CreateChatClientAsync_Invoked_Then_It_Should_Throw

    • 테스트 메서드: LanguageModelConnector.CreateChatClientAsync()
    • 목적: 잘못된 설정(ApiKey = null)일 때 예외 발생을 확인합니다.
    • 예상 결과: InvalidOperationException 발생 (메시지에 "Upstage:ApiKey" 포함)

Copy link
Contributor

@sikutisa sikutisa left a comment

Choose a reason for hiding this comment

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

같은 메소드에 대한 테스트끼리 모아 놓는 게 좋을 것 같습니다.
올려주신 댓글 순서대로 맞춰도 될 것 같은데요?

…lity

- Group GetChatClient related tests together in logical sections
- Maintain all existing test functionality and coverage
- Improve test file structure and maintainability
- No changes to test logic or assertions
- Convert single Fact test to Theory with multiple test cases
- Add comprehensive validation for all required settings: ApiKey, BaseUrl, Model
- Test null value handling for each parameter individually
- Ensure proper InvalidOperationException thrown with specific error messages
- Improve test coverage from 1 to 3 validation scenarios

Changes:
- Replace Given_Invalid_Settings_When_CreateChatClientAsync_Invoked_Then_It_Should_Throw Fact with Theory
- Add InlineData for apiKey, baseUrl, and model null validation
- Use switch expression for dynamic AppSettings creation
- Verify exception type and message content for each case
…attern

- Update exception message validation to match OpenAI connector format
- Change "Upstage" to "Missing configuration: Upstage." for EnsureLanguageModelSettingsValid
- Add specific message validation "Missing configuration: Upstage:ApiKey." for GetChatClientAsync null settings
- Improve consistency across connector error messages
- Enhance test robustness by validating both exception type and specific message content

Benefits:
- Consistent error message format across all connectors
- More descriptive error messages for better debugging
- Follows established OpenAI connector pattern
- Better test coverage with message content validation
…entAsync

- Expand test coverage from 3 to 12 test cases for CreateChatClientAsync validation
- Add empty string ("") validation for all parameters (apiKey, baseUrl, model)
- Add whitespace validation ("   ") for all parameters
- Add mixed whitespace validation ("\t\n\r") for all parameters
- Ensure robust handling of null, empty, and whitespace-only values
- Maintain consistent InvalidOperationException with specific error messages

Enhanced test scenarios:
- apiKey: null, "", "   ", "\t\n\r" → InvalidOperationException: "Upstage:ApiKey"
- baseUrl: null, "", "   ", "\t\n\r" → InvalidOperationException: "Upstage:BaseUrl"
- model: null, "", "   ", "\t\n\r" → InvalidOperationException: "Upstage:Model"

Benefits:
- Comprehensive validation coverage for all invalid input types
- Better protection against configuration errors in production
- Consistent with other connector validation patterns
- Change nullValue to invalidValue in CreateChatClientAsync test method
- Better reflects comprehensive test coverage including null, empty strings, and whitespace variations
- Improves code clarity and test intent documentation
Copy link
Contributor

@sikutisa sikutisa left a comment

Choose a reason for hiding this comment

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

이제 Bicep 작업 시작하시면 될 것 같습니다!

- Add Upstage parameters to main.bicep (upstageModel, upstageBaseUrl, upstageApiKey)
- Add Upstage parameter mappings to main.parameters.json
- Add Upstage environment variables and secrets configuration in resources.bicep
  - Create envUpstage variable with conditional environment variable injection
  - Add upstage-api-key to secrets array for secure API key management
  - Include envUpstage in container environment variables
- Fix parameter name typo in main.parameters.json (":upstageModel" -> "upstageModel")

This enables Azure Container Apps deployment with Upstage AI service integration
through secure environment variable injection and secret management.
@gremh97
Copy link
Contributor Author

gremh97 commented Oct 10, 2025

이제 Bicep 작업 시작하시면 될 것 같습니다!

Azure 테스트는 보통 어디까지 진행하나요?

@sikutisa
Copy link
Contributor

Azure 테스트는 보통 어디까지 진행하나요?

Connector랑 Bicep이 완성됐으니, Azure에 배포되고 Upstage Connector 사용해서 앱이 동작하는 것 까지 확인하면 될 것 같습니다.

@gremh97
Copy link
Contributor Author

gremh97 commented Oct 10, 2025

Azure 테스트는 보통 어디까지 진행하나요?

Connector랑 Bicep이 완성됐으니, Azure에 배포되고 Upstage Connector 사용해서 앱이 동작하는 것 까지 확인하면 될 것 같습니다.

혹시 . bicep 파일에 아래 변수들이 사용되지 않는데 왜 있는건가요??

description('Id of the user or app to assign application roles')
param principalId string

@description('Principal type of user or app')
param principalType string

@gremh97
Copy link
Contributor Author

gremh97 commented Oct 10, 2025

image

확인했습니다....... 🫠 배포 너무 험난했어요 ㅠㅠㅠ

@sikutisa
Copy link
Contributor

확인했습니다....... 🫠 배포 너무 험난했어요 ㅠㅠㅠ

어우 고생하셨습니다! 이제 문서만 하시면... 💪

- Add docs/upstage.md with complete integration guide for Upstage Solar models
  - Local machine setup with dotnet user-secrets configuration
  - Container deployment with Docker build and run instructions
  - Azure deployment using azd with environment variable management
  - Support for solar-1-mini-chat (default) and solar-pro models
  - Step-by-step instructions for all deployment scenarios

- Update docs/README.md to include Upstage connector in supported integrations
  - Add Upstage to the list of available AI service connectors
  - Maintain consistency with existing documentation structure

- Implement secure API key management:
  - Local development: dotnet user-secrets for safe credential storage
  - Azure deployment: azd environment variables with Container Apps secrets
  - Container deployment: command-line parameter injection

- Support multiple deployment environments:
  - Development: http://localhost:5280
  - Container: http://localhost:8080
  - Azure: Container Apps with auto-generated FQDN

This completes the Upstage Solar LLM connector implementation with
comprehensive documentation following project standards and best practices.
@gremh97
Copy link
Contributor Author

gremh97 commented Oct 13, 2025

확인했습니다....... 🫠 배포 너무 험난했어요 ㅠㅠㅠ

어우 고생하셨습니다! 이제 문서만 하시면... 💪

혹시 더 수정할게 있는걸까요?

@sikutisa
Copy link
Contributor

혹시 더 수정할게 있는걸까요?

리뷰하고 코멘트 드리겠습니다!

Copy link
Contributor

@sikutisa sikutisa left a comment

Choose a reason for hiding this comment

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

  1. 얘도 수정해야 하지 않을까요?
    https://github.com/aliencube/open-chat-playground/blob/main/README.md
  2. 문서 작업만 하신 건가요? 아님 작성한 내용대로 직접 실행까지 해보셨나요?

docs/upstage.md Outdated
Comment on lines 57 to 71
Alternatively, if you want to run with a different model, say [solar-pro](https://developers.upstage.ai/docs/apis/chat), other than the default one, you can specify it as an argument:

```bash
# bash/zsh
dotnet run --project $REPOSITORY_ROOT/src/OpenChat.PlaygroundApp -- \
--connector-type Upstage \
--model solar-pro
```

```powershell
# PowerShell
dotnet run --project $REPOSITORY_ROOT/src/OpenChat.PlaygroundApp -- `
--connector-type Upstage `
--model solar-pro
```
Copy link
Contributor

Choose a reason for hiding this comment

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

주어진 링크로 들어가면 solar-pro-2에 대한 내용 밖에 확인이 안 됩니다.
링크를 아래 링크로 걸거나 아니면 내용을 수정하는 게 나을 것 같습니다.
https://console.upstage.ai/docs/models/history#solar-pro-250422

Copy link
Contributor Author

Choose a reason for hiding this comment

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

image 그대로 복붙해서 실행하면 위의 이미지처럼 나오기는하는데 공식문서대로 2를 붙이는게 낫겠죠...

Copy link
Contributor

Choose a reason for hiding this comment

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

넵. 그게 나을 것 같습니다.

docs/upstage.md Outdated
1. Set the connector type to `Upstage`.

```bash
azd env set CONNECTOR_TYPE Upstage
Copy link
Contributor

Choose a reason for hiding this comment

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

얘도 "Upstage"가 아니라 Upstage가 맞나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

둘다가능합니다. 특수문자나 공백이 있으면 따옴표로 감싸줘야하는데 아니면 둘다 되더라고요... 일단 다른 커넥터 문서와 일관성을 위해 추가하겠습니다.

…rences

- Update model references from solar-1-mini-chat to solar-mini for consistency
- Change alternative model example from solar-pro to solar-pro2
- Update API documentation links to point to official Upstage console docs
- Standardize model URLs to use console.upstage.ai instead of developers.upstage.ai
- Add proper quotes to azd environment variable commands for consistency
- Improve model name consistency across all deployment scenarios (local/container/Azure)

This ensures the documentation reflects the current Upstage Solar model names
and provides accurate links to official documentation and model specifications.
- Update Upstage checkbox from [ ] to [x] in supported integrations list
- Reflects successful implementation and documentation of Upstage Solar LLM connector
- Connector now supports local development, container deployment, and Azure deployment
@gremh97
Copy link
Contributor Author

gremh97 commented Oct 13, 2025

  1. 얘도 수정해야 하지 않을까요?
    https://github.com/aliencube/open-chat-playground/blob/main/README.md

수정했습니다

  1. 문서 작업만 하신 건가요? 아님 작성한 내용대로 직접 실행까지 해보셨나요?

전체적으로 복붙해서 돌려보긴 했는데 주소는 눌러보고 대충 모델이 있어서 저렇게 된 것 같습니다

@gremh97
Copy link
Contributor Author

gremh97 commented Oct 13, 2025

PR에

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:

이부분 문서 변경부분도 체크할까요? 뭔가 나눠져야할거 같은데 한곳에서 하게 되네여

@sikutisa
Copy link
Contributor

이부분 문서 변경부분도 체크할까요? 뭔가 나눠져야할거 같은데 한곳에서 하게 되네여

굳이 체크할 필요는 없을 것 같아요.

@sikutisa sikutisa self-requested a review October 14, 2025 15:48
Copy link
Contributor

@sikutisa sikutisa left a comment

Choose a reason for hiding this comment

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

수고하셨습니다!

@sikutisa sikutisa merged commit d528bd1 into aliencube:main Oct 14, 2025
1 check passed
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: Upstage Solar

2 participants