LongCut logo

AIP Study Buddy: Building an AIP-Powered Flashcard App in Foundry

By Ontologize

Summary

Topics Covered

  • AI Transforms Raw Notes into Flashcards
  • Track Wrong Answers for Repeated Review
  • LLM Outputs Structured Arrays for Looping
  • Filter Flashcards to Unsuccessful Attempts Only

Full Transcript

It's January, which means that if you or somebody you know is in school, exams are going to start soon, which means now is the perfect time to build an AI powered study buddy. In this tutorial, I'll show you how to use Foundry to

create an AIP powered application where you can drop in text and generate flashcards. It works by using AIP logic

flashcards. It works by using AIP logic in partnership with objects, actions, and links, the ontology primitives you now know and love. Before we get started, a quick word from our founder.

Discover how Paler customers unlock more value from Foundry and AIP thanks to our live instructorled trainings. [music]

We are ontologies, a group of former Palenter engineers who love teaching. We

trained thousands of Paler users at leading organizations around the world.

Unlock the full potential of your Palenter deployment by going to ontologize.com. [music]

ontologize.com. [music]

>> By the end of this exercise, you will have built the following application which is our AIP study buddy. In this

study buddy, you can show different exams. So, here we're looking at all of my generated flashcards for biology midterm 1.

But most interestingly, let's go through the process of what it looks like to add a new exam and add questions for it. So,

let's say I wanted to add a new exam called something like advanced intro to physics

midterm.

So, I make my new exam and then I'm going to select my new exam. No questions yet. So, here I'm

exam. No questions yet. So, here I'm going to paste in my notes. You take

notes during class. You have your textbooks. All of the questions and

textbooks. All of the questions and answers that you need to study already exist, but it's AIP that's going to format them into a nice question and answer structure that you can use to

study. So, we're going to click on add

study. So, we're going to click on add flashcards using AIP. dump in the text for the exam that's going to be intro to physics midterm and hit submit. And here

we have our generated flash cards. This

is going to show us all the flash cards that either we haven't attempted yet or we've gotten wrong. So here if I click on what happens to an acceleration if the force of an object increases, answer

it, try to get it right, click on it to see the answer. And if I got it right, when I hit correct, it goes away. Now I only have 12 questions left. But if I got this one

questions left. But if I got this one wrong for say and how to say incorrect, it's still there. Shows up as incorrect for me and we got to revisit it. So this

could be a great tool if you yourself are trying to study for something or if there's somebody in your life who's taking classes and you want to help them out. Let's go build it. You're not going

out. Let's go build it. You're not going to need any sort of prerequisites to do this exercise. So let's jump right in.

this exercise. So let's jump right in.

We're going to start by creating a project for our work. If you don't have the ability to create a project in your stack, don't worry. You can just do work in whatever project you have access to.

I'm going to hit new project and I'm going to call this one AIP study buddy.

So, this project is going to contain our backing data, our ontology, our apps, our functions, all that. I'm going to create the project.

I'm going to make some folders to organize this. So, I'm going to put the

organize this. So, I'm going to put the data here. All the data sources are

data here. All the data sources are going to be empty. They're just to back the ontology, but we'll still have them, an ontology folder, and an apps folder.

Let's go create our ontology.

Because all the objects are going to be created as a result of user actions, we don't need to bring in any data. We

don't need to do anything in pipeline builder. We're just going to start off

builder. We're just going to start off right from ontology manager. So, hit

Ctrl J and search for Ontology Manager.

We're going to need to build three object types and a couple of links and the associated actions. To make this object type, you're going to hit new and click on object type,

continue without a data source, and hit select folder.

So, the location is AIP study buddy. I'm

going to call this backing data set.

We're going to start with the flash card object type. So, flash card backing

object type. So, flash card backing data.

Hit browse.

Going to save this in data and hit save and hit next. And I'm going to call this one. So, I'm going to prefix this with

one. So, I'm going to prefix this with my name. Uh you should too in case

my name. Uh you should too in case anybody in your organization is doing the same project. So, Gina flashcard.

For the icon, we can make this a little card and then hit next.

Here it's time to add the properties.

There's no properties right now because the backend data is empty. So add

property. We need a couple of properties. Let's call this primary key

properties. Let's call this primary key flashc card ID. And then for the second property, we

