Dela via


Använda dialogrutor inom en kunskap

GÄLLER FÖR: SDK v4

Den här artikeln visar hur du skapar en färdighet som stöder flera åtgärder. Den stöder dessa åtgärder med hjälp av dialogrutor. Huvuddialogrutan tar emot de första indata från kunskapskonsumenten och startar sedan lämplig åtgärd. Information om hur du implementerar kunskapskonsumenten för den associerade exempelkoden finns i använda en färdighet med hjälp av dialogrutor.

Den här artikeln förutsätter att du redan är bekant med att skapa kunskaper. Mer information om hur du skapar en kunskapsrobot i allmänhet finns i hur du implementerar en färdighet.

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 kan du använda Microsoft Copilot Studio och läsa om hur du väljer rätt copilot-lösning.

Mer information finns i Framtiden för robotbygge.

Förutsättningar

Kommentar

Language Understanding (LUIS) dras tillbaka den 1 oktober 2025. Från och med den 1 april 2023 kan du inte skapa nya LUIS-resurser. En nyare version av språktolkning är nu tillgänglig som en del av Azure AI Language.

Conversational Language Understanding (CLU), en funktion i Azure AI Language, är den uppdaterade versionen av LUIS. Mer information om stöd för språktolkning i Bot Framework SDK finns i Förstå naturligt språk.

Om det här exemplet

Exemplet skills skillDialog innehåller projekt för två robotar:

  • Dialogrutans rotrobot, som använder en kunskapsdialogruta för att använda en färdighet.
  • Dialogrutans kunskapsrobot, som använder en dialogruta för att hantera aktiviteter som kommer från kunskapskonsumenter. Den här färdigheten är en anpassning av robotexemplet . (Mer information om kärnroboten finns i hur du lägger till förståelse för naturligt språk i din robot.)

Den här artikeln fokuserar på hur du använder en dialogruta i en kunskapsrobot för att hantera flera åtgärder.

Information om kunskapskonsumentroboten finns i hur du använder en färdighet med hjälp av dialogrutor.

Resurser

För distribuerade robotar kräver robot-till-robot-autentisering att varje deltagande robot har en giltig identitet. Du kan dock testa kunskaper och kunskapskonsumenter lokalt med Bot Framework-emulatorn utan identitetsinformation.

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.

Alternativt kan kunskapsroboten använda en LUIS-modell för flygbokning. Om du vill använda den här modellen använder du filen CognitiveModels/FlightBooking.json för att skapa, träna och publicera LUIS-modellen.

Tillämpningskonfiguration

  1. Du kan också lägga till kunskapens identitetsinformation i kunskapens konfigurationsfil. (Om antingen färdighets- eller färdighetskonsumenten anger en identitet måste båda två göra det.)

  2. Om du använder LUIS-modellen lägger du till LUIS-app-ID, API-nyckel och API-värdnamn.

DialogSkillBot\appsettings.json

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

  "LuisAppId": "",
  "LuisAPIKey": "",
  "LuisAPIHostName": "",

  // 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 aktivitetsroutning

Färdigheten har stöd för ett par olika funktioner. Det kan boka ett flyg eller få vädret för en stad. Om det dessutom tar emot ett meddelande utanför någon av dessa kontexter kan det använda LUIS för att försöka tolka meddelandet. Färdighetens manifest beskriver dessa åtgärder, deras indata- och utdataparametrar och färdighetens slutpunkter. Observera att färdigheten kan hantera en "BookFlight" eller "GetWeather"-händelse. Den kan också hantera meddelandeaktiviteter.

Färdigheten definierar en dialogruta för aktivitetsdirigering som används för att välja vilken åtgärd som ska initieras, baserat på den inledande inkommande aktiviteten från kunskapskonsumenten. Om det tillhandahålls kan LUIS-modellen identifiera avsikterna book-flight och get-weather i ett första meddelande.

Åtgärden book-flight är en process i flera steg som implementeras som en separat dialogruta. När åtgärden börjar hanteras inkommande aktiviteter av den dialogrutan. Åtgärden get-weather har platshållarlogik som skulle ersättas i en fullständigt implementerad robot.

Dialogrutan för aktivitetsroutning innehåller kod för att:

Dialogrutorna som används i kunskapen ärver från komponentdialogrutans klass. Mer information om komponentdialogrutor finns i hantera dialogkomplexitet.

Initiera dialogrutan

