Stage 1 · 环境与最小可运行
目标:搭好开发环境,用一家国内 provider 跑通第一个 hello 程序;切到第二家验证跨 provider 可用。
摘要:本文是 pi-ai 框架入门的第一课,带你从零搭好 Node + TypeScript 开发环境,用一家国内 provider(如 DeepSeek)跑通第一个 hello 程序,再通过只改
PROVIDER和MODEL_ID两个常量切到第二家模型,验证跨 provider 可用。全文覆盖环境准备、项目搭建、TS 配置、.env密钥管理、模型列表查看、对话调用与常见踩坑,并附自检清单。
1.0 准备工作清单
打开记事本,把你手头有的 key 都写下来(推荐至少要有 DeepSeek 的,或有下面的任意一个都可以):
- DeepSeek:
sk-...(platform.deepseek.com) - MiniMax CN:
ey...(platform.MiniMax.io 国内入口) - 小米 MiMo token plan 国内:
ey... - 阿里云百炼 Qwen Token Plan 国内:
sk-...(bailian.console.aliyun.com,需买 token plan 套餐) - 智谱 GLM:
...(bigmodel.cn) - Moonshot Kimi:
sk-...(platform.moonshot.cn)
1.1 Node 环境确认
node -v # 必须 >= v22.19.0
1.2 建项目
mkdir pi-chat-layer
cd pi-chat-layer
npm init -y
打开 package.json,整段覆盖:
{
"name": "pi-chat-layer",
"version": "0.1.0",
"private": true,
"type": "module",
"engines": {
"node": ">=22.19.0"
},
"scripts": {
"hello": "node --env-file=.env --import tsx src/01-hello.ts",
"list-models": "node --env-file=.env --import tsx src/01-list-models.ts"
},
"dependencies": {
"@earendil-works/pi-ai": "^0.85.1"
},
"devDependencies": {
"tsx": "^4.23.13",
"typescript": "^7.0.2",
"@types/node": "^24.1.0"
}
}
字段解释:
| 字段 | 为什么 |
|---|---|
"type": "module" | pi-ai 是 ESM only 包 |
"engines.node": ">=22.19.0" | 框架硬要求 |
"tsx" 而不是 ts-node | pi-ai 源码带 .ts 后缀 import,ts-node 对 ESM 支持差 |
--env-file=.env | Node 20.6+ 原生支持,无需 dotenv |
npm install
1.3 TypeScript 配置
新建 tsconfig.json:
{
"compilerOptions": {
"target": "ES2023",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": ["ES2023"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"allowImportingTsExtensions": true,
"noEmit": true,
"isolatedModules": true,
"verbatimModuleSyntax": true
},
"include": ["src/**/*"]
}
关键选项:
| 选项 | 为什么 |
|---|---|
"module": "NodeNext" | Node ESM 解析规则 |
"moduleResolution": "NodeNext" | 配套 |
"allowImportingTsExtensions": true | pi-ai 源码大量用 .ts 后缀 import,必须开 |
"noEmit": true | 必须配套——开了 allowImportingTsExtensions 就不能 emit |
"verbatimModuleSyntax": true | 强制 import type 分开,避免踩坑 |
1.4 .env 文件 + .gitignore
.env:
DEEPSEEK_API_KEY=***
MINIMAX_CN_API_KEY=***
QWEN_TOKEN_PLAN_CN_API_KEY=***
ZAI_CODING_CN_API_KEY=***
MOONSHOT_API_KEY=***
XIAOMI_TOKEN_PLAN_CN_API_KEY=***
有 key 的写上,没的删掉那行,别空着。没国内模型只有国外模型的也可以配,自己去查KEY的名字
.gitignore:
node_modules/
.env
.env.local
*.log
dist/
1.5 第一个程序:列出所有 provider 的模型
新建 src/01-list-models.ts:
import { builtinModels } from "@earendil-works/pi-ai/providers/all";
const models = builtinModels();
for (const provider of models.getProviders()) {
const providerModels = models.getModels(provider.id);
console.log(`\n========== ${provider.name} (${provider.id}) ==========`);
if (providerModels.length === 0) {
console.log(" (没有可用模型 — 通常是因为对应 API key 没设)");
continue;
}
for (const m of providerModels) {
console.log(` ${m.id} — ${m.name} [ctx:${m.contextWindow}]`);
}
}
跑:
npm run list-models
预期输出(DeepSeek 那段要看到模型,其他空数组是正常的)这个程序会把pi默认支持所有provider都打印出来,建议复制下来留存备查:
========== DeepSeek (deepseek) ==========
deepseek-v4-flash — DeepSeek V4 Flash [ctx:1000000]
deepseek-v4-flash-vision-exp — DeepSeek V4 Flash Vision Exp [ctx:1000000]
deepseek-v4-pro — DeepSeek V4 Pro [ctx:1000000]
========== MiniMax CN (minimax-cn) ==========
(没有可用模型 — ...)
1.6 第二个程序:Hello, DeepSeek
新建 src/01-hello.ts:
import { type Context } from "@earendil-works/pi-ai";
import { builtinModels } from "@earendil-works/pi-ai/providers/all";
async function main() {
const models = builtinModels();
// ★ 这里只改 provider id 和 model id,就能切到任何一家国内模型
const PROVIDER = "deepseek";
const MODEL_ID = "deepseek-v4-flash";
const model = models.getModel(PROVIDER, MODEL_ID);
if (!model) {
throw new Error(
`找不到 ${PROVIDER}/${MODEL_ID}。先跑 npm run list-models 看哪些模型可用。`
);
}
const context: Context = {
systemPrompt: "你是一个简洁的助手,回答控制在 30 字以内。",
messages: [
{ role: "user", content: "用一句话介绍你自己。", timestamp: Date.now() },
],
tools: [], // 工具列表,不急后面Stage 7教
};
const reply = await models.complete(model, context);
console.log("---- 模型回复 ----");
for (const block of reply.content) {
if (block.type === "text") {
console.log(block.text);
}
}
console.log("\n---- 用量 ----");
console.log("input :", reply.usage.input, "tokens");
console.log("output :", reply.usage.output, "tokens");
console.log("cost : $", reply.usage.cost.total.toFixed(6));
console.log("stop :", reply.stopReason);
}
main().catch((err) => {
console.error("出错了:", err);
process.exit(1);
});
跑:
npm run hello
预期:
---- 模型回复 ----
我是 DeepSeek V4 Flash...
---- 用量 ----
input : 28 tokens
output : 18 tokens
cost : $ 0.000023
stop : stop
1.7 切到其他国内模型(核心练习)
只改 PROVIDER 和 MODEL_ID 两个常量:
// 切到 小米 Token plan 国内
const PROVIDER = "xiaomi-token-plan-cn";
const MODEL_ID = "mimo-v2.5"; // ← 从 list-models 输出照抄
// 切到 Qwen Token plan 国内
const PROVIDER = "qwen-token-plan-cn";
const MODEL_ID = "qwen3.8-max";
1.8 Stage 1 自检清单
-
node -v≥ 22.19.0 -
package.json是"type": "module",engines.node写了>=22.19.0 -
npm install没报错 -
tsconfig.json存在,module/moduleResolution是NodeNext,allowImportingTsExtensions: true+noEmit: true -
npm run list-models跑通,至少 DeepSeek 段有模型 -
src/01-hello.ts自己手敲完成 -
npm run hello跑通,看到模型输出 + token 数字 - 至少切到第二家 provider 跑通 hello
- 你能讲清楚:模型怎么选(provider id + model id)/ key 怎么传(env)/ 对话怎么发(Context + complete)
1.9 常见踩坑
| 现象 | 真原因 | 修法 |
|---|---|---|
Cannot find module '@earendil-works/pi-ai/providers/all' | 0.78 以前版本没有这个入口 | npm i @earendil-works/pi-ai@latest |
SyntaxError: Cannot use import statement outside a module | 没 "type": "module" 或没用 tsx | 改 package.json |
npm install 报 allow-scripts 警告 | npm 11+ 安全机制 | 不影响,warning 而已,不用处理 |
| list-models 有模型但 hello 报 401 | env 在新窗口没设 | 用 .env 文件 + --env-file=.env(推荐) |
| 模型 404 | provider id 或 model id 拼错 | 跑 list-models 看真实值 |
.env 改了没生效 | process.env 是冷启动缓存 | 重跑 npm run hello |
| 国内 provider 用海外 baseUrl 卡住 | 用错了不带 -cn 的 provider id | 改用 minimax-cn / qwen-token-plan-cn / zai-coding-cn / moonshotai-cn / xiaomi-token-plan-cn |
&spm=1001.2101.3001.5002&articleId=164612378&d=1&t=3&u=a5ccf31c4fbc423da7d6db94b012b5f9)
257

被折叠的 条评论
为什么被折叠?



