AI Portfolio analyzer

Transcript

[00:00:00] Today, I'm going to show you how to build this portfolio analyzer with just prompts. So I have my friend's portfolio over here. And when I take one of the case studies and I'm going to copy the link to this case study and I can go into the portfolio analyzer and just paste the link and say analyze case study.

What it will do is go scrape the contents of the website and Run it through an LLM and try to understand everything that's on that page and finally give a score that looks like this. So it will go and assess each part of the whole case study. For example, the background, it writes about what was written and some comments on what could be improved and a suggestion.

Similarly, for the key problem, impact analysis, design scope. And so on.

Behind the scenes. We are going to be learning about some very important concepts like structured output, which means how to get an LLM to give [00:01:00] you the right kind of output that you need that will fit into this kind of an interface. We will learn how to design this interface itself, and we will learn how to get an LLM, create this kind of analysis in a single prompt.

There are a lot of interesting concepts that we're going to learn with, for example, how to work with creating an instructions file and working much faster and better with AI.

And at the end, I will also share tips on how you would turn this into a production application if you were to do it.

So when you're ready, let's get started.

As usual, we will start from a template and we won't be starting from scratch. That's a much better way to approach any project in my opinion. This is a template from Lang Chain. Lang Chain is a library that sits on top of all these LMS that makes interacting with these L LMS much easier.

There are mixed opinions about using libraries like this, but for a non developer, using [00:02:00] libraries makes it so much easier to understand the code.

So now that I've copied it, I can go into my terminal.

In my terminal, what I can do is just say git clone, which basically clones this project. And at the end, I will just name my project as Portfolio Analyzer. And what that does is just goes and clones the template into my local directory. And I can go into CD portfolio analyzer to go into the project and do yarn install to install all the packages,

We can go and open this in cursor and I can do that by typing code. Before I run my application, I need a couple of environment variables. So if I go into env. example, this is where I paste my environment variables. Environment variables store your API keys, which identify who is the user for something like an OpenAI. Or if you use a different LLM, you need to paste that LLM's API key.

Now that I've [00:03:00] pasted my API key, all I need to do is go into the terminal and just type yarn dev and that will start the local server and I can open this link on the browser and see the application

It's the template from. NextJS and LangChain. It uses NextJS on the front end

and LangChain library to interface with the LLM, as I said before. Here in the example, it's made the LLM pretend to be a pirate. So it's just a layer that sits on top of the behavior of an LLM. So we would be modifying all of this to fit into our use case. So if I just ask the example that's given here, what is it like to be a pirate?

It will send this request to OpenAI and give me an answer that sounds like a pirate.

That's useful for us to know that everything is working. And if you see this part, the structured output part is the path that we are specifically going to work with because what the structured output is trying to show us is [00:04:00] that regardless of how you input to the LLM, it will give you an output in a very structured format.

So when I say what a beautiful day in this example, It will always give me back an object, which has something called as a tone, an entity, the chat response, and the final punctuation. So anything you say, it's always going to return this kind of a format. And this is useful because with this kind of format, it makes it more predictable when you are building a UI on top of it

okay, great. So once, now that I'm in cursor, let's quickly go into the files. There are several files over here. We have retrieval, we have retrieval agents, we have structured output. Structured output is what we are interested in. We actually don't need any of the other ones right now.

So we can actually go and delete all the other parts. So I'm going to delete retrieval agents, retrieval, generated UI, then [00:05:00] we can go into API. , within API, we have chat. And within chat, again, we don't need agents. We don't need Retrieval, we don't need retrieval agents.

We will keep structured output because that's what we are going to use for this example and we will keep this one as well because that's the part that defines the endpoint for the chat as a whole.

We also have this folder called retrieval and ingest. This is used to ingest data into the database, but we again are not going to use any of the ingest functions. So I'm going to delete this as well for now and we will keep it just a structured output.

There are probably more components that we don't need, but this is a good start. One last thing. I'm going to go to layout. tsx. Layout is the overall app layout and in this layout, I'm just going to remove the navbar. So we don't need the navbar that sits on top. So we don't access the pages that we don't need.

And I'm going to hit save. And once I hit save, as you see, everything else is gone [00:06:00] except for structured output. And when I go ask the same question, what a beautiful day, we just want to make sure everything works. There you go.