Dialogrutan för aktivitetsdirigering innehåller en underordnad dialogruta för att boka en flygning. Den huvudsakliga vattenfallsdialogrutan har ett steg som startar en åtgärd baserat på den första aktiviteten som togs emot.

Den accepterar också en LUIS-identifierare. Om den här identifieraren initieras använder dialogrutan den för att tolka avsikten med en inledande meddelandeaktivitet.

DialogSkillBot\Dialogs\ActivityRouterDialog.cs

private readonly DialogSkillBotRecognizer _luisRecognizer;

public ActivityRouterDialog(DialogSkillBotRecognizer luisRecognizer)
    : base(nameof(ActivityRouterDialog))
{
    _luisRecognizer = luisRecognizer;

    AddDialog(new BookingDialog());
    AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[] { ProcessActivityAsync }));

    // The initial child Dialog to run.
    InitialDialogId = nameof(WaterfallDialog);
}

Bearbeta en inledande aktivitet

I det första (och enda) steget i den huvudsakliga vattenfallsdialogrutan kontrollerar färdigheten den inkommande aktivitetstypen.

  • Händelseaktiviteter vidarebefordras till en händelseaktivitetshanterare som startar lämplig åtgärd baserat på namnet på händelsen.
  • Meddelandeaktiviteter vidarebefordras till en meddelandeaktivitetshanterare som utför ytterligare bearbetning innan du bestämmer vad du ska göra.

Om färdigheten inte känner igen typen av inkommande aktivitet eller namnet på händelsen skickar den ett felmeddelande och slutar.

DialogSkillBot\Dialogs\ActivityRouterDialog.cs

private async Task<DialogTurnResult> ProcessActivityAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // A skill can send trace activities, if needed.
    await stepContext.Context.TraceActivityAsync($"{GetType().Name}.ProcessActivityAsync()", label: $"Got ActivityType: {stepContext.Context.Activity.Type}", cancellationToken: cancellationToken);

    switch (stepContext.Context.Activity.Type)
    {
        case ActivityTypes.Event:
            return await OnEventActivityAsync(stepContext, cancellationToken);

        case ActivityTypes.Message:
            return await OnMessageActivityAsync(stepContext, cancellationToken);

        default:
            // We didn't get an activity type we can handle.
            await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Unrecognized ActivityType: \"{stepContext.Context.Activity.Type}\".", inputHint: InputHints.IgnoringInput), cancellationToken);
            return new DialogTurnResult(DialogTurnStatus.Complete);
    }
}
// This method performs different tasks based on the event name.
private async Task<DialogTurnResult> OnEventActivityAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activity = stepContext.Context.Activity;
    await stepContext.Context.TraceActivityAsync($"{GetType().Name}.OnEventActivityAsync()", label: $"Name: {activity.Name}. Value: {GetObjectAsJsonString(activity.Value)}", cancellationToken: cancellationToken);

    // Resolve what to execute based on the event name.
    switch (activity.Name)
    {
        case "BookFlight":
            return await BeginBookFlight(stepContext, cancellationToken);

        case "GetWeather":
            return await BeginGetWeather(stepContext, cancellationToken);

        default:
            // We didn't get an event name we can handle.
            await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Unrecognized EventName: \"{activity.Name}\".", inputHint: InputHints.IgnoringInput), cancellationToken);
            return new DialogTurnResult(DialogTurnStatus.Complete);
    }
}

Hantera meddelandeaktiviteter

Om LUIS-identifieraren har konfigurerats anropar färdigheten LUIS och startar sedan en åtgärd baserat på avsikten. Om LUIS-identifieraren inte har konfigurerats eller om avsikten inte stöds skickar färdigheten ett felmeddelande och slutar.

DialogSkillBot\Dialogs\ActivityRouterDialog.cs

