从零打造你的第一个AI Agent!eliza框架让智能体开发变得前所未有的简单

从零打造你的第一个AI Agent!eliza框架让智能体开发变得前所未有的简单

从零打造你的第一个AI Agent!eliza框架让智能体开发变得前所未有的简单

导语: 当我第一次看到eliza的代码仓库时,我完全被它的设计理念震撼了——这是一个能让任何人快速构建智能AI Agent的框架。支持多平台接入、内置记忆系统、插件化架构,这些原本需要专业团队才能实现的功能,eliza帮你一键搞定。今天这篇文章,我将带你从零开始,彻底掌握这个令人惊叹的开源项目。


一、为什么这个项目值得关注

1.1 AI Agent领域的现状与痛点

在过去的几年里,AI领域经历了爆发式的发展。从最初的简单聊天机器人,到如今能够自主执行复杂任务的智能体,技术进步的速度令人惊叹。然而,对于普通开发者而言,想要构建一个真正可用的AI Agent仍然面临着诸多挑战:

技术门槛高: 需要掌握向量数据库、检索增强生成(RAG)、多模型协作等多项前沿技术。这些知识点分散且复杂,学习曲线陡峭。

工程量大: 即便是最基础的多轮对话系统,也需要处理上下文管理、对话状态维护、历史消息检索等一系列工程问题。每一个环节都需要精心设计和完善。

集成困难: 将AI能力与实际应用场景结合时,需要处理平台对接、消息格式转换、认证授权等繁琐的集成工作。

扩展性差: 很多早期构建的AI系统缺乏良好的架构设计,导致后期功能扩展和维护变得异常困难。

1.2 eliza如何解决这些问题

eliza项目正是为了解决上述痛点而诞生的。它采用模块化设计,将复杂的AI Agent功能拆分为独立且可组合的组件。开发者无需从零开始构建每个功能模块,而是可以直接利用eliza提供的现成组件,快速搭建符合自己需求的智能系统。

核心优势体现在以下几个方面:

开箱即用的多平台支持: eliza内置了对Discord、Telegram、Twitter等主流社交平台的支持。开发者只需进行简单的配置,就可以让AI Agent在多个平台上同时运行,无需为每个平台单独开发适配代码。

强大的记忆系统: 内置的向量数据库和检索机制让AI Agent拥有了“记忆”能力。它能够记住之前的对话内容、重要信息,并在需要时快速检索相关记忆,使得对话更加连贯和个性化。

灵活的插件架构: eliza采用插件化设计,开发者可以根据需要添加或移除功能模块。这种设计不仅降低了系统的复杂性,还使得功能扩展变得简单直观。

多模型支持: 支持Claude、GPT等主流大语言模型,开发者可以根据任务需求和成本考虑灵活切换使用不同的模型。

活跃的开源社区: 作为一个新兴的开源项目,eliza拥有活跃的社区支持。这意味着你能获得持续的更新、丰富的文档和热情的开发者帮助。

1.3 项目基本信息和社区生态

eliza项目由elizaOS团队开发和维护,采用MIT开源许可证,这意味着你可以自由地使用、修改和商业化这个项目。项目代码质量高,文档相对完善,社区氛围活跃。

根据项目的README和代码结构分析,eliza主要包含以下技术栈:

  • 运行环境: 基于Node.js/TypeScript构建,充分利用了TypeScript的类型安全和现代JavaScript的特性
  • 核心框架: 支持Express.js服务器,便于构建API服务和Webhook处理
  • 数据库: 使用SQLite作为默认数据库,便于部署和数据持久化
  • 向量存储: 集成了Faiss等向量检索库,支持高效的语义检索
  • AI模型: 通过统一的接口层支持多种大语言模型

二、环境搭建与项目初始化

2.1 前置条件检查

在开始搭建eliza开发环境之前,我们需要确保系统中已经安装了必要的依赖工具。这些工具是开发和运行任何现代JavaScript/TypeScript项目的基础。

Node.js环境配置:

eliza项目要求Node.js版本不低于18.0,这是因为项目使用了一些较新的JavaScript特性和API。如果你的系统还没有安装Node.js,或者当前版本低于要求,建议使用Node版本管理器(如nvm)来安装和切换Node.js版本。

安装完成后,打开终端执行以下命令验证安装:

// 检查Node.js版本
node --version

// 检查npm版本(Node.js自带的包管理器)
npm --version

你应该能看到类似如下的输出:

v20.10.0
10.2.3

如果版本号显示正确,说明Node.js环境已经准备就绪。

Git工具安装:

Git是现代软件开发中不可或缺的版本控制工具,几乎所有的开源项目都托管在Git平台上。确保你的系统已经安装了Git,并且可以通过命令行访问。

// 验证Git是否已安装
git --version

// 正常的输出应该类似于
git version 2.43.0

代码编辑器推荐:

虽然eliza项目可以用任何文本编辑器开发,但选择一个功能强大的IDE能够显著提升开发效率。以下是几个推荐的选项:

VS Code是最佳选择,它免费、开源、跨平台,并且拥有丰富的扩展生态系统。特别是对于TypeScript项目,VS Code提供了出色的类型提示、智能补全和代码导航功能。

2.2 克隆项目仓库

一切准备就绪后,现在可以获取eliza项目的源代码了。打开终端,进入你想要存放项目的目录,然后执行克隆命令:

// 使用HTTPS方式克隆仓库
git clone https://github.com/elizaOS/eliza.git

// 或者如果你的SSH密钥已经配置好,可以使用SSH方式
git clone git@github.com:elizaOS/eliza.git

克隆过程可能需要一些时间,取决于你的网络连接速度。克隆完成后,你会看到一个名为eliza的新目录被创建。

2.3 项目结构一览

进入项目目录,首先让我们熟悉一下整体的项目结构。这是一个复杂的多包项目(monorepo),理解其结构对于后续的开发至关重要。

// 进入项目目录
cd eliza

// 查看项目根目录结构
ls -la

通常你会看到以下关键目录和文件:

// 项目根目录结构说明

// 核心代码包目录
packages/
    ├── agent/          # Agent核心运行时
    ├── client/         # 客户端SDK
    ├── server/         # API服务器
    ├── plugin-template/ # 插件开发模板

// 配置文件目录
configs/               # 各种环境配置文件
scripts/               # 构建和部署脚本

// 文档和资源
docs/                  # 项目文档
examples/              # 使用示例

// 根目录配置文件
package.json           # 项目依赖管理
pnpm-workspace.yaml    # pnpm工作空间配置
tsconfig.json          # TypeScript配置

eliza采用pnpm作为包管理器,并使用工作空间(workspace)模式管理多个相互关联的包。这种架构使得项目既保持了模块化,又便于统一管理和协作开发。

2.4 安装项目依赖

pnpm是一个高效的JavaScript包管理器,它使用硬链接和符号链接来节省磁盘空间,并提供更快的安装速度。在开始安装依赖之前,如果你的系统还没有pnpm,需要先安装它。

// 使用npm全局安装pnpm
npm install -g pnpm

// 验证pnpm安装
pnpm --version

安装依赖的过程可能需要几分钟时间,因为eliza项目包含多个包,每个包都有自己的依赖项。

// 安装项目根目录依赖
pnpm install

// 如果遇到网络问题,可以使用国内镜像源
pnpm install --registry=https://registry.npmmirror.com

安装完成后,项目根目录下会生成node_modules文件夹,里面包含了所有必需的依赖包。

2.5 环境配置详解

每个开发环境都需要特定的配置,eliza项目使用环境变量来管理这些配置。在项目根目录下,通常有一个.env.example文件作为配置模板。

// 复制配置模板文件
cp .env.example .env

// 编辑配置文件
// 在Linux/macOS上可以使用nano或vim
nano .env

// 在Windows上可以使用notepad
notepad .env

典型的配置文件包含以下关键配置项:

// .env 文件示例配置

// Discord机器人配置(如果需要接入Discord平台)
DISCORD_BOT_TOKEN=your_discord_bot_token_here

// OpenAI API配置(用于GPT模型)
OPENAI_API_KEY=your_openai_api_key_here

// Anthropic API配置(用于Claude模型)
ANTHROPIC_API_KEY=your_anthropic_api_key_here

// Twitter/X API配置
TWITTER_USERNAME=your_twitter_username
TWITTER_PASSWORD=your_twitter_password
TWITTER_EMAIL=your_twitter_email

// Telegram Bot配置
TELEGRAM_BOT_TOKEN=your_telegram_bot_token_here

// 数据库配置(使用SQLite)
DATABASE_URL=./data/db.sqlite

// 服务器配置
PORT=3000
HOST=localhost

获取这些API密钥需要在你计划使用的平台注册开发者账号。对于测试目的,eliza也支持使用本地模型,但这需要额外的配置步骤。

2.6 项目的启动与验证

安装完所有依赖并完成配置后,让我们尝试启动项目以验证环境搭建是否成功。

// 方式一:使用pnpm脚本启动
pnpm run dev

// 方式二:直接运行TypeScript代码
pnpm run start

// 方式三:进入特定包目录运行
cd packages/agent
pnpm run dev

如果一切配置正确,你应该能在终端看到类似以下的输出:

// 成功启动的输出示例

> eliza@0.1.0 dev
> ts-node-dev --respawn --transpile-only src/index.ts

[INFO] 初始化Agent运行时...
[INFO] 加载配置文件...
[INFO] 连接数据库...
[INFO] 启动Web服务器...
[INFO] 服务器运行在 http://localhost:3000
[INFO] Agent初始化完成等待连接...

这表明项目已经成功运行。现在你已经完成了环境搭建,接下来可以深入了解eliza的核心功能了。


三、核心功能深度解析

3.1 Agent运行时架构

eliza的Agent运行时是其核心所在,它负责管理AI Agent的生命周期、处理消息流转、协调各种组件的工作。理解这个架构对于深入使用eliza至关重要。

Agent运行时的核心组件:

Agent运行时由多个相互协作的组件构成,每个组件都有其特定的职责。运行时管理器(Runtime Manager)是整个系统的协调者,它负责初始化各个组件、维护运行状态、处理异常情况。消息处理器(Message Handler)负责接收和解析来自不同平台的消息,将它们转换为统一的内部格式。响应生成器(Response Generator)则调用AI模型生成回复,并处理可能的流式输出。

消息流转机制:

当用户发送一条消息时,eliza会经过以下处理流程:首先是消息接收阶段,来自不同平台(Discord、Telegram等)的消息被各自的适配器接收;然后是消息解析阶段,原始消息被转换为统一的Message对象格式;接着是上下文构建阶段,系统检索相关记忆和历史对话,构建完整的上下文;之后是响应生成阶段,AI模型基于上下文生成回复;最后是响应发送阶段,生成的回复被转换回各平台的格式并发送出去。

// 消息流转的核心流程示意

// 消息接收 -> 格式转换 -> 上下文构建 -> AI生成 -> 响应发送

// 简化版的处理逻辑
async function processMessage(rawMessage, platform) {
    // 1. 接收原始消息
    const message = await platformAdapter.receive(rawMessage);

    // 2. 转换为统一格式
    const normalizedMessage = normalizeMessage(message);

    // 3. 构建上下文(包含记忆检索)
    const context = await buildContext(normalizedMessage);

    // 4. 调用AI生成响应
    const response = await generateResponse(context);

    // 5. 发送响应
    await platformAdapter.send(response);

    return response;
}

状态管理机制:

eliza使用状态机来管理Agent的运行状态。Agent可以处于初始化状态、就绪状态、运行状态、暂停状态或错误状态。每种状态之间的转换都有明确的规则和条件。例如,只有在成功加载所有必需的配置和模型后,Agent才能从初始化状态转换到就绪状态。

3.2 记忆系统与向量检索

记忆系统是eliza最具特色的功能之一,它让AI Agent能够“记住”之前的对话和事件,从而实现更加连贯和个性化的交互体验。

记忆的类型与结构:

eliza中的记忆主要分为三种类型:短期记忆(Short-term Memory)、长期记忆(Long-term Memory)和情景记忆(Episodic Memory)。短期记忆存储在内存中,用于当前会话的上下文;长期记忆使用向量数据库持久化存储,跨会话保留;情景记忆则记录特定事件或经历的完整信息。

// 记忆对象的基本结构

const memory = {
    id: "mem_1234567890",           // 记忆的唯一标识符
    type: "long_term",              // 记忆类型:short_term, long_term, episodic
    content: "用户喜欢在早上使用助手",  // 记忆的实际内容
    embedding: [0.123, -0.456, ...], // 语义向量表示
    metadata: {
        source: "conversation",     // 记忆来源
        timestamp: 1699000000000,    // 创建时间戳
        importance: 0.8,            // 重要性评分
        tags: ["用户偏好", "使用习惯"]
    },
    agentId: "agent_001",           // 关联的Agent ID
    userId: "user_123"              // 关联的用户ID
};

向量检索的工作原理:

向量检索是实现语义搜索的核心技术。当需要检索相关记忆时,系统会将当前的查询转换为向量,然后在向量数据库中寻找与查询向量最相似的记忆向量。这种方法比传统的关键词匹配更加智能,因为它能够理解语义上的相似性。

// 向量检索的基本流程

async function retrieveMemories(query, agentId, limit = 10) {
    // 1. 将查询文本转换为向量
    const queryEmbedding = await embeddingModel.embed(query);

    // 2. 在向量数据库中检索相似向量
    const similarMemories = await vectorStore.search({
        vector: queryEmbedding,
        topK: limit,
        filter: { agentId: agentId }  // 筛选特定Agent的记忆
    });

    // 3. 过滤和排序结果
    const filteredMemories = similarMemories
        .filter(m => m.score > 0.7)   // 只保留相关性高的记忆
        .sort((a, b) => b.score - a.score);

    // 4. 返回记忆内容
    return filteredMemories.map(m => m.memory);
}

记忆的更新与管理:

记忆不是静态存储的,系统会持续评估和更新记忆。重要的信息会被提升到更重要的存储层级,而不再相关的信息则会被降级或删除。这种动态管理确保了记忆系统的效率和有效性。

3.3 插件系统架构

eliza的插件系统是其强大扩展性的来源。通过插件,开发者可以为Agent添加新的功能、能力或集成,而无需修改核心代码。

插件的结构规范:

每个插件都是一个独立的模块,包含特定的功能实现。一个完整的插件通常包含以下几个部分:插件元数据(名称、版本、作者等)、初始化函数、处理器函数、以及可能的UI组件或API端点。

// 插件的典型结构示例

// plugin-example/index.ts

// 插件元数据
export const pluginConfig = {
    name: "example-plugin",
    version: "1.0.0",
    description: "这是一个示例插件,演示插件开发规范",
    author: "开发者名称",
    dependencies: [],  // 插件依赖的其他包
    config: {         // 插件配置项定义
        enabled: { type: "boolean", default: true },
        apiKey: { type: "string", required: true }
    }
};

// 插件初始化函数
export async function initializePlugin(context) {
    // 在Agent启动时执行初始化逻辑
    console.log("插件初始化中...");

    // 设置事件监听器
    context.on("message", handleMessage);

    // 注册自定义命令
    context.registerCommand({
        name: "hello",
        handler: handleHelloCommand
    });

    return {
        name: pluginConfig.name,
        status: "ready"
    };
}

// 消息处理器
async function handleMessage(message, context) {
    if (message.content.includes("插件测试")) {
        return {
            type: "text",
            content: "插件正常工作!"
        };
    }
    return null;  // 返回null表示不拦截消息
}

// 命令处理器
async function handleHelloCommand(args, context) {
    return `你好,${args.name || "世界"}!`;
}

插件的加载与生命周期:

插件的加载发生在Agent启动时。运行时系统会扫描配置中启用的所有插件,按照依赖关系排序后依次加载。每个插件都会获得一个执行上下文,通过这个上下文与Agent系统交互。

// 插件加载流程示意

class PluginManager {
    async loadPlugins(config) {
        // 1. 收集所有启用的插件
        const plugins = config.enabledPlugins.map(pkg => {
            return require(`./plugins/${pkg}`);
        });

        // 2. 解析依赖关系并排序
        const sortedPlugins = this.resolveDependencies(plugins);

        // 3. 依次初始化插件
        const context = this.createPluginContext();

        for (const plugin of sortedPlugins) {
            try {
                const result = await plugin.initialize(context);
                console.log(`插件 ${plugin.name} 加载成功`);
            } catch (error) {
                console.error(`插件 ${plugin.name} 加载失败:`, error);
            }
        }

        // 4. 返回加载结果
        return {
            loaded: sortedPlugins.length,
            failed: plugins.length - sortedPlugins.length
        };
    }
}

3.4 多模型支持机制

eliza的另一大特色是支持多种大语言模型。这种设计让开发者能够根据不同任务的需求选择最合适的模型,同时也提高了系统的灵活性。

模型抽象层:

eliza通过统一的抽象层来支持不同的AI模型。无论底层使用的是Claude、GPT还是其他模型,上层的使用接口都是一致的。这种设计使得切换模型变得非常简单,只需要修改配置即可。

// 模型接口的统一抽象

interface AIModelProvider {
    // 同步调用(非流式)
    complete(prompt: string, options?: CompletionOptions): Promise<string>;

    // 流式调用
    completeStream(prompt: string, options?: CompletionOptions): AsyncGenerator<string>;

    // 获取模型信息
    getModelInfo(): ModelInfo;

    // 检查API配额
    checkQuota(): Promise<QuotaStatus>;
}

// 不同模型的具体实现遵循相同接口

class ClaudeProvider implements AIModelProvider {
    async complete(prompt, options) {
        // Claude特定的实现
        const response = await this.anthropic.messages.create({
            model: options.model || "claude-3-sonnet-20240229",
            max_tokens: options.maxTokens || 4096,
            messages: [{ role: "user", content: prompt }]
        });
        return response.content[0].text;
    }
    // ...
}

class GPTProvider implements AIModelProvider {
    async complete(prompt, options) {
        // OpenAI特定的实现
        const response = await this.openai.chat.completions.create({
            model: options.model || "gpt-4-turbo",
            messages: [{ role: "user", content: prompt }],
            max_tokens: options.maxTokens || 4096
        });
        return response.choices[0].message.content;
    }
    // ...
}

模型选择策略:

在实际应用中,不同的任务可能需要不同特点的模型。复杂的推理任务可能更适合Claude,而需要快速响应的简单任务则可以使用更轻量的GPT变体。eliza允许配置自动模型选择策略,让系统根据任务特点智能选择最合适的模型。

3.5 平台适配器体系

为了让Agent能够在不同平台上运行,eliza实现了适配器模式。每个平台都有对应的适配器,负责处理平台特定的协议、认证和消息格式。

适配器的通用接口:

所有平台适配器都实现相同的基础接口,这确保了核心逻辑与平台细节的隔离。

// 平台适配器的通用接口定义

interface PlatformAdapter {
    // 平台标识
    platform: string;

    // 初始化适配器
    initialize(config: PlatformConfig): Promise<void>;

    // 连接到平台
    connect(): Promise<void>;

    // 断开连接
    disconnect(): Promise<void>;

    // 发送消息
    sendMessage(target: string, message: Message): Promise<void>;

    // 发送回复(作为对某条消息的回复)
    sendReply(target: string, originalMessage: string, reply: Message): Promise<void>;

    // 上传媒体文件
    uploadMedia(target: string, mediaPath: string, caption?: string): Promise<void>;

    // 事件监听器
    on(event: string, handler: EventHandler): void;
}

// 事件类型定义
type PlatformEvent = 
    | "message"      // 收到新消息
    | "reaction"     // 收到反应/表情
    | "mention"      // 被@提及
    | "dm"          // 收到私信
    | "error"       // 发生错误
    | "disconnect";  // 连接断开

Discord适配器示例:

Discord是目前最常用的接入平台之一,让我们看看Discord适配器如何实现上述接口。

// Discord平台适配器实现概要

class DiscordAdapter implements PlatformAdapter {
    platform = "discord";
    private client: DiscordClient;
    private handlers: Map<string, EventHandler[]> = new Map();

    async initialize(config: DiscordConfig) {
        // 创建Discord客户端实例
        this.client = new DiscordClient({
            intents: [
                Discord.Intents.FLAGS.GUILDS,
                Discord.Intents.FLAGS.GUILD_MESSAGES,
                Discord.Intents.FLAGS.DIRECT_MESSAGES
            ]
        });

        // 注册消息处理器
        this.client.on("messageCreate", this.handleMessage.bind(this));

        // 注册错误处理器
        this.client.on("error", this.handleError.bind(this));
    }

