AIAI EngineerJun 30, 2025· 1:18:35

Intro to GraphRAG — Zach Blumenfeld

Zach Blumenfeld introduces GraphRAG using Neo4j, showing how to build knowledge graphs from employee and skill data, combine structured and unstructured data, and use graph traversal with vector search for retrieval. The workshop covers Cypher query patterns for multi-hop similarity, entity extraction from resumes via LLMs, and creating semantic similarity relationships. It demonstrates Leiden community detection for skill clustering and builds a LangGraph agent with four custom tools that balance exact skill matches with vector similarity. Blumenfeld argues that knowledge graphs provide controlled, explainable retrieval logic for agentic workflows, enabling developers to decompose data into graph models that expose domain logic for more accurate retrieval than pure vector search.

  1. 0:00Setup
  2. 9:06GraphRAG Intro
  3. 19:23Graph Construction
  4. 35:53Community Detection
  5. 44:25Vector Search
  6. 55:26Entity Extraction
  7. 1:01:02Document Structure
  8. 1:05:00Agent Tools
  9. 1:11:15Agent Demo

Powered by PodHood

Transcript

Setup0:00

Zach Blumenfeld0:15

So as you come in, we have here a server set up with everything you'll need if you want to follow along. You should have gotten a Post-it note; if you don't, just raise your hand and my colleague Alex over here will come find you and we'll provide you with one.

Basically, what you're going to do is you're just going to go if you have a number 160 or below, you go to this link here, the QR code on top as well. And if you have a number that's 201 or above, you go to the second link or the QR code.

From there, I'll give you some directions. You're going to have to clone a repo, and then you're just going to have to move an environment's file over really quick. Also, for everything in this deck, I did create a workshop GraphRAG intro Slack channel, so if you're part of the AIE Slack group, you can also go there and just grab this deck and get the links or however you'd like to do that.

So we'll get started here, I think in just a couple of minutes. Allright, so your number will give you your username and your password. Basically, it's attendee, all lowercase, then your number. That'll be both your username and your password when you sign in.

The other link that you should try to open as well is the browser preview, but I'll walk you through that here in a second. I'll give it just another minute here for everyone to file in and get situated.

Guest1:51

Sorry, what is the username and password?

Zach Blumenfeld1:53

The username and password is going to be attendee, all lowercase, and then the number that you have. Both the username and the password are the same.

Guest2:02

Is that a great question? If these are going to be live after the session, the notebooks?

Zach Blumenfeld2:07

So the notebooks, the servers will be down after the session, but you have the GitHub link you can go back to. So the code is there for you to use. It's just that the environment won't be available afterward.

Allrighty, so I'm going to go ahead and get started here. I'll leave this screen for a second, so if you want to grab the QR codes here, now would be the time to do it. Obviously, you can go to the Slack channel and also pick up this deck.

Allrighty.

So we're going to do an intro to GraphRAG workshop today. I was debating what to actually put in this workshop since everything's changing so quickly, and some of my colleagues convinced me not to make it too complicated. So this course is going to be very much an introductory level course.

If you want to look at more advanced GraphRAG techniques, integrations with things like MCP, we have that at our booth, and we have some other things that we're doing other events tomorrow that will go over some of that stuff, and I'll have links to all of that as we go through.

But basically, what we're going to do is we're going to get everything set up, hopefully that should only take a few more minutes, and then we have three modules. We're going to go over some graph basics. We'll be using Neo4j today, so it's a graph database, just how to query that, kind of how to construct your logic to retrieve data.

We'll go over another module on unstructured data and how to do entity extraction.

Guest3:52

How

many people already know about Neo4j? We're going to get a quick show of hands.

Zach Blumenfeld3:56

How many people know about Neo4j?

Allrighty. How many people have, by the way, used Neo4j, like have written CipherQueries?

OK, so some folks in here. And then how many people have used LangChain before? OK, so a fair number of you. OK, that's good to know. And then in our third module, we'll actually go over, we'll use LangGraph, we'll build a very simple agent that will use some retrieval tools, and you'll get to see how some of that works.

And we'll wrap up after that with some resources. So make sure to ask questions straight away, raise your hand. I'll stop intermittently. We only have 80 minutes though, so I want to make sure if you do have a question, go ahead and raise it and we'll get that answered because we're going to be moving through the material a little bit quickly.

As I said before, we have two Jupyter servers set up, so you don't need to pip install anything. You can go ahead and connect to these notebooks. Attendees, I already explained, you should have a number. If you don't, go ahead and raise your hand.

The username and password is just going to be attendee followed by your number. 160 and less, you go to that first link. 201 and larger, you go to the second link. There's also, if you can, go ahead and open browser.neofjj.io/preview.

I'll show you in a little bit you're going to log into that as well. That will let you visualize the graph a little bit better as we start putting data inside of it.

Guest5:25

Does it say the username and number?

Zach Blumenfeld5:26

Yes. Allright, so Alex, if we can get a number over here.

Allrighty. Once you're inside of your environment, what I want you to do is these two commands. So you're going to open up a terminal window in Jupyter. You can do that by pressing the little plus sign. I want you to git clone.

The command should actually be in the README. It should say git clone, and it will give you the link to the repository that you need to clone. And once you do that, I want you to copy the workshop file over into that genai-workshop-talent folder.

That environment file ws.env is going to have information to a database that's already set up. It'll also have an OpenAI key inside of it that we'll be able to use for the workshop.

So just to show you what this looks like,

if I go over here and I look at my terminal,right, I've already done this. Make this a little bit bigger. You just go ahead and git clone. If you go to the README that was in the main folder, this README here, it has

the GitHub URL. So you just basically go git clone and then, oops. And then after that, you just copy that workshop file into that genai-workshop-talent directory. So you'll get this genai-workshop-talent. It's like a subdirectory in here, and you just have to copy that file.

And that will have resources that you'll need to log into the browser and for you to connect through your notebooks. The other link that is inside of that deck is this browser.neofjj.preview link. Basically, that will give you a way to visualize the graph.

So what you will do, if I go ahead and disconnect and maybe I

got to connect to an instance. So you should get a screen that looks like this. And then that workshop file will have, and it should actually be the same thing for you guys. It should be the attendee, the number, and then the same thing for the password.

So go ahead and make sure you do that because then you'll be able to visualize the graph a little bit better.

Any questions so far?

Guest7:56

Yeah, what's the login?

Zach Blumenfeld7:59

So for the Jupyter environment, if you got your number, it's attendee, all lowercase, and then your number for both the username and the password.

Guest8:12

Sorry, where's the connection URL for this?

It's in the ws dot env for the one.

Zach Blumenfeld8:22

Yeah, ws.env for the Neo4j browser.

Guest8:30

Sorry, Jupyter hub is what?

Zach Blumenfeld8:33

So it'sright here.

