Skip to content
This page has been auto-translated and may contain errors.View in English

在本地运行 Vercel AI SDK 课程

使用本页在你的计算机上运行提取的客户支持代理。你需要将其 Express 服务器连接到 OpenAI 和课程中创建的 Supabase 数据,然后修改一个启动脚本,让 Node 从 .env 加载这些值。嵌入和向量数据库指南对同一类型的 Supabase 向量设置运行相关项目。

你需要先做什么

安装受支持的 Node.js LTS 版本。建议使用 Node 24。你还需要:

  • 具有账单和模型访问权限的 OpenAI API 密钥;
  • 课程期间创建的 Supabase 项目和数据;
  • 具有服务器端数据库访问权限的密钥:要么是 Supabase 密钥(以 sb_secret_ 开头),要么是旧版 service_role 密钥。

Supabase 密钥和旧版 service_role 密钥都绕过行级安全性。这两种类型的密钥都只能放在服务器端的 .env 中,永远不要放在浏览器代码中。Supabase 计划到 2026 年底弃用旧版密钥;它们仍然有效,但密钥是最持久的。详见 Supabase API 密钥

Juno你需要先做什么 安装 Node.js LTS,然后收集你的 OpenAI 密钥、课程中的 Supabase 项目及其密钥。

那个 Supabase 密钥就像整个数据库的主密钥,所以只能放在服务器的 .env 文件中。

Juno你需要先做什么 服务器用具有提升权限的密钥读取 Supabase,如果没有课程期间创建的行,检索就没有用处。这两个服务和那些数据必须在首次运行之前就存在。
Juno你需要先做什么 密钥和旧版 service_role 密钥都绕过行级安全性,所以持有它们的人会拥有服务器的完整数据库权限。在浏览器代码中,打开开发者工具的每个访客都会拥有它。只在 Express 中保留它。

打开并安装项目

在包含 package.json 的已提取文件夹中打开终端,然后安装锁定的包:

bash
$ cd path-to-your-downloaded-project
$ npm ci
Juno打开并安装项目 在包含 package.json 的已提取文件夹中运行 npm ci。它安装课程使用的精确包版本,所以你这里没有选择。
Juno打开并安装项目npm ci 从包含的锁定文件安装,所以你的版本与已提取的客户支持项目完全匹配。这很重要,因为 AI SDK 和模型代码是针对这些版本编写的。
Juno打开并安装项目 在做任何其他事情之前,先从已下载的锁定文件安装。然后只修改启动脚本,这样无关的依赖更新就不会被误认为是环境文件修复。

让 Node 加载 .env

打开 package.json 并将启动脚本从:

json
"start": "node server.js"

改为:

json
"start": "node --env-file=.env server.js"

代码使用旧版变量名 SUPABASE_SERVICE_ROLE_KEY。你可以将当前 Supabase 密钥存储在该变量中而无需重命名代码中的任何内容。该值必须是密钥或旧版 service_role 密钥,而不是可发布密钥。

package.json 旁边创建 .env

dotenv
OPENAI_API_KEY=your-openai-api-key
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-server-side-secret-key
PORT=3000

创建 .gitignore

txt
.env
node_modules/

Git 手册在忽略文件和良好习惯中介绍了这个习惯。

将 Supabase 密钥保留在服务器上

永远不要用 VITE_ 前缀重命名 Supabase 密钥或将其移到 client.js 中。该密钥具有提升的数据库访问权限。不要提交 .env 或在 ZIP 中共享它。

Juno让 Node 加载 .env 在启动脚本中添加 --env-file=.env,创建包含所有四个值的 .env,并将其保留在 Git 外。

在首次提交之前创建 .gitignore,这样密钥就永远不会进入存储库。

