chore: initial commit of ai site platform

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
whm
2026-07-31 10:31:17 +08:00
commit 4ca82fb58a
203 changed files with 45745 additions and 0 deletions

187
scripts/probe_dashscope.py Normal file
View File

@@ -0,0 +1,187 @@
"""Probe DashScope / 通义千问 connectivity and latency."""
from __future__ import annotations
import base64
import os
import socket
import ssl
import sys
import time
from pathlib import Path
import httpx
ROOT = Path(__file__).resolve().parents[1]
def load_env() -> None:
for envp in (ROOT / ".env", ROOT / "ai-service" / ".env"):
if not envp.exists():
continue
for line in envp.read_text(encoding="utf-8", errors="replace").splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
k, v = line.split("=", 1)
k, v = k.strip(), v.strip().strip('"').strip("'")
if k and k not in os.environ:
os.environ[k] = v
def post(base: str, key: str, payload: dict, timeout: float, label: str) -> tuple[float, int | None]:
t0 = time.time()
try:
with httpx.Client(timeout=timeout) as c:
r = c.post(
f"{base}/chat/completions",
headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
json=payload,
)
dt = time.time() - t0
print(f"[{label}] status={r.status_code} time={dt:.1f}s bytes_in={len(r.content)}")
if r.status_code >= 400:
print(f"[{label}] body {r.text[:500].replace(chr(10), ' ')}")
else:
j = r.json()
txt = j["choices"][0]["message"]["content"]
if isinstance(txt, list):
txt = "".join((x.get("text") if isinstance(x, dict) else str(x)) for x in txt)
print(f"[{label}] ok content_len={len(str(txt))} preview={str(txt)[:100]!r}")
return dt, r.status_code
except Exception as e:
dt = time.time() - t0
print(f"[{label}] FAIL after {dt:.1f}s: {type(e).__name__}: {e}")
return dt, None
def main() -> int:
load_env()
key = (os.getenv("DASHSCOPE_API_KEY") or "").strip()
base = (os.getenv("DASHSCOPE_BASE_URL") or "https://dashscope.aliyuncs.com/compatible-mode/v1").rstrip("/")
model = (os.getenv("VISION_MODEL") or "qwen3.6-plus").strip()
print(f"base={base}")
print(f"model={model}")
print(f"key_set={bool(key)} key_len={len(key)}")
if not key:
print("NO DASHSCOPE_API_KEY")
return 1
host = "dashscope.aliyuncs.com"
t0 = time.time()
try:
ips = socket.getaddrinfo(host, 443, type=socket.SOCK_STREAM)
print(f"DNS ok {time.time() - t0:.2f}s -> {sorted({x[4][0] for x in ips})[:4]}")
except Exception as e:
print(f"DNS FAIL {type(e).__name__}: {e}")
t0 = time.time()
try:
ctx = ssl.create_default_context()
with socket.create_connection((host, 443), timeout=10) as sock:
with ctx.wrap_socket(sock, server_hostname=host) as ssock:
print(f"TLS ok {time.time() - t0:.2f}s protocol={ssock.version()}")
except Exception as e:
print(f"TLS FAIL {type(e).__name__}: {e}")
# 1) text-only
post(
base,
key,
{
"model": model,
"temperature": 0,
"messages": [{"role": "user", "content": "只回复:通义可达"}],
"max_tokens": 32,
},
30.0,
"text-only",
)
# 2) tiny image
png_b64 = (
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
)
post(
base,
key,
{
"model": model,
"temperature": 0,
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "这张图是什么颜色?一句话。"},
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{png_b64}"}},
],
}
],
"max_tokens": 64,
},
60.0,
"tiny-image",
)
# 3) real refs
refs = list((ROOT / "test" / "refs").glob("*.png"))[:2]
if not refs:
refs = list((ROOT / "test").rglob("board_*.png"))[:2]
print("refs", [f"{p.name}:{p.stat().st_size}" for p in refs])
if refs:
content: list[dict] = [{"type": "text", "text": "用一句话描述这些界面截图里最显眼的标题。"}]
total = 0
for p in refs:
raw = p.read_bytes()
total += len(raw)
b64 = base64.b64encode(raw).decode("ascii")
content.append({"type": "image_url", "image_url": {"url": f"data:image/png;base64,{b64}"}})
print(f"ref payload images_bytes={total} b64_approx={total * 4 // 3}")
post(
base,
key,
{
"model": model,
"temperature": 0,
"messages": [{"role": "user", "content": content}],
"max_tokens": 128,
},
150.0,
"real-refs",
)
# long prompt + 2 images like fidelity scoring (heavier)
long_text = ("请逐区对照并打分。" + "" * 800)[:2000]
content2 = [{"type": "text", "text": long_text}] + content[1:]
post(
base,
key,
{
"model": model,
"temperature": 0,
"messages": [{"role": "user", "content": content2}],
"max_tokens": 512,
},
150.0,
"fidelity-like",
)
# 4) alternate model text
if model != "qwen-vl-plus":
post(
base,
key,
{
"model": "qwen-vl-plus",
"temperature": 0,
"messages": [{"role": "user", "content": "只回复vl-plus可达"}],
"max_tokens": 32,
},
30.0,
"alt-qwen-vl-plus-text",
)
return 0
if __name__ == "__main__":
raise SystemExit(main())