EVMS 완전 자동화: - 공기 지연 AI 예측 (SPI 기반 준공일 예측) - 기성청구 가능 금액 자동 산출 - 매일 자정 EVMS 스냅샷 자동 생성 (APScheduler) - 매일 07:00 GONGSA 아침 브리핑 자동 생성 준공도서 패키지: - 준공 요약 + 품질시험 목록 + 검측 이력 + 인허가 현황 → ZIP 번들 - 준공 준비 체크리스트 API - 4종 HTML 템플릿 (WeasyPrint PDF 출력) Vision AI Level 3: - 설계 도면 vs 현장 사진 비교 보조 판독 (Claude Vision) - 철근 배근, 거푸집 치수 1차 분석 설계도서 파싱: - PDF 이미지/텍스트에서 공종·수량·규격 자동 추출 - Pandoc HWP 출력 지원 발주처 전용 포털: - 토큰 기반 읽기 전용 API - 공사 현황 대시보드, 공정률 추이 차트 에이전트 협업 고도화: - 협업 시나리오 (concrete_pour, excavation, weekly_report) - GONGSA→PUMJIL→ANJEON 순차 처리 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
134 lines
4.2 KiB
Python
134 lines
4.2 KiB
Python
"""
|
|
설계도서 파싱 서비스 (Phase 3)
|
|
PDF 설계도서에서 공종·수량·규격을 AI로 자동 추출합니다.
|
|
HWP 출력은 Pandoc을 통해 변환합니다.
|
|
"""
|
|
import base64
|
|
import json
|
|
import re
|
|
import subprocess
|
|
import tempfile
|
|
import os
|
|
from pathlib import Path
|
|
from anthropic import AsyncAnthropic
|
|
from app.config import settings
|
|
|
|
_client = AsyncAnthropic(api_key=settings.ANTHROPIC_API_KEY)
|
|
|
|
_PARSE_SYSTEM = """당신은 건설 설계도서 분석 전문가입니다.
|
|
제공된 설계도서 내용에서 다음 정보를 추출하세요:
|
|
1. 공종 목록 (work_types): 주요 공종과 세부 공종
|
|
2. 수량 목록 (quantities): 각 공종별 수량과 단위
|
|
3. 규격 (specifications): 재료 규격, 강도, 등급
|
|
4. 특기 사항 (notes): 시공 시 주의사항, 특수 조건
|
|
|
|
JSON 형식으로만 반환하세요."""
|
|
|
|
|
|
async def parse_design_document_text(text: str) -> dict:
|
|
"""
|
|
설계도서 텍스트에서 공종/수량/규격 추출 (Claude API).
|
|
RAG 시드 스크립트로 읽은 텍스트를 직접 전달하는 용도.
|
|
"""
|
|
prompt = f"""다음 설계도서 내용을 분석해주세요:
|
|
|
|
{text[:8000]}
|
|
|
|
JSON 형식으로만 반환하세요:
|
|
{{
|
|
"work_types": ["터파기", "철근콘크리트", ...],
|
|
"quantities": [
|
|
{{"work_type": "터파기", "quantity": 500, "unit": "m³"}},
|
|
...
|
|
],
|
|
"specifications": [
|
|
{{"item": "콘크리트", "spec": "fck=24MPa", "notes": ""}},
|
|
...
|
|
],
|
|
"notes": ["주의사항1", ...]
|
|
}}"""
|
|
|
|
response = await _client.messages.create(
|
|
model=settings.CLAUDE_MODEL,
|
|
max_tokens=2048,
|
|
system=_PARSE_SYSTEM,
|
|
messages=[{"role": "user", "content": prompt}],
|
|
)
|
|
|
|
raw = response.content[0].text.strip()
|
|
match = re.search(r"\{.*\}", raw, re.DOTALL)
|
|
if match:
|
|
return json.loads(match.group())
|
|
return {"error": "파싱 실패", "raw": raw[:500]}
|
|
|
|
|
|
async def parse_design_document_image(image_data: bytes, media_type: str = "image/jpeg") -> dict:
|
|
"""
|
|
설계 도면 이미지에서 공종/수량/규격 추출 (Claude Vision).
|
|
도면 스캔 이미지나 PDF 페이지를 직접 분석합니다.
|
|
"""
|
|
image_b64 = base64.standard_b64encode(image_data).decode()
|
|
|
|
response = await _client.messages.create(
|
|
model=settings.CLAUDE_MODEL,
|
|
max_tokens=2048,
|
|
system=_PARSE_SYSTEM,
|
|
messages=[{
|
|
"role": "user",
|
|
"content": [
|
|
{"type": "image", "source": {"type": "base64", "media_type": media_type, "data": image_b64}},
|
|
{"type": "text", "text": "이 설계 도면/도서에서 공종, 수량, 규격을 추출해주세요. JSON으로만 반환하세요."},
|
|
],
|
|
}],
|
|
)
|
|
|
|
raw = response.content[0].text.strip()
|
|
match = re.search(r"\{.*\}", raw, re.DOTALL)
|
|
if match:
|
|
return json.loads(match.group())
|
|
return {"error": "파싱 실패", "raw": raw[:500]}
|
|
|
|
|
|
def convert_to_hwp(html_content: str, output_path: str | None = None) -> bytes | str:
|
|
"""
|
|
HTML → HWP 변환 (Pandoc 필요).
|
|
output_path 미지정 시 바이트 반환.
|
|
|
|
사전 요구사항: pandoc 설치 필요
|
|
설치: https://pandoc.org/installing.html
|
|
"""
|
|
try:
|
|
with tempfile.NamedTemporaryFile(suffix=".html", delete=False, mode="w", encoding="utf-8") as f:
|
|
f.write(html_content)
|
|
html_path = f.name
|
|
|
|
if output_path:
|
|
out = output_path
|
|
else:
|
|
out = html_path.replace(".html", ".hwp")
|
|
|
|
result = subprocess.run(
|
|
["pandoc", html_path, "-o", out, "--from=html"],
|
|
capture_output=True, text=True, timeout=30,
|
|
)
|
|
|
|
os.unlink(html_path)
|
|
|
|
if result.returncode != 0:
|
|
raise RuntimeError(f"Pandoc 변환 실패: {result.stderr}")
|
|
|
|
if output_path:
|
|
return output_path
|
|
else:
|
|
with open(out, "rb") as f:
|
|
data = f.read()
|
|
os.unlink(out)
|
|
return data
|
|
|
|
except FileNotFoundError:
|
|
raise RuntimeError(
|
|
"Pandoc이 설치되지 않았습니다.\n"
|
|
"설치: https://pandoc.org/installing.html\n"
|
|
"Windows: winget install JohnMacFarlane.Pandoc"
|
|
)
|