So it's basically going to be your username, or sorry, it's going to be attendee, all lowercase, and then the number that you receive for both the username and the password. Yeah. And if you want to come back to this, if you have, if you're connected through Slack, the workshop GraphRAG intro, you can go there and you can pick up the slides as we move on.

So then that way you just have a constant reference back to it.

GraphRAG Intro9:06

Zach Blumenfeld9:06

So while everyone gets set up here, I'll talk a little bit about just what GraphRAG is in general to kind of motivate what we're doing here. So this is an architecture, actually, that represents what some of our customers do.

It's a very common architecture for GraphRAG users. It's generalized. And basically, the idea is that you have your agent over there, you have your AI models and your UI. So like all the normal things that you might think of if you're putting together a knowledge assistant.

But then there's this knowledge graph thing in the middle. And that knowledge graph thing, you can ingest both unstructured and structured data into that. So unstructured being things like documents and PDFs and that sort of stuff. And then structured being tables like CSVs or stuff from a relational database or what have you.

And so there's a big question of like, well, why in the heck do we need this knowledge graph thing in the middle,right? We have agents, we can have tools, and we can go pick stuff from data sources. And so the idea with this is that if you have a use case and you kind of know the types of questions that you want to answer with your agents, by taking your data and decomposing even a very simple knowledge graph to start, you're going to be able to expose a lot of the domain logic that you'd want to apply through the model of your data.

So the idea is like we'll see when we build a skills graph, we'll make some relationships about people knowing skills. And by making that schema available to the agent and making tools available to the agent, you're going to be able to have a lot more control over how data is retrieved, more accurately explain the retrieval logic better.

And we see this as especially important as we start moving more and more into this agentic world because it's not like a one-shot vector search anymore. We're starting to see that now when we get questions or prompts handed to an agentic workflow, those start to get broken down in various ways.

And when you have a knowledge graph, it just lets you offer retrieval logic to complement that in a much more simple and, in my opinion, a better manner.

And today we're going to be looking at a skills and employee graph. So basically, the use case we'll be looking at is you're building a knowledge assistant to help with things like searching for talent, aligning and analyzing skills within an organization, and doing things like staffing and team formation and substitutions and things of that nature.

And so I'm going to present a little bit about what we're going to go through in these modules first. So I'll do some stuff inside of a deck. Hopefully, it won't take too long. I just want to kind of talk to you about Cipher and some of the things that you'll be seeing.

And then we'll go ahead and get hands-on here pretty quickly.

So we're going to talk about creating a graph. We'll start with some structured data here just to keep things simple. I'll introduce unstructured data a little bit later, some basic CipherQuery, some algorithms, and we'll get into some vector search and semantic stuff.

So a knowledge graph, basically, when we think about it, a knowledge graph generally is defined as design patterns to organize and access interrelated data. And at Neo4j, we model the data inside of the database as what's called a property graph.

And this consists of three primary elements. So the first are nodes. These are like your nouns. These are your people, places, and things. Next are your relationships. These are how things are related together, hence the name. And often will be like verbs.

So person knows person, person lives with person, person drives or owns a car. And both of the nodes and relationships can have properties, which are just attributes. They can be strings, they can be numbers, they can be arrays of things, and they can be vectors as well.

So we can store vectors for we've had for a long time inside of Neo4j. And you can do search over these things. Now, the query language that we're going to use to access the database is called Cipher. And I know a lot of you raised your hands in the beginning, so you already have some familiarity with this.

But Cipher kind of looks like ASCII text. So the idea is that it has this SQLS kind of feel to it, but you get to write these statements like if you see match person knows skill. Basically, you're connecting a person node to a skills node through that knows relationship.

So it reads kind of very literally in the way that it's written. Nodes have what's called labels, which is sort of like it would be the equivalent of a type of table within a SQL database of basically what type of entity it is.

And then, as I said before, they have properties. So for example, you can identify by a property like name, and you can have variables like p and s, which refer to the actual entity as you start to write your query more.

So this is not going to be a course on writing Cipher,right? Because we can make an 80-minute course just on how are we going to make CipherQueries. But we will be walking through these queries. So don't expect to be, if you haven't seen Cipher before, to be a super expert in the CipherQuery language when we're done.

But just know that this is kind of how it works. And then as you go through, hopefully you'll get a better understanding and a feel for how these queries work and the types of data that can be returned as you run them.

And so I'm sure, is everyone pretty familiar with vector search in here at this point? Yeah, I have a feeling this audience probably would be. So I won't spend too long on this,right? I think we all kind of know what embeddings are.

It's basically a type of data compression. You can apply them to all sorts of things,right? Text, audio. You can even apply them to graphs. Oftentimes, it's just going to be a vector of numbers. And then you can use that to find similar things within that domain space.

So find texts that are similar semantically, not just lexically, but actually based on the types of things that they're talking about. And within Neo4j, you have search indices, including vectors. So there's range indices, you have uniqueness constraints, you're able to search text, you're able to do full text with Lucene.

And then we also have approximate nearest neighbor vector search as well that we'll be leveraging as we go through in combination with the CipherQueries that we were just looking at to do graph traversals. The next thing to know about is that in addition to being able to query the database, we also have analytics.

So we have graph analytics powered on the database that lets you do different types of data enrichment and do more graph global type of analytics. So finding which nodes are most central according to different algorithms, doing things like community detection, how do you cluster the graph, finding paths between nodes, doing different types of embeddings.

So we have a lot of those algorithms, and we'll be touching on them very, very briefly today in the first module just to show that once you have a knowledge graph, you can start enriching that data and then actually using things like, we'll see in our case, we'll be using community detection where we'll be summarizing skills inside of our graph, and then we'll be able to pass that on to an agent to actually use that to explain some parts of our graph for our use case.

Allrighty. So with that in mind, we'll go ahead here and jump into the first notebook. Are there any questions before we dive in? Is anyone still, OK, yes, over here.

Guest16:54

Can you give us the link, please?

Zach Blumenfeld16:56

Yes, do you have, let me just go back here to the.

So, and this is available in the Slack channel too. If you don't have a number, my colleague Alex over there can go ahead and grab one for you. We're in the workshop GraphRAG intro Slack channel, so you can go there to grab the deck and all the links.

But basically, if your number is 160 or below, you go to that first Jupyter server. If it's 201 or above, you go to the second one. Use attendee, all lowercase, and then your number as both your username and your password.

You'll do that for the Jupyter notebook and then also for the Neo4j browser if you want to follow along with visualizing the graph as we go through. Any other, yes?

Guest17:54

I know this is introduction to GraphRAG. So

maybe when you're building these graphs, I see you have a small graph. How do you prioritize whether you should make big graphs, like one that contains more than skills, or make smaller graphs? Is there any risk?

Zach Blumenfeld18:18

