Fixes backspace handling and duplicated suggestions.

This commit is contained in:
jahorton 2019-07-01 13:33:24 +07:00
parent 0a0cfd0e97
commit bb3a83b7c8
3 changed files with 60 additions and 12 deletions

View file

@ -9,10 +9,21 @@ class ModelCompositor {
predict(transformDistribution: Transform | Distribution<Transform>, context: Context): Suggestion[] {
let suggestionDistribution: Distribution<Suggestion> = [];
// Assumption: Duplicated 'displayAs' properties indicate duplicated Suggestions.
// When true, we can use an associated array to de-duplicate everything.
let suggestionDistribMap: {[key: string]: ProbabilityMass<Suggestion>} = {};
if(!(transformDistribution instanceof Array)) {
transformDistribution = [ {sample: transformDistribution, p: 1.0} ];
}
// Find the transform for the actual keypress.
let inputTransform = transformDistribution.sort(function(a, b) {
return b.p - a.p;
})[0].sample;
let inputResult = [];
for(let alt of transformDistribution) {
let transform = alt.sample;
let distribution = this.lexicalModel.predict(transform, context);
@ -24,15 +35,24 @@ class ModelCompositor {
pair.sample.transformId = transform.id;
}
let compositedPair = {sample: pair.sample, p: pair.p * alt.p};
suggestionDistribution.push(compositedPair);
// Combine duplicate samples.
let s = suggestionDistribMap[pair.sample.displayAs];
if(s) {
s.p += pair.p * alt.p;
} else {
let compositedPair = {sample: pair.sample, p: pair.p * alt.p};
//suggestionDistribution.push(compositedPair);
suggestionDistribMap[pair.sample.displayAs] = compositedPair;
}
});
}
// Now that we've calculated the set of probability masses, time to join 'em together
// and return the most likely candidates.
// TODO: What if the model emits duplicate samples, each with their own mass?
// Now that we've calculated a unique set of probability masses, time to make them into a proper
// distribution and prep for return.
for(let key in suggestionDistribMap) {
let pair = suggestionDistribMap[key];
suggestionDistribution.push(pair);
}
suggestionDistribution = suggestionDistribution.sort(function(a, b) {
return b.p - a.p; // Use descending order - we want the largest probabilty suggestions first!

View file

@ -0,0 +1,25 @@
namespace models {
export class Common {
static applyTransform(transform: Transform, context: Context): Context {
// First, get the current context
let fullLeftContext = context.left || '';
let lLen = fullLeftContext.length;
let lDel = lLen < transform.deleteLeft ? lLen : transform.deleteLeft;
let leftContext = fullLeftContext.substr(0, lLen - lDel) + (transform.insert || '');
let fullRightContext = context.right || '';
let rLen = fullRightContext.length;
let rDel = rLen < transform.deleteRight ? rLen : transform.deleteRight;
let rightContext = fullRightContext.substr(rDel);
return {
left: leftContext,
right: rightContext,
startOfBuffer: context.startOfBuffer,
endOfBuffer: context.endOfBuffer
};
}
}
}

View file

@ -23,6 +23,7 @@
*/
/// <reference path="../word_breaking/placeholder-word-breaker.ts" />
/// <reference path="common.ts" />
/**
* @file trie-model.ts
@ -101,13 +102,15 @@
})));
}
// EVERYTHING to the left of the cursor:
let fullLeftContext = context.left || '';
// Stuff to the left of the cursor in the current word.
let leftContext = this.getLastWord(fullLeftContext);
// Compute the results of the keystroke:
let newContext = Common.applyTransform(transform, context);
// Computes the different in word length after applying the transform above.
let leftDelOffset = transform.deleteLeft - transform.insert.length;
// All text to the left of the cursor INCLUDING anything that has
// just been typed.
let prefix = leftContext + (transform.insert || '');
let prefix = this.getLastWord(newContext.left);
// Return suggestions from the trie.
return makeDistribution(this._trie.lookup(prefix).map(({text, p}) => ({
@ -117,7 +120,7 @@
// Delete whatever the prefix that the user wrote.
// Note: a separate capitalization/orthography engine can take this
// result and transform it as needed.
deleteLeft: leftContext.length,
deleteLeft: leftDelOffset + prefix.length,
},
displayAs: text,
p: p