如何用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
相关产品推荐
相关产品推荐

