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

在本地运行 Embeddings 和向量数据库

通过这个页面在你的电脑上运行提取出来的课程聊天机器人。你需要安装两个缺失的包,为 Vite 调整聊天机器人的 OpenAI 和 Supabase 设置,然后启动浏览器项目并连接到你在课程中构建的数据库。

你首先需要准备什么

安装一个受支持的 LTS 版本的 Node.js。推荐使用 Node 24,它包含 npm。你还需要一个 OpenAI API 密钥和一个包含课程数据的现有 Supabase 项目。

对于 Supabase,使用可发布密钥或传统的 anon 密钥。这些密钥被设计为出现在浏览器代码中:复制其中任何一个的人只能执行你的行级安全策略(Supabase 的按行读取规则)允许的操作。永远不要在这个浏览器项目中放入秘密密钥或 service_role 密钥。查看 Supabase API 密钥了解当前的密钥类型。

OpenAI 密钥没有对应的范围限制:任何复制它的人都可以发出会记入你账户的请求,因此在生产环境中它绝不应该出现在客户端代码中。这个学习设置还是会将它发送到浏览器;Vite 部分的警告解释了这样做的限制。这个设置的服务端对应物,Vercel AI SDK 项目,使用相同的 Supabase 项目但使用秘密密钥。秘密密钥在那里是可以接受的,因为那个项目运行在服务器上,所以它的密钥永远不会到达浏览器。

Juno你首先需要准备什么 安装 Node.js LTS,然后准备好你的 OpenAI 密钥和你在课程中构建的 Supabase 项目。对于 Supabase,使用可发布密钥或 anon 密钥,这是为浏览器设计的那种,永远不要使用服务端秘密。我曾经用错了密钥类型,花了一个晚上才搞清楚它们的区别!
Juno你首先需要准备什么 这个项目需要 Node 加上两个实时服务:OpenAI 和课程中的 Supabase 数据库。你配置的 Supabase 密钥会在客户端代码中可读,所以它必须是可发布密钥或 anon 密钥,其访问权限由行级安全限制。不要在这个项目中放入任何服务端密钥。
Juno你首先需要准备什么 泄露的 anon 密钥是受限的:它只能执行你的行级安全策略允许的操作,这正是为什么这种密钥类型被设计为浏览器代码用的。OpenAI 密钥没有对应的范围限制,任何复制它的人都会花费你的金钱直到你撤销它。正是这个差异决定了架构:客户端代码中的 Supabase 密钥是一个策略问题,生产环境客户端代码中的 OpenAI 密钥是一个错误。

打开项目文件夹

在包含 package.json 的提取出来的聊天机器人文件夹中打开终端:

bash
$ cd path-to-your-downloaded-project

为了确认你有正确的下载,打开 package.json:聊天机器人导出声明了 Vite,旁边的源代码包含接下来部分编辑的 config.jsindex.js 文件。这些说明适用于完成的聊天机器人,其代码同时导入 openai@supabase/supabase-js;仅凭文件夹名称无法将其与早期课程的导出区分开。

Juno打开项目文件夹 在保存 package.json 的提取文件夹中工作;这个页面上的每个安装和每个文件都属于那里。如果终端在其他地方,命令会在错误的文件夹中运行,之后的一切都不会工作。我在输入任何内容之前都会检查文件夹清单中是否有 package.json,这是在犯过几次那个错误之后养成的习惯。
Juno打开项目文件夹 在编辑任何内容之前确认文件夹:顶级有 package.json,其中声明了 Vite,config.jsindex.js 旁边。在这里花费三十秒钟的检查成本远低于修复不同项目文件的成本。这个页面上的每条命令都假设你在这个文件夹中。
Juno打开项目文件夹 在修复里程碑之前验证它:这些说明适用于源代码同时导入 OpenAI 和 Supabase 并运行完成的聊天机器人流程的导出。早期课程的导出看起来几乎完全相同,如果你只读文件夹名称。花费两分钟阅读导入成本远低于花费整个下午调试项目从未需要的修复。

为 Vite 准备项目

安装声明的 Vite 依赖,然后安装源代码导入但下载的 package.json 没有声明的两个包:

bash
$ npm install
$ npm install openai @supabase/supabase-js

打开 config.js 并替换每个 Scrimba 环境读取。保持现有的导入、导出和验证,但替换四个位置中的三个环境名称;OPENAI_API_KEY 出现两次:

js
process.env.OPENAI_API_KEY
import.meta.env.VITE_OPENAI_API_KEY

process.env.SUPABASE_API_KEY
import.meta.env.VITE_SUPABASE_API_KEY

process.env.SUPABASE_URL
import.meta.env.VITE_SUPABASE_URL

两个 OPENAI_API_KEY 读取分别位于验证检查和 OpenAI 客户端中,所以修改两者。

打开 index.js 并将聊天模型从 gpt-4 改为 gpt-4o-mini。在跟随课程时,保持提供的 text-embedding-ada-002 嵌入模型不变。课程数据库中的现有向量必须与查询嵌入具有相同的维度;更改该模型是单独的数据库迁移,不属于本地设置的一部分。

package.json 旁边创建 .env

dotenv
VITE_OPENAI_API_KEY=your-openai-api-key
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_API_KEY=your-publishable-or-anon-key

同时创建 .gitignore

txt
.env
node_modules/

.env 提交到 Git 仓库是密钥泄露最常见的方式;忽略文件和良好习惯全面介绍了这个习惯。

这些凭证在浏览器中是可见的

Vite 将 VITE_ 值复制到前端包中。使用受限的学习凭证,在 Supabase 中启用行级安全,永远不要发布这个版本。生产应用必须将 OpenAI 请求移到后端。

Juno为 Vite 准备项目 安装缺失的包,将每个旧环境读取替换为其 Vite 等效项,并在 .env 中使用浏览器安全的 Supabase 密钥放入你的密钥。然后将 .env 排除在 Git 之外。我曾经在第一个项目中发布了一个密钥,花了一个晚上才替换它,所以这个顺序是根据经验写的。
Juno为 Vite 准备项目 源代码导入两个下载从未声明的 SDK,并读取 Scrimba 的环境名称,所以在启动 Vite 之前安装两个包并更改所有四个环境读取。如果你留下其中一个未更改,应用会在运行时而不是构建时失败。.env.gitignore 对完成修复。
Juno为 Vite 准备项目 安装 SDK 修复导入;VITE_ 名称是将值放入包中的原因,这也会将 OpenAI 密钥传递到浏览器代码。这对课程来说是可以接受的,对生产来说是不允许的,所以在真实用户到达这个聊天机器人之前将 OpenAI 调用移到后端。我看过一个项目跳过这一步,结果被撤销了密钥并收到了意外的账单。

运行项目

bash
$ npm start

打开 Vite 打印的 Local URL 并询问聊天机器人一个课程数据涵盖的问题。有用的答案表明页面、Supabase 检索和 OpenAI 请求都在正常工作。更改 .env 后重启命令,按 Ctrl+C 停止。

Juno运行项目 运行 npm start,打开 Local URL,并询问聊天机器人课程数据覆盖的内容。如果你更改 .env,重启命令以便 Vite 读取新值,完成时按 Ctrl+C。我曾经忘记重启一次,这让我困惑了整个下午,所以希望这个提示能为你节省一个。
Juno运行项目 Vite 干净地启动证明了修复后的项目能打包;有用的答案证明了其余部分。一个好问题同时测试 OpenAI 访问、Supabase 行和策略,所以把它当作你的集成测试。任何 .env 更改后重启。
Juno运行项目 加载的页面不是通过的测试。将本地服务、Supabase 检索、嵌入查找和答案生成验证为单独的检查点,因为每一个都可能在完美呈现的页面后面静默失败。我曾经在只看到登陆页面后宣布项目完成,然后 bug 在演示中出现。

故障排除

Failed to resolve import "openai""@supabase/supabase-js" 运行这个页面前面显示的两个安装命令,并在包含 package.json 的文件夹中运行它们。

process is not definedconfig.js 中仍然存在 process.env 引用。将其替换为匹配的 import.meta.env.VITE_... 值。

Supabase 返回无行或权限错误: 确认项目 URL,使用可发布密钥或 anon 密钥,并检查课程表和行级安全策略是否存在于同一项目中。

OpenAI 拒绝模型或密钥: 在 OpenAI 账户中确认计费和密钥访问。使用可用于该项目的当前模型。

Juno故障排除 将错误作为线索阅读:缺失的导入意味着额外的包未安装,环境错误意味着 Vite 名称仍然错误,空答案通常表示 Supabase 数据或权限问题。一次一个处理。这个列表上的每个问题都是可逆的,所以你可以修复每个并继续前进。
Juno故障排除 按依赖顺序检查:包解析,然后是所有四个环境替换,然后是 Supabase URL 和 RLS 策略,然后是 OpenAI 密钥和模型。每一层都依赖于它前面的一层,所以无序的修复看起来像是全新的失败。在第一个破损层停止并在那里修复。
Juno故障排除 没有有用答案的聊天机器人在三个层之一中失败:浏览器包、Supabase 权限和行,或 OpenAI 请求,每一个都可能在页面完美呈现时失败。按那个顺序检查它们。打开的页面仅证明 Vite 正在运行。