1.3 技术栈选择

概述

构建 AI Agent 需要选择合适的技术栈。本节将介绍本项目使用的技术及其选择理由。

核心技术栈

1. 编程语言:TypeScript

选择理由:

  • 类型安全 - 在编译时捕获错误,提高代码质量
  • 优秀的 IDE 支持 - 自动补全、重构、导航
  • 渐进式学习 - 从 JavaScript 平滑过渡
  • 生态系统 - 丰富的 NPM 包
  • 可维护性 - 大型项目更容易维护

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 类型定义让代码更清晰
interface Message {
role: 'user' | 'assistant' | 'system';
content: string;
}

interface Tool {
name: string;
description: string;
parameters: JSONSchema;
execute: (params: any) => Promise<any>;
}

// 编译时类型检查
function processMessage(message: Message): string {
// TypeScript 知道 message.role 的类型
return message.content.toUpperCase();
}

2. 运行时:Node.js

选择理由:

  • JavaScript 生态 - 丰富的 NPM 包
  • 异步 I/O - 适合处理并发请求
  • 跨平台 - Windows、Linux、macOS
  • 性能良好 - V8 引擎优化
  • 易于部署 - 容器化友好

版本要求:

1
2
3
4
5
{
"engines": {
"node": ">=20.0.0"
}
}

3. LLM SDK:OpenAI SDK

选择理由:

  • 标准化接口 - 统一的 API 调用方式
  • 类型支持 - 完整的 TypeScript 类型
  • 流式支持 - 内置流式响应处理
  • 多提供商兼容 - 支持 OpenAI、DeepSeek 等

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import OpenAI from 'openai';

const openai = new OpenAI({
baseURL: 'https://api.deepseek.com/v1',
apiKey: process.env.DEEPSEEK_API_KEY
});

// 简单的 API 调用
const response = await openai.chat.completions.create({
model: 'deepseek-chat',
messages: [{ role: 'user', content: 'Hello!' }]
});

// 流式响应
const stream = await openai.chat.completions.create({
model: 'deepseek-chat',
messages: [{ role: 'user', content: 'Tell me a story' }],
stream: true
});

for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content || '');
}

4. 通信协议:WebSocket

选择理由:

  • 双向通信 - 服务器和客户端可以随时发送消息
  • 低延迟 - 建立连接后通信开销小
  • 实时性 - 适合流式输出场景
  • 标准化 - 广泛支持的协议

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({ port: 3000 });

wss.on('connection', (ws) => {
// 接收消息
ws.on('message', (data) => {
const message = JSON.parse(data.toString());
handleMessage(message);
});

// 发送消息
ws.send(JSON.stringify({ type: 'status', data: 'connected' }));
});

5. 配置管理:dotenv + JSON

选择理由:

  • 灵活性 - 支持多种配置方式
  • 安全性 - 敏感信息通过环境变量管理
  • 可维护性 - 配置集中管理
  • 优先级 - 环境变量 > 配置文件 > 默认值

配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// .env 文件(敏感信息)
DEEPSEEK_API_KEY=sk-xxx
DATABASE_URL=postgresql://...

// config.json 文件
{
"llm": {
"model": "deepseek-chat",
"temperature": 0.7
},
"server": {
"port": 3000
}
}

// 代码中使用
import dotenv from 'dotenv';
dotenv.config();

const apiKey = process.env.DEEPSEEK_API_KEY;

开发工具

1. 构建工具

tsx - TypeScript 执行器

1
2
3
4
5
6
# 开发模式(无需编译)
npm run dev # 使用 tsx 直接运行

# 生产模式(编译后执行)
npm run build # 使用 tsc 编译
npm start # 运行编译后的代码

2. 代码质量

TypeScript Compiler

1
2
3
4
5
6
7
8
9
10
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true
}
}

3. 包管理

npm - Node Package Manager

1
2
3
4
5
6
7
8
# 安装依赖
npm install

# 添加依赖
npm install openai

# 添加开发依赖
npm install -D typescript @types/node

技术栈对比

为什么不使用其他技术?

Python vs TypeScript

