-
Notifications
You must be signed in to change notification settings - Fork 481
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor DanceAiClient code #54851
Refactor DanceAiClient code #54851
Conversation
apps/src/dance/ai/DanceAiClient.ts
Outdated
const outputWeightsForSelectedEmojis: {[key: string]: number[]} = {}; | ||
for (const output in cachedWeightsMappings) { | ||
outputWeightsForSelectedEmojis[output] = calculateOutputWeightsVector( | ||
selectedEmojis, | ||
cachedWeightsMappings[output] | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not blocking at all, but I'd tend to do something like this in a single statement with a reduce:
const outputWeightsForSelectedEmojis: {[key: string]: number[]} =
Object.entries(cachedWeightsMappings).reduce( (bucket, [key, cachedMapping]) => (
{ ...bucket, [key] : calculateOutputWeightsVector(selectedEmojis, cachedMapping) }
), {} )
(not tested, so there may be typos)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to keep things as easy to understand for future readers not familiar with context so I think I may keep as is for that reason.
apps/src/dance/ai/DanceAiClient.ts
Outdated
quality === ChooseEffectsQuality.GOOD | ||
? options.slice(0, numRandomOptions) | ||
: options.slice(-numRandomOptions); | ||
allOutputOptions[output] = topOrBottomOptions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment as above about doing this in a reduce vs the external define + for/in.
const selectedOutputOption = | ||
outputOptions[Math.floor(Math.random() * outputOptions.length)]; | ||
chosenEffects[output as keyof GeneratedEffect] = selectedOutputOption[1]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and again, could be a reduce. But doesn't have to be. 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
couple of non-blocking stylistic suggestions about using a reduce
instead of a for/in
, but definitely not blocking.
otherwise, lgtm 🚀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great changes - thanks for doing this! Just had a few comments for further refactoring
apps/src/dance/ai/DanceAiClient.ts
Outdated
|
||
// Sort and slice top scoring options, mapped to their output identifiers (e.g. [[0.25, 'squiggles'], ...]) | ||
// Obtain final output summed weights based on set of three selected emoji inputs | ||
const cachedWeightsMappings: {[key: string]: CachedWeightsMapping} = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: for extra type safety, you could even make this {[key in FieldKey]: CachedWeightsMapping}
apps/src/dance/ai/DanceAiClient.ts
Outdated
|
||
// Sort and slice top scoring options, mapped to their output identifiers (e.g. [[0.25, 'squiggles'], ...]) | ||
// Obtain final output summed weights based on set of three selected emoji inputs | ||
const cachedWeightsMappings: {[key: string]: CachedWeightsMapping} = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also minor - could this be declared outside of this function (alongside CachedPalettes
, etc) since it's always the same for every function invocation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! And removed the individual mappings variables since no longer needed!
// selectedEmojiAssociations is an array of 3 subarrays. Each subarray contains | ||
// the weights ranging from [0, 1] for the selected emojis for a particular output type) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't have to, but if we want to get super strict about this, we can enforce these length requirements with TS directly - something like type EmojiAssociations = [number[], number[], number[]]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried [number, number, number]
but got back the error:
'Type 'number[]' is not assignable to type '[number, number, number]'.
Target requires 3 element(s) but source may have fewer.'
I tried changing type of param emojis
to [string, string, string]
but error still persisted for some reason. So changed back return type back to number[]
.
apps/src/dance/ai/DanceAiClient.ts
Outdated
const allOutputOptions: {[key: string]: [number, string][]} = {}; | ||
for (const output in outputSummedWeightsForSelectedEmojis) { | ||
const weightVector = outputSummedWeightsForSelectedEmojis[output]; | ||
const options = obtainOptions(weightVector, cachedWeightsMappings[output]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While we're here - would it make sense to rename this function to something like get/obtainSortedOptions
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to getSortedOptions
.
apps/src/dance/ai/DanceAiClient.ts
Outdated
}; | ||
|
||
// Select a random option for each output type from the top or bottom scoring options. | ||
for (const output in allOutputOptions) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
General comment about the whole function: If I'm reading this correctly, it looks like we have three for loops that iterate over the same options each time. We're also accessing cachedWeightsMappings[output]
a couple different times. Could we organize this with just one loop so we just do the full pass for each output type once? Something like
for (const field of [FieldKey.BACKGROUND_EFFECT, FieldKey.FOREGROUND_EFFECT, ...]) {
const mapping = cachedWeightsMappings[field];
const weightVector = calculateOutputSummedWeights(emojis, mapping);
const options = obtainOptions(weightVector, mapping);
// ... calculate top options, randomly select, etc
chosenEffects[field] = effect;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this idea. Will do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
apps/src/dance/ai/DanceAiClient.ts
Outdated
for (const field of [ | ||
FieldKey.BACKGROUND_EFFECT, | ||
FieldKey.FOREGROUND_EFFECT, | ||
FieldKey.BACKGROUND_PALETTE, | ||
]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah I guess this could also just be for (const field of Object.keys(chosenEffects)
since that's already been declared
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to for (const field of Object.keys(chosenEffects) as FieldKey[]) {
thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh interesting that you need to cast with Object.keys
- as an alternative, I think you could also use for (const field of Object.values(FieldKey)
and I think that shouldn't require a cast (just tried manually). If you prefer, you could also use that below in the helper function that iterates through the same keys.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Just pushed change.
This PR updates
DanceAiClient.ts
for easier readability; there is no change in functionality.I replaced lists with maps, renamed variables/functions and added/updated comments. In particular, I updated comments so that recent changes are reflected, e.g., using Ada instead of Spacy model values and retrieving the top 3 or bottom 3 options based on
ChooseEffectsQuality
.Links
Testing story
Deployment strategy
Follow-up work
Privacy
Security
Caching
PR Checklist: