Skip to content

[Test] 로컬 테스트 진행을 위한 LLMClient 클래스 구현 및 README 파일의 LocalStack 사용법 업데이트#28

Merged
hjham0856 merged 13 commits intomainfrom
test-deploy
Nov 25, 2025
Merged

[Test] 로컬 테스트 진행을 위한 LLMClient 클래스 구현 및 README 파일의 LocalStack 사용법 업데이트#28
hjham0856 merged 13 commits intomainfrom
test-deploy

Conversation

@hjham0856
Copy link
Copy Markdown
Collaborator

관련 이슈

작업사항

  • LocalStack을 사용하여 AWS Lambda, S3, DynamoDB 등의 기능을 로컬에서 테스트하는 과정을 README에 업데이트했습니다.
  • Bedrock 서비스는 로컬에서 사용 불가능하여, 임시로 Gemini를 호출하도록 변경했습니다. 로컬 환경인 경우에만 Gemini를 호출하며, 아닌 경우 bedrock을 호출합니다.
    • 위 기능 구현을 위한 LLMClient 클래스를 구현했습니다. client 생성 시 temperature: float, top_p: float, 응답 요청 시 system_instruction: str, message: str 값을 설정할 수 있습니다.
    • tos_summarize(), tos_evaluate() 메서드가 해당 클래스를 사용하도록 변경하였습니다.
    • lambda_handler() 메서드에서 client를 생성하고 각 함수에 넘겨주는 방식으로 변경되었습니다.
  • 속도 향상을 위해 Claude 모델이 Sonnet 4.5에서 3.5 Haiku로 변경되었습니다.

기타

반드시 README에 따라 테스트를 수행해 잘 진행되는지 확인 부탁드립니다.

LLMClient의 Bedrock 호출부 수정은 여전히 로컬에서는 테스트가 불가능합니다. 가능하면 해당 부분을 변경하기보다는 텍스트를 일정한 형식(json 등)으로 받아와서 처리하는 방식을 사용해주세요.

hjham0856 and others added 11 commits November 18, 2025 20:00
bedrock으로 전환하며 gemini를 제거했으나, 로컬 테스트 환경에서는 key 발급이 불가능해 bedrock 사용이 어려워 로컬 환경에서만큼은 gemini로 대체합니다.
LLM_PROVIDER 환경 변수의 값이 GEMINI이면 gemini를, 아닌 경우 bedrock에서 claude를 호출합니다.
claude의 경우 기존 sonnet 4.5가 속도가 다소 느려 3.5 haiku로 모델을 변경하였습니다.
이제 tos_summarize와 tos_evaluate 메서드가 직접 bedrock을 호출하지 않고 LLMClient를 통해 간접적으로 모델을 호출합니다.
client를 각 함수별로 초기화하지 않고, lambda_handler에서 만든 client를 받아서 사용합니다.
localstack, awscli-local은 실행용으로 설치하는 것이지 프로젝트에 포함되어야 할 모듈이 아닙니다.
로컬/aws llm 모델 스위치 테스트
@hjham0856 hjham0856 requested a review from Copilot November 21, 2025 07:44
@hjham0856 hjham0856 self-assigned this Nov 21, 2025
@hjham0856 hjham0856 added documentation Improvements or additions to documentation enhancement New feature or request labels Nov 21, 2025
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements local testing support using LocalStack and introduces an LLMClient abstraction layer to switch between Gemini (for local testing) and AWS Bedrock Claude (for production). The implementation eliminates direct Bedrock dependencies from business logic functions and updates the README with comprehensive LocalStack setup and usage instructions.

  • Introduced LLMClient class to abstract LLM provider differences (Gemini vs Bedrock Claude)
  • Updated tos_summarize() and tos_evaluate() to accept a client parameter and use the new abstraction
  • Changed Claude model from Sonnet 4.5 to 3.5 Haiku for improved speed

Reviewed Changes

