Een vaardigheid implementeren

VAN TOEPASSING OP: SDK v4

U kunt vaardigheden gebruiken om een andere bot uit te breiden. Een vaardigheid is een bot die een set taken voor een andere bot kan uitvoeren.

  • De interface van een vaardigheid wordt beschreven door een manifest. Ontwikkelaars die geen toegang hebben tot de broncode van de vaardigheid, kunnen de informatie in het manifest gebruiken om hun vaardigheidsgebruiker te ontwerpen.
  • Een vaardigheid kan claimvalidatie gebruiken om te beheren welke bots of gebruikers er toegang toe hebben.

In dit artikel wordt uitgelegd hoe u een vaardigheid implementeert die de invoer van de gebruiker weergeeft.

Sommige typen vaardigheidsgebruikers kunnen bepaalde typen vaardigheidsbots niet gebruiken. In de volgende tabel wordt beschreven welke combinaties worden ondersteund.

  Vaardigheid voor meerdere tenants Vaardigheid met één tenant Door de gebruiker toegewezen vaardigheden voor beheerde identiteit
Consument met meerdere tenants Ondersteund Niet ondersteund Niet ondersteund
Consument met één tenant Niet ondersteund Ondersteund als beide apps deel uitmaken van dezelfde tenant Ondersteund als beide apps deel uitmaken van dezelfde tenant
Door de gebruiker toegewezen beheerde identiteitgebruiker Niet ondersteund Ondersteund als beide apps deel uitmaken van dezelfde tenant Ondersteund als beide apps deel uitmaken van dezelfde tenant

Notitie

De Sdk's voor Bot Framework JavaScript, C# en Python blijven ondersteund, maar de Java SDK wordt buiten gebruik gesteld met definitieve langetermijnondersteuning die eindigt op november 2023.

Bestaande bots die zijn gebouwd met de Java SDK blijven functioneren.

Voor het bouwen van nieuwe bots kunt u Power Virtual Agents gebruiken en lezen over het kiezen van de juiste chatbotoplossing.

Zie De toekomst van botbouw voor meer informatie.

Vereisten

Notitie

Vanaf versie 4.11 hebt u geen app-id en wachtwoord nodig om een vaardigheid lokaal te testen in de Bot Framework Emulator. Er is nog steeds een Azure-abonnement vereist om uw vaardigheid in Azure te implementeren.

Over dit voorbeeld

Het eenvoudige bot-naar-bot-voorbeeld bevat projecten voor twee bots:

  • De bot met echovaardigheden, waarmee de vaardigheid wordt geïmplementeerd.
  • De eenvoudige hoofdbot, waarmee een hoofdbot wordt geïmplementeerd die de vaardigheid verbruikt.

Dit artikel is gericht op de vaardigheid, die ondersteuningslogica bevat in de bot en adapter.

Zie voor informatie over de eenvoudige hoofdbot hoe u een vaardigheidsconsumer implementeert.

Resources

Voor geïmplementeerde bots is verificatie van bot-naar-bot vereist dat elke deelnemende bot geldige identiteitsgegevens heeft. U kunt echter gebruikers met meerdere tenants lokaal testen met de emulator zonder app-id en wachtwoord.

Registreer de vaardigheid bij Azure om de vaardigheid beschikbaar te maken voor gebruikersgerichte bots. Zie voor meer informatie hoe u een bot registreert bij Azure AI Bot Service.

Toepassingsconfiguratie

Voeg eventueel de identiteitsgegevens van de vaardigheid toe aan het configuratiebestand. Als de gebruiker van de vaardigheid of vaardigheid identiteitsinformatie verstrekt, moeten beide informatie bevatten.

De matrix met toegestane bellers kan beperken welke vaardigheidsgebruikers toegang hebben tot de vaardigheid. Voeg een *-element toe om oproepen van elke vaardigheidsconsumer te accepteren.

Notitie

Als u uw vaardigheid lokaal test zonder botidentiteitsgegevens, voert noch de vaardigheid noch de gebruiker van de vaardigheid de code uit om claimvalidatie uit te voeren.

EchoSkillBot\appsettings.json

