Saját kérések létrehozása felhasználói bemenetek gyűjtéséhez
Cikk
A KÖVETKEZŐKRE VONATKOZIK: SDK v4
A robotok és a felhasználók közötti beszélgetések gyakran magukban foglalják a felhasználó információkérését (kérését), a felhasználó válaszának elemzését, majd az információk alapján történő cselekvést. A robotnak nyomon kell követnie egy beszélgetés kontextusát, hogy kezelni tudja a viselkedését, és emlékezzen a korábbi kérdésekre adott válaszokra. A robot állapota olyan információ, amelyet nyomon követ, hogy megfelelően válaszoljon a bejövő üzenetekre.
Tipp.
A párbeszédpaneltár beépített utasításokat biztosít, amelyek további funkciókat biztosítanak a felhasználók számára. Ezekre a kérdésekre példákat az Implement szekvenciális beszélgetési folyamat című cikkben talál.
Feljegyzés
A Bot Framework JavaScript, C# és Python SDK-k továbbra is támogatottak lesznek, a Java SDK-t azonban 2023 novemberében végső hosszú távú támogatással kivonják.
A Java SDK-val létrehozott meglévő robotok továbbra is működni fognak.
Az új robotépítéshez fontolja meg a Microsoft Copilot Studio használatát, és olvassa el a megfelelő copilot-megoldás kiválasztását.
A jelen cikkben szereplő kód a Felhasználók kérése bemeneti mintán alapul. Szüksége lesz a C#-minta, a JavaScript-minta, a Java-minta vagy a Python-minta másolatára.
A mintarobot kérdések sorozatát kérdezi fel a felhasználótól, ellenőrzi a válaszok egy részét, és menti a bemenetét. Az alábbi ábra a robot, a felhasználói profil és a beszélgetési folyamat osztályai közötti kapcsolatot mutatja be.
A UserProfile robot által gyűjtött felhasználói adatok osztálya.
Egy ConversationFlow osztály, amely szabályozza a beszélgetés állapotát a felhasználói adatok összegyűjtése közben.
Belső ConversationFlow.Question számbavétel a beszélgetés helyének nyomon követéséhez.
A userProfile robot által gyűjtött felhasználói adatok osztálya.
Egy conversationFlow osztály, amely szabályozza a beszélgetés állapotát a felhasználói adatok összegyűjtése közben.
Belső conversationFlow.question számbavétel a beszélgetés helyének nyomon követéséhez.
A UserProfile robot által gyűjtött felhasználói adatok osztálya.
Egy ConversationFlow osztály, amely szabályozza a beszélgetés állapotát a felhasználói adatok összegyűjtése közben.
Belső ConversationFlow.Question számbavétel a beszélgetés helyének nyomon követéséhez.
A UserProfile robot által gyűjtött felhasználói adatok osztálya.
Egy ConversationFlow osztály, amely szabályozza a beszélgetés állapotát a felhasználói adatok összegyűjtése közben.
Belső ConversationFlow.Question számbavétel a beszélgetés helyének nyomon követéséhez.
A felhasználói állapot nyomon követi a felhasználó nevét, életkorát és választott dátumát, a beszélgetés állapota pedig nyomon követi, hogy mit kért a felhasználótól.
Mivel nem tervezi üzembe helyezni ezt a robotot, a felhasználó és a beszélgetés állapotát úgy fogja konfigurálni, hogy memóriatárolót használjon.
A robot üzenetkonfiguráció-kezelőjét, valamint a felhasználói és beszélgetési állapot tulajdonságait használva kezelheti a beszélgetés folyamatát és a bemenetek gyűjteményét. A robotban rögzíteni fogja az üzenetkontraszt kezelőjének minden iterációja során kapott állapottulajdonság-adatokat.
Beszélgetés és felhasználói objektumok létrehozása
Hozza létre a felhasználó- és beszélgetésállapot-objektumokat indításkor, és használja fel őket függőséginjektáláson keresztül a robotkonstruktorban.
Startup.cs
// Create the Bot Adapter with error handling enabled.
services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
// Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.)
services.AddSingleton<IStorage, MemoryStorage>();
// Create the User state.
services.AddSingleton<UserState>();
// Create the Conversation state.
services.AddSingleton<ConversationState>();
Hozza létre a felhasználói és beszélgetési állapot objektumait a index.js , és használja őket a robotkonstruktorban.
index.js
// Catch-all for errors.
adapter.onTurnError = async (context, error) => {
// This check writes out errors to console log .vs. app insights.
// NOTE: In production environment, you should consider logging this to Azure
robotok/customPromptBot.js
class CustomPromptBot extends ActivityHandler {
constructor(conversationState, userState) {
super();
// The state management objects for the conversation and user.
this.conversationState = conversationState;
this.userState = userState;
Hozza létre a CustomPromptBotot a getBot metódusban a Spring-tároló által biztosított ConversationState- és UserState-példányok használatával. A CustomPromptBot konstruktora az indítás során megadott ConversationState-ra és UserState-ra mutató hivatkozásokat tárol.
Application.java
@Bean
public Bot getBot(
ConversationState conversationState,
UserState userState
) {
return new CustomPromptBot(conversationState, userState);
}
CustomPromptBot.java
private final BotState userState;
private final BotState conversationState;
public CustomPromptBot(ConversationState conversationState, UserState userState) {
this.conversationState = conversationState;
this.userState = userState;
Hozza létre a felhasználói és beszélgetési állapot objektumait a app.py , és használja őket a robotkonstruktorban.
app.py
CONVERSATION_STATE = ConversationState(MEMORY)
# Create Bot
BOT = CustomPromptBot(CONVERSATION_STATE, USER_STATE)
# Listen for incoming requests on /api/messages.
robotok/custom_prompt_bot.py
class CustomPromptBot(ActivityHandler):
def __init__(self, conversation_state: ConversationState, user_state: UserState):
if conversation_state is None:
raise TypeError(
"[CustomPromptBot]: Missing parameter. conversation_state is required but None was given"
)
if user_state is None:
raise TypeError(
"[CustomPromptBot]: Missing parameter. user_state is required but None was given"
)
self.conversation_state = conversation_state
self.user_state = user_state
Hozzon létre tulajdonság-tartozékokat a felhasználói profil és a beszélgetési folyamat tulajdonságaihoz, majd hívja meg GetAsync a tulajdonság értékét az állapotból.
Robotok/CustomPromptBot.cs
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
var conversationStateAccessors = _conversationState.CreateProperty<ConversationFlow>(nameof(ConversationFlow));
var flow = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationFlow(), cancellationToken);
var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));
var profile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile(), cancellationToken);
Mielőtt a forduló véget ér, hívja meg SaveChangesAsync , hogy írjon bármilyen állapotváltozást a tárolóba.
Hozzon létre tulajdonság-tartozékokat a felhasználói profil és a beszélgetési folyamat tulajdonságaihoz, majd hívja meg get a tulajdonság értékét az állapotból.
Mielőtt a forduló véget ér, hívja meg saveChanges , hogy írjon bármilyen állapotváltozást a tárolóba.
/**
* Override the ActivityHandler.run() method to save state changes after the bot logic completes.
*/
async run(context) {
await super.run(context);
// Save any state changes. The load happened during the execution of the Dialog.
await this.conversationState.saveChanges(context, false);
await this.userState.saveChanges(context, false);
}
Hozzon létre tulajdonság-tartozékokat a felhasználói profil és a beszélgetési folyamat tulajdonságaihoz, majd hívja meg get a tulajdonság értékét az állapotból.
A konstruktorban létre kell hoznia az állapottulajdonság-tartozékokat, és be kell állítania a (fent létrehozott) állapotkezelési objektumokat a beszélgetéshez.
robotok/custom_prompt_bot.py
async def on_message_activity(self, turn_context: TurnContext):
# Get the state properties from the turn context.
profile = await self.profile_accessor.get(turn_context, UserProfile)
flow = await self.flow_accessor.get(turn_context, ConversationFlow)
Mielőtt a forduló véget ér, hívja meg SaveChangesAsync , hogy írjon bármilyen állapotváltozást a tárolóba.
# Save changes to UserState and ConversationState
await self.conversation_state.save_changes(turn_context)
await self.user_state.save_changes(turn_context)
Üzenetkontraszt kezelője
Üzenettevékenységek kezelésekor az üzenetkezelő segédmetódussal kezeli a beszélgetést, és kéri a felhasználót. A segédmetódus leírása a következő szakaszban található.
async def on_message_activity(self, turn_context: TurnContext):
# Get the state properties from the turn context.
profile = await self.profile_accessor.get(turn_context, UserProfile)
flow = await self.flow_accessor.get(turn_context, ConversationFlow)
await self._fill_out_user_profile(flow, profile, turn_context)
# Save changes to UserState and ConversationState
await self.conversation_state.save_changes(turn_context)
await self.user_state.save_changes(turn_context)
A felhasználói profil kitöltése
A robot információt kér a felhasználótól, amely alapján a robot az előző fordulóban feltett kérdés alapján kérdezett rá. A bemenet egy érvényesítési módszerrel van elemezve.
Minden érvényesítési módszer hasonló kialakítást követ:
A visszatérési érték azt jelzi, hogy a bemenet érvényes válasz-e erre a kérdésre.
Ha az ellenőrzés sikeres, elemzési és normalizált értéket hoz létre a mentéshez.
Ha az ellenőrzés sikertelen, egy üzenetet hoz létre, amellyel a robot újra kérheti az információkat.
Az érvényesítési módszereket a következő szakaszban ismertetjük.
{
var input = turnContext.Activity.Text?.Trim();
string message;
switch (flow.LastQuestionAsked)
{
case ConversationFlow.Question.None:
await turnContext.SendActivityAsync("Let's get started. What is your name?", null, null, cancellationToken);
flow.LastQuestionAsked = ConversationFlow.Question.Name;
break;
case ConversationFlow.Question.Name:
if (ValidateName(input, out var name, out message))
{
profile.Name = name;
await turnContext.SendActivityAsync($"Hi {profile.Name}.", null, null, cancellationToken);
await turnContext.SendActivityAsync("How old are you?", null, null, cancellationToken);
flow.LastQuestionAsked = ConversationFlow.Question.Age;
break;
}
else
{
await turnContext.SendActivityAsync(message ?? "I'm sorry, I didn't understand that.", null, null, cancellationToken);
break;
}
case ConversationFlow.Question.Age:
if (ValidateAge(input, out var age, out message))
{
profile.Age = age;
await turnContext.SendActivityAsync($"I have your age as {profile.Age}.", null, null, cancellationToken);
await turnContext.SendActivityAsync("When is your flight?", null, null, cancellationToken);
flow.LastQuestionAsked = ConversationFlow.Question.Date;
break;
}
else
{
await turnContext.SendActivityAsync(message ?? "I'm sorry, I didn't understand that.", null, null, cancellationToken);
break;
}
case ConversationFlow.Question.Date:
if (ValidateDate(input, out var date, out message))
{
profile.Date = date;
await turnContext.SendActivityAsync($"Your cab ride to the airport is scheduled for {profile.Date}.");
await turnContext.SendActivityAsync($"Thanks for completing the booking {profile.Name}.");
await turnContext.SendActivityAsync($"Type anything to run the bot again.");
flow.LastQuestionAsked = ConversationFlow.Question.None;
profile = new UserProfile();
break;
}
else
{
await turnContext.SendActivityAsync(message ?? "I'm sorry, I didn't understand that.", null, null, cancellationToken);
break;
}
}
}
robotok/customPromptBot.js
// Manages the conversation flow for filling out the user's profile.
static async fillOutUserProfile(flow, profile, turnContext) {
const input = turnContext.activity.text;
let result;
switch (flow.lastQuestionAsked) {
// If we're just starting off, we haven't asked the user for any information yet.
// Ask the user for their name and update the conversation flag.
case question.none:
await turnContext.sendActivity("Let's get started. What is your name?");
flow.lastQuestionAsked = question.name;
break;
// If we last asked for their name, record their response, confirm that we got it.
// Ask them for their age and update the conversation flag.
case question.name:
result = this.validateName(input);
if (result.success) {
profile.name = result.name;
await turnContext.sendActivity(`I have your name as ${ profile.name }.`);
await turnContext.sendActivity('How old are you?');
flow.lastQuestionAsked = question.age;
break;
} else {
// If we couldn't interpret their input, ask them for it again.
// Don't update the conversation flag, so that we repeat this step.
await turnContext.sendActivity(result.message || "I'm sorry, I didn't understand that.");
break;
}
// If we last asked for their age, record their response, confirm that we got it.
// Ask them for their date preference and update the conversation flag.
case question.age:
result = this.validateAge(input);
if (result.success) {
profile.age = result.age;
await turnContext.sendActivity(`I have your age as ${ profile.age }.`);
await turnContext.sendActivity('When is your flight?');
flow.lastQuestionAsked = question.date;
break;
} else {
// If we couldn't interpret their input, ask them for it again.
// Don't update the conversation flag, so that we repeat this step.
await turnContext.sendActivity(result.message || "I'm sorry, I didn't understand that.");
break;
}
// If we last asked for a date, record their response, confirm that we got it,
// let them know the process is complete, and update the conversation flag.
case question.date:
result = this.validateDate(input);
if (result.success) {
profile.date = result.date;
await turnContext.sendActivity(`Your cab ride to the airport is scheduled for ${ profile.date }.`);
await turnContext.sendActivity(`Thanks for completing the booking ${ profile.name }.`);
await turnContext.sendActivity('Type anything to run the bot again.');
flow.lastQuestionAsked = question.none;
profile = {};
break;
} else {
// If we couldn't interpret their input, ask them for it again.
// Don't update the conversation flag, so that we repeat this step.
await turnContext.sendActivity(result.message || "I'm sorry, I didn't understand that.");
break;
}
}
}
CustomPromptBot.java
private static CompletableFuture<Void> fillOutUserProfile(ConversationFlow flow,
UserProfile profile,
TurnContext turnContext) {
String input = "";
if (StringUtils.isNotBlank(turnContext.getActivity().getText())) {
input = turnContext.getActivity().getText().trim();
}
switch (flow.getLastQuestionAsked()) {
case None:
return turnContext.sendActivity("Let's get started. What is your name?", null, null)
.thenRun(() -> {flow.setLastQuestionAsked(ConversationFlow.Question.Name);});
case Name:
Triple<Boolean, String, String> nameValidationResult = validateName(input);
if (nameValidationResult.getLeft()) {
profile.setName(nameValidationResult.getMiddle());
return turnContext.sendActivity(String.format("Hi %s.", profile.getName()), null, null)
.thenCompose(result -> turnContext.sendActivity("How old are you?", null, null))
.thenRun(() -> { flow.setLastQuestionAsked(ConversationFlow.Question.Age); });
} else {
if (StringUtils.isNotBlank(nameValidationResult.getRight())) {
return turnContext.sendActivity(nameValidationResult.getRight(), null, null)
.thenApply(result -> null);
} else {
return turnContext.sendActivity("I'm sorry, I didn't understand that.", null, null)
.thenApply(result -> null);
}
}
case Age:
Triple<Boolean, Integer, String> ageValidationResult = ValidateAge(input);
if (ageValidationResult.getLeft()) {
profile.setAge(ageValidationResult.getMiddle());
return turnContext.sendActivity(String.format("I have your age as %d.", profile.getAge()), null, null)
.thenCompose(result -> turnContext.sendActivity("When is your flight?", null, null))
.thenRun(() -> { flow.setLastQuestionAsked(ConversationFlow.Question.Date); });
} else {
if (StringUtils.isNotBlank(ageValidationResult.getRight())) {
return turnContext.sendActivity(ageValidationResult.getRight(), null, null)
.thenApply(result -> null);
} else {
return turnContext.sendActivity("I'm sorry, I didn't understand that.", null, null)
.thenApply(result -> null);
}
}
case Date:
Triple<Boolean, String, String> dateValidationResult = ValidateDate(input);
AtomicReference<UserProfile> profileReference = new AtomicReference<UserProfile>(profile);
if (dateValidationResult.getLeft()) {
profile.setDate(dateValidationResult.getMiddle());
return turnContext.sendActivity(
String.format("Your cab ride to the airport is scheduled for %s.",
profileReference.get().getDate()))
.thenCompose(result -> turnContext.sendActivity(
String.format("Thanks for completing the booking %s.", profileReference.get().getDate())))
.thenCompose(result -> turnContext.sendActivity("Type anything to run the bot again."))
.thenRun(() -> {
flow.setLastQuestionAsked(ConversationFlow.Question.None);
profileReference.set(new UserProfile());
});
} else {
if (StringUtils.isNotBlank(dateValidationResult.getRight())) {
return turnContext.sendActivity(dateValidationResult.getRight(), null, null)
.thenApply(result -> null);
} else {
return turnContext.sendActivity("I'm sorry, I didn't understand that.", null, null)
.thenApply(result -> null);
}
}
default:
return CompletableFuture.completedFuture(null);
}
robotok/custom_prompt_bot.py
async def _fill_out_user_profile(
self, flow: ConversationFlow, profile: UserProfile, turn_context: TurnContext
):
user_input = turn_context.activity.text.strip()
# ask for name
if flow.last_question_asked == Question.NONE:
await turn_context.send_activity(
MessageFactory.text("Let's get started. What is your name?")
)
flow.last_question_asked = Question.NAME
# validate name then ask for age
elif flow.last_question_asked == Question.NAME:
validate_result = self._validate_name(user_input)
if not validate_result.is_valid:
await turn_context.send_activity(
MessageFactory.text(validate_result.message)
)
else:
profile.name = validate_result.value
await turn_context.send_activity(
MessageFactory.text(f"Hi {profile.name}")
)
await turn_context.send_activity(
MessageFactory.text("How old are you?")
)
flow.last_question_asked = Question.AGE
# validate age then ask for date
elif flow.last_question_asked == Question.AGE:
validate_result = self._validate_age(user_input)
if not validate_result.is_valid:
await turn_context.send_activity(
MessageFactory.text(validate_result.message)
)
else:
profile.age = validate_result.value
await turn_context.send_activity(
MessageFactory.text(f"I have your age as {profile.age}.")
)
await turn_context.send_activity(
MessageFactory.text("When is your flight?")
)
flow.last_question_asked = Question.DATE
# validate date and wrap it up
elif flow.last_question_asked == Question.DATE:
validate_result = self._validate_date(user_input)
if not validate_result.is_valid:
await turn_context.send_activity(
MessageFactory.text(validate_result.message)
)
else:
profile.date = validate_result.value
await turn_context.send_activity(
MessageFactory.text(
f"Your cab ride to the airport is scheduled for {profile.date}."
)
)
await turn_context.send_activity(
MessageFactory.text(
f"Thanks for completing the booking {profile.name}."
)
)
await turn_context.send_activity(
MessageFactory.text("Type anything to run the bot again.")
)
flow.last_question_asked = Question.NONE
Bemenet elemzése és ellenőrzése
A robot a következő feltételek alapján ellenőrzi a bemenetet.
A névnek nem üres sztringnek kell lennie. Normalizálódik a térköz levágásával.
Az életkornak 18 és 120 év közöttinek kell lennie. Egy egész szám visszaadásával normalizálódik.
A dátumnak bármilyen dátumnak vagy időpontnak kell lennie, legalább egy órával később.
Normalizálva van, ha csak az elemzési bemenet dátumrészét adja vissza.
Feljegyzés
A kor- és dátumbemenethez a minta a Microsoft/Recognizers-Text kódtárakat használja a kezdeti elemzés végrehajtásához.
Ez csak egy módja a bemenet elemzésének. Ezekről a kódtárakról további információt a projekt README című témakörében talál.
private static bool ValidateName(string input, out string name, out string message)
{
name = null;
message = null;
if (string.IsNullOrWhiteSpace(input))
{
message = "Please enter a name that contains at least one character.";
}
else
{
name = input.Trim();
}
return message is null;
}
private static bool ValidateAge(string input, out int age, out string message)
{
age = 0;
message = null;
// Try to recognize the input as a number. This works for responses such as "twelve" as well as "12".
try
{
// Attempt to convert the Recognizer result to an integer. This works for "a dozen", "twelve", "12", and so on.
// The recognizer returns a list of potential recognition results, if any.
var results = NumberRecognizer.RecognizeNumber(input, Culture.English);
foreach (var result in results)
{
// The result resolution is a dictionary, where the "value" entry contains the processed string.
if (result.Resolution.TryGetValue("value", out var value))
{
age = Convert.ToInt32(value);
if (age >= 18 && age <= 120)
{
return true;
}
}
}
message = "Please enter an age between 18 and 120.";
}
catch
{
message = "I'm sorry, I could not interpret that as an age. Please enter an age between 18 and 120.";
}
return message is null;
}
private static bool ValidateDate(string input, out string date, out string message)
{
date = null;
message = null;
// Try to recognize the input as a date-time. This works for responses such as "11/14/2018", "9pm", "tomorrow", "Sunday at 5pm", and so on.
// The recognizer returns a list of potential recognition results, if any.
try
{
var results = DateTimeRecognizer.RecognizeDateTime(input, Culture.English);
// Check whether any of the recognized date-times are appropriate,
// and if so, return the first appropriate date-time. We're checking for a value at least an hour in the future.
var earliest = DateTime.Now.AddHours(1.0);
foreach (var result in results)
{
// The result resolution is a dictionary, where the "values" entry contains the processed input.
var resolutions = result.Resolution["values"] as List<Dictionary<string, string>>;
foreach (var resolution in resolutions)
{
// The processed input contains a "value" entry if it is a date-time value, or "start" and
// "end" entries if it is a date-time range.
if (resolution.TryGetValue("value", out var dateString)
|| resolution.TryGetValue("start", out dateString))
{
if (DateTime.TryParse(dateString, out var candidate)
&& earliest < candidate)
{
date = candidate.ToShortDateString();
return true;
}
}
}
}
message = "I'm sorry, please enter a date at least an hour out.";
}
catch
{
message = "I'm sorry, I could not interpret that as an appropriate date. Please enter a date at least an hour out.";
}
return false;
}
robotok/customPromptBot.js
// Validates name input. Returns whether validation succeeded and either the parsed and normalized
// value or a message the bot can use to ask the user again.
static validateName(input) {
const name = input && input.trim();
return name !== undefined
? { success: true, name: name }
: { success: false, message: 'Please enter a name that contains at least one character.' };
};
// Validates age input. Returns whether validation succeeded and either the parsed and normalized
// value or a message the bot can use to ask the user again.
static validateAge(input) {
// Try to recognize the input as a number. This works for responses such as "twelve" as well as "12".
try {
// Attempt to convert the Recognizer result to an integer. This works for "a dozen", "twelve", "12", and so on.
// The recognizer returns a list of potential recognition results, if any.
const results = Recognizers.recognizeNumber(input, Recognizers.Culture.English);
let output;
results.forEach(result => {
// result.resolution is a dictionary, where the "value" entry contains the processed string.
const value = result.resolution.value;
if (value) {
const age = parseInt(value);
if (!isNaN(age) && age >= 18 && age <= 120) {
output = { success: true, age: age };
return;
}
}
});
return output || { success: false, message: 'Please enter an age between 18 and 120.' };
} catch (error) {
return {
success: false,
message: "I'm sorry, I could not interpret that as an age. Please enter an age between 18 and 120."
};
}
}
// Validates date input. Returns whether validation succeeded and either the parsed and normalized
// value or a message the bot can use to ask the user again.
static validateDate(input) {
// Try to recognize the input as a date-time. This works for responses such as "11/14/2018", "today at 9pm", "tomorrow", "Sunday at 5pm", and so on.
// The recognizer returns a list of potential recognition results, if any.
try {
const results = Recognizers.recognizeDateTime(input, Recognizers.Culture.English);
const now = new Date();
const earliest = now.getTime() + (60 * 60 * 1000);
let output;
results.forEach(result => {
// result.resolution is a dictionary, where the "values" entry contains the processed input.
result.resolution.values.forEach(resolution => {
// The processed input contains a "value" entry if it is a date-time value, or "start" and
// "end" entries if it is a date-time range.
const datevalue = resolution.value || resolution.start;
// If only time is given, assume it's for today.
const datetime = resolution.type === 'time'
? new Date(`${ now.toLocaleDateString() } ${ datevalue }`)
: new Date(datevalue);
if (datetime && earliest < datetime.getTime()) {
output = { success: true, date: datetime.toLocaleDateString() };
return;
}
});
});
return output || { success: false, message: "I'm sorry, please enter a date at least an hour out." };
} catch (error) {
return {
success: false,
message: "I'm sorry, I could not interpret that as an appropriate date. Please enter a date at least an hour out."
};
}
}
CustomPromptBot.java
private static Triple<Boolean, String, String> validateName(String input) {
String name = null;
String message = null;
if (StringUtils.isEmpty(input)) {
message = "Please enter a name that contains at least one character.";
} else {
name = input.trim();
}
return Triple.of(StringUtils.isBlank(message), name, message);
}
private static Triple<Boolean, Integer, String> ValidateAge(String input) {
int age = 0;
String message = null;
// Try to recognize the input as a number. This works for responses such as "twelve" as well as "12".
try {
// Attempt to convert the Recognizer result to an integer. This works for "a dozen", "twelve", "12", and so on.
// The recognizer returns a list of potential recognition results, if any.
List<ModelResult> results = NumberRecognizer.recognizeNumber(input, PromptCultureModels.ENGLISH_CULTURE);
for (ModelResult result : results) {
// The result resolution is a dictionary, where the "value" entry contains the processed String.
Object value = result.resolution.get("value");
if (value != null) {
age = Integer.parseInt((String) value);
if (age >= 18 && age <= 120) {
return Triple.of(true, age, "");
}
}
}
message = "Please enter an age between 18 and 120.";
}
catch (Throwable th) {
message = "I'm sorry, I could not interpret that as an age. Please enter an age between 18 and 120.";
}
return Triple.of(StringUtils.isBlank(message), age, message);
}
private static Triple<Boolean, String, String> ValidateDate(String input) {
String date = null;
String message = null;
// Try to recognize the input as a date-time. This works for responses such as "11/14/2018", "9pm", "tomorrow", "Sunday at 5pm", and so on.
// The recognizer returns a list of potential recognition results, if any.
try {
List<ModelResult> results = DateTimeRecognizer.recognizeDateTime(input, PromptCultureModels.ENGLISH_CULTURE);
// Check whether any of the recognized date-times are appropriate,
// and if so, return the first appropriate date-time. We're checking for a value at least an hour in the future.
LocalDateTime earliest = LocalDateTime.now().plus(1, ChronoUnit.HOURS);
for (ModelResult result : results) {
// The result resolution is a dictionary, where the "values" entry contains the processed input.
List<Map<String, Object>> resolutions = (List<Map<String, Object>>) result.resolution.get("values");
for (Map<String, Object> resolution : resolutions) {
// The processed input contains a "value" entry if it is a date-time value, or "start" and
// "end" entries if it is a date-time range.
String dateString = (String) resolution.get("value");
if (StringUtils.isBlank(dateString)) {
dateString = (String) resolution.get("start");
}
if (StringUtils.isNotBlank(dateString)){
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime candidate;
try {
candidate = LocalDateTime.from(f.parse(dateString));
} catch (DateTimeParseException err) {
// If the input is a date, it will throw an exception and it will create a datetime
// with the MIN localtime
DateTimeFormatter d = DateTimeFormatter.ofPattern("yyyy-MM-dd");
candidate = LocalDateTime.of(LocalDate.parse(dateString, d), LocalDateTime.MIN.toLocalTime());
}
if (earliest.isBefore(candidate)) {
DateTimeFormatter dateformat = DateTimeFormatter.ofPattern("MM-dd-yyyy");
date = candidate.format(dateformat);
return Triple.of(true, date, message);
}
}
}
}
robotok/custom_prompt_bot.py
def _validate_name(self, user_input: str) -> ValidationResult:
if not user_input:
return ValidationResult(
is_valid=False,
message="Please enter a name that contains at least one character.",
)
return ValidationResult(is_valid=True, value=user_input)
def _validate_age(self, user_input: str) -> ValidationResult:
# Attempt to convert the Recognizer result to an integer. This works for "a dozen", "twelve", "12", and so on.
# The recognizer returns a list of potential recognition results, if any.
results = recognize_number(user_input, Culture.English)
for result in results:
if "value" in result.resolution:
age = int(result.resolution["value"])
if 18 <= age <= 120:
return ValidationResult(is_valid=True, value=age)
return ValidationResult(
is_valid=False, message="Please enter an age between 18 and 120."
)
def _validate_date(self, user_input: str) -> ValidationResult:
try:
# Try to recognize the input as a date-time. This works for responses such as "11/14/2018", "9pm",
# "tomorrow", "Sunday at 5pm", and so on. The recognizer returns a list of potential recognition results,
# if any.
results = recognize_datetime(user_input, Culture.English)
for result in results:
for resolution in result.resolution["values"]:
if "value" in resolution:
now = datetime.now()
value = resolution["value"]
if resolution["type"] == "date":
candidate = datetime.strptime(value, "%Y-%m-%d")
elif resolution["type"] == "time":
candidate = datetime.strptime(value, "%H:%M:%S")
candidate = candidate.replace(
year=now.year, month=now.month, day=now.day
)
else:
candidate = datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
# user response must be more than an hour out
diff = candidate - now
if diff.total_seconds() >= 3600:
return ValidationResult(
is_valid=True,
value=candidate.strftime("%m/%d/%y"),
)
return ValidationResult(
is_valid=False,
message="I'm sorry, please enter a date at least an hour out.",
)
except ValueError:
return ValidationResult(
is_valid=False,
message="I'm sorry, I could not interpret that as an appropriate "
"date. Please enter a date at least an hour out.",
)
Futtassa a mintát helyileg a számítógépen. Ha útmutatásra van szüksége, tekintse meg a README C#-mintához, a JS-mintához vagy a Python-mintához tartozó fájlt.
Tesztelje az Emulator használatával.
További erőforrások
A Párbeszédpanelek kódtár olyan osztályokat biztosít, amelyek automatizálják a beszélgetések kezelésének számos aspektusát.