CSV 테이블 열 개를 빌드한 직후에는 클래스도 열 개였습니다. 후처리가 끝난 그래프에는 네 개만 남아 있었습니다. 문서에서 나온 유사 개념을 정리하는 규칙이 서로 다른 테이블의 스키마 식별자까지 같은 것으로 합친 것입니다. 클래스의 이름이 무엇을 뜻하는지가 출처마다 다르다는 것을 확인하고, 그 출처를 데이터로 남긴 과정입니다.
빌드 직후 열 개였던 클래스가 후처리 뒤에 네 개였습니다
CSV 빌드가 처음 만든 클래스는 입력 테이블과 하나씩 대응했습니다. 열 개 테이블이면 열 개 클래스입니다.
후처리가 끝난 그래프를 열어보니 네 개였습니다.
한 노드에 여러 테이블의 라벨이 함께 붙어 있었습니다. 주문 관련 노드에 상품 변형과 변형 판매 라벨이 같이 달려 있었고, 의미 유사도 병합이 서로 다른 테이블을 하나의 식별자로 합쳤다는 것이 드러났습니다.
이 병합 규칙 자체는 필요한 것이었습니다. 문서에서 모델이 만든 고객과 회원은 같은 개념일 수 있고, 그런 중복을 정리하지 않으면 그래프가 같은 것을 여러 이름으로 갖게 됩니다.
문제는 그 규칙이 정형 클래스에도 적용됐다는 것입니다.
정형 클래스의 이름은 자연어 개념 후보가 아니라 외래키가 참조하는 스키마 식별자입니다. 주문과 상품 변형과 변형 판매는 이름이 비슷해도 서로 다른 테이블 역할이고, 합쳐지면 그 참조 구조가 무너집니다.
문서에서 나온 클래스 고객 / 회원 → 같은 개념일 수 있다. 합쳐도 된다
CSV에서 나온 클래스 Orders / Variants → 스키마 식별자다. 합치면 참조가 깨진다
같은 자리에 앉아 있는 두 종류의 클래스가 서로 다른 규칙을 요구하고 있었습니다.
후처리를 끄는 것으로는 해결되지 않았습니다
가장 빠른 대응은 순수 정형 빌드에서 개념 중복 병합을 실행하지 않는 것이었습니다. 그렇게 했습니다.
CSV와 문서가 함께 들어오는 하이브리드 빌드가 남았습니다. 거기서는 문서 개념의 중복 정리가 여전히 필요합니다. 전체 후처리를 끄는 것은 한쪽 요구를 버리는 것이지 두 요구를 만족시키는 방법이 아닙니다.
필요한 것은 스위치가 아니라 구분이었습니다. 후처리가 어느 클래스를 건드려도 되고 어느 클래스는 건드리면 안 되는지 알아야 했습니다.
그런데 그 정보가 그래프에 없었습니다. 클래스가 CSV 스키마에서 왔는지 문서 추출에서 왔는지는 빌드 중에만 알 수 있는 사실이었고, 빌드가 끝나면 사라졌습니다.
두 번째 실행에 필요한 맥락이 첫 번째 실행과 함께 없어지고 있었습니다.
생성 출처를 파이프라인 플래그가 아니라 스키마에 저장했습니다
CSV에서 만든 클래스에 출처를 저장하고 중복 정리의 보호 집합으로 썼습니다. 보호된 클래스는 삭제 대상 식별자가 될 수 없습니다.
병합 방향도 한쪽만 열었습니다.
CSV 클래스 → CSV 클래스 병합하지 않음
CSV 클래스 → 문서 개념 허용하지 않음
문서 개념 → CSV 클래스 기존 중복 규칙이 같은 개념으로 판정하면 허용
문서 개념 → 문서 개념 기존 중복 정리 적용
문서에서 추출한 개념이 정형 클래스와 같은 대상을 가리키면 정형 식별자 쪽으로 합칠 수 있습니다. 반대로 정형 식별자를 문서 개념 쪽으로 없애지는 않습니다. 참조의 기준이 되는 쪽이 살아남아야 하기 때문입니다.
출처는 파이프라인의 임시 플래그가 아니라 스키마 레코드에 저장했습니다. 프로세스가 재시작되거나 다음 증분 빌드가 시작돼도 같은 보호 규칙이 적용돼야 하기 때문입니다.
보호 여부를 설명문 형식이나 식별자 이름에서 추측하지 않습니다. 이름 규칙으로 판정하면 이름이 바뀌는 날 보호가 사라집니다.
여러 출처에서 온 데이터를 한 저장소에 합칠 때, 출처 정보를 함께 저장할지는 대체로 나중 문제로 미뤄집니다. 합칠 때는 필요 없어 보이기 때문입니다. 필요해지는 시점은 그 데이터를 처리하는 규칙이 출처마다 달라야 할 때이고, 그때는 이미 출처를 알 수 없습니다.
이어서 빌드가 이어서 하지 않고 처음부터 다시 했습니다
문서 쪽에서도 같은 종류의 문제가 나왔습니다.
새 문서를 추가한 뒤 이어서 빌드를 실행해도 이전 청크 전체를 다시 처리했습니다.
그래프를 지우지는 않았습니다. 다만 문서 그룹을 처음부터 다시 모델에 보냈습니다. RDF 삽입은 여러 번 해도 결과가 같지만 LLM 추출은 실행마다 달라질 수 있어 비용과 개념 수가 함께 늘어납니다.
원인은 앞의 것과 같았습니다. 완료된 청크 집합이 빌드가 끝난 뒤 남아 있지 않아서, 다음 실행이 무엇을 건너뛸지 알 수 없었습니다.
완료된 작업에 처리한 청크 목록을 저장하고 현재 청크 집합과 차집합을 계산했습니다.
이번에 추출할 청크
= 현재 컬렉션의 청크 식별자
- 최근 완료 빌드의 처리 완료 목록
실패하거나 취소된 작업의 부분 목록은 기준으로 쓰지 않습니다. 그래프에 반영됐는지 확정되지 않은 청크를 다음 실행이 건너뛰면 안 되기 때문입니다. 재빌드는 기준을 초기화하고 전부 다시 처리합니다.
최근 완료 작업의 목록을 읽지 못하면 일부를 추측으로 건너뛰지 않고 전체 처리로 돌아갑니다. 증분 최적화가 실패했을 때 비용은 늘어도 데이터 누락 쪽으로는 실패하지 않게 한 선택입니다.
청크 개수만 비교하지도 않습니다. 문서 하나가 삭제되고 다른 문서가 추가되면 개수는 같아도 입력 집합은 다릅니다. 진행률에는 개수를 쓸 수 있지만 변경 판정에는 식별자 집합이 필요합니다.
11개 청크 중 8개가 완료 기준에 있고 3개가 새로 추가된 조건에서, 전체 빌드는 LLM 6회와 25,755토큰을 썼고 이어서 빌드는 새 청크만 2회 호출해 7,789토큰을 썼습니다. 특정 문서와 모델의 결과이므로 일반적인 절감률은 아닙니다. 확인한 것은 기존 8개가 호출 입력에서 빠졌고 완료 뒤 기준 집합이 11개로 갱신됐다는 점입니다.
문서 청크와 정형 파일은 증분 단위가 달랐습니다
증분 처리를 문서와 CSV에 똑같이 적용할 수는 없었습니다.
문서는 모델에 들어가는 청크가 독립된 추출 단위입니다. 새 청크만 보내도 기존 청크를 다시 해석할 필요가 없습니다.
CSV의 한 행은 다릅니다. 전체 컬럼 타입과 기본키 후보, 다른 테이블의 외래키 구조 안에서 의미가 정해집니다. 행 하나를 떼어놓으면 그 행이 무엇인지 알 수 없습니다.
그래서 정형 파일은 청크 필터를 적용하기 전에 별도 경로로 보내 파일 전체를 다시 처리했습니다.
행 단위 증분을 하려면 안정적인 기본키와 삭제 추적, 외래키 갱신 계약이 먼저 필요합니다. 이 계약은 10편의 데이터베이스 색인에서 따로 설계합니다.
증분 처리를 붙일 때 단위는 대체로 파일이나 레코드로 잡힙니다. 실제로 물어야 할 것은 그 단위를 독립적으로 다시 해석할 수 있는가입니다. 없으면 그 단위는 증분 단위가 아닙니다.
다음 실행이 알아야 할 것을 이번 실행이 남겨야 했습니다
이 편의 두 문제는 겉으로 달라 보입니다. 하나는 클래스가 잘못 합쳐졌고 다른 하나는 같은 일을 다시 했습니다.
원인은 같았습니다. 다음 실행에 필요한 판단 근거가 이번 실행이 끝나면서 사라졌습니다.
생성 출처는 후처리가 바꿔도 되는 대상을 정하고, 완료 청크 집합은 다시 처리해야 할 입력을 정합니다. 둘 다 실행 중에는 알고 있던 사실이고, 저장하지 않아서 다음 실행이 모르게 된 것입니다.
반복해서 도는 파이프라인을 만들 때, 한 번의 실행이 잘 끝나는지와 두 번째 실행이 첫 번째를 아는지는 다른 문제였습니다.
현재 문서 증분이 보장하는 것은 새 청크를 다시 추출하지 않는 데까지입니다. 수정되거나 삭제된 청크가 과거에 만든 트리플을 자동으로 무효화하려면 출처별 결과와 다른 출처의 지지 여부를 더 계산해야 합니다.
다음 편에서는 그 앞에 놓인 문제를 다룹니다. 모델마다 컨텍스트와 출력 한도가 달라서 생기는 추출 실패인데, 실패하는 방식이 조용해서 성공으로 기록되고 있었습니다.

