LLM 에이전트의 불확실한 응답 품질을 자동화된 파이프라인으로 검증하고 관리합니다.
LLM 에이전트 개발은 일반적인 백엔드 개발과 다릅니다. 프롬프트 한 줄, 소스코드 한 줄의 수정이 수백 개의 테스트 케이스에 어떤 영향을 줄지 예측하기 어렵습니다. 이 프로젝트는 "딱 떨어지지 않는 LLM 응답"을 효율적으로 검증하기 위해 시작되었습니다. 매일 반복되는 수동 테스트와 번역 작업을 자동화하여, 개발자가 본질적인 제품의 가치에 집중할 수 있도록 돕습니다.
- Multi-Environment Support: Local부터 Production까지 다양한 환경의 API를 한 번에 테스트합니다.
- AI-Driven Judge: Google Gemini API 또는 로컬 LLM(Ollama/Gemma2)을 활용하여 응답의 적절성을 자동으로 판독합니다.
- Auto Translation: Google Sheets의
=GOOGLETRANSLATE를 활용하여 베트남어 등 외국어 응답을 실시간으로 번역하여 확인합니다. - Slack Integration: 테스트 완료 후 성공/실패 여부를 슬랙으로 즉시 알림 받아 리얼타임 피드백 루프를 형성합니다.
- Universal Framework: 날씨, 음악, 일정 등 모든 도메인의 에이전트 테스트에 적용 가능한 범용적인 구조를 제공합니다.
- 검증 리소스 95.8% 절감: 기존 8시간 소요되던 전수 검사를 20분 내외(검토 시간 기준)로 단축.
- 품질 안정성 확보: 수백 개의 케이스를 상시 검증하여 공식 시연 및 UAT 리스크 최소화.
- Node.js (Jest)
- Ollama (Local LLM 사용 시)
- Google Cloud Platform (Google Sheets API 사용 시)
프로젝트 루트에 .env 파일을 생성하고 아래 형식을 참고하여 설정.
(보안을 위해 .env 파일은 절대 Git에 커밋 금지!)
CONTROL_BASE_URL="" # fallback for legacy commands
X_API_KEY=""
AI_API_KEY=""
AI_MODEL="gemini-3-flash-preview"
GOOGLE_SERVICE_ACCOUNT_EMAIL=""
GOOGLE_SHEET_ID=""
# Optional fallback for legacy commands
GOOGLE_SHEET_NAME=""
# Optional: override the profile config file path
TEST_PROFILE_CONFIG="tests/config/profiles.yaml"
GOOGLE_PRIVATE_KEY=""
ACCOUNT_ID=""
AGENT_VERSION=""
DEVICE_ID=""
OS_APP_TYPE=""
OS_APP_VERSION=""
ACCEPT_LANGUAGE=""
TRACE_ID=""
LANGUAGE=""
TEST_TIMEOUT="120000"
# [Service Delay]
SERVICE_DELAY_SEC=1
# [Judge Delay]
# for Gemini API
DELAY_API=12
# for local Ollama
DELAY_LOCAL=0
LOCAL_AI_MODEL='gemma2:27b'
LOCAL_AI_TEMPERATURE=0.1 # 일관된 판정을 위해 낮게 설정
LOCAL_AI_MAX_TOKEN=200 # 답변이 너무 길어지지 않게 제한
GOOGLETRANSLATE_SOURCE_LANGUAGE="auto"
GOOGLETRANSLATE_TARGET_LANGUAGE="en"
RESPONSE_TRANSLATION_PROVIDER="googletranslate" # googletranslate | gpt
# Required only when RESPONSE_TRANSLATION_PROVIDER=gpt
RESPONSE_TRANSLATION_LLM_ID=""
RESPONSE_TRANSLATION_MAX_TOKEN=1000
RESPONSE_TRANSLATION_PROMPT_FILE="prompt.translate.yaml"
# GPT translation reads Redis config:llm:<RESPONSE_TRANSLATION_LLM_ID> using REDIS_URL below.
# Redis stream answer compare watcher
REDIS_URL="redis://127.0.0.1:6379"
WEATHER_ANSWER_COMPARE_STREAM_KEY="weather:answer-compare"
WEATHER_ANSWER_COMPARE_STREAM_GROUP="weather-answer-compare"
WEATHER_ANSWER_COMPARE_STREAM_CONSUMER="watcher-1"
READ_EXISTING_PAYLOADS=0
STREAM_BLOCK_MS=5000
PENDING_RETRY_INTERVAL_MS=30000
GEMMA_TEST_LLM_ID=2
GEMMA_TEST_MODEL="mediaai1/gemma-27b-generation-v3.0.0"
GPT_TEST_LLM_ID=3
OLLAMA_URL="http://localhost:11434/v1/chat/completions"
OLLAMA_MODEL="gemma3:27b"
GOOGLE_SHEET_TAB="WeatherAnswerCompare"
# Slack Settings
SLACK_WEBHOOK_URL=""
SLACK_CHANNEL=""-
Google Sheets API Key
https://console.cloud.google.com/welcome/new
Enable Google Sheets API
Credentials 탭 클릭 → Create Credentials → Service Account Service Accounts→ Keys→ Create private key→ Json 다운로드된 JSON 파일에서
client_email→ Service Account 이메일private_key→ Private Key
이 두 개를
.env에 세팅GOOGLE_SERVICE_ACCOUNT_EMAIL="" GOOGLE_PRIVATE_KEY=""
-
Google Sheets ID
google docs로 파일을 만든 후
주소를 복사하여
https://docs.google.com/spreadsheets/d/ + GOOGLE_SHEET_ID + /edit?gid=0#gid=0
이 구조로 되어있으니 GOOGLE_SHEET_ID를 추출하고 .env에 설정
GOOGLE_SHEET_ID="" GOOGLE_SHEET_NAME="" # legacy fallback TEST_PROFILE_CONFIG="tests/config/settings/profiles.yaml"
GOOGLE_SHEET_NAME은 결과를 기록할 스프레드시트 탭 이름입니다. 프로필을 지정하지 않고 실행할 때만 이 값을 사용합니다. 해당 탭이 없으면 테스트 실행 중 자동으로 생성됩니다.프로필 실행은
tests/config/settings/profiles.yaml에서 읽습니다. 새 환경은 YAML에 추가만 하면 되고,crow같은 이름도 코드 수정 없이 바로 사용할 수 있습니다. -
Gemini
https://ai.google.dev/gemini-api/docs/models 여기 가서 모델 고르기
.env에 설정
AI_MODEL="gemini-3-flash-preview"
-
Ollama
- Ollama 공식 홈페이지에서 다운로드 후 설치
- 모델 고르기
- 다운받기
ollama pull gemma2:9b
- .env 설정
LOCAL_AI_MODEL='gemma2:27b'
Wrap sheet config: tests/config/settings/sheet.yaml
어떤 column을 wrap 허용할지 설정(Google Sheet에서)
wrapColumns:
- E
- FProfile config: tests/config/settings/profiles.yaml
profiles:
prod:
baseUrl: https://prod.com/api
sheetName: prod
stg:
baseUrl: https://stg.com/api
sheetName: stgnpm install
npm run test:sheet:api:dev
npm run test:sheet:internal:stg
npm run test:sheet:local:local
npm run test:terminal:prod
node scripts/run-test-profile.js sheet:api:crowRedis stream answer compare watcher
npm run watch:weather:answer-compare
REPORT_TO=sheet npm run watch:weather:answer-compare
READ_EXISTING_PAYLOADS=1 npm run watch:weather:answer-compare이 watcher는 WEATHER_ANSWER_COMPARE_STREAM_KEY stream의 payload 필드(JSON)를 읽어서 GemmaProd, Ollama, GPT 세 모델 응답을 비교하고 terminal 또는 Google Sheet에 기록합니다.
Legacy-compatible selectors
"test:all": "node --experimental-vm-modules node_modules/jest/bin/jest.js tests/runner --config jest.config.ts",
"test:profile": "node scripts/run-test-profile.js",
"test:sheet:none": "node scripts/run-test-profile.js",
"test:sheet:api:dev": "node scripts/run-test-profile.js",
"test:sheet:local:local": "node scripts/run-test-profile.js",
"test:terminal:prod": "node scripts/run-test-profile.js",
"test:terminal:ai:crow": "node scripts/run-test-profile.js"기존 npm run test:sheet:api -- --dev 같은 -- 방식도 그대로 지원합니다.
나의 구글 시트에 들어가보면 다음과같이 잘 정리된 테스트 케이스들이 있고 나는 Fail인 것만 검토를 하면 됩니다.

- Jest/Axios: 설정된 환경별로 테스트 케이스(JSON) 기반 API 호출 수행.
- Local AI (Gemma2): 수집된 응답 데이터가 질문 의도에 부합하는지 1차 판독.
- Google Sheet: 결과를 시트로 전송하여 자동 번역 및 시각화 수행.
- Slack Webhook: 전체 리포트 요약을 개발자에게 전송.
이 프로젝트는 더 효율적인 AI 에이전트 개발 문화를 지향합니다. 버그 리포트나 기능 제안은 언제나 환영합니다!
