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

如何用NodeJS实现Facebook聊天机器人的文本问答对话流?

嘿,我明白你的问题了——你现在能处理带按钮的交互,但纯文本的多轮对话(比如一步步问电话、年龄)搞不定,核心问题其实是没做对话状态的追踪。Facebook Messenger本身不会帮你记住用户当前处于对话的哪一步,所以咱们得自己存这个状态,然后根据状态来处理用户的纯文本输入。下面给你具体的实现方案:

实现多轮提问→回答对话流的核心思路

1. 为每个用户维护对话状态

你需要一个存储来记录每个用户当前处于对话的哪个步骤,以及已经收集到的数据。开发测试阶段可以用内存对象,生产环境一定要用数据库(比如Redis、MongoDB)来持久化数据。

示例内存存储(仅用于开发测试):

// 用Map存储用户对话状态,key是用户ID,value是状态对象
const userConversations = new Map();
// 状态对象示例:{ currentStep: 'ask_phone', collectedData: { phone: '123456789' } }

2. 定义你的对话流程步骤

把要问的问题按顺序整理成配置,方便后续调用:

const conversationFlow = [
  { stepId: 'ask_phone', prompt: '欢迎,我有几个问题要问你。你的电话号码是多少?' },
  { stepId: 'ask_age', prompt: '你多大了?' },
  { stepId: 'complete', prompt: '感谢你的回答!你的信息:电话号码{{phone}},年龄{{age}}' }
];

3. 修改现有代码,根据状态处理用户输入

结合你现有的messaging_event逻辑,加入状态判断和分支处理:

// 从messaging_event中提取关键信息
const senderId = messaging_event.sender.id;
const userInput = messaging_event.message?.text?.trim();

// 获取用户当前对话状态,没有则初始化第一步
let userState = userConversations.get(senderId);
if (!userState) {
  // 初始化状态,发送第一个问题
  userState = {
    currentStep: 'ask_phone',
    collectedData: {}
  };
  userConversations.set(senderId, userState);
  sendFbMessage(senderId, conversationFlow.find(step => step.stepId === 'ask_phone').prompt);
  return;
}

// 根据当前对话步骤处理用户输入
switch(userState.currentStep) {
  case 'ask_phone':
    // 可选:验证电话号码格式(比如正则匹配)
    if (userInput && /^[\d\-\+\s]{8,}$/.test(userInput)) {
      // 保存数据,切换到下一步
      userState.collectedData.phone = userInput;
      userState.currentStep = 'ask_age';
      userConversations.set(senderId, userState);
      // 发送下一个问题
      sendFbMessage(senderId, conversationFlow.find(step => step.stepId === 'ask_age').prompt);
    } else {
      // 输入无效,提示重新输入
      sendFbMessage(senderId, '抱歉,我没识别到有效的电话号码,请重新输入哦~');
    }
    break;

  case 'ask_age':
    // 验证年龄是有效数字
    const age = parseInt(userInput);
    if (!isNaN(age) && age > 0 && age < 120) {
      userState.collectedData.age = age;
      userState.currentStep = 'complete';
      userConversations.set(senderId, userState);
      // 替换模板变量,发送完成消息
      const completeMsg = conversationFlow.find(step => step.stepId === 'complete').prompt
        .replace('{{phone}}', userState.collectedData.phone)
        .replace('{{age}}', userState.collectedData.age);
      sendFbMessage(senderId, completeMsg);
      // 可选:对话结束后清除状态,或者保留以便后续交互
      // userConversations.delete(senderId);
    } else {
      sendFbMessage(senderId, '请输入有效的数字年龄(比如18)~');
    }
    break;

  default:
    // 未知状态,重置对话
    sendFbMessage(senderId, '咱们重新开始吧~');
    userConversations.delete(senderId);
    break;
}

// 辅助函数:发送消息到Facebook Messenger(你应该已有类似实现)
function sendFbMessage(senderId, text) {
  const requestBody = {
    recipient: { id: senderId },
    message: { text: text }
  };
  // 这里用你现有的HTTP请求方式(axios/fetch等)调用Messenger API
  axios.post('https://graph.facebook.com/v18.0/me/messages', requestBody, {
    params: { access_token: process.env.FB_PAGE_ACCESS_TOKEN }
  }).catch(err => console.error('发送消息失败:', err));
}

4. 生产环境的优化建议

  • 不要用内存Map存状态:服务器重启后数据会丢失,推荐用Redis(存状态)+ MongoDB(存用户数据)
  • 加入状态过期:如果用户很久没回复,可以自动重置对话状态
  • 完善输入验证:根据需求增加更严格的校验规则,避免无效数据
  • 处理异常情况:比如用户发送非文本消息(图片、语音),要给出友好提示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:33:20