ID. And then for the second property, we have to have a question that's kind of cord flashcard. And then we also have to

cord flashcard. And then we also have to have an answer.

Then we should also have an exam ID. So

the funny thing about exams, there's not normally just one. So we want to be able to study for multiple exams, which is why every flash card is going to be tethered to some sort of exam. For the

primary key, it's going to be the flash card ID. And for the title key, it's

card ID. And for the title key, it's going to be the question.

And hit next. Yes, we're going to generate all these action types. And hit

create.

Let's create two more objects. We're

also going to create an exam object type to better organize our studying. Hit new

and then you're going to click on object type. Same thing, continue without a

type. Same thing, continue without a data source. Select the folder.

data source. Select the folder.

Call this one exam backing data. Hit browse.

backing data. Hit browse.

Save it in data and hit save.

And hit next.

And for the exam, I'm going to use a beaker.

Call this Gina exam.

And then hit next. So we need a couple more properties here. Just two actually though. So we're going to have the exam

though. So we're going to have the exam ID and then we're also going to have the exam title. So for the primary key

exam title. So for the primary key that's exam ID and for the exam title it's going to be exam title. Hit next.

Yes, we need all those action types so we can actually add exams and hit create. One more object type to go. The

create. One more object type to go. The

last object type that we're going to need is an exam attempt. So the reason why we need that is that studying is not normally a one-time thing. We have to actually go a couple of rounds and so it

also cut. And in order to better

also cut. And in order to better organize the studying experience, you want to be able to mark questions that you've gotten wrong or maybe those that you've gotten wrong at least once.

Because of that, we're going to track our flashc card attempts using the flashcard attempt object type.

Hit select folder flashcard attempt backing data.

Save that in the data folder to stay organized and hit save.

and hit next.

For the attempt, I like to the little refresh icon like so or repeat. So, click on that one.

or repeat. So, click on that one.

We want to name this your name flashcard attempt. Now, to be very clear, it's not

attempt. Now, to be very clear, it's not normally convention to put your name in the name of an object type. It's not

even really a good idea to put brackets in. However, when you're in a training

in. However, when you're in a training setting and everybody's going to be building the same thing, it can be a helpful way to make sure that you're not having clashing API names. So, we're

going to hit next.

For this one, the primary key is going to be attempt ID.

That's the primary key. We need two more properties here. So, we're going to need

properties here. So, we're going to need the flash card ID. We want to know which flash card we got to come back to.

And then we need the status. So, did we get it wrong? Did we get it right? Cuz

if we keep getting things right, that doesn't need to be in the set of cards anymore. For the title key,

anymore. For the title key, I'm going to put this as the status and hit next.

We're going to have all those actions for now and hit create.

We've created our three object types and it's time to create some links.

To create those links, we're going to go to new and click on link type. These are

all going to be object type foreign key relationships which support one to one and one to many relationships. So hit

next.

Let's start with flashc card attempt and flash card.

So Gina flash card attempt is going to be many to one with flash card. So flash card ID is going to be the foreign key for a

flash card.

So Gina flash card and hit next and create one more link. So we also need to link our flash card and our

exam. New link type

exam. New link type object type foreign keys. So on the menu side,

this is going to be Gina flashc card. So

one exam has many flash cards.

Foreign key here is going to be the exam ID.

That's going to be the foreign key for Gina exam.

and hit next and create.

Now, here's the fun part. We're going to save our work, save the changes. The fun

part, though, is we're going to create the function that uses AIP to create our flash cards.

Let's hop into AIP logic, and we're going to talk about what we're doing.

Once you've saved your changes, you're going to hop into AIP logic by hitting J and searching for AIP logic. Click on

AIP logic.

Hit new logic and call this one your name. And again,

we prefix these things in case you're doing the same exercise to avoid clashing API names. I'm going to call this flashcard

maker.

Hit browse. Go to all projects AIP Study Buddy. And we're going to put that in apps and hit save. Before

we start authoring our function, let's think about how we're going to use this.

So, at its core, a flash card is composed of a question and an answer.

You read the question, you try to answer it without seeing the answer, then you check the other side to make sure that you answer it correctly. So, what it really is is a series of questions and

answers. The idea here is to use AIP to

