사용자와 봇 간에 교환되는 메시지에는 이미지, 비디오, 오디오 및 파일과 같은 미디어 첨부 파일이 포함될 수 있습니다. Bot Framework SDK는 사용자에게 풍부한 메시지를 보내는 작업을 지원합니다. 채널(Facebook, Slack 등)에서 지원하는 서식 있는 메시지 유형을 확인하려면 채널 설명서에서 제한 사항에 대한 정보를 참조하세요.
참고 항목
Bot Framework JavaScript, C#및 Python SDK는 계속 지원되지만 Java SDK는 2023년 11월에 종료되는 최종 장기 지원으로 사용 중지됩니다.
Java SDK를 사용하여 빌드된 기존 봇은 계속 작동합니다.
새 봇 빌드의 경우 Power Virtual Agents 사용을 고려하고 올바른 챗봇 솔루션을 선택하는 방법을 읽어 보세요.
개체의 Activity 속성에는 Attachments 미디어 첨부 파일과 메시지에 첨부된 서식 있는 카드 나타내는 개체 배열 Attachment 이 포함되어 있습니다. 메시지에 미디어 첨부 파일을 추가하려면 활동에 대한 개체를 reply 만들고 Attachment , ContentUrl및 Name 속성을 설정합니다ContentType.
회신 메시지를 만들려면 텍스트를 정의한 다음 첨부 파일을 설정합니다. 회신에 첨부 파일을 할당하는 것은 각 첨부 파일 유형에 대해 동일합니다. 그러나 다음 코드 조각에 표시된 것처럼 다양한 첨부 파일이 설정되고 다르게 정의됩니다. 아래 코드는 인라인 첨부 파일에 대한 회신을 설정합니다.
봇/AttachmentsBot.cs
{
reply = MessageFactory.Text("This is an inline attachment.");
다음으로 첨부 파일 유형을 살펴봅니다. 첫 번째는 인라인 첨부 파일입니다.
봇/AttachmentsBot.cs
{
var imagePath = Path.Combine(Environment.CurrentDirectory, @"Resources", "architecture-resize.png");
var imageData = Convert.ToBase64String(File.ReadAllBytes(imagePath));
return new Attachment
{
Name = @"Resources\architecture-resize.png",
ContentType = "image/png",
ContentUrl = $"data:image/png;base64,{imageData}",
};
}
그런 다음 업로드된 첨부 파일:
봇/AttachmentsBot.cs
{
if (string.IsNullOrWhiteSpace(serviceUrl))
{
throw new ArgumentNullException(nameof(serviceUrl));
}
if (string.IsNullOrWhiteSpace(conversationId))
{
throw new ArgumentNullException(nameof(conversationId));
}
var imagePath = Path.Combine(Environment.CurrentDirectory, @"Resources", "architecture-resize.png");
var connector = turnContext.TurnState.Get<IConnectorClient>() as ConnectorClient;
var attachments = new Attachments(connector);
var response = await attachments.Client.Conversations.UploadAttachmentAsync(
conversationId,
new AttachmentData
{
Name = @"Resources\architecture-resize.png",
OriginalBase64 = File.ReadAllBytes(imagePath),
Type = "image/png",
},
cancellationToken);
var attachmentUri = attachments.GetAttachmentUri(response.Id);
return new Attachment
{
Name = @"Resources\architecture-resize.png",
ContentType = "image/png",
ContentUrl = attachmentUri,
};
}
마지막으로, 인터넷 첨부 파일입니다.
봇/AttachmentsBot.cs
{
// ContentUrl must be HTTPS.
return new Attachment
{
Name = @"Resources\architecture-resize.png",
ContentType = "image/png",
ContentUrl = "https://docs.microsoft.com/en-us/bot-framework/media/how-it-works/architecture-resize.png",
};
}
}
회신 메시지를 만들려면 텍스트를 정의한 다음 첨부 파일을 설정합니다. 회신에 첨부 파일을 할당하는 것은 각 첨부 파일 유형에 대해 동일합니다. 그러나 다음 코드 조각에 표시된 것처럼 다양한 첨부 파일이 설정되고 다르게 정의됩니다. 아래 코드는 인라인 첨부 파일에 대한 회신을 설정합니다.
bots/attachmentsBot.js
const reply = { type: ActivityTypes.Message };
reply.text = 'This is an inline attachment.';
reply.attachments = [this.getInlineAttachment()];
사용자에게 이미지 또는 비디오와 같은 단일 콘텐츠를 보내려면 몇 가지 다른 방법으로 미디어를 보낼 수 있습니다. 먼저 인라인 첨부 파일입니다.
개체의 Activity 메서드에는 getAttachments() 미디어 첨부 파일과 메시지에 첨부된 서식 있는 카드 나타내는 개체 배열 Attachment 이 포함되어 있습니다. 메시지에 미디어 첨부 파일을 추가하려면 활동에 대한 개체를 reply 만들고 Attachment , ContentUrl및 Name 속성을 설정합니다ContentType.
회신 메시지를 만들려면 텍스트를 정의한 다음 첨부 파일을 설정합니다. 회신에 첨부 파일을 할당하는 것은 각 첨부 파일 유형에 대해 동일합니다. 그러나 다음 코드 조각에 표시된 것처럼 다양한 첨부 파일이 설정되고 다르게 정의됩니다. 아래 코드는 인라인 첨부 파일에 대한 회신을 설정합니다.
AttachmentsBot.java
result = getInlineAttachment()
.thenApply(attachment -> {
Activity reply = MessageFactory.text("This is an inline attachment.");
reply.setAttachment(attachment);
return reply;
});
다음으로 첨부 파일 유형을 살펴봅니다. 첫 번째는 인라인 첨부 파일입니다.
AttachmentsBot.java
// Creates an inline attachment sent from the bot to the user using a base64 string.
// Using a base64 string to send an attachment will not work on all channels.
// Additionally, some channels will only allow certain file types to be sent this way.
// For example a .png file may work but a .pdf file may not on some channels.
// Please consult the channel documentation for specifics.
private CompletableFuture<Attachment> getInlineAttachment() {
return getEncodedFileData("architecture-resize.png")
.thenApply(encodedFileData -> {
Attachment attachment = new Attachment();
attachment.setName("architecture-resize.png");
attachment.setContentType("image/png");
attachment.setContentUrl("data:image/png;base64," + encodedFileData);
return attachment;
});
}
// Creates an Attachment to be sent from the bot to the user from a HTTP URL.
private static Attachment getInternetAttachment() {
// ContentUrl must be HTTPS.
Attachment attachment = new Attachment();
attachment.setName("architecture-resize.png");
attachment.setContentType("image/png");
attachment.setContentUrl("https://docs.microsoft.com/en-us/bot-framework/media/how-it-works/architecture-resize.png");
return attachment;
}
회신 메시지를 만들려면 텍스트를 정의한 다음 첨부 파일을 설정합니다. 회신에 첨부 파일을 할당하는 것은 각 첨부 파일 유형에 대해 동일합니다. 그러나 다음 코드 조각에 표시된 것처럼 다양한 첨부 파일이 설정되고 다르게 정의됩니다.
아래 코드는 인라인 첨부 파일에 대한 회신을 설정합니다.
봇/attachments_bot.py
reply.text = "This is an inline attachment."
reply.attachments = [self._get_inline_attachment()]
사용자에게 이미지 또는 비디오와 같은 단일 콘텐츠를 보내려면 몇 가지 다른 방법으로 미디어를 보낼 수 있습니다. 먼저 인라인 첨부 파일입니다.
봇/attachments_bot.py
def _get_inline_attachment(self) -> Attachment:
"""
Creates an inline attachment sent from the bot to the user using a base64 string.
Using a base64 string to send an attachment will not work on all channels.
Additionally, some channels will only allow certain file types to be sent this way.
For example a .png file may work but a .pdf file may not on some channels.
Please consult the channel documentation for specifics.
:return: Attachment
"""
file_path = os.path.join(os.getcwd(), "resources/architecture-resize.png")
with open(file_path, "rb") as in_file:
base64_image = base64.b64encode(in_file.read()).decode()
return Attachment(
name="architecture-resize.png",
content_type="image/png",
content_url=f"data:image/png;base64,{base64_image}",
)
그런 다음 업로드된 첨부 파일:
봇/attachments_bot.py
async def _get_upload_attachment(self, turn_context: TurnContext) -> Attachment:
"""
Creates an "Attachment" to be sent from the bot to the user from an uploaded file.
:param turn_context:
:return: Attachment
"""
with open(
os.path.join(os.getcwd(), "resources/architecture-resize.png"), "rb"
) as in_file:
image_data = in_file.read()
connector = await turn_context.adapter.create_connector_client(
turn_context.activity.service_url
)
conversation_id = turn_context.activity.conversation.id
response = await connector.conversations.upload_attachment(
conversation_id,
AttachmentData(
name="architecture-resize.png",
original_base64=image_data,
type="image/png",
),
)
base_uri: str = connector.config.base_url
attachment_uri = (
base_uri
+ ("" if base_uri.endswith("/") else "/")
+ f"v3/attachments/{response.id}/views/original"
)
return Attachment(
name="architecture-resize.png",
content_type="image/png",
content_url=attachment_uri,
)
마지막으로 URL에 포함된 인터넷 첨부 파일은 다음과 같습니다.
봇/attachments_bot.py
def _get_internet_attachment(self) -> Attachment:
"""
Creates an Attachment to be sent from the bot to the user from a HTTP URL.
:return: Attachment
"""
return Attachment(
name="architecture-resize.png",
content_type="image/png",
content_url="https://docs.microsoft.com/en-us/bot-framework/media/how-it-works/architecture-resize.png",
)
첨부 파일이 이미지, 오디오 또는 비디오인 경우 커넥트또는 서비스는 채널이 대화 내에서 해당 첨부 파일을 렌더링할 수 있도록 채널에 첨부 파일 데이터를 전달합니다. 첨부 파일이 파일인 경우 파일 URL은 대화 내 하이퍼링크로 렌더링됩니다.
영웅 카드 보내기
단순 이미지 또는 비디오 첨부 파일 외에도 영웅 카드를 첨부할 수 있습니다. 이 카드를 사용하면 이미지 및 단추를 하나의 개체로 결합하여 사용자에게 보낼 수 있습니다. Markdown은 대부분의 텍스트 필드에 지원되지만 채널별로 지원이 다를 수 있습니다.
private static async Task DisplayOptionsAsync(ITurnContext turnContext, CancellationToken cancellationToken)
{
// Create a HeroCard with options for the user to interact with the bot.
var card = new HeroCard
{
Text = "You can upload an image or select one of the following choices",
Buttons = new List<CardAction>
{
// Note that some channels require different values to be used in order to get buttons to display text.
// In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
// need to provide a value for other parameters like 'text' or 'displayText'.
new CardAction(ActionTypes.ImBack, title: "1. Inline Attachment", value: "1"),
new CardAction(ActionTypes.ImBack, title: "2. Internet Attachment", value: "2"),
new CardAction(ActionTypes.ImBack, title: "3. Uploaded Attachment", value: "3"),
},
};
var reply = MessageFactory.Attachment(card.ToAttachment());
await turnContext.SendActivityAsync(reply, cancellationToken);
hero 카드 및 단추로 메시지를 작성하려면 메시지에 개체를 HeroCard 첨부할 수 있습니다.
async displayOptions(turnContext) {
const reply = { type: ActivityTypes.Message };
// Note that some channels require different values to be used in order to get buttons to display text.
// In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
// need to provide a value for other parameters like 'text' or 'displayText'.
const buttons = [
{ type: ActionTypes.ImBack, title: '1. Inline Attachment', value: '1' },
{ type: ActionTypes.ImBack, title: '2. Internet Attachment', value: '2' },
{ type: ActionTypes.ImBack, title: '3. Uploaded Attachment', value: '3' }
];
const card = CardFactory.heroCard('', undefined,
buttons, { text: 'You can upload an image or select one of the following choices.' });
reply.attachments = [card];
await turnContext.sendActivity(reply);
}
hero 카드 및 단추로 메시지를 작성하려면 메시지에 개체를 HeroCard 첨부할 수 있습니다.
private static CompletableFuture<Void> displayOptions(TurnContext turnContext) {
// Create a HeroCard with options for the user to interact with the bot.
HeroCard card = new HeroCard();
card.setText("You can upload an image or select one of the following choices");
// Note that some channels require different values to be used in order to get buttons to display text.
// In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
// need to provide a value for other parameters like 'text' or 'displayText'.
card.setButtons(
new CardAction(ActionTypes.IM_BACK, "1. Inline Attachment", "1"),
new CardAction(ActionTypes.IM_BACK, "2. Internet Attachment", "2"),
new CardAction(ActionTypes.IM_BACK, "3. Uploaded Attachment", "3")
);
Activity reply = MessageFactory.attachment(card.toAttachment());
return turnContext.sendActivity(reply).thenApply(resourceResponse -> null);
}
hero 카드 및 단추로 메시지를 작성하려면 메시지에 개체를 HeroCard 첨부할 수 있습니다.
async def _display_options(self, turn_context: TurnContext):
"""
Create a HeroCard with options for the user to interact with the bot.
:param turn_context:
:return:
"""
# Note that some channels require different values to be used in order to get buttons to display text.
# In this code the emulator is accounted for with the 'title' parameter, but in other channels you may
# need to provide a value for other parameters like 'text' or 'displayText'.
card = HeroCard(
text="You can upload an image or select one of the following choices",
buttons=[
CardAction(
type=ActionTypes.im_back, title="1. Inline Attachment", value="1"
),
CardAction(
type=ActionTypes.im_back, title="2. Internet Attachment", value="2"
),
CardAction(
type=ActionTypes.im_back, title="3. Uploaded Attachment", value="3"
),
],
)
풍부한 카드 내의 이벤트 처리
풍부한 카드 내에서 이벤트를 처리하려면 카드 작업 개체를 사용하여 사용자가 단추를 선택하거나 카드 섹션을 탭할 때 발생할 작업을 지정합니다. 각 카드 작업에는 형식 및 값 속성이 있습니다.
올바르게 작동하려면 hero 카드 클릭 가능한 각 항목에 작업 유형을 할당합니다. 이 표에서는 사용 가능한 작업 유형과 연결된 값 속성에 있어야 하는 작업을 나열하고 설명합니다.
messageBack 카드 작업은 다른 카드 작업보다 더 일반화된 의미를 줍니다. 기타 카드 작업 유형에 대한 자세한 내용은 활동 스키마의 messageBack 카드 작업 섹션을 참조하세요.
public static HeroCard GetHeroCard()
{
var heroCard = new HeroCard
{
Title = "BotFramework Hero Card",
Subtitle = "Microsoft Bot Framework",
Text = "Build and connect intelligent bots to interact with your users naturally wherever they are," +
" from text/sms to Skype, Slack, Office 365 mail and other popular services.",
Images = new List<CardImage> { new CardImage("https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg") },
Buttons = new List<CardAction> { new CardAction(ActionTypes.OpenUrl, "Get Started", value: "https://docs.microsoft.com/bot-framework") },
};
return heroCard;
}
Cards.cs
public static SigninCard GetSigninCard()
{
var signinCard = new SigninCard
{
Text = "BotFramework Sign-in Card",
Buttons = new List<CardAction> { new CardAction(ActionTypes.Signin, "Sign-in", value: "https://login.microsoftonline.com/") },
};
return signinCard;
}
createOAuthCard() {
return CardFactory.oauthCard(
'OAuth connection', // Replace with the name of your Azure AD connection
'Sign In',
'BotFramework OAuth Card'
);
}
public static HeroCard getHeroCard() {
HeroCard heroCard = new HeroCard();
heroCard.setTitle("BotFramework Hero Card");
heroCard.setSubtitle("Microsoft Bot Framework");
heroCard.setText("Build and connect intelligent bots to interact with your users naturally wherever they are," +
" from text/sms to Skype, Slack, Office 365 mail and other popular services.");
heroCard.setImages(new CardImage("https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg"));
heroCard.setButtons(new CardAction(ActionTypes.OPEN_URL, "Get Started", "https://docs.microsoft.com/bot-framework"));
return heroCard;
}
Cards.java
public static SigninCard getSigninCard() {
SigninCard signinCard = new SigninCard();
signinCard.setText("BotFramework Sign-in Card");
signinCard.setButtons(new CardAction(ActionTypes.SIGNIN, "Sign-in", "https://login.microsoftonline.com/"));
return signinCard;
}
def create_oauth_card(self) -> Attachment:
card = OAuthCard(
text="BotFramework OAuth Card",
connection_name="OAuth connection", # Replace it with the name of your Azure AD connection.
buttons=[
CardAction(
type=ActionTypes.signin,
title="Sign in",
value="https://example.org/signin",
)
],
)
return CardFactory.oauth_card(card)
적응형 카드 보내기
메시지 팩터리를 사용하여 첨부 파일이 포함된 메시지를 만들 수 있지만 적응형 카드는 특정 유형의 첨부 파일입니다. 일부 채널은 적응형 카드를 지원하지 않으며 일부 채널은 적응형 카드만 부분적으로만 지원할 수 있습니다. 예를 들어 Facebook에서 적응형 카드를 보내는 경우 텍스트와 이미지가 잘 작동하는 동안에는 단추가 작동하지 않습니다. 메시지 팩터리는 만들기 단계를 자동화하는 데 사용되는 Bot Framework SDK 도우미 클래스입니다.
적응형 카드는 개발자가 공통적이고 일관된 방식으로 UI 콘텐츠를 교환할 수 있도록 하는 개방형 카드 교환 형식입니다. 그러나 모든 채널이 적응형 카드를 지원하는 것은 아닙니다.
적응형 카드 디자이너는 적응형 카드 작성하기 위한 풍부한 대화형 디자인 타임 환경을 제공합니다.
참고 항목
봇에서 사용할 채널을 사용하여 이 기능을 테스트하여 해당 채널이 적응형 카드 지원하는지 여부를 확인해야 합니다.
// Cards are sent as Attachments in the Bot Framework.
// So we need to create a list of attachments for the reply activity.
var attachments = new List<Attachment>();
// Reply to the activity we received with an activity.
var reply = MessageFactory.Attachment(attachments);
그런 다음 첨부 파일을 추가하고 레이아웃 유형을 회전식으로 설정합니다.
여기서는 한 번에 하나씩 추가하지만 원하는 카드 추가하도록 목록을 자유롭게 조작할 수 있습니다.
// Display a carousel of all the rich card types.
reply.AttachmentLayout = AttachmentLayoutTypes.Carousel;
reply.Attachments.Add(Cards.CreateAdaptiveCardAttachment());
reply.Attachments.Add(Cards.GetAnimationCard().ToAttachment());
reply.Attachments.Add(Cards.GetAudioCard().ToAttachment());
reply.Attachments.Add(Cards.GetHeroCard().ToAttachment());
reply.Attachments.Add(Cards.GetOAuthCard().ToAttachment());
reply.Attachments.Add(Cards.GetReceiptCard().ToAttachment());
reply.Attachments.Add(Cards.GetSigninCard().ToAttachment());
reply.Attachments.Add(Cards.GetThumbnailCard().ToAttachment());
reply.Attachments.Add(Cards.GetVideoCard().ToAttachment());
첨부 파일이 추가되면 다른 항목과 마찬가지로 회신을 보낼 수 있습니다.
// Send the card(s) to the user as an attachment to the activity
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
// Cards are sent as Attachments in the Bot Framework.
// So we need to create a list of attachments for the reply activity.
List<Attachment> attachments = new ArrayList<>();
// Reply to the activity we received with an activity.
Activity reply = MessageFactory.attachment(attachments);
그런 다음 첨부 파일을 추가하고 레이아웃 유형을 회전식으로 설정합니다.
여기서는 한 번에 하나씩 추가하지만 원하는 카드 추가하도록 목록을 자유롭게 조작할 수 있습니다.
// Display a carousel of all the rich card types.
reply.setAttachmentLayout(AttachmentLayoutTypes.CAROUSEL);
reply.getAttachments().add(Cards.createAdaptiveCardAttachment());
reply.getAttachments().add(Cards.getAnimationCard().toAttachment());
reply.getAttachments().add(Cards.getAudioCard().toAttachment());
reply.getAttachments().add(Cards.getHeroCard().toAttachment());
reply.getAttachments().add(Cards.getOAuthCard().toAttachment());
reply.getAttachments().add(Cards.getReceiptCard().toAttachment());
reply.getAttachments().add(Cards.getSigninCard().toAttachment());
reply.getAttachments().add(Cards.getThumbnailCard().toAttachment());
reply.getAttachments().add(Cards.getVideoCard().toAttachment());
첨부 파일이 추가되면 다른 항목과 마찬가지로 회신을 보낼 수 있습니다.
// Send the card(s) to the user as an attachment to the activity
return stepContext.getContext().sendActivity(reply)
# Send the card(s) to the user as an attachment to the activity
await step_context.context.send_activity(reply)
적응형 카드 입력 처리를 위한 코드 샘플
다음 샘플에서는 봇 대화 상자 클래스 내에서 적응형 카드 입력을 사용하는 한 가지 방법을 보여 줍니다.
응답 클라이언트에서 텍스트 필드에 수신된 입력의 유효성을 검사하여 hero 카드s 샘플을 확장합니다.
먼저 리소스 폴더에 있는 adaptiveCard.json 마지막 대괄호 바로 앞에 다음 코드를 추가하여 기존 적응 카드 텍스트 입력 및 단추 기능을 추가해야 합니다.
유효성 검사기는 Newtonsoft.json 사용하여 먼저 이를 변환한 다음 비교를 JObject위해 잘려진 텍스트 문자열을 만듭니다. 따라서 MainDialog.cs에 다음을 추가합니다.
using System;
using System.Linq;
using Newtonsoft.Json.Linq;
를 MainDialog.cs Newtonsoft.Json의 안정적인 최신 NuGet 패키지를 설치합니다.
유효성 검사기 코드에서 코드 주석에 논리 흐름을 추가했습니다.
이 ChoiceValidator 메서드는 MainDialog 선언을 위해 닫힌 중괄호 public 바로 다음에 using 카드s 샘플에 배치됩니다.
private async Task ChoiceValidator(
PromptValidatorContext promptContext,
CancellationToken cancellationToken)
{
// Retrieves Adaptive Card comment text as JObject.
// looks for JObject field "text" and converts that input into a trimmed text string.
var jobject = promptContext.Context.Activity.Value as JObject;
var jtoken = jobject?["text"];
var text = jtoken?.Value().Trim();
// Logic: 1. if succeeded = true, just return promptContext
// 2. if false, see if JObject contained Adaptive Card input.
// No = (bad input) return promptContext
// Yes = update Value field with JObject text string, return "true".
if (!promptContext.Recognized.Succeeded && text != null)
{
var choice = promptContext.Options.Choices.FirstOrDefault(
c => c.Value.Equals(text, StringComparison.InvariantCultureIgnoreCase));
if (choice != null)
{
promptContext.Recognized.Value = new FoundChoice
{
Value = choice.Value,
};
return true;
}
}
return promptContext.Recognized.Succeeded;
}
이제 선언 변경 내용에서 위와 같습니다 MainDialog .
// Define the main dialog and its related components.
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
다음과 같이 변경합니다.
// Define the main dialog and its related components.
AddDialog(new ChoicePrompt(nameof(ChoicePrompt), ChoiceValidator));
그러면 새 선택 프롬프트가 생성될 때마다 유효성 검사기가 호출되어 적응형 카드 입력을 찾습니다.
기본Dialog.js 열고 run 메서드 async run(turnContext, accessor) 를 찾습니다. 이 메서드는 들어오는 작업을 처리합니다.
호출 dialogSet.add(this); 직후에 다음을 추가합니다.
// The following check looks for a non-existent text input
// plus Adaptive Card input in _activity.value.text
// If both conditions exist, the Activity Card text
// is copied into the text input field.
if(turnContext._activity.text == null
&& turnContext._activity.value.text != null) {
this.logger.log('replacing null text with Activity Card text input');
turnContext._activity.text = turnContext._activity.value.text;
}
이 검사 클라이언트에서 존재하지 않는 텍스트 입력을 찾으면 적응형 카드의 입력이 있는지 확인합니다.
적응형 카드 입력이 _activity.value.text있는 경우 이를 일반 텍스트 입력 필드에 복사합니다.
유효성 검사기는 com.microsoft.bot.schema의 Serialization 도우미를 사용하여 먼저 이를 변환JsonNode한 다음 비교를 위해 잘려진 텍스트 문자열을 만듭니다. 이 작업을 완료하려면 몇 가지 다른 가져오기도 필요하므로 다음을 추가합니다.
을 MainDialog.java.
유효성 검사기 코드에서 코드 주석에 논리 흐름을 추가했습니다.
이 PromptValidator 식은 MainDialog 선언을 위해 닫힌 중괄호 공용 바로 다음에 있는 Using 카드s 샘플에 배치됩니다.
PromptValidator<FoundChoice> validator = (promptContext) -> {
// Retrieves Adaptive Card comment text as JObject.
// looks for JObject field "text" and converts that input into a trimmed text
// string.
JsonNode jsonNode = Serialization.getAs(promptContext.getContext().getActivity().getValue(), JsonNode.class);
JsonNode textNode = jsonNode != null ? jsonNode.get("text") : null;
String text = textNode != null ? textNode.textValue() : "";
// Logic: 1. if succeeded = true, just return promptContext
// 2. if false, see if JObject contained Adaptive Card input.
// No = (bad input) return promptContext
// Yes = update Value field with JObject text string, return "true".
if (!promptContext.getRecognized().getSucceeded() && text != null) {
Optional<Choice> choice = promptContext.getOptions()
.getChoices()
.stream()
.filter(c -> StringUtils.compareIgnoreCase(c.getValue(), text) == 0)
.findFirst();
if (choice.isPresent()) {
promptContext.getRecognized().setValue(new FoundChoice() {
{
setValue(choice.get().getValue());
}
});
return CompletableFuture.completedFuture(true);
}
}
return CompletableFuture.completedFuture(promptContext.getRecognized().getSucceeded());
};
이제 선언 변경 내용에서 위와 같습니다 MainDialog .
// Define the main dialog and its related components.
addDialog(new ChoicePrompt("ChoicePrompt"));
다음과 같이 변경합니다.
// Define the main dialog and its related components.
addDialog(new ChoicePrompt("ChoicePrompt", validator, null));
그러면 새 선택 프롬프트가 생성될 때마다 유효성 검사기가 호출되어 적응형 카드 입력을 찾습니다.
제안된 작업이 포함된 활동을 만들고 사용자에게 보냅니다.
이 choice_validator 메서드는 다음 선언MainDialog을 위해 닫힌 중괄호 public 바로 다음에 있는 Using 카드s 샘플에 배치됩니다.
@staticmethod
async def choice_validator(prompt_context: PromptValidatorContext) -> bool:
if prompt_context.context.activity.value:
text = prompt_context.context.activity.value["text"].lower()
if not prompt_context.recognized.succeeded and text:
matching_choices = [choice for choice in prompt_context.options.choices if choice.value.lower() == text]
if matching_choices:
choice = matching_choices[0]
prompt_context.recognized.value = FoundChoice(
value=choice.value,
index=0,
score=1.0
)
return True
return prompt_context.recognized.succeeded