Skip to main content

创建一个全功能的聊天机器人项目模板

分类:  Azure机器人 标签:  #Azure Bot Framework SDK #Azure Bot Service #机器人 发布于: 2023-08-07 22:43:39

我们前面的文章向大家展示了如何快速的写一个简单的聊天机器人,如果您还没有看过这篇文章,您可以使用如下的连接阅读:https://www.azuredeveloper.cn/article/hello-bot

需要说明的是,之前文章介绍的虽然是一个很简单的聊天机器人,但是它的应用场景不简单。它已经可以很好的满足很多场景下的聊天需求了,您需要需要做的仅仅是在Bot里添加更多或者集成的服务,用于满足更多场景:例如在BotOnMessageActivity的事件里添加更多的命令,保存每个用户的id和它和bot之间的conversationId,添加自然语言处理,或者问答系统。机器人的架构可以不用做任何更改,通过扩充和集成其他系统到Bot事件处理方法里,就可以提升和增加它的处理能力了。

相比于上一节我们介绍的"简单"机器人,我们本章先创建一个功能更为全面的机器人模板,后面的文章逐渐完善下述功能:

  • 给机器人会话添加上认证的功能。
  • 给机器人的会话和用户添加状态跟踪的机制
  • 使用卡片丰富Activity的通讯。
  • 使用Dialog系统丰富交互。

认证功能

实际上在我们echoBot中也集成了该功能,我们已经添加了必要的服务,但是并没有使用该功能,打开之前的项目可以在Program.cs文件里观察到:

builder.Services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();

我们今天介绍,之后我们开始介绍如何使用认证功能。

创建一个项目

创建项目之前,我们还是需要满足一些前提条件:

然后我们使用.Net CLi工具开始创建项目:

mkdire CoreBot
cd CoreBot
dotnew new webapi
dotnet add package Microsoft.Bot.Builder.Integration.AspNet.Core
dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson
mkdir Bots
mkdir Adapters

在目录Adapters里创建类:AdapterWithErrorHandler.cs

using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Bot.Builder.TraceExtensions;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.Extensions.Logging;

namespace CoreBot.Adapters;
public class AdapterWithErrorHandler : CloudAdapter
{
    public AdapterWithErrorHandler(BotFrameworkAuthentication auth, ILogger<IBotFrameworkHttpAdapter> logger)
        : base(auth, logger)
    {
        OnTurnError = async (turnContext, exception) =>
        {
            //向日志中记录来自Bot中的异常
            logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");

            // 发送消息通知用户有异常发生
            await turnContext.SendActivityAsync("The bot encountered an error or bug.");
            await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");

            //启用Activity trace, 如果使用模拟器调试可以看到详细的trace
            await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
        };
    }
}

在目录Bots里创建Bot类:TestBot.cs:

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;

namespace CoreBot.Bots;

public class TestBot : ActivityHandler
{
    protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
    {
        var replyText = $"Echo: {turnContext.Activity.Text}";
        await turnContext.SendActivityAsync(MessageFactory.Text(replyText, replyText), cancellationToken);
    }

    protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
    {
        var welcomeText = "Hello and welcome!";
        foreach (var member in membersAdded)
        {
            if (member.Id != turnContext.Activity.Recipient.Id)
            {
                await turnContext.SendActivityAsync(MessageFactory.Text(welcomeText, welcomeText), cancellationToken);
            }
        }
    }
}

在目录Controllers里添加BotController.cs:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Integration.AspNet.Core;

namespace CoreBot.Controllers;
[Route("api/messages")]
[ApiController]
public class BotController : ControllerBase
{
    private readonly IBotFrameworkHttpAdapter _adapter;
    private readonly IBot _bot;

    public BotController(IBotFrameworkHttpAdapter adapter, IBot bot)
    {
        _adapter = adapter;
        _bot = bot;
    }

    [HttpPost, HttpGet]
    public async Task PostAsync()
    {
        await _adapter.ProcessAsync(Request, Response, _bot);
    }
}

至此程序的基本框架已经完成了,剩下的是我们需要开始配置Program.cs了。

Program.cs

之所以要这个文件单独拿出来,是因为全功能Bot的配置几乎都在这个文件里了,我们先看内容:

using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Connector.Authentication;
using CoreBot.Adapters;
using CoreBot.Bots;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers().AddNewtonsoftJson(
    options =>
            {
                options.SerializerSettings.MaxDepth = HttpHelper.BotMessageSerializerSettings.MaxDepth;
            });

builder.Services.AddHttpClient();

builder.Services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();

builder.Services.AddSingleton<IStorage, MemoryStorage>();
builder.Services.AddSingleton<UserState>();
builder.Services.AddSingleton<ConversationState>();

builder.Services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
builder.Services.AddTransient<IBot, TestBot>();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

对比之前简单的Bot,我们会发现该项目中仅仅多了三行:

builder.Services.AddSingleton<IStorage, MemoryStorage>();
builder.Services.AddSingleton<UserState>();
builder.Services.AddSingleton<ConversationState>();

您可以像之前的测试来测试一下这个Bot, 至此我们已经创建了一个全功能的模板,后面几个章节都会以这个项目作为模板持续开发。