2016-08-19 85 views
3

與微軟的Luis + bot框架一起玩,我的「這會讓一個好的類型提供者」感覺開始刺痛。不幸的是,類型提供者不能輸出歧視聯盟。我希望做一些像下面,但它是不可能的:爲Microsoft的Luis編寫F#Type Provider有什麼好方法?

type Luis = LuisProvider<@"LuisId",@"LuisPasskey"> 
let IntentMatcher Intent = 
    match intent with 
    | Luis.Intents.Greeting -> GreetingHandler() 
    | Luis.Intents.SetAlarm title startDate startTime -> AlarmHandler title startDate startTime 
    | _ -> CouldNotUnderstand() 

的路易斯意圖及其參數都可以通過API使他們極大的候選人typeProviderization

僅供參考這裏是一個從一個例子C#機器人處理器(我想這可能是更清潔,更型F#安全):

public const string Entity_Alarm_Title = "builtin.alarm.title"; 
public const string Entity_Alarm_Start_Time = "builtin.alarm.start_time"; 
public const string Entity_Alarm_Start_Date = "builtin.alarm.start_date"; 
public const string DefaultAlarmWhat = "default"; 

[LuisIntent("builtin.intent.alarm.set_alarm")] 
public async Task SetAlarm(IDialogContext context, LuisResult result) 
{ 
     EntityRecommendation title; 
     if (!result.TryFindEntity(Entity_Alarm_Title, out title)) 
     { 
      title = new EntityRecommendation(type: Entity_Alarm_Title) { Entity = DefaultAlarmWhat }; 
     } 
     EntityRecommendation date; 
     if (!result.TryFindEntity(Entity_Alarm_Start_Date, out date)) 
     { 
      date = new EntityRecommendation(type: Entity_Alarm_Start_Date) { Entity = string.Empty }; 
     } 
     EntityRecommendation time; 
     if (!result.TryFindEntity(Entity_Alarm_Start_Time, out time)) 
     { 
      time = new EntityRecommendation(type: Entity_Alarm_Start_Time) { Entity = string.Empty }; 
     } 
     var parser = new Chronic.Parser(); 
     var span = parser.Parse(date.Entity + " " + time.Entity); 
     if (span != null) 
     { 
      var when = span.Start ?? span.End; 
      var alarm = new Alarm() { What = title.Entity, When = when.Value }; 
      this.alarmByWhat[alarm.What] = alarm; 
      string reply = $"alarm {alarm} created"; 
      await context.PostAsync(reply); 
     } 
     else 
     { 
      await context.PostAsync("could not find time for alarm"); 
     } 
     context.Wait(MessageReceived); 
} 

但無論如何,問題是:有沒有人有更多經驗的建築類型供應商對我哪有什麼好主意構建一個可讀的dsl,即ac完全可行的構建?

回答

7

我不是特別熟悉的BOT框架,但我可以識別聯合評論 - 我們在F#中的數據面臨着類似的問題。

如果你有<One name="string" /><Two id="42" />,這將是很好的提供歧視聯盟與案件One of stringTwo of int。我們做的,而不是什麼是我們提供一個類型:

type OneOrTwo = 
    member One : option<string> 
    member Two : option<int> 

你可以遵循相同的模式,揭露API,它看起來是這樣的:

type Luis = LuisProvider<"LuisId", "LuisPasskey"> 

let intentMatcher (intent:Luis.Intents) = 
    match intent.Greetings, intent.SetAlarm with 
    | Some(), _ -> greetingHandler() 
    | _, Some(title, startDate, startTime) -> alarmHandler title startDate startTime 
    | _ -> couldNotUnderstand() 

Luis.Connect().OnIntent 
|> Observable.subscribe intentMatcher 

這是不太識別聯合優雅,但它應該是技術上可行的。

我想,另一種方法是暴露的個人行動作爲單獨的事件處理程序,然後你可以寫這樣的事情:

type Luis = LuisProvider<"LuisId", "LuisPasskey"> 

let luis = Luis.Connect() 

luis.BuiltIn.Greetings 
|> Observable.add greetingHandler 

luis.BuiltIn.SetAlarm 
|> Observable.add (fun (title, startDate, startTime) -> 
    alarmHandler title startDate startTime) 

現在我想想,這很可能是更好的,但它取決於bot框架的典型用途。

+0

托馬斯你是明星!後者的兩個看起來很完美:) –

相關問題