LLM 기반 그래프 구축: 스키마 유도 추출·검증·휴먼인더루프

추출의 전환 — 무거운 전통 파이프라인에서 스키마 유도 LLM 추출로, 검증 관문은 그대로 추출을 뒤집다 — 그래도 검증은 남는다 전통 파이프라인 — 도메인마다 무겁다 규칙라벨링학습튜닝 LLM 경로 — 스키마 프롬프트 하나로 문서 스키마 프롬프트 LLM 구조화 출력 추출된 트리플 (김지수, 근무, 누리테크) (누리테크, 출시, 미리내) 검증 관문 환각·중복·불일치 사람 검수 지식 그래프 LLM은 추출의 문턱을 낮춘다 — 스키마 규율과 엔티티 해소 숙제는 검증 관문에 그대로 남는다 "공짜가 아니다" — 품질을 가르는 것은 추출이 아니라 그 뒤의 검증이다
추출의 전환을 한 장으로 — 도메인마다 무겁던 전통 파이프라인 대신, 문서 + 스키마 프롬프트를 LLM에 넣어 곧바로 트리플을 얻는다. 그러나 환각·중복·불일치를 거르는 검증 관문과 사람 검수는 그대로 남는다 — 품질을 가르는 것은 그 관문이다.

들어가며

이 글은 Agentic Knowledge Graph Curriculum4단계이자, 시리즈 2막 “지능을 얹기”의 문을 여는 글입니다. 3단계에서 우리는 전통 추출 파이프라인 — 규칙·통계·지도학습 — 이 강력하지만 도메인마다 라벨링·튜닝 비용이 크고 이식성이 낮다는 한계를 봤습니다. 이 글은 그 판을 뒤집는 엔진, LLM 기반 그래프 구축을 다룹니다.

핵심 전환은 단순합니다. 정교한 규칙이나 라벨링된 코퍼스 대신, LLM에 스키마를 프롬프트로 알려 주고 문서에서 트리플을 뽑아 달라고 하는 것입니다. 도메인이 바뀌면 프롬프트의 스키마만 바꾸면 됩니다 — 재학습이 없습니다. 이 낮아진 문턱이 2020년대 지식 그래프 부흥의 첫 번째 동력입니다.

다만 3단계에서 예고했듯, LLM은 공짜가 아닙니다. 추출의 문턱은 낮췄지만, 스키마 규율과 엔티티 해소라는 옛 숙제는 그대로 남고 — 거기에 LLM 특유의 새 문제인 환각(없는 관계 지어내기)이 더해집니다. 그래서 이 글의 무게중심은 “어떻게 뽑는가”만큼이나 “어떻게 검증하는가“에 있습니다.

📌 이 글에서 다루는 내용

  • 스키마 유도 LLM 추출: 프롬프트로 타입·관계를 지시하고 구조화 출력(JSON·함수 호출)으로 트리플을 강제로 뽑는 법, few-shot과 스키마 제약
  • 구축 도구와 파이프라인: LangChain LLMGraphTransformer, LlamaIndex 프로퍼티 그래프 인덱스의 접근, 청킹·프롬프트 설계·비용 관리
  • 품질·검증·휴먼인더루프: 환각·중복·불일치를 잡는 검증, 신뢰도 점수, 엔티티 해소가 여전히 필요한 이유, 사람 검수 루프

한눈에 보기 — LLM 추출 파이프라인

LLM으로 그래프를 짓는 일도 하나의 파이프라인입니다. 문서를 청크로 나누고, 스키마를 곁들여 LLM에 추출을 시키고, 나온 트리플을 검증·해소한 뒤 그래프에 적재합니다. 검증 루프가 다시 추출로 되돌아가는 것이 핵심입니다.

flowchart TD
    DOC["문서 코퍼스"] --> CHUNK["청킹<br/>컨텍스트 창에 맞게 분할"]
    SCHEMA["타깃 스키마<br/>허용 타입·관계"] --> LLM
    CHUNK --> LLM["LLM 추출<br/>스키마 유도 · 구조화 출력"]
    LLM --> TRIPLE["후보 트리플"]
    TRIPLE --> VALID{"검증<br/>환각·중복·타입 위반?"}
    VALID -->|"통과"| ER["엔티티 해소<br/>같은 실체 병합"]
    VALID -->|"실패"| FIX["재추출 · 사람 검수"]
    FIX --> LLM
    ER --> KG["지식 그래프"]

이 그림의 좌표는 하나입니다 — LLM은 파이프라인의 한 상자를 바꿀 뿐, 파이프라인 자체를 없애지 않습니다. 스키마가 앞에서 추출을 안내하고, 검증이 뒤에서 품질을 지킵니다.

스키마 유도 LLM 추출 — 프롬프트로 트리플을 뽑다

스키마를 프롬프트에 싣기