answers. The idea here is to use AIP to take in some sort of chunk of text like maybe somebody's notes from class or something like that or a page of a textbook and put it into AIP so AIP can

digest it into questions and answers and spit it out as separate objects. We're

going to be using a loop to do this.

We're going to start by adding our function inputs. So click on add

function inputs. So click on add function inputs.

And because AIP logic itself is going to be executing these actions to create new flash cards, we want it to be able to take in whatever information it needs to

properly create the flash card. So for

starters, that's the text. We need some text here. And the other piece of

text here. And the other piece of information we need is the exam. We need

to know what exam it's for.

So this input is going to be an object of the type GINA exam.

Let's start with the prompt. So this

block, let's name it generate array of questions and answers.

For the system prompt, we're going to say, given the input text, generate question

answer pairs for flashc cards for studying for an exam.

Be authentic to the original text.

Do not bring in facts that are not directly covered. So this is our fancy way of

covered. So this is our fancy way of saying please don't hallucinate.

And for the task prompt, we're going to drop in our text data there.

For the text, I'm going to drop in just a blob of biology notes. You can imagine that again, these are somebody's notes they're taking in class. If I drop those in, select the exam. and we don't have any exams yet. You're going to notice

that's a problem because you can't run the function without putting in an exam.

To unblock ourselves, we're actually going to go quickly create an exam in object explorer using our actions and then come back here to test out our function. Save your work while you're

function. Save your work while you're here. Pop over to object explorer. We're

here. Pop over to object explorer. We're

just going to go over there, make a quick little object so that we can actually try out our function in object explorer. I'm going to go make myself one instance of the exam object

type.

And then I'm going to go to actions and click on create GINA exam. So the

actions associated with this object type are going to show up here. Create exam.

I'm going to call this one biology midterm one.

and hit submit. So now we have one sample exam just so that we can try out our function.

Back in AIP logic, if you just do a quick refresh and go to preview for the text, I'm going to drop in these biology notes,

select our only exam, and hit preview run.

Okay, so we have 10 flash cards. They

look pretty good. What is cellular respiration? What are the three main

respiration? What are the three main stages of cellular respiration? Very

good.

Problem is here, we want every flash card to be its own object. And right

now, the structure that we have is not conducive to that. We're going to leverage the LLM's ability to output a structured response to have it output a array of strrus

that is going to help us very easily parse this into multiple objects so we can loop through that and create multiple objects.

To do that under the output type you're going to click on array. So we're going to be making an array not of strings but an array of strcts. This strct is going to have two string fields. One is going

to be the question and the other one is going to be the answer. And so the output is going to now look like this.

The fact that it's an array now is going to enable us to loop through it in the next step and create an object on every iteration of the loop. To do that, you're going to go to control flow and

click on loop and click on select a variable. So what

elements are we looping through? It's

going to be the output of that LLM block. So generate array of questions

block. So generate array of questions and answers.

You'll see here it makes this into another block. So it makes us a block

another block. So it makes us a block that transforms the array into a literal list.

If you want you can rename this. We can

call this list of questions and answers.

Now, so for each element of the list, we're going to be doing something here. For each element, we're going to

here. For each element, we're going to create a flash card. So, we're going to use that action that we created as part of our ontology setup. To find that action, you're going to search for

create Gina or your name, create Gina flashcard for the question. The question is going to be you're going to see that there's a

limited number of compatible variables.

Don't worry, hover over element and click on question. And for the exam ID, the exam ID is going to be the ID attribute from the exam input. So hover

over that and click on exam ID.

And for the answer, the answer is going to be you're going to hover over element, which is again the element of the list that we're iterating over. It's

a strct that also contains the answer.

Now when I preview the run, you'll see the LLM output which makes our our questions and answers and chops it up into an array of strus. And then

you're going to see that our loop is starting to execute. So for the loop, it is creating the flash card. It's going

to run this as many times as we have flash cards coming out of this.

All the flash cards are created now. And

we can see this in the preview. it would

have created these 10 flashcards.

It's time to save and publish. Remember,

this function can't really do anything on its own, so we're going to have to wrap it in an action. So, hit publish, bind to an ontology, and hit publish.

Next, you're going to be prompted to either create an action or create a new automation to call this function. We're

going to be creating an action which we're going to then call from a workshop application which we're going to build next.