So your question is about data modeling and whether, how do you prioritize making one graph versus multiple graphs? I mean, it's a good question. I think in general, for a lot of what we're seeing with agents, I find it's helpful to have a smaller data model if possible, especially if you're doing different types of dynamic query generation.

So to keep that in mind. But as things are getting better, we can pull back the graph schema and offer it to agents. And we're noticing that as agents sort of keep, or as language models really keep iterating, they're starting to get better and better at interpreting.

So whenever you want to do traversals in a low-latency way between two data points, those things really should go in the same graph. And then it's a question as far as what you make a label versus a property in that scenario.

So we'll go through some of it, and then if you want to talk after and come by our booth, we can have a more sort of use case-focused conversation. Anything else? Allrighty. So I'm going to go ahead here and then dive into the notebook.

So for our first notebook,

Graph Construction19:23

Zach Blumenfeld19:28

you can go ahead and restart. That's fine.

Allrighty.

So you're just going to come down here and start. And remember, we're in the talent subfolder. So there's two workshops in here. The one we'll be doing is called talent. If you're in the other one, there's also some interesting stuff in there, but you won't be able to follow along.

Allrighty. So it looks like I'm running now. So basically, what I'm going to do is I'm going to get my environments file here, and I'm just going to load it. If you don't have the environments file, just go ahead and move it.

It's in the root directory. Just go ahead and move it into this subdirectory. It's this ws.en file.

And basically, what we're going to do first is we're just going to load our skills data sets. It's going to be a table. And if we look at that table, we're going to have basically three fields.

There's

an email field, a name field, and then just a list of skills for the person. And as I said before, we'll go into a little bit of detail here around how you might extract this from documents like resumes in a second.

But basically, for now, because we're interested in sort of this skills mapping and team formation and staffing kind of use case, we're starting with this sort of very simple data set to get us started.

And so there's a couple steps here that just go through basically organizing the data to make it easy to load. And then we're going to start to create our graph. And so a lot of this is just what we'd call basic kind of Neo4j data loading.

We're going to create chunks out of our data frame. You're going to basically check to make sure you've got nothing in your database. I do have stuff in my database because I was just running this before, but that's on me because I was just running the course before.

Yours should say zero. Now, the first thing we do is set a constraint. So basically, inside of Neo4j, whenever you create nodes, if you have what's called a node key constraint or a uniqueness constraint, it's basically saying in this case that the email has to be unique and non-null for all your people.

And that will make it so that it's very fast to match on people and do merging operations. So a lot of times, people will say, well, Neo4j is really slow. And that's often because of simple mistakes like not setting a constraint, and then you're going to have to do very complex searches in the database every time you search on a user rather than having it in an index that's unique.

And then you also do the same for skill because our data model is going to be person and skill. So we have two types of nodes. And when we do that, we'll go ahead and have two constraints here inside of the database.

You'll see for skill and for person. After that, we'll go ahead and start loading our nodes and our relationships. So the way that this query works, and I guess I won't run it even though it won't actually change anything in my database.

But what we're doing here is we're looping through chunks of our data frame, and we're saying, hey, merge a person on email, set their name. And then for that list of skills, basically, you're going to merge a skill on a skill name.

And then you're going to merge here that the person knows that skill. So it's going to create this graph pattern of person knows skill in the database. Once you run that, what you can do is if you have that browser window open that we were going over before, is I can go ahead and copy one of these, or maybe I'll just take this one.

Well, I'll go ahead and take this one first. What this will show you inside of the database is if I just match people, I'll get my people back here. And I may have lost, oh, cool, I still have my internet connection.

Allright. So I can go ahead and see that I have my people. They have their names and their email addresses. You can do the same thing for matching skills. And then you can also look for relationships. So this gets into that pattern matching that we were talking about before with Cipher.

This is a very simple version of matching a path. So I'm saying p, which is path, is equal to node, connect to nodes, connects to another node. And I'm saying limit 25. And that will return a graph where I get to see all these different relationships.

Looks like my internet connection is still somewhat slow, but I get it back here. So you'll see I'll get my people, I'll get that node's relationship. And then in this case, this person knows API design, Tableau, Flask. And you'll see different skills pop up here inside of your graph.

And you can go ahead and run these through our driver here as well to look at the data, pull back the different people that are in there, and find out what skills they have and such. We do here.

Guest24:49

Question.

Zach Blumenfeld24:50

Yeah?

Guest24:50

When you say nodes, is that you're just making up a term? That could be any string, or is nodes like a specific concept?

Zach Blumenfeld24:58

Nodes is a relationship type. We are making it up. So our domain model that we have, I can actually call it here. And mine is going to show more than yours if you run the same command because it has some other later stuff that we do in the course.

But basically, you have person knows skill. That's our data model. So you can say person has skill would be another way to put it,right?

Guest25:26

But the word know is just something that you could change that word in.

Zach Blumenfeld25:30

Exactly.

Guest25:30

There's an edge there.

Zach Blumenfeld25:31

Exactly, yeah. And it's actually funny because this is becoming even more important now that we're using LLMs to design queries because the language that you use is sort of like an annotation for the model,right? So that starts to become very interesting.

Allrighty. So there's some Cipher queries here that I'll go ahead and run through really quick. And I may, depending on time, need to kind of speed things up through this notebook because I want to make sure that we actually get to the agent at the end.

Guest26:09

How did you start visualizing graphs like here?

Zach Blumenfeld26:11

So if you go into the deck, there's this link, browser.neoforgj.io/preview. And then I think it's just your username and your password. But you can also look inside of your workshop environment file, and it will have that information there.

You just use your username and your password and your URI information, which you get here. So you get your URI, then your username and your password.

Allrighty. So like I said, we'll go through some of these. So for example, we can count in Cipher. So we can say, match person knows skill. We can get back the name, and we can count the distinct people basically here for each skill.

So basically, what we're doing here is you can think of it as like, OK, I've got all my skills, and I'm going to count the distinct people that know that skill. It's very simply what we're doing. When we get that back, we'll see kind of what our most popular skills are here going down.

And they're all kind of tech-focused. We can also ask different types of multi-hop questions, which is very interesting. So for example, I'll take this, and I'll copy it over to my browser because it's interesting to see these visually.

But what we're asking here is we're going to take this person named Lucy, and I'm just going to ask what people are kind of similar to Lucy in terms of knowing the same skills,right? So I can go ahead and run that.

And then what I'll get is I'll get Lucy here. I'll get all of her skills. And then I'll get all the other people that know those skills here,right? And you can build on that iteratively. So if I go back here, I can also say, well, now I want to know all of those skills or all of those people, and I want to know basically I'm going to add at the end of that query, I get they know a certain skill, and then I want to get all of those people, and then I want to get all the skills they know.

