55 lines
1.7 KiB
Bash
Executable File
55 lines
1.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Tests local vLLM OpenAI-compatible API using curl and validates response shape.
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
ENV_FILE="${REPO_ROOT}/.env"
|
|
|
|
if [[ ! -f "${ENV_FILE}" ]]; then
|
|
echo "[test_api][error] .env file not found. Copy .env.example to .env first." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# shellcheck disable=SC1090
|
|
source "${ENV_FILE}"
|
|
|
|
BACKEND_PORT="${BACKEND_PORT:-8000}"
|
|
GEMMA_MODEL_ID="${GEMMA_MODEL_ID:-google/gemma-3-1b-it}"
|
|
VLLM_API_KEY="${VLLM_API_KEY:-EMPTY}"
|
|
API_URL="http://localhost:${BACKEND_PORT}/v1/chat/completions"
|
|
|
|
payload_file="$(mktemp)"
|
|
response_file="$(mktemp)"
|
|
trap 'rm -f "${payload_file}" "${response_file}"' EXIT
|
|
|
|
cat > "${payload_file}" <<JSON
|
|
{
|
|
"model": "${GEMMA_MODEL_ID}",
|
|
"messages": [
|
|
{"role": "system", "content": "You are a concise assistant."},
|
|
{"role": "user", "content": "Say hello from Gemma 3 running on vLLM."}
|
|
],
|
|
"temperature": 0.2,
|
|
"max_tokens": 64
|
|
}
|
|
JSON
|
|
|
|
http_status="$(curl -sS -o "${response_file}" -w '%{http_code}' -H "Content-Type: application/json" -H "Authorization: Bearer ${VLLM_API_KEY}" -X POST "${API_URL}" --data @"${payload_file}")"
|
|
|
|
if [[ ! "${http_status}" =~ ^2 ]]; then
|
|
echo "[test_api][error] API returned HTTP ${http_status}" >&2
|
|
cat "${response_file}" >&2
|
|
echo "[test_api][hint] See docs/TROUBLESHOOTING.md#vllm-container-exits-or-fails-healthchecks" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! grep -q '"choices"' "${response_file}"; then
|
|
echo "[test_api][error] API response did not include expected 'choices' field." >&2
|
|
cat "${response_file}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "[test_api] Success. API responded with expected structure."
|
|
cat "${response_file}"
|