Implementera en färdighet

GÄLLER FÖR: SDK v4

Du kan använda kunskaper för att utöka en annan robot. En färdighet är en robot som kan utföra en uppsättning uppgifter för en annan robot.

  • En färdighets gränssnitt beskrivs av ett manifest. Utvecklare som inte har åtkomst till kompetensens källkod kan använda informationen i manifestet för att utforma sin kompetenskonsument.
  • En färdighet kan använda anspråksverifiering för att hantera vilka robotar eller användare som kan komma åt den.

Den här artikeln visar hur du implementerar en färdighet som ekar användarens indata.

Vissa typer av kunskapskonsumenter kan inte använda vissa typer av kunskapsrobotar. I följande tabell beskrivs vilka kombinationer som stöds.

  Kompetens för flera klientorganisationer Kompetens för enskild klientorganisation Användartilldelad kompetens för hanterad identitet
Konsument för flera klientorganisationer Stöds Stöds inte Stöds inte
Enskild klientorganisationskonsument Stöds inte Stöds om båda apparna tillhör samma klientorganisation Stöds om båda apparna tillhör samma klientorganisation
Användartilldelad hanterad identitetskonsument Stöds inte Stöds om båda apparna tillhör samma klientorganisation Stöds om båda apparna tillhör samma klientorganisation

Kommentar

Bot Framework JavaScript-, C#- och Python-SDK:erna fortsätter att stödjas, men Java SDK dras tillbaka med slutligt långsiktigt stöd som slutar i november 2023.

Befintliga robotar som skapats med Java SDK fortsätter att fungera.

Om du vill skapa en ny robot bör du överväga att använda Power Virtual Agents och läsa om hur du väljer rätt chattrobotlösning.

Mer information finns i Framtiden för robotbygge.

Förutsättningar

Kommentar

Från och med version 4.11 behöver du inget app-ID och lösenord för att testa en färdighet lokalt i Bot Framework-emulatorn. En Azure-prenumeration krävs fortfarande för att distribuera dina kunskaper till Azure.

Om det här exemplet

Det enkla exemplet för robot-till-robot innehåller projekt för två robotar:

  • Den ekofärdighetsrobot som implementerar kunskapen.
  • Den enkla rotroboten, som implementerar en rotrobot som använder kunskapen.

Den här artikeln fokuserar på kunskapen, som innehåller supportlogik i roboten och adaptern.

Information om den enkla rotroboten finns i Implementera en kunskapskonsument.

Resurser

För distribuerade robotar kräver robot-till-robot-autentisering att varje deltagande robot har giltig identitetsinformation. Du kan dock testa kunskaper och kunskaper för flera klientorganisationer lokalt med emulatorn utan app-ID och lösenord.

Om du vill göra kunskapen tillgänglig för användarriktade robotar registrerar du kunskapen med Azure. Mer information finns i registrera en robot med Azure AI Bot Service.

Tillämpningskonfiguration

Du kan också lägga till kunskapens identitetsinformation i konfigurationsfilen. Om antingen kunskaps- eller kunskapskonsumenten tillhandahåller identitetsinformation måste båda två.

Den tillåtna uppringarens matris kan begränsa vilka kompetenskonsumenter som kan komma åt färdigheten. Lägg till ett "*"-element för att acceptera anrop från alla kunskapskonsumenter.

Kommentar

Om du testar din kompetens lokalt utan robotidentitetsinformation kör varken kunskapen eller kunskapskonsumenten koden för att utföra anspråksverifiering.

EchoSkillBot\appsettings.json

Du kan också lägga till kunskapens identitetsinformation i filen appsettings.json.

{
  "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": [ "*" ]
}

Logik för aktivitetshanterare

Så här accepterar du indataparametrar

Kunskapskonsumenten kan skicka information till kunskapen. Ett sätt att acceptera sådan information är att acceptera dem via värdeegenskapen för inkommande meddelanden. Ett annat sätt är att hantera händelser och anropa aktiviteter.

Färdigheten i det här exemplet accepterar inte indataparametrar.

Så här fortsätter eller slutför du en konversation

När färdigheten skickar en aktivitet ska kunskapskonsumenten vidarebefordra aktiviteten till användaren.

