Dialogflow如何捕获完整用户输入 存储会话至Firebase Firestore
Dialogflow Fulfillment 存储全量会话记录到Firestore实现方案
完全可以通过内置的Cloud Functions for Firebase(即inline editor中的fulfillment逻辑)实现,不需要额外部署服务,三个所需字段都可以从webhook请求体和fulfillment实例中直接获取,具体实现方式如下:
核心字段获取方式
所有字段不需要额外调用Dialogflow API,直接从webhook的请求上下文里就能取到:
- 用户ID:Telegram渠道的用户唯一ID存放在原始请求载荷中,路径为
request.body.originalDetectIntentRequest.payload.data.from.id,该ID是Telegram侧生成的固定用户标识,不会随会话变化。如果需要关联同一会话的所有消息,可以同时取request.body.session字段,截取最后一段即为会话唯一ID。 - 用户输入完整原始消息:不要取
queryResult.parameters(该字段是Dialogflow提取后的结构化参数,不是用户输入原文),直接取request.body.queryResult.queryText即可,该字段是用户发送的完整原始文本内容。 - 机器人返回完整消息:如果是Dialogflow控制台配置的静态响应,取
request.body.queryResult.fulfillmentMessages即可,该字段是Dialogflow预设的全量返回内容,包含文本、按钮、卡片所有结构;如果是在fulfillment中通过agent.add()动态构造的响应,取agent.responseMessages_即可,该属性是fulfillment库合并完成后即将返回给渠道的最终内容,不会遗漏动态添加的回复。
可直接运行的代码示例
inline editor默认使用Node.js环境,以下代码可以直接替换原有inline editor内容,注意不要把存库逻辑绑定到单个intent handler上,通过全局中间件注册可以保证所有intent触发时都能执行存库,不会遗漏无自定义handler的意图:
'use strict'; const functions = require('firebase-functions'); const {WebhookClient} = require('dialogflow-fulfillment'); const admin = require('firebase-admin'); admin.initializeApp(); const db = admin.firestore(); exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => { const agent = new WebhookClient({ request, response }); // 全局存库中间件,所有intent匹配后都会自动执行 const saveChatLog = async (agent) => { try { // 提取所需字段 const telegramPayload = request.body.originalDetectIntentRequest.payload.data; const userId = telegramPayload.from.id; const sessionId = request.body.session.split('/').pop(); const userRawMsg = request.body.queryResult.queryText; // 优先取动态构造的响应,没有则取控制台配置的静态响应 const botFullResponse = agent.responseMessages_.length ? agent.responseMessages_ : request.body.queryResult.fulfillmentMessages; // 写入Firestore await db.collection('chatLogs').add({ userId: String(userId), sessionId: sessionId, userInput: userRawMsg, botReply: botFullResponse, matchIntent: request.body.queryResult.intent.displayName, createTime: admin.firestore.FieldValue.serverTimestamp() }); } catch (err) { // 捕获存库异常,避免存库失败导致机器人无法正常回复 console.error('聊天记录存储失败:', err); } }; // 以下为原有业务逻辑,不需要修改 function welcomeHandler(agent) { agent.add('你好,有什么可以帮你的?'); } const intentMap = new Map(); intentMap.set('Default Welcome Intent', welcomeHandler); // 其余intent映射按原有逻辑添加即可 // 注册中间件,所有请求优先执行存库逻辑 agent.handleRequest(intentMap, [saveChatLog]); });
注意事项
- 如果机器人支持接收图片、语音、文件等非文本消息,文本字段
queryText不会存储这类内容,直接将telegramPayload(即originalDetectIntentRequest.payload.data)整体存入数据库即可,该结构和Telegram Bot API返回的Message结构完全一致,包含所有非文本消息的元信息和资源ID。 - 存库逻辑必须加异常捕获,不要让数据库操作的阻塞或错误影响正常的消息回复流程,生产环境可以根据需要调整Firestore集合的拆分规则,比如按用户ID、按月份分集合降低单集合数据量。
- 如果需要排查会话上下文问题,可以额外存储
request.body.queryResult.outputContexts字段,该字段包含当前会话的所有上下文参数和生命周期信息。
内容的提问来源于stack exchange,提问作者andrea1493
相关产品推荐
相关产品推荐

