IMG_Worker/modules/test_openrouter_dual_model.py

434 lines
15 KiB
Python

# -*- coding: utf-8 -*-
"""
OpenRouter 클라이언트 이중 모델 테스트 스크립트
직역과 마케팅 변환에 각각 다른 모델을 사용할 수 있는 테스트 코드
사용법:
python modules/test_openrouter_dual_model.py
환경변수 설정:
export OPENROUTER_API_KEY="sk-or-v1-xxxxx"
또는 코드에서 직접 설정
"""
import os
import sys
import time
import logging
from typing import List, Dict, Any, Optional
from dataclasses import dataclass
# 로깅 설정
logging.basicConfig(
level=logging.INFO,
format='[%(asctime)s] [%(levelname)s] %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)
# 모듈 경로 추가
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from modules.openrouter_client import OpenRouterTranslator
# =============================================================================
# 로그에서 추출한 샘플 OCR 데이터
# =============================================================================
# 샘플 1: 이미지 35 (7개 텍스트, 모두 중국어)
SAMPLE_1: List[Dict[str, Any]] = [
{'text': '高密【拉毛布】', 'confidence': 0.8697245717048645},
{'text': '柔中带韧不易坏', 'confidence': 0.9874316453933716},
{'text': '安静无声助力深度睡眠', 'confidence': 0.9960897564888},
{'text': 'newpet家的', 'confidence': 0.9988763928413391},
{'text': '别人家的', 'confidence': 0.9997605085372925},
{'text': '密织拉毛布保暖还结实', 'confidence': 0.9967950582504272},
{'text': '劣质无纺布一拉就烂一洗就散', 'confidence': 0.9917935729026794},
]
# 샘플 2: 이미지 37 (3개 텍스트, 모두 중국어)
SAMPLE_2: List[Dict[str, Any]] = [
{'text': '隐藏拉链不易咬', 'confidence': 0.9800551533699036},
{'text': '宠物更安全', 'confidence': 0.9966630935668945},
{'text': '隐藏式拉链+顺滑手感告别突元五金', 'confidence': 0.9670320749282837},
]
# =============================================================================
# 테스트 함수들
# =============================================================================
@dataclass
class DualModelTestResult:
"""이중 모델 테스트 결과 데이터 클래스"""
step1_model_id: str
step2_model_id: Optional[str]
elapsed_time: float
success: bool
step1_results: Optional[List[str]] = None
step2_results: Optional[List[str]] = None
error: Optional[str] = None
def print_separator(title: str = ""):
"""구분선 출력"""
print("\n" + "=" * 80)
if title:
print(f" {title}")
print("=" * 80)
print()
def test_dual_model_translation(
api_key: str,
step1_model_id: str,
step2_model_id: Optional[str],
ocr_results: List[Dict[str, Any]],
product_name: str = "테스트 상품",
category: str = "테스트 카테고리",
use_llm_translation: bool = True,
steps: int = 1
) -> DualModelTestResult:
"""
이중 모델을 사용한 번역 테스트
Args:
api_key: OpenRouter API 키
step1_model_id: Step 1 (직역)에 사용할 모델 ID
step2_model_id: Step 2 (마케팅톤 변환)에 사용할 모델 ID (None이면 step1과 동일)
ocr_results: OCR 결과 데이터
product_name: 상품명
category: 카테고리
use_llm_translation: True면 run_llm_translation 사용, False면 translate_ocr_texts 사용
steps: 번역 단계 (1=직역만, 2=직역+마케팅톤 변환)
Returns:
테스트 결과
"""
print_separator("이중 모델 번역 테스트")
print(f"Step 1 모델 (직역): {step1_model_id}")
if steps == 2:
step2_actual = step2_model_id or step1_model_id
print(f"Step 2 모델 (마케팅톤): {step2_actual}")
print(f"입력 텍스트 수: {len(ocr_results)}")
print(f"상품명: {product_name}")
print(f"카테고리: {category}")
print(f"사용 메서드: {'run_llm_translation' if use_llm_translation else 'translate_ocr_texts'}")
print(f"번역 단계: {steps} ({'직역만' if steps == 1 else '직역+마케팅톤 변환'})")
print()
start_time = time.time()
success = False
step1_results = None
step2_results = None
error_msg = None
try:
if not use_llm_translation:
# translate_ocr_texts 사용 (단일 모델)
translator = OpenRouterTranslator(
api_key=api_key,
model_id=step1_model_id,
timeout=10,
logger=logger
)
results = translator.translate_ocr_texts(
product_name=product_name,
category=category,
ocr_results=ocr_results
)
step1_results = results
step2_results = None
success = True
elif steps == 1:
# run_llm_translation, steps=1 (직역만)
translator = OpenRouterTranslator(
api_key=api_key,
model_id=step1_model_id,
timeout=10,
logger=logger
)
results = translator.run_llm_translation(
product_name=product_name,
category=category,
ocr_results=ocr_results,
steps=1
)
step1_results = results
step2_results = None
success = True
else:
# run_llm_translation, steps=2 (직역 + 마케팅톤 변환, 다른 모델 사용)
step2_actual = step2_model_id or step1_model_id
# Step 1: 직역
translator_step1 = OpenRouterTranslator(
api_key=api_key,
model_id=step1_model_id,
timeout=10,
logger=logger
)
print(f"[Step 1] 직역 시작 - 모델: {step1_model_id}")
step1_results = translator_step1.run_llm_translation(
product_name=product_name,
category=category,
ocr_results=ocr_results,
steps=1
)
print(f"[Step 1] 직역 완료")
print("Step 1 결과:")
for i, (original, translated) in enumerate(zip(ocr_results, step1_results), 1):
print(f" {i}. {original['text']}{translated}")
print()
# Step 2: 마케팅톤 변환 (Step 1 결과를 입력으로 사용)
if step2_actual != step1_model_id:
translator_step2 = OpenRouterTranslator(
api_key=api_key,
model_id=step2_actual,
timeout=10,
logger=logger
)
else:
translator_step2 = translator_step1
print(f"[Step 2] 마케팅톤 변환 시작 - 모델: {step2_actual}")
# Step 1 결과를 OCR 결과 형태로 변환
step1_ocr_results = [{"text": text} for text in step1_results]
step2_results = translator_step2.run_llm_translation(
product_name=product_name,
category=category,
ocr_results=step1_ocr_results,
steps=2
)
print(f"[Step 2] 마케팅톤 변환 완료")
print("Step 2 결과:")
for i, (step1_text, step2_text) in enumerate(zip(step1_results, step2_results), 1):
print(f" {i}. {step1_text}{step2_text}")
print()
success = True
elapsed_time = time.time() - start_time
print(f"✅ 성공 - 총 소요 시간: {elapsed_time:.2f}")
print()
print("최종 번역 결과:")
final_results = step2_results if step2_results else step1_results
for i, (original, translated) in enumerate(zip(ocr_results, final_results), 1):
print(f" {i}. {original['text']}{translated}")
except Exception as e:
elapsed_time = time.time() - start_time
error_msg = str(e)
print(f"❌ 실패 - 소요 시간: {elapsed_time:.2f}")
print(f"오류: {error_msg}")
import traceback
traceback.print_exc()
return DualModelTestResult(
step1_model_id=step1_model_id,
step2_model_id=step2_model_id or step1_model_id if steps == 2 else None,
elapsed_time=elapsed_time,
success=success,
step1_results=step1_results,
step2_results=step2_results,
error=error_msg
)
def test_combined_translation(
api_key: str,
model_id: str,
ocr_results: List[Dict[str, Any]],
product_name: str = "테스트 상품",
category: str = "테스트 카테고리"
) -> DualModelTestResult:
"""
통합 프롬프트를 사용한 번역 테스트 (한 번의 API 호출로 직역+마케팅톤 변환)
Args:
api_key: OpenRouter API 키
model_id: 사용할 모델 ID
ocr_results: OCR 결과 데이터
product_name: 상품명
category: 카테고리
Returns:
테스트 결과
"""
print_separator("통합 프롬프트 번역 테스트")
print(f"모델: {model_id}")
print(f"입력 텍스트 수: {len(ocr_results)}")
print(f"상품명: {product_name}")
print(f"카테고리: {category}")
print(f"사용 메서드: run_combined_llm_translation (직역+마케팅톤 변환 통합)")
print()
start_time = time.time()
success = False
results = None
error_msg = None
try:
translator = OpenRouterTranslator(
api_key=api_key,
model_id=model_id,
timeout=10,
logger=logger
)
print("번역 중...")
results = translator.run_combined_llm_translation(
product_name=product_name,
category=category,
ocr_results=ocr_results
)
success = True
elapsed_time = time.time() - start_time
print(f"✅ 성공 - 소요 시간: {elapsed_time:.2f}")
print("번역 결과:")
for i, (original, translated) in enumerate(zip(ocr_results, results), 1):
print(f" {i}. {original['text']}{translated}")
except Exception as e:
elapsed_time = time.time() - start_time
error_msg = str(e)
print(f"❌ 실패 - 소요 시간: {elapsed_time:.2f}")
print(f"오류: {error_msg}")
import traceback
traceback.print_exc()
return DualModelTestResult(
step1_model_id=model_id,
step2_model_id=None,
elapsed_time=elapsed_time,
success=success,
step1_results=results,
step2_results=None,
error=error_msg
)
def main():
"""메인 테스트 함수"""
print_separator("OpenRouter 이중 모델 테스트")
# =============================================================================
# 설정
# =============================================================================
API_KEY = os.getenv("OPENROUTER_API_KEY", "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")
# 테스트 데이터
product_name = "NewPet 반려동물 House"
category = "반려동물용품"
test_sample = SAMPLE_1 # 또는 SAMPLE_2 등
# =============================================================================
# 테스트 설정
# =============================================================================
# 방법 선택
USE_LLM_TRANSLATION = True # True: run_llm_translation 사용, False: translate_ocr_texts 사용
STEPS = 2 # run_llm_translation 사용 시 번역 단계 (1=직역만, 2=직역+마케팅톤 변환)
# "xiaomi/mimo-v2-flash:free",
# "openai/gpt-oss-20b:deepinfra/fp4",
# "mistralai/devstral-2512:free",
# "mistralai/mistral-7b-instruct:free",
# "openai/gpt-oss-20b:gmicloud/fp4",
# "z-ai/glm-4.5-air:novita/bf16",
# "x-ai/grok-4.1-fast:xai",
# "deepseek/deepseek-v3.2:atlas-cloud/fp8",
# "openai/gpt-5-nano:azure",
# "google/gemma-3n-e4b-it:together",
# "google/gemma-3-4b-it:deepinfra/bf16",
# 추가 모델 ID를 여기에 추가하세요
# 모델 설정
STEP1_MODEL_ID = "qwen/qwen3-next-80b-a3b-instruct:gmicloud/fp8" # Step 1 (직역) 모델
STEP2_MODEL_ID = "qwen/qwen3-next-80b-a3b-instruct:gmicloud/fp8" # Step 2 (마케팅톤) 모델 (None이면 Step1과 동일)
# 통합 프롬프트 테스트용 모델 (선택사항)
USE_COMBINED = False # True면 통합 프롬프트 테스트도 실행
COMBINED_MODEL_ID = "google/gemma-3-4b-it:deepinfra/bf16" # 통합 프롬프트 테스트용 모델
# =============================================================================
# 테스트 실행
# =============================================================================
# 이중 모델 테스트
result = test_dual_model_translation(
api_key=API_KEY,
step1_model_id=STEP1_MODEL_ID,
step2_model_id=STEP2_MODEL_ID,
ocr_results=test_sample,
product_name=product_name,
category=category,
use_llm_translation=USE_LLM_TRANSLATION,
steps=STEPS
)
# 통합 프롬프트 테스트 (선택사항)
if USE_COMBINED:
print_separator("통합 프롬프트 테스트")
combined_result = test_combined_translation(
api_key=API_KEY,
model_id=COMBINED_MODEL_ID,
ocr_results=test_sample,
product_name=product_name,
category=category
)
# 결과 비교
if result.success and combined_result.success:
print_separator("결과 비교")
print("이중 모델 방식 vs 통합 프롬프트 방식")
print("-" * 80)
final_dual = result.step2_results if result.step2_results else result.step1_results
final_combined = combined_result.step1_results
differences = []
for i, (dual_text, combined_text) in enumerate(zip(final_dual, final_combined), 1):
if dual_text != combined_text:
differences.append(i)
print(f"차이 {len(differences)}: 항목 {i}")
print(f" 이중 모델: {dual_text}")
print(f" 통합 프롬프트: {combined_text}")
if not differences:
print("모든 번역 결과가 동일합니다.")
else:
print(f"{len(differences)}개 항목에서 차이 발견")
print()
print(f"이중 모델 소요 시간: {result.elapsed_time:.2f}")
print(f"통합 프롬프트 소요 시간: {combined_result.elapsed_time:.2f}")
print_separator("테스트 완료")
if __name__ == "__main__":
main()