tchbcb commited on
Commit
0318eea
·
verified ·
1 Parent(s): 0b8e372

backup s27b_serve.sh

Browse files
Files changed (1) hide show
  1. sft-adapter/s27b_serve.sh +153 -0
sft-adapter/s27b_serve.sh ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # ============================================================================
3
+ # s27b_serve.sh — samai-27b-mixbit OpenAI 兼容 API 服务管理 (Kaggle 2x T4)
4
+ # 移植自 s4b_serve.sh; 上游 llama.cpp (QWEN35 arch, 双卡 layer split)
5
+ #
6
+ # 端点: /v1/chat/completions /v1/completions /v1/models (Bearer 鉴权, key=1234)
7
+ # 默认: Q5_K_M(Q6_K emb) @ CTX=131072 + KV q8_0 + 思考默认关(隧道120s防护)
8
+ #
9
+ # 用法:
10
+ # bash s27b_serve.sh start | stop | status | test
11
+ # 覆盖: GGUF=/path/model.gguf CTX=131072 KVQ=q8_0 PORT=8100 API_KEY=1234 \
12
+ # EXTRA_ARGS="-fa" bash s27b_serve.sh start
13
+ # ============================================================================
14
+ set -euo pipefail
15
+
16
+ GGUF="${GGUF:-/tmp/k27/gguf/samai-27b-mixbit-Q5_K_M.gguf}"
17
+ CTX="${CTX:-131072}"
18
+ PORT="${PORT:-8100}"
19
+ NGL="${NGL:-999}"
20
+ KVQ="${KVQ:-q8_0}"
21
+ API_KEY="${API_KEY:-1234}"
22
+ THREADS="${THREADS:-4}"
23
+ EXTRA_ARGS="${EXTRA_ARGS:-}"
24
+ RPEN="${RPEN:-1.1}"
25
+ RLASTN="${RLASTN:-512}"
26
+ TEMP="${TEMP:-0.6}"
27
+ DRYM="${DRYM:-0.8}"
28
+ DRLN="${DRLN:-512}"
29
+ THINKING="${THINKING:-off}"
30
+ BIN="/tmp/k27/lcpp-up/build/bin/llama-server"
31
+ LOG_FILE="/tmp/k27/s27b-api-server.log"
32
+ PID_FILE="/tmp/k27/s27b-api-server.pid"
33
+
34
+ GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; CYAN='\033[0;36m'; NC='\033[0m'
35
+ info() { echo -e "${GREEN}[API]${NC} $*"; }
36
+ warn() { echo -e "${YELLOW}[API]${NC} $*"; }
37
+ fail() { echo -e "${RED}[API]${NC} $*"; exit 1; }
38
+
39
+ do_stop() {
40
+ if [[ -f "$PID_FILE" ]] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
41
+ kill "$(cat "$PID_FILE")" && info "已停止 PID $(cat "$PID_FILE")"
42
+ fi
43
+ rm -f "$PID_FILE"
44
+ }
45
+
46
+ do_start_inner() {
47
+ local extra="$1"
48
+ local kv_args=""
49
+ [[ -n "$KVQ" ]] && kv_args="-ctk $KVQ -ctv $KVQ"
50
+ local key_args=""
51
+ [[ -n "$API_KEY" && "$API_KEY" != "off" ]] && key_args="--api-key $API_KEY"
52
+ local think_args=""
53
+ [[ "$THINKING" == "off" ]] && think_args="--chat-template-kwargs '{\"enable_thinking\":false}'"
54
+
55
+ info "启动: $GGUF ctx=$CTX kv=$KVQ port=$PORT"
56
+ local bindir="$(dirname "$BIN")"
57
+ nohup bash -c "cd '$bindir' && exec ./llama-server -m '$GGUF' -ngl $NGL -c $CTX -t $THREADS --jinja \
58
+ --host 0.0.0.0 --port $PORT \
59
+ $kv_args $key_args $think_args $extra --repeat-penalty $RPEN --repeat-last-n $RLASTN --temp $TEMP --dry-multiplier $DRYM --dry-penalty-last-n $DRLN" \
60
+ > "$LOG_FILE" 2>&1 &
61
+ echo $! > "$PID_FILE"
62
+ }
63
+
64
+ do_start() {
65
+ [[ -x "$BIN" ]] || fail "llama-server 不存在: $BIN (先编译 lcpp-up)"
66
+ [[ -f "$GGUF" ]] || fail "模型不存在: $GGUF (先跑 s27_gguf_src + convert + quantize)"
67
+ do_stop 2>/dev/null || true
68
+
69
+ do_start_inner "$EXTRA_ARGS"
70
+ local ok=0
71
+ for i in $(seq 1 60); do
72
+ sleep 5
73
+ if ! kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
74
+ warn "进程退出(-fa 兼容性?), 去掉 -fa 重试一次..."
75
+ tail -5 "$LOG_FILE" || true
76
+ do_stop 2>/dev/null || true
77
+ do_start_inner "$(echo "$EXTRA_ARGS" | sed 's/-fa\( on\| off\)\?//g')"
78
+ ok=0
79
+ continue
80
+ fi
81
+ if curl -s --max-time 3 "http://127.0.0.1:$PORT/health" 2>/dev/null | grep -q '"status"'; then
82
+ ok=1; break
83
+ fi
84
+ done
85
+ [[ $ok == 1 ]] || fail "300s 未就绪,日志尾部:\n$(tail -30 "$LOG_FILE")"
86
+
87
+ info "服务就绪!"
88
+ echo -e "${CYAN}──────────────────────────────────────────────────${NC}"
89
+ echo -e " 本机地址: http://127.0.0.1:$PORT/v1/chat/completions"
90
+ echo -e " API Key: ${API_KEY}"
91
+ echo -e " 上下文: $CTX tokens (KV q8_0)"
92
+ echo -e " 模型文件: $GGUF"
93
+ echo -e " 思考模式: $([[ "$THINKING" == "off" ]] && echo '默认关闭(隧道504防护)' || echo '默认开启')"
94
+ echo -e "${CYAN}──────────────────────────────────────────────────${NC}"
95
+ nvidia-smi --query-gpu=memory.used,memory.total --format=csv,noheader | awk '{print " 显存占用: " $0}'
96
+ }
97
+
98
+ do_status() {
99
+ if [[ -f "$PID_FILE" ]] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
100
+ info "运行中 (PID $(cat "$PID_FILE"))"
101
+ curl -s --max-time 5 "http://127.0.0.1:$PORT/health" 2>/dev/null | head -c 300 || true; echo
102
+ tail -3 "$LOG_FILE" 2>/dev/null || true
103
+ else
104
+ warn "未运行"
105
+ fi
106
+ }
107
+
108
+ do_test() {
109
+ local auth=(-H "Authorization: Bearer ${API_KEY}")
110
+ info "== 非流式 =="
111
+ curl -s --max-time 115 "http://127.0.0.1:$PORT/v1/chat/completions" \
112
+ "${auth[@]}" -H "Content-Type: application/json" \
113
+ -d '{"model":"samai-27b","messages":[{"role":"user","content":"回复两个字:收到"}],"max_tokens":32,"temperature":0}' \
114
+ | python3 -c "import json,sys;d=json.load(sys.stdin);print('content:',d['choices'][0]['message']['content'][:200])" || warn "非流式失败"
115
+ info "== 流式 (SSE) =="
116
+ curl -sN --max-time 115 "http://127.0.0.1:$PORT/v1/chat/completions" \
117
+ "${auth[@]}" -H "Content-Type: application/json" \
118
+ -d '{"model":"samai-27b","messages":[{"role":"user","content":"从1数到8,用顿号分隔"}],"stream":true,"max_tokens":64,"temperature":0}' \
119
+ | python3 -c "
120
+ import sys, json
121
+ n=0; buf=[]
122
+ for line in sys.stdin:
123
+ line=line.strip()
124
+ if line.startswith('data: ') and line != 'data: [DONE]':
125
+ try:
126
+ d=json.loads(line[6:]); c=(d['choices'][0].get('delta') or {}).get('content') or ''
127
+ if c: n+=1; buf.append(c)
128
+ except Exception: pass
129
+ print(''.join(buf)); print(f'--- {n} chunks, SSE', 'OK ---' if n else 'FAIL ---')" || warn "流式失败"
130
+ info "== 租金题 (验收) =="
131
+ curl -sN --max-time 115 "http://127.0.0.1:$PORT/v1/chat/completions" \
132
+ "${auth[@]}" -H "Content-Type: application/json" \
133
+ -d '{"model":"samai-27b","messages":[{"role":"user","content":"一个出租院落面积20亩,去年每亩租金1600元,今年每亩租金比去年上涨50%。今年该院落全部出租,租金总额是多少?注意:不需要考虑押金和卫生费。"}],"stream":true,"max_tokens":256,"temperature":0}' \
134
+ | python3 -c "
135
+ import sys, json
136
+ buf=[]
137
+ for line in sys.stdin:
138
+ line=line.strip()
139
+ if line.startswith('data: ') and line != 'data: [DONE]':
140
+ try:
141
+ d=json.loads(line[6:]); c=(d['choices'][0].get('delta') or {}).get('content') or ''
142
+ if c: buf.append(c)
143
+ except Exception: pass
144
+ print(''.join(buf))" || warn "租金题失败"
145
+ }
146
+
147
+ case "${1:-help}" in
148
+ start) do_start ;;
149
+ stop) do_stop ;;
150
+ status) do_status ;;
151
+ test) do_test ;;
152
+ *) grep '^# ' "$0" | sed 's/^# //' ;;
153
+ esac