본문 바로가기
C.W.K.
Stream
Lesson 03 of 04 · published

모델 없는 바닥

~11 min · deterministic, floor, no-model, filler

Level 0불씨 없음
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"모델이 차갑고 네트워크가 사라졌을 때도, 뭔가는 네 단어를 정리해야 해. 그 뭔가는 기도가 아니라 코드야."

브레인 없는 프로바이더

Pippa 풀 이랑 로컬 Mini Pippa 모델, 그 둘 밑에 모델을 아예 안 쓰는 세 번째 정리 프로바이더가 앉아 있어. 결정론적 프로바이더야. 순수한 코드라서 콜드 스타트가 0 이고 타임아웃도 절대 안 나. 톤을 다시 쓰거나 구조를 추론하진 못해. 대신 원시 전사를 쓸 만하게 만드는 기계적인 일은 다 해. 공백 다듬고, 사전 치환 적용하고, 스니펫 펴고, 필러 토큰 벗기고, 간격이랑 따옴표 정규화하고, 말한 문장부호 명령을 옮기고, 끝에 붙은 '엔터 쳐' 를 잡아내고. LLM 이 없을 때 받아쓰기를 계속 굴러가게 하는 게 얘야.

결정론적 정리가 실제로 하는 일

"어 보고서 보내 쉼표 그다음 은행에 전화해 마침표"
         |  필러 벗기기 ("어")
         |  말한 문장부호 매핑 ("쉼표" -> ",", "마침표" -> ".")
         v
"보고서 보내, 그다음 은행에 전화해."

# 모델 없음. 규칙만: 필러, 문장부호 단어, 사전,
# 스니펫, 공백, 그리고 끝의 "엔터 쳐" 명령.

말한 문장부호랑 엔터 치기는 두 언어에서 다 돌아가. Firekeeper 가 영어랑 한국어를 나란히 매핑해 뒀거든. "comma" 랑 "쉼표", "period" 랑 "마침표", "press enter" 랑 "엔터 쳐". 이게 솔직한 오프라인 이야기야. 흉내만 내는 쪼그라든 LLM 이 아니라, 기계적인 정리의 80% 를 해내는 진짜 빠른 규칙 기반 변형.

한국어 필러 함정

따로 경고할 만한 미묘한 지점이 하나 있어. 필러 벗기기는 한국어에선 보수적이어야 해. "um", "uh" 같은 영어 필러는 진짜 단어인 경우가 드무니까 지워도 안전해. 그런데 한국어 필러는 진짜 어휘랑 겹쳐. 는 필러이기도 하지만 진짜 단어이기도 하고, 는 머뭇거림이기도 하지만 '저것' 이기도 하잖아. 필러를 전부 벗기는 순진한 규칙은 뜻을 지워 버려. 그래서 결정론적 한국어 필러 목록은 짧고 조심스러워. 진짜 단어를 먹느니 애매한 단어를 남기는 쪽으로 기울어 있고. 뜻을 망치는 공격적인 정리는 아예 정리 안 하는 것보다 나빠.

아무것도 필요 없는 바닥을 항상 둬. 시스템에서 제일 안정적인 컴포넌트는 의존성이 없는 거야. 모델도 없고, 네트워크도 없고, 서비스도 없는 것. 똑똑한 경로 밑에 결정론적 바닥을 깔아 둬. 그래야 똑똑한 부분이 없을 때 기능이 '고장' 이 아니라 '기계적으로는 맞음' 으로 내려앉아. 똑똑한 건 있으면 좋은 거고, 바닥은 없으면 안 되는 거야.
어디에나 통하는 규칙보다 언어를 아는 규칙이 나아. 영어에 맞춘 필러 벗기기 규칙은 한국어를 조용히 망가뜨려. 겉보기 같은 토큰이 한 언어에선 필러고 다른 언어에선 내용이니까. 여러 언어를 건드리는 결정론적 텍스트 규칙은 언어별로 따로 써야 하고, 남기는 쪽으로 기울어야 해. 여러 언어에 걸쳐 '대체로 맞는' 규칙은, 맞춰 주지 않은 그 언어를 조용히 뭉개는 규칙이야.

Code

결정론적 정리, 규칙만 쓰고 언어를 알고 남기는 쪽으로 기울어·swift
func deterministicClean(_ raw: String, language: String, dict: [DictEntry]) -> String {
    var t = raw.trimmingCharacters(in: .whitespacesAndNewlines)
    t = mapSpokenPunctuation(t, language: language)   // "comma"/"쉼표" -> ","
    t = stripFillers(t, language: language)           // EN: um/uh; KO: 짧고 조심스러운 목록
    t = applyDictionary(t, dict)                      // 명명 용어 강제
    t = expandSnippets(t)
    return normalizeWhitespace(t)
}

// KO 필러 목록은 일부러 아주 작아: 어 와 그 는 진짜 단어이기도 하니,
// 규칙이 의미 삭제 위험 대신 모호한 토큰을 남겨.

External links

Exercise

평소엔 LLM 으로 돌릴 기능에 결정론적인, 그러니까 모델 없는 폴백을 설계해봐. 규칙만으로 할 수 있는 것과 솔직히 못 하는 걸 나눠 적어. 그다음 한 언어나 한 맥락에선 안전한데 다른 데선 망가뜨릴 규칙을 하나 찾아봐. 안 망가지게 하려면 범위를 어떻게 좁힐래?
Hint
규칙만 쓰는 바닥은 기계적이고 헷갈릴 여지 없는 부분을 맡아. 포매팅, 정해진 치환, 구조 정규화 같은 거. 판단이 필요한 부분은, 그러니까 톤이나 추론이나 다시 쓰기는 솔직하게 건너뛰고. 맥락이 바뀔 때 터지는 함정은 보통 한쪽에선 잡음이고 다른 쪽에선 신호인 토큰이야. 해법은 규칙이 맥락을 알게 하는 거고. 언어든 로케일이든 도메인이든. 그리고 확실치 않으면 남기는 걸 기본으로 두는 거야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.