Here's a much Better way to work with llms. I got this concept credits to this guy called ai jason And he is the product head at relevance ai And it's a great way to approach building applications that makes things so much easier and reusable. In the root of my directory, I'm going to create a folder called prompts, and this is where I will be storing all my prompts that I will be using to build this application with.

So within prompts, I'm going to create a first prompt called zero instructions dot MD. Instructions dot MD is the place where I store the instructions of the general application that I'm going to build. So AI knows. What is my final objective?

Within instructions, first, I'm going to paste my project overview I'm building an application that takes [00:07:00] a URL from a user, then scrapes the content using Firecrawl. Firecrawl is the Third party service that we will be using to scrape the content.

And it displays a report for the case study in a structured format. Now, the next thing I need is for AI to know what the file structure is. This is an extremely useful tip because it understands the whole way the project is organized. And when it knows this, it knows where to create files when it needs to create new files.

And this is a, this is extremely helpful so to grab the file structure, we're going to use a package called tree. Tree is a simple command line tool that will give us the file structure that we have in a form like this, which we can just copy paste and use in our Markdown files.

So if I go back into my cursor, I can open a new terminal over here And within this new terminal, I just have to paste this command. What it does is, and I'm going to change this to three. [00:08:00] So what it'll do is it'll go into three levels of going from within a folder into a file, into a folder and it will skip node modules, because node modules is all the packages that we installed.

Don't worry about it if this is too confusing, all we need to do is just use this and retrieve our entire folder structure. So everything that you see here is what is graphically represented here. And let's just copy this text, and we can go and paste it over here. So it understands this is what our file structure is.

And the last thing we need to do is, we need to give the documentation of the packages that we're going to use. And the reason we do this is because LLMs are usually trained with data that is in a much earlier date.

So packages keep getting updated. When it writes code, it uses the latest syntax as recommended in the documentation. So in this case, because we're going to use Firecrawl, so I'm going to Firecrawl [00:09:00] docs, If I go into scrape, because scraping is what we're going to use, I already have an example that I can copy paste.

So here's an example that I can simply copy paste, and I also know what kind of output that I'm going to get. So I'm going to just paste all of this. Back into cursor, and paste it here. So what I'm going to say is, see, this is an example of scraping with Firecrawl.

To scrape, here are the options, and here's what you're going to do, and here's how the response should look like. It's just as how we would learn, we are telling the AI to learn using the latest documentation available on a specific package. And finally, we'll mention some other specific instructions that we will say, make sure to use the existing code as examples to build new features, because we want AI to understand from what's already written in the template when building new features.

So it doesn't overwrite on top of what's already written and it takes advantage of the template that we already have. So [00:10:00] this is a one time effort. It's really useful later as you will see how fast it is to build applications when you go this approach.

The next thing we're going to do is we're going to create another file called.

create component, which is where we will first design the front end of the whole application.

So if I go into my Figma, you'll see that I already have created a design that looks something like this.

Now I'm going to port this exact design and create a new component inside code. And the way I'm going to do it is using a plugin that I built, and I'm going to put a link to this plugin in the description that you can access and get it for free

so when I select this frame, you can see that the plugin shows a button called copy to cursor. So when I copy your cursor, it copies all the properties of this frame. Into the clipboard and I can go into cursor and what I can do is

say, create a new react component for displaying [00:11:00] a report , for a given case study. The component should be in the app components folder. S It has two columns, a list, the left column overall score for the case study from one to five. And the right column,

a breakdown of different sections of the report and their scores. And I will give a little more information so that I further reduce the chances of it making errors. So I can say each breakdown section has a title, can be expanded to show more details, show a detailed report.

The details are named as comments. content,

comments, and suggestions. Actually, this part I forgot to add. I'm going to go and add another field here

okay, so I modified it a bit to add the content field, which wasn't there earlier. So I'm gonna go and copy this again, and I will go here and finally say, [00:12:00] render the component in. Structured output.

page. tsx in the info card section. So why do I say this? It's because in the app, when I go into structure. output in page. tsx, this is the page that we see. This part is the info card. It's called an info card. Again, if you don't know how to read this code, here's a simple way to do it. You can go into the composer by hitting command I, go into chat and say, explain this, the contents of this page in pseudocode. What that will do is explain what's here without having to read to code.