// This method just gets a message activity and runs it through LUIS. 
private async Task<DialogTurnResult> OnMessageActivityAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activity = stepContext.Context.Activity;
    await stepContext.Context.TraceActivityAsync($"{GetType().Name}.OnMessageActivityAsync()", label: $"Text: \"{activity.Text}\". Value: {GetObjectAsJsonString(activity.Value)}", cancellationToken: cancellationToken);

    if (!_luisRecognizer.IsConfigured)
    {
        await stepContext.Context.SendActivityAsync(MessageFactory.Text("NOTE: LUIS is not configured. To enable all capabilities, add 'LuisAppId', 'LuisAPIKey' and 'LuisAPIHostName' to the appsettings.json file.", inputHint: InputHints.IgnoringInput), cancellationToken);
    }
    else
    {
        // Call LUIS with the utterance.
        var luisResult = await _luisRecognizer.RecognizeAsync<FlightBooking>(stepContext.Context, cancellationToken);

        // Create a message showing the LUIS results.
        var sb = new StringBuilder();
        sb.AppendLine($"LUIS results for \"{activity.Text}\":");
        var (intent, intentScore) = luisResult.Intents.FirstOrDefault(x => x.Value.Equals(luisResult.Intents.Values.Max()));
        sb.AppendLine($"Intent: \"{intent}\" Score: {intentScore.Score}");

        await stepContext.Context.SendActivityAsync(MessageFactory.Text(sb.ToString(), inputHint: InputHints.IgnoringInput), cancellationToken);

        // Start a dialog if we recognize the intent.
        switch (luisResult.TopIntent().intent)
        {
            case FlightBooking.Intent.BookFlight:
                return await BeginBookFlight(stepContext, cancellationToken);

            case FlightBooking.Intent.GetWeather:
                return await BeginGetWeather(stepContext, cancellationToken);

            default:
                // Catch all for unhandled intents.
                var didntUnderstandMessageText = $"Sorry, I didn't get that. Please try asking in a different way (intent was {luisResult.TopIntent().intent})";
                var didntUnderstandMessage = MessageFactory.Text(didntUnderstandMessageText, didntUnderstandMessageText, InputHints.IgnoringInput);
                await stepContext.Context.SendActivityAsync(didntUnderstandMessage, cancellationToken);
                break;
        }
    }

    return new DialogTurnResult(DialogTurnStatus.Complete);
}

Påbörja en åtgärd i flera steg

Åtgärden book-flight startar en dialogruta i flera steg för att hämta bokningsinformationen från användaren.

Åtgärden get-weather implementeras inte. För närvarande skickar den ett platshållarmeddelande och slutar sedan.

DialogSkillBot\Dialogs\ActivityRouterDialog.cs

private async Task<DialogTurnResult> BeginBookFlight(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activity = stepContext.Context.Activity;
    var bookingDetails = new BookingDetails();
    if (activity.Value != null)
    {
        bookingDetails = JsonConvert.DeserializeObject<BookingDetails>(JsonConvert.SerializeObject(activity.Value));
    }

    // Start the booking dialog.
    var bookingDialog = FindDialog(nameof(BookingDialog));
    return await stepContext.BeginDialogAsync(bookingDialog.Id, bookingDetails, cancellationToken);
}
private static async Task<DialogTurnResult> BeginGetWeather(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activity = stepContext.Context.Activity;
    var location = new Location();
    if (activity.Value != null)
    {
        location = JsonConvert.DeserializeObject<Location>(JsonConvert.SerializeObject(activity.Value));
    }

    // We haven't implemented the GetWeatherDialog so we just display a TODO message.
    var getWeatherMessageText = $"TODO: get weather for here (lat: {location.Latitude}, long: {location.Longitude}";
    var getWeatherMessage = MessageFactory.Text(getWeatherMessageText, getWeatherMessageText, InputHints.IgnoringInput);
    await stepContext.Context.SendActivityAsync(getWeatherMessage, cancellationToken);
    return new DialogTurnResult(DialogTurnStatus.Complete);
}

Returnera ett resultat

Färdigheten startar en bokningsdialogruta för book-flight-åtgärden. Eftersom dialogrutan för aktivitetsroutning bara har ett steg avslutas även dialogrutan aktivitetsroutning när bokningsdialogrutan avslutas, och dialogrutans resultat från bokningsdialogrutan blir dialogresultatet för dialogrutan för aktivitetsroutning.

Åtgärden get-weather slutar helt enkelt utan att ange ett returvärde.

Avbryta en åtgärd i flera steg

Bokningsdialogrutan och dess underordnade date-resolver-dialogruta härleds båda från den grundläggande dialogrutan cancel-and-help, som kontrollerar meddelanden från användaren.

  • På "hjälp" eller "?", visas ett hjälpmeddelande och fortsätter sedan konversationsflödet på följande tur.
  • Vid "avbryt" eller "avsluta" avbryts alla dialogrutor, vilket avslutar färdigheten.

Mer information finns i hantera användaravbrott.

Tjänstregistrering

De tjänster som behövs för den här kompetensen är desamma som de som behövs för en kunskapsrobot i allmänhet. Se hur du implementerar en färdighet för en diskussion om de tjänster som krävs.

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.

