# -*- coding: utf-8 -*- """ router.py 기능: - HTML 입력의 분량을 판단하여 적절한 파이프라인으로 분기 - 긴 문서 (5000자 이상): RAG 파이프라인 (step3→4→5→6→7→8→9) - 짧은 문서 (5000자 미만): 직접 생성 (step7→8→9) """ import re import os from typing import Dict, Any # 분량 판단 기준 LONG_DOC_THRESHOLD = 5000 # 5000자 이상이면 긴 문서 # 이미지 assets 경로 (개발용 고정) - r prefix 필수! ASSETS_BASE_PATH = r"D:\for python\geulbeot-light\geulbeot-light\output\assets" def count_characters(html_content: str) -> int: """HTML 태그 제외한 순수 텍스트 글자 수 계산""" # HTML 태그 제거 text_only = re.sub(r'<[^>]+>', '', html_content) # 공백 정리 text_only = ' '.join(text_only.split()) return len(text_only) def is_long_document(html_content: str) -> bool: """긴 문서 여부 판단""" char_count = count_characters(html_content) return char_count >= LONG_DOC_THRESHOLD def convert_image_paths(html_content: str) -> str: """ HTML 내 상대 이미지 경로를 서버 경로로 변환 assets/xxx.png → /assets/xxx.png """ result = re.sub(r'src="assets/', 'src="/assets/', html_content) return result def replace_src(match): original_path = match.group(1) # 이미 절대 경로이거나 URL이면 그대로 if original_path.startswith(('http://', 'https://', 'file://', 'D:', 'C:')): return match.group(0) # assets/로 시작하면 절대 경로로 변환 if original_path.startswith('assets/'): filename = original_path.replace('assets/', '') absolute_path = os.path.join(ASSETS_BASE_PATH, filename) return f'src="{absolute_path}"' return match.group(0) # src="..." 패턴 찾아서 변환 result = re.sub(r'src="([^"]+)"', replace_src, html_content) return result def run_short_pipeline(html_content: str, options: dict) -> Dict[str, Any]: """ 짧은 문서 파이프라인 (5000자 미만) """ try: # 이미지 경로 변환 processed_html = convert_image_paths(html_content) # TODO: step7, step8, step9 연동 return { 'success': True, 'pipeline': 'short', 'char_count': count_characters(html_content), 'html': processed_html } except Exception as e: return { 'success': False, 'error': str(e), 'pipeline': 'short' } def run_long_pipeline(html_content: str, options: dict) -> Dict[str, Any]: """ 긴 문서 파이프라인 (5000자 이상) """ try: # 이미지 경로 변환 processed_html = convert_image_paths(html_content) # TODO: step3~9 순차 실행 return { 'success': True, 'pipeline': 'long', 'char_count': count_characters(html_content), 'html': processed_html } except Exception as e: return { 'success': False, 'error': str(e), 'pipeline': 'long' } def process_document(content: str, options: dict = None) -> Dict[str, Any]: """ 메인 라우터 함수 - 분량에 따라 적절한 파이프라인으로 분기 Args: content: HTML 문자열 options: 추가 옵션 (page_option, instruction 등) Returns: {'success': bool, 'html': str, 'pipeline': str, ...} """ if options is None: options = {} if not content or not content.strip(): return { 'success': False, 'error': '내용이 비어있습니다.' } char_count = count_characters(content) if is_long_document(content): result = run_long_pipeline(content, options) else: result = run_short_pipeline(content, options) # 공통 정보 추가 result['char_count'] = char_count result['threshold'] = LONG_DOC_THRESHOLD return result