本节目标:把跑这条流水线需要的三个组件装好、连通。
读完,你会有一个「一条命令就能验证连通」的环境。
预计耗时 15~20 分钟,大部分时间在等解析模型下载。
一、三个组件
跑通最小问答,本质上要让三个角色凑齐:
| 组件 | 是什么 | 跑在哪 |
|---|---|---|
| 🟦 主程序 | 我们写的 TS 代码,串起整条流水线 | 你的电脑,Node 运行 |
| 🟩 向量库 | 带 pgvector 扩展的 Postgres | Supabase 云端(本课主库,免装) |
| 🐍 解析服务 | MinerU 封装成的 HTTP 服务 | 本地 Python 进程 |
| ☁️ 云端模型 | 嵌入模型 + 大模型 | 经 API 调用,不在本地跑 |
三个角色,三种取舍,各有原因。
模型为什么走云端 API、不本地跑?
本地跑大模型对显卡要求高。
而嵌入 / 生成 API 又便宜又快,对独立开发者最省运维成本。
向量库为什么走 Supabase?
它就是托管版的 Postgres + pgvector——注册即用、免装免运维、跨平台,免费层做演示绰绰有余。
本课就把它定为唯一主库:后面建索引、入库、检索的每一行代码、每一条 SQL,都跑在这套 Supabase 上。
它对接的是标准 Postgres,所以真要私有化、离线部署,本地起个 Docker pgvector 也能平替、只改连接串——但那是边界场景,正文一律以 Supabase 为准,细节见文末附录。
解析服务为什么本地跑?
因为 MinerU 免费、中文表格识别最强,且我们要借它讲「Python 即服务」的架构。
二、前置清单
开工前确认:
- Node.js 20+(
node -v检查) - 一个 Supabase 账号(免费,下面讲怎么建库)
- Python 3.10+(给 MinerU 用,
python3 --version) - 两个 API Key(下面讲怎么拿)
本课主库走 Supabase,不需要装 Docker(私有化 / 离线平替见文末附录,那才需要 Docker Desktop)。
API Key:嵌入与生成分开拿
本课用了两个国内服务,各司其职:
| 用途 | 服务 | 拿 Key 的地方 |
|---|---|---|
| 嵌入(BGE-large-zh) | 硅基流动 SiliconFlow | siliconflow.cn 注册 → API 密钥 |
| 大模型(对话生成) | DeepSeek | platform.deepseek.com → API keys |
两者都是 OpenAI 兼容接口。
所以代码里用同一套 @ai-sdk/openai-compatible 就能接,换服务只改 baseURL。
🔒 安全红线(贯穿全课)
Key 一律放
.env,绝不写进代码、绝不提交到 Git。仓库里只留一份不含真实值的
.env.example作模板。
三、搭建向量库
不用装任何东西,三步拿到一个带 pgvector 的云端 Postgres。
1、建项目
登录 supabase.com → New project,选一个离你近的区域,设置数据库密码(记牢,等下要用)。
等 1~2 分钟项目初始化完成。
2、开 vector 扩展
进项目 → Database → Extensions,搜索 vector,点开启。
这一步让 Postgres 具备向量检索能力——Supabase 后台用的正是 pgvector。
3、复制连接串
Project Settings → Database → Connection string,选 URI 那一栏,复制出来,形如:
postgresql://postgres:[你的密码]@db.xxxxx.supabase.co:5432/postgres
把 [你的密码] 替换成第 1 步设的密码。
这串就是下一步要填进 .env 的 POSTGRES_CONNECTION_STRING。
建表、写入、查询的 SQL 和代码,对接的都是标准 Postgres。
所以这串连接串就是本课主库的入口;真要搬到自建服务器或本地,也只改这一串(私有化 / 离线见文末附录),其余代码完全不动。
四、环境变量
把模板复制一份成 .env,填进你自己的 Key 和连接串:
cp .env.example .env
.env 的关键字段(值是示意,填你自己的):
# 向量库:粘贴你刚从 Supabase 主库复制的连接串(把 [密码] 换成真实密码)
POSTGRES_CONNECTION_STRING=postgresql://postgres:你的密码@db.xxxxx.supabase.co:5432/postgres
# 私有化 / 离线时改用本地 Docker pgvector(见文末附录):postgresql://finrag:finrag@127.0.0.1:5433/finrag
# 嵌入:硅基流动 BGE-large-zh,1024 维
EMBED_BASE_URL=https://api.siliconflow.cn/v1
EMBED_API_KEY=sk-你的硅基流动key
EMBED_MODEL=BAAI/bge-large-zh-v1.5
EMBED_DIM=1024
# 大模型:DeepSeek
LLM_BASE_URL=https://api.deepseek.com/v1
LLM_API_KEY=sk-你的deepseek-key
LLM_MODEL=deepseek-chat
# 解析服务地址(下一步起)
PARSER_URL=http://127.0.0.1:8000
PARSER_URL 用 127.0.0.1 而不是 localhost,是有原因的。
Node 在某些系统会把 localhost 解析成 IPv6 的 ::1,而服务监听的是 IPv4。
这个坑 1.3 还会再提。
代码侧用 zod 在启动时校验这些变量(src/lib/config.ts)。
缺了或填错会直接报错退出,而不是等跑到一半才崩——这就是「系统边界先校验」。
五、启动解析服务
MinerU 是 Python 包,我们把它封装成一个 FastAPI 服务(services/parser/app.py),对外只暴露一个 POST /parse 接口:
cd services/parser
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt # 装 mineru + fastapi(首次较慢)
# 起服务(首次会下载 MinerU 模型,一次性)
export MINERU_CMD="$(pwd)/.venv/bin/mineru"
uvicorn app:app --port 8000 --host 127.0.0.1
验证它活着:
curl http://127.0.0.1:8000/health
# {"ok":true}
⚠️ 首次启动会下载模型(几百 MB,可能要几分钟)
这是一次性的,之后秒起。
如果看到
ModuleNotFoundError,十有八九是用了系统全局的 uvicorn 而不是 venv 里的——一定要确认走的是.venv/bin/uvicorn。
六、验证全链路
仓库准备了两个「冒烟测试」脚本,在写业务代码前先确认基础设施 OK:
npx tsx scripts/smoke-db.ts # 测向量库:建索引 / 写入 / 带过滤查询
npx tsx scripts/smoke-providers.ts # 测云端:嵌入返回 1024 维 + 大模型能应答
两个都绿了,实验台就算搭好了。
小结
1、三个组件凑齐
主程序 (TS) + 向量库 (Supabase / pgvector) + 解析服务 (MinerU),外加云端嵌入 / 大模型。
2、向量库定为 Supabase 主库
免装、跨平台、免费层够用,本质是托管的 Postgres + pgvector;私有化 / 离线才换本地,只改连接串。
3、Key 走 .env,启动即校验
绝不进代码 / Git;用 zod 在边界校验,缺了就快速失败。
4、先冒烟、再写业务
别在地基未夯实时就盖楼——两个冒烟脚本绿了才动手。
附录:Docker pgvector 平替(私有化 / 离线)
本课主库是 Supabase。
只有私有化、离线、不依赖云这几种边界场景,才用这个本地平替——日常学习直接走主库即可,可跳过本节。
用 Docker 起一个本地 pgvector,代码和 SQL 与 Supabase 完全一致,只换连接串。
前置:Docker Desktop 已安装并启动(docker ps 不报错)。
仓库里已写好 docker-compose.yml,一条命令起库:
docker compose up -d # 后台起 pgvector,默认映射到本机 5433 端口
docker ps # 看到 finrag-db 在 running 即可
然后把 .env 里的连接串换成本地的:
POSTGRES_CONNECTION_STRING=postgresql://finrag:finrag@127.0.0.1:5433/finrag
这里有两个本地细节坑:
坑 1:端口用 5433 而非默认 5432。 避免和你本机可能已有的 Postgres 撞端口。
坑 2:地址用 127.0.0.1 而非 localhost。 Node 在某些系统会把 localhost 解析成 IPv6 的 ::1,而容器监听的是 IPv4。
换好连接串后,后续步骤(冒烟测试、入库、问答)与主线完全相同。