# -*- 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()