han-dong.link — 空間化作品駕駛艙、基於來源的問答與職位匹配 agent
- TypeScript
- Astro
- React
- Three.js
- Spatial UI
- Provider-agnostic LLM
- LLM Tool-Calling
- Generative UI
- Guardrails
- Progressive Enhancement
職位匹配 agent 把貼上或上傳的 JD 轉成帶來源的契合簡報,面向招聘方快速核對;同一套 han-dong.link 也把即時問答助手與 Three.js 駕駛艙串起簡介、作品、研究與履歷。
一眼看懂
角色 獨立開發者 — 互動駕駛艙 UI、Three.js 導航、問答與職位匹配 agent loop、帶來源答案卡、文件/JD 護欄、部署
問題
公開作品集要同時服務招聘方、技術同儕與研究合作者,不能讓讀者自己猜每個主張背後有什麼證據。靜態頁面可以列出作品,但很少能回答職位相關問題,也很少展示網站本身如何組織證據。
解法
我做了空間化駕駛艙,也保留正典閱讀頁,並把兩者連到同一組 Astro content collections,供問答與職位匹配共用。訪客可以打開簡介、作品、研究與履歷四個星球,也可以線性閱讀或透過帶證據的卡片提問。
成果
已在 han-dong.link 上線 · 主頁駕駛艙入口呈現即時作品集數量 · 答案卡引用來源頁 · 可見回答軌跡 · 職位匹配把 JD 文字或文件轉成強項、相鄰證據、缺口與追問
我的工作
- 空間化作品駕駛艙:圍繞助手構建的 Three.js 體驗,以簡介、作品、研究、履歷四個星球呈現,並為減少動態、手機與無 WebGL 環境保留 read-mode 頁面
- 五個 typed tools(getProjects / getPublications / getStack / getTimeline / getContact),LLM 按問題自選,並有文字兜底
- 職位匹配 agent:獨立 `/role-fit` 頁面接受貼上的 JD 文字或 PDF/PNG/JPEG/WebP 上傳,輸出包含強匹配、相鄰證據、誠實缺口與招聘方追問的倡導式簡報——不做百分比打分或錄用/不錄用建議
- Source-linked 生成式 UI:每個工具結果渲染成 React 卡片(項目卡、論文列表、工具標籤、時間線、聯絡),並連回對應來源頁
- 可見回答軌跡:助手把從站內內容檢索到答案卡生成的來源路徑顯示出來,讓訪客能看見回答為何成立
- content collections 作為單一數據源——新項目自動進 agent,無需重訓、無需 embedding
- 誠實的說服:先講優勢、用一句簡短承認短板、絕不編造事實/頭銜/數字
技術證據
- 漸進增強的 Three.js 外殼:WebGL/減少動態/手機能力檢查、啟動序列、鍵盤與滾輪導航,以及從同一組 Astro content collections 顯示即時數量的駕駛艙儀表板
- Agent loop:校驗輸入 → 從 collections 組裝 grounded system prompt → LLM 工具決策 → 工具調用去重 → 解析 typed tools → 渲染卡片 + 文字
- Observable agent traces 讓 loop 可檢查:檢索到的 collection 記錄、選中的 tool cards 與最終文字保持可見連接,不會消失在純聊天回答裡
- 護欄:輸入校驗(長度上限、prompt-injection 正則、拒答越界與套取 prompt)加 per-IP 限流
- 職位匹配護欄:JD 專用校驗、拒絕而非爬取第三方招聘連結、PDF/圖片提取、證據白名單、數字/資質主張守衛,以及完整分析延遲時基於站內證據生成簡報
- provider-agnostic LLM 整合 + 確定性 mock fallback,dev / 無 key 時完全離線可跑
- Astro + Vercel 服務端渲染;三語(EN / 繁中 / 简中);答案經 markdown 渲染
Agent loop
每個問題的流程:校驗輸入 → 從 content collections 組裝 grounded system prompt → 問 LLM 該調哪些工具 → 工具調用去重 → 解析 typed tools → 渲染卡片加文字。由 LLM 決定說什麼、調哪個工具;代碼不硬編碼問題到答案的路由。
最新 agent 更新把這條路徑變成可見 answer trace:被檢索的來源記錄、選中的卡片與最終文字保持連接,因此助手可被檢查,而不是只能被相信。
Role Fit——帶證據的 JD 匹配
Role Fit 是獨立任務流程,而不是另一個聊天 prompt。招聘方可以貼上職位描述,或上傳 PDF/截圖;網站提取 JD 文字後,對照公開 content collections,輸出按強匹配、相鄰證據、缺口與待確認問題組織的簡報。
邊界是明確的:本站不讀取第三方招聘網站 URL,不把 JD 存入聊天歷史,不編造私人細節,也不做百分比打分或錄用/不錄用建議。trace 也會標記結果何時只由站內證據組成,讓邊界保持可檢查。
Grounded,而非 RAG
content collections 是單一數據源。沒有 embedding、沒有向量庫——網站新增一個項目就自動進 agent,零重訓。system prompt 明確:只用提供的信息、絕不編造事實/頭銜/數字;若某細節不在,就直說並指向聯絡方式。
護欄與誠實的說服
輸入按長度校驗並篩查 prompt-injection 嘗試;越界、角色扮演、套取 prompt 的請求一律拒答;請求按 IP 限流。Role Fit 另加 JD 專用校驗、上傳文件提取限制、第三方 URL 拒答、證據白名單,以及數字/資質主張守衛。prompt 先講優勢並誠實標出缺口——有說服力,但絕不編造。
駕駛艙外殼——空間化作品集
駕駛艙是網站的互動前端。它以全窗口 Three.js 場景呈現四個可導航星球:簡介、作品、研究、履歷。訪客可用滾輪、鍵盤或點擊在四個星球之間移動;每個星球打開的卡片都來自與助手相同的 Astro content collections,因此 3D 場景、檔案視圖與答案卡保持一致。
儀表板呈現同一組 collections 的即時數量。減少動態、手機與無 WebGL 環境保留正典 read-mode 頁面,讓空間化互動疊加在可訪問、可回鏈的作品集之上。
界面截圖