So I'm basically adding this, and what skills do these other people know to the query? And then I'll get a very large graph back. But the idea with this is that once we have this logic extracted from whatever our original data source is, we can now control at a much more fine-tuned level how we define what a similar person is or what a similar skill is because we have this ability to traverse over the graph and apply concrete logic.

It's basically like having your information in a symbolic versus just a subsymbolic vector. And so you'll get a lot of stuff back because now we're looking at people and all the other skills that they know, and I can go in here and find the most central skills among these people,right?

Like for example, Scrum is very central among this group because there's a lot of people that know that skill. So I'm figuring out about this local community that sort of knows the similar skills to Lucy.

And in here, it's just some examples of running that same logic basically inside of the notebook.

Guest29:24

Yes. At the end, do I get only the table and the row? I don't see the graph.

Zach Blumenfeld29:29

So to get to the graph, basically what you're going to do is you're going to go to this Neo4j browser link.

Guest29:36

I'm over there. I'm over there. I mean on the UI.

Zach Blumenfeld29:39

Oh, I see.

Guest29:41

Here. Allright. I see the graph now, yeah.

Zach Blumenfeld29:43

You table, then graph. And then sometimes if you're not returning nodes, it will only return a table. Like if I said, return.

Guest29:51

I think I put the same query as you.

Zach Blumenfeld29:55

Yeah, OK.

Guest29:56

You did. Oh.

Zach Blumenfeld29:59

OK, yeah. So if you just say return p, in that case, it should return the path. Sometimes if you don't see it, it's because you're returning just the name or something. And then in that case, it'll just show you a list of names.

Guest30:13

Oh, wonderful. Thank you. That's perfect. Oh, question. What is a distinct doing in this case?

Zach Blumenfeld30:20

And I don't have a distinct here.

Guest30:22

You deleted it.

Zach Blumenfeld30:23

Oh, yeah, I did.

I don't know if it's completely necessary for this one, actually.

Yeah, I don't think it is completely necessary for this one. There are times when you do very complicated, especially we'll see that there are a couple other examples where we do multi-hop paths. And there's a chance with some of those that you'll get basically two paths that are the same, in which case having the distinct there just allows you to filter it better.

Guest30:56

Question.

Zach Blumenfeld30:56

Yep?

Guest30:58

So how good are any of the LLMs based in writing those Cipher queries?

Zach Blumenfeld31:05

So that's hard to say. They're getting better. A lot of it depends on the complexity of your schema. And basically, we see for simpler aggregation queries or when you have a lot of prompt engineering around doing different types of path queries that are very specific on a smaller model, they can do well.

We do often recommend that you have your own expert tools if there's a really complicated type of traversal that you want to do. So you can write your own Python functions, or you can have your own MCP server that will just have your set of functions for your more complicated traversals.

We also see too you can sort of restrict the options for LLMs. So instead of writing a complete query, you can say, hey, there's these three types of general patterns. And write that part of the pattern, and then it will go into this other query.

So you can do stuff like that to help it. We've also done, we've had fine-tuned models that we just released, I think, back in April. They're fine-tuned from Gemma. They're on Hugging Face. So you can try using those as well.

They can do a little bit better. We're not going to use them here, though, unfortunately, because we're using a bunch of OpenAI models for this.

Allrighty. So a lot of this, as I was just going over, is basically just running these queries. Returning, in this case, the distinct is important to return a distinct name because you might actually get to the same person multiple times.

So if you're just returning a name

of a skill, then it's important to use distinct in that case. So we get all the distinct skills that basically showed up in the graph we were just looking at. Another thing that might be important for our use case is finding similar people.

So this is, again, using that query that we were just going over to find. We used Lucy before, but now we can actually parameterize that here and then basically go knows skill. And then we can match basically from that skill going to another person, and we can sort of count number of shared skills between people.

And so when we do that,

we can go ahead and see in this case the number of shared skills between different individuals.

And we do it again here, I think, for a different set of people. I think this just counts most skills shared between any two people. So you can kind of see that here. Again, just another way to measure similarity beyond just semantic similarity, measuring actually what we have from our model in terms of exact shared skills.

And as we go through this, some of the things that we can do to help speed up our queries, and this is sort of optional. But if we know that we're going to sort of look for similar skill sets a lot, we can create a similar skill relationship inside of our graph.

So basically, we can match two different people, and then we can merge a similar skill set basically based on an overlap of a skill count. So we have our data frame locally that we can use for that that we were just looking.

We basically just pulled it back when we were looking at those similar skills. And what that's going to do is it's just going to create, again, this relationship that has similar skill set between people. And if I were to look at that, it will

go over to my browser.

We'll go ahead and see I can have a similar skill. Some of these are overlap one. Others will be greater inside of here. I think they go up to three. So all this is doing is basically saying, hey, if two people, what is their overlap?

So we don't have to do that full traversal over and over again if we don't want to with that similar skill set relationship. The next thing I wanted to show you and.

Guest35:21

Yes. But if you do this, you need to this is static, and if you want to update what's the overlap, you need to run this query again.

Zach Blumenfeld35:29

You would need to run that query over again, yeah. So I mean it depends on how often your data gets updated. There's nothing actually wrong with doing the multi-hop query over and over again. The graph database is designed to handle that.

So if you had a situation where you had a graph that was constantly getting updated, you might not even need to create this relationship.

The next thing that I wanted to show you was how our graph analytics works inside of Neo4j and basically using that to enrich the graph. So this is basically creating what we call a GDS or a graph data science client.

Community Detection35:53

Zach Blumenfeld36:11

And what we're basically doing here is we're creating something called a projection, and then we're running an algorithm called Lyden. For the GraphRAG community, how many people here have heard of Lyden as an algorithm? OK, so just a few people.

How many people have heard of Louvain as a graph algorithm? OK, so we got a couple people. Basically, what this algorithm does is it breaks the graph down into a hierarchy. So we'll start by basically breaking the graph into a few big communities and then going into smaller communities.

And what it's trying to do is optimize what we call modularity. And it's basically this metric that says, hey, I want to create these clusters in my graph where the connections within the cluster are very high and connections across clusters are very low.

So I'm creating these modules. And basically what I do by creating these, and I'm using that similar skill set relationship. This is another important reason to create it because if you do analytics on your graph, it can help with those analytics running a little bit better because I have a person connect to another person with a similar skill set.

And by running this Lyden algorithm, basically what we get is a bunch of communities that reflect people within the communities knowing similar skills. So this is all simulated data. But basically, if I go down to and I'll skip over some of this.

We do some checks around how good the communities are. I'd encourage you to run this just so that the agent works well at the end. But what I wanted to show you here is this graphicright here. So what this graphic is looking at because basically we wrote this community ID property back to the graph.

And you get these different community IDs, and you get to see which communities in a heat map have the most skills in a certain area. So this data is randomly generated. So a lot of these patterns are going to look maybe a little bit funky if you were to really dig into them.

