Použití dialogů v rámci dovednosti

PLATÍ PRO: SDK v4

Tento článek ukazuje, jak vytvořit dovednost, která podporuje více akcí. Podporuje tyto akce pomocí dialogových oken. Hlavní dialog obdrží počáteční vstup od příjemce dovednosti a pak zahájí příslušnou akci. Informace o implementaci příjemce dovedností pro přidružený vzorový kód najdete v tématu využití dovednosti pomocí dialogových oken.

Tento článek předpokládá, že už máte zkušenosti s vytvářením dovedností. Pokud chcete vytvořit robota dovedností obecně, podívejte se , jak implementovat dovednost.

Poznámka:

Sady SDK služby Bot Framework JavaScript, C# a Python budou nadále podporovány, ale sada Java SDK se vyřazuje s konečnou dlouhodobou podporou končící v listopadu 2023.

Stávající roboti sestavení pomocí sady Java SDK budou i nadále fungovat.

Při vytváření nových robotů zvažte použití aplikace Microsoft Copilot Studio a přečtěte si o výběru správného řešení copilotu.

Další informace najdete v tématu Budoucnost vytváření robotů.

Požadavky

Poznámka:

Služba Language Understanding (LUIS) bude vyřazena 1. října 2025. Od 1. dubna 2023 nebudete moct vytvářet nové prostředky LUIS. Novější verze language understanding je teď dostupná jako součást jazyka Azure AI.

Konverzační jazyk understanding (CLU), funkce jazyka Azure AI, je aktualizovaná verze služby LUIS. Další informace o podpoře porozumění jazyku v sadě SDK služby Bot Framework najdete v tématu Principy přirozeného jazyka.

O této ukázce

Ukázka dovednostíDialog dovedností zahrnuje projekty pro dva roboty:

  • The dialog root bot, which uses a skill dialog class to consume a skill.
  • Robot dovedností dialogového okna, který používá dialogové okno pro zpracování aktivit pocházejících od příjemců dovedností. Tato dovednost je adaptací základní ukázky robota . (Další informace o základním robotovi najdete v článku o tom, jak do robota přidat porozumění přirozenému jazyku.)

Tento článek se zaměřuje na použití dialogového okna v robotovi dovedností ke správě více akcí.

Informace o uživatelském robotovi dovednosti najdete v tématu o tom, jak využívat dovednosti pomocí dialogových oken.

Zdroje informací

U nasazených robotů vyžaduje ověřování robota k robotovi platnou identitu každého zúčastněného robota. Pomocí bot Framework Emulatoru ale můžete testovat dovednosti a uživatele dovedností místně bez informací o identitě.

Pokud chcete, aby byla dovednost dostupná pro uživatelem robotů, zaregistrujte si dovednost v Azure. Další informace najdete v tématu registrace robota ve službě Azure AI Bot Service.

Volitelně může robot dovedností používat model služby LUIS rezervace letů. Pokud chcete tento model použít, použijte k vytvoření, trénování a publikování modelu LUIS soubor CognitiveModels/FlightBooking.json.

Konfigurace aplikací

  1. Volitelně můžete do konfiguračního souboru dovednosti přidat informace o identitě dovednosti. (Pokud dovednost nebo příjemce dovednosti specifikuje identitu, musí obě možnosti.)

  2. Pokud používáte model LUIS, přidejte ID aplikace LUIS, klíč rozhraní API a název hostitele rozhraní API.

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

Logika směrování aktivit

Dovednost podporuje několik různých funkcí. Může si rezervovat let nebo získat počasí pro město. Kromě toho, pokud obdrží zprávu mimo některý z těchto kontextů, může použít službu LUIS k pokusu o interpretaci zprávy. Manifest dovednosti popisuje tyto akce, jejich vstupní a výstupní parametry a koncové body dovednosti. Nezapomeňte, že dovednost dokáže zpracovat událost "BookFlight" nebo "GetWeather". Může také zpracovávat aktivity zpráv.

Dovednost definuje dialogové okno směrování aktivity, které používá k výběru akce, která se má zahájit, na základě počáteční příchozí aktivity od příjemce dovednosti. Pokud je k dispozici, model LUIS dokáže rozpoznat záměry book-flight a get-weather v počáteční zprávě.

Akce book-flight je vícekrokový proces, implementovaný jako samostatný dialog. Po zahájení akce se příchozí aktivity zpracovávají tímto dialogem. Akce get-weather má zástupnou logiku, která by byla nahrazena plně implementovaným robotem.

Dialogové okno směrování aktivit obsahuje kód pro:

Dialogy použité v dovednosti dědí z třídy dialogového okna komponenty. Další informace o dialogových oknech komponent najdete v tématu správa složitosti dialogového okna.

Inicializace dialogového okna

Dialogové okno směrování aktivit obsahuje podřízené dialogové okno pro rezervaci letu. Hlavní vodopádový dialog obsahuje jeden krok, který spustí akci na základě počáteční přijaté aktivity.

Přijímá také rozpoznávání luis. Pokud je tento rozpoznač inicializován, dialogové okno ho použije k interpretaci záměru počáteční aktivity zprávy.

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

