Text Generation
Transformers
Safetensors
GGUF
Korean
English
llama
3b
korean
from-scratch
orpo
instruction-tuned
preference-aligned
fp8
b200
Eval Results (legacy)
text-generation-inference
Instructions to use pathcosmos/frankenstallm with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use pathcosmos/frankenstallm with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="pathcosmos/frankenstallm")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("pathcosmos/frankenstallm") model = AutoModelForCausalLM.from_pretrained("pathcosmos/frankenstallm", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use pathcosmos/frankenstallm with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf pathcosmos/frankenstallm:Q4_K_M # Run inference directly in the terminal: llama cli -hf pathcosmos/frankenstallm:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf pathcosmos/frankenstallm:Q4_K_M # Run inference directly in the terminal: llama cli -hf pathcosmos/frankenstallm:Q4_K_M
Build from source code
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-app # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama serve -hf pathcosmos/frankenstallm:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama cli -hf pathcosmos/frankenstallm:Q4_K_M
Use Docker
docker model run hf.co/pathcosmos/frankenstallm:Q4_K_M
- Llama new
- LM Studio
- Jan
- vLLM
How to use pathcosmos/frankenstallm with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "pathcosmos/frankenstallm" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "pathcosmos/frankenstallm", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/pathcosmos/frankenstallm:Q4_K_M
- SGLang
How to use pathcosmos/frankenstallm with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "pathcosmos/frankenstallm" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "pathcosmos/frankenstallm", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "pathcosmos/frankenstallm" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "pathcosmos/frankenstallm", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Ollama
How to use pathcosmos/frankenstallm with Ollama:
ollama run hf.co/pathcosmos/frankenstallm:Q4_K_M
- Unsloth Desktop
- Docker Model Runner
How to use pathcosmos/frankenstallm with Docker Model Runner:
docker model run hf.co/pathcosmos/frankenstallm:Q4_K_M
- Lemonade
How to use pathcosmos/frankenstallm with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull pathcosmos/frankenstallm:Q4_K_M
Run and chat with the model
lemonade run user.frankenstallm-Q4_K_M
List all available models
lemonade list
- Atomic Chat
Download source/scripts/quality_gate.sh from pathcosmos/frankenstallm: direct link, hf CLI and curl.
- Browser
- Download file 18.9 kB
-
https://huggingface.co/pathcosmos/frankenstallm/resolve/refs%2Fpr%2F17/source/scripts/quality_gate.sh
- Command line
-
hf download hf://pathcosmos/frankenstallm@refs/pr/17/source/scripts/quality_gate.sh
-
curl -L -o quality_gate.sh https://huggingface.co/pathcosmos/frankenstallm/resolve/refs%2Fpr%2F17/source/scripts/quality_gate.sh
18.9 kB
| # ============================================================================= | |
| # quality_gate.sh โ Phase ์๋ฃ ์๋ ํ์ง ๊ฒ์ดํธ ๊ฒ์ฆ | |
| # | |
| # Usage: | |
| # bash scripts/quality_gate.sh <phase> | |
| # | |
| # Phases: | |
| # pretrain โ ์ฌ์ ํ์ต ๊ฒ์ดํธ (val_loss, loss ๋จ์กฐ ๊ฐ์) | |
| # sft โ SFT ๊ฒ์ดํธ (val_loss ์๋ ด, ๋ฐ๋ณต๋ฅ , KoBEST) | |
| # orpo โ ORPO ๊ฒ์ดํธ (๋ฐ๋ณต๋ฅ , KoBEST, chosen > rejected) | |
| # deploy โ ๋ฐฐํฌ ๊ฒ์ดํธ (GGUF perplexity, Ollama ์๋ต) | |
| # all โ ๋ชจ๋ ๊ฒ์ดํธ ์์ฐจ ์คํ | |
| # | |
| # Exit codes: | |
| # 0 โ ๊ฒ์ดํธ ํต๊ณผ | |
| # 1 โ ๊ฒ์ดํธ ์คํจ (๊ธฐ์ค ๋ฏธ๋ฌ) | |
| # 2 โ ํ์ ํ์ผ / ์์กด์ฑ ์์ (์คํ ๋ถ๊ฐ) | |
| # ============================================================================= | |
| set -uo pipefail | |
| PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" | |
| # --------------------------------------------------------------------------- | |
| # ์์ ์ถ๋ ฅ ํฌํผ | |
| # --------------------------------------------------------------------------- | |
| _RED='\033[0;31m' | |
| _GREEN='\033[0;32m' | |
| _YELLOW='\033[1;33m' | |
| _BLUE='\033[0;34m' | |
| _NC='\033[0m' | |
| log_info() { echo -e "${_BLUE}[INFO]${_NC} $*"; } | |
| log_ok() { echo -e "${_GREEN}[PASS]${_NC} $*"; } | |
| log_warn() { echo -e "${_YELLOW}[WARN]${_NC} $*"; } | |
| log_fail() { echo -e "${_RED}[FAIL]${_NC} $*"; } | |
| log_skip() { echo -e " [SKIP] $*"; } | |
| # --------------------------------------------------------------------------- | |
| # ์ ํธ๋ฆฌํฐ: Python ํ ์ค ํํ์ ํ๊ฐ (๋ถ๋์์์ ๋น๊ต) | |
| # --------------------------------------------------------------------------- | |
| py_eval() { | |
| python3 -c "import sys; sys.exit(0 if ($1) else 1)" | |
| } | |
| py_value() { | |
| python3 -c "print($1)" | |
| } | |
| # --------------------------------------------------------------------------- | |
| # ์ ํธ๋ฆฌํฐ: JSON์์ ๊ฐ ์ถ์ถ | |
| # --------------------------------------------------------------------------- | |
| json_get() { | |
| local file="$1" key="$2" | |
| python3 -c " | |
| import json, sys | |
| try: | |
| d = json.load(open('$file')) | |
| keys = '$key'.split('.') | |
| for k in keys: | |
| d = d[k] | |
| print(d) | |
| except Exception as e: | |
| print('NOT_FOUND') | |
| sys.exit(1) | |
| " | |
| } | |
| # --------------------------------------------------------------------------- | |
| # ๊ฒ์ดํธ ๊ฒฐ๊ณผ ์ง๊ณ | |
| # --------------------------------------------------------------------------- | |
| GATE_PASS=0 | |
| GATE_FAIL=0 | |
| GATE_SKIP=0 | |
| record_pass() { GATE_PASS=$((GATE_PASS + 1)); log_ok "$*"; } | |
| record_fail() { GATE_FAIL=$((GATE_FAIL + 1)); log_fail "$*"; } | |
| record_skip() { GATE_SKIP=$((GATE_SKIP + 1)); log_skip "$*"; } | |
| # ============================================================================= | |
| # Gate 1: Pretrain | |
| # ============================================================================= | |
| gate_pretrain() { | |
| echo "" | |
| echo "==================================================================" | |
| echo " Gate: PRETRAIN" | |
| echo " ๊ธฐ์ค: val_loss < 2.5 | loss ๋จ์กฐ ๊ฐ์ ํ์ธ" | |
| echo "==================================================================" | |
| # ์ต์ ์ฒดํฌํฌ์ธํธ ๋๋ ํ ๋ฆฌ ํ์ | |
| CKPT_BASE="$PROJECT_DIR/checkpoints" | |
| METRICS_FILE="" | |
| # metrics.json ๋๋ train_log.jsonl ํ์ | |
| for candidate in \ | |
| "$CKPT_BASE/korean_3b_fp8_pretrain/metrics.json" \ | |
| "$CKPT_BASE/korean_3b_pretrain/metrics.json" \ | |
| "$PROJECT_DIR/outputs/pretrain_metrics.json" \ | |
| "$PROJECT_DIR/logs/pretrain_metrics.json" | |
| do | |
| if [[ -f "$candidate" ]]; then | |
| METRICS_FILE="$candidate" | |
| break | |
| fi | |
| done | |
| if [[ -z "$METRICS_FILE" ]]; then | |
| log_warn "์ฌ์ ํ์ต ๋ฉํธ๋ฆญ ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค." | |
| log_warn "์ฐพ๋ ๊ฒฝ๋ก: $CKPT_BASE/korean_3b_*/metrics.json" | |
| log_warn "๋ฉํธ๋ฆญ ํ์ผ์ด ์์ผ๋ฉด ํ์ต ์คํฌ๋ฆฝํธ์์ ์๋ ํ์์ผ๋ก ์ ์ฅํ์ธ์:" | |
| log_warn ' {"val_loss": 2.3, "loss_history": [3.1, 2.8, 2.5, 2.3]}' | |
| record_skip "๋ฉํธ๋ฆญ ํ์ผ ์์ โ ๊ฒ์ดํธ ๊ฑด๋๋" | |
| return 0 | |
| fi | |
| log_info "๋ฉํธ๋ฆญ ํ์ผ: $METRICS_FILE" | |
| # val_loss ํ์ธ | |
| VAL_LOSS=$(json_get "$METRICS_FILE" "val_loss" 2>/dev/null || echo "NOT_FOUND") | |
| if [[ "$VAL_LOSS" == "NOT_FOUND" ]]; then | |
| record_skip "val_loss ํค ์์ โ ๊ฑด๋๋" | |
| else | |
| log_info "val_loss = $VAL_LOSS (๊ธฐ์ค: < 2.5)" | |
| if py_eval "$VAL_LOSS < 2.5" 2>/dev/null; then | |
| record_pass "val_loss $VAL_LOSS < 2.5" | |
| else | |
| record_fail "val_loss $VAL_LOSS >= 2.5 (๊ธฐ์ค ๋ฏธ๋ฌ)" | |
| fi | |
| fi | |
| # loss ๋จ์กฐ ๊ฐ์ ํ์ธ (loss_history) | |
| python3 - "$METRICS_FILE" <<'PYEOF' | |
| import json, sys | |
| metrics_file = sys.argv[1] | |
| try: | |
| d = json.load(open(metrics_file)) | |
| history = d.get("loss_history", []) | |
| except Exception as e: | |
| print(f"[SKIP] loss_history ์ฝ๊ธฐ ์คํจ: {e}") | |
| sys.exit(0) | |
| if len(history) < 2: | |
| print(f"[SKIP] loss_history ๋ฐ์ดํฐ ๋ถ์กฑ ({len(history)}๊ฐ)") | |
| sys.exit(0) | |
| # ์ ์ฒด ์ถ์ธ๊ฐ ๊ฐ์ํ๋์ง ํ์ธ (์ฒ์ 1/4 vs ๋ง์ง๋ง 1/4 ํ๊ท ๋น๊ต) | |
| n = len(history) | |
| q = max(1, n // 4) | |
| early_avg = sum(history[:q]) / q | |
| late_avg = sum(history[-q:]) / q | |
| if late_avg < early_avg: | |
| print(f"[PASS] loss ๋จ์กฐ ๊ฐ์ ํ์ธ: ์ด๊ธฐ avg={early_avg:.4f} โ ์ต๊ทผ avg={late_avg:.4f}") | |
| sys.exit(0) | |
| else: | |
| print(f"[FAIL] loss ๊ฐ์ ๋ฏธํ์ธ: ์ด๊ธฐ avg={early_avg:.4f}, ์ต๊ทผ avg={late_avg:.4f}") | |
| sys.exit(1) | |
| PYEOF | |
| local mono_exit=$? | |
| if [[ $mono_exit -eq 0 ]]; then | |
| GATE_PASS=$((GATE_PASS + 1)) | |
| elif [[ $mono_exit -eq 1 ]]; then | |
| GATE_FAIL=$((GATE_FAIL + 1)) | |
| fi | |
| # exit 0 (SKIP) ๋ ์ด๋ฏธ ์ฒ๋ฆฌ๋จ | |
| } | |
| # ============================================================================= | |
| # Gate 2: SFT | |
| # ============================================================================= | |
| gate_sft() { | |
| echo "" | |
| echo "==================================================================" | |
| echo " Gate: SFT" | |
| echo " ๊ธฐ์ค: val_loss ์๋ ด | ๋ฐ๋ณต๋ฅ < 15% | KoBEST > 55%" | |
| echo "==================================================================" | |
| METRICS_FILE="" | |
| for candidate in \ | |
| "$PROJECT_DIR/outputs/sft_metrics.json" \ | |
| "$PROJECT_DIR/logs/sft_metrics.json" \ | |
| "$PROJECT_DIR/checkpoints/sft/metrics.json" | |
| do | |
| if [[ -f "$candidate" ]]; then | |
| METRICS_FILE="$candidate" | |
| break | |
| fi | |
| done | |
| if [[ -z "$METRICS_FILE" ]]; then | |
| log_warn "SFT ๋ฉํธ๋ฆญ ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค." | |
| log_warn ' {"val_loss": 1.8, "rep_rate": 0.08, "kobest_score": 0.62}' | |
| record_skip "SFT ๋ฉํธ๋ฆญ ํ์ผ ์์ โ ๊ฒ์ดํธ ๊ฑด๋๋" | |
| return 0 | |
| fi | |
| log_info "๋ฉํธ๋ฆญ ํ์ผ: $METRICS_FILE" | |
| # val_loss ์๋ ด (์๋ ๋ณํ์จ < 1% โ ๋ง์ง๋ง ๋ ์ฒดํฌํฌ์ธํธ) | |
| python3 - "$METRICS_FILE" <<'PYEOF' | |
| import json, sys | |
| metrics_file = sys.argv[1] | |
| try: | |
| d = json.load(open(metrics_file)) | |
| history = d.get("val_loss_history", []) | |
| except Exception as e: | |
| print(f"[SKIP] val_loss_history ์ฝ๊ธฐ ์คํจ: {e}") | |
| sys.exit(0) | |
| if len(history) < 2: | |
| # ๋จ์ผ val_loss๋ง ์์ผ๋ฉด ๋จ์ ํ์ธ | |
| val_loss = d.get("val_loss") | |
| if val_loss is not None: | |
| print(f"[INFO] val_loss = {val_loss} (์๋ ด ํ์คํ ๋ฆฌ ์์ โ ๋จ์ผ ๊ฐ ํ์ธ ๊ฑด๋๋)") | |
| sys.exit(0) | |
| last = history[-1] | |
| second = history[-2] | |
| rel_change = abs(last - second) / max(abs(second), 1e-9) | |
| if rel_change < 0.01: | |
| print(f"[PASS] val_loss ์๋ ด (์๋๋ณํ์จ {rel_change*100:.3f}% < 1%): {second:.4f} โ {last:.4f}") | |
| sys.exit(0) | |
| else: | |
| print(f"[FAIL] val_loss ๋ฏธ์๋ ด (์๋๋ณํ์จ {rel_change*100:.3f}% >= 1%): {second:.4f} โ {last:.4f}") | |
| sys.exit(1) | |
| PYEOF | |
| local conv_exit=$? | |
| [[ $conv_exit -eq 0 ]] && GATE_PASS=$((GATE_PASS + 1)) || GATE_FAIL=$((GATE_FAIL + 1)) | |
| # ๋ฐ๋ณต๋ฅ ํ์ธ | |
| REP_RATE=$(json_get "$METRICS_FILE" "rep_rate" 2>/dev/null || echo "NOT_FOUND") | |
| if [[ "$REP_RATE" == "NOT_FOUND" ]]; then | |
| record_skip "rep_rate ํค ์์ โ ๊ฑด๋๋" | |
| else | |
| REP_PCT=$(py_value "$REP_RATE * 100") | |
| log_info "๋ฐ๋ณต๋ฅ = ${REP_PCT}% (๊ธฐ์ค: < 15%)" | |
| if py_eval "$REP_RATE < 0.15" 2>/dev/null; then | |
| record_pass "๋ฐ๋ณต๋ฅ ${REP_PCT}% < 15%" | |
| else | |
| record_fail "๋ฐ๋ณต๋ฅ ${REP_PCT}% >= 15% (๊ธฐ์ค ๋ฏธ๋ฌ)" | |
| fi | |
| fi | |
| # KoBEST ํ์ธ | |
| KOBEST=$(json_get "$METRICS_FILE" "kobest_score" 2>/dev/null || echo "NOT_FOUND") | |
| if [[ "$KOBEST" == "NOT_FOUND" ]]; then | |
| record_skip "kobest_score ํค ์์ โ ๊ฑด๋๋" | |
| else | |
| KOBEST_PCT=$(py_value "$KOBEST * 100") | |
| log_info "KoBEST = ${KOBEST_PCT}% (๊ธฐ์ค: > 55%)" | |
| if py_eval "$KOBEST > 0.55" 2>/dev/null; then | |
| record_pass "KoBEST ${KOBEST_PCT}% > 55%" | |
| else | |
| record_fail "KoBEST ${KOBEST_PCT}% <= 55% (๊ธฐ์ค ๋ฏธ๋ฌ)" | |
| fi | |
| fi | |
| } | |
| # ============================================================================= | |
| # Gate 3: ORPO | |
| # ============================================================================= | |
| gate_orpo() { | |
| echo "" | |
| echo "==================================================================" | |
| echo " Gate: ORPO" | |
| echo " ๊ธฐ์ค: ๋ฐ๋ณต๋ฅ < 5% | KoBEST > 60% | chosen > rejected 90%+" | |
| echo "==================================================================" | |
| METRICS_FILE="" | |
| for candidate in \ | |
| "$PROJECT_DIR/outputs/orpo_metrics.json" \ | |
| "$PROJECT_DIR/logs/orpo_metrics.json" \ | |
| "$PROJECT_DIR/checkpoints/orpo/metrics.json" | |
| do | |
| if [[ -f "$candidate" ]]; then | |
| METRICS_FILE="$candidate" | |
| break | |
| fi | |
| done | |
| if [[ -z "$METRICS_FILE" ]]; then | |
| log_warn "ORPO ๋ฉํธ๋ฆญ ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค." | |
| log_warn ' {"rep_rate": 0.03, "kobest_score": 0.63, "chosen_win_rate": 0.92}' | |
| record_skip "ORPO ๋ฉํธ๋ฆญ ํ์ผ ์์ โ ๊ฒ์ดํธ ๊ฑด๋๋" | |
| return 0 | |
| fi | |
| log_info "๋ฉํธ๋ฆญ ํ์ผ: $METRICS_FILE" | |
| # ๋ฐ๋ณต๋ฅ (๋ ์๊ฒฉ: < 5%) | |
| REP_RATE=$(json_get "$METRICS_FILE" "rep_rate" 2>/dev/null || echo "NOT_FOUND") | |
| if [[ "$REP_RATE" == "NOT_FOUND" ]]; then | |
| record_skip "rep_rate ํค ์์ โ ๊ฑด๋๋" | |
| else | |
| REP_PCT=$(py_value "$REP_RATE * 100") | |
| log_info "๋ฐ๋ณต๋ฅ = ${REP_PCT}% (๊ธฐ์ค: < 5%)" | |
| if py_eval "$REP_RATE < 0.05" 2>/dev/null; then | |
| record_pass "๋ฐ๋ณต๋ฅ ${REP_PCT}% < 5%" | |
| else | |
| record_fail "๋ฐ๋ณต๋ฅ ${REP_PCT}% >= 5% (๊ธฐ์ค ๋ฏธ๋ฌ)" | |
| fi | |
| fi | |
| # KoBEST (๋ ์๊ฒฉ: > 60%) | |
| KOBEST=$(json_get "$METRICS_FILE" "kobest_score" 2>/dev/null || echo "NOT_FOUND") | |
| if [[ "$KOBEST" == "NOT_FOUND" ]]; then | |
| record_skip "kobest_score ํค ์์ โ ๊ฑด๋๋" | |
| else | |
| KOBEST_PCT=$(py_value "$KOBEST * 100") | |
| log_info "KoBEST = ${KOBEST_PCT}% (๊ธฐ์ค: > 60%)" | |
| if py_eval "$KOBEST > 0.60" 2>/dev/null; then | |
| record_pass "KoBEST ${KOBEST_PCT}% > 60%" | |
| else | |
| record_fail "KoBEST ${KOBEST_PCT}% <= 60% (๊ธฐ์ค ๋ฏธ๋ฌ)" | |
| fi | |
| fi | |
| # Chosen win rate (chosen log-prob > rejected log-prob ๋น์จ) | |
| CHOSEN_WIN=$(json_get "$METRICS_FILE" "chosen_win_rate" 2>/dev/null || echo "NOT_FOUND") | |
| if [[ "$CHOSEN_WIN" == "NOT_FOUND" ]]; then | |
| record_skip "chosen_win_rate ํค ์์ โ ๊ฑด๋๋" | |
| else | |
| WIN_PCT=$(py_value "$CHOSEN_WIN * 100") | |
| log_info "Chosen win rate = ${WIN_PCT}% (๊ธฐ์ค: >= 90%)" | |
| if py_eval "$CHOSEN_WIN >= 0.90" 2>/dev/null; then | |
| record_pass "Chosen win rate ${WIN_PCT}% >= 90%" | |
| else | |
| record_fail "Chosen win rate ${WIN_PCT}% < 90% (๊ธฐ์ค ๋ฏธ๋ฌ)" | |
| fi | |
| fi | |
| } | |
| # ============================================================================= | |
| # Gate 4: Deploy | |
| # ============================================================================= | |
| gate_deploy() { | |
| echo "" | |
| echo "==================================================================" | |
| echo " Gate: DEPLOY" | |
| echo " ๊ธฐ์ค: Q4_K_M perplexity < F16 ร 1.05 | Ollama 5๊ฐ ํ๋กฌํํธ ์๋ต" | |
| echo "==================================================================" | |
| local MODEL_NAME="frankenstallm-3b" | |
| local GGUF_DIR="$PROJECT_DIR/outputs/gguf" | |
| local F16_GGUF="$GGUF_DIR/${MODEL_NAME}-f16.gguf" | |
| local Q4KM_GGUF="$GGUF_DIR/${MODEL_NAME}-Q4_K_M.gguf" | |
| # --- GGUF ํ์ผ ์กด์ฌ ํ์ธ --- | |
| if [[ ! -f "$Q4KM_GGUF" ]]; then | |
| log_warn "Q4_K_M GGUF ํ์ผ ์์: $Q4KM_GGUF" | |
| log_warn "๋จผ์ ์คํ: bash scripts/convert_3b_gguf.sh" | |
| record_skip "GGUF ํ์ผ ์์ โ perplexity ๊ฒ์ดํธ ๊ฑด๋๋" | |
| else | |
| # perplexity ์ธก์ (llama-perplexity ๋๋ Python fallback) | |
| LLAMA_PPL_BIN="$PROJECT_DIR/outputs/llama.cpp/build/bin/llama-perplexity" | |
| if [[ ! -f "$LLAMA_PPL_BIN" ]]; then | |
| log_warn "llama-perplexity ๋ฐ์ด๋๋ฆฌ ์์ โ ๋น๋ ์๋ ์ค ..." | |
| cmake --build "$PROJECT_DIR/outputs/llama.cpp/build" \ | |
| --target llama-perplexity -j "$(nproc)" &>/dev/null || true | |
| fi | |
| # ์ํ ํ ์คํธ๋ก perplexity ๋น๊ต | |
| SAMPLE_TEXT="$PROJECT_DIR/outputs/gguf/ppl_sample.txt" | |
| if [[ ! -f "$SAMPLE_TEXT" ]]; then | |
| # ์งง์ ํ๊ตญ์ด ์ํ ์์ฑ | |
| cat > "$SAMPLE_TEXT" <<'SAMPLE' | |
| ์ธ๊ณต์ง๋ฅ์ ํ๋ ์ฌํ์์ ๋งค์ฐ ์ค์ํ ๊ธฐ์ ๋ก ์๋ฆฌ์ก๊ณ ์์ต๋๋ค. | |
| ๊ธฐ๊ณ ํ์ต๊ณผ ๋ฅ๋ฌ๋์ ๋ฐ์ ์ผ๋ก ์ธํด ๋ค์ํ ๋ถ์ผ์์ ํ์ ์ด ์ด๋ฃจ์ด์ง๊ณ ์์ต๋๋ค. | |
| ์์ฐ์ด ์ฒ๋ฆฌ ๊ธฐ์ ์ ๋ฐ์ ์ ์ธ๊ฐ๊ณผ ์ปดํจํฐ์ ์ํธ์์ฉ ๋ฐฉ์์ ๊ทผ๋ณธ์ ์ผ๋ก ๋ณํ์ํค๊ณ ์์ต๋๋ค. | |
| ํ๊ตญ์ด๋ ๊ต์ฐฉ์ด๋ก์ ํน์ ์ ํํ๋ก ์ ํน์ฑ์ ๊ฐ์ง๊ณ ์์ด ์์ฐ์ด ์ฒ๋ฆฌ์ ๋ ํนํ ๋์ ์ ์ ์ํฉ๋๋ค. | |
| ๋๊ท๋ชจ ์ธ์ด ๋ชจ๋ธ์ ๋ฑ์ฅ์ผ๋ก ๊ธฐ๊ณ ๋ฒ์ญ, ํ ์คํธ ์์ฝ, ์ง์์๋ต ๋ฑ์ ์ฑ๋ฅ์ด ํฌ๊ฒ ํฅ์๋์์ต๋๋ค. | |
| SAMPLE | |
| fi | |
| if [[ -f "$LLAMA_PPL_BIN" && -f "$F16_GGUF" ]]; then | |
| log_info "Perplexity ์ธก์ ์ค (F16 vs Q4_K_M) ..." | |
| PPL_F16=$(timeout 120 "$LLAMA_PPL_BIN" -m "$F16_GGUF" -f "$SAMPLE_TEXT" 2>&1 \ | |
| | grep -oP "Perplexity: \K[0-9.]+" | head -1 || echo "0") | |
| PPL_Q4=$(timeout 120 "$LLAMA_PPL_BIN" -m "$Q4KM_GGUF" -f "$SAMPLE_TEXT" 2>&1 \ | |
| | grep -oP "Perplexity: \K[0-9.]+" | head -1 || echo "0") | |
| if [[ "$PPL_F16" == "0" || "$PPL_Q4" == "0" ]]; then | |
| record_skip "Perplexity ์ธก์ ์คํจ โ ๊ฑด๋๋" | |
| else | |
| THRESHOLD=$(py_value "$PPL_F16 * 1.05") | |
| log_info "F16 PPL = $PPL_F16 | Q4_K_M PPL = $PPL_Q4 | ๊ธฐ์ค: < $THRESHOLD" | |
| if py_eval "$PPL_Q4 < $PPL_F16 * 1.05" 2>/dev/null; then | |
| record_pass "Q4_K_M PPL $PPL_Q4 < F16 PPL ร 1.05 ($THRESHOLD)" | |
| else | |
| record_fail "Q4_K_M PPL $PPL_Q4 >= F16 PPL ร 1.05 ($THRESHOLD)" | |
| fi | |
| fi | |
| else | |
| record_skip "llama-perplexity ๋๋ F16 GGUF ์์ โ perplexity ๊ฒ์ดํธ ๊ฑด๋๋" | |
| fi | |
| fi | |
| # --- Ollama ์๋ต ํ ์คํธ --- | |
| if ! command -v ollama &>/dev/null; then | |
| record_skip "ollama ์์ โ ์๋ต ํ ์คํธ ๊ฑด๋๋" | |
| return 0 | |
| fi | |
| if ! ollama list 2>/dev/null | grep -q "$MODEL_NAME"; then | |
| log_warn "Ollama์ $MODEL_NAME ๋ชจ๋ธ์ด ๋ฑ๋ก๋์ง ์์์ต๋๋ค." | |
| log_warn "๋จผ์ ์คํ: bash scripts/deploy_3b_ollama.sh" | |
| record_skip "Ollama ๋ชจ๋ธ ๋ฏธ๋ฑ๋ก โ ์๋ต ํ ์คํธ ๊ฑด๋๋" | |
| return 0 | |
| fi | |
| log_info "Ollama ์๋ต ํ ์คํธ (5๊ฐ ํ๋กฌํํธ) ..." | |
| declare -a PROMPTS=( | |
| "์๋ ํ์ธ์." | |
| "1 ๋ํ๊ธฐ 1์ ๋ฌด์์ธ๊ฐ์?" | |
| "ํ์ด์ฌ์ด๋ ๋ฌด์์ธ๊ฐ์?" | |
| "ํ๊ตญ์ ์๋๋ ์ด๋์ธ๊ฐ์?" | |
| "์ค๋ ๋ ์จ๊ฐ ์ข๋ค์." | |
| ) | |
| local PASS=0 FAIL=0 | |
| for i in "${!PROMPTS[@]}"; do | |
| local PROMPT="${PROMPTS[$i]}" | |
| local NUM=$((i + 1)) | |
| if RESP=$(timeout 45 ollama run "$MODEL_NAME" "$PROMPT" 2>&1) && [[ -n "$RESP" ]]; then | |
| log_ok " ํ๋กฌํํธ $NUM ์๋ต OK (${#RESP}์)" | |
| PASS=$((PASS + 1)) | |
| else | |
| log_fail " ํ๋กฌํํธ $NUM ์๋ต ์คํจ" | |
| FAIL=$((FAIL + 1)) | |
| fi | |
| done | |
| log_info "Ollama ์๋ต: $PASS/5 ์ฑ๊ณต" | |
| if [[ $FAIL -eq 0 ]]; then | |
| record_pass "Ollama 5๊ฐ ํ๋กฌํํธ ๋ชจ๋ ์๋ต ์ฑ๊ณต" | |
| else | |
| record_fail "Ollama ์๋ต ์คํจ $FAIL/5" | |
| fi | |
| } | |
| # ============================================================================= | |
| # ์ต์ข ์์ฝ ์ถ๋ ฅ | |
| # ============================================================================= | |
| print_summary() { | |
| local phase="$1" | |
| local TOTAL=$((GATE_PASS + GATE_FAIL + GATE_SKIP)) | |
| echo "" | |
| echo "==================================================================" | |
| echo " Quality Gate ๊ฒฐ๊ณผ: $phase" | |
| echo " PASS: $GATE_PASS | FAIL: $GATE_FAIL | SKIP: $GATE_SKIP | TOTAL: $TOTAL" | |
| echo "==================================================================" | |
| if [[ $GATE_FAIL -eq 0 ]]; then | |
| echo -e "${_GREEN} [GATE PASSED]${_NC} ๋ชจ๋ ๊ฒ์ฆ ๊ธฐ์ค ํต๊ณผ" | |
| echo "" | |
| return 0 | |
| else | |
| echo -e "${_RED} [GATE FAILED]${_NC} ${GATE_FAIL}๊ฐ ๊ฒ์ฆ ๊ธฐ์ค ๋ฏธ๋ฌ" | |
| echo " ์คํจ ํญ๋ชฉ์ ์์ ํ ํ ๋ค์ ์คํํ์ธ์." | |
| echo "" | |
| return 1 | |
| fi | |
| } | |
| # ============================================================================= | |
| # ์ง์ ์ | |
| # ============================================================================= | |
| PHASE="${1:-}" | |
| if [[ -z "$PHASE" ]]; then | |
| echo "Usage: bash scripts/quality_gate.sh <phase>" | |
| echo " phase: pretrain | sft | orpo | deploy | all" | |
| exit 2 | |
| fi | |
| echo "" | |
| echo "==================================================================" | |
| echo " Quality Gate ๊ฒ์ฆ ์์: $PHASE" | |
| echo " ํ๋ก์ ํธ: $PROJECT_DIR" | |
| echo " ์๊ฐ : $(date '+%Y-%m-%d %H:%M:%S')" | |
| echo "==================================================================" | |
| case "$PHASE" in | |
| pretrain) | |
| gate_pretrain | |
| print_summary "pretrain" | |
| ;; | |
| sft) | |
| gate_sft | |
| print_summary "sft" | |
| ;; | |
| orpo) | |
| gate_orpo | |
| print_summary "orpo" | |
| ;; | |
| deploy) | |
| gate_deploy | |
| print_summary "deploy" | |
| ;; | |
| all) | |
| gate_pretrain | |
| gate_sft | |
| gate_orpo | |
| gate_deploy | |
| print_summary "all" | |
| ;; | |
| *) | |
| echo "ERROR: ์ ์ ์๋ phase: $PHASE" | |
| echo "Usage: bash scripts/quality_gate.sh <pretrain|sft|orpo|deploy|all>" | |
| exit 2 | |
| ;; | |
| esac | |