2024. 11. 24. 11:23ㆍ카테고리 없음
3줄 요약
정규표현식(regex) 을 Language Model의 결과를 후처리하고 있습니다. 특히 hallucination 을 필터링하는 데 유용하게 쓰고 있는데요, regex 에서도 무한루프가 걸릴 수 있답니다! (저는 몰랐고 알고 싶지 않았습니다)
이런 regex 의 무한루프에 대해 알아보고 python 에서 해결방법을 구현해 보았습니다.
Regex
정규표현식은 Regular Expression 으로, 문자열에서 특정 패턴을 찾고, 대체하고, 분할하는 데 사용합니다.
대표적인 사용처는
- 데이터 유효성 검사 (ID, PW, 이메일 주소, 전화번호 등)
- 데이터셋 전처리
등이 있습니다.
python에서 정규표현식은 내장 모듈인 re를 대부분 이용합니다.
이 re 모듈의 사용예시를 간단히 살펴보면 아래와 같이 이메일 주소의 형식을 검증하고, 형식에서 벗어나는 내용을 필터링해서 리턴합니다.
import re
pattern = r'[^a-zA-Z0-9._%+-@]'
myemail = 'myemail오타@gmail틀림.com'
re.sub(pattern, '', myemail)

regex101 사이트를 이용해서도 간편히 체크할 수 있습니다

Catastrophic Backtracking
그러나 regex 필터링은 반복되는 글자가 있을 때 hang이 발생할 수 있습니다. 특히 .* 나 .+ 이 사용되는 경우에 주의가 필요합니다. 정규표현식에서 .*는 탐욕적 반복자 로서 해당 패턴을 가능한 많이 매치시키려고 하기 때문입니다.
Language Model 이 흔하게 발생시키는 hallucination 인 무의미한 글자 반복의 예시를 들어보겠습니다.
pattern = '(아니.*)+아니$'
text = '아니...아니...아니... 아니...아니...아니... 아니...아니...아니... 아니...아니...아니... 아니...아니...아니... 아니...아니...아니... 아니...'
regex101 사이트 우측 상단에 'catastrophic backtracking' 이라고 표시되는 것을 볼 수 있습니다.

javascript 공식문서 에서는 catastrophic backtracking 을 피하는 두 가지 방법을 제시합니다.
- 가능한 조합의 갯수 줄이기: 정규표현식을 최대한 효율적으로 작성하세요
- backtracking 예방하기: .* .+ 같은 greedy search 를 최대한 지양하고, 반복횟수에 제한을 두세요.
그러나 hallucination 을 후처리하기 위한 목적으로는 슬프게도 두 가지 방법 모두 사용이 어렵습니다 😂
해결방법
python 내장모듈 re가 아닌 pypi의 서드파티 모듈인 regex는 연산에서 타임아웃을 지원합니다.
아래 모듈을 사용할 환경에 설치하고
pip install regex
실습용 스크립트를 실행하면 실행시간이 1ms 가 넘어가기 때문에 자동으로 timeout 을 실행시켜 무한루프를 방지해 줍니다.
import regex as re
pattern = '(아니.*)+아니$'
text = '아니...아니...아니... 아니...아니...아니... \
아니...아니...아니... 아니...아니...아니... 아니...아니... \
아니... 아니...아니...아니... 아니...아니...아니...아니... \
아니...아니...아니... 아니...아니...아니... 아니...아니... \
아니... 아니...아니...아니... 아니...아니...아니... 아니...\
아니...아니...아니... 아니...아니...아니... 아니...아니...\
아니... 아니...아니...아니... 아니... 아니...아니...
아 니...아니...아니... 아니...'
re.sub(pattern, '', text, timeout=0.001)

무한루프 없는 정규표현식 사용에 도움이 되시기를 바랍니다 🙃