DialogSkillBot\wwwroot\manifest\dialogchildbot-manifest-1.0.json

{
  "$schema": "https://schemas.botframework.com/schemas/skills/skill-manifest-2.0.0.json",
  "$id": "DialogSkillBot",
  "name": "Skill bot with dialogs",
  "version": "1.0",
  "description": "This is a sample skill definition for multiple activity types.",
  "publisherName": "Microsoft",
  "privacyUrl": "https://dialogskillbot.contoso.com/privacy.html",
  "copyright": "Copyright (c) Microsoft Corporation. All rights reserved.",
  "license": "",
  "iconUrl": "https://dialogskillbot.contoso.com/icon.png",
  "tags": [
    "sample",
    "travel",
    "weather",
    "luis"
  ],
  "endpoints": [
    {
      "name": "default",
      "protocol": "BotFrameworkV3",
      "description": "Default endpoint for the skill.",
      "endpointUrl": "https://dialogskillbot.contoso.com/api/messages",
      "msAppId": "00000000-0000-0000-0000-000000000000"
    }
  ],
  "activities": {
    "bookFlight": {
      "description": "Books a flight (multi turn).",
      "type": "event",
      "name": "BookFlight",
      "value": {
        "$ref": "#/definitions/bookingInfo"
      },
      "resultValue": {
        "$ref": "#/definitions/bookingInfo"
      }
    },
    "getWeather": {
      "description": "Retrieves and returns the weather for the user's location.",
      "type": "event",
      "name": "GetWeather",
      "value": {
        "$ref": "#/definitions/location"
      },
      "resultValue": {
        "$ref": "#/definitions/weatherReport"
      }
    },
    "passthroughMessage": {
      "type": "message",
      "description": "Receives the user's utterance and attempts to resolve it using the skill's LUIS models.",
      "value": {
        "type": "object"
      }
    }
  },
  "definitions": {
    "bookingInfo": {
      "type": "object",
      "required": [
        "origin"
      ],
      "properties": {
        "origin": {
          "type": "string",
          "description": "This is the origin city for the flight."
        },
        "destination": {
          "type": "string",
          "description": "This is the destination city for the flight."
        },
        "travelDate": {
          "type": "string",
          "description": "The date for the flight in YYYY-MM-DD format."
        }
      }
    },
    "weatherReport": {
      "type": "array",
      "description": "Array of forecasts for the next week.",
      "items": [
        {
          "type": "string"
        }
      ]
    },
    "location": {
      "type": "object",
      "description": "Location metadata.",
      "properties": {
        "latitude": {
          "type": "number",
          "title": "Latitude"
        },
        "longitude": {
          "type": "number",
          "title": "Longitude"
        },
        "postalCode": {
          "type": "string",
          "title": "Postal code"
        }
      }
    }
  }
}

Schemat för färdighetsmanifestet är en JSON-fil som beskriver schemat för färdighetsmanifestet. Den senaste schemaversionen är v2.1.

Testa kunskapsroboten

Du kan testa kunskapen i emulatorn med kunskapskonsumenten. För att göra det måste du köra både kunskaps- och kunskapsrobotarna på samma gång. Se hur du använder en dialogruta för att använda en färdighet för information om hur du konfigurerar kunskapen.

Ladda ned och installera den senaste Bot Framework-emulatorn.

  1. Kör dialogrutans kunskapsrobot och dialogrotrobot lokalt på datorn. Om du behöver instruktioner kan du läsa exempelfilen README för C#, JavaScript, Java eller Python.
  2. Använd emulatorn för att testa roboten.
    • När du först ansluter till konversationen visar roboten ett välkomstmeddelande och frågar dig vilken färdighet du vill ringa. Kunskapsroboten för det här exemplet har bara en färdighet.
    • Välj DialogSkillBot.
  3. Därefter ber roboten dig att välja en åtgärd för färdigheten. Välj "BookFlight".
    1. Skickligheten börjar sin bokflygåtgärd; besvara anvisningarna.
    2. När kunskapen har slutförts visar rotroboten bokningsinformationen innan du frågar igen om den färdighet du vill anropa.
  4. Välj DialogSkillBot igen och "BookFlight".
    1. Svara på den första uppmaningen och ange sedan "avbryt" för att avbryta åtgärden.
    2. Kunskapsroboten slutar utan att slutföra åtgärden, och konsumenten frågar efter den färdighet du vill anropa.

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.

Ytterligare information