Skip to content

我用代码

本文档介绍了如何通过编写代码来配置 PPAgent 应用,包括集成各种后端模型、消息源以及技能。

具体的每一个消息源等的详细配置,请参考配置部分。

本页部分内容由AI生成,如有配置问题,可在首页二维码加群交流。

WARNING

使用代码配置仅支持以代码的方式运行。如果使用的是Docker方式,建议使用页面进行配置

配置概述

PPAgent 应用通过 src/app.ts 文件进行配置,它是应用的实际启动入口,负责初始化 PPAgent 实例并配置所有组件。配置内容主要包括以下几个部分:

  • 后端模型 (Bots)
  • 消息源 (Sources)
  • 技能 (Skills)
  • 智能体 (Agents)
  • 任务 (Tasks)

启动流程

PPAgent 应用的启动流程如下,通常情况无需更改这部分代码:

  1. 通过 starter 函数初始化 PPAgent 实例
  2. 加载默认插件和 API 插件
  3. 启动应用
  4. 设置重启监听器
typescript
const starter = async () => {
    const chat = new PPAgent({
        // 配置项
    });
    await chat.use(defaultPlugin);
    await chat.use(apiPlugin);
    await chat.start();
    return chat;
};

// 初始化应用
const chater = await starter();
// 监听重启事件,如果未来不使用页面配置,也可以删除这句代码
chater.globalEvent.on("restart", () => onRestart(chater));

配置后端模型 (Bots)

后端模型是处理用户消息并生成回复的组件。PPAgent 内置多种类型的后端模型,例如:

  • DeepSeek(支持推理)
  • OpenAI (GPT系列)
  • Ollama
  • 百度文心
  • 腾讯混元
  • 智谱清言
  • FastGPT
  • RagFlow
  • QAnything
  • Dify Agent
  • Coze 等

每个后端模型的配置方式如下(详细配置项可以参考配置手册、API手册或者ts的描述文件):

typescript
{
    name: 机器人类型名称,
    options: {
        instanceName: "实例名称",
        // 其他特定于该机器人类型的配置项
    }
}

例如,配置一个 OpenAI 机器人:

typescript
{
    name: OpenAIBot.params.name,
    options: {
        instanceName: "openai-bot", // 需要全局唯一
        apiKey: "你的API密钥",
        apiBase: "API基础URL",
        chatOptions: {
            model: "gpt-4o-mini",
        }
    }
}

配置消息源 (Sources)

消息源是接收用户消息的渠道,PPAgent 支持多种消息源:

  • 微信公众号 (WCOASource)
  • 企业微信 (WeWorkSource)
  • 钉钉机器人 (DingRobotSource)
  • 飞书 (FeishuSource)
  • QQ (QQSource)
  • 微信对话平台 (WCAISource) 等

还有第三方实现的各类消息源,如基于gewechat的消息源,实现对接个人微信。

每个消息源的配置方式如下:

typescript
{
    name: 消息源类型名称,
    options: {
        instanceName: "实例名称",
        // 其他特定于该消息源类型的配置项
    }
}

例如,配置一个飞书消息源:

typescript
{
    name: FeishuSource.params.name,
    options: {
        instanceName: "feishu-app",
        appId: "你的应用ID",
        appSecret: "你的应用密钥",
        replayTextMode: "stream",
        richTextTitle: true
    }
}

配置技能 (Skills)

技能是扩展智能体功能的组件,例如语音转文字、文字转语音、绘图、视频生成、消息总结等。PPAgent 内置了一些简单的技能,如:

  • Sovite项目的文字转语音
  • SenseVoice项目的语音转文字
  • 百度文字转语音和语音转文字
  • FishAudio的文字转语音
  • 硅基流动的文字转语音和语音转文字
  • 腾讯的文字转语音和语音转文字
  • 讯飞的文字转语音和语音转文字
  • 智普的绘图
  • 智普的视频生成
  • 硅基流动的绘图

技能配置方式如下:

typescript
{
    name: 技能类型名称,
    options: {
        instanceName: "实例名称",
        // 其他特定于该技能类型的配置项
    }
}