Juno让 Node 加载 .env Node 不会自动读取 .env,所以提取的项目启动时没有配置。--env-file 标志内置于 Node 中:无需额外包,值保留在 Express 读取的服务器上。
Juno让 Node 加载 .env 该标志在 server.js 运行之前将四个现有变量名加载到 process.env 中。只有 Express 读取它们,所以 OpenAI 和 Supabase 密钥永远不会出现在发送到浏览器的代码中,也不需要 dotenv 依赖。

保持提供的模型

已下载的 constants.js 使用 gpt-4o 进行答案生成和分类,使用 text-embedding-3-small 进行嵌入。本地设置不需要更改任何模型。除非 OpenAI 拒绝某个模型用于你的项目,否则保持不变。

如果你稍后替换模型,请测试完整的代理流。替换嵌入模型需要格外小心:具有相同维度数但不同向量空间的模型会返回较差的匹配并且不报告错误,所以在更改后重新生成存储的 Supabase 向量。

Juno保持提供的模型constants.js 中的两个模型名称保持原样。如果你的 OpenAI 项目拒绝其中一个,在编辑代码之前检查当前模型列表,并在之后重新测试整个代理。
Juno保持提供的模型 答案、分类和嵌入角色有不同的兼容性需求,所以替换模型从不只是单行改动。替换必须与此 SDK 兼容,并与已存储在 Supabase 中的向量保持兼容。
Juno保持提供的模型 查询嵌入与存储的向量进行比较,所以两者都必须来自同一模型。具有相同维度数的不同嵌入模型会无声地破坏检索:答案变差且没有错误。更改它意味着重新生成存储的向量,不只是编辑 constants.js

运行代理

bash
$ npm start

打开 http://localhost:3000,或使用你在 .env 中设置的端口。用 Ctrl+C 停止服务器。

页面加载表明本地服务器正在运行。提出课程数据涵盖的问题:有用的答案表明 Supabase 检索和 OpenAI 生成也在工作。RAG 章节解释了为什么代理基于检索的课程数据来回答问题。

Juno运行代理 运行 npm start 并在浏览器中打开本地地址。页面加载证明服务器运行。

完整答案还需要 OpenAI 和课程的 Supabase 数据,所以将这些视为第二个、单独的检查。

Juno运行代理 将服务器启动和答案生成视为单独的检查:一个运行但答案失败的服务器指向 OpenAI、Supabase 或你给它们的密钥,而不是代码。用 Ctrl+C 停止,如果另一个进程已使用端口 3000,则在 .env 中设置 PORT
Juno运行代理 一个 Express 进程同时提供页面和 API,所以加载的页面只证明 HTTP 服务。答案仍然取决于 OpenAI 调用和 Supabase 检索,两者都可能在启动成功后很久才失败。

故障排除

Missing OPENAI_API_KEY 确认启动脚本包含 --env-file=.env.envpackage.json 旁边,变量名完全匹配。

Supabase 身份验证或关系错误: 确认 URL 和 Supabase 密钥属于同一项目,然后完成课程的架构和数据步骤。此服务器端操作需要密钥或旧版 service_role 密钥;设计用于浏览器代码的可发布密钥没有所需的访问权限。

端口 3000 已在使用中: 更改 .env 中的 PORT,重新启动服务器,并打开新端口。

页面加载但答案失败: 检查服务器终端中的第一个提供程序或数据库错误。页面加载不能证明 OpenAI 或 Supabase 会回答。

Juno故障排除 缺少密钥指向启动脚本或 .env,Supabase 错误指向项目或其数据,加载的页面但答案失败指向外部服务。首先匹配症状与其中之一。
Juno故障排除 读取第一个服务器终端错误,而不是最后一个;后来的失败通常是它的后果。那第一个错误会区分环境加载、数据库访问、端口绑定和 OpenAI 访问。
Juno故障排除 按顺序检查:Node 是否加载了 .env,Supabase 是否返回了课程数据,OpenAI 是否生成了答案?永远不要用可发布密钥替换来消除错误;那会隐藏丢失的表或策略而不是修复它。