Voeg desgewenst de identiteitsgegevens van de vaardigheid toe aan het appsettings.json-bestand.

{
  "MicrosoftAppType": "",
  "MicrosoftAppId": "",
  "MicrosoftAppPassword": "",
  "MicrosoftAppTenantId": "",

  // This is a comma separate list with the App IDs that will have access to the skill.
  // This setting is used in AllowedCallersClaimsValidator.
  // Examples: 
  //    [ "*" ] allows all callers.
  //    [ "AppId1", "AppId2" ] only allows access to parent bots with "AppId1" and "AppId2".
  "AllowedCallers": [ "*" ]
}

Logica voor activiteitshandler

Invoerparameters accepteren

De gebruiker van de vaardigheid kan informatie naar de vaardigheid verzenden. Een manier om dergelijke informatie te accepteren, is door deze te accepteren via de waarde-eigenschap voor binnenkomende berichten. Een andere manier is om gebeurtenissen te verwerken en activiteiten aan te roepen.

De vaardigheid in dit voorbeeld accepteert geen invoerparameters.

Een gesprek voortzetten of voltooien

Wanneer de vaardigheid een activiteit verzendt, moet de gebruiker van de vaardigheid de activiteit doorsturen naar de gebruiker.

U moet echter een endOfConversation activiteit verzenden wanneer de vaardigheid is voltooid. Anders blijft de gebruiker van de vaardigheid gebruikersactiviteiten doorsturen naar de vaardigheid. U kunt eventueel de waarde-eigenschap van de activiteit gebruiken om een retourwaarde op te nemen en de code-eigenschap van de activiteit gebruiken om aan te geven waarom de vaardigheid eindigt.

EchoSkillBot\Bots\EchoBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    if (turnContext.Activity.Text.Contains("end") || turnContext.Activity.Text.Contains("stop"))
    {
        // Send End of conversation at the end.
        var messageText = $"ending conversation from the skill...";
        await turnContext.SendActivityAsync(MessageFactory.Text(messageText, messageText, InputHints.IgnoringInput), cancellationToken);
        var endOfConversation = Activity.CreateEndOfConversationActivity();
        endOfConversation.Code = EndOfConversationCodes.CompletedSuccessfully;
        await turnContext.SendActivityAsync(endOfConversation, cancellationToken);
    }
    else
    {
        var messageText = $"Echo: {turnContext.Activity.Text}";
        await turnContext.SendActivityAsync(MessageFactory.Text(messageText, messageText, InputHints.IgnoringInput), cancellationToken);
        messageText = "Say \"end\" or \"stop\" and I'll end the conversation and back to the parent.";
        await turnContext.SendActivityAsync(MessageFactory.Text(messageText, messageText, InputHints.ExpectingInput), cancellationToken);
    }
}

De vaardigheid annuleren

Voor vaardigheden met meerdere paden accepteert endOfConversation u ook activiteiten van een vaardigheidsconsumer, zodat de consument het huidige gesprek kan annuleren.

De logica voor deze vaardigheid verandert niet van turn-to-turn. Als u een vaardigheid implementeert die gespreksresources toewijst, voegt u code voor het opschonen van resources toe aan de handler voor het einde van het gesprek.

EchoSkillBot\Bots\EchoBot.cs

protected override Task OnEndOfConversationActivityAsync(ITurnContext<IEndOfConversationActivity> turnContext, CancellationToken cancellationToken)
{
    // This will be called if the root bot is ending the conversation.  Sending additional messages should be
    // avoided as the conversation may have been deleted.
    // Perform cleanup of resources if needed.
    return Task.CompletedTask;
}

Claimvalidatie

In dit voorbeeld wordt een lijst met toegestane bellers gebruikt voor claimvalidatie. De lijst wordt gedefinieerd in het configuratiebestand van de vaardigheid en wordt ingelezen in het validatieobject wanneer deze wordt gemaakt.

