Skip to content
This repository has been archived by the owner on May 6, 2022. It is now read-only.

NLU returns an empty slot instead of crashing #83

Merged
merged 6 commits into from
Jun 3, 2020

Conversation

noelweichbrodt
Copy link
Collaborator

Does what it says on the tin. For example, "take a selfie" in ios-studio results in NLUError.metadata("Could not find a slot called item in NLU model metadata.").

Copy link
Contributor

@space-pope space-pope left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change looks good on its own. If I'm reading things correctly, though, in order to have full parity across all platforms, we need iOS to ensure that all slots present in the metadata for a given intent are represented in the parser's return value. Slots not tagged by the model get a nil value. Right now, we're only returning slots that the model finds in the input.

@noelweichbrodt
Copy link
Collaborator Author

@space-pope nlu classification output now includes all slots defined by the classified intent

Spokestack/NLUTensorflowSlotParsers.swift Outdated Show resolved Hide resolved
// Go over the slots defined by the intent, checking if each one has a value in the model output.
try intent.slots.reduce(into: [:], { (result, intentSlot) in
// Check the dictionary of slot name keys with input token values to see if there's a match for this intent slot.
let taggedSlotValues = tagsToTokens.filter({ $0.key == intentSlot.name })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't tagsToTokens a dictionary? So

if let tokenIndices = tagsToTokens[intentSlot.name] {
    // decode and parse tokenIndices
    result[intentSlot.name] = parsedSlot
} else {
  result[intentSlot.name] = emptySlot
}

And while we're at it, this doesn't really need to be a reduction; it might be easier to read as a dictionary followed by a for-loop to populate.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, that's what i kept trying to get to here, thanks

// Check the dictionary of slot name keys with input token values to see if there's a match for this intent slot.
let taggedSlotValues = tagsToTokens.filter({ $0.key == intentSlot.name })
if taggedSlotValues.isEmpty {
// no match, so hyrdate this intent slot with nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// no match, so hyrdate this intent slot with nil
// no match, so hydrate this intent slot with nil

The judges would also have accepted "include an empty slot"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the judge here

SpokestackTests/NLUTensorflowSlotParserTest.swift Outdated Show resolved Hide resolved
// Slots declared by an intent but not tagged by the model are returned to the caller in the output with a null value
let taggedInputEmpty = ["o", "o"]
let parsedEmpty = try! parser.parse(tags: taggedInputEmpty, intent: metadata!.intents.filter({ $0.name == "i.i" }).first!, encoder: encoder!, encodedTokens: et)
XCTAssertNil(parsedEmpty!["iMi"]!.value)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The number of exclamation points in the last two lines here is horrifically amusing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Swifty!

noelweichbrodt and others added 2 commits June 3, 2020 16:21
Co-authored-by: Josh <space-pope@users.noreply.github.com>
Copy link
Contributor

@space-pope space-pope left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good; thanks for all the revisions.

There is one other thing I just noticed, but it's sort of out of the scope of these changes: it doesn't look like Slot includes the original string tagged in the utterance (before we've parsed it into a concrete type). This is pretty much only useful in the case of selsets to give the caller both the normalized and observed value of the slot, but it is something that the other two platforms do.

// Iterate over the slots defined by the intent, checking if each one has a value in the model output.
for slot in intent.slots {
if let tokenIndices = tagsToTokens[slot.name] {
// decode and parse tokenIndices
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, this comment was in the suggestion just as a placeholder for "I'm not actually writing the code for this", but I'll take it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was much simpler than my comment

@@ -14,7 +14,7 @@ import Foundation
/// - Remark: ex: "up,dog"
/// - Warning: cannot contain spaces
/// - SeeAlso: `AppleWakewordRecognizer`
@objc public var wakewords: String = "spokestack, spoke stack"
@objc public var wakewords: String = "spokestack, spoke stack, smokestack, smoke stack"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sneaky sneaky

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕵🏼‍♀️

Copy link
Contributor

@space-pope space-pope left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice; simpler than I thought...not having thought about the actual implementation.

@noelweichbrodt
Copy link
Collaborator Author

Cool, thanks for the feedback, this ended up simpler and better documented than before, with a nice additional feature.

@noelweichbrodt noelweichbrodt merged commit 836fdd6 into master Jun 3, 2020
@noelweichbrodt noelweichbrodt deleted the ndw-unspecified-slot branch June 3, 2020 21:51
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants