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

在本地运行 Intro to AI Engineering ​

用这个页面在你的电脑上运行从 Intro to AI Engineering 提取的 Gift Genie 项目,并使用自己的 AI 提供商。这个项目有两种形式:在后端迁移之前的课程中是纯浏览器 Vite 应用,从后端迁移开始是 Express 和 Vite 应用。package.json 中的一行代码能告诉你有哪种形式;安装和 .env 文件对两种都一样,只是启动方式不同。

你首先需要的东西 ​

安装支持的 Node.js LTS 版本。推荐使用 Node 24,它已经包含 npm。

检查这两个命令都能正常运行。你的版本号可能会不同:

bash
$ node --version
v24.18.0
$ npm --version
11.18.0

你还需要在 Scrimba 课程中设置的三个值:提供商的 URL、API 密钥和模型 ID。如果你不再有这个密钥,可以在提供商那里创建一个新的。

Juno你首先需要的东西 安装包含 npm 的 Node.js LTS 版本,检查 node --version 和 npm --version 都能打印出版本号。

准备好你的提供商的 URL、API 密钥和模型 ID。几分钟后你会把这三个值粘贴到一个文件里。

Juno你首先需要的东西 这三个值作为一个整体而存在:URL 选择提供商,密钥向该提供商证明你的身份,模型 ID 指定它的某个模型。一个提供商的密钥发送到另一个提供商的 URL 会被拒绝。
Juno你首先需要的东西 项目的两种形式都使用 Vite 7.3,它需要 Node 20.19 或 22.12 及更新版本。Node 20 已经停止支持,所以实际上意味着 Node 22.12 或更新的 LTS 版本。

找出你有哪种项目 ​

在提取的文件夹中打开 package.json,找到 start 这一行。如果它只说 vite,你有的是纯浏览器项目:

json
"start": "vite"

如果它说 concurrently,下面还有 server 脚本,你有的是后端项目。它的文件夹中还有 server.js:

json
"start": "concurrently \"npm run client\" \"npm run server\" ",
"server": "node --watch server.js",
Juno找出你有哪种项目 打开 package.json 并读 start 这一行。如果它只说 vite 什么都没有,你有纯浏览器项目。如果它说 concurrently,你有后端项目。

记住是哪一种:最后两个部分各涵盖一种。

Juno找出你有哪种项目start 脚本是运行 npm start 时执行的命令。纯浏览器项目只运行 Vite;后端项目从一条命令同时运行 Vite 和 Express 服务器。
Juno找出你有哪种项目concurrently 将 npm run client 和 npm run server 作为两个子进程启动,并在输出前加上 [0] 和 [1],这样 Vite 和 Express 的输出可以共享一个终端。

安装依赖包 ​

在包含 package.json 的提取文件夹中打开终端。这个页面上的所有命令都从这里运行:

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

安装项目列出的依赖包。两种形式都是一样的:

bash
$ npm install

npm 安装完成时会报告添加了多少个包。它也可能报告漏洞,或关于 esbuild 和 fsevents 的 allow-scripts 警告。这些都不会阻止项目运行。

Juno安装依赖包 在包含 package.json 的文件夹中运行 npm install。它会在结尾说明添加了多少个包。

如果 npm 说找不到 package.json,说明你在错误的文件夹中。

Juno安装依赖包 下载中包含 package-lock.json,所以 npm 安装的是课程使用的相同包版本。漏洞计数反映的是这些版本的情况;它不是安装失败的标志。
Juno安装依赖包 较新的 npm 版本会列出那些安装脚本尚未被批准的包。Vite 仍然可以在这里启动而无需批准它们,因为 esbuild 的二进制文件作为平台包到达,而不是通过那个脚本。

将你的值添加到 .env ​

在 Scrimba 上,编辑器为你填入了三个环境变量。在你的电脑上,它们来自一个文件。在 package.json 旁边创建 .env 并用这些名称精确地将你的值放在其中:

dotenv
AI_URL=https://api.openai.com/v1
AI_KEY=your-key-here
AI_MODEL=your-model-id

这个例子使用的是 OpenAI 的 URL。如果你在课程中使用了另一个提供商,比如 Groq 或 OpenRouter,改用它的 URL。模型 ID 必须是该提供商提供的某个模型。

在 package.json 旁边创建 .gitignore 并添加:

txt
.env
node_modules/

一旦密钥到达 Git 仓库,即使删除了文件它也会留在历史记录中。Git 手册在 忽略文件和良好实践 中介绍了这个习惯。

永远不要提交你的 API 密钥

.env 包含一个有效的密钥。不要上传它、粘贴密钥到你的代码中,也不要提交这个文件。如果密钥曾被泄露,请在提供商那里删除它并创建一个新的。

Juno将你的值添加到 .env 在 package.json 旁边创建一个名为 .env 的文件,每行放一个值,然后在 .gitignore 中列出 .env 以便 Git 永远不会保存它。
Juno将你的值添加到 .env 两个项目在运行时都会监视 .env。保存它,Vite 会打印 .env changed, restarting server...;在后端项目中服务器也会打印 Restarting 'server.js'。重新加载页面,新值就会被使用。
Juno将你的值添加到 .env 两种形式在不同的地方读取同一个文件。纯浏览器项目的 vite.config.js 用 loadEnv 加载它;后端项目用启动时添加的标志将它加载到 Node 中。后端的 Vite 配置仍然读 .env,但永远不会把密钥放在页面中。

运行纯浏览器项目 ​

这个版本会把你的密钥放在浏览器中

这些课程直接从页面调用 AI 提供商,所以 Vite 会把 AI_KEY 写入发送到浏览器的代码中,任何打开这个页面的人都可以读到它。使用一个完成后会删除的密钥,把这个版本保留在自己的电脑上,永远不要部署或分享它。课程后面的后端迁移会把密钥移到服务器上。

启动项目:

bash
$ npm start

Vite 会打印打开的地址:

text
  VITE v7.3.0  ready in 176 ms

  ➜  Local:   http://localhost:5173/

打开确切的 Local 地址。如果 5173 端口被占用,Vite 会选择下一个端口并打印那个地址。

在早期的课程中,比如 Setting Up Your AI Client,页面故意是空白的:工作发生在浏览器控制台中。打开你的浏览器开发工具(F12,或在 Mac 上的 Chrome 中按 Cmd+Option+J)并查看 Console 标签页。它应该显示你的值:

text
AI provider URL: https://api.openai.com/v1
AI model: your-model-id

构建 Gift Genie 页面的课程会改为显示那个页面。用 Ctrl+C 停止项目。

Juno运行纯浏览器项目 运行 npm start 并打开 Local 地址。如果页面空白,打开 Console:那两行带你的提供商 URL 和模型的行表示 .env 被读取了。

控制台中红色的 Missing AI_URL 表示它没有被读取。

Juno运行纯浏览器项目utils.js 在页面加载时立即检查这三个值,并在第一个缺失的值处抛出错误。控制台的那些行是这个检查通过了;它们还没有说明提供商是否接受密钥。
Juno运行纯浏览器项目vite.config.js 用 define 将你代码中的每个 process.env.AI_KEY、AI_URL 和 AI_MODEL 替换为 .env 中的值,同时它提供页面。正是这个替换让密钥最终出现在加载它的每个浏览器中。

运行后端项目 ​

在 Scrimba 上,服务器自动获得了你的环境变量。在你的电脑上,Node 只在你告诉它的时候才读 .env,而下载中的服务器脚本没有这样做。所以在启动前在 package.json 中做一个改变。把 server 脚本从:

json
"server": "node --watch server.js",

改为:

json
"server": "node --env-file=.env --watch server.js",

然后启动应用的两个部分:

bash
$ npm start

[1] 开头的行来自 Express 服务器,[0] 开头的行来自 Vite:

text
[1] Server running at http://localhost:3001
[0]
[0]   VITE v7.3.1  ready in 1526 ms
[0]
[0]   ➜  Local:   http://localhost:5173/

打开 Vite 的 Local 地址,而不是 3001 端口:服务器只回答应用的 /api 请求,所以单独访问 3001 端口会显示 Cannot GET /。输入礼物是给谁的,点击 Rub the Lamp。按钮会变成 Summoning Gift Ideas...,几秒后礼物创意会出现在它下面。这表示你的密钥、URL 和模型都有效。

如果页面说 Sorry, I can't access what I need right now,原因在终端中,来自服务器的 [1] 行。下面的故障排除会匹配每条消息。

用一次 Ctrl+C 停止两个部分。当你在应用运行时保存 .env,两个部分会自动重启并使用新值。

部署项目 需要为其服务器做同样的 --env-file 改变。

Juno运行后端项目 向 server 脚本添加 --env-file=.env,运行 npm start,打开 Vite Local 地址。点击 Rub the Lamp 并等待礼物创意。

如果页面改为道歉,读终端中最新的 [1] 行。

Juno运行后端项目 页面向 Vite 地址上的 /api/gift 发送请求。Vite 将每个 /api 请求转发到 3001 端口上的 Express,Express 用从 .env 读取的密钥调用提供商。浏览器永远看不到密钥。
Juno运行后端项目vite.config.js 中的代理目标固定在 http://localhost:3001,而 server.js 监听 PORT 或 3001。把 PORT 从 .env 中留出来,两者就会一致,除非你的终端已经设置了 PORT,它会覆盖 .env。每当服务器落在另一个端口上时,代理目标必须改为匹配。

故障排除 ​

纯浏览器:空白页,控制台说 Missing AI_URL、Missing AI_MODEL 或 Missing AI_KEY: Vite 没有找到那个值。检查 .env 是否在 package.json 旁边,名称是否与上面完全相同,然后保存。Vite 会自动重启(.env changed, restarting server...);重新加载页面。

后端:终端说 Missing credentials,然后是 Failed running 'server.js': 服务器启动时没有你的 .env。检查 server 脚本是否包含 --env-file=.env,AI_KEY 在 .env 中的拼写是否完全正确,然后用 Ctrl+C 停止项目并再次运行 npm start。

后端:终端说 node: .env: not found: 标志已就位,但 package.json 旁边没有 .env。在那里创建它,或检查你的编辑器是否没有把它保存为 .env.txt。服务器已经停止,所以用 Ctrl+C 停止项目并再次运行 npm start。

后端:页面说 Sorry, I can't access what I need right now,终端显示 401 和 Incorrect API key provided: 请求到达了你的提供商,提供商没有接受密钥。重新复制密钥,检查 AI_URL 中的 URL 是否属于同一提供商。

你的提供商说模型不存在或不可用: 消息在后端项目的终端的 [1] 行或发送请求的纯浏览器课程的浏览器控制台中显示。按照提供商列出的方式精确地重新复制模型 ID,检查它是否属于 AI_URL 中的提供商。

后端:终端显示 http proxy error: /api/gift 和 ECONNREFUSED: Vite 无法在 3001 端口上到达 Express。向上滚动查看第一批 [1] 行。如果它们显示一个错误,服务器在那里停止,通常是因为上面的原因之一。如果它们说 Server running at 的端口不是 3001,你的终端已经设置了 PORT,它会覆盖 .env:将 vite.config.js 中的代理目标改为那个端口。

后端:EADDRINUSE 提到 3001 端口: 另一个程序正在使用服务器的端口。停止它,或在 .env 中设置 PORT,并将 vite.config.js 中的代理目标改为同一端口。

npm start 说 concurrently: command not found 或 vite: command not found: 依赖包没有安装在这个文件夹中。在包含 package.json 的文件夹中运行 npm install。

Juno故障排除 找到第一个错误并将其匹配到上面的粗体标题。在纯浏览器项目中,看浏览器的 Console;在后端项目中,看终端。
Juno故障排除 区分开三个问题:.env 没有被读取、一个进程没有运行,以及提供商拒绝密钥或模型。它们按这个顺序失败,前两个永远不会到达提供商。
Juno故障排除401 表示整条链直到提供商都有效:页面、代理、Express 和 --env-file。缺失凭证错误来自 OpenAI 客户端的构造器,所以服务器在监听任何端口之前就停止了。