例如,配置语音转文字技能:

typescript
{
    name: SenseVoiceSTTSkill.params.name,
    options: {
        apiHost: "技能API地址",
        authType: "basic",
        userName: "用户名",
        password: "密码",
        instanceName: "sensevoice-stt",
    }
}

配置智能体 (Agents)

智能体定义了如何将消息源、机器人和技能关联起来,包括回复规则、消息处理方式等。配置内容包括:

  • 关联的消息源
  • 使用的机器人
  • 响应规则
  • 消息分割规则
  • 发送模式
  • 技能应用规则
  • ...
typescript
{
    sourceInstanceNames: ["消息源实例名称列表"],
    name: "代理名称",
    botResponseRule: {
        instanceName: "机器人实例名称",
        respondTo: {
            at: true,
            refered: true,
            names: ["xxx"] // 触发回复的关键名称,与上面是或的关系
        }
    },
    minSendInterval: 1000, // 最小发送间隔
    bufferWordsMinCount: 30, // 缓冲区最小字数
    maxSplitCount: 5, // 最大分割数
    splitImageFromBotText: true, // 从机器人文本中分离图片
    removeImageAfterSplit: false, // 分离后是否删除图片
    sendMode: "queue", // 发送模式
    fallbackAnswer: "该功能暂不支持😀", // 失败时的回复
    skillRules: [
        // 技能应用规则,请参考详细配置手册
    ],
    multiActiveChatInConversationTips: "哎呦,等我这句话说完再回复下一个!", // 多活跃聊天提示
    multiActiveChatInConversationMode: "pool_tips", // 多活跃聊天模式
    sendErrorLog: true // 是否发送错误日志
}

配置任务 (Tasks)

任务是定时或事件触发的操作,可以用于系统维护、定时通知等。支持的任务类型包括:

  • 消息源事件任务 (SourceEventTaskTrigger)
  • 全局事件任务 (GlobalEventTaskTrigger)
  • 定时任务 (CronTaskTrigger)

任务配置方式如下:

typescript
{
    name: "任务名称",
    triggerName: 触发器类型名称,
    triggerOptions: {
        // 触发器配置项
    },
    runnerName: 运行器类型名称,
    runnerOptions: {
        // 运行器配置项
    }
}

例如,配置定时任务:

typescript
{
    name: "定时任务",
    triggerName: CronTaskTrigger.params.name,
    triggerOptions: {
        cron: "*/5 * * * * *" // 每5秒执行一次
    },
    runnerName: EchoTaskRunner.params.name,
    runnerOptions: {
        instanceName: "echo-task-runner"
    }
}

热重启机制

PPAgent 应用提供了热重启机制,当触发重启事件时,会先停止当前实例,然后创建新实例:

typescript
const onRestart = async (chater: PPAgent) => {
    await chater.stop();
    setTimeout(async () => {
        chater.globalEvent.emit(GlobalEventNames.APP_RESTARTED);
        chater.off("restart", onRestart);
        chater = await starter();
        chater.globalEvent.on("restart", () => onRestart(chater));
    }, 500);
};

注意事项

  1. 配置文件中可能包含敏感信息(API密钥、密码等),请妥善保管和加密
  2. 在实际部署时,应从环境变量或配置文件中读取这些敏感信息,而不是硬编码
  3. 使用前先阅读各组件的文档,了解其支持的功能和配置选项
  4. 测试配置时,建议先使用较简单的配置,确认可用后再添加更多复杂配置

完整的配置示例

以下是一个完整的配置示例,包括一个 OpenAI 机器人、飞书消息源、语音转文本技能、智能体和定时任务:

typescript
// src/app.ts
import { 
  config,
  PPAgent, 
  OpenAIBot, 
  IOpenAIBotOptions, 
  FeishuSource, 
  IFeishuSourceOptions, 
  ISenseVoiceSTTSkillOptions, 
  SenseVoiceSTTSkill, 
  SourceChatMessageType, 
  SourceEventType, 
  GlobalEventTaskTrigger, 
  IEventTaskTriggerOptions, 
  EchoTaskRunner, 
  GlobalEventNames, 
  defaultPlugin, 
  apiPlugin, 
  getLogger 
} from "ppagent";
import { v4 } from "uuid";