U moet een claimvalidator toevoegen aan de verificatieconfiguratie. De claims worden geëvalueerd na de verificatieheader. Uw validatiecode moet een fout of uitzondering genereren om de aanvraag te weigeren. Er zijn veel redenen waarom u een anderszins geverifieerde aanvraag wilt weigeren. Voorbeeld:

  • De vaardigheid maakt deel uit van een betaalde service. De gebruiker mag geen toegang hebben tot de database.
  • De vaardigheid is eigendom. Alleen bepaalde vaardigheidsconsumenten kunnen de vaardigheid aanroepen.

Belangrijk

Als u geen claimvalidator opgeeft, genereert uw bot een fout of uitzondering bij het ontvangen van een activiteit van de vaardigheidsconsumer.

De SDK biedt een AllowedCallersClaimsValidator klasse waarmee autorisatie op toepassingsniveau wordt toegevoegd op basis van een eenvoudige lijst met id's van de toepassingen die de vaardigheid mogen aanroepen. Als de lijst een sterretje (*) bevat, zijn alle bellers toegestaan. De claimvalidator is geconfigureerd in Startup.cs.

Vaardigheidsadapter

Wanneer er een fout optreedt, moet de adapter van de vaardigheid de gespreksstatus voor de vaardigheid wissen en moet deze ook een endOfConversation activiteit naar de gebruiker van de vaardigheid verzenden. Gebruik de code-eigenschap van de activiteit om aan te geven dat de vaardigheid is beëindigd vanwege een fout.

EchoSkillBot\SkillAdapterWithErrorHandler.cs

private async Task HandleTurnError(ITurnContext turnContext, Exception exception)
{
    // Log any leaked exception from the application.
    _logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");

    await SendErrorMessageAsync(turnContext, exception);
    await SendEoCToParentAsync(turnContext, exception);
}

private async Task SendErrorMessageAsync(ITurnContext turnContext, Exception exception)
{
    try
    {
        // Send a message to the user.
        var errorMessageText = "The skill encountered an error or bug.";
        var errorMessage = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.IgnoringInput);
        await turnContext.SendActivityAsync(errorMessage);

        errorMessageText = "To continue to run this bot, please fix the bot source code.";
        errorMessage = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.ExpectingInput);
        await turnContext.SendActivityAsync(errorMessage);

        // Send a trace activity, which will be displayed in the Bot Framework Emulator.
        // Note: we return the entire exception in the value property to help the developer;
        // this should not be done in production.
        await turnContext.TraceActivityAsync("OnTurnError Trace", exception.ToString(), "https://www.botframework.com/schemas/error", "TurnError");
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, $"Exception caught in SendErrorMessageAsync : {ex}");
    }
}

private async Task SendEoCToParentAsync(ITurnContext turnContext, Exception exception)
{
    try
    {
        // Send an EndOfConversation activity to the skill caller with the error to end the conversation,
        // and let the caller decide what to do.
        var endOfConversation = Activity.CreateEndOfConversationActivity();
        endOfConversation.Code = "SkillError";
        endOfConversation.Text = exception.Message;
        await turnContext.SendActivityAsync(endOfConversation);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, $"Exception caught in SendEoCToParentAsync : {ex}");
    }
}

Serviceregistratie

De Bot Framework-adapter maakt gebruik van een verificatieconfiguratieobject (ingesteld wanneer de adapter wordt gemaakt) om de verificatieheader voor binnenkomende aanvragen te valideren.

In dit voorbeeld wordt claimsvalidatie toegevoegd aan de verificatieconfiguratie en wordt de vaardigheidsadapter gebruikt met de fouthandler die in de vorige sectie is beschreven.

EchoSkillBot\Startup.cs

    options.SerializerSettings.MaxDepth = HttpHelper.BotMessageSerializerSettings.MaxDepth;
});

