Service Thesis

Plan2Do는 산업 현장 사진이나 문서를 입력받아 "무엇이 위험한가"를 찾고, 법령 근거가 붙은 감소대책 표로 바꾸는 AI 안전도우미입니다.

핵심은 일반 챗봇 답변이 아니라 위험요인, 예상 위험 수준, 감소대책, 관련 법령 근거를 구조화된 산출물로 만드는 실행 흐름입니다.
FastAPI 엔진은 이미지/문서 분석, Qdrant 법령 검색, LangGraph 위험성평가 workflow, PostgreSQL 기록 저장을 하나의 API 서비스로 묶습니다.

Plan2Do를 다시 정의하면

Plan2Do의 문제 공간은 산업안전 담당자가 현장 사진, 작업 설명, PDF 자료를 읽고 위험요인과 감소대책을 표로 정리해야 하는 반복 업무입니다.
단순히 “안전모를 쓰세요”라고 답하는 AI가 아니라, 입력 자료에서 위험 후보를 추출하고, 관련 법령을 찾아 근거를 붙이며, 사용자가 검토할 수 있는 HTML 테이블을 반환하는 것이 목표입니다.

소스 기준의 제품 표면은 세 가지입니다. /api/chat/reqQuestion/api/v2/chat/reqQuestion은 이미지를 산업안전 관련 자료인지 먼저 분류하고, 안전 현장 이미지일 때만 위험 관찰 결과를 만듭니다. /api/chat/noRag/api/v2/chat/noRag/stream은 위험성평가, 위험요인, 감소대책, 표 요청 같은 키워드를 감지해 LangGraph workflow로 넘어갑니다. /api/document/riskAnalysis/api/document/riskAnalysisIntegrated는 PDF나 이미지 파일을 개별 또는 통합 분석해 위험성평가 JSON을 반환합니다.

문제

산업 현장 자료는 비정형 입력이 많고, 결과는 검토 가능한 표와 법령 근거로 남아야 합니다.

접근

입력 분석, 위험요인 추출, 법령 벡터 검색, 감소대책 생성, 법령 검증, HTML 표 생성을 단계별 workflow로 분리했습니다.

결과

사용자는 위험요인과 감소대책을 체크 가능한 표로 받고, 각 조치가 어떤 법령 근거와 연결되는지 함께 검토할 수 있습니다.

사용자가 실제로 얻는 기능

이미지 안전 판별

업로드 이미지를 산업안전 관련 이미지인지 먼저 분류하고, 관련성이 낮으면 NON_INDUSTRIAL_IMAGE로 거절합니다.

현장 위험 관찰

안전모 미착용, 사다리 안전대, 낙하물, 감전, 화재 같은 관찰 결과를 이미지 설명으로 통합합니다.

문서 위험성 분석

PDF와 이미지 파일을 읽어 파일별 위험요인과 감소대책을 만들고, 여러 파일을 하나의 통합 분석으로 합칠 수 있습니다.

법령 근거 검색

산업안전보건법, 중대재해처벌법, 건설기술진흥법 계열 XML을 Qdrant collection으로 올려 관련 조문을 검색합니다.

LangGraph Workflow

법규 검색 후 위험 분석과 감소대책 생성을 병렬 수행하고, 법령 검증과 HTML 표 생성까지 같은 상태 객체로 이어갑니다.

SSE Progress

긴 분석 작업은 진행 시작, 관련 법규 검색 완료, 감소대책 수립 완료, 결과 테이블 생성 완료 같은 이벤트로 흘러갑니다.

HTML 결과 테이블

선택 체크박스, 위험요인, 예상 위험 수준, 감소대책, 관련 근거, 상세내용을 포함하는 검토용 표를 생성합니다.

로컬 운영 묶음

Docker Compose가 FastAPI engine, PostgreSQL, Qdrant, vector init/load 작업을 한 개발 환경으로 묶습니다.

