[Test] 로컬 테스트 진행을 위한 LLMClient 클래스 구현 및 README 파일의 LocalStack 사용법 업데이트#28
[Test] 로컬 테스트 진행을 위한 LLMClient 클래스 구현 및 README 파일의 LocalStack 사용법 업데이트#28
Conversation
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 모델 스위치 테스트
There was a problem hiding this comment.
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
LLMClientclass to abstract LLM provider differences (Gemini vs Bedrock Claude) - Updated
tos_summarize()andtos_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.
| json_text = response[start:end] | ||
|
|
There was a problem hiding this comment.
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.
| 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] |
|
|
||
| def tos_evaluate(summarized_tos): | ||
| system_instruction=[{"text": """ | ||
| def tos_evaluate(summarized_tos, client: LLMClient) -> dict: |
There was a problem hiding this comment.
The summarized_tos parameter is missing a type hint. For consistency with the client parameter, add a type hint (likely str based on usage).
| def tos_evaluate(summarized_tos, client: LLMClient) -> dict: | |
| def tos_evaluate(summarized_tos: str, client: LLMClient) -> dict: |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
junhanjeong
left a comment
There was a problem hiding this comment.
코드 확인했습니다.
그런데, 제가 직접 실행해봤는데 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 호환성을 고려하여 람다함수 생성 시 환경변수 설정에 큰따옴표 대신 작은따옴표를 사용합니다.
관련 이슈
작업사항
LLMClient클래스를 구현했습니다. client 생성 시temperature: float,top_p: float, 응답 요청 시system_instruction: str,message: str값을 설정할 수 있습니다.tos_summarize(),tos_evaluate()메서드가 해당 클래스를 사용하도록 변경하였습니다.lambda_handler()메서드에서client를 생성하고 각 함수에 넘겨주는 방식으로 변경되었습니다.기타
반드시 README에 따라 테스트를 수행해 잘 진행되는지 확인 부탁드립니다.
LLMClient의 Bedrock 호출부 수정은 여전히 로컬에서는 테스트가 불가능합니다. 가능하면 해당 부분을 변경하기보다는 텍스트를 일정한 형식(json 등)으로 받아와서 처리하는 방식을 사용해주세요.