8000 GitHub - SM17-YoonDongJu/AI: OCR, RAG, LangGraph 레포 · GitHub
[go: up one dir, main page]

Skip to content
SM17-YoonDongJuPublic

About

OCR, RAG, LangGraph 레포

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

241 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
< 8000 svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AI Engine — 보험·법률 AI 처리 엔진

보험 청구 서류를 받아 OCR → PII 마스킹 → Hybrid RAG → LangGraph 멀티에이전트 → 가드레일을 거쳐 보상 분석 리포트를 만드는 Python 엔진.

CI Python uv ruff

파일 수신·JWT·S3 저장·SQS 발행은 Spring Boot 게이트웨이(별도 레포) 가 맡고, 이 레포는 그 뒤의 AI 처리만 담당한다.


목차


아키텍처

Spring Boot gateway  — 별도 레포: 업로드 · JWT · S3 PutObject
   │
   │  SQS ocr-job-queue  — 문서 1건 = 1메시지
   ▼
ocr_worker (02, CPU)
   │  S3 원본 → PaddleOCR (+VLM 표 보조) → 분류·추출
   │  → PII 마스킹 (텍스트+이미지) → ai.ocr_results
   │  → 청구 fan-in 판정 → 청구당 1건 발행
   │
   │  SQS report-job
   ▼
report_worker (05, 범용)
      LangGraph: 진단 → 약관·담보 → 판례 → 후유장해
      → 지급액 계산 (순수 함수) → 리포트 → 가드레일

corpus_worker (상시 데몬)
      Notion 약관 카탈로그 → PG 미러 동기화 + 원문 S3 스테이징

core · rag (04) · guardrail (06)  — 공용 모듈, 워커가 import
   │
   │  HTTP (OpenAI 호환)
   ▼
Ollama / vLLM  — 외부 GPU 노드: LLM · 임베딩 · VLM
구분 방식 비고
OCR·리포트 SQS 워커 (at-least-once) job_id/report_id 멱등, poison 가드, 결정적 실패 즉시 종결
RAG·가드레일 공용 Python 모듈 워커가 import해서 조립
LLM·임베딩 외부 Ollama/vLLM HTTP 호출 모델은 config(LLM_MODEL·EMBEDDING_MODEL)로만 지정
인프라 RDS(PostgreSQL+pgvector) · SQS · S3 로컬은 docker-compose(LocalStack·pgvector)

돈에 직결되는 숫자(장해 지급률·예상 보상금)는 LLM이 아니라 정해진 계산 규칙(순수 함수) 이 만든다. LLM은 분류·해석만 맡는다.

모듈 맵

패키지 역할 실행 형태 상세
src/core 설정·계약(contracts.py)·SQS 래퍼·asyncpg 풀·ai_client·암호화·로깅 라이브러리 README
src/rag Hybrid RAG: 쿼리 라우터 → trigram 오타보정 → tsvector + pgvector → RRF → 인용 역추적 라이브러리 README
src/guardrail 입력(PII·도메인 차단) / 생성(단정 표현 치환·인용 강제) / 출력(고지문·LLM Judge) 라이브러리 README
src/ocr_worker ocr-job-queue 소비 → OCR·마스킹·저장 → 청구 fan-in → report-job 발행 python -m ocr_worker (CPU) README
src/report_worker report-job 소비 → LangGraph 멀티에이전트 리포트 생성 python -m report_worker README
src/corpus_worker Notion 약관 카탈로그 → PG 미러 동기화 + 원문 S3 스테이징 (상시 데몬) python -m corpus_worker README
리포트 그래프 노드 (src/report_worker/graph.py)
load_context → input_guardrail ─┬─▶ persist_blocked                         (1)
                                └─▶ diagnosis ─┬─▶ terms_parse ─┐           (2)
                                               └────────────────┴─▶ coverage_parse → coverage_analysis
                                    → case_search ─┬─▶ disability_rag → disability_verify → disability_calc ─┐
                                                   └─────────────────────────────────────────────────────────┤  (3)
                                    payment_calc ◀───────────────────────────────────────────────────────────┘
                                    → report_compose → output_guardrail → persist
  1. 보험·법률 외 질문이거나 PII 복호화에 실패하면 reports.status=BLOCKED만 기록하고 종료
  2. 약관이 policy_chunks에 없을 때만 런타임 파싱
  3. 후유장해 검토가 필요 없으면 payment_calc로 바로 이동

상세: docs/architecture/langgraph.md

퀵스타트

요구사항: Python 3.12, uv, Docker. OCR 워커는 GPU가 필요 없다(PaddleOCR·NER 모두 CPU). 다만 paddlepaddle CPU 휠이 linux x86_64뿐이라 OCR 이미지는 Apple Silicon에서 --platform linux/amd64로 빌드한다.

# 1) 의존성 — base + dev, 필요한 워커 extra만 추가
uv sync                          # base + dev
uv sync --extra report           # 리포트 워커
uv sync --extra ocr --extra ner  # OCR 워커 (CPU: PaddleOCR + NER)

# 2) 로컬 백킹 서비스 — LocalStack(SQS, 큐 자동 생성) · PostgreSQL+pgvector
docker compose up -d

# 3) 환경변수
cp .env.example .env             # DATABASE_URL · SQS_*_QUEUE_URL · SQS_ENDPOINT_URL · AI_BASE_URL · LLM_MODEL ...

