coredot.today
기술 탐색으로 돌아가기
검색·RAG연구

AEVS

트리플의 주어·관계·목적어마다 원문 글자 위치를 묶고, 본문에서 찾은 말로만 조합한 뒤 원문으로 되돌려 검증한다 — 점수보다 '어디서 왔는지 확인할 수 있다'를 사는 지식 그래프 추출

직접 해보기 6실측
종류
논문
언어
Python
사실 확인
2026.11.01

TRY IT

직접 해보기

OVERVIEW

개요

무엇인가

AEVS는 MDPI Computers 2026년 3월호(15권 3호, 178)에 실린 「Grounded Knowledge Graph Extraction via LLMs: An Anchor-Constrained Framework with Provenance Tracking」(Yang·Chen·He·Zhao)의 방법입니다. 이름은 Anchor(앵커)·Extraction(추출)·Verification(검증)·Supplement(보충)의 머리글자입니다.

풀려는 문제는 LLM으로 문서에서 (주어, 관계, 목적어) 트리플을 뽑을 때 섞여 드는 "세상에서는 참이지만 본문에는 없는" 줄입니다. "Steve Jobs co-founded Apple Inc. in Cupertino in 1976. He served as CEO until his resignation in 2011."에서 (Steve Jobs, 국적, 미국)이나 (Steve Jobs, 사망연도, 2011)이 붙어 나오는 식입니다. 기존 방법은 트리플만 내놓고 원문 위치를 남기지 않으니 충실성을 검증할 길이 없다는 것이 저자들의 진단입니다. 그래서 '맞다/틀리다' 대신 원문만 보고 기계적으로 확인할 수 있는 '근거가 있다/없다'로 문제를 다시 정의합니다. 주어·관계·목적어 셋 모두 원문의 글자 구간을 가리킬 수 있어야 충실한 트리플입니다.

보장하는 것은 "이 문서가 그렇게 말했다"이지 "세상이 그렇다"가 아닙니다. 논문 예문 자체가 세상과 다른데도(애플은 로스앨터스에서 출발했고 'Apple Inc.'는 2007년 이름입니다) (Apple Inc., location, Cupertino)는 근거 있는 트리플로 통과합니다. 출처와 진실은 다른 물건입니다.

어떻게 동작하나

1. 앵커 찾기
개체·관계구·속성값을 글자 위치와 함께 목록화, 관계구는 스키마 이름으로 사상
→
2. 앵커로만 추출
주어=개체 앵커, 관계=관계 앵커의 사상, 목적어=개체·속성 앵커
→
3. 복원 검증 + 보충
원소마다 문자열로 원문에 되돌림, 실패분만 LLM 재검토, 안 쓰인 앵커로 보충
  • 앵커는 (글자, 종류, 시작, 끝, 메타데이터) 다섯 칸입니다. LLM이 찾되 코드가 위치 범위, 글자-위치 일치(다르면 본문 검색으로 위치를 고침), 스키마 사상 이름(오타는 퍼지 매칭)을 검사합니다. LLM이 글자 위치를 자주 틀린다는 것은 논문 스스로 적은 전제입니다.
  • 추출은 열린 생성을 앵커 조합 선택으로 바꿉니다. 단, 관계 칸은 본문 관계 앵커 또는 스키마 전체와의 합집합이라, 개체는 본문으로 닫히지만 관계는 스키마의 아무 이름(WebNLG 159종, REBEL 200종)에 열려 있습니다.
  • 복원 사다리는 LLM 없이 스키마 매칭(관계만) → 정확 일치 → 부분 일치(포함 관계) → 본문 검색 순으로 원소를 되돌립니다. 셋 다 복원되면 바로 통과, 하나라도 실패하면 어느 원소를 못 찾았는지 알려 주고 LLM이 재검토합니다.
  • 보충은 한 번도 쓰이지 않은 앵커를 겨냥해 한 번 더 추출하고, all-MiniLM-L6-v2 임베딩 코사인 0.85 이상이면 중복으로 버립니다.

논문이 보고한 결과(WebNLG+ 2020 관계 159종 1,165문장, REBEL 200종 1,000문장, Wiki-NRE 45종 1,000문장, 백본 GPT-4o-mini·GPT-5.1·Claude 4.5 Haiku·Gemini 2.5 Flash):

항목 (논문 수치)값
그냥 묻기 → AEVS (GPT-4o-mini, WebNLG Strict F1)0.458 → 0.760, 4모델 × 3데이터셋 × 3기준 36칸 모두 상승
학습 모델 대비 (REBEL, Claude 4.5 Haiku, Partial F1)0.797 vs GenIE 0.385
같은 GPT-4o-mini의 EDC 대비 (Partial F1)WebNLG +0.007, REBEL +0.012, Wiki-NRE +0.074
부품별 기여 (Partial F1)+앵커 +0.117~+0.324, +복원 검증 −0.010~+0.011, +보충 최대 +0.045
앵커 재현율 (REBEL·Wiki-NRE)개체 86.2~99.7%, 관계 34.1~62.1%
부분 복원 실패의 모양99% 이상이 '주어 ✓ 관계 × 목적어 ✓'
문장당 LLM 호출 / 입력 토큰2.83~4.28회 / 3,754~16,867 (대부분 프롬프트에 넣는 스키마 몫)