    async connect() {
        // 使用机器人令牌登录
        await this.client.login(process.env.DISCORD_BOT_TOKEN);
        console.log("Discord机器人已连接");
    }

    async sendMessage(channelId: string, message: Message) {
        const channel = await this.client.channels.fetch(channelId);
        if (channel.isText()) {
            await channel.send(this.formatMessage(message));
        }
    }

    // 将统一格式的消息转换为Discord格式
    private formatMessage(message: Message): DiscordMessage {
        return {
            content: message.content,
            embeds: message.embeds,
            files: message.attachments
        };
    }

    // 处理接收到的消息
    private async handleMessage(discordMessage: DiscordMessage) {
        // 忽略机器人自己的消息
        if (discordMessage.author.bot) return;

        // 转换为统一格式
        const normalizedMessage = {
            id: discordMessage.id,
            platform: "discord",
            channelId: discordMessage.channelId,
            guildId: discordMessage.guildId,
            author: {
                id: discordMessage.author.id,
                username: discordMessage.author.username,
                avatar: discordMessage.author.avatarURL()
            },
            content: discordMessage.content,
            timestamp: discordMessage.createdTimestamp,
            replyTo: discordMessage.reference?.messageId
        };

        // 触发事件
        this.emit("message", normalizedMessage);
    }

    private emit(event: string, data: any) {
        const handlers = this.handlers.get(event) || [];
        handlers.forEach(handler => handler(data));
    }

    on(event: string, handler: EventHandler) {
        if (!this.handlers.has(event)) {
            this.handlers.set(event, []);
        }
        this.handlers.get(event)!.push(handler);
    }
}

四、实战教程:从零构建你的第一个AI Agent

4.1 项目创建与基础配置

现在让我们开始实战环节。我将手把手带你创建一个完整的AI Agent项目,从项目初始化到功能实现,再到部署运行。

创建新的Agent项目:

虽然可以直接修改eliza源码来创建自定义Agent,但更推荐的方式是在eliza项目外部创建一个新的项目,这样便于版本管理和独立部署。

// 创建项目目录
mkdir my-first-agent
cd my-first-agent

// 初始化npm项目
npm init -y

// 安装eliza作为依赖
npm install @elizaos/core

// 安装TypeScript相关依赖
npm install -D typescript @types/node ts-node

// 初始化TypeScript配置
npx tsc --init

TypeScript配置:

编辑生成的tsconfig.json文件,配置适合开发环境的选项。

