Spaces:
Running
Running
Download index.html from junbin666/campusforge-ai: direct link, hf CLI and curl.
- Browser
- Download file 18.4 kB
-
https://huggingface.co/spaces/junbin666/campusforge-ai/resolve/main/index.html
- Command line
-
hf download hf://spaces/junbin666/campusforge-ai/index.html
-
curl -L -o index.html https://huggingface.co/spaces/junbin666/campusforge-ai/resolve/main/index.html
18.4 kB
| <html lang="zh-Hant"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <meta name="description" content="CampusForge AI — 台灣建築影像 LoRA 評估作品集"> | |
| <title>CampusForge AI</title> | |
| <style> | |
| :root { | |
| color-scheme: light; | |
| --ink: #16312e; --muted: #5d716e; --line: #d8e5e2; --paper: #fff; | |
| --wash: #f2f7f5; --teal: #0f766e; --teal-dark: #115e59; --sky: #155e75; | |
| font-family: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; | |
| } | |
| * { box-sizing: border-box; } | |
| body { margin: 0; color: var(--ink); background: var(--wash); } | |
| a { color: var(--teal-dark); font-weight: 700; } | |
| button, textarea, select { font: inherit; } | |
| .shell { width: min(1180px, calc(100% - 32px)); margin: 32px auto 64px; } | |
| .hero { min-height: 430px; position: relative; display: flex; align-items: center; padding: 42px; border-radius: 24px; color: #fff; background: linear-gradient(90deg,rgba(0,47,50,.96) 0%,rgba(0,54,58,.76) 42%,rgba(0,54,58,.12) 78%), url("assets/campusforge-cover.png") center/cover; box-shadow: 0 16px 40px rgba(21,94,117,.22); overflow: hidden; } | |
| .hero-content { position: relative; max-width: 660px; } | |
| .hero h1 { margin: 0 0 8px; font-size: clamp(2rem,5vw,3.4rem); letter-spacing: -.04em; } | |
| .hero p { max-width: 720px; margin: 0; font-size: 1.08rem; line-height: 1.7; } | |
| .badges { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; } | |
| .badge { padding: 7px 11px; border-radius: 999px; color: var(--teal-dark); background: #ccfbf1; font-size: .86rem; font-weight: 800; } | |
| .notice { margin: 18px 0; padding: 14px 18px; border: 1px solid var(--line); border-radius: 14px; background: var(--paper); color: var(--muted); } | |
| .proofs { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 12px; margin: 18px 0; } | |
| .proof { padding: 16px 18px; border: 1px solid var(--line); border-radius: 14px; background: var(--paper); } | |
| .proof strong { display: block; color: var(--teal-dark); font-size: 1.35rem; } | |
| .tabs { display: flex; gap: 8px; padding: 7px; border: 1px solid var(--line); border-radius: 16px; background: var(--paper); overflow-x: auto; } | |
| .tab { min-width: max-content; padding: 11px 17px; border: 0; border-radius: 11px; color: var(--muted); background: transparent; cursor: pointer; font-weight: 800; } | |
| .tab[aria-selected="true"] { color: #fff; background: var(--teal); } | |
| .panel { display: none; padding-top: 22px; } | |
| .panel.active { display: block; } | |
| .grid { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 18px; } | |
| .cards { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 18px; } | |
| .card { border: 1px solid var(--line); border-radius: 18px; background: var(--paper); overflow: hidden; box-shadow: 0 8px 24px rgba(22,49,46,.05); } | |
| .card-body { padding: 20px; } | |
| .card h2, .card h3 { margin: 0 0 10px; } | |
| .card p { color: var(--muted); line-height: 1.65; } | |
| .photo { width: 100%; height: 250px; object-fit: cover; display: block; background: #e5efec; } | |
| .reference { width: 100%; max-height: 520px; object-fit: contain; display: block; background: #e5efec; } | |
| label { display: block; margin: 0 0 7px; font-weight: 800; } | |
| textarea, select { width: 100%; padding: 12px 14px; border: 1px solid #b9cfca; border-radius: 11px; color: var(--ink); background: #fff; } | |
| textarea { resize: vertical; line-height: 1.55; } | |
| .field { margin-bottom: 16px; } | |
| .primary { width: 100%; padding: 13px 18px; border: 0; border-radius: 11px; color: #fff; background: var(--teal); cursor: pointer; font-weight: 850; } | |
| .primary:hover { background: var(--teal-dark); } | |
| .concept { min-height: 220px; padding: 24px; border-radius: 16px; background: linear-gradient(145deg,#d9f7f0,#e0f2fe); } | |
| .concept h2 { margin: 10px 0; } | |
| .output { margin-top: 16px; padding: 14px; border-radius: 12px; background: #edf5f3; overflow-wrap: anywhere; } | |
| .rubric { display: grid; grid-template-columns: repeat(5,minmax(0,1fr)); gap: 10px; margin-top: 18px; } | |
| .rubric span { padding: 13px; border: 1px solid var(--line); border-radius: 12px; background: #fff; text-align: center; font-weight: 750; } | |
| .slots { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 18px; margin-top: 18px; } | |
| .slot { min-height: 230px; display: grid; place-items: center; padding: 24px; border: 2px dashed #a8bdb9; border-radius: 16px; color: var(--muted); background: #f8fbfa; text-align: center; } | |
| .result-card { border: 1px solid var(--line); border-radius: 18px; background: var(--paper); overflow: hidden; box-shadow: 0 8px 24px rgba(22,49,46,.05); } | |
| .result-image { width: 100%; aspect-ratio: 1; object-fit: cover; display: block; background: #e5efec; } | |
| .result-meta { padding: 18px; } | |
| .result-meta h2 { margin: 0 0 7px; } | |
| .small { font-size: .9rem; color: var(--muted); } | |
| .flow { width: 100%; display: block; border: 1px solid var(--line); border-radius: 18px; background: #fff; } | |
| .metric { font-variant-numeric: tabular-nums; } | |
| footer { margin-top: 34px; color: var(--muted); text-align: center; } | |
| @media (max-width: 850px) { .grid,.cards,.slots,.proofs { grid-template-columns: 1fr; } .rubric { grid-template-columns: repeat(2,minmax(0,1fr)); } .hero { min-height: 500px; padding: 25px; background-position: 66% center; } } | |
| </style> | |
| </head> | |
| <body> | |
| <main class="shell"> | |
| <header class="hero"> | |
| <div class="hero-content"><h1>CampusForge AI</h1> | |
| <p>台灣建築影像 LoRA 評估作品集:從可追溯的公開資料、固定 prompts 到 Base/LoRA 比較,完整展示負責任的影像模型開發流程。</p> | |
| <div class="badges"><span class="badge">3 張 Qwen Base 輸出</span><span class="badge">Diffusers LoRA smoke test</span><span class="badge">免費 Static Space</span></div></div> | |
| </header> | |
| <div class="proofs"><div class="proof"><strong>3 / 3</strong><span class="small">固定基線已生成</span></div><div class="proof"><strong>23,040</strong><span class="small">LoRA 可訓練參數</span></div><div class="proof"><strong>PASS</strong><span class="small">訓練/匯出/重新載入</span></div></div> | |
| <p class="notice">評估參考圖僅用於公平比較原始模型與 LoRA,不會加入訓練資料;三張圖片均已人工核准授權與署名。</p> | |
| <nav class="tabs" aria-label="作品集頁籤"> | |
| <button class="tab" type="button" role="tab" aria-selected="true" data-tab="concept">場景構想</button> | |
| <button class="tab" type="button" role="tab" aria-selected="false" data-tab="evaluation">固定評估基準</button> | |
| <button class="tab" type="button" role="tab" aria-selected="false" data-tab="compare">Base/LoRA 比較</button> | |
| <button class="tab" type="button" role="tab" aria-selected="false" data-tab="process">工程流程</button> | |
| </nav> | |
| <section id="concept" class="panel active" role="tabpanel"> | |
| <div class="grid"> | |
| <article class="card"><div class="card-body"> | |
| <h2>建立場景構想卡</h2><p>先把題目轉成可重複使用的影像 prompt。免費版不呼叫外部生成模型,也不傳送輸入內容。</p> | |
| <div class="field"><label for="concept-prompt">場景描述</label><textarea id="concept-prompt" rows="5">繁體中文校名招牌、紅磚步道、學生廣場與機車停車區</textarea></div> | |
| <div class="field"><label for="concept-scene">場景類型</label><select id="concept-scene"><option>校園入口</option><option>教學大樓</option><option>校園廣場</option><option>走廊</option><option>校園道路</option></select></div> | |
| <div class="field"><label for="concept-weather">時間與天候</label><select id="concept-weather"><option>午後陰天</option><option>晴天</option><option>雨天</option><option>黃昏</option><option>夜間</option></select></div> | |
| <button id="build-concept" class="primary" type="button">建立構想卡</button> | |
| </div></article> | |
| <article class="card"><div class="card-body"><div id="concept-preview" class="concept" aria-live="polite"><span class="badge">瀏覽器內離線預覽</span><h2>尚未建立</h2><p>輸入描述後建立場景構想卡。</p></div><div id="concept-output" class="output"><strong>組合後 prompt</strong><p class="small">等待輸入。</p></div></div></article> | |
| </div> | |
| </section> | |
| <section id="process" class="panel" role="tabpanel"> | |
| <h2>從資料風險到可分享 Demo</h2><p class="small">固定評估集與訓練資料隔離;每一步保留可重現的輸入、設定與結果。</p> | |
| <img class="flow" src="assets/pipeline-flow.svg" alt="CampusForge AI 可稽核影像模型開發流程圖"> | |
| <div class="cards" style="margin-top:18px"> | |
| <article class="card"><div class="card-body"><h3>Base baseline</h3><p>Qwen/Qwen-Image,三組固定 prompt、seed、1024×1024、30 steps、guidance 4.0。</p></div></article> | |
| <article class="card"><div class="card-body"><h3>LoRA smoke test</h3><p class="metric">CPU · rank 4 · 4 steps · 23,040 trainable parameters · 96 exported tensors。</p></div></article> | |
| <article class="card"><div class="card-body"><h3>Evaluation firewall</h3><p>三張人工核准參考圖僅用於比較,smoke test 使用 4 張程式生成幾何圖,evaluation_images_used=false。</p></div></article> | |
| </div> | |
| </section> | |
| <section id="evaluation" class="panel" role="tabpanel"> | |
| <h2>3 張人工核准固定評估基準</h2><p class="small">來源、授權與署名均已逐筆查核;固定評估集與未來訓練集分離。</p> | |
| <div id="evaluation-cards" class="cards"></div> | |
| <h2>評分標準(每項 0–5)</h2><div class="rubric"><span>構圖符合度</span><span>台灣語意</span><span>繁中品質</span><span>建築完整性</span><span>視覺品質</span></div> | |
| <p class="notice">安全門檻:若生成結果出現可辨識人臉、車牌、浮水印或品牌標誌,該結果不計入模型勝負。</p> | |
| </section> | |
| <section id="compare" class="panel" role="tabpanel"> | |
| <div class="grid"> | |
| <article class="card"><img id="reference-image" class="reference" alt="固定評估參考圖"><div class="card-body"><h2 id="reference-title"></h2><p id="reference-attribution"></p><a id="reference-source" target="_blank" rel="noopener">查看官方來源</a></div></article> | |
| <article class="card"><div class="card-body"> | |
| <h2>固定條件比較工作區</h2><p>同一場景使用完全相同的 prompt、seed、尺寸與推論參數。</p> | |
| <div class="field"><label for="scene-select">評估基準</label><select id="scene-select"></select></div> | |
| <div class="field"><label for="prompt-zh">固定中文 prompt</label><textarea id="prompt-zh" rows="6" readonly></textarea></div> | |
| <div class="field"><label for="prompt-en">Fixed English prompt</label><textarea id="prompt-en" rows="7" readonly></textarea></div> | |
| <div class="output"><strong>固定生成設定</strong><p id="fixed-settings" class="small"></p></div> | |
| </div></article> | |
| </div> | |
| <div class="slots"> | |
| <article class="result-card"><img id="base-output-image" class="result-image" alt="Qwen-Image 固定 Base 輸出"><div class="result-meta"><h2>Qwen-Image Base</h2><p id="base-output-meta" class="small"></p></div></article> | |
| <div class="slot"><div><h2>LoRA output</h2><p>待正式 LoRA 微調;目前先以小模型完成流程 smoke test。</p></div></div> | |
| </div> | |
| </section> | |
| <footer>可稽核資料流程與固定模型輸出 · Static Demo 本身不執行 GPU 推論</footer> | |
| </main> | |
| <script> | |
| const scenes = { | |
| "萬善堂": { image:"data/evaluation_set/images/item-152.jpg", baseImage:"data/evaluation_set/base_outputs/base-152.png", seed:152031, promptZh:"台灣中央山脈霧林中的小型萬善堂,正面建築攝影,八階石階通往入口,左右紅色金屬欄杆,低矮矩形祭祀建築位於畫面中央,潮濕森林、苔蘚與落葉,陰天柔光,寫實、自然色彩、清楚建築結構,無人物、無車輛", promptEn:"A small Wanshan shrine in a misty forest of Taiwan's Central Mountain Range, frontal architectural photography, eight stone steps leading to the entrance, red metal handrails on both sides, a low rectangular worship building centered in frame, wet forest, moss and fallen leaves, soft overcast light, photorealistic, natural colors, clearly defined architecture, no people, no vehicles", attribution:"萬善堂/原住民族委員會原住民族文化發展中心/CC BY 3.0 TW", source:"https://tcmb.culture.tw/zh-tw/detail?indexCode=Culture_Place&id=625990" }, | |
| "崇德隧道南口": { image:"data/evaluation_set/images/item-1028.jpg", baseImage:"data/evaluation_set/base_outputs/base-1028.png", seed:1028031, promptZh:"台灣花蓮蘇花公路的山區公路隧道南口,隧道入口置中,灰色混凝土洞門嵌入陡峭茂密山林,雙線柏油道路由前景延伸進入隧道,入口上方有繁體中文隧道名稱牌,陰霧天氣,寫實公共基礎設施攝影,正確透視,自然色彩,無人物、無車輛、無車牌", promptEn:"The southern portal of a mountain road tunnel on Taiwan's Suhua Highway in Hualien, tunnel entrance centered, gray concrete portal embedded in steep dense subtropical forest, a two-lane asphalt road leading from the foreground into the tunnel, a Traditional Chinese tunnel-name sign above the entrance, misty overcast weather, photorealistic public-infrastructure photography, correct perspective, natural colors, no people, no vehicles, no license plates", attribution:"崇德隧道南口/原住民族委員會原住民族文化發展中心/CC BY 3.0 TW", source:"https://tcmb.culture.tw/zh-tw/detail?indexCode=Culture_Place&id=618704" }, | |
| "虎尾水道": { image:"data/evaluation_set/images/item-2787.jpg", baseImage:"data/evaluation_set/base_outputs/base-2787.png", seed:2787031, promptZh:"台灣雲林虎尾的日治時期歷史水塔,低角度廣角建築攝影,高聳灰色鋼筋混凝土水塔位於畫面左中,圓形水槽由外露柱梁支撐,前景紅磚矮牆,右側大樹與藍天白雲形成平衡,周邊可見台灣街區尺度建築,晴天自然光,寫實、細節清楚,無人物、無車輛、無車牌", promptEn:"A historic Japanese-era water tower in Huwei, Yunlin, Taiwan, low-angle wide architectural photography, a tall gray reinforced-concrete water tower left of center, cylindrical tank supported by exposed columns and beams, low red-brick wall in the foreground, a large tree on the right balancing a blue sky with white clouds, Taiwan-scale neighborhood buildings in the surroundings, natural sunny light, photorealistic, clearly detailed, no people, no vehicles, no license plates", attribution:"虎尾水道/雲林縣政府文化觀光處/CC BY 3.0 TW", source:"https://tcmb.culture.tw/zh-tw/detail?indexCode=Culture_Place&id=147686" } | |
| }; | |
| const escapeHtml = value => value.replace(/[&<>'"]/g, char => ({"&":"&","<":"<",">":">","'":"'",'"':"""})[char]); | |
| document.querySelectorAll(".tab").forEach(button => button.addEventListener("click", () => { | |
| document.querySelectorAll(".tab").forEach(item => item.setAttribute("aria-selected", String(item === button))); | |
| document.querySelectorAll(".panel").forEach(panel => panel.classList.toggle("active", panel.id === button.dataset.tab)); | |
| })); | |
| document.getElementById("build-concept").addEventListener("click", () => { | |
| const prompt = document.getElementById("concept-prompt").value.trim().replace(/\s+/g," "); | |
| const scene = document.getElementById("concept-scene").value; | |
| const weather = document.getElementById("concept-weather").value; | |
| const preview = document.getElementById("concept-preview"); | |
| const output = document.getElementById("concept-output"); | |
| if (!prompt) { preview.innerHTML = "<span class='badge'>需要輸入</span><h2>請先描述場景</h2>"; output.innerHTML = "<strong>組合後 prompt</strong><p class='small'>尚未建立。</p>"; return; } | |
| preview.innerHTML = `<span class="badge">瀏覽器內離線預覽</span><h2>${escapeHtml(scene)} · ${escapeHtml(weather)}</h2><p>${escapeHtml(prompt)}</p><p class="small">不呼叫生成模型,也不傳送資料。</p>`; | |
| output.innerHTML = `<strong>組合後 prompt</strong><p class="small">${escapeHtml(`TWCampus, ${scene}, ${weather}, ${prompt}, realistic architectural photography`)}</p>`; | |
| }); | |
| const cards = document.getElementById("evaluation-cards"); | |
| Object.entries(scenes).forEach(([name,scene]) => { const article=document.createElement("article"); article.className="card"; article.innerHTML=`<img class="photo" src="${scene.image}" alt="${name}"><div class="card-body"><h3>${name}</h3><p>${scene.attribution}</p><a href="${scene.source}" target="_blank" rel="noopener">查看官方來源</a></div>`; cards.appendChild(article); }); | |
| const selector = document.getElementById("scene-select"); | |
| Object.keys(scenes).forEach(name => selector.add(new Option(name,name))); | |
| const renderScene = name => { const scene=scenes[name]; document.getElementById("reference-image").src=scene.image; document.getElementById("reference-image").alt=name; document.getElementById("reference-title").textContent=name; document.getElementById("reference-attribution").textContent=scene.attribution; document.getElementById("reference-source").href=scene.source; document.getElementById("prompt-zh").value=scene.promptZh; document.getElementById("prompt-en").value=scene.promptEn; document.getElementById("fixed-settings").textContent=`seed=${scene.seed} · 1024×1024 · 30 steps · guidance=4.0`; document.getElementById("base-output-image").src=scene.baseImage; document.getElementById("base-output-image").alt=`${name} 的 Qwen-Image Base 固定輸出`; document.getElementById("base-output-meta").textContent=`Qwen/Qwen-Image · seed=${scene.seed} · 由 Hugging Face Inference Providers 路由生成`; }; | |
| selector.addEventListener("change", event => renderScene(event.target.value)); | |
| renderScene(selector.value); | |
| </script> | |
| </body> | |
| </html> | |