And you can see that this is a component and it defines an info card. And what does info card do? And it renders this and here are the key features. So you can pretty much understand what's inside each page by just using the chat and asking it to explain it to you in pseudocode. I'm going to go back into create component. Let me close this. And finally, I [00:13:00] will say, here are the specs for the component. And then I will paste everything that I copied from Figma. So cursor can recreate it easily without having, without needing too much guidance.

That's it. I'm going to save this for now. And let's go ahead and run this and see how it works. So I'm going to go into structure output because this is where I want the component to be visible here on the top. And I can open my Composer by heading command I.

So because this is only a front end thing that we're doing, we are not talking to any API, we are not going to talk to OpenAI just yet. We don't need any other file to tag. Because we have the file structure, it should automatically understand to create a component in the components folder. And also we have specifically mentioned in our instructions to create a new file within components folder.

As you see, let me show back, show it back to you again. So as you see, the new file should be created in app. [00:14:00] components directory. So it should pretty much understand what needed to be done. So I'm going to tag instructions. So it understands what am I building at the end. And I will say create component.

So I'm just telling it, look, these are my instructions. This is the first step I want you to create. Make sure page is linked because that's where we want to make the changes. And I'm going to say, I'm going to hit on enter.

Now cursor will go and generate all the code that I need.

See, it created a new component called case study report. It's creating right now. And this component would obviously sit inside components folder. You should see this appear anytime now. There you go. And now it's updating the structure of the page to include this component, which is great. And as you see, it added the case study report on top.

The other stuff is still around. That's good. And we can just accept all the changes, right? There seems to be some error in case study report. Let's go and see what the error is. It's using something called hero icons and clearly hero icons [00:15:00] package is not installed. So that's why I get this error.

But I'm going to use lucid react instead of hero icons. It's just because I know the package for lucid react. And I also have to obviously install this package. So while it does that, I can just go say yarn add lucid react. I can go and install this package simultaneously.

Okay. The packages are installed and while it's again making these changes, okay, there you go. It made all the changes and there are no more errors because Lucid React is installed and everything else is working fine. So we're just going to accept the changes. And when I go back, I see a little error and that's because it's using use state.

And to use a competent that uses use state, we need to call it a used client at the top. This can be fixed with an instruction generally by saying, when a competent uses use state, always use, use client. You can do that inside cursor settings. , in a later video, I will show you how to write, explicit instructions so this error doesn't happen.

But [00:16:00] for now I'm just going to manually define it. Okay, there you go. See, it actually made the whole interface and it also added a bit of color and interesting. So let me remove all of this so you can have a clear view of what you see here. Now that in the info card, I'm going to select all everything here except for the case study report and I'm going to do command K which is to edit inline because I know this is the part that generates this component.

I'm going to say remove everything else apart from case study report.

Which is the component that we just created. So what that does is just keeps only what we need and just removes everything else for us. So I think it pretty much did what we asked. And I, we also don't need this h1. Maybe it just insists that we have a title. And if I go here, there you go. We can go and style this better, but we're going to focus on the functionality in this application for now. And I can later show you how [00:17:00] you can style it yourself.

You would just go and say, look, change the background color or adjust the spacing or whatever you want to say, just say that into cursor and it should do it for you. But this is a great start for me as I just. So we can go into the next step.

So the next step we're going to do is to modify the structure output where when we paste. a Markdown file, it needs to give us a structured output in the way that we want. So before I create a new prompt, I want to show you a way to visualize what kind of a structured output that you might need.

So if you go into playground at OpenAI, you can go into assistants and I have created an assistant here and the assistant basically is the one that, you can try playing with prompts and its outputs over here before using it in your application, which is a great feature.

So what I did was I created a prompt over here and said that you are an [00:18:00] expert designer and portfolio reviewer, and please analyze the design portfolio. On all these factors, which is a background key problem. Who does it impact? And what do I have to analyze? Does the case study effectively describe the problem statement?

If I go here at the bottom, you can see something called as a response format. So response format is how you want the output to be. And within response format, I'm going to select JSON schema. And if I open this thing, you can see that there's a schema file that I already have. So the schema file, how I generate is I can go into generate and I can say that

