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

如何用Node.js在Bot Emulator启动时加载SQL Server中的历史对话?

实现Node.js Bot在Emulator启动时加载SQL Server历史对话记录

我来一步步帮你搞定这个需求,核心思路就是从SQL Server读取历史对话数据,转换成Bot Framework能识别的格式,再在Emulator连接会话时把这些历史消息“还原”出来,让用户能无缝衔接之前的对话。

1. 安装必要依赖

首先得搞定Node.js和SQL Server的连接,以及Bot Framework的核心工具,直接装这两个包就行:

npm install mssql botbuilder restify

2. 配置SQL Server连接

先写个数据库连接模块db-connection.js,专门处理和SQL Server的连接逻辑:

const sql = require('mssql');

// 替换成你的SQL Server配置
const sqlConfig = {
    user: '你的SQL用户名',
    password: '你的SQL密码',
    server: 'localhost', // 比如本地服务器地址
    database: '你的对话记录数据库名',
    options: {
        encrypt: false, // 本地测试一般关,Azure SQL需要开
        trustServerCertificate: true // 本地测试可开启,生产环境不建议
    }
};

async function getSqlPool() {
    try {
        const pool = await sql.connect(sqlConfig);
        return pool;
    } catch (err) {
        console.error('SQL连接失败:', err);
        throw err;
    }
}

module.exports = { getSqlPool };

3. 编写历史对话查询逻辑

创建conversation-history.js模块,负责从SQL读取并转换历史对话:

const { getSqlPool } = require('./db-connection');

async function fetchHistoryByConversationId(conversationId) {
    const pool = await getSqlPool();
    try {
        // 假设你的对话表名为ConversationLogs,字段和Bot Activity结构对应
        const result = await pool.request()
            .input('conversationId', sql.NVarChar, conversationId)
            .query(`SELECT * FROM ConversationLogs 
                    WHERE conversationId = @conversationId 
                    ORDER BY timestamp ASC`);

        // 把SQL记录转换成Bot标准的Activity对象
        return result.recordset.map(record => ({
            type: record.type || 'message',
            id: record.activityId,
            conversation: { id: record.conversationId },
            from: { id: record.fromId, name: record.fromName },
            recipient: { id: record.recipientId, name: record.recipientName },
            text: record.text,
            timestamp: new Date(record.timestamp),
            channelId: 'emulator' // 指定为Emulator渠道,确保显示正确
        }));
    } finally {
        await pool.close();
    }
}

module.exports = { fetchHistoryByConversationId };

⚠️ 注意:如果你的SQL表结构和Bot Activity字段不匹配,要调整查询和转换逻辑,保证输出是标准的Activity对象,否则Emulator没法正确渲染消息。

4. 在Bot中加载并发送历史记录

修改你的Bot主文件bot.js,在会话启动时(比如Emulator连接、用户发第一条消息时)加载历史并发送:

const { ActivityHandler } = require('botbuilder');
const { fetchHistoryByConversationId } = require('./conversation-history');

class HistoryLoadedBot extends ActivityHandler {
    constructor() {
        super();

        // 处理会话更新事件(Emulator连接时触发)
        this.onConversationUpdate(async (context, next) => {
            const conversationState = context.turnState.get('ConversationState');
            const botState = await conversationState.createProperty('BotSessionState').get(context, {});

            // 只有第一次启动会话时加载历史,避免重复发送
            if (!botState.historyLoaded && context.activity.membersAdded.some(m => m.id === context.activity.recipient.id)) {
                const conversationId = context.activity.conversation.id;
                const historyLogs = await fetchHistoryByConversationId(conversationId);

                // 逐条发送历史消息到Emulator
                for (const activity of historyLogs) {
                    await context.sendActivity(activity);
                }

                // 标记历史已加载
                botState.historyLoaded = true;
                await conversationState.saveChanges(context);
            }
            await next();
        });

        // 处理用户实时消息
        this.onMessage(async (context, next) => {
            await context.sendActivity(`收到你的消息:${context.activity.text}`);
            await next();
        });
    }
}

module.exports.HistoryLoadedBot = HistoryLoadedBot;

5. 配置会话状态管理

在入口文件index.js中,配置ConversationState来跟踪历史是否已加载,避免重复发送:

const { BotFrameworkAdapter, ConversationState, MemoryStorage } = require('botbuilder');
const { HistoryLoadedBot } = require('./bot');
const restify = require('restify');

// 创建服务器
const server = restify.createServer();
server.listen(process.env.PORT || 3978, () => {
    console.log(`\n${server.name} 运行在 ${server.url}`);
});

// 创建Bot适配器
const adapter = new BotFrameworkAdapter({
    appId: process.env.MICROSOFT_APP_ID || '',
    appPassword: process.env.MICROSOFT_APP_PASSWORD || ''
});

// 用内存存储会话状态(生产环境建议用Azure Blob/SQL存储)
const memoryStorage = new MemoryStorage();
const conversationState = new ConversationState(memoryStorage);

// 初始化Bot
const bot = new HistoryLoadedBot();

// 处理消息请求
server.post('/api/messages', (req, res) => {
    adapter.processActivity(req, res, async (context) => {
        context.turnState.set('ConversationState', conversationState);
        await bot.run(context);
    });
});

关键注意事项

  • 会话ID匹配:Emulator每次重启可能生成新会话ID,如果想加载特定用户的历史,建议用用户ID筛选,或者在Emulator设置中固定会话ID。
  • 性能优化:如果历史记录很多,不要一次性全发,可以分页加载最近的N条,避免Emulator卡顿。
  • 数据一致性:确保SQL中存储的对话记录和Bot Activity结构一致,尤其是from、recipient、timestamp这些核心字段,否则消息显示会错乱。

这样配置后,启动Bot再打开Emulator连接,就能自动看到SQL Server里存储的过往对话记录了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:20:10