So click on create action and that's going to take you straight back to ontology manager and you're going to be all set up to create a functionbacked action. Make sure you

functionbacked action. Make sure you select a version and hit next. For the action type name, we're going to call this your name.

Create flashc cards using AIP and hit next and create.

Save your work and then it's time to go develop our app and workshop and save changes.

Let's hop into workshop. So from here, hit control J and search for workshop.

Click on workshop and hit new module and call this one AIP study buddy.

Hit browse to save it in the project that we've been working in in the apps folder and hit save.

Let's build our application.

We're going to get rid of this section on the side here.

and put everything in a section above this one. So, split section, a section

this one. So, split section, a section below.

Can actually just swap these around.

And I'm going to call this one AIP study buddy.

And what more fitting icon would there be than a brain? So, let's pick a brain.

Here we're going to add some filters up top.

We don't need this header here. So, I'm

going to get rid of the section header.

So, we're going to have some buttons, some filters up top. And then here, we're going to have the cards. So, click

on add widget and we're going to add the object list.

So, click on object list and we're going to have to make an object set variable to power this list.

So, click on object set variable and click on new object set variable.

We're going to call this one flashcards.

Select starting object set.

Call this one filtered flashcards. The filters will come in in

flashcards. The filters will come in in a moment. The starting object set here

a moment. The starting object set here is going to be Gina flashc card.

Hit select and we're going to add some filtering in a bit.

Let's think about how we want these flash cards to be filtered. Really, we

just don't want to see the correct ones.

We want to see the ones that we either haven't attempted yet or the ones that we've gotten wrong.

Because of that, we're going to be filtering to only get the flash cards that are not linked to a successful flashc card attempt. Now, we don't have any flash card attempts here. So, this

app will get a little bit more interesting as we have data, but we'll get there. So, instead of filtering on a

get there. So, instead of filtering on a property, we're going to filter using a link. So, we're going to click on on a

link. So, we're going to click on on a link. Click on flashcard attempt.

link. Click on flashcard attempt.

And instead of saying it is linked, we're going to say is not linked to. And

we want to show any flash card that is not linked to a successful attempt. And

so instead of any, we're going to click on subset. And that gives us the ability

on subset. And that gives us the ability to define a subset of flashcard attempts that we do not want our flash cards associated with. To make that subset,

associated with. To make that subset, you're going to click on select object set variable, new object set variable, and we'll call this one successful

flashcard attempts.

And essentially, we're going to want to define these successful flash card attempts as those that have a status with correct.

So everything's empty here cuz we have no attempts, but we'll get a couple in there. So close that. And so let's also

there. So close that. And so let's also add the button to add the flash card so we could have some data to play with. So

click on add widget.

It's going to be a button group.

We're going to add two buttons. So,

we're going to add one to delete flashcards in case we make one or we see one that we don't like.

Intent is going to be danger. We'll put

a trash can on that.

And then the other button, the other button is going to be success.

And so that one is going to be add flashcards using AIP.

For the left icon, we can use a little some sparkles. Sparkles normally mean

some sparkles. Sparkles normally mean AIP.

And then let's make sure these buttons do something. So button delete flashc

do something. So button delete flashc card. On click, it's going to be an

card. On click, it's going to be an action.

The action is going to be delete Gina flashcard.

And then for the other button, that's where we're going to be putting our functionbacked action. So on click, it's

functionbacked action. So on click, it's an action. And the action is going to be

an action. And the action is going to be Gina create flashc cards using AIP.

For the delete flash card for this one here, we're going to want to make sure that that auto selects to the currently selected flash card from the table.

So for the parameter default, we're going to say that the flash card should default to the active object from the object list.

Let's play with these sizes a little bit. So the row height here should be

bit. So the row height here should be auto.

And let's go ahead and add some flashcards. So I'm going to paste in

flashcards. So I'm going to paste in that text. And also we can modify how

that text. And also we can modify how this text field shows up. Right now it's a single line. If we want it to be a text area, we can do that in ontology manager. And that's for biology midterm

manager. And that's for biology midterm 1. Hit submit.

1. Hit submit.

The edits are applying now. And there we have our flash cards. So these are displaying in the object list.

And we could have them display as a list or as a grid. So this would be more traditional like flashcards. But I