Write a schema with the following fields. And I can say, background,

key problem, and so on. I'm just listing down all the fields that I want from the output. Of the AI, and within each field, it's going to give me a score and a content and the comments and the suggestion,

so within each field. So this is the background. So I'm, this is the background key problem. [00:19:00] Who does it impact? So I'm telling that give me a schema which defines the output and the output is in this exact format. i'm just going to list all the fields that I need and within each field I also need a content comment and a suggestion.

So once I've mentioned this, so I'll enter the rest of the fields. And at the end, I will also say for each field, include the field content, a score, a comment, and a suggestion. So when I go type this and hit on create, it will go and create the schema for me. So I already created it here, so I can just copy the schema

and I can go into cursor and in the second file, so we'll say modify. structured output dot MD and within this

I can say modify the structured output to include a score for each section and overall score for the case study. Here's the format. For the output, rewrite it to match the current page syntax. So what I'm saying is, instead of giving me the [00:20:00] stone and whatever was there in the template, modify the structure output to include a score for each section.

and give an overall score for the case study, precisely how I described it in this interface. So I'm saying give me an output that looks like the structure, so later I can plug it in into the interface. So finally, I'm going to paste my schema over here and just paste the whole thing.

And say schema for structured output.

So now I'm going to go and run this so I can go into root. ts, which is the structured output root that has already been defined. As you can see, there's a schema over here that says that you need a tone, you need an entity, you need a word count, a chat response, as the first example that I showed you.

So now we know that this is the file that we want to make the change to. We can go into the composer, add a new one, and we can again, Like the previous time, tag instructions and tag our new [00:21:00] file, which is to modify structured output.

We will just say modify structured output. And that is all we need to do. And let's just go and run this.

So no errors. It's gotten us most of what we need. Let's see what it did. So let me make this easier for you to read. So this part's fine. We're just going to accept this part.. So instead of saying extract the requested fields from the input, it says extract, analyze the case study and provide detailed evaluation, extract the relevant content, provide a score between, it's actually one to five.

Maybe I wrote it wrong in one of these places. Add constructive comments, give specific suggestion for improvement. That's great., let me just change this. And once I'm here, the field entity refers to the first input content to analyze. Okay, that's good. It's just saying that this is the task for the LLM and It removed the previous one and it says like I'm just going to give the input content.

Okay, this is good This is just changing the comments. All right, that's [00:22:00] fine and it's changing The model which I think I want to keep the gpt40 model, so i'm just gonna say no over here And it's removing this that's fine . Here's the part where it adjusts the schema So it removed the previous schema and it says describe the score out of 10 for the section And here's the content and here's the comment and suggestion.

So the three fields that we need within each section over here, the content, comment, and suggestion, and we need a total score.

For this, I think I have specified 10 elsewhere. That's why it keeps picking up 10. So I need to modify it to five because I mixed it up. It's my fault. I am going to accept this, but let me make these changes, not 10, but from 5. Describe the score to 5 and I'm just going to accept my own changes. And when I go here and I will also change this to 5 because the maximum score is 5.

So it goes into all of these parts and it creates a score out of 5 and it creates [00:23:00] a content and evaluate improvement suggestion.

Now the describe part is how it understands what to display here. I think it, this could be a little more clearer in my opinion, but let's go and finish the rest. So I think these parts are pretty straightforward. We don't need to make any more changes here. Everything else is the same.

So I'm just going to make things a little more clear over here. So instead of saying relevant extracted content, I'm going to say extract relevant content of the section from the input. And over here, I'm going to say comment is basically a brief comment on the effectiveness. So what I'm going to do is off the section

so the last one is also, I'm just going to say for the suggestions, instead of just saying improvement suggestion, brief suggestion for improvement, maximum 5 characters, single line. So what I'm just saying is like, look, I need all these, you need to show me all of this in the output and how you go and do it.

Look at each of the fields for each of them. You give me a [00:24:00] structure that looks like this. So just as I've done that, what I can do is go into my field. And as you see, the chat was already existing.

Now to see the structured output work, I can just paste the whole markdown file of a case study that I will be analyzing later and into this file and just hit on send. As you see, it just sent the whole markdown file to the OpenAI API as text and it's generating an output which should imitate the structure that we want.