But the idea is that as you have more relevant data and realistic data, this can actually show you your data engineers are here, and your front end guys and front end folks are over here, and then your ML people are over here.

So you can start to see that within the graph and really break that down. But do go ahead and run everything here through the g.drop so that you have that property. Another way that we can break down

different groups inside of the graph is to look at go ahead, sorry.

Guest38:55

I just had one question regarding when do you customize your graph, for example, the community detection algorithm that you're running?

Zach Blumenfeld39:03

Yeah.

Guest39:03

And when do you just let the agents? Is there any, again, heuristics where you say, OK, well, actually, it's better to invest time in figuring out whether we should improve our graph rather than just.

Zach Blumenfeld39:19

Well, I think it depends on your use case. If you're very interested in saying, hey, I want to understand the skill communities inside of my company, if that's a question that's going to come up frequently, then using something like graph analytics can be very beneficial because you can do basically employee segmentation.

And you can understand performance within different groups and stuff. We see it oftentimes used for customer segmentation and recommendation systems and that sort of thing too. At the same time, if you're just like, hey, I just want to look for matches of different people with similar skills, maybe you don't need community detection for that because that's just like a pairing exercise.

So I'd say you use it whenever you want to do some sort of clustering analysis and persist that and then even have visibility and, I guess, the confidence in knowing that there was some way that you did that.

And it's not just up to the model that's just making stuff up around how that works.

Guest40:18

So basically, you look at what the users are doing and then try to see if you need to build.

Zach Blumenfeld40:23

Yeah, yeah, yeah.

Guest40:26

Thanks.

Zach Blumenfeld40:29

Yes.

Guest40:31

Since the communities are based on their skills, what is the heat map showing us? Secondary skills?

Zach Blumenfeld40:40

The heat map is showing you how often different skills show up within each community.

Guest40:48

Aren't the communities based on what skills they have?

Zach Blumenfeld40:52

Yeah, so the first community, for example, is it looks like either Tableau or Swift.

Guest40:58

So it's basically like we could use this to name those communities or to understand.

Zach Blumenfeld41:02

Yeah, to understand the skill breakdown within each community. And again, this is generated data, so this is a little bit random. But you can imagine that in a non-random scenario, what you're probably going to end up seeing is if you have a lot of product managers versus a lot of

front end developers versus DevOps folks, you'll see that grouping start to emerge.

Yes?

Guest41:29

Two connected questions. One, do you have any different best practices for data modeling for an agent to understand the data model or just general graph best practices around creating data models?

Zach Blumenfeld41:43

Yeah, I mean I'd say a lot of the agent stuff is evolving super, super quickly as LLMs keep changing and getting better. We've had for a long time guides on how to do data migration from relational systems to graph and how to think about that.

There's a certain way in graph how you think about, again, nodes being nouns, relationships being verbs, and how to connect those together. For agents, I think it's really nice when the data model reflects a natural language. So person knows skill, very natural language way of saying something that translates directly to a data model.

And as I was saying before, simpler data models seem to work better when you do dynamic query generation. So there's stuff like that. And the rest of it is I know the it depends answer is such a cop out.

But it is true that depending on the type of retrievers that you have, the size of your data, the cardinality of different categories of things in your data, you generally don't want, if you can avoid it, to have hundreds or thousands of node labels because it's just a lot.

So then you make them properties. So there's a lot of stuff like that to consider. So I don't know if that answers your question.

Guest42:56

So the first part. The second part is how have you seen it be effective to show or teach the agent how to reason about the data model? What sort of schema file would you give it? Or

what do you generate to then shove into the agent?

Zach Blumenfeld43:12

Yeah, we'll see at the end of module three, which we might not have time to get to, but you'll see it in the code and I'll show it really quick, is that from the graph schema, there's functions that we have to pull back the node labels and the relationship types.

So you can create a sort of JSON representation of what the graph schema looks like and then combine it with specific prompts. So then it's like, OK, I follow that. Another thing to do that helps even more is if you have a graph data model that's not going to change a lot over time where you know you can just pull it and it will be the same for a while, is you can annotate that schema.

So you can say for specific properties or node labels or relationship types, hey, this thing does this. And when you ingest data, make sure you put it here. And when you pull data, make sure you can go on different paths.

The other thing is putting in we had person knows skill. Putting those actual query patterns into the schema as well helps a lot because the model can read that and then understand how to do that traversal better.

Anything else? Right, cool. So we're actually getting close on time. So I'm going to go pretty quickly through the rest of this. But hopefully,

Vector Search44:25

Zach Blumenfeld44:25

it'll be pretty understandable. So there's another way that we can start thinking about skills and relationships between skills is how they're semantically similar. So basically, what we can do is actually make embeddings on our skills. So there's another file in here that basically has a CSV file that you read into this notebook that has skills and descriptions and an embedding.

So which field here do you think we embedded, the skills or the description, and why? So one of the things is when you have really short names like R is technically a programming language, although a lot of people don't love it.

I love R.

AWS, they're very short. So having descriptions about those skill names, if you embed those, it provides a more informative embedding. So that's the whole idea there. So basically, we give each skill a description, and then we embed that description.

And what we're seeing inside of this is we're actually going to and these are all text embedding ADAs, so they're 1536. We're going to go ahead and create a vector property. This is just loading those up in chunks.

And then we're going to set the description as well. And after we do that, we'll basically have, I think we create our vector index down here that we call a skills embedding. Once that's set up, basically what we're able to do, and you'll see it show up here, we'll get that skills embedding index, is we're now going to be able to do vector search on skills inside of the graph.

So if I have Python as a skill and I go ahead and I'll use this command in Cypher to search the skills embedding, pull back the 10 most relevant skills, and you'll see here it'll bring some skills back.

Here it's like Ruby and Java. We got pandas at least, that's good. Django, PyTorch. So some of these are better than others. But the point is that we can go ahead and apply these vectors and then pull information back with vector search.

And another interesting thing that we can do as well

is if I had something that wasn't in the database, like say I'm just looking for API coding, and I searched that as a term, basically what I'm doing here is I'm using the OpenAI client here to just embed this model.

Or I might be using actually LangChain up here. Looks like it's LangChain. And then I'm doing a search on the database to pull back relevant skills with a certain similarity threshold. And I'll get back API design and JavaScript for that API coding example.

And what I can actually do in this case is I can say, well, I have this ability to do semantic similarity in the database. I can actually write a relationship that's just similar semantic. And I can attach a score to that.

So there's some advantages to doing this. But a big one is visualization and also clustering. So if I were to take this command, which takes a similar semantic relationship, and I go into my graph and I just put that in here and I just return all basically the skills that are semantically similar.

This internet speeds up, hopefully.

