gpt4 book ai didi

c# - LUIS Bot 框架不会从外部调用中调用 Intent

转载 作者:行者123 更新时间:2023-11-30 18:18:49 24 4
gpt4 key购买 nike

我为我的 BOT 实现了外部登录。当外部站点调用 Bot CallBack 方法时,我需要在 PrivateConversationData 中设置 token 和用户名,然后使用 “Welcome back [username]!” 等消息恢复聊天。

为了显示此消息,我发送了一个 MessageActivity,但此事件从未连接到我的聊天并且不会触发适当的 [LuisIntent("UserIsAuthenticated")]

登录流程之外的其他意图按预期工作。

这是回调方法:

public class OAuthCallbackController : ApiController
{
[HttpGet]
[Route("api/OAuthCallback")]
public async Task OAuthCallback([FromUri] string userId, [FromUri] string botId, [FromUri] string conversationId,
[FromUri] string channelId, [FromUri] string serviceUrl, [FromUri] string locale,
[FromUri] CancellationToken cancellationToken, [FromUri] string accessToken, [FromUri] string username)
{
var resumptionCookie = new ResumptionCookie(TokenDecoder(userId), TokenDecoder(botId),
TokenDecoder(conversationId), channelId, TokenDecoder(serviceUrl), locale);

var container = WebApiApplication.FindContainer();

var message = resumptionCookie.GetMessage();
message.Text = "UserIsAuthenticated";

using (var scope = DialogModule.BeginLifetimeScope(container, message))
{
var botData = scope.Resolve<IBotData>();
await botData.LoadAsync(cancellationToken);

botData.PrivateConversationData.SetValue("accessToken", accessToken);
botData.PrivateConversationData.SetValue("username", username);

ResumptionCookie pending;
if (botData.PrivateConversationData.TryGetValue("persistedCookie", out pending))
{
botData.PrivateConversationData.RemoveValue("persistedCookie");
await botData.FlushAsync(cancellationToken);
}

var stack = scope.Resolve<IDialogStack>();
var child = scope.Resolve<MainDialog>(TypedParameter.From(message));
var interruption = child.Void<object, IMessageActivity>();

try
{
stack.Call(interruption, null);

await stack.PollAsync(cancellationToken);
}
finally
{
await botData.FlushAsync(cancellationToken);
}
}
}
}

public static string TokenDecoder(string token)
{
return Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(token));
}
}

这是 Controller :

public class MessagesController : ApiController
{
private readonly ILifetimeScope scope;

public MessagesController(ILifetimeScope scope)
{
SetField.NotNull(out this.scope, nameof(scope), scope);
}

public async Task<HttpResponseMessage> Post([FromBody] Activity activity, CancellationToken token)
{
if (activity != null)
{
switch (activity.GetActivityType())
{
case ActivityTypes.Message:
using (var scope = DialogModule.BeginLifetimeScope(this.scope, activity))
{
var postToBot = scope.Resolve<IPostToBot>();
await postToBot.PostAsync(activity, token);
}
break;
}
}

return new HttpResponseMessage(HttpStatusCode.Accepted);
}
}

这是我注册组件的方式:

protected override void Load(ContainerBuilder builder)
{
base.Load(builder);

builder.Register(
c => new LuisModelAttribute("myId", "SubscriptionKey"))
.AsSelf()
.AsImplementedInterfaces()
.SingleInstance();

builder.RegisterType<MainDialog>().AsSelf().As<IDialog<object>>().InstancePerDependency();

builder.RegisterType<LuisService>()
.Keyed<ILuisService>(FiberModule.Key_DoNotSerialize)
.AsImplementedInterfaces()
.SingleInstance();
}

这是对话框:

[Serializable]
public sealed class MainDialog : LuisDialog<object>
{
public static readonly string AuthTokenKey = "TestToken";
public readonly ResumptionCookie ResumptionCookie;
public static readonly Uri CloudocOauthCallback = new Uri("http://localhost:3980/api/OAuthCallback");

public MainDialog(IMessageActivity activity, ILuisService luis)
: base(luis)
{
ResumptionCookie = new ResumptionCookie(activity);
}

[LuisIntent("")]
public async Task None(IDialogContext context, LuisResult result)
{
await context.PostAsync("Sorry cannot understand!");
context.Wait(MessageReceived);
}

[LuisIntent("UserAuthenticated")]
public async Task UserAuthenticated(IDialogContext context, LuisResult result)
{
string username;
context.PrivateConversationData.TryGetValue("username", out username);

await context.PostAsync($"Welcome back {username}!");
context.Wait(MessageReceived);
}

[LuisIntent("Login")]
private async Task LogIn(IDialogContext context, LuisResult result)
{
string token;
if (!context.PrivateConversationData.TryGetValue(AuthTokenKey, out token))
{
context.PrivateConversationData.SetValue("persistedCookie", ResumptionCookie);

var loginUrl = CloudocHelpers.GetLoginURL(ResumptionCookie, OauthCallback.ToString());

var reply = context.MakeMessage();

var cardButtons = new List<CardAction>();
var plButton = new CardAction
{
Value = loginUrl,
Type = ActionTypes.Signin,
Title = "Connetti a Cloudoc"
};
cardButtons.Add(plButton);
var plCard = new SigninCard("Connect", cardButtons);

reply.Attachments = new List<Attachment>
{
plCard.ToAttachment()
};

await context.PostAsync(reply);
context.Wait(MessageReceived);
}
else
{
context.Done(token);
}
}
}

我错过了什么?

更新

还尝试在回调方法中使用 ResumeAsync:

var container = WebApiApplication.FindContainer();

var message = resumptionCookie.GetMessage();
message.Text = "UserIsAuthenticated";

using (var scope = DialogModule.BeginLifetimeScope(container, message))
{
var botData = scope.Resolve<IBotData>();
await botData.LoadAsync(cancellationToken);

botData.PrivateConversationData.SetValue("accessToken", accessToken);
botData.PrivateConversationData.SetValue("username", username);

ResumptionCookie pending;
if (botData.PrivateConversationData.TryGetValue("persistedCookie", out pending))
{
botData.PrivateConversationData.RemoveValue("persistedCookie");
await botData.FlushAsync(cancellationToken);
}

await Conversation.ResumeAsync(resumptionCookie, message, cancellationToken);
}

但它给我错误Operation is not valid due to the current state of the object.

更新 2

正在关注 Ezequiel想法我这样改变了我的代码:

    [HttpGet]
[Route("api/OAuthCallback")]
public async Task OAuthCallback(string state, [FromUri] string accessToken, [FromUri] string username)
{
var resumptionCookie = ResumptionCookie.GZipDeserialize(state);
var message = resumptionCookie.GetMessage();
message.Text = "UserIsAuthenticated";

await Conversation.ResumeAsync(resumptionCookie, message);
}

resumptionCookie 似乎没问题:

enter image description here

但是 await Conversation.ResumeAsync(resumptionCookie, message); 继续给我错误 Operation is not valid due to the current state of the object.

最佳答案

您需要恢复与机器人的对话,这就是消息可能未到达的原因。

尝试使用

而不是使用对话框堆栈
await Conversation.ResumeAsync(resumptionCookie, message);

根据您的身份验证需求,您可能需要考虑 AuthBot .您还可以查看 logic在库的 OAuthCallback Controller 上了解他们如何在授权后恢复与机器人的对话。

ContosoFlowers例如,也在使用 resume conversation mechanism .不是为了验证目的,而是为了展示如何处理虚拟信用卡付款。

关于c# - LUIS Bot 框架不会从外部调用中调用 Intent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40484662/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com