152 lines
5.0 KiB
Python
152 lines
5.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
보고서(report) 처리 로직
|
|
- 다페이지 보고서
|
|
- 원본 구조 유지
|
|
- RAG 파이프라인 연동 (긴 문서)
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
from pathlib import Path
|
|
from flask import session
|
|
|
|
from handlers.common import call_claude, extract_html, load_prompt, client
|
|
from converters.pipeline.router import process_document, convert_image_paths
|
|
|
|
|
|
class ReportProcessor:
|
|
"""보고서 처리 클래스"""
|
|
|
|
def __init__(self):
|
|
self.prompts_dir = Path(__file__).parent / 'prompts'
|
|
|
|
def _load_prompt(self, filename: str) -> str:
|
|
"""프롬프트 로드"""
|
|
return load_prompt(str(self.prompts_dir), filename)
|
|
|
|
def generate(self, content: str, options: dict) -> dict:
|
|
"""보고서 생성"""
|
|
try:
|
|
if not content.strip():
|
|
return {'error': '내용이 비어있습니다.'}
|
|
|
|
# 이미지 경로 변환
|
|
processed_html = convert_image_paths(content)
|
|
|
|
# router를 통해 분량에 따라 파이프라인 분기
|
|
result = process_document(processed_html, options)
|
|
|
|
if result.get('success'):
|
|
session['original_html'] = content
|
|
session['current_html'] = result.get('html', '')
|
|
|
|
return result
|
|
|
|
except Exception as e:
|
|
import traceback
|
|
return {'error': str(e), 'trace': traceback.format_exc()}
|
|
|
|
def refine(self, feedback: str, current_html: str, original_html: str = '') -> dict:
|
|
"""피드백 반영"""
|
|
try:
|
|
if not feedback.strip():
|
|
return {'error': '피드백 내용을 입력해주세요.'}
|
|
|
|
if not current_html:
|
|
return {'error': '수정할 HTML이 없습니다.'}
|
|
|
|
refine_prompt = f"""당신은 HTML 보고서 수정 전문가입니다.
|
|
|
|
사용자의 피드백을 반영하여 현재 HTML을 수정합니다.
|
|
|
|
## 규칙
|
|
1. 피드백에서 언급된 부분만 정확히 수정
|
|
2. **페이지 구조(sheet, body-content, page-header 등)는 절대 변경하지 마세요**
|
|
3. 완전한 HTML 문서로 출력 (<!DOCTYPE html> ~ </html>)
|
|
4. 코드 블록(```) 없이 순수 HTML만 출력
|
|
|
|
## 현재 HTML
|
|
{current_html}
|
|
|
|
## 사용자 피드백
|
|
{feedback}
|
|
|
|
---
|
|
위 피드백을 반영하여 수정된 완전한 HTML을 출력하세요."""
|
|
|
|
response = call_claude("", refine_prompt, max_tokens=8000)
|
|
new_html = extract_html(response)
|
|
|
|
session['current_html'] = new_html
|
|
|
|
return {
|
|
'success': True,
|
|
'html': new_html
|
|
}
|
|
|
|
except Exception as e:
|
|
return {'error': str(e)}
|
|
|
|
def refine_selection(self, current_html: str, selected_text: str, user_request: str) -> dict:
|
|
"""선택된 부분만 수정 (보고서용 - 페이지 구조 보존)"""
|
|
try:
|
|
if not current_html or not selected_text or not user_request:
|
|
return {'error': '필수 데이터가 없습니다.'}
|
|
|
|
message = client.messages.create(
|
|
model="claude-sonnet-4-20250514",
|
|
max_tokens=8000,
|
|
messages=[{
|
|
"role": "user",
|
|
"content": f"""HTML 문서에서 지정된 부분만 수정해주세요.
|
|
|
|
## 전체 문서 (컨텍스트 파악용)
|
|
{current_html[:5000]}
|
|
|
|
## 수정 대상 텍스트
|
|
"{selected_text}"
|
|
|
|
## 수정 요청
|
|
{user_request}
|
|
|
|
## 규칙
|
|
1. **절대로 페이지 구조(sheet, body-content, page-header, page-footer)를 변경하지 마세요**
|
|
2. 선택된 텍스트만 수정하고, 주변 HTML 태그는 그대로 유지
|
|
3. 요청을 분석하여 수정 유형을 판단:
|
|
- TEXT: 텍스트 내용만 수정 (요약, 문장 변경, 단어 수정, 번역 등)
|
|
- STRUCTURE: HTML 구조 변경 필요 (표 생성, 박스 추가 등)
|
|
|
|
4. 반드시 다음 형식으로만 출력:
|
|
|
|
TYPE: (TEXT 또는 STRUCTURE)
|
|
CONTENT:
|
|
(수정된 내용만 - 선택된 텍스트의 수정본만)
|
|
|
|
5. TEXT인 경우: 순수 텍스트만 출력 (HTML 태그 없이, 선택된 텍스트의 수정본만)
|
|
6. STRUCTURE인 경우: 해당 요소만 출력 (전체 페이지 구조 X)
|
|
7. 개조식 문체 유지 (~임, ~함, ~필요)
|
|
"""
|
|
}]
|
|
)
|
|
|
|
result = message.content[0].text
|
|
result = result.replace('```html', '').replace('```', '').strip()
|
|
|
|
edit_type = 'TEXT'
|
|
content = result
|
|
|
|
if 'TYPE:' in result and 'CONTENT:' in result:
|
|
type_line = result.split('CONTENT:')[0]
|
|
if 'STRUCTURE' in type_line:
|
|
edit_type = 'STRUCTURE'
|
|
content = result.split('CONTENT:')[1].strip()
|
|
|
|
return {
|
|
'success': True,
|
|
'type': edit_type,
|
|
'html': content
|
|
}
|
|
|
|
except Exception as e:
|
|
return {'error': str(e)} |