Copilot reviewed 6 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/llm_client.py New abstraction class for LLM clients with environment-based provider selection
src/tos_summarize.py Refactored to use LLMClient instead of direct Bedrock calls
src/tos_evaluate.py Refactored to use LLMClient instead of direct Bedrock calls
src/lambda_function.py Creates LLMClient instance and passes it to processing functions
requirements.txt Added google-genai dependency for Gemini support
README.md Updated with comprehensive LocalStack setup and testing instructions
.gitignore Added build artifacts and test files to ignore list
src/test_local.py Removed old test file (entire file deleted)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/tos_evaluate.py
Comment on lines +51 to 52
json_text = response[start:end]

Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

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

If the response doesn't contain '{' or '}', find() returns -1, which would cause incorrect string slicing. Add validation to check if start is -1 before proceeding with slicing and JSON parsing.

Suggested change
json_text = response[start:end]
if start == -1 or end == 0 or end <= start:
raise ValueError("Response does not contain a valid JSON object: " + repr(response))
json_text = response[start:end]

Copilot uses AI. Check for mistakes.
Comment thread src/tos_summarize.py Outdated
Comment thread src/tos_evaluate.py

def tos_evaluate(summarized_tos):
system_instruction=[{"text": """
def tos_evaluate(summarized_tos, client: LLMClient) -> dict:
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

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

The summarized_tos parameter is missing a type hint. For consistency with the client parameter, add a type hint (likely str based on usage).

Suggested change
def tos_evaluate(summarized_tos, client: LLMClient) -> dict:
def tos_evaluate(summarized_tos: str, client: LLMClient) -> dict:

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Collaborator

@junhanjeong junhanjeong left a comment

Choose a reason for hiding this comment

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

코드 확인했습니다.
그런데, 제가 직접 실행해봤는데 Status code는 200이 뜨는데, 내부적으로 에러가 발생하는 것 같습니다. 제가 무엇을 잘못 했을까요?

터미널

(.venv) ➜  TermLens_BE git:(test-deploy) ✗ awslocal lambda invoke --function-name analyzeTermsOfServices \
    --payload '{"queryStringParameters": {"url" : "www.example.com"}, "body" : "약관 텍스트" }' output.json
{
    "StatusCode": 200,
    "FunctionError": "Unhandled",
    "ExecutedVersion": "$LATEST"
}

output.json

{"errorMessage": "An error occurred (InternalFailure) when calling the Converse operation: The API for service 'bedrock-runtime' is either not included in your current license plan or has not yet been emulated by LocalStack. Please refer to https://docs.localstack.cloud/references/coverage for more details.", "errorType": "ClientError", "requestId": "716ca2a8-c122-4343-8ae3-49f1d183373d", "stackTrace": ["  File \"/var/task/lambda_function.py\", line 44, in lambda_handler\n    summarized_tos = tos_summarize(tos_content)\n", "  File \"/var/task/tos_summarize.py\", line 23, in tos_summarize\n    response = client.converse(\n", "  File \"/var/task/botocore/client.py\", line 602, in _api_call\n    return self._make_api_call(operation_name, kwargs)\n", "  File \"/var/task/botocore/context.py\", line 123, in wrapper\n    return func(*args, **kwargs)\n", "  File \"/var/task/botocore/client.py\", line 1078, in _make_api_call\n    raise error_class(parsed_response, operation_name)\n"]}

GPT 피셜로는 lambda_function.py 또는 tos_summarize.py 내부 로직이 Bedrock client를 생성하고있어서라는데 한번 확인부탁드립니다.

arm환경에서 pip install로 설치하는 경우 arm용 바이너리가 설치되어, aws lambda와 동일하게 amd64 기반으로 작동하는 localstack에서 인식하지 못해 docker를 사용하여 amd64 환경을 현재 디렉토리에서 시뮬레이션하여 설치하도록 하는 명령어를 예시에 추가했습니다.
zsh 호환성을 고려하여 람다함수 생성 시 환경변수 설정에 큰따옴표 대신 작은따옴표를 사용합니다.
@hjham0856 hjham0856 merged commit 3dc3f02 into main Nov 25, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Test] 로컬 테스트 환경 구성

3 participants