As you see here, see it sent a background, it gave a score, the introduction lab depth, and it gave a suggestion. And it gave a key problem and so on. So we've gotten a structured output. Now it makes it easier for us to plug in the structured output into the interface. That's all we wanted at this stage.

Okay, great. So now we're going to go to the third step, which is to format the structured output and display it in the UI. So we're just going [00:25:00] to say, format in component dot MD and here I'm just going to go paste the instructions. What I'm saying here is that instead of the chat window, which is the chat interface that we have, create a input field.

So how do I know chat window? If I go into structured output dot page, I can see that this component is called chat window. So I'm just saying instead of the chat window, create an input field where I can paste the case study content in Markdown format. If you see, I still haven't gone into scraping, which we are going to go at the end, because I want to get the back end of the functionality, but first and then move into the first steps.

So then I will say, make a post request to API chat structure output, because as you see, we were dealing with two files, which is the page. tsx and the route. ts. The route. ts is what? takes the request from page. tsx and handles the post request. It does all the talking to OpenAI. It does all the defining the schema for how we want [00:26:00] the output to be.

So I'm, in my instructions, I'm saying make a post request as you would, as it is doing now, with the case study content as the payload. So I'm just saying, look, take that content that I paste, just send that case study content and render the response in the case study report component.

And case study report component is the component that we already created. And finally, I'm saying that match the response structure of the return format to the case study report component. So I'm saying like, look, take this structure that I get, that you get in response and match it to the case study component.

over here. Pretty straightforward. And as you see, it's going to take care of all the heavy lifting. You don't have to do any of this code logic, manually writing code that you would have previously had to do. So I can go into my structure output page and let me open a new composer window. As you see here, we need to tag a bunch of files to make this work.

So we're going to tag first page [00:27:00] structure output, which is already tagged. And we're going to tag route. ts, which is the back end for root. And we are also going to tag instructions. So it again understands the overall objective that we're making. And we are also going to tag case study report. Because it needs to make changes.

to that file to accommodate this new dynamic response in a structured way to the new component. And finally, we will say execute 3, which is format and component. So we're just providing all the access to all the files to which it might need to make changes and say, look, go and make all these changes and just give me this part of the feature.

Okay, great. There seems to be some error over here, which we will see what the error is. First,

let's update the structure output page., it removes the chat window, replaces with direct text area input as a state management for content input and analysis.

Okay. I'm going to accept this for now. There are some errors. Let me see what the error is. So the error is that the argument of type is [00:28:00] not Overall score is missing. There's some information missing.

Okay, I'm just going to accept whatever it's giving. Right now everything looks fine and let me see what it has done. So it's also made some changes to the layout. tsx. It's also made some changes to case study. So it's updated the code to accommodate the final score.

As you see, I think pretty much everything should work fine. Let me go back here and if I refresh, there you go. So I can simply paste my. JSON that I paste the markdown file over here and I'll just paste this here and say analyze case study. And if everything goes well, it should bring back the previous interface that we had.

So obviously the scores look different here because the prompts were different and it's breaking. We can adjust this by saying, hey, look, always have a fixed width. It's working. See, you see all the content is captured from the case study and then it gives a comment on it.

And it [00:29:00] says that, look, this is a suggestion that you can do to improve this part. And this is actually pretty interesting. So it gives the content, a comment and a suggestion, and it gives the overall score as well. Of course, the store doesn't score This score doesn't reflect the actual portfolio because the prompts that we used are pretty weak.

We could still improve the prompts, but so far everything looks great.

And the final part of this is instead of having to manually copy the markdown, which we don't have to do every single time, we just provide a link and it does it for us.

So we can go back into cursor and We can get the fourth prompt, which is for extract firecrawl. md, and within firecrawl, I'm just going to go and paste this

instruction. So what I'm saying here is instead of an input field to paste the case study content, which I have right now, turn the input field into a URL field, then make the post request to structure output, as I already have, and take the [00:30:00] URL instead of the output. Markdown and in the URL to send the URL to Firecrawl, which is the service that we are using.

And this will return the case study content in a Markdown format in a specific, in a specified format. So I'm just saying that I already have specified the output format over here, if you see. So this is how the format should look like. So I'm just saying I've already specified here and extract the Markdown file from the response and pass it down to the LLM.