const logger = getLogger("app");

const starter = async () => {
    logger.debug("app starting");
    const chat = new PPAgent({
        name: "default",
        agentServiceOptions: {
            models: {
                bots: [
                    {
                        name: OpenAIBot.params.name,
                        options: {
                            instanceName: "openai-bot-main",
                            apiKey: process.env.OPENAI_API_KEY || "your-api-key-here",
                            apiBase: "https://api.openai.com/v1",
                            chatOptions: {
                                model: "gpt-4o",
                            },
                        } as IOpenAIBotOptions,
                    },
                ],
                sources: [
                    {
                        name: FeishuSource.params.name,
                        options: {
                            instanceName: 'feishu-app-main',
                            appId: process.env.FEISHU_APP_ID || 'your-app-id-here',
                            appSecret: process.env.FEISHU_APP_SECRET || 'your-app-secret-here',
                            replayTextMode: 'stream',
                            richTextTitle: true,
                        } as IFeishuSourceOptions,
                    },
                ],
                skills: [
                    {
                        name: SenseVoiceSTTSkill.params.name,
                        options: {
                            apiHost: "https://your-api-host.com",
                            authType: "basic",
                            userName: process.env.STT_USER || "username",
                            password: process.env.STT_PASSWORD || "password",
                            instanceName: "sensevoice-stt-main",
                        } as ISenseVoiceSTTSkillOptions
                    }
                ],
                agents: [
                    {
                        sourceInstanceNames: ["feishu-app-main"],
                        name: "chat-agent-main",
                        botResponseRule: {
                            instanceName: "openai-bot-main",
                            respondTo: {
                                at: true,
                                refered: true,
                                names: ["小助手"]
                            }
                        },
                        minSendInterval: 1000,
                        bufferWordsMinCount: 30,
                        maxSplitCount: 5,
                        splitImageFromBotText: true,
                        removeImageAfterSplit: false,
                        sendMode: "queue",
                        fallbackAnswer: "该功能暂不支持😀",
                        skillRules: [
                            {
                                instanceName: "sensevoice-stt-main",
                                messageTypes: [SourceChatMessageType.AUDIO],
                                skillApplyOn: "source",
                            }
                        ],
                        multiActiveChatInConversationTips: "请稍等,我正在回复上一个问题...",
                        multiActiveChatInConversationMode: "pool_tips",
                        sendErrorLog: true,
                    }
                ],
            },
        },
        offline: config.offline,
        taskServiceOptions: {
            tasks: [
                {
                    name: "应用启动通知任务",
                    triggerName: GlobalEventTaskTrigger.params.name,
                    triggerOptions: {
                        instanceName: "app-started-task-trigger",
                        eventNames: [GlobalEventNames.APP_STARTED]
                    } as IEventTaskTriggerOptions,
                    runnerName: EchoTaskRunner.params.name,
                    runnerOptions: {
                        instanceName: "app-started-task-runner"
                    }
                },
            ],
        },
    });
    
    // 注册插件
    await chat.use(defaultPlugin);
    await chat.use(apiPlugin);
    
    // 启动应用
    await chat.start();
    logger.debug("app started");
    
    return chat;
};

// 热重启处理函数
const onRestart = async (chater: PPAgent) => {
    logger.warn("app restarting, stop old instance...");
    await chater.stop();
    setTimeout(async () => {
        logger.warn("old instance stopped, start new instance...");
        chater.globalEvent.emit(GlobalEventNames.APP_RESTARTED, { title: "应用重启", id: v4() });
        chater.off("restart", onRestart);
        chater = await starter();
        logger.warn("new instance started");
        chater.globalEvent.on("restart", () => onRestart(chater));
    }, 500);
};

// 启动应用
const chater = await starter();
chater.globalEvent.on("restart", () => onRestart(chater));