성능의 대부분은 앵커 제약에서 나왔고, 복원 검증은 점수를 거의 바꾸지 않았습니다. 저자들은 검증의 가치를 점수가 아니라 출처 보증에서 찾습니다. 남은 오류는 개체가 아니라 관계에 몰려 있습니다.

빠른 시작

공개 저장소는 git clone https://github.com/yyz-nbt/AEVS로 받을 수 있지만, 아래 '한계와 주의'처럼 3단계가 논문과 다릅니다. 직접 만든다면 핵심은 위치를 LLM에게 묻지 않고 코드가 정하는 것입니다. 앵커 글자만 받아 원문에서 찾고, 한국어는 NFC와 띄어쓰기 차이를 먼저 흡수합니다.

python
import re, unicodedata

def norm(s: str) -> str:
    return unicodedata.normalize("NFC", s)

def locate(text: str, anchor: str):
    """앵커 글자를 원문에서 찾아 (start, end)를 돌려준다. 못 찾으면 None → 버리고 건수를 기록"""
    text, anchor = norm(text), norm(anchor)
    i = text.find(anchor)
    if i >= 0:
        return i, i + len(anchor)
    # 모델이 넣은 공백('1976 년', '2 조 원')을 흡수: 글자 사이 공백을 선택으로
    chars = [re.escape(c) for c in anchor if not c.isspace()]
    m = re.search(r"\s*".join(chars), text)
    return (m.start(), m.end()) if m else None

text = "삼성전자는 1969년 수원에서 설립되었다."
print(locate(text, "1969 년"))   # (6, 11) — 원문 글자 범위로 되돌림

관계 복원은 '그 관계로 사상된 본문 관계 앵커가 있는가'로 판정하고, 부분 일치에는 최소 길이(예: 3글자)를 두고, 재검토는 추출기와 다른 모델(또는 NLI)에 맡깁니다.

코어닷투데이 실측

2026년 10월 말, 로컬 qwen3.5:9b(Ollama, 온도 0.3, 사고 모드 끔, 1회 실행)로 다시 돌렸습니다. 한국어는 직접 쓴 30문장(정답 트리플 55개, 관계 스키마 25종; 참인 문장 15개에는 국적·설립자 같은 함정을, 반사실 문장 15개에는 "에펠탑은 로마에 있다" 같은 세상과 다른 값을 넣음), 영어는 WebNLG 시험셋 무작위 20문장(정답 69개, 스키마 159종)입니다. 1·2단계 출력은 같게 두고, 3단계는 저장소 코드와 논문 식 10~18·Box 3·4를 코어닷투데이가 구현한 것을 나란히 붙였습니다.

F1 (정밀도 / 재현율)한국어 30문장WebNLG 20문장
그냥 묻기, 스키마 없음—0.178 (0.182 / 0.174)
그냥 묻기, 스키마 제공 (호출 1회)0.800 (0.840 / 0.764)0.587 (0.649 / 0.536)
공개 코드 (호출 2회)0.674 (0.800 / 0.582)0.589 (0.633 / 0.551)
논문 3단계, 보충 없음0.644 (0.829 / 0.527)0.578 (0.627 / 0.536)
논문 전체 (한국어 호출 3.47회)0.716 (0.850 / 0.618)0.600 (0.639 / 0.565)
  • 한국어에서는 그냥 묻기가 이겼습니다. 정밀도는 같고(0.84 대 0.85) 재현율이 0.764→0.618로 떨어졌습니다. 2단계를 지나며 50줄이 45줄로 줄었고, 45줄 중 완전 복원은 16줄, 재검토 29줄 중 거부 10줄의 6줄이 정답이었습니다.
  • 스키마가 대부분의 일을 했습니다. WebNLG에서 스키마를 빼면 0.178, 넣으면 0.587이고 AEVS의 나머지 단계가 더한 것은 +0.013입니다. 저장소 평가 스크립트의 Exact F1은 오히려 AEVS가 낮았습니다(0.277 대 0.444). 앵커가 "the Acharya Institute of Technology of Bangalore, India"처럼 본문 글자를 길게 가져오기 때문입니다.
  • 환각이 나오지 않았습니다. 스키마를 준 그냥 묻기에서 본문에 없는 값은 50줄 중 0, 함정 0, 반사실 문장을 세상 값으로 고친 경우 15문장 중 0이었습니다. 유일한 예외는 한국어 문장에서 나온 (Albert Einstein, birthPlace, Ulm)인데, 공개 저장소의 프롬프트 예시가 그대로 복사된 것이었습니다.
  • 검증기가 본문보다 세상을 믿었습니다. 본문에 충실한 정답 트리플만 검증기에 따로 물었더니(해석 가능 161건) 참인 문장 89건 중 8건(9.0%), 반사실 문장 72건 중 12건(16.7%)을 거부했고, 반사실 쪽 7건은 "현실과 다르다"가 이유였습니다(참인 문장에서는 0건). "에펠탑은 로마에 있다"의 (에펠탑, 위치, 로마)가 그렇게 지워졌습니다.
  • 글자 위치는 영어도 한국어도 열에 아홉 틀렸습니다. 모델이 보고한 위치가 정확한 앵커는 한국어 15.5%(116개 중 18), 영어 13.3%(143개 중 19). 앵커 글자가 본문에 그대로 있는 비율은 영어 100%, 한국어 81.0%이고, 못 찾은 22개 중 20개가 "1976 년" 같은 원문에 없는 띄어쓰기였습니다.
  • 공개 코드의 판정을 결정론적으로 확인했습니다. 논문 그림 3의 앵커 10개를 그대로 만들어 저장소 TripletRestorer에 WebNLG 스키마로 넣자, 논문이 환각 예로 든 deathYear·nationality·almaMater·deathDate 네 트리플이 모두 통과했습니다.