핵심은 LLM에 “무엇을 뽑을지”를 명확히 지시하는 것입니다. 허용할 노드 타입관계 타입을 프롬프트에 실으면(스키마 유도, schema-guided), LLM이 자유롭게 지어내는 대신 그 어휘 안에서 추출합니다. 이것이 스키마 없이 뽑을 때보다 일관성을 크게 높입니다.

[지시]
다음 텍스트에서 지식 그래프 트리플을 추출하라.
허용 노드 타입: 사람, 회사, 제품, 날짜
허용 관계 타입: 근무(사람→회사), 출시(회사→제품), 합류시점(사람→날짜)
스키마에 없는 타입·관계는 만들지 마라. 텍스트에 없는 사실은 추론하지 마라.
출력은 아래 JSON 스키마를 따른다.

[텍스트]
"김지수는 2021년 누리테크에 합류해 미리내 개발을 이끌었다."

구조화 출력으로 강제하기

추출 결과가 매번 다른 형식이면 파이프라인이 깨집니다. 구조화 출력(structured output) — JSON 스키마나 함수 호출(tool calling) — 로 형식을 강제합니다. 요즘 모델은 JSON 스키마를 주면 그에 맞는 출력을 보장하므로, 후처리 파싱이 안정됩니다.

{
  "nodes": [
    {"id": "김지수", "type": "사람"},
    {"id": "누리테크", "type": "회사"},
    {"id": "미리내", "type": "제품"},
    {"id": "2021", "type": "날짜"}
  ],
  "edges": [
    {"source": "김지수", "type": "근무",     "target": "누리테크"},
    {"source": "김지수", "type": "합류시점", "target": "2021"},
    {"source": "누리테크", "type": "출시", "target": "미리내"}
  ]
}

few-shot 예시 한둘을 프롬프트에 넣으면 경계 사례(대명사 해소, 암시된 관계)의 품질이 눈에 띄게 올라갑니다. “텍스트에 없는 사실은 추론하지 마라”는 지시는 환각을 억제하는 핵심 가드레일입니다 — 5·6단계의 추론과 이 단계의 추출을 분리해 두는 것이 중요합니다.

스키마 유도 추출과 구조화 출력 — 자유로운 문장이 허용 어휘의 거푸집을 지나 고정된 JSON 슬롯으로 나온다 문장 → 스키마 거푸집 → 구조화 출력 → 트리플 원문 문장 — 자유 형식 김지수는 2021년 누리테크에 합류해 미리내를 이끌었다. 타입 없음 · 표현 제각각 스키마 = 허용 어휘 (거푸집) 노드: 사람 · 회사 · 제품 · 날짜 관계: 근무 · 출시 · 합류시점 LLM 스키마 유도 추출 구조화 출력 강제 구조화 출력 — 고정 슬롯 nodes[ ] 사람 · 김지수 회사 · 누리테크 제품 · 미리내 edges[ ] 근무 김지수 → 누리테크 출시 누리테크 → 미리내 매번 같은 모양 → 파싱 안정 트리플 적재 자유로운 문장이 허용 어휘의 거푸집을 지나면, 매번 같은 모양의 JSON 슬롯으로 나온다 — 후처리 파싱이 안정된다
스키마 유도 추출과 구조화 출력이 하는 일 — 허용 어휘(거푸집)가 자유로운 문장을 고정된 JSON 슬롯으로 찍어 낸다. 타입이 앞에서 붙박이로 정해지므로, 나온 출력은 매번 같은 모양이라 파싱이 안정되고 트리플로 곧장 적재된다.

구축 도구와 파이프라인 — 바퀴를 다시 만들지 않기

실무에서는 이 파이프라인을 처음부터 짜지 않고 프레임워크를 씁니다. 대표적인 둘의 접근을 좌표로 잡아 둡니다.

  • LangChain LLMGraphTransformer: 문서를 넣으면 스키마 유도 추출로 GraphDocument(노드·관계 목록)를 돌려주고, Neo4jGraph 같은 스토어로 바로 적재합니다. 허용 노드/관계 타입을 파라미터로 제약할 수 있어, 위에서 본 스키마 유도를 코드로 표현합니다.
  • LlamaIndex 프로퍼티 그래프 인덱스(Property Graph Index): 문서에서 그래프를 구축하고, 그 위에 검색을 얹는 것까지 하나로 묶습니다. 추출기(SchemaLLMPathExtractor 등)를 스키마로 제약하고, 구축된 그래프를 5단계의 GraphRAG 검색에 그대로 연결합니다.
# LangChain — 스키마로 제약한 LLM 추출 (개념 스니펫)
from langchain_experimental.graph_transformers import LLMGraphTransformer

transformer = LLMGraphTransformer(
    llm=llm,
    allowed_nodes=["사람", "회사", "제품", "날짜"],
    allowed_relationships=["근무", "출시", "합류시점"],
    strict_mode=True,          # 스키마 밖 타입 배제 → 일관성
)
graph_docs = transformer.convert_to_graph_documents(documents)
neo4j_graph.add_graph_documents(graph_docs)   # 2단계의 Neo4j로 적재