actually prefer the list representation myself.

And then in another column we can display if there has been a flashc card attempt. So that is in the object list

attempt. So that is in the object list we can add a property and then go under linked objects and aggregations to add a flashc card attempt.

So you won't see any here because we are now hiding null properties, but as we get flash card attempts, they will show up. Now, here is where they're actually

up. Now, here is where they're actually going to become flashcards because right now it's just a list of questions.

So we're going to have a little popup so that when we click on a row in this list, we can see the answer and we can mark, did we get it right or did we get it wrong?

To do that, we're going to need to make ourselves a popup. Let's do that under layout. So go to layout, click on the

layout. So go to layout, click on the plus sign, click on new overlay, and we want this to be a modal, not a drawer, but a modal.

We're going to use both these sections.

We're just going to alter the heights a little bit.

So I like to display the responses and the correct answers in markdown. And so

we're going to have a markdown widget with a header that displays the question just to make it look nice. So add a widget, then add a markdown widget. That

can be good if you have any markdown text in your answers.

And the markdown variable that we're going to display, we're going to need to make a new string variable here. Select

string variable. New string variable.

It's going to be a object property. So

it's going to be the answer property of the selected row. So click on object property. We're going to call this

property. We're going to call this answer of selected flash card object set with a single set that is

going to be object list one active object that is the selected line from the list and the object property is the answer.

Let's go ahead and add a header to this markdown widget where we can put the question.

And so in the section header, we're going to have a variable back name. So

the title right now is section, but we're going to hit use variable. Select

a string variable. Make a new string variable just like we did the last time.

Object property. We're going to call this one flashc card question.

And the object set is going to be object plus one active object again. And the

object property is going to be question.

Next, we need a way to figure out if we got it right. If we got it right, we don't need to see it again. If we got it wrong, we definitely need to see it again. To add in functionality to mark

again. To add in functionality to mark these as wrong or right, you're going to hit add widget and add a button group.

So, click on button group.

We're going to have two buttons and we're going to make them fill all the available space.

Button one, we're going to click that one if we get it correct.

Button two, we're going to click that one if we get it incorrect.

Let's go ahead and make the correct button green.

So, these buttons are actually going to be pulling the same action. They're both

going to be triggering the create flashcard attempt action. However,

they're going to be filling in different values. and the values that they're

values. and the values that they're going to be filling in. So on click correct, it's going to trigger an action, specifically the create Gina flashcard

attempt.

But the parameter default here. So first

of all, the flash card ID, the flash card ID, we're going to grab the flash card ID from the currently selected flash card. We're going to have to make

flash card. We're going to have to make a new variable for that. Hop right over to variables. Hit the plus sign.

to variables. Hit the plus sign.

string variable object property. We're

going to call this flashc card ID and the object set is again is going to be object list one active object that is the user selection

and the object property is going to be flash card ID.

So the default value for flash card ID is going to be that flash card ID. We're

going to add one more default. So the

status the status if we click correct is going to be Correct. So, we're going to have to make

Correct. So, we're going to have to make two more variables that just say correct and incorrect to hardcode the statuses when you respectively hit correct or incorrect. So, two more variables to

incorrect. So, two more variables to make.

So, we're going to make a static string variable. It's going to be called

variable. It's going to be called correct and the default value is correct.

Duplicate that. And this one's going to be incorrect and incorrect.

Now we're going to go back into that button group. Go to correct. Set that

button group. Go to correct. Set that

parameter default, the status parameter default to correct. And of course, we got to add some color here. So for the intent, we're going to make that success.

And then for incorrect, we're going to make the intent danger.

And on click, it's going to be an action.

The action is going to be also create Gina flashcard attempt and the parameters are going to be flashcard ID.

We're going to fill that out with flashcard ID and the other parameter is going to be status and that's going to be incorrect.

We have to do two more things. Problem

is right now if I click on correct it's going to pull up a form. That's not a great user experience.

So for both of these, we're going to want to under additional options, hit hide form and apply immediately if valid.

Same thing on correct on the correct button. Hide form and apply immediately

button. Hide form and apply immediately if valid. So what that's going to do for

if valid. So what that's going to do for us, let's say I got this wrong. For

instance, if I hit incorrect, it's going to immediately get applied.

