You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为基于Discord.js与OpenAI API的聊天机器人添加记忆功能?

Discord.js + OpenAI 聊天机器人记忆功能实现方案

优先方案:基于MongoDB存储对话历史(适配现有已连接的数据库)

这个方案无需额外依赖,直接利用现有MongoDB连接,开发成本低,适合独立开发者快速落地。

1. 数据结构设计(Mongoose示例)

针对Discord用户的对话场景,设计如下Schema,区分不同用户/服务器的对话,同时保留时间戳用于管理:

const mongoose = require('mongoose');

const conversationSchema = new mongoose.Schema({
  userId: { type: String, required: true }, // Discord用户唯一ID
  guildId: String, // 可选,区分不同服务器的对话上下文
  history: [{
    role: { type: String, enum: ['user', 'assistant'], required: true },
    content: { type: String, required: true },
    timestamp: { type: Date, default: Date.now }
  }],
  lastActive: { type: Date, default: Date.now } // 用于自动清理长期未活跃的对话
});

// 建立复合索引,提升查询效率
conversationSchema.index({ userId: 1, guildId: 1 });

module.exports = mongoose.model('Conversation', conversationSchema);

2. 对话存储与查询逻辑

  • 存储:每次用户发送消息时,先通过userId(加guildId可选)查找对应对话文档,不存在则新建;将用户消息添加到history数组,调用OpenAI得到回复后,再将机器人回复也存入数组,同时更新lastActive时间。
  • 查询:调用OpenAI前,查询该用户的最近N条对话(比如10条,可根据模型token上限调整),避免Prompt过长导致token超限。

3. 按要求构建OpenAI Prompt

直接基于查询到的历史对话拼接成指定格式的Prompt,适配Curie/Babbage模型:

const Conversation = require('./models/Conversation');

async function buildOpenAIPrompt(userId, guildId, currentMessage) {
  // 硬编码系统介绍
  const systemIntro = "你是一个活跃在Discord的聊天机器人,会结合用户的历史对话上下文给出自然的回复。";
  
  // 查询最近10条对话
  const conversation = await Conversation.findOne(
    { userId, guildId },
    { history: { $slice: -10 } } // 只取最后10条
  ) || { history: [] };

  // 转换历史对话为字符串
  const historyStr = conversation.history.map(item => {
    return item.role === 'user' ? `用户:${item.content}` : `机器人:${item.content}`;
  }).join('\n');

  // 拼接完整Prompt
  return `${systemIntro}\n\n对话历史:\n${historyStr}\n\n用户:${currentMessage}\n机器人:`;
}

4. 优化建议

  • 限制对话历史长度:Curie/Babbage的token上限为2048,建议用openai-count-tokens包计算Prompt的token数,超过阈值时截断早期对话。
  • 定期清理过期数据:通过定时任务删除lastActive超过30天的对话文档,减少数据库占用。

轻量化补充:关键信息提取(无需复杂NLP库)

如果觉得全量对话存储占用资源,可同时提取对话中的关键信息(如用户爱好、提到的事件等),存储到用户对话文档中,进一步精简Prompt:

  1. 在上述Schema中新增keyInfo字段:
keyInfo: {
  userNickname: String,
  preferences: [String],
  recentTopics: [String]
}
  1. 用简单字符串匹配提取关键信息,比如:
// 示例:提取用户提到的爱好
function extractKeyInfo(messageContent, existingKeyInfo) {
  const hobbyKeywords = ['喜欢', '爱好', '玩', '看'];
  hobbyKeywords.forEach(keyword => {
    if (messageContent.includes(keyword)) {
      const hobby = messageContent.split(keyword)[1]?.trim().split(' ')[0];
      if (hobby && !existingKeyInfo.preferences.includes(hobby)) {
        existingKeyInfo.preferences.push(hobby);
      }
    }
  });
  return existingKeyInfo;
}
  1. 构建Prompt时可将keyInfo加入系统介绍,让机器人快速掌握用户基本信息。

代码改造注意事项

  1. 模块化拆分:将对话存储、Prompt构建等逻辑封装成独立服务类,与现有机器人逻辑解耦,避免大规模修改原有代码。
  2. 灰度测试:先在测试Discord服务器部署验证功能,确认稳定后再推广到正式环境。
  3. 错误处理:为数据库操作、OpenAI API调用添加try-catch,避免单个功能异常导致整个机器人崩溃。

内容的提问来源于stack exchange,提问作者Op12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 17:53:21