And I zoom in. I'll start to see sort of interesting groupings here. So I'll start to see, for example, that I get my cloud skills here, Azure, AWS, cloud architecture all in one place. Similarly, I have Flask and Django here connected.

I've got my data analytics groups like Tableau, Power BI, data visualization. And then I've got a big grouping over here. So you see you have your JVM languages like your Java and Scala and Kotlin here. And then I've got my Python stuff here with pandas.

And then if I go up in this group that's connected, I've got my Java. And then I've got all this front end frameworks and stuff up here. So don't underestimate the power of being able to visualize similarities. Very important because I can create communities from these.

I can use this for customized scoring in my retrieval queries, which we'll see. But the other really cool thing is that if for some reason, maybe I don't think Java should be connected to Python, I can control that.

I can remove that relationship. And then every time I do similarity relationships, I have control over that and I can filter that. So that's just some important things to keep in mind about how you can use vectors and graphs together.

Guest49:27

Quick question. Is it only when you do semantic similarity, is it only to visualize or is there any other use case?

Zach Blumenfeld49:35

We'll see in a bit here because basically what we can do and I'll answer this actually as I go down. I can pull back this semantic similarity relationship here. But what I can start to do, which is actually pretty cool, is I can start creating these sort of customized scorings between things that kind of balance the semantic similarity versus hard skill matches.

And I can weight that if I wanted to in a custom way. So you can use it in your retrieval patterns as well to improve things.

Guest50:14

If you put retrieval pattern, would you go directly to Neo4j or would you do vector search first, look at the entities, then find similar entities, and then do maybe vector search again? Do you use both typically?

Zach Blumenfeld50:28

So you can use both. So there's a lot of workflows because now you can compose things together into multiple steps. So you can definitely do something where you can pull similar skills and then look for people. And it just depends on how you break down those functions for the agents.

Sometimes if you know that there's a very specific pattern that you want to follow, like here, this looks like a really big query. It's somewhat intimidating, but it's actually not that complicated. What you're doing here is you're just sort of doing a weighting between the semantic similarity and a hard overlap with similar skill sets.

That might be a case where coupling that logic together might make sense if there's a very specific type of metric that you want for similarity.

Guest51:13

But what if you're coming from when you're coming from you have a query and let's say you have an assistant and you have a much larger ontology? Tell me about people with certain skills. How do you know that these are even the entities that you're looking at?

What's the first step when you go from query to retrieval? How do you break it into the entities to know that this is the type of query that you should be or this is the query that you should be doing anyway?

Does that make sense?

Zach Blumenfeld51:39

Yeah, I mean why don't we revisit that when we get to the third module. The second module should be really quick. And then you can see some of the functions in the third module. And then that might help me answer that question a little bit better.

I think I know where you're going, but maybe seeing that will help. So as I said before, this is doing kind of like a balance between the semantic similarity and sort of a hard overlap of skills. And then you can use that to kind of weight how you want to find similar people inside of the graph.

So you can start balancing both the vector search similarity and the similarity that just happens with inside of the hard matches. And another cool thing about a graph database specifically is I'll go ahead and take this query here just so you can see what this looks like.

Oh, go ahead.

Guest52:36

Feel free to push this question. But are you going to talk a little bit about the trade-offs between doing vector embeddings within Neo4j versus maintaining a separate Postgres database?

Zach Blumenfeld52:48

Yeah, I mean you could go either way. So a lot of this, to be honest, will come down to cost considerations, like how expensive is it in Neo4j versus how expensive is it inside of Postgres. And that varies a lot depending on the type of infrastructure you have.

Having everything in one place means that it's a little bit you don't have to sync your data. And then you also the query latency is, at least in theory, going to be lower because you're just querying from the same database.

But if you already have data in Postgres, maybe, or you already have a specialized vector database, you also don't have to migrate your data necessarily to Neo4j to make that work. So yeah, I'd say a lot of it actually it's performance, but it's really cost per performance is kind of what you're thinking about in terms of what does each deployment cost.

So this query here is actually I'm looking for similarity between two people. And then you see I have this star dot dot thing here. And basically, with a graph, you're allowed to do what's called variable length queries. So I'm saying, hey, go out on similar semantic, but you're allowed to go out anywhere from 0 to 2 hops between these skill sets before you find a connection between John and Matthew here.

And then I can also union it against just the plain person knows same skill. And when we get that back, we'll see you get Matthew over here. Matthew knows React. John knows HTML. And then those are sort of similar because they both have a semantic similarity to JavaScript.

Same thing here. You see we have this semantic similarity, but this is only one hop. This is where the variable hop comes in. So you can start to control how far out you can go on either of these paths to be able to pull back similarities between people.

So it's just an advantage of a graph database. Then I think I might want to finish it off for this notebook. I would take a break, except that we only have 23 more minutes. So what do you say?

Should we just power through the last 20 minutes, you think?

Guest55:04

Yeah.

Zach Blumenfeld55:04

Yeah, let's do that. So now we looked at some of the advantages of using the graph and the semantic similarity inside of the graph. And now we'll talk a little bit about our second module here. And I won't go over to the slides because I think for you guys, I can probably just hopright into the notebook around, well, what if we have just resumes?

Entity Extraction55:26

Zach Blumenfeld55:26

We don't have a CSV file. So this is going to be a simple example that will show you basically how to take the data from text and turn it into useful data for the graph. So again, if you're going through and running this live, you're just connecting to your same workshop file, which you should have from before, testing the connection, making sure you can count.

Now you should actually get 154 nodes. So here, if you come by our booth, we can show you much more exciting examples than the two text blobs that we have here. But here we have two different bios. And basically, the way that you can do this, and if you've already done some entity extraction, you're probably already familiar with this workflow, is we can define our domain model in terms of pedantic classes.

So here, basically, I'm going to define my person with a name and an email and then a list of skills. And then I have the skills field here. If you add relationship properties, you would have a knows. Maybe in a more complicated model, knows as a relationship would also have a proficiency property, in which case this would be a list of knows skills.

And then you would have a knows skill would have a class, would have a skill property inside of it. But you can see this is a very simple example. So all we're doing here is we're defining a list of skills that someone can have.

Skills just has the name property. And then we can create this person list. And then once we have our pedantic class defined, we can create our system message to basically be a prompt for our model. And then we can use in this case, I used 41 here.

And we gave it the documents to ingest. And then it will spit out, at the end of this, some JSON with those two people. So we had two documents. Each one corresponded to one person. And then we got our emails and skills with all their different names and such.

And once we have that,

from there, it's pretty trivial to load it. And it's very similar to what we did last time. In fact, if we go down to our graph creation here, we'll see this isn't exactly the query that we had, but it's very similar where we're ingesting one person at a time, merging on that email address, which we have indexed, sending the name.

And then for each of the skills, that's sort of a list inside of there. We're going to go ahead and merge the skill name and then that knows property connecting them together. And then, of course, I could go back to the graph and I can say these are Neo4j employees that I loaded.

