B-Day Buddy: Unleashing laughter and love in every language!
Katerina Chernevskaya
????Principal Microsoft Cloud Architect (Power Platform & Azure AI) ||?? AI unlocks opportunities, low-code provides tools, I transform them into business impact. ||??BizApps MVP || ??MCT || ??Speaker
Do you sometimes feel a bit rushed when a birthday notification appears? If so, I have a solution designed for ease and creativity. The new app, powered by Azure OpenAI, transforms ordinary birthday messages into unique and heartfelt greetings.
?
This app takes a step further by incorporating a global touch. Each wish is translated into a random language and then audibly pronounced. This 24/7 service ensures your birthday messages are always distinctive and memorable, offering a serene shift away from the usual "Happy Birthday" routine.
?
And, of course, UX! B-Day Buddy's modern, one-button interface makes it highly user-friendly.
?
Would you like to start playing with the app immediately? You can follow the link to GitHub to download the whole solution at the end of this article.
??
Solution overview
The solution includes the following components:
?
I will cover creating a custom connector in one of my upcoming articles. In this article, let's explore how to build a one-button, one-screen B-Day Buddy app.
?
B-Day Buddy app overview
This app uses using following main controls:
?
Below, I'll highlight the key parts of the app.
You can notice that some code includes the Trace function, which allows for collecting usage statistics for Azure Application Insights. You can add your instrumentation key to the app and collect the statistics.
Live background
I used a live background with pink and purple colors to add some dynamics to the app. This can be achievable with CSS and Image control. The code for the Image control is below:
"data:image/svg+xml;utf8, "& EncodeUrl("
???<svg xmlns='https://www.w3.org/2000/svg' viewBox='0 0 200 200'>
???<defs>
???????<linearGradient id='gradient' x1='0%' y1='0%' x2='100%' y2='100%'>
???????<stop offset='0%' stop-color='#E63B86'/>
???????<stop offset='10%' stop-color='#83158E'/>
???????<stop offset='60%' stop-color='#570F89'/>
???????<stop offset='100%' stop-color='#250C6B'/>
???????</linearGradient>
???</defs>
???<style>
???????.background {
???????fill: url(#gradient);
???????animation: transition 10s ease infinite alternate;
???????}
???????@keyframes transition {
???????from {transform:translateX(-300%)}
???????to {transform:translateX(0%)}
???????}?????
???</style>
???<g class='background'>
???????<rect width='1000' height='" & Parent.Height & "'/>
???</g>
???</svg>
")
By the way, if you would like to know more about how to enhance the UI/UX of your Canvas apps, follow Kristine Kolodziejski ??? ; she is the Queen of this magic ????
??
Declare app's variables and collections
When the app launches, we declare all variables and collections used for storing data and the app logic.
?Concurrent(
???// Play mode: false - waiting Push Me from the user; true - ready to play
???Set(_mode, false),
???// start - before loading; play - in play process; next - a wish has been played, but there is at least 1 more wish; end - all 10 wishes was played
???Set(_iteration, "start"),
???Clear(_wishesList),
???Clear(_wishesListForPlay),
???Set(_wishNum, 0),
???// false - not ready to play wish; true - ready to play and start a small delay before playing
???Set(_timerPause, false),
???Set(_audioOn, false),
???Set(_env,
???????LookUp(
???????????'Environment Variable Values',
???????????'Environment Variable Definition'.'Schema Name' = "kch_EnvironmentName"
???????).Value
???),
???Set(_prompt,
???????LookUp(
???????????'Environment Variable Values',
???????????'Environment Variable Definition'.'Schema Name' = "kch_BDayPrompt"
???????).Value
???)
);
?
//Add Application Insights Trace
???Trace(
???????"B-Day Buddy",
???????TraceSeverity.Information,
???????{
???????????UserName: User().FullName,
???????????UserEmail: User().Email,
???????????Environment: _env,
???????????Action: "Open the app"
???????}
???)
Variables:
_mode - identify if the app is ready to generate wishes, or if wishes has been requested
_iteration - identify the current stage in the wishes playing process
_timePause - identify if the wish is ready to play or not
_audioOn - identify if the wish is playing or not
_env - store the name of the current environment
_prompt - store the prompt string
?
Collections:
_wishesList - the list of wishes that Azure OpenAI generates
_wishesListForPlay - the list of wishes with translation, ready to display and play
?
Ask Azure OpenAI for wishes and prepare the playlist
When a user clicks on the Push Me button, the below code executes:
Set(_mode, true);
Set(_iteration, "start");
//Get data from Chat GPT
ClearCollect(
???_wishesList,
???First(
???????Defaulttitle.RequestParameters(
???????????{
???????????????'Content-Type': "application/json",
???????????????'api-key': "",
???????????????'api-version': "2023-03-15-preview",
???????????????max_tokens: 500,
???????????????temperature: 1,
???????????????frequency_penalty: 0,
???????????????presence_penalty: 0,
???????????????top_p: 0.95,
???????????????messages:
???????????????????{
???????????????????????role: "user",
???????????????????????content: _prompt
???????????????????}
???????????}
???????).choices
???).message
);
// Split
Clear(_wishesListForPlay);
ForAll(
???_wishesList,
???ForAll(
???????Split(
???????????content,
???????????"https://"
???????),
???????Collect(
???????????_wishesListForPlay,
???????????{
???????????????content: Value,
???????????????Index: 0,
???????????????LangNum: RandBetween(
???????????????????1,
???????????????????CountRows(AvailableLanguages)
???????????????),
???????????????TranslateC: "",
???????????????SpeechC: "",
???????????????LangName: ""
???????????}
???????)
???)
);
// Add index
ForAll(
???Sequence(CountRows(_wishesListForPlay)),
???Patch(
???????_wishesListForPlay,
???????Index(_wishesListForPlay,Value),
???????{Index: Value}
???)???
);
// Add language info
ForAll(RenameColumns(_wishesListForPlay, "Index", "tempIndex"),
???Patch(_wishesListForPlay,
???????LookUp(_wishesListForPlay, Index = tempIndex),
???????{
???????????TranslateC:
???????????????LookUp(
???????????????????AvailableLanguages,
???????????????????LanguageNum = LangNum,
???????????????????TranslateCode
???????????????),
???????????SpeechC:
???????????????LookUp(
???????????????????AvailableLanguages,
???????????????????LanguageNum = LangNum,
???????????????????SpeechCode
???????????????),
???????????LangName:
???????????????LookUp(
???????????????????AvailableLanguages,
???????????????????LanguageNum = LangNum,
???????????????????LanguageName
???????????????)
???????}
???)
);
// Start audio
Set(
???_wishNum,
???1
);?
Set(
???_timerPause,
???true
);
Set(_mode, true);
Set(_iteration, "play");
//Add Application Insights Trace
Trace(
???"B-Day Buddy",
???TraceSeverity.Information,
???{
???????UserName: User().FullName,
???????UserEmail: User().Email,
???????Environment: _env,
???????Action: "Load wishes",
???????WishesList: First(_wishesList).content,
???????WishForPlayNum: _wishNum,
???????WishForPlayText: First(
???????????????????????Filter(
???????????????????????????_wishesListForPlay,
???????????????????????????Index = _wishNum
???????????????????????)
???????????????).content
???}
);
This code makes the following:
1.?Hide the Push me button and show Playing / Next button
2. Using the custom connector makes the request to Azure OpenAI for wishes generation
领英推荐
3. Split the received data to store in an array
4. Randomly choose the language for translation and store its code in the collection with wishes
5. Add information about the language
This step is required because Translator and Speech use different codes. You can find the Excel file with the information about the language name, code for Translator, and code for Speech.
6. Set the number of displayed wish as 1
7. Launch the timer to make a pause before playing to allow wish to be displayed
?
Display translated wish
By using the below code in the Label control, we can display the wish translated in the selected in the previous step language:
If(
???_wishNum > 0,
???MicrosoftTranslator.Translate(
???????If(
???????????CountRows(_wishesListForPlay)=0,
???????????"Happy birthday",
???????????LookUp(
???????????????_wishesListForPlay,
???????????????Index = _wishNum,
???????????????content
???????????)
???????),
???????If(
???????????CountRows(_wishesListForPlay)=0,
???????????"en-US",
???????????LookUp(
???????????????_wishesListForPlay,
???????????????Index = _wishNum,
???????????????TranslateC
???????????)
???????)
???)
)
To display the language into which the wish has been translated, implement the following code in a separate Label control
If(
???_wishNum = 0,
???"",
???"in " &
???LookUp(
???????_wishesListForPlay,
???????Index = _wishNum,
???????LangName
???)
???& " language:"
)
Move to the next wish
Once the current wish has been played and provided, additional wishes are in the list; the user can click the Next button to proceed. However, an Exit button will be displayed if no more wishes exist. Upon clicking this Exit button, the application will close. To achieve this, add the following code to the Next button:
If(
???_iteration = "end",
???// Close the app
???Exit();
???Trace(
???????"B-Day Buddy",
???????TraceSeverity.Information,
???????{
???????????UserName: User().FullName,
???????????UserEmail: User().Email,
???????????Environment: _env,
???????????Action: "Close the app after 10 wishes"
???????}
???),
???If(
???????_iteration = "next",
???????// Play next wish
???????Set(_wishNum, _wishNum + 1);
???????Set(_timerPause, true);
???????Set(_iteration, "play");
???????//Add Application Insights Trace
???????Trace(
???????????"B-Day Buddy",
???????????TraceSeverity.Information,
???????????{
???????????????UserName: User().FullName,
???????????????UserEmail: User().Email,
???????????????Environment: _env,
???????????????Action: "Play next wishe",
???????????????WishForPlayNum: _wishNum,
???????????????WishForPlayText: First(
???????????????????????????????Filter(
???????????????????????????????????_wishesListForPlay,
???????????????????????????????????Index = _wishNum
???????????????????????????????)
???????????????????????).content
???????????}
???????)
???)
);
?
Play wishes
To play wishes a,dd the below code to the Audio control. Don't forget to hide this control.
If(
???And(
???????_wishNum > 0,
???????_audioOn
???),
???MicrosoftTranslator.TextToSpeech(
???????If(
???????????!_audioOn,
???????????"Happy birthday!",
???????????'Congratulations Foreign'.Text
???????),
???????If(
???????????CountRows(_wishesListForPlay)=0,
???????????"en-US",
???????????LookUp(
???????????????_wishesListForPlay,
???????????????Index = _wishNum,
???????????????SpeechC
???????????)
???????),
???????{options:"MaxQuality",format:"audio/mp3"}
???)
)
?
?? Want a quick start?
We've covered the primary elements of the app above. If you wish to delve deeper into all the controls and properties and want a faster launch, you can download the solution from my GitHub repository. By following the instructions provided in the Read.Me file, you'll be able to install the solution in your tenant and start to use it.
?
Conclusion
To sum up, the B-Day Buddy app stands as a shining example of how AI capabilities can inject fun and ease into our lives. Powered by ChatGPT, this app has reinvented the way we craft birthday wishes, bringing a sprinkle of humor and a dash of convenience to every message.
?
Its modern, one-button interface is designed to streamline the user experience, ensuring every individual can enjoy its benefits effortlessly. But the real magic unfolds with its unique language feature, which translates each wish into a random language. This adds a delightful surprise element to each greeting, ensuring every birthday wish is memorable and entertaining.
?
So, the B-Day Buddy app is more than just a tool - it's a bridge to laughter, global connections, and effortless birthday wishes.
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?