23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
아래는 "LLM 최신 연구 동향 알려줘" 라는 질문에 대한 adot.ai 의 GPT-4o-mini 답변입니다.
흥미롭게도, 아래처럼 에이닷 모바일 앱에서는 동일한 질문에 대해 위 예시보다 훨씬 더 풍부하고 정확한 답변을 제공하고 있습니다.
동일하게 GPT-4o-mini를 기반으로 하는데도 이러한 품질 차이가 발생하는 이유는 무엇일까요?
바로 접근 방식의 차이에 있습니다.
첫 번째 예시는 단순히 LLM만 활용한 반면, 에이닷 모바일 앱은 LLM과 검색 기능을 결합한 'LLM search' 시스템을 구축했기 때문입니다.
에이닷은 답변 하단에 빨간색 네모로 표시된 출처 웹페이지들을 실시간으로 스크래핑하여 최신 정보를 LLM에 제공합니다.
이러한 접근 방식을 통해 사전 학습 데이터의 한계를 넘어 최신 정보를 반영한 더욱 상세하고 정확한 답변을 생성할 수 있게 되었습니다.
LLM은 학습된 데이터를 기반으로 텍스트를 생성하고 이해하는 데 특화되어 있지만, 실시간 정보 검색이나 출처 제공에는 한계가 있습니다.
이러한 한계를 극복하고자 LLM Search는 아래와 같은 기능을 추가로 제공합니다.
실시간 웹 검색 기능
신뢰할 수 있는 출처 제공
최신 정보 접근 기능
참고로 작년 말부터 오픈AI도 검색과 출처 제공을 시작했습니다.
현재 에이닷의 LLM search 엔진은 PAAS입니다.
GPT-4o-mini 사용을 제외한 나머지 LLM search 기능들은 SKT에서 직접 개발했으며, 프로젝트명은 PAAS (PAA Search)입니다.
PAAS의 데이터 흐름은 아래와 같습니다.
위 이미지에서 빨간색 네모로 표시된 두 부분이 바로 오늘 소개해 드릴 HTML 본문 추출기입니다.
지금부터 HTML에서 더 깔끔하고 정확하게 본문을 추출하기 위해 그동안 연구하고 고민했던 내용들을 공유해 드리겠습니다.
실시간 본문 추출기는 다음과 같은 제약 조건을 충족해야 합니다:
시간 제약
본문 추출 작업은 1초 이내에 완료되어야 합니다
전체 프로세스(HTML 가져오기 + 본문 추출)는 4초 이내로 제한됩니다
HTML 가져오기에 최대 3초가 소요되므로, 본문 추출에 쓸 수 있는 시간은 1초만 남게 됩니다.
손실 없는 제거
문서 크기는 최소화하되 중요 정보의 손실이 없어야 합니다.
LLM 토큰 제한으로 인해 모든 문서(최대 10개)의 총 텍스트는 3만 자 이내여야 합니다
광고, 메뉴, 목록 등 검색에 불필요한 요소들은 가급적 제거해야 합니다
성능 기준
벤치마크 라이브러리인 trafilatura보다 우수한 성능을 보여야만 실제 서비스에 적용됩니다
1) CSS 활용
본문이나 중요한 내용이라고 잘 알려진 HTML 속성들만 사용하는 방식입니다.
trafilatura 는 이와 같은 방식을 사용하고 있습니다.
https://github.com/adbar/trafilatura/blob/master/trafilatura/xpaths.py
단점
설정 파일의 수동 관리와 부정확한 태그 지정은 중요 정보의 누락을 초래할 수 있습니다.
2) 키워드 (og tag, user query) 활용
사용자 쿼리나 og tag 의 title, description 등과 유사도가 높은 영역을 찾아보자는 아이디어입니다.
단점
키워드를 포함하더라도 추출할 영역의 범위를 정하는 것이 불가능합니다.
단순히 키워드가 포함된 텍스트의 직속 부모 태그만 추출할 경우 단어나 문장 한 개만 추출되는 문제가 있을 수 있고, 영역을 넓게 잡으면 문서 전체가 되기 때문입니다.
유사도가 높은 정도를 정하는 것이 어렵습니다.
문장 일치 인지 단어 일치 인지, 임베딩을 써야 할지... 등등
위의 방식들은 각 사이트마다 다를 수 있어서 수동 관리가 많이 필요하므로, 좀 더 일반화된 아이디어가 필요했습니다.
3) Longest Child
트리구조에서 (실험을 통해) 고정된 depth를 정하고, 가장 size가 큰 노드의 하위 text 전체만 추출하자는 아이디어입니다.
단점
만약 고정된 depth를 정할 수 없다면 (i.e. 사이트마다 최적 depth가 다르다면), 결국 다른 로직이 추가로 필요합니다.
위 방식들의 효용과 한계를 검증하기 위해 다양한 웹사이트에서 실험을 진행했습니다.
실험 결과들 중 일부를 공유합니다.
번호 | trafilatura | text 전체 길이 | 키워드만 활용 | css만 활용 | Longest Child만 활용 | URL |
|---|---|---|---|---|---|---|
1 | 8095 | 40782 | 40782 | 5082 | 40581 | https://namu.wiki/w/2025%20KBO%20%EC%8B%A0%EC%9D%B8%20%EB%93%9C%EB%9E%98%ED%94%84%ED%8A%B8 |
2 | 1638 | 8841 | 8680 | 3507 | 8841 | https://namu.wiki/w/%EC%9A%A9%EC%9D%B8%20%EB%B2%84%EC%8A%A4%205500-2 |
3 | 4522 | 5023 | 4875 | 4892 | 5023 | https://triple.guide/articles/86993982-1e41-41ae-a0f1-e9aabf3053b1 |
4 | 2769 | 4107 | 3923 | 3961 | 4107 | https://m.blog.naver.com/sunnny_j/223239126135 |
5 | 385 | 1015 | 339 | 619 | 761 | http://lonelyplanet.co.kr/magazine/articles/AI_00003545 |
6 | 4139 | 6444 | 6088 | 6204 | 6444 | https://m.blog.naver.com/seoulhiker/222453695185 |
7 | 593 | 3151 | 2887 | 3014 | 3151 | https://m.blog.naver.com/saramcomm1/222980976728 |
8 | 3431 | 5846 | 5235 | 5256 | 5846 | https://angelosuu.tistory.com/5 |
9 | 2811 | 3165 | 566 | 3144 | 2893 | https://visithalla.jeju.go.kr/contents/contents.do?id=49 |
10 | 632 | 7111 | 6801 | 6928 | 7111 | https://m.blog.naver.com/cr23_miku_kr/222324612403 |
11 | 953 | 1748 | 199 | 1727 | 1476 | https://visithalla.jeju.go.kr/contents/contents.do?id=61 |
표에서 빨간색으로 표시된 부분은 과도한 제거로 인해 본문 일부가 유실된 케이스입니다.
예를 들어, 11번 "키워드만 활용"의 199결과는 아래와 같습니다.
https://visithalla.jeju.go.kr/contents/contents.do?id=61
동절기(10,11,12,1, 2, 3월) 하절기(4, 5, 6, 7, 8, 9월) 입산시간 05:00 부터
성판악탐방로 입구 하절기 12:30, 동절기 11:30부터, 진달래밭통제소 하절기 12:30, 동절기 11:30 정상 탐방 통제
정상(백록담) 하절기 14:30 동절기 13:30 하산
탐방 가능 여부 : 탐방 가능 (기상 이변 발생 시 통제)실제 서비스 적용을 위해서는 이러한 유실 사례를 완전히 제거해야 합니다.
(위 표는 실험 결과의 일부 예시입니다. 1856개 URL에 대한 결과는 "성능 비교" 및 "Appendix" 섹션을 참고해 주세요.)
실험 결과를 요약하면 아래와 같습니다.
CSS 나 키워드보다, 트리구조의 depth나 텍스트 밀도 등의 feature 를 활용하여 일반화한 방식이 더 robust 하고 좋은 성능을 보였습니다.
CSS 만 사용하면 나무위키에서 본문 유실이 너무 컸습니다. (위의 예시 1,2,7번 참고, 실제로 CSS 방식을 사용하는 trafilatura 에서도 유실이 발생)
og tag 가 없는 경우가 많고, og tag가 있더라도 해당 영역만 보면 정보 유실이 큰 경우가 많았습니다.
따라서 Longest Child 가 안정된 성능을 보이지만, 최적 depth 가 문서마다 다르다는 문제가 있었습니다.
즉, 트리구조와 일반화된 feature 를 활용하면서 사이트에 따라 flexible 하게 동작할 수 있는 새로운 로직이 필요했습니다.
다양한 실험을 통해, 처음 보는 구조의 HTML 에 대해서도 flexible 하게 노이즈를 제거할 수 있는 방법을 찾아냈습니다.
<DOM>은 부모/자식 관계로 이루어진 트리 구조라서, 모든 노드는 자신의 자식 노드들의 텍스트 길이 비율을 알아낼 수 있습니다.
이때 노이즈만으로 이루어진 노드의 경우에는 자식 노드의 비율이 비슷한 경향을 보였습니다.
따라서 최 상위 노드에서부터 아래로 내려가며 계산하여, 자식 노드 비율이 한쪽으로 치우치는 경우를 핵심 본문으로 추출해 낼 수 있었습니다.
예를 들어, 위와 같은 HTML 에서 각 자식 노드의 비율은 아래와 같습니다.
body 의 자식 노드 비율 = 6 : 4
child1 의 자식 노드 비율 = 2 : 3 : 1
child2 의 자식 노드 비율 = 3 : 1
자식 노드의 비율이 치우치는 정도는 entropy를 이용하여 계산했는데요, 먼저 entropy가 무엇인지 간단히 알아보겠습니다.
entropy는 데이터의 불확실성이나 무질서도를 수치로 나타내는 값입니다.
예를 들어, "a : b" 의 비율이 "0.5 : 0.5" 인 상태는 "0.1 : 0.9" 보다 무질서한 상태입니다.
누가 이겼는지 확실한 경우를 질서 있다고 보는 것입니다.
이를 수치화해야 로직에 사용할 수 있는데요, 이때 아래와 같은 수의 성질을 이용합니다.
0.5 x 0.5 = 0.25
0.4 x 0.6 = 0.24
......
0.2 x 0.8 = 0.16
0.1 x 0.9 = 0.09
위처럼 곱하기를 하면 비율의 차이가 클수록 값이 작아집니다.
즉, 더 작은 값일 수록 한쪽으로 치우친 경우입니다.
위의 성질을 이용해서 무질서도를 0~1 사이의 값으로 계산할 수 있게 만든 공식이 아래의 entropy 공식입니다.
# entropy 공식, H(x) = entropy
H(x) = ∑−P(x)⋅log(P(x))
# 실제 구현된 코틀린 코드
val entropy = descendantLengthList.filter { it > 0 }.sumOf {
it.toDouble() / descendantLength * ln(it.toDouble() / descendantLength)
} * -1.0위 코드에서 childLengh가 아니라 descendantLength 인 이유는, 직속 자식 뿐 아니라 하위 모든 자식의 텍스트 길이에 대해 계산하기 때문입니다.
역시 실험을 통해, entropy를 사용 했을 때 중요한 내용을 빠뜨리지 않으면서 안정적으로 텍스트를 줄이는 것을 확인했습니다. (최대 제거율 40%, 평균 제거율 10%)
종종 중요한 내용을 빠뜨리는 trafilatura 에 비해 안정적이기 때문에 서비스에 적용할 수 있었습니다. (전체 URL에 대한 결과는 "성능 비교" 및 "Appendix" 섹션 참고)
번호 | trafilatura | text 전체 길이 | 키워드만 활용 | css만 활용 | Longest Child만 활용 | Entropy만 활용 |
|---|---|---|---|---|---|---|
1 | 8095 | 40782 | 40782 | 5082 | 40581 | 40581 |
2 | 1638 | 8841 | 8680 | 3507 | 8841 | 8579 |
3 | 4522 | 5023 | 4875 | 4892 | 5023 | 4644 |
4 | 2769 | 4107 | 3923 | 3961 | 4107 | 3309 |
5 | 385 | 1015 | 339 | 619 | 761 | 561 |
6 | 4139 | 6444 | 6088 | 6204 | 6444 | 5428 |
7 | 593 | 3151 | 2887 | 3014 | 3151 | 2440 |
8 | 3431 | 5846 | 5235 | 5256 | 5846 | 5054 |
9 | 2811 | 3165 | 566 | 3144 | 2893 | 2627 |
10 | 632 | 7111 | 6801 | 6928 | 7111 | 6353 |
11 | 953 | 1748 | 199 | 1727 | 1476 | 1308 |
Kaggle과 같은 데이터 과학 대회에서는 복잡한 딥러닝 알고리즘보다 간단한 모델들을 앙상블로 결합한 방식이 자주 우승을 차지합니다.
앙상블은 여러 모델의 장점을 결합하여 더 안정적이고 정확한 예측을 가능하게 만들기 때문입니다.
저희도 entropy 만을 사용해서 본문을 놓치는 경우를 대비하여, 추가 feature들과 기존에 잘 알려진 CSS 필터링 로직을 함께 사용했습니다.
PAAS에서 현재 사용 중인 실제 구현 로직을 소개해 드리겠습니다.
entropy 는 depth 가 낮을수록 (c.f. 가장 높은 노드,body tag의 depth = 1) entropy도 낮아지는 경향이 있습니다.
예를 들어, 최하위 노드에서는 글자 수가 1 : 10 이어도 entropy 가 굉장히 낮아지기 때문입니다.
그런데 글자 수가 1이나 10인 경우는 본문 전체일 확률이 낮기 때문에, entropy에 depth 값과 텍스트 밀도 가중치를 주어 유의미한 본문일 확률이 높아지도록 만들어 사용했습니다.
# 실제 구현된 코틀린 코드
stat.density = stat.descendantLength.toDouble() / (1 + stat.descendantCount)
stat.rankScore = stat.entropy * stat.depth.toDouble() / (0.1 + stat.density.pow(stat.density))그리고 드물지만 entropy가 동일한 경우의 정렬 기준은 "Appendix. HTML 노드 feature 들의 회귀분석 결과" 를 그대로 사용했습니다.
fun List<ElementStat>.sortByEntropy(): List<ElementStat> {
return this.sortedWith(
compareBy<ElementStat> { it.rankScore }
// rankScore가 동일한 경우
.thenBy { it.descendantLength / it.outerHtmlSize }
.thenByDescending { it.depth }
)
}웹 상의 무수한 케이스에 대비하여, 과도하게 제거한 경우거나 유효한 CSS 선택자가 전혀 없는 경우에는 잘 알려진 CSS 선택자를 적용하는 방어 로직도 함께 사용했습니다.
기존에 팀에서 수동으로 찾아냈던 CSS 선택자들 (e.g. "#book-info") 과 trafilatura 에서 사용하는 CSS를 함께 활용했습니다.
val removalThreshold = extractProperties.removalThreshold
val enoughRemaining = 1 - removalThreshold
val notEnoughText =
if (bestEntropyElement.descendantLength / (0.1 + elementCandidates.last().descendantLength) < enoughRemaining)
true else false
if (notEnoughText || !bestEntropyElement.containsCSS) {
val bestCssElement = elementStats.filter { it.containsCSS }
bestElementList.addAll(bestCssElement)
}최 하위 노드에서부터 feature들을 집계하면서 동시에 text를 html 포지션 순서대로 memory에 저장해두고,
best element 를 찾으면 해당 element 의 startIndex 와 endIndex 로 저장해둔 memory에서 꺼내 재조합 하는 방식으로 코드를 개션했습니다.
이전의 노드 순회 방식 (i.e. merge([node.text() for node in jsoupElements])) 에 비해 본문 추출 속도가 약 30배 정도 빨라졌습니다.
# 최초 1회 노드 순회하며 Memorize
fun dfs(element: Element, depth: Int): ElementStat {
var descendantCount = element.childrenSize()
val tagName = element.tagName()
val startIndex = textBuilder.length
...... (생략) ......
val endIndex = textBuilder.length
val descendantLength = endIndex - startIndex
...... (생략) ......
}
# best element 들을 찾아 greedy 하게 본문 추출
fun String.getMainTextByBestEntropy(elementStats: List<ElementStat>): String {
...... (생략) ......
val (resultStartIndex, resultEndIndex) = bestElementList.findMinMaxIndex()
return this.substring(resultStartIndex, resultEndIndex)
}1856개 url 대상으로 테스트 했을 때, 지금까지 설명한 HTML 본문 추출기를 통해 정보의 유실 없이 평균 10% 정도의 노이즈를 제거하는데 성공했습니다.
"Appendix. 실험에 사용한 데이터셋" 참고
현재 PAAS에 적용되어 HTML 본문이 50만자 이내인 경우, 실시간 본문 추출에 사용중입니다.
html 본문이 50만자 이상인 경우 (e.g. 나무위키 아이유) 노이즈 포함 확률이 낮고 (대부분이 유의미한 정보), 1초 이상 소요되는 경우가 종종 발생하기 때문입니다.
실험을 위해 아래 두 가지 척도를 정의했습니다. (핵심 본문이 true 라고 한다면)
precision : 얼마나 제거 했는가
recall : 본문의 정보가 유실되지 않았는가
목표
precision 이 낮더라도, (실험데이터에 대해서는) recall 이 100% 여야 실 서비스에 사용
결과
PAAS 본문 추출 로직으로 평균 10% 정도의 노이즈를 제거하며, 본문 내용이 유실되는 경우 없이 추출에 성공했습니다. (recall 100%)
trafilatura 는 평균 55% 가량 제거하지만, 본문 내용이 유실되는 경우가 꽤 발생했습니다. (대략 20~30% 비율로 본문 일부 유실)
예시 1
https://bbs.ruliweb.com/community/board/300147/read/30581769
본문의 주요 내용
"... 이런 류의 게임을 뭐라고 부르나요?"
댓글 : "타워디펜스 장르인거 같습니다."
trafilatura 는 71% 를 제거하지만 댓글을 추출하지 않아서 LLM에게 유용한 정보를 전달하지 못하는 문제가 있습니다.
PAAS 본문 추출 로직은 48% 제거하며 본문과 댓글 모두 추출합니다.
예시 2
trafilatura 는 76% 제거하지만, 등반 적절한 시간대와 기타 리뷰 등, 유의미한 정보가 모두 유실하는 문제가 있습니다.
PAAS 본문 추출 로직은 26% 제거하며 아래와 같이 본문 내용을 유실하지 않고 모두 추출합니다.
trafilatura 는 precision 이 높지만 recall 이 70~80% 이고, PAAS 본문 추출기는 trafilatura 보다 precision 은 낮지만 recall 이 100%
2k 문서를 모두 눈으로 살펴보지는 못하므로, 통계적 이상치 case 들을 site 별로 샘플링하여 직접 살펴 본 결과
("Appendix. Baseline 활용을 위한 trafilatura 와의 자카드 유사도 비교" 참고)
실험데이터에서 PAAS 본문 추출기가 본문을 유실한 경우는 없었습니다.
Y값
테스트 HTML 들에서 직접 본문이라고 볼 수 있는 노드(HTML 태그)들을 찾아, 해당 노드를 정답으로 라벨링한 데이터
X값
각 노드의 text 에서 구한 feature 들
depth: 트리의 level 값, e.g. 최상위 노드 의 depth 는 1, 직속 하위 노드의 depth 는 2, ...
childrenSize: 자식 노드의 개수
entropy: 자식들의 텍스트 길이 무질서도, 위의 "Entropy 를 활용한 문제 해결" 참고
density: 하위 자식 수에 대한 텍스트 밀도, 위의 "rankScore" 참고
text/html: outer HTML 길이에 대한 (태그 및 기타 속성을 제외한) 텍스트 밀도
depth: 0.23551285
childrenSize: -0.02007661
entropy: -0.15763946
density: 0.11217826
text/html: -0.21388728
Wald 테스트 결과, childrenSize를 제외한 모든 feature가 통계적으로 유의미
특히 depth, entropy, text/html이 가장 유의미한 feature
Wald 테스트는 각 계수가 통계적으로 유의미한지를 판단하는 데 사용됩니다.
이 테스트는 계수의 추정치를 표준 오차로 나눈 값을 제곱하여 계산한 결과입니다.
depth: p-value가 0.0001보다 작아 매우 유의미합니다. 이는 depth가 분류에 중요한 영향을 미친다는 것을 의미합니다.
childrenSize: p-value가 0.5005로, 일반적인 유의수준(0.05)보다 높습니다. 따라서 childrenSize는 통계적으로 유의미하지 않을 수 있습니다.
entropy: p-value가 0.0001보다 작아 매우 유의미합니다. entropy도 분류에 중요한 역할을 합니다.
density: p-value가 0.0003으로 유의수준 0.05보다 낮아 유의미합니다. density도 분류에 영향을 미칩니다.
text/html: p-value가 0.0001보다 작아 매우 유의미합니다. 이 feature도 분류에 중요한 영향을 미칩니다.
테스트에 사용한 URL 은 총 1856개이며, 아래처럼 6개 그룹으로 나누어 실험에 사용했습니다.
case1. url_short_community : text 100자 이하 & 커뮤니티 사이트
case2. url_short_etc : text 100자 이하 & 일반 사이트
case3. url_medium_community : text 1000자 이하 & 커뮤니티 사이트
case4. url_medium_etc : text 1000자 이하 & 일반 사이트
case5. url_long_community : text 1000자 이상 & 커뮤니티 사이트
case6. url_long_etc : text 1000자 이상 & 일반 사이트
위의 URL 들은 아래 순서대로 필터링 & 조인하여 만들었습니다.
자유 크롤러가 2024년 10월 한 달 동안 크롤링한 95TB 데이터 (3천만개 unique URL - long 87% medium 9% short 4%) 중에서
대표 community site 인지 구분하고
PAAS 로그에서 구글 검색결과로 등장했던 url들과 도메인 단위 (e.g. "https://namu.wiki/" ) 로 조인한 결과
예시 URL
case1. url_short_community : text 100자 이하 & 커뮤니티 사이트
https://m.ssul.nate.com/todayssul/2024-04-06
case2. url_short_etc : text 100자 이하 & 일반 사이트
http://okdong.es.kr/_mdl/popupAll/okdong-e/7931
case3. url_medium_community : text 1000자 이하 & 커뮤니티 사이트
https://m.comm.news.nate.com/Comment/ArticleComment/ReplyList?mid=m04&artc_sq=20240325n00051&cmt_sq=252876257
case4. url_medium_etc : text 1000자 이하 & 일반 사이트
https://www.nps.or.kr/jsppage/app/receive/talkRoom/05_01_freeboard02.jsp?seq=123756&cPage=10&bbsId=talkNews&SK=&SW=
정상적으로 수집된 문서 1775 건 중에, 오직 rankingScore (entropy) 만으로 추출되는 경우는 5% (81건)
인증서나 랜더링, 네트워크 이슈 등으로 정상 수집이 되지 않은 케이스는 제외
나머지 95% 는 bestEnropyElement 가 css 를 포함하지 않거나 (NotContainsCSS), 너무 많이 잘린 케이스 (NotEnoughText)
위 두 케이스는 약 64% 정도 겹치는 경향을 보임 (i.e. entropy 만으로 해결되지 못하는 경우가 css 와 notEnough 로직으로 비슷하게 보완되지만, 100% 일치하지 않으므로 둘 다 사용해야 함)
어떤 문서에서 '이 부분이 본문이다' 라고 정의된 데이터가 없기 때문에 (i.e. 정답 데이터가 없으므로), 약 2천여개 문서에서 본문이 정상적으로 추출되었다는 것을 자동으로 탐지할 필요가 있었습니다.
이상치 탐지를 위해 벤치마크 trafilatura와의 자카드 유사도 및 본문 길이의 정상 범위를 측정했습니다.
파란색 막대그래프는 Jaccard 유사도
빨간색 점은 trafilatura 본문의 길이, 주황색 X는 PAAS 본문의 길이
그래프 해석
Jaccard 유사도는 데이터 포인트마다 큰 차이를 보임
대부분의 경우 PAAS 본문의 길이가 trafilatura 본문 보다 김
길이 차이가 클 때 Jaccard 유사도가 낮은 경향이 있음
Jaccard 유사도 통계
Jaccard 유사도의 평균은 40.19%
표준편차는 27.30%
trafilatura 본문과 PAAS 본문간의 유사도가 평균적으로 40% 정도이지만, 데이터 포인트 간 편차가 큼
trafilatura 가 본문을 제대로 추출하지 못한 20% 정도를 제외하고, 둘 다 정상인 케이스만 따로 계산하면:
Jaccard 유사도 평균: 52.49%
최소값: 16.82%
최대값: 85.77%
표준편차: 24.17%
텍스트 길이
trafilatura 본문의 평균 길이: 3,147.9 문자
PAAS 본문의 평균 길이: 5,278.4 문자
평균 길이 차이: 2,130.5 문자
Baseline Distribution
본문 추출이 정상적일때 trafilatura 에 비해 PAAS 본문이 1.7배정도 길이가 길고, Jaccard 유사도 평균은 53%, 표준편차 24%
데이터의 양이 방대한 상황에서 정상 범위를 벗어나는 이상치 케이스들만 선별하여 직접 육안으로 본문 추출 결과를 검증함으로써, 테스트 효율성을 크게 향상시킬 수 있었습니다.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.