Plan2Do runtime topology diagram
Plan2Do runtime topology. FastAPI engine은 API 요청을 받아 AI provider, PostgreSQL, Qdrant 법령 검색, vector build/load pipeline과 연결됩니다.

위험성평가 workflow

NoRagLangGraphWorkflow는 Plan2Do에서 가장 제품적인 실행 단위입니다.
입력은 risk_factors, query, trace_id이고, 출력은 processed_risks, references, mitigation_plans, legal_validations, html_table, summary를 담은 최종 결과입니다.
이 구조 덕분에 UI나 클라이언트는 전체 분석이 끝날 때까지 기다리지 않고 단계별 진행 상황을 받을 수 있습니다.

workflow는 먼저 입력 위험요인을 초기화하고, 각 위험요인에 대해 Qdrant 법령 검색을 수행합니다.
그다음 위험요인 상세 분석과 감소대책 생성을 병렬로 실행합니다.
이후 법령 검증 단계에서 감소대책과 법령 매칭 품질을 다시 판단한 뒤, HtmlGenerator.generate_progressive_table이 최종 표를 만듭니다.

01 입력 정규화 02 법령 검색 03 위험 분석 04 감소대책 생성 05 표와 근거 반환
Plan2Do risk analysis workflow diagram
Risk analysis workflow. 법령 검색이 먼저 수행되고, 위험 분석과 감소대책 생성이 병렬로 진행된 뒤 법령 검증과 HTML 테이블 생성으로 합류합니다.

법령 RAG가 동작하는 방식

Plan2Do의 RAG는 산업안전 관련 법령 corpus를 먼저 구축해 놓고 위험요인에 맞는 근거를 찾는 구조입니다. servers/vectordb/data에는 법령 XML 10개와 행정규칙 XML 1개가 포함되어 있고, 전처리기는 법령 원문의 원문자, 특수기호, HTML 태그, 전각 문자를 정규화합니다.
법령은 조, 항, 호 같은 계층 단위로 나뉘고, build.pytext-embedding-3-large 기반 embedding과 Qdrant point payload를 생성합니다. load.pydocuments collection을 준비하고 batch upload와 간단한 검색 확인을 담당합니다.

검색 시에는 위험 설명 하나를 그대로 embedding하는 것에서 끝나지 않습니다.
RiskAnalysisService는 먼저 LLM으로 안전 키워드를 추출하고, JSON 파싱에 실패하면 정규식/명사 기반 fallback을 사용합니다.
이후 원본 설명 검색과 키워드 강화 검색을 따로 수행하고, 두 결과에 가중치를 부여해 병합합니다.
같은 법령이나 같은 조문으로 결과가 편중되지 않도록 law/article cap도 둡니다.

코드 기준으로 확인한 구성

구성 확인한 역할 제품 의미
servers/engine/src/main.py FastAPI app, CORS, router mount, docs endpoint 외부 요청이 들어오는 API 경계
api/chat_endpoints.py 이미지 질문 생성, noRag streaming, RAG 분석 분기 사용자 입력을 위험성평가 요청으로 바꾸는 기존 API 표면
api/chat_v2_endpoints.py UUID 기반 이미지 병렬 처리, stream 분석 여러 이미지와 진행률이 필요한 클라이언트 흐름
api/document_endpoints.py PDF/image 위험성 분석, 여러 파일 통합 분석 현장 문서까지 입력 채널을 넓히는 기능
service/workflow_service.py LangGraph node와 async SSE event 생성 법령 검색부터 표 생성까지 이어지는 핵심 실행 경로
service/risk_analysis_service.py 키워드 추출, vector search, 위험 분석, 감소대책, 법령 검증 LLM 추론과 법령 근거를 제품 로직으로 묶는 서비스 계층
servers/vectordb/processor.py 법령 XML 정규화, 조문 단위 chunk 생성 검색 가능한 안전 법령 corpus를 만드는 전처리 파이프라인
data/database.py Conversation, Question, Document, Answer, Report, Reference, Userlist schema 대화, 질문, 문서, 답변, 참조 관계를 PostgreSQL에 남기는 영속성 경계
docker-compose.yml engine, rdb, qdrant, init-check, load-data 서비스 연결 로컬 개발자가 한 번에 API, RDB, VectorDB, 벡터 로딩을 띄우는 운영 단위

