13.4.3 날짜 논리 검증(Temporal Logic): 발주일 ≤ 청구일 ≤ 만기일 순서 보장

13.4.3 날짜 논리 검증(Temporal Logic): 발주일 ≤ 청구일 ≤ 만기일 순서 보장

엔터프라이즈 재무 문서에 기재된 날짜와 시간 정보들은 결코 서로 독립적으로 흩어져 있는 무의미한 텍스트 파편이 아니다. 이 시계열 텐서들은 기업의 상거래 트랜잭션(Transaction) 생명주기를 꿰뚫고 지나가는 **‘단방향의 인과율(Causality)’**이라는 강력한 거시적 질서를 지닌다.
물리학에서 시간의 화살(Arrow of Time)이 불가역적이듯, 비즈니스 세계에서도 물건을 주문(발주)하기도 전에 대금을 먼저 청구할 수 없고, 청구서(Invoice)가 발행되기도 전에 납부 만기일(Due Date)이 우주에 먼저 도래할 수는 없다.

그러나 2차원의 시각적 레이아웃 공간과 어텐션 확률에만 의존하는 거대 언어 모델(LLM)은 종종 문서 상단에 적힌 날짜와 하단 구석에 적힌 날짜를 아무런 의미론적 이해 계통 없이 무작위로 뒤바꾸어 서로 엉뚱한 필드에 쑤셔 넣는 **‘시간 역전 환각(Time Reversal Hallucination)’**을 뻔뻔하게 일으키곤 한다.

앞서 13.3.4절에서 구축한 1단계 날짜 구문 오라클은 그저 각각의 배열 노드에 들어온 날짜 문자열 값이 ISO 8601 포맷인지 검증하고 달력에 존재하는 유효한 날짜인지만을(예: 2월 30일 방어) 심판했을 뿐이다. 1단계 오라클은 독립적인 날짜들이 모여서 만들어내는 거시적인 타임라인의 논리 모순까지는 알아채지 못한다.
따라서 우리는 2단계 오라클에서 문서 전체를 조망하며 시계열 데이터 간의 대수학적 부등식 관계를 스크리닝 하는 **‘의미론적 날짜 논리 검열기(Temporal Logic Validator)’**를 반드시 파이프라인 최하단에 가동해야만 한다.

1. 시간의 화살(Arrow of Time) 부등식 스키마 코어 구현

Pydantic의 메타 모델 최상단에 @model_validator를 활용하여, LLM 추출이 끝난 전체 JSON 객체의 날짜 데이터 셋이 현실 세계의 시간 물리 법칙인 발주일 \le 청구일 \le 만기일 의 절대 공리를 준수하는지 관계 대수학 코드로 검열한다.

from pydantic import BaseModel, model_validator
from datetime import date
from typing import Optional

class TemporalIntegrityOracle(BaseModel):
    """ 문서 상의 모든 시계열 사건들이 단방향 인과율을 따르는지 스캔하는 오라클 """
    
    # 발주일(PO Date)은 영수증 같은 문서에는 없을 수 있으므로 Optional 처리
    purchase_order_date: Optional[date] = None
    
    # 송장 청구일과 만기일은 필수(Required) 타임라인 거점
    invoice_date: date                       
    due_date: date                           
    
    @model_validator(mode='after')
    def verify_chronological_time_arrow(self):
        """ 추출 완료된 날짜 노드 간의 인과성 및 타임라인 부등식을 통제 검증한다. """
        
        # 1. 청구일 vs 만기일(Due Date) 타임라인 역전 붕괴 검증
        if self.invoice_date > self.due_date:
             # 청구하기도 전에 만기가 도래하는 기괴한 환각 요격
            raise ValueError(
                f"[시간 논리 모순 트리거] 송장 청구일({self.invoice_date})의 위상이 "
                f"결제 만기일({self.due_date})보다 미래에 존재할 수 없습니다. "
                f"LLM이 문서의 날짜 레이아웃 배치를 혼동한 명백한 환각입니다."
            )
            
        # 2. 발주일(PO) vs 청구일 인과율 방어망 (발주일이 문서에 명시된 상황에 한함)
        if self.purchase_order_date is not None:
            if self.purchase_order_date > self.invoice_date:
                # 미래의 발주를 위해 과거에 돈을 청구하는 타임 패러독스 차단
                raise ValueError(
                    f"[인과율 붕괴 트리거] 물건을 발주한 기준 날짜({self.purchase_order_date})가 "
                    f"벤더사가 대금을 청구한 날짜({self.invoice_date})보다 시간상 느릴 수 없습니다. "
                    f"원문 참조 오류 롤백 수행 요망."
                )
                
        return self # 시공간의 무결성이 모두 수학적으로 증명된 객체만 릴리스.

2. 날짜 논리 검증의 거시적 MLOps 파이프라인 수호 효과

이 날짜 논리 검증 오라클 엔진이 if 문에 걸려 런타임 스레드에서 ValueError 예외 패닉을 공중으로 격발시키는 순간, 시스템 엔지니어가 명심해야 할 아키텍처적 진실이 하나 있다.
이 오류는 단순히 *“LLM이 날짜 데이터 한두 개를 조금 잘못 읽어서 실수했다”*는 수준의 가벼운 의미가 결단코 아니다.

파라미터 모델이 시간의 인과율이 완전히 뒤집힌 추출 결과 페이로드를 당당히 내놓았다는 현상 자체는, LLM의 트랜스포머 어텐션 헤드(Attention Heads)가 원문 문서의 전체 공간 레이아웃 맥락(Contextual Topology)을 근본적으로 완전히 헛짚었으며, 현재 해당 배치(Batch) 추론 스레드가 통제 불능의 **심연의 환각 상태(Deep Hallucination)**에 헤어 나오지 못하게 빠져있다는 매우 파괴적이고 확실한 **임상적 징후(Symptom)**다.

즉, 이 촘촘한 시계열 모순을 그물망으로 찾아내는 오라클 과정은 곧 **“현재 이 문서 이미지에 대한 LLM 에이전트의 신경망 추론 상태 전체가 완전히 오염되었다”**는 사실을 백엔드 시스템 스스로 가장 빠르고 정확하게 진단하는 청진기와 같다.
따라서 논리 오라클은 이런 타임 패러독스를 발견하는 즉시 지금까지 추출된 수십 개의 JSON 페이로드(Payload)를 메모리에서 단 1비트도 남김없이 영구 폐기(Drop) 시켜 버려야 한다. 그리고 앞서 설계한 자동 복구 피드백 루프를 통해 “네가 방금 추출한 시간 데이터는 시간 역전 모순(Time Paradox)을 일으키고 있다. 처음부터 문서를 픽셀 하나하나 다시 세밀하게 스캔해서 읽어라!” 라고 엄중하게 경고 템플릿을 던져, 파이프라인의 엔트로피를 정화하고 AI를 가혹하게 통제하게 되는 것이다.