With existing structured output prompt and retain the rest of the functionality as is. So I'm just saying, look, extract this markdown, give it to the LLM and retain the existing structure output that we just built and don't change anything else. Pretty straightforward.

I can go back into my

Structured output file. So I'll go here. And I will open a new window and let me. So this time again, as usual, I need to tag my instructions file. So it has access to all the Firecrawl syntax. And I can tag ro ts, which is the whole backend [00:31:00] with which we interface with Firecrawl. And we can say execute Firecrawl.

And what this does is just basically executes the last instruction we gave right now.

I think that's pretty much it. Oh, okay. It's not inside the chat. We need to put it inside the composer. And one more thing is that we also need to add an environment variable.

With the api key for firecrawl, so i'm just going to paste my api key here But you can get the api key directly in firecrawl by just going to firecrawl firecrawl link is firecrawl. dev. app and over here. You can just go into api keys create a new key or over here you have a API key that you can simply just copy. And yeah, I've, once I've pasted the API key, it knows that it can access the API key as well. So I will also just like say, I have specified, I've added the API key in env.

So this is for it to know that, okay, look, I have the API key as well. [00:32:00] Just make sure you include that. Okay, so let me execute this in the composer this time, the right place where I need to do it, and it'll go and make all the changes that needs to be made.

Okay, so it made the changes to the page component, which is just instead of the content, it's at the URL. Great. I think it made all the other updates as well. And now it also made changes to the structure output root component, which is before it goes and sends everything to the Let me make this bit bigger.

So before, so first it scrapes content, it created a function for scraping content, create, all of this is, and it returns the markdown file, nothing to worry about here. Let's just accept that part. And over here, It says, okay, in terms this first scrape, the content first, great.

And then it goes into the template and it says, okay, now send this to the open AI API. I'm just going to keep, I'm just going to say no here because I don't want to use turbo preview. I'll probably just use the photo mini and let's see what it does. And that's it. I think [00:33:00] everything else is just say yes, because there's not much to change here.

And for everything else over here, I will just go and accept all the changes. That's it. So I can go back into my browser. Here, it's as simple as, let me go back into my friends. portfolio. And this time I'll find a different project. So let me pick out this project and I will just copy the URL of this project , I can go back into my browser and just enter the URL and hit on analyze case study.

So now on the background, it goes to firecrawl. crawls, gets the markdown, passes it to an OpenAI, and OpenAI goes and understands this thing and creates a score for each of this and goes and renders the UI. There you go. As you see, it pulled out the right content for MindArt, and it extracted what the content is, and it gave a comment for that content, and it gave a specific suggestion

and it did it for each section. Pretty cool, right?

So that's the end of this video. And before you [00:34:00] go, I want to give a, maybe a little idea of how I would approach it if I were to do this in production. First, what I would do is just use an LLM to get an entire summary of the whole case study to give an idea of what the case study is supposed to do

and then I would make separate calls for each section in terms of assessing how the background was written, how the key problem is defined, how the research is done. And I would, there are lots of things that's still missing here. For example, there are images , in the Markdown file that we are not scraping.

So within each LLM API call, we would first scrape the content of the images and we would understand what's in the image. And you can do that by using some of the text to image to text models already available in HuggingFace. And you can use that to understand the entire content. And you would use an LLM to compare this content to the overall objective that we summarized before.

And then come up with a better [00:35:00] scoring and you would also give more details on how to score like for example the key problem has to be a user problem and not like a business problem. Or, you have to be very specific in terms of how to analyze and give more manual instructions as we would analyze a natural portfolio.

And this would make things so much stronger. But the downside is that it would take longer because it makes several API calls. So you need to find a balance between the number of API calls made, number of tokens sent, and also the user experience, because It would take longer to achieve this whole thing, but you could manage all of this by giving the right load of states by explaining to the user what's happening during this whole interaction process and give them at least a score to begin with, , or you can give a score that automatically adjusts based on how each section is being assessed.

And the user experience is critical over here because you understand so many things are happening in the background, which is very different from how it would happen in a traditional front end back end [00:36:00] interaction. So it's useful for us to know this. So we are also thinking about the user experience, understanding how the LLM interacts with the front end application.

Okay. So I hope this was useful and

I will see you in the next video.