从零构建 Mastra RAG MVP:DeepSeek、SiliconFlow 与 PostgreSQL/pgvector 实战
最近我在尝试使用 Mastra 构建一个简单的 RAG(Retrieval-Augmented Generation,检索增强生成)应用。目标并不是一开始就做完整的知识库平台,而是先打通一条最小可用链路:把自己的 Markdown 技术文章导入向量数据库,然后用自然语言提问,让模型根据文章内容回答问题。 这次选用的技术组合是: Mastra:组织 Agent 和 Tool。 DeepSeek:负责理解问题、决定调用检索工具并生成答案。 SiliconFlow:提供 BAAI/bge-m3 Embedding 模型,将文本转换为向量。 PostgreSQL + pgvector:保存并检索文档向量。 TypeScript:实现导入脚本、检索服务和命令行问答。 这篇文章记录 MVP 的实现思路、关键代码,以及真正遇到的几次错误。代码按这次项目的实现方式整理;Mastra 和 AI SDK 的具体类型、方法签名可能随版本调整,复制时应以项目安装版本为准。 一、先理解要实现的 RAG 链路普通 LLM 并不知道我最近在 GitHub 上修改了什么,也不一定知道 Health Mas...
从密码哈希迁移到 Argon2id:一次 Go 项目中的密码安全实践
从密码哈希迁移到 Argon2id:一次 Go 项目中的密码安全实践最近在维护我的开源项目 Health Master 时,我完成了一次密码哈希机制的升级,将原有的 MD5 迁移到 Argon2id。 相关代码可以参考 PR #333:Migrate password hashing to Argon2id and improve login errors。 最初的想法其实很简单:MD5 已经不适合存储用户密码了,应该换成更加安全的算法。 但在实际修改过程中,我发现这并不只是一次简单的函数替换。 比如: 为什么 MD5 和 SHA-256 都不适合直接存储密码? Argon2id 所谓的 Memory-hard 究竟是什么意思? 为什么 Argon2id 要把 Salt、算法版本和计算参数一起保存在数据库中? 如果攻击者拿到了完整的哈希字符串,为什么不能直接解密密码? 为什么 Go 中验证 Hash 时,还要使用 subtle.ConstantTimeCompare? 已经使用 MD5 存储密码的用户,又应该如何迁移? 为了弄清楚这些问题,我阅读了 《Argon2id 密码哈...
不使用 SSR 框架,如何给 React + Vite 实现 Prerender
不使用 SSR 框架,如何给 React + Vite 实现 Prerender最近在优化一个 React + Vite 项目的 SEO。 项目本身使用 React Router Data Mode,是一个标准的 SPA。公开页面主要有: 123//subscriptions/upgrade-plan 而 /dashboard 等页面属于登录后的应用页面,并不需要搜索引擎抓取。 最开始考虑过迁移到 React Router Framework Mode,通过 SSR 或 SSG 解决这个问题。但对于一个已经存在的 Vite SPA 来说,为了三个公开页面迁移整个应用架构,成本有些过高。 最终采用了一个更轻量的方案: 保持 React + Vite SPA 架构不变,在构建阶段额外运行一次 React Static Prerender,只为指定公开页面生成静态 HTML。 最终架构可以概括为: 1234567React + Vite SPA +Build-time SSR Renderer +React prerender() ↓Selec...
Oh My Zsh 更新失败:第三方插件安装目录冲突及解决方案
Oh My Zsh 更新失败:第三方插件安装目录冲突及解决方案最近在更新 Oh My Zsh 时,遇到了一个 Git 文件冲突问题。排查后发现,我之前编写的 Zsh 自动安装脚本将第三方插件直接安装到了 Oh My Zsh 的内置插件目录。 本文记录问题现象、排查思路、解决方法,以及如何调整安装脚本,避免以后再次出现类似问题。 一、问题现象执行以下命令更新 Oh My Zsh: 1omz update 终端提示: 1234567891011121314Updating Oh My Zsherror: The following untracked working tree fileswould be overwritten by merge: plugins/zsh-autosuggestions/LICENSE plugins/zsh-autosuggestions/README.md plugins/zsh-autosuggestions/src/async.zsh plugins/zsh-syntax-highlighting/README.md ...
Debian 13 上安装最新版 Ruby:使用 rbenv 管理 Ruby 版本
Debian 13 上安装最新版 RubyRuby 是一门动态、面向对象的编程语言,以简洁、优雅的语法著称。对于需要维护 Ruby 项目或学习 Ruby on Rails 的开发者来说,配置合适的 Ruby 开发环境是第一步。 本文介绍如何在 Debian 13 上使用 rbenv + ruby-build 安装 Ruby、配置 Zsh 开发环境、管理多个 Ruby 版本,并解决安装过程中常见的问题。 一、为什么选择 rbenv?Debian 自带 Ruby 软件包,可以直接执行: 1sudo apt install ruby 但是,Debian 软件仓库提供的 Ruby 版本不一定是最新版本。如果需要同时维护多个项目,不同项目之间还可能存在 Ruby 版本不兼容的问题。 因此,更推荐使用 rbenv。 rbenv 的主要优势包括: 多版本管理:支持同时安装多个 Ruby 版本。 项目级版本切换:通过 .ruby-version 为不同项目指定 Ruby 版本。 不影响系统 Ruby:无须覆盖 Debian 自带的 Ruby。 方便升级:可以独立安装和切换新版本。 需要注意...
Mastra 入门:从零搭建旅行助手 Agent
Mastra 入门:从零搭建旅行助手 Agent本文面向熟悉 TypeScript、刚接触 Mastra 的开发者。完成后,你会有一个能追问旅行需求、生成行程,并按需调用模拟天气工具的 Agent。示例使用 Bun 和 DeepSeek Flash;天气数值固定,仅用于学习工具调用。 1. 先理解三个概念 概念 在本例中的职责 Agent 配置模型、指令和可用工具,处理用户对话 Tool 接受经过 Schema 约束的输入,执行代码,返回结构化结果 Studio 本地可视化调试界面,试聊 Agent、查看工具调用与运行过程 Agent 可以决定是否请求调用工具;工具的 execute 才负责真正执行代码。当前示例没有持久化 Memory、实时天气、车票和酒店查询,也没有保证跨新会话记住偏好。更完整的 Workflow、Memory、RAG、MCP 可以以后逐步加入。 2. 初始化项目确认 Node.js 满足当前 Mastra 文档的最低要求(教程所列为 22.13.0),并检查 Bun: 12node -vbun -v 最可控的入门方式是手动安装。这样项...
Docker Compose 部署 Nginx 反向代理与 Cloudflare 建坑避坑指南
Docker Compose 部署 Nginx 反向代理与 Cloudflare 建坑避坑指南在自建服务或部署 Docker 应用时,我们经常需要通过 Nginx 进行反向代理,将二级域名解析到具体的容器服务上。本文将以部署一个 Docker 镜像代理服务 为例,完整记录通过 Docker Compose + Nginx 实现域名解析、SSL 证书配置以及解决常见 Cloudflare 301 重定向循环 和 404 响应 的实战过程。 1. 架构与准备 域名:registry.example.com(DNS 解析至服务器 IP,通过 Cloudflare 代理) 后端服务:运行在宿主机 18234 端口的 Docker Registry 代理容器 Nginx:通过 Docker / Docker Compose 部署,监听 80 和 443 端口 2. Nginx 配置文件在宿主机的配置文件目录(例如 ./conf.d/registry.conf)中创建对应的反向代理配置: 12345678910111213141516171819202122232425262...
使用 Traefik、cert-manager 和 DNS-01 为内网 Kubernetes 服务配置 HTTPS
使用 Traefik、cert-manager 和 DNS-01 为内网 Kubernetes 服务配置 HTTPS最近我给部署在内网 K3s 集群中的 Web 应用配置了一个浏览器可信的 HTTPS 入口。最终采用的方案是: 自有域名的内部子域名 + 本地 DNS 解析 + Traefik Ingress + cert-manager + Let’s Encrypt DNS-01 这套方案最大的优点是,服务本身不需要暴露到公网。Let’s Encrypt 只通过公网 DNS 的 TXT 记录验证域名所有权,签发完成后,用户仍然通过局域网 IP 访问服务。 本文记录完整的配置过程,并使用以下示例信息: 123456公网域名:example.com内部域名:health-master-dev.internal.example.comK3s 节点:192.168.31.215应用命名空间:health-master-dev-namespaceIngress Controller:TraefikDNS 服务商:Cloudflare 一、整体原理访问服务和签发证书走的是两条不同的链...
使用 FluxCD + GitHub + SOPS + age 构建完整 GitOps 部署流程
使用 FluxCD + GitHub + SOPS + age 构建完整 GitOps 部署流程最近我将自己的 Kubernetes 部署方式从手工 Helm 部署逐步迁移到了 FluxCD 管理的 GitOps 模式。 最终希望实现的目标是: 12345678910111213GitHub │ ├── fleet-infra │ └── 管理集群以及 FluxCD 配置 │ └── hoteler-deployment └── 管理 Hoteler 的 Kubernetes manifests │ ▼ FluxCD │ ▼ K3s 其中两个 GitHub Repository 都是 Private Repository。 同时,由于 FluxCD 访问 hoteler-deployment 需要 SSH Deploy Key,因此又引出了一个新的问...
使用 FluxCD 构建 Homelab GitOps:从私有 Git 仓库到 Hoteler 自动部署
使用 FluxCD 构建 Homelab GitOps:从私有 Git 仓库到 Hoteler 自动部署最近我重新整理了自己的 Homelab 部署方式。 过去 Kubernetes 应用虽然已经使用 Kustomize管理,但本质上仍然需要人为执行部署操作。既然集群已经运行FluxCD,更合理的方式应该是: Git 描述期望状态,FluxCD 负责让 Kubernetes 的实际状态持续向 Git中的状态收敛。 这次以 Hoteler 为例,将现有 Kustomize 部署配置接入FluxCD,并将应用源码、应用部署配置和集群配置拆分。 1. 仓库职责划分整个 GitOps 体系拆成三个部分: Application Repositoryhoteler 是应用源码仓库,负责: 12345Source CodeDockerfileTestsCIContainer Image CI 最终产生类似: 1ghcr.io/damingerdai/hoteler:v0.0.5 这样的应用镜像。 应用仓库本身不直接操作 Kubernetes。 Application GitOps R...
