Upload report/processor.py with corrected encoding/content
This commit is contained in:
159
03.Code/geulbeot_업로드용/handlers/report/processor.py
Normal file
159
03.Code/geulbeot_업로드용/handlers/report/processor.py
Normal file
@@ -0,0 +1,159 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
리포트(report) 처리기
|
||||
- 보고서 생성
|
||||
- 이미지 경로 변환
|
||||
"""
|
||||
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': '콘텐츠가 없습니다.'}
|
||||
|
||||
# 템플릿 스타일 로드
|
||||
template_id = options.get('template_id')
|
||||
if template_id:
|
||||
from handlers.template import TemplateProcessor
|
||||
template_processor = TemplateProcessor()
|
||||
style = template_processor.get_style(template_id)
|
||||
if style and style.get('css'):
|
||||
options['template_css'] = style['css']
|
||||
|
||||
# 이미지 경로 변환
|
||||
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-3-5-sonnet-20240620",
|
||||
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)}
|
||||
Reference in New Issue
Block a user