Rule-based Filter : meaningless_keywords 리스트 개선방안 (260424)

WonTerry·2026년 4월 23일

LLM

목록 보기
55/66

Rule-based Filter의 예시에서 meaningless_keywords 리스트를 구축하는 것도 상당한 낭비가 아닐까 생각한다. 더 효율적인 방법은 없는가?

def rule_filter(text: str) -> tuple[bool, str]:
    meaningless_keywords = [
        "ㅋㅋ", "ㅎㅎ", "lol", "test", "1234"
    ]

    for k in meaningless_keywords:
        if k in text.lower():
            return False, "의미 없는 입력으로 판단됨"

    return True, text


text = "가나다라마바사"

print(rule_filter(text))

그 생각이 맞습니다. meaningless_keywords를 사람이 계속 추가하는 방식은 유지보수 비용 + 커버리지 한계 + 언어 의존성 때문에 금방 깨집니다. 특히 실제 서비스에서는 “ㅋㅋㅋㅋ / lol / ㅎㅎ / asdf / …”처럼 패턴이 끝없이 변형되기 때문에 리스트 방식은 장기적으로 비효율적입니다.

대신 방향을 이렇게 바꾸는 게 좋습니다:


✅ 핵심 전략: “단어”가 아니라 “특징(feature)”으로 판단

👉 의미 없는 입력은 특정 단어가 아니라
형태적/통계적 특징을 갖습니다.

예:

  • 문자 다양성이 낮음
  • 반복 패턴이 많음
  • 자연어 구조가 없음
  • 정보 밀도가 낮음

1️⃣ Entropy 기반 필터 (강력 추천)

👉 문자열의 “정보량”으로 판별

import math
from collections import Counter

def shannon_entropy(text: str) -> float:
    counts = Counter(text)
    probs = [c / len(text) for c in counts.values()]
    return -sum(p * math.log2(p) for p in probs)

def entropy_filter(text: str):
    ent = shannon_entropy(text)

    # 경험적으로 튜닝 필요
    if ent < 1.5:
        return False, f"정보량 낮음 (entropy={ent:.2f})"

    return True, text

효과

  • "ㅋㅋㅋㅋㅋㅋㅋㅋ" → entropy 낮음 → 차단
  • "asdfasdfasdf" → 낮음 → 차단
  • 정상 문장 → entropy 높음 → 통과

2️⃣ 문자 다양도 비율

def diversity_filter(text: str):
    unique_ratio = len(set(text)) / len(text)

    if unique_ratio < 0.2:
        return False, "문자 다양도 낮음"

    return True, text

3️⃣ 반복 패턴 감지 (n-gram)

def repetition_score(text: str, n=2):
    chunks = [text[i:i+n] for i in range(len(text)-n+1)]
    return len(set(chunks)) / len(chunks)

def repetition_filter(text: str):
    score = repetition_score(text)

    if score < 0.3:
        return False, "반복 패턴 과다"

    return True, text

4️⃣ 자연어 여부 판별 (가벼운 방식)

👉 “단어 구조”가 있는지 확인

def natural_language_filter(text: str):
    # 공백 기준 단어 수
    words = text.split()

    if len(words) == 1 and len(text) > 10:
        return False, "자연어 구조 부족"

    return True, text

5️⃣ 종합 스코어링 방식 (추천)

👉 개별 필터보다 훨씬 안정적

def smart_filter(text: str):
    score = 0

    # entropy
    if shannon_entropy(text) > 1.5:
        score += 1

    # 다양성
    if len(set(text)) / len(text) > 0.3:
        score += 1

    # 반복
    if repetition_score(text) > 0.4:
        score += 1

    # 자연어
    if len(text.split()) > 1:
        score += 1

    if score < 2:
        return False, "의미 없는 입력으로 판단"

    return True, text

🔥 더 진짜 실전적인 방법 (중요)

6️⃣ “Tiny ML 모델” (keyword보다 훨씬 효율적)

👉 로컬에서 1ms 내 판별 가능

  • Logistic Regression
  • FastText
  • TinyBERT

예:

# pseudo
prediction = tiny_model.predict(text)

if prediction == "nonsense":
    reject

👉 장점

  • 언어 독립적
  • 유지보수 거의 없음
  • keyword보다 훨씬 정확

💡 결론

단순 비교하면:

방식성능유지보수확장성
keyword 리스트❌ 낮음❌ 매우 높음
패턴/통계 기반✅ 중간✅ 낮음
tiny ML 모델✅ 매우 높음✅ 매우 낮음✅ 최고

🚀 추천 조합 (실전 베스트)

Fast validation
   ↓
Entropy + 다양도 + 반복 필터
   ↓
Tiny classifier (optional)
   ↓
LLM

원하면 다음 단계로
👉 “한국어 특화 meaningless detector (ㅋㅋ, ㅎ, 자모 분해 포함)”
👉 “FastText로 10KB짜리 분류 모델 만드는 방법”
👉 “LangChain Runnable로 이걸 체인에 붙이는 구조”

까지 실제 운영 수준으로 더 구체화해 드릴게요.

profile
Hello, I'm Terry! 👋 Enjoy every moment of your life! 🌱 My current interests are Signal processing, Machine learning, Python, Database, LLM & RAG, MCP & ADK, Multi-Agents, Physical AI, ROS2...

0개의 댓글