// Register AuthConfiguration to enable custom claim validation.
services.AddSingleton(sp =>
{
    var allowedCallers = new List<string>(sp.GetService<IConfiguration>().GetSection("AllowedCallers").Get<string[]>());

    var claimsValidator = new AllowedCallersClaimsValidator(allowedCallers);

    // If TenantId is specified in config, add the tenant as a valid JWT token issuer for Bot to Skill conversation.
    // The token issuer for MSI and single tenant scenarios will be the tenant where the bot is registered.
    var validTokenIssuers = new List<string>();
    var tenantId = sp.GetService<IConfiguration>().GetSection(MicrosoftAppCredentials.MicrosoftAppTenantIdKey)?.Value;

    if (!string.IsNullOrWhiteSpace(tenantId))
    {
        // For SingleTenant/MSI auth, the JWT tokens will be issued from the bot's home tenant.
        // Therefore, these issuers need to be added to the list of valid token issuers for authenticating activity requests.
        validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidTokenIssuerUrlTemplateV1, tenantId));
        validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidTokenIssuerUrlTemplateV2, tenantId));
        validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidGovernmentTokenIssuerUrlTemplateV1, tenantId));
        validTokenIssuers.Add(string.Format(CultureInfo.InvariantCulture, AuthenticationConstants.ValidGovernmentTokenIssuerUrlTemplateV2, tenantId));
    }

    return new AuthenticationConfiguration
    {
        ClaimsValidator = claimsValidator,
        ValidTokenIssuers = validTokenIssuers
    };
});

// Create the Bot Framework Authentication to be used with the Bot Adapter.
services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();

Vaardigheidsmanifest

Een vaardigheidsmanifest is een JSON-bestand dat de activiteiten beschrijft die de vaardigheid kan uitvoeren, de invoer- en uitvoerparameters en de eindpunten van de vaardigheid. Het manifest bevat de informatie die u nodig hebt om toegang te krijgen tot de vaardigheid van een andere bot. De nieuwste schemaversie is v2.1.

EchoSkillBot\wwwroot\manifest\echoskillbot-manifest-1.0.json

{
  "$schema": "https://schemas.botframework.com/schemas/skills/skill-manifest-2.0.0.json",
  "$id": "EchoSkillBot",
  "name": "Echo Skill bot",
  "version": "1.0",
  "description": "This is a sample echo skill",
  "publisherName": "Microsoft",
  "privacyUrl": "https://echoskillbot.contoso.com/privacy.html",
  "copyright": "Copyright (c) Microsoft Corporation. All rights reserved.",
  "license": "",
  "iconUrl": "https://echoskillbot.contoso.com/icon.png",
  "tags": [
    "sample",
    "echo"
  ],
  "endpoints": [
    {
      "name": "default",
      "protocol": "BotFrameworkV3",
      "description": "Default endpoint for the skill",
      "endpointUrl": "http://echoskillbot.contoso.com/api/messages",
      "msAppId": "00000000-0000-0000-0000-000000000000"
    }
  ]
}

Het manifestschema voor vaardigheden is een JSON-bestand dat het schema van het vaardigheidsmanifest beschrijft. De huidige schemaversie is 2.1.0.

De vaardigheid testen

Op dit moment kunt u de vaardigheid in de emulator testen alsof het een normale bot is. Als u het echter als vaardigheid wilt testen, moet u een vaardigheidsconsumer implementeren.

De nieuwste Bot Framework Emulator downloaden en installeren

  1. Voer de bot voor echovaardigheden lokaal uit op uw computer. Als u instructies nodig hebt, raadpleegt u het bestand voor het READMEC#-, JavaScript-, Java- of Python-voorbeeld.
  2. Gebruik de emulator om de bot te testen zoals hieronder wordt weergegeven. Wanneer u een 'end' of 'stop'-bericht naar de vaardigheid verzendt, wordt er een endOfConversation activiteit verzonden naast het antwoordbericht. De vaardigheid verzendt de endOfConversation activiteit om aan te geven dat de vaardigheid is voltooid.

Voorbeeldtranscriptie met de activiteit einde van gesprek.

Meer informatie over foutopsporing

Omdat verkeer tussen vaardigheden en vaardigheidsgebruikers wordt geverifieerd, zijn er extra stappen bij het opsporen van fouten in dergelijke bots.

Anders kunt u fouten opsporen in een vaardigheidsconsumer of vaardigheid, net zoals bij het opsporen van fouten in andere bots. Zie Fouten opsporen in een bot en fouten opsporen met de Bot Framework Emulator voor meer informatie.

Volgende stappen