But I can go ahead and look for one of them in the graph. And I should get them back here where I have them and I have the different skills that they went ahead and picked up that I can put inside of the database.

So very, very simple. We have our own Graph RAG Python package as well, which is very good for and also our knowledge graph builder. If you look at some of the code that we used to implement that, which is kind of like a reference UI, which has more examples around if you wanted to do things like document chunking with overlap

and, of course, also doing multi-threading with async and stuff like that. So you're not just doing a for loop over a bunch of bios. So we have all of that. If you stop by the booth, we can give you more around that.

But like I said, especially for this crowd, because you guys are already familiar with this, this is a very short module. And yes.

Guest59:23

So we've just gone through two resumes, added them to the graph. Do we now need to go to recluster our data and re-embed it and do that?

Zach Blumenfeld59:32

So we would have to do that, yes. So ideally, I would have done this in an order where I would have done this first. And then we would have gone through the clustering.

Guest59:43

Materializing new relationships in with weights on them.

Zach Blumenfeld59:47

We're putting new relationships in. These don't have weights on them. But if we wanted to reformulate our communities.

Guest59:55

There you go, sir. Then everyone can hear you.

Guest 259:57

Thank you. So the communities I'm kind of following what you're doing. You're adding extra links in between the nodes that have weights on them, whether it's for semantic distance for skills or whether it's for your X hops away from somebody else in terms of some other distance computation that you've materialized.

Zach Blumenfeld1:00:19

Yeah, so we would ideally rerun that in a recurring way as we upload data. So because I did, in this case, create, I think, some new skills in addition to the people. So has similar skill set that we would redo that.

And then we would get a couple more relationships there. The semantic one, if we created new skills, we would create new semantic relationships between the skills. Yes.

Guest 21:00:48

Thank you.

Zach Blumenfeld1:00:56

Allright. Any other questions

before we move on?

Guest1:01:01

I'm ready.

Document Structure1:01:02

Zach Blumenfeld1:01:02

Allright. Well, then that was a very quick module. So I'll go over and cover just some other topics around this very, very quickly

inside of my slides here. So what we saw was an example where I'd call it entity extraction or named entity recognition, where we were taking a document and we were literally breaking out people, places, and things, and relationships from within that document.

There's other things that we can do. For example, if we have certain types of documents, like from a catalog or, in this case, RFPs, we can start to break things out by actual document structure. So I'm only going to walk through this just so you understand that there's different types of extraction that we can do to create graphs.

For example, if you know what the anatomy of a document is, like in this case, if we have an RFP, we know that this RFP is going to be designed in a way where there'll be different sections, that we have an intro, objective, proposal, and subsections within that.

We can actually create a graph out of those things too. So this is another way that we can do. I would call it more like document extraction, where we're actually putting the metadata of the document and modeling it as a graph.

And the advantage of doing things this way is that, basically, as you start to embed these different pieces

and put them into a knowledge graph, you can basically do these patterns where you can do these searches on either entities that come from different chunks. And you can sort of go up and down these document hierarchies to find things, which can be very helpful if you have documents that always have repeated structure.

So you know that entity sometimes connects between the structures of those documents. You can start to incorporate that inside of your graph retrieval queries. And then it also gives you a way to do community summaries because we saw Lighting before.

But also, if you have documents that give you a natural hierarchy, you have a way of also summarizing information across those documents as well.

Guest1:03:22

Why do you have entities and documents and chunks in the same ontology as opposed to extracting entities and just creating a separate ontology separate from documents and chunks? Why do you combine the two?

Zach Blumenfeld1:03:35

Well, I think when they're combined, you can just do traversals between them.

Guest1:03:40

What's an example of a traversal that you want to do between entities and chunks?

Zach Blumenfeld1:03:46

An example that you want to do between a traversal of entities and chunks? I say legal contracts is a good example, where if you want to search for different legal clauses, but then the expiry date, that might be somewhere else.

So that would be one example.

Guest1:04:01

Thank you.

Zach Blumenfeld1:04:03

Yes.

Guest1:04:03

So just making sure I understand. So

Guest 21:04:08

Just want to make sure I'm clear on what you're talking about traversing the document. So in a legal document, say, like a data protection clause across multiple vendors or something like that, and comparing the language, is that a use case?

Zach Blumenfeld1:04:22

Yeah.

Guest 21:04:22

Yeah. OK.

Zach Blumenfeld1:04:23

Yeah, so that. And then so there might be a perpetuity piece or dates and different things, and then being able to kind of traverse over that document to find that in addition to the entities.

Anything else? Allright. Allrighty. So I just wanted to introduce that as another example of how to do things. For the third module, because we're already at 10:07, so let me just go ahead and jump into the thing so you'll get to see it.

Agent Tools1:05:00

Zach Blumenfeld1:05:00

We'll go over to module three. And this is going to be very simple. So who here we probably asked this in the beginning. I think we already asked how many people have experience building agents. This is going to be very simple.

It's just going to be a LangGraph agent that we're going to make here. Basically, what we're going to do is, again, a similar setup with our environments file. We're going to connect to Neo4j, test our connection. There's going to be four tools that we want to build.

We want to be able to retrieve the skills of a person. We want to be able to retrieve similar skills to other skills, similar people, like if we wanted to find out who's another good person to work on a thing, and then retrieve people based on a set of skills.

And in this example, we're basically going to do a lot of tools first. So at the end of this notebook, there's going to be that text-decipher stuff where you get the schema back. But here, what we're going to go over first is actually going to be putting these different tools together.

And we do that by graph patterns. And it's the same graph patterns that we've been going over. So for example, here, if we just want to find the skills that someone knows, it's very simple, just person matching to their skills.

And as you go down this notebook, basically what you're seeing is all the different patterns. So the second is retrieving people with similar skills. And here, we're actually going to use the vector index and that similar semantic relationship.

So we're basically going to pull actually, this one is searching for people with skills. I apologize. So in this one, this is

you're going to look for skills. So for example, if a user puts in different skills, those might not match the skills we have inside of the database exactly word for word. So you're going to use vector search to pull out the specific skills and what's semantically similar to those skills.

And we can do some scoring thresholds in here to pull back exactly what we want. And then that will go ahead and return some skills. So if we had, for example, this continuous delivery, cloud native, and security, this would be the types of skills that we pull back from that.

The person similarity, there's a few different ways that we can do that. And we've talked about that a lot towards the beginning. We can do it by community. So we can look for people that know different skills. We can get all of their names.

And then we can look for that Lighting community that we created. We can look for all the skills that those people know. And basically, what we're doing at that point is we're looking for people inside of the same skills community.

But the other way that you can do that is you can look for similar skill sets using the similar skill set relationship, so the hard-coded relationship that we've made from before, which basically looks at, hey, what's the actual skill overlap if you just looked at who knows what inside of the graph?

