나의 llama.cpp 포크 - 실험적 튜닝
요약
llama.cpp의 루프 방지 기능을 개선한 개인 포크 버전을 소개합니다. 실시간 토큰 모니터링을 통해 반복적인 출력 사이클을 감지하고, 온도를 조절하여 모델이 루프에서 벗어나도록 돕는 샘플러를 구현했습니다.
핵심 포인트
- 루프 탐지 샘플러를 통한 실시간 토큰 스트림 모니터링
- 반복 패턴 감지 시 샘플링 온도를 높여 무작위성 부여
- last_n, min_pattern_len 등 세밀한 매개변수 조절 가능
- LLM의 출력 품질 저하 및 무한 루프 문제 해결
Claude의 도움을 받아 만든 저의 작은 llama.cpp 놀이터를 소개하고자 합니다. ;)
https://github.com/ALange/llama.cpp
제가 필요하다고 느꼈고 유용할 것이라고 생각한 기본 llama.cpp 대비 개선 사항들입니다. 예를 들어, llama.cpp에 내장된 루프 방지(anti-loop protection) 기능 등이 있습니다.
변경 사항 예시:
루프 탐지 샘플러 (Loop Detection Sampler) — 구현 설계
개요
루프 탐지 샘플러 (llama_sampler_init_loop_detect)는 llama.cpp 샘플링 파이프라인에 추가된 새로운 조합 가능한 샘플러(composable sampler)입니다. 이 샘플러는 생성된 토큰 스트림을 실시간으로 모니터링하여 정확한 반복 사이클을 식별하고, 샘플링 온도(sampling temperature)를 일시적으로 높여 무작위성을 증가시킴으로써 모델이 루프에서 벗어나도록 대응합니다.
문제점
LLM은 추론(inference) 중에 반복적인 출력 사이클에 갇힐 수 있습니다. 일반적인 패턴은 다음과 같습니다:
단일 토큰 반복: ... the the the the the ...
짧은 구절 루프: ... I think I think I think I think ...
문단 수준의 사이클: 모델이 수십 개의 토큰마다 동일한 문장이나 문단을 다시 방문함
이러한 루프는 출력 품질을 저하시키고, 토큰을 낭비하며, 생성 길이 제한(generation length limit)이 설정되지 않은 경우 무한히 실행될 수 있습니다.
매개변수 (Parameters)
| 매개변수 | CLI 플래그 | 기본값 | 비고 |
|---|---|---|---|
| last_n | --loop-detect-last-n | 64 | 슬라이딩 윈도우(Sliding window) 크기. 값이 클수록 더 길거나 느린 사이클을 포착하지만 토큰당 스캔 비용이 증가합니다. 완전히 비활성화하려면 0으로 설정하세요. |
| min_pattern_len | --loop-detect-min-pattern | 3 | 토큰 단위의 최소 사이클 길이. 1로 설정하면 단일 토큰 반복을 포착합니다 (이미 repeat-penalty에 의해 처리됨). 더 높게 설정하면 정당한 짧은 반복 구절(예: "yes, yes")에 대한 오탐(false positives)을 방지할 수 있습니다. |
| min_reps | --loop-detect-min-reps | 3 | 트리거되기 전에 몇 번의 전체 반복이 발생해야 하는지를 나타냅니다. 2는 공격적이며(한 번의 반복 후 실행), 3은 보수적인 기본값입니다. 2 미만의 값은 내부적으로 2로 고정됩니다. |
| temp_factor | --loop-detect-temp-factor | 0.0 | 루프가 발생했을 때 적용되는 온도 배수(temperature multiplier). 0.0은 샘플러를 비활성화합니다 (체인 내에서 아무 작업도 수행하지 않는 no-op이 됩니다). |
1.5에서 3.0 사이의 값이 실용적입니다; 더 높은 값은 일관성 없는 출력(incoherent output)의 위험이 있습니다.
사용법 (Usage)
보수적인 설정으로 활성화 (권장 시작 지점)
sh llama-cli -m model.gguf \ --loop-detect-temp-factor 2.0 \ -n 500
기본값 사용: last_n=64, min_pattern_len=3, min_reps=3. 마지막 64개 토큰 내에서 3개 이상의 토큰 사이클이 3회 연속 반복되면 작동합니다.
더 짧거나 빠른 루프 포착
sh llama-cli -m model.gguf \ --loop-detect-temp-factor 1.5 \ --loop-detect-min-pattern 1 \ --loop-detect-min-reps 2 \ -n 500
단일 토큰 루프를 포함하여, 어떤 사이클이든 단 2회만 반복되어도 트리거됩니다. 더 공격적이며 — 일반적인 출력 중 단어가 반복될 때 가끔 작동할 수 있습니다.
계층적 보호를 위해 DRY와 결합
sh llama-cli -m model.gguf \ --dry-multiplier 0.8 \ --loop-detect-temp-factor 2.0 \ --loop-detect-min-reps 3 \ -n 500
DRY는 알려진 패턴을 계속 이어가는 특정 토큰에 페널티를 부여하며; loop-detect는 모델이 여전히 사이클에 진입할 경우 전역적으로 온도를 높입니다.
샘플러 시퀀스 문자열(sampler sequence string)을 통해
'l'은 시퀀스 약어에서의 loop-detect 문자입니다
llama-cli -m model.gguf --sampler-seq edskypmxlt --loop-detect-temp-factor 2.0 ```
JSON API (llama-server)
json { "prompt": "...", "loop_detect_last_n": 64, "loop_detect_min_pattern": 3, "loop_detect_min_reps": 3, "loop_detect_temp_factor": 2.0 }
프로그래밍 방식 (C API)
c struct llama_sampler * chain = llama_sampler_chain_init(params); llama_sampler_chain_add(chain, llama_sampler_init_top_k(40)); llama_sampler_chain_add(chain, llama_sampler_init_top_p(0.95f, 1)); llama_sampler_chain_add(chain, llama_sampler_init_loop_detect( 64, // last_n 3, // min_pattern_len 3, // min_reps 2.0f // temp_factor )); llama_sampler_chain_add(chain, llama_sampler_init_temp(0.8f)); llama_sampler_chain_add(chain, llama_sampler_init_dist(LLAMA_DEFAULT_SEED));
튜닝 가이드 (Tuning Guide)
일반적인 출력에서 샘플러가 너무 자주 작동한다면: - --loop-detect-min-pattern을 증가시키세요 (예:
5) 짧은 반복 문구를 무시하려면 - `--loop-detect-min-reps`를 증가시키세요 (예: 4) 하여 작동하기 전 더 많은 반복을 요구하도록 합니다 - `--loop-detect-temp-factor`를 감소시키세요 (예: 1.3) 하여 더 완만한 부스트를 적용합니다.
만약 루프(loops)가 감지되지 않는다면: - `--loop-detect-min-reps`를 감소시키세요 (예: 2) 하여 더 빠르게 반응하도록 합니다 - `--loop-detect-last-n`을 증가시키세요 (예: 128) 하여 더 넓은 윈도우(window)를 스캔하도록 합니다 - `--loop-detect-temp-factor`를 증가시키세요 (예: 3.0) 하여 더 강력한 방해(disruption)를 가합니다.
일관성(coherence)이 중요한 매우 긴 출력의 경우: - `--dry-multiplier` 0.8과 결합하여 루프 감지(loop-detect)가 놓칠 수 있는 패턴(대략적이거나 다양한 반복)을 처리하세요 - 의도적인 반복(리스트, 시, 구조화된 형식)을 방해하지 않도록 `--loop-detect-min-reps`를 3 이상으로 유지하세요.
제출자: /u/AdamLangePL
[link] [comments]
AI 자동 생성 콘텐츠
본 콘텐츠는 r/LocalLLaMA의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기