gpt-5.4-mini @ medium · api
apimedium
- config
- gpt-5.4-mini-eff-medium--api--official--dev
- batch
- 2026-07-19--unified
- transport
- openai-official-api
- protocol
- api · metered
- served model
- gpt-5.4-mini-2026-03-17
- 采集于
- 2026年7月18日 11:54 · N=4
variant
live
slot 0 · P-q · sandboxed iframe

截图是 similarity 通道测量时的原始像素。运行 live 会在 sandboxed iframe 中重新执行原始输出;渲染结果取决于你的浏览器和字体,不保证与测量像素一致。
similarity 邻居
最近
claude-opus-4-8 @low · kiro0.66gpt-5.6-sol @low · kiro0.66claude-sonnet-5 @low · CC0.64gpt-5.6-sol @low · codex-oauth0.64gpt-5.6-terra @high · kiro0.64最远
gpt-5.6-luna @high · kiro0.44gemini-3.1-pro-preview @low · api0.44kimi-k2.6 · go0.47gpt-5.6-luna @medium · codex-oauth0.47gpt-5.5 @xhigh · codex-oauth0.47限于 session 2026-07-19--unified
similarity 衡量本 session 内的趋同程度 —— 不是质量。
Fidelity —— 卡片展示的数据对不对?
- namenot-foundtext-present-no-name-hit
- conditionmismatchother-wmo-code
- datenot-foundno-parseable-date
- max tempnot-foundno-temperature-candidate
- min tempnot-foundno-temperature-candidate
- hourlynot-foundcoverage · 0 命中 · 0 不符 · 24 未展示
- request sidematch0 处违规
extractor fidelity-extractor-v1+Berlin-2026-07-15
源码 —— 原始模型输出,一字节未改
下载 card.html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Weather Card</title>
<style>
:root{
--bg0:#07101f;
--bg1:#0b1630;
--bg2:#0f1f3e;
--card:rgba(10, 18, 36, 0.66);
--card-strong:rgba(12, 20, 41, 0.82);
--stroke:rgba(255,255,255,0.12);
--stroke-strong:rgba(255,255,255,0.18);
--text:#f4f7ff;
--muted:#9fb0d0;
--muted2:#7285a8;
--accent1:#7ad7ff;
--accent2:#7f7bff;
--accent3:#93f0d2;
--shadow:0 24px 80px rgba(0,0,0,.42);
--bar-fill:linear-gradient(180deg, rgba(255,255,255,.95), rgba(255,255,255,.68));
--bar-glow:rgba(255,255,255,.14);
--theme-label:rgba(255,255,255,.08);
}
*{box-sizing:border-box}
html,body{height:100%}
body{
margin:0;
overflow:hidden;
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color:var(--text);
background:
radial-gradient(1200px 700px at 15% 10%, rgba(114, 168, 255, 0.22), transparent 55%),
radial-gradient(1000px 600px at 85% 18%, rgba(149, 104, 255, 0.18), transparent 52%),
radial-gradient(900px 600px at 65% 90%, rgba(64, 193, 255, 0.12), transparent 58%),
linear-gradient(145deg, var(--bg0), var(--bg1) 48%, var(--bg2));
}
body::before,
body::after{
content:"";
position:fixed;
inset:auto;
pointer-events:none;
filter: blur(18px);
opacity:.8;
}
body::before{
width:420px;
height:420px;
left:-120px;
top:-100px;
background: radial-gradient(circle at 30% 30%, rgba(122, 215, 255, .28), rgba(122, 215, 255, 0) 70%);
}
body::after{
width:520px;
height:520px;
right:-180px;
bottom:-170px;
background: radial-gradient(circle at 50% 50%, rgba(127, 123, 255, .22), rgba(127, 123, 255, 0) 68%);
}
.shell{
position:relative;
z-index:1;
width:100%;
height:100%;
display:grid;
place-items:center;
padding:20px;
}
.card{
width:min(1160px, calc(100vw - 40px));
height:min(740px, calc(100vh - 40px));
border:1px solid var(--stroke);
border-radius:30px;
background:
linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.02)),
linear-gradient(160deg, rgba(11,18,34,.84), rgba(9,14,28,.72));
box-shadow:var(--shadow);
backdrop-filter: blur(18px);
-webkit-backdrop-filter: blur(18px);
overflow:hidden;
position:relative;
}
.card::before{
content:"";
position:absolute;
inset:0;
background:
radial-gradient(650px 240px at 16% 0%, rgba(255,255,255,.11), transparent 58%),
radial-gradient(560px 240px at 86% 8%, rgba(122,215,255,.11), transparent 56%),
linear-gradient(180deg, rgba(255,255,255,.04), transparent 24%);
pointer-events:none;
}
.inner{
position:relative;
z-index:1;
height:100%;
display:grid;
grid-template-rows:auto 1fr;
padding:26px;
gap:22px;
}
.topbar{
display:flex;
align-items:flex-start;
justify-content:space-between;
gap:18px;
}
.brand{
display:flex;
align-items:center;
gap:12px;
min-width:0;
}
.dot{
width:14px;
height:14px;
border-radius:999px;
background:linear-gradient(135deg, var(--accent1), var(--accent2));
box-shadow:0 0 0 6px rgba(255,255,255,.05), 0 0 30px rgba(122,215,255,.34);
flex:0 0 auto;
}
.brand-copy{
display:flex;
flex-direction:column;
gap:3px;
min-width:0;
}
.kicker{
text-transform:uppercase;
letter-spacing:.28em;
color:var(--muted2);
font-size:11px;
font-weight:700;
line-height:1;
}
.headline{
font-size:18px;
font-weight:700;
line-height:1.1;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.status{
display:flex;
align-items:center;
gap:10px;
flex-wrap:wrap;
justify-content:flex-end;
}
.pill{
display:inline-flex;
align-items:center;
gap:8px;
padding:10px 14px;
border-radius:999px;
background:rgba(255,255,255,.06);
border:1px solid var(--stroke);
color:var(--text);
font-size:13px;
font-weight:600;
letter-spacing:.01em;
box-shadow:inset 0 1px 0 rgba(255,255,255,.06);
white-space:nowrap;
}
.pill.subtle{
color:var(--muted);
font-weight:500;
background:rgba(255,255,255,.04);
}
.content{
display:grid;
grid-template-columns: 350px minmax(0, 1fr);
gap:22px;
min-height:0;
}
.panel{
border:1px solid var(--stroke);
background:
linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,.02)),
rgba(6, 10, 20, 0.24);
border-radius:24px;
box-shadow:inset 0 1px 0 rgba(255,255,255,.04);
overflow:hidden;
min-height:0;
}
.summary{
display:flex;
flex-direction:column;
padding:22px;
gap:18px;
}
.icon-wrap{
display:flex;
align-items:center;
gap:18px;
}
.icon-badge{
width:96px;
height:96px;
border-radius:26px;
background:
radial-gradient(circle at 30% 24%, rgba(255,255,255,.16), transparent 56%),
linear-gradient(160deg, rgba(255,255,255,.10), rgba(255,255,255,.04));
border:1px solid rgba(255,255,255,.14);
box-shadow:0 16px 34px rgba(0,0,0,.18), inset 0 1px 0 rgba(255,255,255,.06);
display:grid;
place-items:center;
flex:0 0 auto;
position:relative;
overflow:hidden;
}
.icon-badge::after{
content:"";
position:absolute;
inset:auto -20% -36% -20%;
height:65%;
background:linear-gradient(180deg, transparent, rgba(255,255,255,.12));
transform:rotate(-8deg);
}
.icon-badge svg{
width:66px;
height:66px;
position:relative;
z-index:1;
}
.location{
min-width:0;
flex:1;
display:flex;
flex-direction:column;
gap:8px;
}
.location h1{
margin:0;
font-size:33px;
line-height:1.02;
letter-spacing:-0.04em;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.date-line{
display:flex;
flex-wrap:wrap;
gap:8px 10px;
align-items:center;
color:var(--muted);
font-size:14px;
font-weight:500;
}
.date-line .iso{
color:var(--muted2);
font-variant-numeric: tabular-nums;
}
.summary-stack{
display:grid;
gap:14px;
}
.range-card{
padding:18px 18px 16px;
border-radius:20px;
background:linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.03));
border:1px solid rgba(255,255,255,.10);
}
.range-label{
color:var(--muted);
font-size:12px;
text-transform:uppercase;
letter-spacing:.18em;
margin-bottom:10px;
font-weight:700;
}
.range-value{
display:flex;
align-items:flex-end;
gap:10px;
margin-bottom:6px;
}
.max-temp{
font-size:60px;
font-weight:800;
letter-spacing:-0.06em;
line-height:0.9;
background: linear-gradient(180deg, #ffffff, rgba(255,255,255,.72));
-webkit-background-clip:text;
background-clip:text;
color:transparent;
font-variant-numeric: tabular-nums;
}
.min-temp{
font-size:25px;
font-weight:700;
color:var(--muted);
letter-spacing:-0.03em;
margin-bottom:8px;
font-variant-numeric: tabular-nums;
}
.condition{
font-size:16px;
color:var(--text);
font-weight:600;
line-height:1.35;
}
.meta-grid{
display:grid;
grid-template-columns:1fr 1fr;
gap:12px;
}
.meta{
padding:14px 16px;
border-radius:18px;
background:rgba(255,255,255,.04);
border:1px solid rgba(255,255,255,.09);
}
.meta .label{
display:block;
font-size:11px;
text-transform:uppercase;
letter-spacing:.18em;
color:var(--muted2);
margin-bottom:7px;
font-weight:700;
}
.meta .value{
font-size:14px;
font-weight:600;
color:var(--text);
line-height:1.35;
font-variant-numeric: tabular-nums;
}
.chart{
display:flex;
flex-direction:column;
padding:22px 22px 18px;
gap:16px;
min-height:0;
}
.chart-head{
display:flex;
align-items:flex-start;
justify-content:space-between;
gap:14px;
}
.chart-title{
display:flex;
flex-direction:column;
gap:5px;
}
.chart-title h2{
margin:0;
font-size:18px;
letter-spacing:-0.02em;
line-height:1.2;
}
.chart-title p{
margin:0;
color:var(--muted);
font-size:13px;
line-height:1.35;
}
.legend{
display:flex;
align-items:center;
gap:8px;
color:var(--muted);
font-size:12px;
white-space:nowrap;
padding-top:4px;
}
.legend-swatch{
width:12px;
height:12px;
border-radius:999px;
background:linear-gradient(135deg, var(--accent1), var(--accent2));
box-shadow:0 0 18px rgba(122,215,255,.25);
}
.hourly-grid{
position:relative;
display:grid;
grid-template-columns:repeat(24, minmax(0, 1fr));
gap:8px;
min-height:0;
align-items:end;
flex:1;
padding:14px 10px 10px;
border-radius:22px;
background:
linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.02)),
rgba(255,255,255,.02);
border:1px solid rgba(255,255,255,.08);
overflow:hidden;
}
.hour-cell{
display:flex;
flex-direction:column;
justify-content:flex-end;
align-items:center;
gap:8px;
height:100%;
min-height:0;
padding:6px 0;
}
.hour-top,
.hour-temp{
width:100%;
text-align:center;
font-variant-numeric: tabular-nums;
line-height:1;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.hour-top{
font-size:11px;
color:var(--muted2);
font-weight:700;
letter-spacing:.07em;
}
.hour-temp{
font-size:12px;
color:var(--text);
font-weight:700;
}
.bar-track{
position:relative;
width:100%;
height:246px;
border-radius:14px;
display:flex;
align-items:flex-end;
justify-content:center;
padding:8px 0;
background:linear-gradient(180deg, rgba(255,255,255,.025), rgba(255,255,255,.01));
overflow:hidden;
}
.bar-track::before{
content:"";
position:absolute;
inset:0;
background:
linear-gradient(180deg, transparent 0, transparent calc(100% - 1px), rgba(255,255,255,.08) calc(100% - 1px), rgba(255,255,255,.08) 100%);
opacity:.35;
pointer-events:none;
}
.bar-fill{
width:78%;
border-radius:10px 10px 4px 4px;
background:
linear-gradient(180deg, rgba(255,255,255,.95), rgba(255,255,255,.72));
box-shadow:0 0 22px var(--bar-glow);
position:relative;
min-height:4px;
transition:height .35s ease;
}
.bar-fill::after{
content:"";
position:absolute;
inset:auto 0 0 0;
height:100%;
border-radius:inherit;
background:linear-gradient(180deg, rgba(255,255,255,.24), transparent);
pointer-events:none;
}
.footer-note{
display:flex;
justify-content:space-between;
align-items:center;
gap:12px;
color:var(--muted2);
font-size:12px;
padding-top:2px;
}
.footer-note strong{
color:var(--muted);
font-weight:600;
}
.loading,
.error-state{
position:absolute;
inset:0;
display:grid;
place-items:center;
padding:24px;
text-align:center;
}
.loading-card,
.error-card{
width:min(560px, 100%);
border-radius:24px;
padding:28px;
border:1px solid rgba(255,255,255,.12);
background:rgba(7, 12, 24, .70);
box-shadow:var(--shadow);
backdrop-filter: blur(16px);
}
.spinner{
width:42px;
height:42px;
border-radius:50%;
margin:0 auto 16px;
border:3px solid rgba(255,255,255,.14);
border-top-color:rgba(255,255,255,.86);
animation:spin 0.9s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}
.loading-card h2,
.error-card h2{
margin:0 0 8px;
font-size:22px;
letter-spacing:-0.02em;
}
.loading-card p,
.error-card p{
margin:0;
color:var(--muted);
line-height:1.5;
font-size:14px;
}
.error-card{
border-color:rgba(255, 120, 120, .22);
background:rgba(33, 10, 18, .68);
}
@media (max-width: 1100px){
.card{height:auto; min-height:calc(100vh - 40px)}
.content{grid-template-columns:1fr}
body{overflow:auto}
}
</style>
</head>
<body>
<div class="shell">
<main class="card" id="card" aria-live="polite">
<div class="inner" id="app">
<div class="topbar">
<div class="brand">
<div class="dot" aria-hidden="true"></div>
<div class="brand-copy">
<div class="kicker">Weather card</div>
<div class="headline" id="headline">Loading weather…</div>
</div>
</div>
<div class="status">
<div class="pill subtle" id="sourcePill">UTC</div>
<div class="pill" id="endpointPill">Fetching</div>
</div>
</div>
<div class="content">
<section class="panel summary" aria-label="Weather summary">
<div class="icon-wrap">
<div class="icon-badge" id="iconBadge" aria-hidden="true"></div>
<div class="location">
<h1 id="locationName">Berlin</h1>
<div class="date-line">
<span id="humanDate">Today</span>
<span class="iso" id="isoDate">2026-01-01</span>
</div>
</div>
</div>
<div class="summary-stack">
<div class="range-card">
<div class="range-label">Daily temperatures</div>
<div class="range-value">
<div class="max-temp" id="maxTemp">—</div>
</div>
<div class="min-temp" id="minTemp">—</div>
<div class="condition" id="conditionText">Weather data will appear here.</div>
</div>
<div class="meta-grid">
<div class="meta">
<span class="label">Coordinates</span>
<div class="value" id="coordsText">—</div>
</div>
<div class="meta">
<span class="label">Source</span>
<div class="value" id="sourceText">—</div>
</div>
<div class="meta">
<span class="label">Latitude</span>
<div class="value" id="latText">—</div>
</div>
<div class="meta">
<span class="label">Longitude</span>
<div class="value" id="lonText">—</div>
</div>
</div>
</div>
</section>
<section class="panel chart" aria-label="Hourly temperatures">
<div class="chart-head">
<div class="chart-title">
<h2>Hourly temperatures</h2>
<p>UTC, one value per hour for the requested date.</p>
</div>
<div class="legend"><span class="legend-swatch"></span> temperature</div>
</div>
<div class="hourly-grid" id="hourlyGrid"></div>
<div class="footer-note">
<div><strong>Weather condition:</strong> <span id="conditionSmall">—</span></div>
<div><strong>Date:</strong> <span id="dateSmall">—</span></div>
</div>
</section>
</div>
</div>
<div class="loading" id="loadingState">
<div class="loading-card">
<div class="spinner" aria-hidden="true"></div>
<h2>Loading weather data</h2>
<p>Fetching a single-day forecast or archive in UTC.</p>
</div>
</div>
</main>
</div>
<script>
(function () {
const defaultLat = 52.52;
const defaultLon = 13.405;
const defaultName = "Berlin";
const qs = new URLSearchParams(location.search);
function parseNumber(v, fallback) {
const n = Number.parseFloat(v);
return Number.isFinite(n) ? n : fallback;
}
function isValidISODate(v) {
return /^\d{4}-\d{2}-\d{2}$/.test(v) && !Number.isNaN(Date.parse(v + "T00:00:00Z"));
}
function todayUTC() {
return new Date().toISOString().slice(0, 10);
}
const lat = parseNumber(qs.get("lat"), defaultLat);
const lon = parseNumber(qs.get("lon"), defaultLon);
const name = (qs.get("name") || defaultName).trim() || defaultName;
const date = isValidISODate(qs.get("date") || "") ? qs.get("date") : todayUTC();
const utcToday = todayUTC();
const endpoint = date < utcToday ? "/api/om/archive" : "/api/om/forecast";
const els = {
card: document.getElementById("card"),
app: document.getElementById("app"),
loading: document.getElementById("loadingState"),
headline: document.getElementById("headline"),
sourcePill: document.getElementById("sourcePill"),
endpointPill: document.getElementById("endpointPill"),
iconBadge: document.getElementById("iconBadge"),
locationName: document.getElementById("locationName"),
humanDate: document.getElementById("humanDate"),
isoDate: document.getElementById("isoDate"),
maxTemp: document.getElementById("maxTemp"),
minTemp: document.getElementById("minTemp"),
conditionText: document.getElementById("conditionText"),
conditionSmall: document.getElementById("conditionSmall"),
coordsText: document.getElementById("coordsText"),
sourceText: document.getElementById("sourceText"),
latText: document.getElementById("latText"),
lonText: document.getElementById("lonText"),
hourlyGrid: document.getElementById("hourlyGrid"),
dateSmall: document.getElementById("dateSmall")
};
document.title = `${name} — Weather`;
function setTheme(kind) {
const themes = {
sunny: ["#ffd66b", "#ff9f47", "#ffecad"],
partly: ["#8fd5ff", "#7a7cff", "#d7f0ff"],
cloudy: ["#91a6c7", "#708ab2", "#d2def1"],
foggy: ["#b7c2d9", "#8fa0bf", "#e5edf8"],
rainy: ["#73b8ff", "#5a77ff", "#d8ecff"],
snowy: ["#8ef0ff", "#6dc3ff", "#e0fbff"],
stormy: ["#a48bff", "#664aff", "#eadfff"]
};
const t = themes[kind] || themes.cloudy;
document.documentElement.style.setProperty("--accent1", t[0]);
document.documentElement.style.setProperty("--accent2", t[1]);
document.documentElement.style.setProperty("--accent3", t[2]);
document.documentElement.style.setProperty("--bar-glow", hexToRgba(t[0], 0.22));
}
function hexToRgba(hex, alpha) {
const h = hex.replace("#", "");
const bigint = parseInt(h.length === 3 ? h.split("").map(ch => ch + ch).join("") : h, 16);
const r = (bigint >> 16) & 255;
const g = (bigint >> 8) & 255;
const b = bigint & 255;
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
function fmtTemp(n) {
if (!Number.isFinite(n)) return "—";
const rounded = Math.round(n * 10) / 10;
return `${Number.isInteger(rounded) ? rounded.toFixed(0) : rounded.toFixed(1)}°C`;
}
function fmtHour(iso) {
const d = new Date(iso);
if (Number.isNaN(d.getTime())) return "--";
return String(d.getUTCHours()).padStart(2, "0");
}
function formatFullDate(iso) {
const d = new Date(`${iso}T00:00:00Z`);
if (Number.isNaN(d.getTime())) return iso;
return new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
timeZone: "UTC"
}).format(d);
}
function weatherMeta(code) {
const c = Number(code);
const common = { kind: "cloudy", label: "Unknown conditions", icon: cloudySvg() };
if (c === 0) return { kind: "sunny", label: "Clear sky", icon: sunSvg() };
if (c === 1) return { kind: "partly", label: "Mainly clear", icon: partlySvg() };
if (c === 2) return { kind: "partly", label: "Partly cloudy", icon: partlySvg() };
if (c === 3) return { kind: "cloudy", label: "Overcast", icon: cloudSvg() };
if (c === 45 || c === 48) return { kind: "foggy", label: c === 45 ? "Fog" : "Depositing rime fog", icon: fogSvg() };
if ([51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 80, 81, 82].includes(c)) {
return { kind: "rainy", label: rainLabel(c), icon: rainSvg() };
}
if ([71, 73, 75, 77, 85, 86].includes(c)) {
return { kind: "snowy", label: snowLabel(c), icon: snowSvg() };
}
if ([95, 96, 99].includes(c)) return { kind: "stormy", label: stormLabel(c), icon: stormSvg() };
return common;
}
function rainLabel(c) {
if ([51, 53, 55].includes(c)) return "Drizzle";
if ([56, 57].includes(c)) return "Freezing drizzle";
if ([61, 63, 65].includes(c)) return "Rain";
if ([66, 67].includes(c)) return "Freezing rain";
return [80, 81, 82].includes(c) ? "Rain showers" : "Rain";
}
function snowLabel(c) {
if ([71, 73, 75].includes(c)) return "Snow fall";
if (c === 77) return "Snow grains";
return "Snow showers";
}
function stormLabel(c) {
if (c === 95) return "Thunderstorm";
if (c === 96) return "Thunderstorm with slight hail";
return "Thunderstorm with hail";
}
function sunSvg() {
return `
<svg viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<circle cx="48" cy="48" r="16" fill="rgba(255,255,255,.18)" stroke="rgba(255,255,255,.95)" stroke-width="3"/>
<g stroke="rgba(255,255,255,.95)" stroke-width="3" stroke-linecap="round">
<path d="M48 13v10"/>
<path d="M48 73v10"/>
<path d="M13 48h10"/>
<path d="M73 48h10"/>
<path d="M24 24l7 7"/>
<path d="M65 65l7 7"/>
<path d="M24 72l7-7"/>
<path d="M65 31l7-7"/>
</g>
</svg>`;
}
function partlySvg() {
return `
<svg viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<g opacity=".95">
<circle cx="35" cy="35" r="13" fill="rgba(255,255,255,.18)" stroke="rgba(255,255,255,.95)" stroke-width="3"/>
<g stroke="rgba(255,255,255,.95)" stroke-width="3" stroke-linecap="round">
<path d="M35 13v8"/>
<path d="M35 49v8"/>
<path d="M13 35h8"/>
<path d="M49 35h8"/>
<path d="M20 20l6 6"/>
<path d="M44 44l6 6"/>
<path d="M20 50l6-6"/>
<path d="M44 26l6-6"/>
</g>
</g>
<path d="M31 69h29c8.2 0 14.5-5.8 14.5-13.3S68.2 42.4 60 42.4c-2.2 0-4.3.5-6.2 1.3C51 39 45.8 36 40 36c-9.8 0-17.7 7-18.5 16.1C15 53.3 10.5 58.6 10.5 65c0 6 4.9 11 11 11H31"
fill="rgba(255,255,255,.14)" stroke="rgba(255,255,255,.95)" stroke-width="3.2" stroke-linejoin="round"/>
</svg>`;
}
function cloudSvg() {
return `
<svg viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M29 69h35c10 0 18-7 18-16.5S74 36 64 36c-2.8 0-5.4.6-7.8 1.7C53.6 31.1 46.7 26.5 38.7 26.5c-12.2 0-22.1 9.2-22.8 20.7C9.5 49.3 5 54.8 5 61.5 5 67.8 10 73 16.2 73H29"
fill="rgba(255,255,255,.16)" stroke="rgba(255,255,255,.95)" stroke-width="3.2" stroke-linejoin="round"/>
</svg>`;
}
function rainSvg() {
return `
<svg viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M26 55h32c10 0 18-7 18-16.5S72 22 62 22c-2.8 0-5.4.6-7.8 1.7C51.6 17.1 44.7 12.5 36.7 12.5c-12.2 0-22.1 9.2-22.8 20.7C6.5 35.3 2 40.8 2 47.5 2 53.8 7 59 13.2 59H26"
fill="rgba(255,255,255,.14)" stroke="rgba(255,255,255,.95)" stroke-width="3.2" stroke-linejoin="round"/>
<g stroke="rgba(122,215,255,.98)" stroke-width="3.5" stroke-linecap="round">
<path d="M28 66l-4 10"/>
<path d="M46 66l-4 10"/>
<path d="M64 66l-4 10"/>
</g>
</svg>`;
}
function snowSvg() {
return `
<svg viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M26 52h32c10 0 18-7 18-16.5S72 19 62 19c-2.8 0-5.4.6-7.8 1.7C51.6 14.1 44.7 9.5 36.7 9.5c-12.2 0-22.1 9.2-22.8 20.7C6.5 32.3 2 37.8 2 44.5 2 50.8 7 56 13.2 56H26"
fill="rgba(255,255,255,.14)" stroke="rgba(255,255,255,.95)" stroke-width="3.2" stroke-linejoin="round"/>
<g stroke="rgba(155, 240, 255, .98)" stroke-width="3" stroke-linecap="round">
<path d="M28 66v12"/>
<path d="M22 72h12"/>
<path d="M44 66v12"/>
<path d="M38 72h12"/>
<path d="M60 66v12"/>
<path d="M54 72h12"/>
</g>
</svg>`;
}
function fogSvg() {
return `
<svg viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M26 40c0-9 7.3-16.3 16.3-16.3 7.2 0 13.3 4.6 15.6 11 1.3-.4 2.8-.6 4.2-.6 7.7 0 13.9 6.2 13.9 13.9S69.8 62 62.1 62H24.6C15.9 62 9 55.1 9 46.4 9 39.4 14.1 33.5 20.9 32.2c1.2-7 6.9-12.2 14-12.2"
fill="rgba(255,255,255,.12)" stroke="rgba(255,255,255,.92)" stroke-width="3.1" stroke-linejoin="round"/>
<g stroke="rgba(255,255,255,.9)" stroke-width="3.4" stroke-linecap="round" opacity=".9">
<path d="M18 72h60"/>
<path d="M24 82h48"/>
<path d="M14 62h68"/>
</g>
</svg>`;
}
function stormSvg() {
return `
<svg viewBox="0 0 96 96" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path d="M26 54h32c10 0 18-7 18-16.5S72 21 62 21c-2.8 0-5.4.6-7.8 1.7C51.6 16.1 44.7 11.5 36.7 11.5c-12.2 0-22.1 9.2-22.8 20.7C6.5 34.3 2 39.8 2 46.5 2 52.8 7 58 13.2 58H26"
fill="rgba(255,255,255,.14)" stroke="rgba(255,255,255,.95)" stroke-width="3.2" stroke-linejoin="round"/>
<path d="M42 59l-7 14h8l-4 13 15-19h-9l4-8"
fill="rgba(255, 221, 105, .9)" stroke="rgba(255,255,255,.92)" stroke-width="1.6" stroke-linejoin="round"/>
</svg>`;
}
function renderHourly(hourly, minTemp, maxTemp) {
const times = Array.isArray(hourly?.time) ? hourly.time : [];
const temps = Array.isArray(hourly?.temperature_2m) ? hourly.temperature_2m : [];
const count = Math.min(times.length, temps.length, 24);
const pad = Math.max(1.5, (maxTemp - minTemp) * 0.16);
const lo = minTemp - pad;
const hi = maxTemp + pad;
const range = Math.max(0.0001, hi - lo);
els.hourlyGrid.innerHTML = "";
for (let i = 0; i < count; i++) {
const t = Number(temps[i]);
const norm = Math.min(100, Math.max(0, ((t - lo) / range) * 100));
const hour = fmtHour(times[i]);
const fullLabel = `${hour}:00 — ${fmtTemp(t)}`;
const cell = document.createElement("div");
cell.className = "hour-cell";
cell.title = fullLabel;
cell.innerHTML = `
<div class="hour-top">${hour}</div>
<div class="bar-track">
<div class="bar-fill" style="height:${Math.max(4, norm)}%;"></div>
</div>
<div class="hour-temp">${fmtTemp(t)}</div>
`;
els.hourlyGrid.appendChild(cell);
}
for (let i = count; i < 24; i++) {
const cell = document.createElement("div");
cell.className = "hour-cell";
cell.innerHTML = `
<div class="hour-top">--</div>
<div class="bar-track"><div class="bar-fill" style="height:4%;opacity:.25"></div></div>
<div class="hour-temp">—</div>
`;
els.hourlyGrid.appendChild(cell);
}
}
function showError(message) {
document.getElementById("loadingState").style.display = "none";
els.app.innerHTML = `
<div class="topbar">
<div class="brand">
<div class="dot" aria-hidden="true"></div>
<div class="brand-copy">
<div class="kicker">Weather card</div>
<div class="headline">Weather unavailable</div>
</div>
</div>
<div class="status">
<div class="pill subtle">UTC</div>
<div class="pill">Error</div>
</div>
</div>
<div class="error-state">
<div class="error-card">
<h2>Could not load weather data</h2>
<p>${escapeHtml(message || "The weather service returned no usable data.")}</p>
</div>
</div>
`;
}
function escapeHtml(str) {
return String(str)
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """)
.replaceAll("'", "'");
}
async function main() {
try {
const url = new URL(endpoint, location.origin);
const sp = url.searchParams;
sp.set("latitude", String(lat));
sp.set("longitude", String(lon));
sp.set("daily", "temperature_2m_max,temperature_2m_min,weather_code");
sp.set("hourly", "temperature_2m");
sp.set("timezone", "UTC");
sp.set("temperature_unit", "celsius");
sp.set("start_date", date);
sp.set("end_date", date);
els.endpointPill.textContent = endpoint.includes("archive") ? "Archive" : "Forecast";
els.sourceText.textContent = endpoint;
els.coordsText.textContent = `${lat.toFixed(3)}, ${lon.toFixed(3)}`;
els.latText.textContent = lat.toFixed(3);
els.lonText.textContent = lon.toFixed(3);
els.locationName.textContent = name;
els.humanDate.textContent = formatFullDate(date);
els.isoDate.textContent = date;
els.dateSmall.textContent = date;
els.sourcePill.textContent = "UTC";
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 12000);
const res = await fetch(url.toString(), {
signal: controller.signal,
headers: { "Accept": "application/json" }
});
clearTimeout(timeout);
if (!res.ok) throw new Error(`Weather request failed with status ${res.status}.`);
const data = await res.json();
const daily = data && data.daily;
const hourly = data && data.hourly;
const max = daily?.temperature_2m_max?.[0];
const min = daily?.temperature_2m_min?.[0];
const code = daily?.weather_code?.[0];
if (!Number.isFinite(max) || !Number.isFinite(min) || !hourly) {
throw new Error("Weather response was missing the expected temperature data.");
}
const meta = weatherMeta(code);
setTheme(meta.kind);
document.body.style.background =
`radial-gradient(1200px 700px at 15% 10%, ${hexToRgba(getComputedStyle(document.documentElement).getPropertyValue('--accent1').trim() || '#7ad7ff', 0.20)}, transparent 55%),
radial-gradient(1000px 600px at 85% 18%, ${hexToRgba(getComputedStyle(document.documentElement).getPropertyValue('--accent2').trim() || '#7f7bff', 0.16)}, transparent 52%),
radial-gradient(900px 600px at 65% 90%, rgba(64, 193, 255, 0.12), transparent 58%),
linear-gradient(145deg, var(--bg0), var(--bg1) 48%, var(--bg2))`;
els.loading.style.display = "none";
els.headline.textContent = `${name} — ${date}`;
els.iconBadge.innerHTML = meta.icon;
els.maxTemp.textContent = fmtTemp(max);
els.minTemp.textContent = `Low ${fmtTemp(min)}`;
els.conditionText.textContent = meta.label;
els.conditionSmall.textContent = meta.label;
els.endpointPill.textContent = endpoint.includes("archive") ? "Archive" : "Forecast";
const latlon = `${lat.toFixed(3)}, ${lon.toFixed(3)}`;
els.coordsText.textContent = latlon;
els.sourceText.textContent = endpoint;
els.latText.textContent = lat.toFixed(3);
els.lonText.textContent = lon.toFixed(3);
renderHourly(hourly, min, max);
} catch (err) {
showError(err && err.message ? err.message : "The weather data could not be loaded.");
}
}
main();
})();
</script>
</body>
</html>L1 —— 廉价的确定性描述量
| bytes 总计 | 34,284 | html / css / js | 3,664 / 13,281 / 17,339 |
|---|---|---|---|
| dom 节点 | 69 | dom 深度 | 11 |
| css 规则 | 72 | 含 js | 是 |
| brightness | 33.2 | contrast | 13.7 |
| colorfulness | 16.7 | 留白 | 82.8% |
该 slot 的 telemetry
| prompt tokens | 312 | completion tokens | 23,897 |
|---|---|---|---|
| total tokens | 24,209 | wall | 115.8 s |
| cost | — | request id | — |
config.json587 B
{
"N": 4,
"auth": {
"credential_ref": "WCB_OPENAI_OFFICIAL_KEY",
"method": "api-key"
},
"billing": "metered",
"config_id": "gpt-5.4-mini-eff-medium--api--official--dev",
"effort": "medium",
"family": "gpt",
"m": {
"min": 4,
"q": 4
},
"model_id": "gpt-5.4-mini",
"protocol": "api",
"served_model": "gpt-5.4-mini-2026-03-17",
"telemetry": {
"completion_tokens": 157566,
"cost_usd": null,
"prompt_tokens": 2464,
"total_tokens": 160030,
"wall_ms": 787555
},
"transport": "openai-official-api",
"vendor_sanction_ref": null
}send-log4.7 KB
{
"N": 4,
"batch_id": "2026-07-18--official-gpt",
"config_id": "gpt-5.4-mini-eff-medium--api--official--dev",
"positions": [
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-07-17T19:56:15.902123+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-17T19:55:23.564159+00:00"
}
],
"block_index": 0,
"model_reaching_attempt_index": 0,
"slot_index": 0,
"terminal_state": "valid",
"variant": "P-min"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-07-17T19:58:15.219380+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-17T19:56:19.467255+00:00"
}
],
"block_index": 0,
"model_reaching_attempt_index": 0,
"slot_index": 0,
"terminal_state": "valid",
"variant": "P-q"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-07-17T19:59:22.708375+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-17T19:58:19.604412+00:00"
}
],
"block_index": 1,
"model_reaching_attempt_index": 0,
"slot_index": 1,
"terminal_state": "valid",
"variant": "P-min"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-07-17T20:02:13.259618+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-17T19:59:26.127010+00:00"
}
],
"block_index": 1,
"model_reaching_attempt_index": 0,
"slot_index": 1,
"terminal_state": "valid",
"variant": "P-q"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-07-17T20:05:04.153718+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-17T20:02:17.042142+00:00"
}
],
"block_index": 2,
"model_reaching_attempt_index": 0,
"slot_index": 2,
"terminal_state": "valid",
"variant": "P-q"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-07-17T20:06:53.882894+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-17T20:05:07.580138+00:00"
}
],
"block_index": 2,
"model_reaching_attempt_index": 0,
"slot_index": 2,
"terminal_state": "valid",
"variant": "P-min"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-07-17T20:08:00.901075+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-17T20:06:57.743819+00:00"
}
],
"block_index": 3,
"model_reaching_attempt_index": 0,
"slot_index": 3,
"terminal_state": "valid",
"variant": "P-q"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-07-17T20:08:57.206266+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-17T20:08:04.538786+00:00"
}
],
"block_index": 3,
"model_reaching_attempt_index": 0,
"slot_index": 3,
"terminal_state": "valid",
"variant": "P-min"
}
],
"retry_policy": {
"max_unreachable_retries": 5,
"rate_limit_backoff": {
"max_attempts": 4,
"max_total_ms": 60000
}
}
}