And that will bring back some answers here between because we were looking at John Garcia. And we're saying, hey, find similar people. And then we can get a score count of overlap to the different people here. And then we can start adding in that semantic similarity.

So this is where we get this big query. But what this query is actually doing is it's sort of balancing between the similar skill set and semantically similar skill set. So it's kind of taking both those scores and adding them together.

And then from there, we get a floating number score and a little bit of a different answer that's not just based on hard skill connections, but also skills that are kind of close together. And we can weight those independently as well.

And we can also recommend people given a set of skills. So if we have a set of skills here, we can just do a vector search

on those skills. And then actually, this one, combination of person-given skills. Skills.

Yeah, here it is.

So basically, the query was broken out into two parts just because this is kind of a big thing to look at. But the idea with this is we can basically do vector search on skills, get semantically similar skills, and then find person who knows those skills.

So very similar to some of the last ones. And then we can get a skill count for all of those groups and get people back. When we actually define the functions for our agent, we're going to create here a skills object, which basically is just going to help us with some of our function arguments and returns.

But basically, first tool, retrieve skills of person, very simple query. And then we'll have down here for tool two, when we say find similar skills, what we're going to look at here is, again, that query where we're going to do that semantic similarity between skills.

So we're going to do a vector search to find skills. And then we're going to go out one hop on semantic similarity. And then we're basically going to collect everything and return it. And then for the third one, we're going to do that weighting because this tool three is going to be for person similarity.

We're going to do that weighting between the similar semantic and the similar skill set with that larger query. And then I know I'm going through this kind of quickly. For the fourth one, where we say find person based on skills, here, again, our entry point is going to be a vector search on skills going out to match those semantically similar skills.

But then kind of at the end of that, we'll add on a traversal that will attach the person to knowing those skills, count who knows the most, and then effectively return that. So those are the four tools that we're going to end up using for this agent.

Agent Demo1:11:15

Zach Blumenfeld1:11:15

When we set up the agent here, if you're familiar with how LangGraph works, basically, we get our LLM. We test that it's alive. We define our list of tools. We can, if we didn't want to do this in an agentic way, we can just bind our tools to our LLM.

And we can invoke our LLM with tools. But what we're going to do instead, so this is just showing invoking the different tools, is we are going to go and run it with an agent. So we're going to use Create React Agent, which comes from LangGraph.

It's one of their pre-built agents that uses the React I don't know if you'd call it a framework, but sort of that methodology to build an agent. And effectively, once we do that, we give it the LLM. We give it the four tools that we had.

And then we can see that here, we're just testing. We're saying hi. And we're just making sure we get some response back. There's a utility function here just to make it easier running in the notebook, which will basically just do

some of the streaming methodology. So I can just say, hey, what skills does Christoph have? And then if I run that and I don't know if I need to rerun my agent here. Looks like not. Everything's running.

So you'll see it says when I ran that and actually, I ran it for the wrong question. Here, what skills does Christoph have? Person named Christoph. And then it will bring back his skill. So you see there, it will choose to use the retrieve skills of person.

And similarly, if I went down and I said, what skills are similar to Power BI and data visualization, it'll go through and choose the appropriate

tool for the job. So in this case, find similar skills. It'll pull those back. And you'll see going down, if I said, well, what person has similar skills to this other person here, then it will know, oh, I need person similarity.

So we'll go ahead and use that specific tool. So in this case, what we're doing is we're providing a bunch of tools that are presumably expert tools that we can give to the model. And then it will know that, OK, I have to go ahead and pull those specific tools to be able to provide a response.

And then there's a little app down here as well if you wanted to run the chatbot. So

it's a little Gradio app here. But basically, if I ran that, I can go ahead and come in here. And then I can have a little conversation with it. So this is very small. But what skills are similar?

I can go ahead and ask it in here and then provide it everything's working. It'll go ahead and choose the appropriate tool. And then I can say, well, who knows?

Maybe I'll just say those skills. And it should

go ahead and pull the appropriate tool to be able to find out who knows all these different skills. And if I go back

to my example here, I should see the query logic that it used. So first, it said find similar skills to what I just mentioned because I asked about Power BI. And then after that, I asked about people who know skills.

So it said find persons based on similar skills. And likewise, I can say, who is similar to those people

in the graph? And it will likewise go through. And it should understand that it needs to use the find other similar persons tools to be able to do that.

So you'll see if I was to keep going down, I should get calls here to find persons with similar. We have it here. Yeah, person similarity. So it just called the person similarity for each person.

And I know we only have a few minutes left. There is, if you wanted to run this further, basically, I have a text-decipher example. So this is where I'll have an example of passing it the annotated schema. So this is getting to kind of what you were asking about, where I've provided these descriptions.

So it's sort of like annotations for the schema as well. And then I can go ahead and give that to an aggregation query function that will have there's also an LLM inside of here that will create the cipher.

But you can see in here, I asked it some questions like describe communities. It was able to understand that it needed to grab the match person knows skill. And then it needed to grab the Lighting community. So it knew from the schema that it needed to generate this cipher.

And there's a couple more examples of that in the notebook. Are there any questions? I know I just went over a lot. Are there any questions from that that are worth answering now while we have just a couple minutes left?

Guest1:16:43

Got it. How long will the

Guest 21:16:47

Got it. Got you. Sorry, Christoph.

Guest1:16:49

I didn't even know you were here. How long will the Jupyter server be up if we want to play with this?

Zach Blumenfeld1:16:54

Jupyter server is going to go down very quickly. But if you look at the deck, at the end of the deck, I have a link to the code. And the data is all in GitHub too. So basically, if you go here, that's the GitHub repository.

So you can play with it.

Guest1:17:11

Where do I get the deck?

Zach Blumenfeld1:17:13

What's that? The deck is in the do you have access to the Slack channel?

Guest1:17:17

Yes.

Zach Blumenfeld1:17:18

So the deck is in the Slack channel. And I'll go ahead and jump to that in a second. But there's the GitHub repository. You can use ORA console. We have a free trial that you can use. You can just set up a cloud database.

And you can load the data into there. Also, before you guys leave, there's a meetup happening tomorrow.

Guest1:17:41

Is it today? Is it tonight?

Zach Blumenfeld1:17:42

It's tonight. Oh, sorry. Tonight at 5:00. And there's a link there for more information on that. And then we also have another workshop at 1 o'clock where today was very simple. We're going to go over more graph analytics type of stuff in that workshop.

So the community stuff that I was doing, we're going to dive more into depth on that in that workshop.

Other than that, come by our booth if you have more questions. We're going to be whereverright there is. I don't think we have a big expo hall. But if you want to see Neo4j, MCP servers, ADK examples, more knowledge graph construction, all a great place to come to ask all those types of questions.