Add reproducible DGX Spark deployment for Qwen3.8 Flash Next NVFP4
This commit is contained in:
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$(dirname -- "${BASH_SOURCE[0]}")/common.sh"
|
||||
"${compose[@]}" build vllm
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
PROJECT_ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
cd "$PROJECT_ROOT"
|
||||
if [[ ! -f .env ]]; then
|
||||
echo 'Copy .env.example to .env and configure paths/proxy first.' >&2
|
||||
exit 1
|
||||
fi
|
||||
compose=(docker compose --env-file .env -f compose.yaml)
|
||||
@@ -0,0 +1,7 @@
|
||||
from huggingface_hub import snapshot_download
|
||||
|
||||
print(snapshot_download(
|
||||
repo_id="nvidia/Qwen3.8-Flash-Next-NVFP4",
|
||||
revision="fc694b54fb0174e0913e6adf86691ef85a4ead47",
|
||||
max_workers=4,
|
||||
), flush=True)
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$(dirname -- "${BASH_SOURCE[0]}")/common.sh"
|
||||
"${compose[@]}" --profile tools run --rm download
|
||||
@@ -0,0 +1,42 @@
|
||||
import json
|
||||
import time
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
key = Path('/run/secrets/qwen_api_key').read_text().strip()
|
||||
base = 'http://127.0.0.1:8000'
|
||||
headers = {'Authorization': 'Bearer ' + key, 'Content-Type': 'application/json'}
|
||||
|
||||
def request(path, payload=None):
|
||||
data = None if payload is None else json.dumps(payload).encode()
|
||||
with urllib.request.urlopen(urllib.request.Request(base + path, data=data, headers=headers), timeout=900) as response:
|
||||
return json.load(response)
|
||||
|
||||
print(json.dumps({'models': request('/v1/models')}, ensure_ascii=False), flush=True)
|
||||
cases = [
|
||||
('arithmetic', '计算 17 × 19,只给出数字。', '323'),
|
||||
('chinese', '请用中文简短说明为什么天空是蓝色的。', None),
|
||||
]
|
||||
for name, prompt, expected in cases:
|
||||
start = time.monotonic()
|
||||
result = request('/v1/chat/completions', {
|
||||
'model': 'qwen3.8-flash-next',
|
||||
'messages': [{'role': 'user', 'content': prompt}],
|
||||
'temperature': 0, 'max_tokens': 1024, 'reasoning_effort': 'low',
|
||||
})
|
||||
choice = result['choices'][0]
|
||||
content = choice['message'].get('content') or ''
|
||||
record = {'test': name, 'seconds': round(time.monotonic()-start, 2),
|
||||
'content': content, 'finish_reason': choice['finish_reason'], 'usage': result.get('usage')}
|
||||
print(json.dumps(record, ensure_ascii=False), flush=True)
|
||||
assert content.strip(), 'No final answer'
|
||||
if expected:
|
||||
assert expected in content, 'Arithmetic mismatch'
|
||||
|
||||
|
||||
p={'model':'qwen3.8-flash-next','messages':[{'role':'user','content':'请调用 get_weather 查询上海的天气,不要自行编造。'}],'tools':[{'type':'function','function':{'name':'get_weather','description':'查询城市天气','parameters':{'type':'object','properties':{'city':{'type':'string'}},'required':['city']}}}],'tool_choice':'auto','temperature':0,'max_tokens':512,'reasoning_effort':'low'}
|
||||
t=time.monotonic();r=request('/v1/chat/completions', p);m=r['choices'][0]['message'];print(json.dumps({'test':'tool_call','seconds':time.monotonic()-t,'message':m},ensure_ascii=False),flush=True)
|
||||
assert m.get('tool_calls') and m['tool_calls'][0]['function']['name']=='get_weather'
|
||||
print('TOOL_TEST_PASS',flush=True)
|
||||
|
||||
print("SMOKE_TEST_PASS", flush=True)
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$(dirname -- "${BASH_SOURCE[0]}")/common.sh"
|
||||
if [[ "${1:-}" == baseline ]]; then
|
||||
compose+=(-f configs/baseline-32k.yaml)
|
||||
elif [[ $# -gt 0 ]]; then
|
||||
echo "Usage: $0 [baseline]" >&2; exit 2
|
||||
fi
|
||||
"${compose[@]}" config --quiet
|
||||
"${compose[@]}" up -d --no-build vllm
|
||||
echo 'Loading takes about 10-13 minutes. Run scripts/wait.sh, then scripts/test.sh.'
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$(dirname -- "${BASH_SOURCE[0]}")/common.sh"
|
||||
"${compose[@]}" run --rm --no-deps -T --entrypoint python3 vllm -u - < tests/test_disk_adapter.py
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$(dirname -- "${BASH_SOURCE[0]}")/common.sh"
|
||||
"${compose[@]}" exec -T vllm python3 -u - < scripts/smoke-test.py
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
source "$(dirname -- "${BASH_SOURCE[0]}")/common.sh"
|
||||
for ((i=0; i<120; i++)); do
|
||||
if "${compose[@]}" exec -T vllm python3 -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health',timeout=3)" >/dev/null 2>&1; then
|
||||
echo READY; exit 0
|
||||
fi
|
||||
sleep 15
|
||||
done
|
||||
echo 'Startup timed out. Inspect docker compose logs vllm.' >&2
|
||||
exit 1
|
||||
Reference in New Issue
Block a user