API와 산출물 매트릭스

사용자 기능 Endpoint 주요 처리 반환 산출물
이미지 기반 질문 생성 POST /api/chat/reqQuestion 산업안전 이미지 분류, vision 분석, 여러 이미지 관찰 결과 통합, 질문 저장 query, img_description, question_id, rag_flag
v2 이미지 병렬 처리 POST /api/v2/chat/reqQuestion asyncio.gather로 uuid별 이미지 분류와 vision 분석 수행 uuid가 유지된 img_descriptions 배열
이미지/문서 설명 기반 RAG 분석 GET /api/chat/noRag description을 위험요인으로 추출하고 Qdrant 근거와 감소대책으로 확장 risk_factor, reduction_measure, related_evidence
위험성평가 표 생성 GET /api/chat/noRag 위험성평가/표 키워드를 감지해 LangGraph workflow 실행 SSE chunk와 최종 html_table
v2 위험분석 스트리밍 GET /api/v2/chat/noRag/stream URL encoded risk descriptions와 uuids를 risk factor 객체로 매핑 진행률, references, mitigations, validations, final result
파일별 위험성 분석 POST /api/document/riskAnalysis PDF text extraction 또는 image vision 후 JSON 위험 분석 수행 파일별 filename, page_cnt, 위험 분석 결과
여러 파일 통합 분석 POST /api/document/riskAnalysisIntegrated 파일 설명을 병렬 생성하고 하나의 통합 prompt로 종합 분석 total_files, page_cnt, 통합 위험성평가 JSON

운영과 검증 관점

Docker Compose 기준으로 Plan2Do는 engine, rdb, qdrant, init-check, load-data로 나뉩니다. init-check는 vector 파일이 비어 있을 때만 build.py를 실행하고, load-data는 Qdrant가 시작된 뒤 생성된 point 데이터를 collection에 올립니다. engine은 PostgreSQL이 열릴 때까지 대기한 뒤 python3 main.py로 시작합니다.

다만 현재 소스 묶음은 git repository가 아니며, 별도의 자동 테스트 파일도 포함되어 있지 않았습니다.
그래서 이 글은 “코드와 문서로 확인되는 아키텍처”를 기준으로 작성했고, 실제 운영 트래픽이나 배포 상태를 새로 검증했다는 의미는 아닙니다.
운영 환경에서는 API key와 DB password를 파일이 아니라 환경변수나 Secret Manager로 주입하고, Qdrant/PostgreSQL 포트는 외부 인터넷에 노출하지 않는 구성이 필요합니다.

기여를 어떻게 볼 수 있는가

포트폴리오의 수상 데이터는 Plan2Do를 “AI 안전도우미와 위험성평가 지원 시스템” 고도화 기여로 설명합니다.
소스 기준으로 보면 이 기여는 단순 prompt 작성이 아니라, 현장 입력을 산업안전 도메인으로 판별하고, 법령 검색으로 근거를 붙이며, LangGraph 상태 머신으로 위험성평가 표를 끝까지 생성하는 제품 실행 경계에 가깝습니다.

그래서 Plan2Do 프로젝트 페이지의 핵심 메시지는 “AI로 안전 답변을 생성했다”가 아닙니다.
더 정확히는 산업안전 담당자가 검토 가능한 위험성평가 표를 만들기 위해, 비정형 입력, 법령 corpus, LLM 추론, 벡터 검색, 관계형 저장, SSE 진행률을 하나의 API 제품으로 묶었다는 점입니다.