Zpracování počáteční aktivity

V prvním (a jediném) kroku hlavního vodopádového dialogu dovednost kontroluje typ příchozí aktivity.

  • Aktivity událostí se předávají obslužné rutině aktivity události, která spustí příslušnou akci na základě názvu události.
  • Aktivity zpráv se předávají obslužné rutině aktivity zprávy, která provádí další zpracování před rozhodováním, co dělat.

Pokud dovednost nerozpozná typ příchozí aktivity nebo názvu události, odešle chybovou zprávu a končí.

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

Zpracování aktivit zpráv

Pokud je služba rozpoznávání LUIS nakonfigurovaná, dovednost volá službu LUIS a pak zahájí akci na základě záměru. Pokud rozpoznávání luis není nakonfigurované nebo záměr není podporovaný, dovednost odešle chybovou zprávu a končí.

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

Zahájení akce s více kroky

Akce rezervace spustí vícekrokové dialogové okno pro získání podrobností rezervace od uživatele.

Akce get-weather není implementována. V současné době odesílá zástupnou zprávu a končí.

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

Vrácení výsledku

Dovednost zahájí dialogové okno rezervace pro akci book-flight. Vzhledem k tomu, že dialogové okno směrování aktivit má jenom jeden krok, končí dialogové okno směrování aktivit a výsledek dialogového okna rezervace se stane výsledkem dialogového okna pro směrování aktivit.

Akce get-weather jednoduše skončí bez nastavení návratové hodnoty.

Zrušení akce s více kroky

Dialogové okno rezervace a jeho podřízený dialog pro datum-překladač jsou odvozeny z dialogového okna základní zrušení a nápovědy, které kontroluje zprávy od uživatele.

  • Na kartě "nápověda" nebo "?"se zobrazí zpráva nápovědy a pak pokračuje v toku konverzace na následujícím turnu.
  • Při "zrušení" nebo "ukončit" zruší všechna dialogová okna, která ukončí dovednost.

Další informace najdete v tématu řešení přerušení uživatelů.

Registrace služby

Služby potřebné pro tuto dovednost jsou stejné jako služby potřebné pro robota dovedností obecně. Podívejte se , jak implementovat dovednost pro diskuzi o požadovaných službách.

Manifest dovednosti

Manifest dovednosti je soubor JSON, který popisuje aktivity, které může dovednost provádět, její vstupní a výstupní parametry a koncové body dovednosti. Manifest obsahuje informace, které potřebujete pro přístup ke dovednosti z jiného robota.

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

Schéma manifestu dovedností je soubor JSON, který popisuje schéma manifestu dovednosti. Nejnovější verze schématu je verze 2.1.

Otestování robota dovedností

Dovednosti můžete otestovat v emulátoru s příjemcem dovedností. K tomu musíte současně spouštět dovednosti i roboty uživatelů. Podívejte se, jak pomocí dialogového okna využívat dovednosti pro informace o konfiguraci dovednosti.

Stáhněte a nainstalujte nejnovější bot Framework Emulator.

  1. Spusťte robota dovednosti dialogového okna a kořenového robota dialogového okna místně na svém počítači. Pokud potřebujete pokyny, projděte si ukázkový README soubor pro C#, JavaScript, Javu nebo Python.
  2. K otestování robota použijte emulátor.
    • Když se k konverzaci poprvé připojíte, robot zobrazí uvítací zprávu a zeptá se, jakou dovednost byste chtěli volat. Robot dovedností pro tuto ukázku má jen jednu dovednost.
    • Vyberte DialogSkillBot.
  3. V dalším kroku vás robot požádá o výběr akce pro dovednost. Zvolte "BookFlight".
    1. Dovednost začíná svou kniholetní akcí; odpovězte na výzvy.
    2. Po dokončení dovednosti zobrazí kořenový robot podrobnosti rezervace před opětovnou výzvou k zadání dovednosti, kterou chcete zavolat.
  4. Znovu vyberte DialogSkillBot a BookFlight.
    1. Odpovězte na první výzvu a pak akci zrušte zadáním "zrušit".
    2. Robot dovedností končí bez dokončení akce a uživatel vyzve ke zručnosti, kterou chcete zavolat.

Další informace o ladění

Vzhledem k tomu, že se ověřuje provoz mezi dovednostmi a uživateli dovedností, při ladění takových robotů existují další kroky.

  • Dovednost konzument a všechny dovednosti, které využívá, přímo nebo nepřímo, musí být spuštěné.
  • Pokud jsou roboti spuštěni místně a pokud některý z robotů má ID a heslo aplikace, musí mít všichni roboti platné ID a hesla.
  • Pokud jsou roboti všichni nasazeni, podívejte se , jak ladit robota z libovolného kanálu pomocí devtunnelu.
  • Pokud některé roboty běží místně a některé se nasadí, podívejte se , jak ladit dovednosti nebo příjemce dovedností.

Jinak můžete ladit dovednost uživatele nebo dovednosti podobně jako ostatní roboty. Další informace naleznete v tématu Ladění robota a ladění pomocí bot Framework Emulator.

Další informace