파이프라인 설계에서 실질적으로 손이 많이 가는 곳은 청킹(컨텍스트 창에 맞게 나누되, 한 사실이 청크 경계에서 잘리지 않도록)과 비용(문서 전체를 LLM에 통과시키므로 토큰 비용·지연이 큼 — 배치·캐싱·모델 선택으로 관리)입니다.

품질·검증·휴먼인더루프 — 품질을 가르는 관문

LLM 추출의 진짜 승부처는 여기입니다. 뽑는 것은 쉬워졌지만, 믿을 수 있는가는 별개입니다. 세 가지 문제를 잡아야 합니다.

  • 환각(hallucination): 텍스트에 없는 관계를 지어냅니다. 대응 — 프롬프트 가드레일(“없는 사실 추론 금지”), 각 트리플에 출처 근거(source span)를 함께 뽑게 해 원문과 대조, 낮은 신뢰도 트리플은 보류.
  • 불일치(inconsistency): 같은 개체를 다르게 부릅니다(“누리테크” / “Nuritech” / “㈜누리테크”). 이것이 바로 3단계의 엔티티 해소입니다 — LLM이 등장해도 이 숙제는 사라지지 않고, 오히려 자유로운 표현 탓에 더 자주 필요합니다.
  • 스키마 위반·중복: 허용 밖 타입, 방향이 뒤집힌 관계, 같은 트리플의 중복. 스키마 검증기로 자동 거르고, 중복은 병합합니다.
세 가지 품질 문제와 검증 관문 — 자동으로 거르고, 남는 건 사람에게 세 가지 품질 문제와 검증 관문 환각 텍스트에 없는 관계를 지어냄 (김지수, 창업, 누리테크) ← 원문에 없음 방어 출처 근거 대조 · '추론 금지' 가드레일 불일치 같은 개체를 다르게 부름 누리테크 · Nuritech · ㈜누리테크 방어 엔티티 해소로 병합 (3단계 숙제) 스키마 위반·중복 (미리내, 근무, 김지수) ← 방향 뒤집힘 방어 스키마 검증기 자동 거름 · 중복 병합 검증 관문 신뢰도 점수로 분기 자동 통과 저신뢰·경계 보류 지식 그래프 휴먼인더루프 사람이 마지막 관문을 지킨다 확정 판정을 추출 프롬프트·규칙에 피드백 완전 자동화는 어렵다 — 검증기가 대부분을 거르고, 신뢰도가 낮거나 경계에 걸친 것만 사람이 지킨다
품질을 가르는 관문 — 환각·불일치·스키마 위반 세 문제를 각자의 방어로 거른 뒤, 검증 관문이 신뢰도로 분기한다. 통과분은 그래프로 자동 적재하고, 저신뢰·경계 트리플만 휴먼인더루프로 올려 사람이 확정하며, 그 판정은 다시 프롬프트·규칙으로 피드백된다.

이 검증을 완전 자동화하기 어렵기 때문에, 실무 표준은 휴먼인더루프(human-in-the-loop)입니다 — 신뢰도가 낮거나 스키마 경계에 걸친 트리플만 사람에게 올려 검수하고, 그 판정을 다시 추출 프롬프트·규칙에 피드백합니다. (예: 의료 논문에서 약물–질환–유전자 트리플을 LLM으로 대량 추출하되, 안전이 걸린 관계는 도메인 전문가가 검수해 확정하는 방식.) 이 “사람이 마지막 관문을 지킨다”는 원칙은 7단계에서 에이전트가 그래프를 쓰는 단계로 그대로 이어집니다.

정리

  • LLM이 추출의 판을 뒤집었다: 스키마를 프롬프트로 유도하고 구조화 출력으로 강제하면, 라벨링·재학습 없이 새 도메인·새 관계에 적응하는 추출기가 됩니다.
  • 스키마 유도가 일관성의 열쇠입니다. 허용 노드/관계를 명시하고 “없는 사실 추론 금지”를 가드레일로 두면 환각과 잡음이 크게 줍니다.
  • 도구가 바퀴를 대신 만들어 줍니다: LangChain LLMGraphTransformer, LlamaIndex 프로퍼티 그래프 인덱스가 추출→적재→검색을 이어 줍니다. 손이 가는 곳은 청킹과 비용입니다.
  • 품질을 가르는 것은 추출이 아니라 검증입니다. 환각·불일치(엔티티 해소)·스키마 위반을 거르고, 휴먼인더루프로 마지막 관문을 지킵니다 — LLM이 있어도 3단계의 숙제는 남습니다.

다음 글에서는 이렇게 지은 그래프를 검색에 결합합니다 — 벡터 RAG의 한계를 그래프로 메우는 GraphRAG입니다.

다음 학습 (Next Learning)