// tsconfig.json

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "lib": ["ES2022"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

项目目录结构:

创建清晰的项目目录结构,便于后续开发和维护。

// 创建目录结构
mkdir -p src/agents
mkdir -p src/adapters
mkdir -p src/plugins
mkdir -p src/config
mkdir -p src/utils
mkdir -p data
mkdir -p logs

// src目录结构
// ├── agents/      # Agent定义
// ├── adapters/   # 平台适配器
// ├── plugins/    # 自定义插件
// ├── config/     # 配置文件
// ├── utils/      # 工具函数
// └── index.ts    # 入口文件

4.2 定义你的第一个Agent

现在让我们定义一个简单但功能完整的Agent。这个Agent将具备基本的对话能力,并集成Discord平台支持。

// src/agents/my-first-agent.ts

import {
    Agent,
    AgentConfig,
    Memory,
    VectorStore,
    createVectorStore
} from "@elizaos/core";

// Agent配置类型定义
interface MyAgentConfig extends AgentConfig {
    name: string;
    description: string;
    greeting: string;
    personality: {
        traits: string[];
        speakingStyle: "formal" | "casual" | "friendly";
    };
}

// 创建Agent配置的工厂函数
function createAgentConfig(): MyAgentConfig {
    return {
        name: "小助手",
        description: "一个友善的AI助手,能够回答各种问题",
        greeting: "你好!我是你的AI助手,有什么我可以帮助你的吗?",

        // 底层Agent配置
        model: {
            provider: "openai",
            model: "gpt-4-turbo",
            temperature: 0.7,
            maxTokens: 2048
        },

        // 个性化设置
        personality: {
            traits: ["helpful", "friendly", "patient"],
            speakingStyle: "friendly"
        },

        // 系统提示词
        systemPrompt: `你是一个友善、耐心的AI助手。
你的目标是帮助用户解决问题和回答问题。
始终保持礼貌和专业,但又不失亲切感。
如果你不确定某个问题的答案,诚实地告诉用户,而不是编造信息。`,

        // 记忆配置
        memory: {
            type: "vector",
            vectorStore: "pinecone",  // 或 "faiss" 用于本地存储
            topK: 5,                   // 检索最相关的5条记忆
            similarityThreshold: 0.7  // 相似度阈值
        }
    };
}

// 创建Agent实例
async function createMyAgent() {
    const config = createAgentConfig();

    // 初始化向量存储
    const vectorStore = await createVectorStore({
        type: "faiss",  // 使用本地Faiss向量数据库
        dimension: 1536,  // OpenAI embedding维度
        persistPath: "./data/vectors"
    });

    // 创建Agent实例
    const agent = new Agent({
        ...config,
        vectorStore
    });

    return agent;
}

export { MyAgentConfig, createAgentConfig, createMyAgent };

4.3 实现Discord平台集成

接下来,让我们在Agent中添加Discord平台支持。这需要创建一个Discord适配器并正确配置机器人。

创建Discord适配器:

// src/adapters/discord-adapter.ts

import { Client, GatewayIntentBits } from "discord.js";
import {
    PlatformAdapter,
    PlatformConfig,
    Message
} from "@elizaos/core";

// Discord适配器配置
interface DiscordConfig extends PlatformConfig {
    token: string;
    guildId?: string;
    channelIds?: string[];
}

// 消息转换函数
function convertDiscordMessage(discordMsg: any): Message {
    return {
        id: discordMsg.id,
        platform: "discord",
        content: discordMsg.content,
        author: {
            id: discordMsg.author.id,
            name: discordMsg.author.username,
            avatar: discordMsg.author.displayAvatarURL()
        },
        channel: {
            id: discordMsg.channelId,
            type: discordMsg.channel?.type
        },
        guild: discordMsg.guildId ? {
            id: discordMsg.guildId,
            name: discordMsg.guild?.name
        } : null,
        timestamp: discordMsg.createdTimestamp,
        attachments: discordMsg.attachments.map((att: any) => ({
            id: att.id,
            name: att.name,
            url: att.url,
            type: att.contentType
        }))
    };
}

// Discord适配器实现
class DiscordAdapter implements PlatformAdapter {
    private client: Client;
    private config: DiscordConfig;
    private messageHandler?: (message: Message) => Promise<void>;
    private messageHandlers: Array<(message: Message) => Promise<void>> = [];

    constructor(config: DiscordConfig) {
        this.config = config;

        // 创建Discord客户端,指定需要的权限
        this.client = new Client({
            intents: [
                GatewayIntentBits.Guilds,
                GatewayIntentBits.GuildMessages,
                GatewayIntentBits.MessageContent,
                GatewayIntentBits.DirectMessages,
                GatewayIntentBits.DirectMessageTyping
            ]
        });

        this.setupEventListeners();
    }

    private setupEventListeners() {
        // 监听消息事件
        this.client.on("messageCreate", async (msg) => {
            // 忽略机器人消息
            if (msg.author.bot) return;

            // 如果配置了限制频道,只处理指定频道的消息
            if (this.config.channelIds && 
                !this.config.channelIds.includes(msg.channelId)) {
                return;
            }

            // 转换为统一格式
            const normalizedMessage = convertDiscordMessage(msg);

            // 调用所有注册的消息处理器
            for (const handler of this.messageHandlers) {
                await handler(normalizedMessage);
            }
        });

        // 监听错误事件
        this.client.on("error", (error) => {
            console.error("Discord适配器错误:", error);
        });

        // 监听断开连接
        this.client.on("disconnect", () => {
            console.log("Discord机器人已断开连接");
        });
    }

    async connect(): Promise<void> {
        await this.client.login(this.config.token);
        console.log("Discord适配器已连接");
    }

    async disconnect(): Promise<void> {
        this.client.destroy();
        console.log("Discord适配器已断开");
    }

    async sendMessage(channelId: string, content: string): Promise<void> {
        const channel = await this.client.channels.fetch(channelId);
        if (channel?.isTextBased()) {
            await channel.send(content);
        }
    }

    async sendReply(channelId: string, messageId: string, content: string): Promise<void> {
        const channel = await this.client.channels.fetch(channelId);
        if (channel?.isTextBased()) {
            await channel.send({
                content: content,
                reply: {
                    messageReference: messageId
                }
            });
        }
    }

    async sendEmbed(channelId: string, embed: any): Promise<void> {
        const channel = await this.client.channels.fetch(channelId);
        if (channel?.isTextBased()) {
            await channel.send({ embeds: [embed] });
        }
    }

    on(event: "message", handler: (message: Message) => Promise<void>): void;
    on(event: string, handler: any): void {
        if (event === "message") {
            this.messageHandlers.push(handler);
        }
    }

    // 移除事件监听器
    off(event: "message", handler: (message: Message) => Promise<void>): void {
        const index = this.messageHandlers.indexOf(handler);
        if (index > -1) {
            this.messageHandlers.splice(index, 1);
        }
    }
}

export { DiscordAdapter, DiscordConfig };

4.4 实现核心对话逻辑

现在让我们实现Agent的核心对话逻辑,将平台适配器、记忆系统和AI模型连接起来。

// src/utils/conversation-engine.ts

import { Agent, Message, Memory } from "@elizaos/core";
import { v4 as uuidv4 } from "uuid";

// 对话上下文构建器
class ContextBuilder {
    private context: {
        systemPrompt: string;
        recentMessages: Message[];
        relevantMemories: Memory[];
        userInfo: any;
    } = {
        systemPrompt: "",
        recentMessages: [],
        relevantMemories: [],
        userInfo: null
    };

    setSystemPrompt(prompt: string): this {
        this.context.systemPrompt = prompt;
        return this;
    }

    addRecentMessages(messages: Message[], limit = 10): this {
        this.context.recentMessages = messages.slice(-limit);
        return this;
    }

    addRelevantMemories(memories: Memory[]): this {
        this.context.relevantMemories = memories;
        return this;
    }

    setUserInfo(userInfo: any): this {
        this.context.userInfo = userInfo;
        return this;
    }

    build(): string {
        const parts: string[] = [];

        // 添加系统提示
        if (this.context.systemPrompt) {
            parts.push(`系统提示: ${this.context.systemPrompt}`);
        }

        // 添加相关记忆
        if (this.context.relevantMemories.length > 0) {
            const memoryText = this.context.relevantMemories
                .map(m => `[记忆] ${m.content}`)
                .join("\n");
            parts.push(`相关记忆:\n${memoryText}`);
        }

        // 添加用户信息
        if (this.context.userInfo) {
            parts.push(`用户信息: ${JSON.stringify(this.context.userInfo)}`);
        }

        // 添加对话历史
        if (this.context.recentMessages.length > 0) {
            const historyText = this.context.recentMessages
                .map(m => `${m.author.name}: ${m.content}`)
                .join("\n");
            parts.push(`对话历史:\n${historyText}`);
        }

        return parts.join("\n\n");
    }
}

// 对话引擎
class ConversationEngine {
    private agent: Agent;
    private messageHistory: Map<string, Message[]> = new Map();
    private maxHistoryLength = 50;

    constructor(agent: Agent) {
        this.agent = agent;
    }

    // 处理用户消息
    async processMessage(message: Message): Promise<string> {
        const userId = message.author.id;

        // 1. 获取或初始化用户对话历史
        if (!this.messageHistory.has(userId)) {
            this.messageHistory.set(userId, []);
        }
        const history = this.messageHistory.get(userId)!;

        // 2. 检索相关记忆
        const relevantMemories = await this.agent.retrieveMemories({
            query: message.content,
            limit: 5,
            threshold: 0.7
        });

        // 3. 构建上下文
        const context = new ContextBuilder()
            .setSystemPrompt(this.agent.config.systemPrompt)
            .addRecentMessages(history)
            .addRelevantMemories(relevantMemories)
            .setUserInfo({
                id: message.author.id,
                name: message.author.name
            })
            .build();

        // 4. 调用AI生成响应
        const response = await this.agent.generate(context, message.content);

        // 5. 更新对话历史
        history.push(message);
        if (history.length > this.maxHistoryLength) {
            history.shift();
        }

        // 6. 保存对话到记忆(异步,不阻塞响应)
        this.saveToMemory(message, response).catch(console.error);

        return response;
    }

    // 保存对话到记忆系统
    private async saveToMemory(userMessage: Message, agentResponse: string): Promise<void> {
        // 保存用户消息
        await this.agent.addMemory({
            type: "conversation",
            content: `用户 ${userMessage.author.name}: ${userMessage.content}`,
            metadata: {
                platform: userMessage.platform,
                timestamp: Date.now(),
                type: "user_message"
            }
        });

        // 保存Agent响应
        await this.agent.addMemory({
            type: "conversation",
            content: `助手: ${agentResponse}`,
            metadata: {
                platform: userMessage.platform,
                timestamp: Date.now(),
                type: "agent_response"
            }
        });
    }

    // 获取对话历史
    getHistory(userId: string): Message[] {
        return this.messageHistory.get(userId) || [];
    }

    // 清空对话历史
    clearHistory(userId: string): void {
        this.messageHistory.delete(userId);
    }
}

export { ConversationEngine, ContextBuilder };

4.5 主入口文件整合

现在让我们创建项目的主入口文件,将所有组件整合在一起。

// src/index.ts

import dotenv from "dotenv";
import { createMyAgent } from "./agents/my-first-agent";
import { DiscordAdapter } from "./adapters/discord-adapter";
import { ConversationEngine } from "./utils/conversation-engine";
import { Message } from "@elizaos/core";

// 加载环境变量
dotenv.config();

// 主程序类
class MyAgentApplication {
    private agent: any;
    private discordAdapter: DiscordAdapter | null = null;
    private conversationEngine: ConversationEngine | null = null;
    private isRunning = false;

    // 初始化应用
    async initialize() {
        console.log("=".repeat(50));
        console.log("正在初始化AI Agent应用...");
        console.log("=".repeat(50));

        try {
            // 创建Agent实例
            console.log("[1/4] 创建Agent实例...");
            this.agent = await createMyAgent();
            console.log("[✓] Agent创建成功");

            // 初始化对话引擎
            console.log("[2/4] 初始化对话引擎...");
            this.conversationEngine = new ConversationEngine(this.agent);
            console.log("[✓] 对话引擎就绪");

            // 初始化Discord适配器(如果配置了)
            if (process.env.DISCORD_BOT_TOKEN) {
                console.log("[3/4] 初始化Discord适配器...");
                this.discordAdapter = new DiscordAdapter({
                    token: process.env.DISCORD_BOT_TOKEN,
                    channelIds: process.env.DISCORD_CHANNEL_IDS?.split(",")
                });

                // 注册消息处理器
                this.discordAdapter.on("message", this.handleMessage.bind(this));

                await this.discordAdapter.connect();
                console.log("[✓] Discord适配器已连接");
            }

            console.log("[4/4] 启动服务...");
            this.isRunning = true;
            console.log("[✓] 所有服务启动完成");

            console.log("\n" + "=".repeat(50));
            console.log("🎉 AI Agent应用已成功启动!");
            console.log("=".repeat(50));

        } catch (error) {
            console.error("初始化失败:", error);
            throw error;
        }
    }

    // 处理收到的消息
    private async handleMessage(message: Message) {
        console.log(`\n[收到消息] 来自 ${message.author.name}:`);
        console.log(`  内容: ${message.content.substring(0, 100)}${message.content.length > 100 ? "..." : ""}`);

        try {
            // 忽略空消息
            if (!message.content.trim()) {
                return;
            }

            // 忽略命令前缀的消息(如果有特殊命令处理器)
            if (message.content.startsWith("!")) {
                await this.handleCommand(message);
                return;
            }

            // 处理普通对话
            if (this.conversationEngine) {
                const response = await this.conversationEngine.processMessage(message);

                // 发送响应
                if (this.discordAdapter) {
                    await this.discordAdapter.sendReply(
                        message.channel.id,
                        message.id,
                        response
                    );
                }

                console.log(`[发送响应] ${response.substring(0, 50)}...`);
            }

        } catch (error) {
            console.error("处理消息时出错:", error);

            // 发送错误消息
            if (this.discordAdapter) {
                await this.discordAdapter.sendReply(
                    message.channel.id,
                    message.id,
                    "抱歉,处理你的消息时出现了一些问题,请稍后再试。"
                );
            }
        }
    }

    // 处理特殊命令
    private async handleCommand(message: Message) {
        const parts = message.content.split(" ");
        const command = parts[0].substring(1);  // 移除!前缀
        const args = parts.slice(1);

        switch (command) {
            case "help":
                await this.discordAdapter?.sendReply(
                    message.channel.id,
                    message.id,
                    `可用命令:\n!help - 显示帮助信息\n!history - 查看对话历史\n!clear - 清空对话历史\n!ping - 测试连接`
                );
                break;

            case "ping":
                await this.discordAdapter?.sendReply(
                    message.channel.id,
                    message.id,
                    "Pong! 🏓"
                );
                break;

            case "history":
                if (this.conversationEngine) {
                    const history = this.conversationEngine.getHistory(message.author.id);
                    const count = history.length;
                    await this.discordAdapter?.sendReply(
                        message.channel.id,
                        message.id,
                        `你目前有 ${count} 条对话记录。`
                    );
                }
                break;

            case "clear":
                if (this.conversationEngine) {
                    this.conversationEngine.clearHistory(message.author.id);
                    await this.discordAdapter?.sendReply(
                        message.channel.id,
                        message.id,
                        "对话历史已清空。"
                    );
                }
                break;

            default:
                await this.discordAdapter?.sendReply(
                    message.channel.id,
                    message.id,
                    `未知命令: ${command}。输入 !help 查看可用命令。`
                );
        }
    }

    // 关闭应用
    async shutdown() {
        console.log("\n正在关闭应用...");

        this.isRunning = false;

        if (this.discordAdapter) {
            await this.discordAdapter.disconnect();
        }

        console.log("应用已关闭。再见!");
    }
}

// 启动应用
async function main() {
    const app = new MyAgentApplication();

    // 处理进程退出信号
    process.on("SIGINT", async () => {
        console.log("\n收到中断信号...");
        await app.shutdown();
        process.exit(0);
    });

    process.on("SIGTERM", async () => {
        console.log("\n收到终止信号...");
        await app.shutdown();
        process.exit(0);
    });

    // 启动应用
    try {
        await app.initialize();
    } catch (error) {
        console.error("启动失败:", error);
        process.exit(1);
    }
}

// 运行主程序
main();

4.6 运行和测试

完成了代码编写后,现在让我们运行并测试这个Agent。

启动前的检查清单:

// 确保以下配置都已正确设置

// .env 文件检查清单
/*
1. OPENAI_API_KEY - OpenAI API密钥(必需)
2. DISCORD_BOT_TOKEN - Discord机器人令牌(如果要使用Discord)
3. 其他可选配置...
*/

// 检查.env文件是否存在
const fs = require("fs");
if (!fs.existsSync(".env")) {
    console.log("警告: .env文件不存在,请创建并配置");
}

编译TypeScript代码:

// 编译TypeScript
npx tsc

// 或者使用监视模式开发
npx tsc --watch

启动应用:

// 开发模式启动(使用ts-node直接运行)
npx ts-node src/index.ts

// 或者使用ts-node-dev进行热重载开发
npx ts-node-dev --respawn src/index.ts

预期输出:

// 成功启动的输出示例

==================================================
正在初始化AI Agent应用...
==================================================
[1/4] 创建Agent实例...
[] Agent创建成功
[2/4] 初始化对话引擎...
[] 对话引擎就绪
[3/4] 初始化Discord适配器...
[] Discord适配器已连接
[4/4] 启动服务...
[] 所有服务启动完成

==================================================
🎉 AI Agent应用已成功启动
==================================================

[收到消息] 来自 用户名:
  内容: 你好

[发送响应] 你好很高兴见到你有什么我可以帮助你的吗

五、常见使用场景与进阶功能

5.1 多平台同时运行

eliza的一个强大特性是能够同时在多个平台上运行。让我们扩展项目以支持Discord和Telegram。

安装Telegram依赖:

// 安装Telegram Bot SDK
npm install node-telegram-bot-api

// 更新适配器目录
mkdir -p src/adapters/telegram

创建Telegram适配器:

// src/adapters/telegram-adapter.ts

import TelegramBot from "node-telegram-bot-api";
import { PlatformAdapter, PlatformConfig, Message } from "@elizaos/core";

// Telegram适配器配置
interface TelegramConfig extends PlatformConfig {
    token: string;
    allowedChats?: number[];  // 允许接收消息的聊天ID
}

// Telegram适配器实现
class TelegramAdapter implements PlatformAdapter {
    private bot: TelegramBot;
    private config: TelegramConfig;
    private messageHandlers: Array<(message: Message) => Promise<void>> = [];

    constructor(config: TelegramConfig) {
        this.config = config;
        this.bot = new TelegramBot(config.token, { polling: true });
        this.setupEventListeners();
    }

    private setupEventListeners() {
        // 监听消息
        this.bot.on("message", async (msg) => {
            // 忽略命令消息(以/开头)
            if (msg.text?.startsWith("/")) return;

            // 检查是否在允许的聊天中
            if (this.config.allowedChats && 
                !this.config.allowedChats.includes(msg.chat.id)) {
                return;
            }

            // 转换为统一格式
            const normalizedMessage: Message = {
                id: msg.message_id.toString(),
                platform: "telegram",
                content: msg.text || "",
                author: {
                    id: msg.from?.id.toString() || "",
                    name: msg.from?.first_name || "Unknown",
                    avatar: msg.from?.photo?.small_file_id
                },
                channel: {
                    id: msg.chat.id.toString(),
                    type: msg.chat.type
                },
                timestamp: msg.date * 1000
            };

            // 调用消息处理器
            for (const handler of this.messageHandlers) {
                await handler(normalizedMessage);
            }
        });

        // 监听错误
        this.bot.on("error", (error) => {
            console.error("Telegram适配器错误:", error);
        });
    }

    async connect(): Promise<void> {
        console.log("Telegram适配器已启动");
    }

    async disconnect(): Promise<void> {
        this.bot.stopPolling();
        console.log("Telegram适配器已停止");
    }

    async sendMessage(chatId: string, content: string): Promise<void> {
        await this.bot.sendMessage(chatId, content);
    }

    async sendReply(chatId: string, originalMessageId: string, content: string): Promise<void> {
        await this.bot.sendMessage(chatId, content, {
            reply_to_message_id: parseInt(originalMessageId)
        });
    }

    on(event: "message", handler: (message: Message) => Promise<void>): void {
        if (event === "message") {
            this.messageHandlers.push(handler);
        }
    }

    off(event: "message", handler: (message: Message) => Promise<void>): void {
        const index = this.messageHandlers.indexOf(handler);
        if (index > -1) {
            this.messageHandlers.splice(index, 1);
        }
    }
}

export { TelegramAdapter, TelegramConfig };

更新主程序支持多平台:

// src/index.ts 的更新版本

import { createMyAgent } from "./agents/my-first-agent";
import { DiscordAdapter } from "./adapters/discord-adapter";
import { TelegramAdapter } from "./adapters/telegram-adapter";
import { ConversationEngine } from "./utils/conversation-engine";
import { Message } from "@elizaos/core";

class MultiPlatformAgentApplication {
    private agent: any;
    private discordAdapter: DiscordAdapter | null = null;
    private telegramAdapter: TelegramAdapter | null = null;
    private conversationEngine: ConversationEngine | null = null;

    async initialize() {
        console.log("正在初始化多平台AI Agent...");

        // 创建Agent实例
        this.agent = await createMyAgent();
        this.conversationEngine = new ConversationEngine(this.agent);

        // 初始化Discord
        if (process.env.DISCORD_BOT_TOKEN) {
            this.discordAdapter = new DiscordAdapter({
                token: process.env.DISCORD_BOT_TOKEN
            });
            this.discordAdapter.on("message", this.handleMessage.bind(this));
            await this.discordAdapter.connect();
            console.log("[✓] Discord已连接");
        }

        // 初始化Telegram
        if (process.env.TELEGRAM_BOT_TOKEN) {
            this.telegramAdapter = new TelegramAdapter({
                token: process.env.TELEGRAM_BOT_TOKEN,
                allowedChats: process.env.TELEGRAM_ALLOWED_CHATS?.split(",").map(Number)
            });
            this.telegramAdapter.on("message", this.handleMessage.bind(this));
            await this.telegramAdapter.connect();
            console.log("[✓] Telegram已连接");
        }

        console.log("多平台Agent启动完成!");
    }

    private async handleMessage(message: Message) {
        console.log(`[${message.platform}] 来自 ${message.author.name}: ${message.content}`);

        if (this.conversationEngine) {
            const response = await this.conversationEngine.processMessage(message);

            // 根据消息来源平台发送响应
            if (message.platform === "discord" && this.discordAdapter) {
                await this.discordAdapter.sendReply(
                    message.channel.id,
                    message.id,
                    response
                );
            } else if (message.platform === "telegram" && this.telegramAdapter) {
                await this.telegramAdapter.sendReply(
                    message.channel.id,
                    message.id,
                    response
                );
            }
        }
    }

    async shutdown() {
        if (this.discordAdapter) await this.discordAdapter.disconnect();
        if (this.telegramAdapter) await this.telegramAdapter.disconnect();
        console.log("所有平台已断开");
    }
}

export { MultiPlatformAgentApplication };

5.2 自定义插件开发

插件是扩展eliza功能的最佳方式。让我们创建一个实际的插件来添加一些有用的功能。

天气查询插件示例:

// src/plugins/weather-plugin.ts

import { Plugin, PluginContext, PluginConfig } from "@elizaos/core";

// 插件配置
const weatherPluginConfig: PluginConfig = {
    name: "weather-plugin",
    version: "1.0.0",
    description: "提供天气查询功能的插件",
    author: "开发者",

    // 插件依赖
    dependencies: [],

    // 配置项定义
    configSchema: {
        apiKey: {
            type: "string",
            required: true,
            description: "天气API密钥"
        },
        defaultUnit: {
            type: "string",
            default: "celsius",
            enum: ["celsius", "fahrenheit"],
            description: "温度单位"
        },
        defaultLocation: {
            type: "string",
            default: "Beijing",
            description: "默认查询位置"
        }
    }
};

// 天气API调用函数(示例,实际使用时请替换为真实的API)
async function fetchWeather(city: string, apiKey: string, unit: string = "celsius") {
    // 这里使用OpenWeatherMap API作为示例
    const baseUrl = "https://api.openweathermap.org/data/2.5/weather";
    const unitParam = unit === "celsius" ? "metric" : "imperial";

    try {
        const response = await fetch(
            `${baseUrl}?q=${encodeURIComponent(city)}&appid=${apiKey}&units=${unitParam}`
        );

        if (!response.ok) {
            throw new Error(`天气API请求失败: ${response.status}`);
        }

        const data = await response.json();

        return {
            city: data.name,
            country: data.sys.country,
            temperature: data.main.temp,
            feelsLike: data.main.feels_like,
            humidity: data.main.humidity,
            description: data.weather[0].description,
            icon: data.weather[0].icon,
            windSpeed: data.wind.speed
        };
    } catch (error) {
        console.error("获取天气信息失败:", error);
        return null;
    }
}

// 格式化天气信息
function formatWeatherResponse(weather: any): string {
    if (!weather) {
        return "抱歉,无法获取天气信息。请检查城市名称是否正确。";
    }

    const unitSymbol = weather.temperature > 0 ? "°C" : "°C";

    return `
🌤️ **${weather.city}, ${weather.country}**

当前天气: ${weather.description}
温度: ${weather.temperature}${unitSymbol}
体感温度: ${weather.feelsLike}${unitSymbol}
湿度: ${weather.humidity}%
风速: ${weather.windSpeed} m/s

📌 ${getWeatherAdvice(weather)}
`.trim();
}

// 根据天气给出建议
function getWeatherAdvice(weather: any): string {
    const temp = weather.temperature;
    const description = weather.description.toLowerCase();

    if (description.includes("rain") || description.includes("storm")) {
        return "今天有雨,出门记得带伞!";
    }

    if (temp < 0) {
        return "天气较冷,请注意保暖!";
    }

    if (temp > 30) {
        return "天气炎热,请注意防暑!";
    }

    return "天气不错,适合外出活动!";
}

// 插件初始化函数
async function initializePlugin(context: PluginContext): Promise<void> {
    const { config, registerCommand, registerAction } = context;

    // 注册天气命令
    registerCommand({
        name: "weather",
        aliases: ["天气", "查天气"],
        description: "查询指定城市的天气",
        usage: "!weather <城市名>",
        examples: [
            "!weather 北京",
            "!weather 上海",
            "天气 东京"
        ],

        async handler(args, messageContext) {
            const city = args.trim() || config.defaultLocation;

            if (!config.apiKey) {
                return "天气插件未配置API密钥,请联系管理员。";
            }

            // 显示加载提示
            context.emit("typing", { duration: 1000 });

            const weather = await fetchWeather(city, config.apiKey, config.defaultUnit);
            return formatWeatherResponse(weather);
        }
    });

    // 注册空气质量的子命令
    registerCommand({
        name: "aqi",
        aliases: ["空气质量", "空气"],
        description: "查询指定城市的空气质量",
        usage: "!aqi <城市名>",

        async handler(args, messageContext) {
            const city = args.trim() || config.defaultLocation;
            // 空气质量API调用逻辑...
            return `空气质量功能开发中...`;
        }
    });

    console.log(`[${weatherPluginConfig.name}] 插件初始化完成`);
}

// 导出插件配置和初始化函数
export {
    weatherPluginConfig,
    initializePlugin
};

插件注册和使用:

// 在主程序中注册插件

import { weatherPluginConfig, initializePlugin as initWeatherPlugin } from "./plugins/weather-plugin";

// 在Agent配置中添加插件
const agentConfig = {
    // ...其他配置
    plugins: [
        {
            config: weatherPluginConfig,
            initialize: initWeatherPlugin,
            settings: {
                apiKey: process.env.WEATHER_API_KEY,
                defaultUnit: "celsius",
                defaultLocation: "Beijing"
            }
        }
    ]
};

5.3 高级对话管理

在实际应用中,对话管理是一个复杂但重要的课题。让我们实现一些高级的对话管理功能。

对话状态机:

// src/utils/dialogue-state-machine.ts

import { Message } from "@elizaos/core";

// 对话状态枚举
enum DialogueState {
    IDLE = "idle",                    // 空闲状态
    GREETING = "greeting",            // 问候状态
    COLLECTING_INFO = "collecting",  // 收集信息状态
    PROCESSING = "processing",       // 处理中状态
    WAITING_CONFIRMATION = "waiting", // 等待确认状态
    COMPLETED = "completed",         // 完成状态
    ERROR = "error"                  // 错误状态
}

// 状态转换规则
interface StateTransition {
    from: DialogueState;
    to: DialogueState;
    condition: (context: DialogueContext) => boolean;
    action?: (context: DialogueContext) => void;
}

// 对话上下文
interface DialogueContext {
    userId: string;
    state: DialogueState;
    data: Record<string, any>;
    history: DialogueState[];
    startTime: number;
    lastInteraction: number;
}

// 对话状态机
class DialogueStateMachine {
    private states = new Map<string, DialogueContext>();
    private transitions: StateTransition[] = [];
    private handlers: Map<DialogueState, (ctx: DialogueContext) => Promise<string>>;

    constructor() {
        this.handlers = new Map();
        this.initializeTransitions();
    }

    // 初始化状态转换规则
    private initializeTransitions() {
        this.transitions = [
            {
                from: DialogueState.IDLE,
                to: DialogueState.GREETING,
                condition: (ctx) => ctx.data.isFirstMessage
            },
            {
                from: DialogueState.IDLE,
                to: DialogueState.COLLECTING_INFO,
                condition: (ctx) => ctx.data.hasIntent && ctx.data.intentRequiresInfo
            },
            {
                from: DialogueState.COLLECTING_INFO,
                to: DialogueState.COLLECTING_INFO,
                condition: (ctx) => !ctx.data.infoComplete,
                action: (ctx) => {
                    // 验证收集到的信息
                    this.validateCollectedInfo(ctx);
                }
            },
            {
                from: DialogueState.COLLECTING_INFO,
                to: DialogueState.PROCESSING,
                condition: (ctx) => ctx.data.infoComplete,
                action: (ctx) => {
                    ctx.data.processingStart = Date.now();
                }
            },
            {
                from: DialogueState.PROCESSING,
                to: DialogueState.WAITING_CONFIRMATION,
                condition: (ctx) => ctx.data.processingComplete
            },
            {
                from: DialogueState.WAITING_CONFIRMATION,
                to: DialogueState.COMPLETED,
                condition: (ctx) => ctx.data.confirmed === true
            },
            {
                from: DialogueState.WAITING_CONFIRMATION,
                to: DialogueState.PROCESSING,
                condition: (ctx) => ctx.data.confirmed === false
            },
            {
                from: DialogueState.WAITING_CONFIRMATION,
                to: DialogueState.IDLE,
                condition: (ctx) => ctx.data.cancelled
            }
        ];
    }

    // 获取或创建对话上下文
    getContext(userId: string): DialogueContext {
        if (!this.states.has(userId)) {
            this.states.set(userId, {
                userId,
                state: DialogueState.IDLE,
                data: {},
                history: [],
                startTime: Date.now(),
                lastInteraction: Date.now()
            });
        }
        return this.states.get(userId)!;
    }

    // 处理消息并更新状态
    async processMessage(userId: string, message: Message): Promise<{
        response: string;
        state: DialogueState;
    }> {
        const context = this.getContext(userId);
        context.lastInteraction = Date.now();

        // 解析用户意图
        await this.parseIntent(context, message);

        // 尝试进行状态转换
        await this.tryTransitions(context);

        // 获取当前状态的处理器
        const handler = this.handlers.get(context.state);
        let response = "";

        if (handler) {
            response = await handler(context);
        }

        return {
            response,
            state: context.state
        };
    }

    // 解析用户意图
    private async parseIntent(context: DialogueContext, message: Message): Promise<void> {
        const content = message.content.toLowerCase();

        // 意图关键词识别(简化版)
        const intents = [
            { name: "help", keywords: ["帮助", "help", "怎么用"] },
            { name: "order", keywords: ["订购", "order", "下单"] },
            { name: "cancel", keywords: ["取消", "cancel", "不要了"] },
            { name: "confirm", keywords: ["确认", "yes", "好的", "确定"] },
            { name: "greeting", keywords: ["你好", "hi", "hello", "嗨"] }
        ];

        for (const intent of intents) {
            if (intent.keywords.some(kw => content.includes(kw))) {
                context.data.intent = intent.name;
                context.data.hasIntent = true;
                return;
            }
        }

        // 如果正在收集信息,收集答案
        if (context.state === DialogueState.COLLECTING_INFO) {
            context.data.collectedAnswers = context.data.collectedAnswers || [];
            context.data.collectedAnswers.push(message.content);
        }
    }

    // 尝试状态转换
    private async tryTransitions(context: DialogueContext): Promise<void> {
        for (const transition of this.transitions) {
            if (transition.from === context.state && transition.condition(context)) {
                // 记录历史
                context.history.push(context.state);

                // 执行动作
                transition.action?.(context);

                // 更新状态
                context.state = transition.to;
                console.log(`状态转换: ${transition.from} -> ${transition.to}`);

                // 只进行一次转换
                return;
            }
        }
    }

    // 验证收集的信息
    private validateCollectedInfo(context: DialogueContext): void {
        const requiredFields = context.data.requiredFields || [];
        const answers = context.data.collectedAnswers || [];

        if (answers.length >= requiredFields.length) {
            context.data.infoComplete = true;
        }
    }

    // 注册状态处理器
    registerHandler(state: DialogueState, handler: (ctx: DialogueContext) => Promise<string>) {
        this.handlers.set(state, handler);
    }

    // 重置对话状态
    reset(userId: string): void {
        this.states.delete(userId);
    }
}

// 导出
export { DialogueStateMachine, DialogueState, DialogueContext };

5.4 知识库集成

对于需要回答专业问题的Agent,集成知识库可以显著提高回答的准确性和专业性。

知识库配置和检索:

// src/utils/knowledge-base.ts

import { Agent } from "@elizaos/core";

// 知识库条目
interface KnowledgeEntry {
    id: string;
    question: string;
    answer: string;
    category: string;
    tags: string[];
    embedding?: number[];
    confidence: number;
    lastUpdated: number;
}

// 知识库管理器
class KnowledgeBase {
    private entries: KnowledgeEntry[] = [];
    private agent: Agent;
    private embeddingModel: any;

    constructor(agent: Agent) {
        this.agent = agent;
        this.initialize();
    }

    private async initialize() {
        // 加载预定义的知识库条目
        this.entries = this.getDefaultEntries();

        // 为所有条目生成向量
        await this.generateEmbeddings();
    }

    // 默认知识库条目
    private getDefaultEntries(): KnowledgeEntry[] {
        return [
            {
                id: "kb_001",
                question: "eliza支持哪些平台?",
                answer: "eliza目前支持Discord、Telegram、Twitter等多个平台。通过适配器模式,可以方便地添加新的平台支持。",
                category: "平台支持",
                tags: ["平台", "集成", "适配器"],
                confidence: 0.95,
                lastUpdated: Date.now()
            },
            {
                id: "kb_002",
                question: "如何配置API密钥?",
                answer: "在项目根目录创建.env文件,添加相应的API密钥配置,如OPENAI_API_KEY、DISCORD_BOT_TOKEN等。具体配置项可以参考.env.example文件。",
                category: "配置",
                tags: ["配置", "API", "密钥"],
                confidence: 0.95,
                lastUpdated: Date.now()
            },
            {
                id: "kb_003",
                question: "eliza的记忆系统是如何工作的?",
                answer: "eliza使用向量数据库存储记忆,通过语义检索找到相关的历史对话。这种设计让Agent能够记住之前的交互,提供更连贯的对话体验。",
                category: "技术原理",
                tags: ["记忆", "向量", "检索"],
                confidence: 0.9,
                lastUpdated: Date.now()
            }
        ];
    }

    // 生成向量表示
    private async generateEmbeddings() {
        for (const entry of this.entries) {
            if (!entry.embedding) {
                entry.embedding = await this.agent.embed(entry.question + " " + entry.answer);
            }
        }
    }

    // 添加新条目
    async addEntry(entry: Omit<KnowledgeEntry, "id" | "embedding" | "lastUpdated">): Promise<KnowledgeEntry> {
        const newEntry: KnowledgeEntry = {
            ...entry,
            id: `kb_${Date.now()}`,
            embedding: await this.agent.embed(entry.question + " " + entry.answer),
            lastUpdated: Date.now()
        };

        this.entries.push(newEntry);
        return newEntry;
    }

    // 检索相关知识
    async retrieve(query: string, limit = 3): Promise<KnowledgeEntry[]> {
        const queryEmbedding = await this.agent.embed(query);

        // 计算相似度并排序
        const scored = this.entries.map(entry => ({
            entry,
            score: this.cosineSimilarity(queryEmbedding, entry.embedding!)
        }));

        // 过滤低分结果并返回top k
        return scored
            .filter(s => s.score > 0.6)
            .sort((a, b) => b.score - a.score)
            .slice(0, limit)
            .map(s => s.entry);
    }

    // 余弦相似度计算
    private cosineSimilarity(a: number[], b: number[]): number {
        let dotProduct = 0;
        let normA = 0;
        let normB = 0;

        for (let i = 0; i < a.length; i++) {
            dotProduct += a[i] * b[i];
            normA += a[i] * a[i];
            normB += b[i] * b[i];
        }

        return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
    }

    // 基于知识库回答问题
    async answerFromKnowledge(query: string): Promise<string | null> {
        const relevantEntries = await this.retrieve(query, 3);

        if (relevantEntries.length === 0) {
            return null;
        }

        // 构建基于知识的提示
        const knowledgeContext = relevantEntries
            .map(e => `[相关问答]\n问: ${e.question}\n答: ${e.answer}`)
            .join("\n\n");

        return `基于知识库信息:\n\n${knowledgeContext}`;
    }

    // 更新条目
    async updateEntry(id: string, updates: Partial<KnowledgeEntry>): Promise<KnowledgeEntry | null> {
        const index = this.entries.findIndex(e => e.id === id);
        if (index === -1) return null;

        const entry = this.entries[index];
        const updatedEntry = {
            ...entry,
            ...updates,
            lastUpdated: Date.now()
        };

        // 如果更新了内容,重新生成向量
        if (updates.question || updates.answer) {
            updatedEntry.embedding = await this.agent.embed(
                updatedEntry.question + " " + updatedEntry.answer
            );
        }

        this.entries[index] = updatedEntry;
        return updatedEntry;
    }

    // 删除条目
    deleteEntry(id: string): boolean {
        const index = this.entries.findIndex(e => e.id === id);
        if (index === -1) return false;

        this.entries.splice(index, 1);
        return true;
    }

    // 获取所有条目
    getAllEntries(): KnowledgeEntry[] {
        return [...this.entries];
    }

    // 按分类获取条目
    getEntriesByCategory(category: string): KnowledgeEntry[] {
        return this.entries.filter(e => e.category === category);
    }
}

export { KnowledgeBase, KnowledgeEntry };

六、最佳实践与性能优化

6.1 错误处理策略

在生产环境中,健壮的错误处理是保证服务稳定运行的关键。

统一错误处理机制:

// src/utils/error-handler.ts

// 错误类型枚举
enum ErrorType {
    VALIDATION = "validation_error",
    API = "api_error",
    NETWORK = "network_error",
    AUTH = "auth_error",
    RATE_LIMIT = "rate_limit_error",
    INTERNAL = "internal_error",
    UNKNOWN = "unknown_error"
}

// 自定义错误类
class AgentError extends Error {
    type: ErrorType;
    code: string;
    details?: any;
    retryable: boolean;

    constructor(
        message: string,
        type: ErrorType,
        code: string,
        options?: {
            details?: any;
            retryable?: boolean;
        }
    ) {
        super(message);
        this.type = type;
        this.code = code;
        this.details = options?.details;
        this.retryable = options?.retryable ?? false;

        // 捕获堆栈跟踪
        Error.captureStackTrace(this, this.constructor);
    }

    toJSON() {
        return {
            error: {
                type: this.type,
                code: this.code,
                message: this.message,
                details: this.details,
                retryable: this.retryable
            }
        };
    }
}

// 错误处理中间件
class ErrorHandler {
    private errorLog: Array<{
        timestamp: number;
        error: AgentError;
        context: any;
    }> = [];

    // 记录错误
    log(error: Error | AgentError, context?: any) {
        const agentError = error instanceof AgentError 
            ? error 
            : new AgentError(error.message, ErrorType.UNKNOWN, "UNKNOWN");

        this.errorLog.push({
            timestamp: Date.now(),
            error: agentError,
            context
        });

        // 控制日志大小
        if (this.errorLog.length > 1000) {
            this.errorLog.shift();
        }

        // 输出到控制台
        console.error(`[${agentError.type}] ${agentError.code}: ${agentError.message}`);
        if (context) {
            console.error("Context:", context);
        }

        // 发送错误通知(如果是严重错误)
        if (agentError.type === ErrorType.API || agentError.type === ErrorType.INTERNAL) {
            this.notifyError(agentError);
        }
    }

    // 处理错误并返回友好的用户消息
    handle(error: Error | AgentError): string {
        const agentError = error instanceof AgentError 
            ? error 
            : new AgentError(error.message, ErrorType.UNKNOWN, "UNKNOWN");

        switch (agentError.type) {
            case ErrorType.VALIDATION:
                return `输入验证失败: ${agentError.message}`;

            case ErrorType.API:
                return `服务暂时不可用,请稍后再试。`;

            case ErrorType.NETWORK:
                return `网络连接出现问题,请检查网络后重试。`;

            case ErrorType.AUTH:
                return `认证失败,请检查您的配置是否正确。`;

            case ErrorType.RATE_LIMIT:
                return `请求过于频繁,请稍后再试。`;

            case ErrorType.INTERNAL:
                return `遇到了内部错误,我们会尽快修复。`;

            default:
                return `发生了未知错误,请联系管理员。`;
        }
    }

    // 错误通知(可以接入飞书、Slack等)
    private notifyError(error: AgentError) {
        // 这里可以添加错误通知逻辑
        // 例如发送到监控系统、发送邮件通知等
        console.log("错误通知:", error.toJSON());
    }

    // 获取错误统计
    getStatistics() {
        const stats = {
            total: this.errorLog.length,
            byType: {} as Record<ErrorType, number>,
            recent: this.errorLog.slice(-10)
        };

        for (const entry of this.errorLog) {
            stats.byType[entry.error.type] = (stats.byType[entry.error.type] || 0) + 1;
        }

        return stats;
    }
}

// 重试装饰器
function withRetry(options?: {
    maxRetries?: number;
    delay?: number;
    backoff?: "linear" | "exponential";
}) {
    const maxRetries = options?.maxRetries ?? 3;
    const initialDelay = options?.delay ?? 1000;
    const backoff = options?.backoff ?? "exponential";

    return function <T>(
        target: any,
        propertyKey: string,
        descriptor: PropertyDescriptor
    ) {
        const originalMethod = descriptor.value;

        descriptor.value = async function (...args: any[]) {
            let lastError: Error | undefined;

            for (let attempt = 0; attempt <= maxRetries; attempt++) {
                try {
                    return await originalMethod.apply(this, args);
                } catch (error) {
                    lastError = error as Error;

                    // 如果是不可重试的错误,直接抛出
                    if (error instanceof AgentError && !error.retryable) {
                        throw error;
                    }

                    // 如果还有重试次数
                    if (attempt < maxRetries) {
                        const delay = backoff === "exponential"
                            ? initialDelay * Math.pow(2, attempt)
                            : initialDelay * (attempt + 1);

                        console.log(`重试 ${attempt + 1}/${maxRetries},等待 ${delay}ms...`);
                        await new Promise(resolve => setTimeout(resolve, delay));
                    }
                }
            }

            throw lastError;
        };

        return descriptor;
    };
}

export { 
    AgentError, 
    ErrorType, 
    ErrorHandler, 
    withRetry 
};

在实际业务中使用错误处理:

// src/services/user-service.ts

import { AgentError, ErrorType, ErrorHandler, withRetry } from "../utils/error-handler";

const errorHandler = new ErrorHandler();

// 使用重试装饰器的示例
class UserService {
    @withRetry({ maxRetries: 3, backoff: "exponential" })
    async fetchUserData(userId: string): Promise<any> {
        try {
            const response = await fetch(`/api/users/${userId}`);

            if (!response.ok) {
                if (response.status === 404) {
                    throw new AgentError(
                        "用户不存在",
                        ErrorType.VALIDATION,
                        "USER_NOT_FOUND",
                        { userId }
                    );
                }

                if (response.status === 401) {
                    throw new AgentError(
                        "认证失败",
                        ErrorType.AUTH,
                        "AUTH_FAILED"
                    );
                }

                if (response.status === 429) {
                    throw new AgentError(
                        "请求过于频繁",
                        ErrorType.RATE_LIMIT,
                        "RATE_LIMITED",
                        { retryable: true }
                    );
                }

                throw new AgentError(
                    `API请求失败: ${response.status}`,
                    ErrorType.API,
                    "API_ERROR"
                );
            }

            return await response.json();

        } catch (error) {
            errorHandler.log(error as Error, { userId });

            if (error instanceof AgentError) {
                throw error;
            }

            throw new AgentError(
                (error as Error).message,
                ErrorType.NETWORK,
                "NETWORK_ERROR",
                { retryable: true }
            );
        }
    }
}

6.2 性能优化技巧

缓存策略:

// src/utils/cache.ts

// 简单的内存缓存实现
class Cache<T> {
    private store: Map<string, {
        value: T;
        expiresAt: number;
    }> = new Map();

    private defaultTTL: number;

    constructor(defaultTTL = 60000) {  // 默认60秒
        this.defaultTTL = defaultTTL;
    }

    set(key: string, value: T, ttl?: number): void {
        const expiresAt = Date.now() + (ttl ?? this.defaultTTL);
        this.store.set(key, { value, expiresAt });
    }

    get(key: string): T | null {
        const entry = this.store.get(key);

        if (!entry) {
            return null;
        }

        // 检查是否过期
        if (Date.now() > entry.expiresAt) {
            this.store.delete(key);
            return null;
        }

        return entry.value;
    }

    has(key: string): boolean {
        return this.get(key) !== null;
    }

    delete(key: string): void {
        this.store.delete(key);
    }

    clear(): void {
        this.store.clear();
    }

    // 清理过期条目
    cleanup(): number {
        const now = Date.now();
        let count = 0;

        for (const [key, entry] of this.store.entries()) {
            if (now > entry.expiresAt) {
                this.store.delete(key);
                count++;
            }
        }

        return count;
    }
}

// LRU缓存实现
class LRUCache<T> {
    private capacity: number;
    private store: Map<string, T> = new Map();

    constructor(capacity: number) {
        this.capacity = capacity;
    }

    get(key: string): T | null {
        if (!this.store.has(key)) {
            return null;
        }

        // 移到末尾(最近使用)
        const value = this.store.get(key)!;
        this.store.delete(key);
        this.store.set(key, value);

        return value;
    }

    put(key: string, value: T): void {
        if (this.store.has(key)) {
            this.store.delete(key);
        } else if (this.store.size >= this.capacity) {
            // 删除最旧的条目
            const firstKey = this.store.keys().next().value;
            this.store.delete(firstKey);
        }

        this.store.set(key, value);
    }

    clear(): void {
        this.store.clear();
    }

    size(): number {
        return this.store.size;
    }
}

// 使用缓存优化向量检索
class CachedVectorStore {
    private store: any;
    private embeddingCache: Cache<number[]>;
    private retrievalCache: LRUCache<any[]>;

    constructor() {
        this.embeddingCache = new Cache(3600000);  // 1小时缓存
        this.retrievalCache = new LRUCache(100);   // LRU缓存100条
    }

    async getEmbedding(text: string): Promise<number[]> {
        const cacheKey = `embedding:${text}`;

        // 先检查缓存
        const cached = this.embeddingCache.get(cacheKey);
        if (cached) {
            return cached;
        }

        // 缓存未命中,调用API
        const embedding = await this.computeEmbedding(text);

        // 存入缓存
        this.embeddingCache.set(cacheKey, embedding);

        return embedding;
    }

    async retrieve(query: string, limit = 5): Promise<any[]> {
        const cacheKey = `retrieve:${query}:${limit}`;

        // 先检查缓存
        const cached = this.retrievalCache.get(cacheKey);
        if (cached) {
            return cached;
        }

        // 执行检索
        const results = await this.store.search(await this.getEmbedding(query), limit);

        // 存入LRU缓存
        this.retrievalCache.put(cacheKey, results);

        return results;
    }

    private async computeEmbedding(text: string): Promise<number[]> {
        // 这里调用实际的embedding API
        // 实际实现中需要调用OpenAI或其他embedding服务
        return [];
    }
}

并发控制:

// src/utils/concurrency.ts

// 信号量实现,用于限制并发数
class Semaphore {
    private permits: number;
    private queue: Array<() => void> = [];

    constructor(permits: number) {
        this.permits = permits;
    }

    async acquire(): Promise<void> {
        if (this.permits > 0) {
            this.permits--;
            return Promise.resolve();
        }

        // 如果没有可用许可,加入等待队列
        return new Promise<void>(resolve => {
            this.queue.push(resolve);
        });
    }

    release(): void {
        this.permits++;

        // 唤醒一个等待的调用
        if (this.queue.length > 0) {
            this.permits--;
            const resolve = this.queue.shift()!;
            resolve();
        }
    }

    available(): number {
        return this.permits;
    }
}

// 速率限制器
class RateLimiter {
    private tokens: number;
    private maxTokens: number;
    private refillRate: number;  // 每秒补充的token数
    private lastRefill: number;
    private queue: Array<() => void> = [];
    private processing = false;

    constructor(maxTokens: number, refillRate: number) {
        this.maxTokens = maxTokens;
        this.tokens = maxTokens;
        this.refillRate = refillRate;
        this.lastRefill = Date.now();
    }

    private refill(): void {
        const now = Date.now();
        const elapsed = (now - this.lastRefill) / 1000;
        const newTokens = elapsed * this.refillRate;

        this.tokens = Math.min(this.maxTokens, this.tokens + newTokens);
        this.lastRefill = now;
    }

    async acquire(tokens = 1): Promise<void> {
        this.refill();

        if (this.tokens >= tokens) {
            this.tokens -= tokens;
            return Promise.resolve();
        }

        // 需要等待token补充
        return new Promise<void>(resolve => {
            this.queue.push(() => {
                this.refill();
                if (this.tokens >= tokens) {
                    this.tokens -= tokens;
                    resolve();
                }
            });

            // 启动处理循环
            if (!this.processing) {
                this.processQueue();
            }
        });
    }

    private async processQueue(): Promise<void> {
        this.processing = true;

        while (this.queue.length > 0) {
            const callback = this.queue[0];

            // 计算需要等待的时间
            const tokensNeeded = 1;
            const tokensDeficit = tokensNeeded - this.tokens;
            const waitTime = tokensDeficit / this.refillRate * 1000;

            if (waitTime > 0) {
                await new Promise(resolve => setTimeout(resolve, waitTime));
            }

            this.refill();
            if (this.tokens >= tokensNeeded) {
                this.queue.shift()!();
            }
        }

        this.processing = false;
    }

    reset(): void {
        this.tokens = this.maxTokens;
        this.lastRefill = Date.now();
        this.queue = [];
    }
}

// 并发控制的使用示例
class ControlledAgentService {
    private apiLimiter: RateLimiter;
    private processingSemaphore: Semaphore;

    constructor() {
        // OpenAI API限制:每分钟60次请求
        this.apiLimiter = new RateLimiter(60, 60);
        // 最多同时处理10个请求
        this.processingSemaphore = new Semaphore(10);
    }

    async processRequest(request: any): Promise<string> {
        // 获取处理许可
        await this.processingSemaphore.acquire();

        try {
            // 获取API调用许可(速率限制)
            await this.apiLimiter.acquire();

            // 执行实际的API调用
            const response = await this.callAPI(request);

            return response;

        } finally {
            // 释放处理许可
            this.processingSemaphore.release();
        }
    }

    private async callAPI(request: any): Promise<string> {
        // 实际的API调用逻辑
        return "响应内容";
    }
}

6.3 日志与监控

结构化日志系统:

// src/utils/logger.ts

import fs from "fs";
import path from "path";

// 日志级别
enum LogLevel {
    DEBUG = 0,
    INFO = 1,
    WARN = 2,
    ERROR = 3,
    FATAL = 4
}

const levelNames: Record<LogLevel, string> = {
    [LogLevel.DEBUG]: "DEBUG",
    [LogLevel.INFO]: "INFO",
    [LogLevel.WARN]: "WARN",
    [LogLevel.ERROR]: "ERROR",
    [LogLevel.FATAL]: "FATAL"
};

// 日志条目
interface LogEntry {
    timestamp: string;
    level: string;
    message: string;
    context?: Record<string, any>;
    error?: {
        name: string;
        message: string;
        stack?: string;
    };
}

// 结构化日志器
class Logger {
    private level: LogLevel;
    private context: Record<string, any>;
    private logFile?: string;

    constructor(options?: {
        level?: LogLevel;
        context?: Record<string, any>;
        logFile?: string;
    }) {
        this.level = options?.level ?? LogLevel.INFO;
        this.context = options?.context ?? {};
        this.logFile = options?.logFile;

        // 确保日志目录存在
        if (this.logFile) {
            const dir = path.dirname(this.logFile);
            if (!fs.existsSync(dir)) {
                fs.mkdirSync(dir, { recursive: true });
            }
        }
    }

    private log(level: LogLevel, message: string, context?: Record<string, any>, error?: Error) {
        if (level < this.level) {
            return;
        }

        const entry: LogEntry = {
            timestamp: new Date().toISOString(),
            level: levelNames[level],
            message,
            context: { ...this.context, ...context }
        };

        if (error) {
            entry.error = {
                name: error.name,
                message: error.message,
                stack: error.stack
            };
        }

        const logLine = JSON.stringify(entry);

        // 输出到控制台
        console.log(logLine);

        // 输出到文件
        if (this.logFile) {
            fs.appendFileSync(this.logFile, logLine + "\n");
        }
    }

    debug(message: string, context?: Record<string, any>): void {
        this.log(LogLevel.DEBUG, message, context);
    }

    info(message: string, context?: Record<string, any>): void {
        this.log(LogLevel.INFO, message, context);
    }

    warn(message: string, context?: Record<string, any>): void {
        this.log(LogLevel.WARN, message, context);
    }

    error(message: string, error?: Error, context?: Record<string, any>): void {
        this.log(LogLevel.ERROR, message, context, error);
    }

    fatal(message: string, error?: Error, context?: Record<string, any>): void {
        this.log(LogLevel.FATAL, message, context, error);
    }

    // 创建子日志器
    child(context: Record<string, any>): Logger {
        return new Logger({
            level: this.level,
            context: { ...this.context, ...context },
            logFile: this.logFile
        });
    }
}

// 全局日志器实例
const logger = new Logger({
    level: process.env.LOG_LEVEL as any ?? LogLevel.INFO,
    logFile: process.env.LOG_FILE,
    context: {
        service: "my-agent",
        version: process.env.VERSION ?? "1.0.0"
    }
});

// 使用示例
export function logUsage() {
    const requestLogger = logger.child({ component: "request" });

    requestLogger.info("收到请求", {
        userId: "user123",
        endpoint: "/api/chat",
        method: "POST"
    });

    requestLogger.info("请求处理完成", {
        duration: 150,
        status: 200
    });
}

export { Logger, LogLevel, LogEntry };

七、总结与资源链接

7.1 核心要点回顾

通过这篇文章的学习,你已经掌握了以下关键知识点:

环境搭建与初始化: 学会了如何搭建eliza开发环境,包括Node.js配置、项目克隆、依赖安装和环境变量配置。理解了一个清晰的项目目录结构对于长期维护的重要性。

Agent运行时架构: 深入理解了eliza的Agent运行时如何协调各个组件,处理消息的完整生命周期,从接收、解析、上下文构建到响应生成和发送。

记忆系统: 掌握了eliza强大的记忆系统原理,包括短期记忆、长期记忆和情景记忆的分类,以及向量检索如何实现语义搜索。

插件系统: 了解了插件架构的设计理念,学会了如何开发自定义插件来扩展Agent功能。插件化设计让功能扩展变得简单而安全。

多平台支持: 学会了如何配置Discord、Telegram等多个平台的适配器,实现一个Agent同时在多个平台运行。

实战开发: 从零开始构建了一个完整的AI Agent项目,包含了配置管理、适配器实现、对话引擎和错误处理等核心模块。

7.2 相关资源链接

官方资源:

  • GitHub仓库:https://github.com/elizaOS/eliza
  • 官方文档:https://eliza.docs.ai
  • Discord社区:加入官方Discord服务器获取帮助

学习资源:

  • TypeScript官方文档:https://www.typescriptlang.org/docs/
  • Node.js官方文档:https://nodejs.org/docs/
  • Discord.js官方文档:https://discord.js.org/
  • Vector Database Guide:https://www.pinecone.io/learn/vector-database/

相关开源项目:

  • LangChain:构建LLM应用的框架
  • AutoGPT:自主AI Agent实验项目
  • ChatGPT Plugin Templates:OpenAI插件开发模板

7.3 进一步学习的建议

深入方向一:自定义模型集成

eliza目前主要支持OpenAI和Anthropic的模型。你可以尝试集成其他开源模型,如LLaMA、Mistral等,构建完全本地化的AI Agent解决方案。

深入方向二:高级RAG应用

当前的知识库检索是基础版本。你可以探索更高级的RAG技术,如混合检索、重新排序、多跳推理等,进一步提升Agent的知识问答能力。

深入方向三:多Agent协作

研究如何让多个Agent协作完成复杂任务,如分工处理、信息共享、结果汇总等。这是当前AI Agent研究的前沿方向。

深入方向四:生产环境部署

学习Docker容器化、Kubernetes编排、CI/CD流水线等生产环境必备技能,将你的Agent项目部署到云端提供服务。

7.4 写在最后

eliza是一个非常年轻但充满潜力的开源项目。它将复杂的AI Agent技术封装成易于使用的组件,让更多开发者能够参与到智能体应用的开发中来。无论你是想要构建一个客服机器人、个人助手还是自动化工具,eliza都能为你提供一个良好的起点。

AI Agent领域正处于快速发展阶段,新的技术和应用场景不断涌现。保持学习、持续实践,你一定能在这个激动人心的领域找到属于自己的位置。

祝你在eliza的学习和使用过程中收获满满!如果遇到问题,欢迎在社区中寻求帮助,也欢迎为项目贡献代码和文档。


本文档会持续更新以反映项目的最新变化。如有任何问题或建议,欢迎提出。

如果内容对您有帮助,欢迎打赏

您的支持是我继续创作的动力

前往打赏页面

评论区

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注