个人网站
一个把个人基础设施当生产环境来做的双语开发者作品集 —— 自托管 Docker 栈、基于站点自身内容的 AI 助手、WCAG AAA 无障碍,以及跑着 222 个 E2E 测试和 Lighthouse 审计的 CI 流水线。
- 角色
- 独立开发 · 从设计到部署
- 年份
- 2025
- 类型
- 作品集 · Web + AI
- 状态
- 运行中

一个对待个人基础设施, 像对待生产环境一样认真的作品集。
17 个页面、17 个 API 路由,以及一个用站点自身内容回答关于我的问题的 AI 助手 —— 全部独立开发、完整双语,跑在自己的服务器上。博客、摄影画廊、隐私优先的分析和 WCAG AAA 无障碍,通过带健康检查门禁的部署流水线交付。
为什么做这个
从零搭建,最初是学习 Next.js App Router、Server Components 和 i18n 的实验场 —— 后来一路长成自带部署流水线和 AI 助手的自托管平台。同时它也是面向雇主的正式线上作品集。
检索管线可视化的 RAG 助手、自托管分析、每个页面的 E2E 测试、axe-core 无障碍审计、Lighthouse CI、带健康检查门禁的部署 —— 因为这个网站本身就是作品。
一览
全栈维度
前端
界面与动效后端
API 与契约数据库
持久化Ask
站内 RAG设计
系统与无障碍测试
质量关卡DevOps
07 · 把一切发布出去的那一层线上实况


Ask 如何工作
这个网站能基于自身内容回答关于我的问题。索引脚本把博客文章、项目/经历/教育数据和个人资料按标题切成 300–800 token 的块,用 Voyage 3.5-lite 向量化,存进与网站同一个 Postgres。提问时,所有防护先于任何付费 API 调用执行 —— 按 IP 限流、输入校验、全局每日配额 —— 然后向量化问题、按余弦相似度检索前 5 个块,再由 grounding 提示词强制模型只依据编号摘录作答并标注 [n] 引用,通过 SSE 逐 token 流式返回。
语料
博客 MDX · 作品集数据库 · 个人资料
切块
按标题切分 · 300–800 token
向量化
Voyage 3.5-lite · 1024 维
入库
pgvector —— 与网站同一个数据库
检索
余弦相似度前 5 · 0.2 下限
约束
编号摘录 · 强制 [n] 引用
生成
自托管 LiteLLM 网关 · SSE 流式
回答
过滤推理块 · 实时引用面板
功能概览
全栈作品集:博客、摄影画廊、项目展示、基于站点自身内容的 AI 助手、隐私优先的分析和生产级基础设施 —— 全部双语。
内容
- 博客
- 摄影
- 项目展示
AI 与体验
- Ask —— AI 站点问答
- 命令面板 (Cmd+K)
- 主题与键盘
基础设施
- 隐私优先分析
- 安全
- SEO
权衡
自托管,告别 Vercel + Supabase
网站最初跑在 Vercel 和 Supabase 上,后来刻意迁移到自托管:自己的 VPS 上跑 Dokploy + Traefik、Postgres 与应用在同一个 compose 里、GHCR 镜像、每晚 pg_dump 备份并保留 14 天。运维成本更高 —— 但部署流水线、备份和缓存行为本身成了作品集展示的一部分。
向量放进应用数据库,而非独立向量库
RAG 语料只有约 70 个块。独立向量数据库纯属额外开销 —— pgvector 让检索和其他数据只隔一条 SQL,这个规模下精确余弦扫描亚毫秒完成、100% 召回。语料超过约 1 万块之前不建向量索引。
网站和模型之间隔一层 LLM 网关
应用通过一个稳定的模型别名调用自托管 LiteLLM 代理,而不直连任何供应商。换上游模型只需改网关配置、无需重新部署应用;供应商密钥只存在网关里;流式过滤器会剥离思考块,推理模型可以直接换上,UI 不用改。
检索阈值靠实测调出来,不靠理论
相似度下限定在 0.2,因为设 0.35 时一个真实答案(毕业院校问题,仅 ~0.34)被丢弃,而无关噪声反而拿到 ~0.39。向量阈值只筛明显噪声 —— 真正把关相关性的是 grounding 提示词:强制 [n] 引用、允许回答"不知道"。
WCAG AAA,而非仅 AA
所有颜色 token 都达到 AAA 标准(两种主题下 13:1+ 对比度)。OkLCh 色彩空间在明暗模式间保持感知一致性。每个页面在 E2E 中运行 axe-core 检查 —— 无障碍退化会让构建失败。
_zh 后缀列而非独立翻译表
只有 2 种语言,用外键关联的翻译表是过度设计。每张表上的 _zh 后缀列保持查询简单 —— 一次查询、一次语言判断、不需要 JOIN。