# 4) 워커 실행 (각각 별도 터미널)
uv run python -m ocr_worker      # 기동 시 migrations/ai 자동 적용
uv run python -m report_worker
uv run python -m corpus_worker   # 기동 시 migrations/corpus 자동 적용 (NOTION_TOKEN 필요)
샘플 메시지 발행해 보기 (LocalStack)
aws --endpoint-url http://localhost:4566 sqs send-message \
  --queue-url http://localhost:4566/000000000000/ocr-job-queue \
  --message-body '{
    "job_id": "00000000-0000-0000-0000-000000000001",
    "s3_key": "uploads/sample.pdf",
    "content_type": "application/pdf",
    "user_ref": "u-1",
    "report_id": "00000000-0000-0000-0000-0000000000a1",
    "attachment_id": "00000000-0000-0000-0000-0000000000b1",
    "doc_index": 1, "doc_total": 1,
    "uploaded_at": "2026-01-01T00:00:00Z"
  }'

전체 흐름 데모: scripts/demo_pipeline.py

uv run은 pythonpath=src를 잡아 준다. uv 없이 실행할 때는 PYTHONPATH=src python -m <worker>로 실행한다.

메시지 계약 & 상태 흐름

통합 경계는 src/core/contracts.py 다. 발행 측(Spring의 OcrJob.java)과 소비 측이 이 스키마를 함께 지켜야 한다.

큐 페이로드 발행 → 소비 멱등 키
ocr-job-queue OcrJob Spring → ocr_worker (문서 1건씩) job_id
report-job ReportJob ocr_worker → report_worker (청구당 1건) report_id

청구 fan-in (ai.claim_readiness) 한 청구는 문서 여러 건(doc_index/doc_total)으로 들어온다. 문서가 종결될 때마다 카운터가 오른다. 종결에는 성공, 확정 실패, poison 소진이 모두 포함된다. 마지막 문서를 처리한 워커가 필수 유형(증권과 진단서)이 갖춰졌는지 판정한다.

판정 (전 문서 종결 시) claim_readiness.status 발행 결과
필수 유형 충족 pending → published ReportJob(ocr_quality=ok) 리포트 생성
필수 유형 누락·인식 불완전 pending → blocked ReportJob(ocr_quality=needs_reupload) reports.status = NEEDS_REUPLOAD

실패 처리: DLQ는 쓰지 않는다. 결정적 실패(NonRetryableError: 마스킹 잔류, 디코드 실패)는 첫 시도에서 바로 ack하고 종결한다. 일시 실패는 재전달되며, 수신 횟수 상한을 넘기면 poison으로 스킵한다. 모든 실패는 ai.ocr_job_failures 저널에 기록되므로 실패가 조용히 사라지지 않는다.

상세: .claude/docs/contracts.md · docs/architecture/lifecycle.md

DB 스키마 & 마이그레이션

프레임워크 없이 번호 순서대로 적용하는 멱등 SQL 파일로 관리한다. 디렉터리마다 소유 스키마와 실행 워커가 정해져 있다.

디렉터리 스키마 소유 role 적용 주체
migrations/ai/ ai_owner ocr_worker 기동 시
migrations/corpus/ corpus_owner corpus_worker 기동 시
core.* — backend Flyway (이 레포 범위 밖)

새 마이그레이션은 소유 워커의 디렉터리에만 추가한다. 다른 role의 스키마를 건드리면 permission denied로 워커가 다운된다. 배경: migrations/README.md PII 컬럼은 AES-256-GCM으로 암호화한다. deploy/DB_ENCRYPTION.md

테스트 & 품질

uv run ruff check src tests && uv run ruff format .   # 린트·포맷
uv run mypy src                                        # 타입 (strict)
uv run pytest                                          # 단위 테스트
  • 무거운 의존성(paddleocr·paddle, pymupdf, torch)은 lazy import로 분리해 두어서, 모델 없이도 OCR 오케스트레이션과 엔진 어댑터를 테스트할 수 있다.
  • e2e 테스트(tests/e2e)는 LocalStack에 자체 유니크 큐를 만들어 실행한다.
  • 코드 컨벤션: .claude/CODE_CONVENTIONS.md

배포

dev 브랜치에 push하면 deploy.yml이 실행된다. ci.yml의 테스트 게이트를 통과해야 진행하며, 변경된 서비스만 빌드해 ECR에 push한다.

서비스 Dockerfile 배포 경로
report src/report_worker/Dockerfile (slim) K8s-manifests의 image.tag를 커밋하면 Argo CD가 롤링 업데이트
ocr src/ocr_worker/Dockerfile (CPU, 모델 포함) OCR EC2(GPU 불필요)에 SSM으로 호스트 compose 재시작
corpus src/corpus_worker/Dockerfile ETL EC2에 SSM으로 호스트 compose 재시작

공용 코드(core, pyproject.toml, uv.lock)가 바뀌면 전 서비스를 다시 빌드한다. migrations/ai/**가 바뀌면 ocr을, migrations/corpus/**가 바뀌면 corpus를 다시 배포한다. 상세: deploy/README.md

문서

문서 내용
docs/architecture/ LangGraph·DB·RAG·가드레일·라이프사이클 통합 아키텍처
docs/report-worker/ 후유장해 파이프라인·일정 데이터·알려진 이슈
.claude/docs/contracts.md 워커 간 인터페이스 계약 (병렬 개발 기준)
.claude/docs/ 기능별 설계 (02 OCR · 04 RAG · 05 리포트 · 06 가드레일, Notion 미러)

기여

dev에서 브랜치를 따서 작업하고 PR을 올린다. contracts.py를 바꿀 때는 Spring 쪽 OcrJob.java도 함께 맞춰야 한다. 커밋 메시지는 한국어 Conventional Commits 형식(feat(ocr): ...)을 따른다.

About

OCR, RAG, LangGraph 레포

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0