Du måste dock skicka en endOfConversation aktivitet när färdigheten är klar. Annars fortsätter kunskapskonsumenten att vidarebefordra användaraktiviteter till färdigheten. Du kan också använda aktivitetens värdeegenskap för att inkludera ett returvärde och använda aktivitetens kodegenskap för att ange varför färdigheten slutar.

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);
    }
}

Så här avbryter du färdigheten

För färdigheter med flera turer accepterar endOfConversation du också aktiviteter från en kunskapskonsument, så att konsumenten kan avbryta den aktuella konversationen.

Logiken för den här färdigheten ändras inte från tur till tur. Om du implementerar en färdighet som allokerar konversationsresurser lägger du till kod för resursrensning i hanteraren för konversationsslut.

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;
}

Anspråksverifierare

I det här exemplet används en lista över tillåtna anropare för anspråksverifiering. Listan definieras i kunskapens konfigurationsfil och läss in i validatorobjektet när den skapas.

Du måste lägga till en anspråksverifiering i autentiseringskonfigurationen. Anspråken utvärderas efter autentiseringshuvudet. Verifieringskoden bör utlösa ett fel eller ett undantag för att avvisa begäran. Det finns många orsaker till att du kanske vill avvisa en annars autentiserad begäran. Till exempel:

  • Färdigheten är en del av en betald tjänst. Användaren ska inte ha åtkomst till databasen.
  • Skickligheten är proprietär. Endast vissa kompetenskonsumenter kan kalla färdigheten.

Viktigt!

Om du inte anger någon anspråksverifierare genererar roboten ett fel eller undantag när du tar emot en aktivitet från kunskapskonsumenten.

SDK:t tillhandahåller en AllowedCallersClaimsValidator klass som lägger till auktorisering på programnivå baserat på en enkel lista över ID:er för de program som tillåts anropa kunskapen. Om listan innehåller en asterisk (*) tillåts alla anropare. Anspråksverifieraren har konfigurerats i Startup.cs.

Kunskapsadapter

När ett fel inträffar bör färdighetens kort rensa konversationstillståndet för färdigheten, och det bör också skicka en endOfConversation aktivitet till kunskapskonsumenten. Använd kodegenskapen för aktiviteten för att signalera att färdigheten avslutades på grund av ett fel.

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}");
    }
}

Tjänstregistrering

Bot Framework-adaptern använder ett autentiseringskonfigurationsobjekt (anges när adaptern skapas) för att verifiera autentiseringshuvudet för inkommande begäranden.

Det här exemplet lägger till anspråksvalidering i autentiseringskonfigurationen och använder kunskapskortet med felhanteraren som beskrivs i föregående avsnitt.

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>();

Färdighetsmanifest

Ett kunskapsmanifest är en JSON-fil som beskriver de aktiviteter som färdigheten kan utföra, dess indata- och utdataparametrar och kunskapens slutpunkter. Manifestet innehåller den information du behöver för att komma åt kunskapen från en annan robot. Den senaste schemaversionen är 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"
    }
  ]
}

Schemat för färdighetsmanifestet är en JSON-fil som beskriver schemat för färdighetsmanifestet. Den aktuella schemaversionen är 2.1.0.

Testa färdigheten

Nu kan du testa färdigheten i emulatorn som om det vore en vanlig robot. Men för att testa det som en färdighet skulle du behöva implementera en kunskapskonsument.

Ladda ned och installera den senaste Bot Framework-emulatorn

  1. Kör ekofärdighetsroboten lokalt på datorn. Om du behöver instruktioner kan du läsa README filen för exemplet C#, JavaScript, Java eller Python .
  2. Använd emulatorn för att testa roboten enligt nedan. När du skickar ett "slut" eller "stopp"-meddelande till färdigheten skickar det en endOfConversation aktivitet utöver svarsmeddelandet. Färdigheten endOfConversation skickar aktiviteten för att indikera att färdigheten har slutförts.

Exempelavskrift som visar aktiviteten för konversationens slut.

Mer om felsökning

Eftersom trafiken mellan kompetens och kunskapskonsumenter autentiseras finns det extra steg när du felsöker sådana robotar.

Annars kan du felsöka en kunskapskonsument eller färdighet ungefär som du felsöker andra robotar. Mer information finns i Felsöka en robot och felsöka med Bot Framework-emulatorn.

Nästa steg