特性 Python TypeScript
AI 生态 ⭐⭐⭐⭐⭐ ⭐⭐⭐
Web 开发 ⭐⭐⭐ ⭐⭐⭐⭐⭐
类型安全 ⭐⭐ ⭐⭐⭐⭐⭐
性能 ⭐⭐⭐ ⭐⭐⭐⭐
学习曲线 ⭐⭐⭐⭐⭐ ⭐⭐⭐

选择 TypeScript 的原因:

  • 本项目侧重 Web 交互和服务化
  • TypeScript 更适合全栈开发
  • 类型系统减少运行时错误

React/Vue vs 纯 JavaScript

特性 框架 纯 JS
开发效率 ⭐⭐⭐⭐⭐ ⭐⭐⭐
学习曲线 ⭐⭐⭐ ⭐⭐⭐⭐⭐
包大小 ⭐⭐ ⭐⭐⭐⭐⭐
灵活性 ⭐⭐⭐ ⭐⭐⭐⭐⭐

选择纯 JavaScript 的原因:

  • 简化项目结构
  • 减少依赖和学习成本
  • 更好的控制性能
  • 适合教学目的

WebSocket vs HTTP 轮询

特性 WebSocket HTTP 轮询
实时性 ⭐⭐⭐⭐⭐ ⭐⭐
服务器负载 ⭐⭐⭐⭐ ⭐⭐
双向通信 ⭐⭐⭐⭐⭐ ⭐⭐⭐
实现难度 ⭐⭐⭐ ⭐⭐⭐⭐⭐

选择 WebSocket 的原因:

  • 流式输出需要实时推送
  • 双向通信更适合 Agent 交互
  • 减少轮询开销

依赖管理

核心依赖

1
2
3
4
5
6
7
8
9
10
{
"dependencies": {
"openai": "^4.28.0", // LLM SDK
"ws": "^8.16.0", // WebSocket
"dotenv": "^16.4.5", // 环境变量
"uuid": "^9.0.1", // 唯一标识
"yaml": "^2.3.4", // YAML 解析
"@modelcontextprotocol/sdk": "^1.0.4" // MCP
}
}

开发依赖

1
2
3
4
5
6
7
8
9
{
"devDependencies": {
"typescript": "^5.3.0", // TS 编译器
"tsx": "^4.7.0", // TS 执行器
"@types/node": "^20.0.0", // Node 类型
"@types/ws": "^8.5.10", // WS 类型
"@types/uuid": "^10.0.0" // UUID 类型
}
}

架构层次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌─────────────────────────────────────────┐
│ 应用层 (Application) │
│ - CLI 客户端 │
│ - Web 客户端 │
└─────────────────┬───────────────────────┘

┌─────────────────▼───────────────────────┐
│ 业务逻辑层 (Business Logic) │
│ - Agent 核心逻辑 │
│ - 会话管理 │
│ - 技能系统 │
└─────────────────┬───────────────────────┘

┌─────────────────▼───────────────────────┐
│ 服务层 (Services) │
│ - LLM 服务 │
│ - 工具服务 │
│ - 存储服务 │
└─────────────────┬───────────────────────┘

┌─────────────────▼───────────────────────┐
│ 基础设施层 (Infrastructure) │
│ - HTTP/WebSocket 服务器 │
│ - 文件系统 │
│ - 进程管理 │
└─────────────────────────────────────────┘

技术债务和权衡

当前权衡

  1. 纯 JavaScript 前端

    • ✅ 优点:简单、轻量
    • ❌ 缺点:缺少现代框架特性
    • 🔄 未来:可考虑迁移到 Vue/React
  2. 文件系统存储

    • ✅ 优点:简单、透明
    • ❌ 缺点:扩展性有限
    • 🔄 未来:可添加数据库支持
  3. 单机架构

    • ✅ 优点:部署简单
    • ❌ 缺点:无法水平扩展
    • 🔄 未来:可添加分布式支持

总结

本项目的技术栈选择遵循以下原则:

  1. 简单优先 - 易于理解和学习
  2. 渐进增强 - 从简单到复杂
  3. 实用主义 - 选择最适合的工具
  4. 可扩展性 - 预留升级空间

这个技术栈既适合教学,又能构建实用的 AI Agent 系统。接下来,我们将使用这些技术逐步构建各个功能。

导航

上一篇: 1.2 AI Agent 的核心能力

下一篇: 1.4 本教程学习路径