언제 쓰고, 언제 피하나

상황판단
의료·법률·공시처럼 각 줄을 원문으로 되짚어 감사해야 한다앵커 + 코드가 정한 글자 위치를 트리플마다 저장. 호출 3~4배는 F1이 아니라 확인 가능성을 사는 비용
추출 모델이 환각을 많이 낸다 (논문의 GPT-4o-mini 조건)복원 검증과 재검토의 이득이 커질 수 있음. 재검토는 다른 모델로
짧은 문장, 스키마가 있고, F1이 목표먼저 스키마를 준 프롬프트 한 번을 기준선으로 잰다. 환각이 드물면 거름망은 맞는 줄만 흘린다
문서가 세상을 앞서는 곳 (정정 공시, 개정 조례, 반사실 시나리오)LLM 재검토가 맞는 줄을 지울 수 있음. 반사실 시험 문항으로 검증기부터 점검

한계와 주의

  • "EDC보다 최대 +0.152"는 서로 다른 모델끼리의 비교입니다. Gemini 2.5 Flash로 돌린 AEVS와 GPT-4o-mini로 돌린 EDC의 차이이고, 같은 백본이면 +0.007~+0.074입니다. 'EDC와 비슷하거나 조금 낫고, 대신 출처를 준다'가 정확한 요약입니다.
  • 환각률은 자기 검증의 거부율입니다. 재검토를 같은 백본이 하므로 Claude 4.5 Haiku의 0.23~0.44%는 부분 복원 트리플 승인율 98.7~99.0%와 같은 이야기입니다. '덜 지어냈다'와 '너그럽게 통과시켰다'가 구별되지 않습니다.
  • 보충 트리플은 환각 집계 밖입니다. 환각 정의의 분모가 '2단계 트리플'이고, 알고리즘 2의 보충 부분은 의미 중복만 거르고 복원·재검토를 거치지 않습니다(본문 설명은 거친다고 씀).
  • 공개 코드는 논문과 다릅니다. 2026년 1월 7일 두 번 커밋 뒤 갱신이 없고, 셋 중 둘만 복원돼도 통과(restored >= 2), 관계는 스키마 목록에 있기만 하면 복원, LLM 재검토와 보충이 없고, 못 찾은 앵커를 버리지 않으며, 중복 문턱이 0.9입니다. 모델이 위치에 null을 쓰면 예외로 그 문장의 트리플을 통째로 잃고, 평가 스크립트는 논문의 Partial·Strict·Exact를 출력하지 않습니다.
  • '복원'은 글자가 있다는 뜻이지 관계가 맞다는 뜻이 아닙니다. "in" 앵커가 location으로 사상되면 '쿠퍼티노에서 창업'이 소재지로 통과하고, 두 글자 "in"은 foundingYear 같은 이름에 포함돼 부분 일치로 엉뚱하게 복원됩니다. 원소의 위치와 관계의 함의는 따로 확인해야 합니다.
  • '그냥 묻기'에 스키마를 줬는지 논문이 밝히지 않습니다. 위 실측에서 그 차이만으로 F1이 0.178과 0.587로 갈렸으니, '그냥 묻기 대비 +0.2~+0.3'의 뜻이 여기에 달려 있습니다.
  • 그 밖의 어긋남. 표 3 GenIE Strict는 F1(0.362)이 P(0.353)·R(0.356)보다 크고, REBEL "200종"인데 공개 스키마 파일은 196줄입니다. 문장 단위라 상호 참조('He'가 누구인지)를 못 풀고, 한중일 문자는 평가하지 않았습니다.
  • 실측의 한계. 작은 표본, 1회 실행, 짧은 문장, 직접 만든 한국어 정답, 논문 모델보다 약한 9B, 3단계는 논문을 읽고 구현한 것입니다. 논문을 반박하는 증거가 아니라 한 가지 조건에서 일어난 일의 기록입니다.

DEEP DIVE

더 깊이 읽기