2025년 1학기 산학협력프로젝트
LLM을 활용하여 통계 데이터를 분석하고, 분석 결과를 한글(HWPX) 보고서로 자동 생성하는 서비스입니다. 전북대학교 산학협력 프로젝트로 개발되었습니다.
- 통합 데이터 DB 기반 SQL 쿼리 생성 및 데이터 검색
- 사용자 데이터 파일(Excel, CSV) 업로드 및 자동 전처리
- 데이터 파일 미리보기 및 시각화
- LLM 기반 데이터 분석 및 챗봇 기능
- 분석 결과 기반 HWPX 한글보고서 자동 생성
- 그래프 자동 생성 및 보고서 삽입
┌─────────────────┐
│ User Input │ (질문, 파일 업로드, STT 텍스트)
└────────┬────────┘
│
v
┌─────────────────┐ ┌─────────────────┐
│ Streamlit App │ <-> │ Flask Server │
│ (Frontend UI) │ │ (Backend API) │
│ Port: 8501 │ │ Port: 5000 │
└────────┬────────┘ └────────┬────────┘
│ │
v v
┌─────────────────┐ ┌─────────────────┐
│ FastAPI Server │ │ LLM Agent │
│ (HWPX 생성) │ │ - Qwen3-14B │
│ Port: 5001 │ │ - GPT-4o-mini │
└────────┬────────┘ │ - KURE-v1 │
│ └─────────────────┘
v
┌─────────────────┐
│ HWPX 파일 생성 │
└─────────────────┘
- Frontend: Streamlit
- Backend: Flask, FastAPI
- LLM: Qwen3-14B (로컬), GPT-4o-mini (OpenAI)
- Embedding: KURE-v1
- Database: SQLite
- Container: Docker
HWPX는 한컴오피스의 XML 기반 문서 포맷으로, ZIP 압축 파일입니다:
hwpx_file/
├── mimetype # 파일 타입 정의
├── META-INF/
│ ├── container.xml
│ └── manifest.xml
├── Contents/
│ ├── content.hpf # 컨텐츠 매니페스트
│ ├── header.xml # 헤더 정보
│ └── section0.xml # 본문 내용
├── BinData/ # 이미지/그래프
├── settings.xml
└── version.xml
- 입력 데이터 검증: Pydantic 모델(
DocheongReport)로 검증 - 템플릿 복사:
hwpx_report/template/에서 템플릿 폴더를 임시 위치로 복사 - XML 조작:
lxml을 사용해section0.xml의 고정 섹션 내용 교체- 개요, 테스트현황, 주요이슈, 향후계획 (4개 섹션 고정)
- 이미지 등록: 그래프를
BinData/에 복사하고content.hpf매니페스트 업데이트 - ZIP 압축: mimetype은 STORED, 나머지는 DEFLATED로 압축
- 입력 데이터 검증: Pydantic 모델(
DynamicReport)로 검증 - 템플릿 복사: 동일
- XML 조작:
- 기존 모든 섹션 제거
- LLM이 결정한 섹션 헤더와 내용을 동적 생성
- 섹션 수/이름에 제한 없음
- 이미지 등록: 동일
- ZIP 압축: 동일
- 네임스페이스:
http://www.hancom.co.kr/hwpml/2011/paragraph replace_section(): 섹션 헤더를 찾아 기존 내용 제거 후 새 텍스트 삽입update_header_date(): 헤더의 날짜를 오늘 날짜로 업데이트register_images_to_content_hpf(): 이미지 파일을 매니페스트에 등록
| Method | Endpoint | 설명 |
|---|---|---|
| POST | /api/report/docheong |
고정 섹션 JSON으로 보고서 생성 |
| POST | /api/report/docheong-auto |
원시 텍스트 → 고정 섹션 자동 분류 |
| POST | /api/report/dynamic |
동적 섹션 JSON으로 보고서 생성 |
| POST | /api/report/dynamic-auto |
원시 텍스트 → LLM이 섹션 자유 구성 |
| GET | /api/download/{file_id} |
생성된 HWPX 파일 다운로드 |
| DELETE | /api/cleanup/{file_id} |
임시 파일 정리 |
| Method | Endpoint | 설명 |
|---|---|---|
| POST | /chat |
SSE 기반 채팅 및 SQL 분석 |
| POST | /upload |
파일 업로드 및 전처리 |
class DocheongReport(BaseModel):
title: str # 보고서 제목
overview: List[str] # 개요
test_status: List[str] # 테스트 현황
key_issues: List[str] # 주요이슈
followup: List[str] # 향후계획class DynamicSection(BaseModel):
header: str # 섹션 헤더 (예: "□ 사업 개요")
content: List[str] # bullet points
class DynamicReport(BaseModel):
title: str
sections: List[DynamicSection] # LLM이 자유롭게 구성LLM이 입력 내용에 따라 섹션 수와 이름을 동적으로 결정:
- 내용이 많으면 5-7개 섹션으로 세분화
- 내용이 간단하면 2-3개 섹션으로 간결하게
- 섹션 이름은 내용에 맞게 자유롭게 작성
각 리스트는 개조식 형태의 bullet point를 포함:
○ (항목명) 내용- 세부사항※ 비고
app/
├── streamlit_app.py # Frontend Streamlit UI
├── server.py # Backend Flask 서버
├── main.py # FastAPI HWPX 생성 서버
├── data/
│ ├── csv_data/ # 전처리된 데이터
│ ├── xlsx_data/ # 원본 데이터
│ ├── faiss/ # FAISS 인덱스
│ ├── graph/ # 생성된 그래프
│ └── database.db # SQLite DB
├── hwpx_report/
│ ├── template/ # HWPX 템플릿
│ ├── hwp_file/ # 생성된 파일
│ ├── json_file/ # JSON 출력
│ ├── hwp_pydantic.py # Pydantic 모델
│ ├── docheong_report.py # 도청보고서 XML 처리
│ ├── hwp_xml.py # XML 유틸리티
│ ├── hwpx_compress.py # ZIP 압축
│ ├── jbnu_report.py # JBNU 보고서 처리
│ └── model_json.py # GPT-4o-mini 텍스트 분류
├── llm_agent/
│ ├── sql_report.py # SQL 쿼리 생성 및 분석
│ ├── search.py # FAISS 문서 검색
│ ├── embedding.py # KURE-v1 임베딩
│ ├── graph.py # 그래프 생성
│ ├── preprocess.py # Excel/CSV 전처리
│ └── csv_2_db.py # CSV to SQLite
├── Dockerfile
└── requirements.txt
- 사용자 입력: Streamlit UI를 통해 질문 또는 파일 업로드
- 데이터 분석: Flask 서버가 Qwen3-14B를 사용해 SQL 생성 및 실행
- 응답 생성: LLM이 분석 결과를 자연어로 정리
- 보고서 변환: GPT-4o-mini가 자유 텍스트를 구조화된 JSON으로 변환
- 고정 모드: 4개 섹션(개요/현황/이슈/계획)으로 분류
- 동적 모드: LLM이 내용에 맞는 섹션을 자유롭게 구성
- HWPX 생성: FastAPI가 템플릿 기반으로 XML 조작 후 HWPX 파일 생성
- 다운로드: 생성된 HWPX 파일을 사용자에게 제공
- Language: Python
- Framework: Streamlit, Flask, FastAPI
- Server: Docker
- Model: KURE-v1 (Embedding), Qwen3-14B (LLM), GPT-4o-mini (텍스트 분류)