139 lines
4.0 KiB
Python
139 lines
4.0 KiB
Python
# -*- 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 |