And we can see in the background that there was an incorrect attempt on this question.

How do we get this thing to go away though?

So on each button, we got to do one more thing.

You'll see at the very bottom on successful completion of action submission, we have to have an event go and that event is to close overlay one.

Same thing on the incorrect button.

On the incorrect button again on successful completion of action submission, we have to close overlay one.

Now, here's the other problem.

How do I actually get that popup?

You're going to click on your object list, and in your object list, you're going to scroll down to selection. We have to add an event on

selection. We have to add an event on object selection. So, click on add

object selection. So, click on add event, and it's going to be to open overlay one.

So, now what are the three main stages of cellular respiration?

So, let's say I try to answer this.

Click on it to check my work. And if I got this correct, I'm going to say, "Wonderful. I got this correct."

"Wonderful. I got this correct."

And now it's gone. So, it's gone because we got it correct. Therefore, we don't need to look at this anymore. Let's add

two more things and we're almost done.

The last two things that we're going to add is we're going to add a metric card to count how many questions we have left because everybody needs a little bit of motivation during exam season. and we're

going to add a filter to be able to filter by exam. So, we're going to split this header section and add a section on the left.

Make this one a little bit bigger. So,

make this one flex. Make this one a little smaller.

flex. Make this one a little smaller.

We'll make this one absolute with a size of like probably not 600 and probably do with 700.

We'll bump up the flex parameter of this one.

And then in this section here, we're going to add a metric card and a filter.

So for the metric card, we're going to add that metric card. And metric one is just going to be questions left. So

we'll call this questions left. And for the variable,

questions left. And for the variable, we're going to go ahead and make a new numeric variable. So click on select

numeric variable. So click on select numeric variable. New numeric variable.

numeric variable. New numeric variable.

Objects set aggregation.

We're going to be aggregating filtered flashcards. Call this questions left.

flashcards. Call this questions left.

It's not going to be the average, but the count. And so here I can see that I

the count. And so here I can see that I have 11 questions left.

The other thing that we're going to add is a little drop down so we can make sure we're filtering on exam. We can

also shrink this top section a little bit while we're here.

So right now it's a little bit bigger than we need. We can also change the metric card to be tag style and then it looks a little bit better.

So let's add a section on the right to put a drop down in. So search for object dropdown.

Click on object dropown.

We can also shrink down this section a little bit. So right now it's a flex of

little bit. So right now it's a flex of two. It can probably just be one.

two. It can probably just be one.

We're going to call this select exam.

And the input object set here is going to be a new one. So new object set variable. We'll call this exams.

variable. We'll call this exams. Select starting object set is going to be Gina

exam. So click on exam and hit select.

exam. So click on exam and hit select.

And we can also reorder these if we like. So we can put that one to the

like. So we can put that one to the side.

Maybe even scoot these ones around.

probably give this one a little bit less space because it doesn't really need it.

So, we can bump up the display parameter here and actually let it fill all the space.

So, we can say here we go.

But, of course, you can play with the layout as much as you want until you like it.

To actually make this filter work, what we'd have to do, you'll see that in this selector object dropdown, it has selected object

And so we're we would name this to selected exam.

Then we have to filter filtered flashcards further so that not only is it not linked to the successful attempts, but it's also linked to the

selected exam.

So we would filter again on a link and say exam and we would say is this linked to not just any GINA exam but a

subset and the object set variable would be selected exam.

Of course we can also add another button here to add another exam. So save your work while you're at it.

And of course, the next thing you might want to do is add that add exam button.

So, while we're here, we're going to add another button to this button row here.

You can also change the styling of the buttons. You can change the styling of

buttons. You can change the styling of everything if you like. You could add button three, which is add new exam.

So, on click, the intent here would be primary.

Left icon would be a plus sign.

And on click this would be an action specifically would be create GINA exam

and click on that button and that's going to let us add a new exam.

And lastly, if we want to do a little bit of cleanup here, we can also rename the linked property on these questions.

So, we could call this something like attempt.

We could also do something like sum up the number of attempts, but that's something that you can do on your own.

For now, you're going to save your work and hopefully you can get some good use out of this. Thanks for watching. We

hope you found this helpful and that you ace your exam. Let us know if there's any other sort of ERP content you want to see next in the comments.

[music]

Loading...

Loading video analysis...