 all right welcome everybody to this episode of going meta we are on episode 17 and this episode is going to be about open ai and neo4j and how you can integrate rdf uh with that i am subbing in for for alex this week and yeah i think i'll hand it over to you jesus and tell us more about this perfect yeah thanks max yeah it's um different host and different time because normally this should have uh taken place next week but both alex and me we're going to be traveling so you kindly step in and a couple days earlier but you know hopefully equally good it's going to be a an interesting one so let me um as usual bring my screen um i'm gonna share my screen let me sure i'm doing it right so share the whole screen, hopefully. I can also mention while we're waiting that our developer conference, Nodes 2023, is open for CFPs and early registrations. So if you want to have a talk about Neo4j or something like that, you can head over to that link down there and uh sign up excellent that is definitely great advice and everyone should be so yeah exactly good stuff so hopefully you can you can see my screen and and well you know that you know how we do it right we've done this before i don't know it was the last one we did but it's probably close to to a year or less than a year i believe ago yeah but we open with a couple of slides really just uh uh to introduce introduce the concept of what we're going to try and and go we go straight into into coding which is what we normally do in in uh in these growing matters the fun part exactly exactly so yeah well like like you said i mean today you know, we couldn't, you know, keep postponing it any longer because, you know, everybody's talking about OpenAI, so we had to do our episode on it. So, yeah, I mean, the idea is we're going to try to use OpenAI and in particular, well, I'm going to show at the beginning chat GPT, but then we're going to use the OpenAI API to show some more advanced integration. But the idea is pretty simple, right? So we want to accelerate the creation of a knowledge graph in NeoPJ by getting data from OpenAI, from the API. And the idea, as we know, is we interact with these api using uh using natural language right so our questions are going to be natural language but we're going to see what type of answers can we get of course we've all seen it returning uh amazing you know natural language explanations and um but we're going to explore uh uh return more structured responses like in the form of things like JSON, Cypher, and we'll eventually get to using RDF and connect that with NeoSemantics as well because we're going to see and we've talked about RDF in those terms many times here. So RDF is a great vehicle to exchange graph-shaped data. It's a very, very good way of... Does that make sense? Is it? Yeah, I think that sounds great. I mean, RDF is this kind of thing that has all these references and you work with ontologies that are set up to actually give you a semantic meaning, right? Just beyond what the data is actually capturing, right? That's exactly it. So it's a standard to exchange data. I mean, there's multiple serializations. And you're right. I mean, every statement, because RDF is described in terms of statement or triples as they call it, subject, predicate, object, and these statements use unique identifiers called URIs that refer to vocabularies, ontologies, that provide additional context and definitions of the concepts that are being described. So that's exactly it. And I thought it would be a good mechanism to exchange information between the API, between the ChatGPT and Neo4j in this context. And like I was mentioning before, we'll go from there to looking at a more programmatic integration, right? Because interestingly, APOC, the extended version, has just released a couple of additional methods that provide integration with this OpenAI API. So that's really, really cool because in a couple of lines of code, we're going to be able to generate a natural language request to this API, get some results. And if we get them in RDF, as you know, it's the objective of this session, we should be able to import them directly using new semantics or visualize them against semantics. But that's the idea. Let's go one step at a time. But that's the outline of the session. I can also mention that these ML functions are now available in sandbox as well. So if you want to go and try them out there, you can do that as well. Absolutely. Not only you can do that, I am going to show that that is the case. Let me, I'm going to run these in the Sandbox. So as we speak, we're going to create an instance and let's leave this one running. And I'm going to bring up my uh chat gpt a new a new chat i'm going to put here on on the side so that i'm going to try to get the two things uh running in parallel so i have the the chat here and have my um sandbox once it's created it's already here perfect and yes you're totally right so i i learned that these functions were already deployed in the sandbox so we're going to see them in in action so we should have that uh ready now so we have the user and the password let's leave it connecting and uh well let's start with the session. So I'm going to begin with a normal chat first. So before we hit the integration with APOC, let's look at the kind of things that we can ask from ChatGPT. And I'm going to take any random question. And the one thing that came to mind, normally I prepare this session with some code, but it's interesting because this one is very much natural language, right? So we're going to be presenting prompts and my plan is literally just a few notes of the kind of questions that I wanted to ask. But let's take a random one. So I was saying, which uh what uh commercial products actually slow that noise it's my keyboard commercial oh that's my sandbox still starting we don't need that we can this is maybe a bit of a distraction but let's focus here yeah actually probably i should go with something a bit split like that. And then we put this one on the other side and let this one. So I was going to say what commercial products are associated with the tennis player Rafa Nadal all that's and you know question like any other so if i ask this question to the chat gpt i will get a a very nice answer in natural language which is right but what i want to do like i said at the beginning is we we're going to want to populate a knowledge graph with this information right so what i'm I'm going to ask the bot is to, can you provide the answer? And we can do it in many different ways, right? So we can, of course, ask it to, well, I don't know, we could, in Jason, like, I mean, we can even put it some structure. I don't know what kind of JSON will it generate, but let's let it surprise us. Well, there you go. So we have, yeah. So you can give it kind of system commands to kind of, you know, take your answer and kind of reshape it in in different formats that is that is right so we uh now we have kind of a less less rich answer right better better structured so we have a we have something that we could eventually i mean why not i mean i see the the the the name of Rafa here. So I could say, why don't you, I could ask maybe to produce a cipher to import that JSON into Neo4j. Let's see what that does. that that would be a you know uh there you go so it's telling us that there is a function called um json which is uh totally right so that would be one way of of doing it so that's great advice. So we could even try that. So this is basically reading the JSON. So it's unwinding and creating actually the player. It's hard-coded, but then it's iterating over the keys. I mean, we could even give it a try. Because sometimes it's not totally accurate, but let's let's let's put it to the test why not so if we take the the json and we put it in a parameter let's call it json and we store this right so we have this data and if we take this uh code now will it work so basically what we need to do though is to change it from uh reading it from a file to reading it from this parameter right so instead of so we need to um unwind not value but we need to unwind oops um what is it is it right but it it doesn't seem i don't i don't think that's built for this type of of output is it because you know it seems to be unwinding on the player it's because it's not a collection so we have like lists of products so it doesn't uh depending player because there's not a player uh element here no clearly clearly it's not not not polished but anyway that's that yeah that's that's not what i you know wanted to test anyway but it's uh it's you know one possibility is to try and and have it uh have it structured like that so um yeah it would be great if the two would be in sync but anyway so that that will be one one one possible way but what i was going today is um to to try and and and do it in a way that basically i didn't have to face this kind of problem right that the format of the input determines very much the you know the the the code that we have to write to to ingest uh the you know this json in particular because you know it could have been organized in a different way right so we have so you want to be a little bit more precise about what you're asking for and such and you want to be structured about how you're actually doing yeah because you know the thing is you know i i wonder if we could ask the bot to generate an alternative JSON. So basically the same information could be conveyed in different structures. So we could have a route, the Rafa Nadal, and then we'll have a map with the... It could have been a list or it could have been a different way of nesting. And this is, in the general case, I suppose undesirable, right? Because we have to adapt your ingestion code to deal with that. And that's what I was thinking. Maybe you trying to explore the RDF option would be an interesting way. Let's see what it comes up with. So if I say, can you provide the... I mean, actually, let me copy the previous question. I suppose we can go back and say the same, but now actually let's ask it to produce it. but provide the result in RDF serialize as turtle because we have multiple realizations let's see if you know what that gets so hopefully that will produce something that we can read and okay so perfect. So as you can see, these are the triples that we're talking about before. So it's telling us that Rafael Nadal is a player. There's a brand called Nike and some others. So it's describing products and the products have labels and they're endorsed by Rafael Nadal. So they link to it so you know that looks that looks uh decent so it's uh it's a collection of of statements that we could eventually uh try to injure let's let's be ambitious and try this time again if he could otherwise i can write it myself but can i uh ask you to produce a cipher statement to import that into Neo4j using neo semantics or m10s i don't know if that's help it finding the way to do it okay to import that that's looking good perfect so it's uh i suppose it's just nesting the whole rdf but inside a call to the method RDF input inline and that's exactly what I was meaning before so because RDF is a collection of statements that they themselves form a graph I don't need to care much about you know that the structure and the kind of graph that I'm producing because it's already it's already a graph right so so just keep everything in line and just throw it in there right exactly and then delegate to to neo semantics to process those triples and uh let's uh let's copy this code maybe adjust it a little bit so let's get rid of this json which was not very useful but if i if i paste this code and i don't know if this is being um very useful to split the screen like that but is it is it readable on your side max or is it too yeah i think it's all right i think it's all right right so basically as we see all it's done is you know there's a collection of triples here serializes rdf but they're inside the this call uh antennas uh Neosemantics, RDF import, inline. Inline is the flavor of the procedure that takes the RDF's payload, so that's exactly what we're doing. But instead of just returning the termination status, I'm going to, because it's a single call, I can run it from here. It's going to complain because before you can import as we know this has happened many times it's going to ask us to create first a um a constraint that needs to be added before new semantics can operate so I will uh quite handily it's part of the error message so all I need to do is copy this paste it here uh and where is it did I know there you go so that's the constraint created and if I run it again now it's going to complain because we need a config first so the first time actually let me because you know I'm thinking of this as if I, I mean, I'm, of course, familiar with the new semantics plugin and I know what to do next. But what if I said, hey, I wonder if it gets to that. Certainly, that means... Oh, brilliant. That's great. Oh, stop it. I don't need to... I mean, I don't need to run it. Yeah, basically, it's found exactly the missing piece. So we need a a configuration we need to initialize it right initialize the the the graph and that would be perfect and then of course continue with the whole input in line which they needed to repeat so let's just copy that fragment which is exactly what we need is it letting me copy just a portion of it or am I being copy so yeah that's useful and probably that removes pressure from me generating, uh, the manual because people can do that and get answers for everything. Right. So we don't need to let's skip the docs for next iteration. Right. Exactly. Okay. So, well, we can, we can, yeah, we can set that up. Um, uh, we can create the. That's done. And finally, we can try it finally once more. And actually, before I do imports, yeah, no, let's go ahead and do the input. Why not? Didn't like it. So, there was a dot in line 49 I wonder if that could be. Is it some URI that's malformed? I don't know. Let's give it another try. Okay, so that was it. It looks, I mean, this is not a problem in general is when we run it through the browser sometimes the escaping of some uh strings creates trouble but it's um in general it's fine so it's imported the the the triples the collection of triples and now we have a graph that we can explore in in neo look at that oh wow yeah let's you know get move this a bit to the left oh there you there you go. We could take a bit more state for this. So look at that. So we have a collection of triples imported. Well, now it's been translated into a property graph, but we have kind of the, as expected, we have a node representing the player, which we can, didn't add to it the the label just have the uri but anyway that's the note representing rafa nadal and we have a number of of things related to it like uh for example that there's nike footwear that's endorsed by uh rafa there's which are mile looks real meal i don't know that but you know there's there's a number of products. So that's pretty cool, I would say. Because we actually, again, it's this idea of using, getting ChatGPT in this case to generate RDS. A context we can explore, right? Like we can grab whatever kind of question we want that we want to dig down to. Exactly. I mean, there's only one one thing that i would question here and it's um you know what happens if i want to because you know this is one one call to these uh maybe i don't know i want to combine this with with information coming from other sources and i would like things to merge nicely right So if I bring additional information about Rafa Nadal or even about, you know, Banco, Sabadell, whatever, or any of these items, I want them to link nicely. And if, you know, in the RDF world, things are identified with URIs. And if you see by default, what ChatGPT has done is generate random URIs. So it's defined a prefix up here that's called example and i think it probably adds it to the comment right not not here in the previous one where it generated so um sometimes it adds a uh comment here we go so the player rafa nadal so let's see if it has an additional information no it doesn't but anyway it's not using any any standard uh so i was wondering if in the comment it mentions the fact that he's come up with this kind of random uh uri but it's not using any kind of standard way of referring to to these things because we could have used, for example, any, I'm thinking of DBpedia or Wikidata IDs. Right, right. Make it simpler. But you might have to ask for that, for it to actually include that. So it looks like by default, it comes up with its own terminology, which is great. And the same with, I don't know if it's using any specific vocabulary so just rdf rdfs so it's using the the you know these example uh vocabulary which is okay because it forms a graph but it would cause you know create difficulties if we then want things to integrate nicely by using the same uris or even using standard standard vocabulary so let's exactly do what you said so i'm going to say can you can you um regenerate the rdf but uh using uh let's use schema.org it's a standard vocabulary and wikidataata IDs for resources. That's now work. Let's see. So it might build something similar, but hopefully, oh, it's still using example. It's, well, but Wikidata. Right, so that's been useful on the... But he's clearly ignored me on the Wikidata thing. I think if you ask it from the beginning with a question as well, it might be different because now it thinks that it needs to reiterate whatever uh reiterate whatever you already know there's one thing that has changed if you see now uh the predicates uh used here are fixed by schema which is one of the uh additional constraints that we added so let's use uh these um vocabulary terms but then the thing that it's still not doing is identifying Rafa Nadal. Okay, so you think we can use the same, I mean, like, copy the question, but... I just add to the... The whole thing? Yeah. Okay. I mean, I'm not sure, but... Yeah, I don't know. It's worth a try. with their Wikidata. Did that say Wikidata? Wikidata. Yeah. Wikidata IDs. Okay. Let's, sorry. That's the wrong answer. Let's see if that improved things. But I also think like chat GPT, no, it doesn't do that. I mean, I think it also has to do with like it tries oh it did it did yeah so it still has the the example but it's now using the id so now that looks like it's a step in the right direction but i'm not sure that the ids would actually be correct because i know that i know that uh okay we can chat gptPT has a way of guesstimating things like that. Exactly. Yeah, because we have to keep in mind that this is kind of machine learning. I mean, I don't know. I'm certain that chatGPT is not loaded with the wiki data. The wiki data is a structural source that we can query with Sparkle, which we have done in the past. But it looks like it can generate some plausible statements. Let's see what they look like. Let me delete the graph. If I empty everything that we've imported, but I kind of re-initialize. Let's keep this time the namespaces because we're going to be using them. So, if I copy this new fragment of RDF, so let's initialize the graph and now let's try to import again. So it was called n10s input in line. It's RDF import, I think. Yeah. Input in line. And we pass the RDF here, pasting it, and then we said that this realization is total. I wonder if we're still going to have the double quotes issue. Looks like we do. Let's try to find it. Invite input as expected. So let's see what that is okay so that's the quote yeah because you know we're inside single quote so if we have any any quotes break it but again this is the that's it so it's uh you know it. But again, this is the... That's it. So it's, you know, the problem of running it in the browser, but it's... Yeah. You can escape it and get it to work, but probably... Yeah, exactly. Copy paste this. But anyway, so the graphs should hopefully look, you know, pretty much the same. So if we look at it, we still, I mean, it's changed the coloring, but now, you know, we have a bit more annotated things. Right. The difference now, let's make this a bit bigger like we were doing before. So we have Rafa Nadal at the center and now we have all the predicates. Everything is prefixed by schema.s.c.h, which is the prefix for schema.org. Now, whether these are real predicates in the vocabulary or they have been made up, we'll find out. So what you were suggesting, Max, is that maybe these IDs that in theory, it's adamant that they are the ones, they might not be. Well, we have an easy way to find out. So we can actually, if we have Rafa Nadal and and we click on this that should take us to rafanadal's page and you're right this is building so yeah clearly not not the not what we were after so well anyway that that's interesting so it's a it's a great observation because you know the yeah that's uh let's keep in mind that this is a machine. I mean, it's a completion end. So it's basically guessing what an ID might look like and it tries to make its best estimate based on that. It would be interesting to know if it would be consistent. So for example, if I come and say, for example, let's, yeah, I mean, for example, this Banco Sabadell. So this is one of the things that one of the brands, one of the products, brands in this case that Nadal is associated with. Maybe he's done say can you provide additional facts about bamco sabadell i would say again uh in rdf and do we have to keep some memory let's let's see what it does i suppose it will will provide it in RDF in the same way and using the same skill. What I'm after... There you go. So it's... I'm trying to find if it's going to try to keep consistency, right? Because this might be wrong, right? If I click on Banco Sabadell, maybe it's going to take it somewhere else. But... And yeah, so football club. Perfect. Yeah. But will it, if I try to enrich my graph with another fragment of RDF, will these IDs be used consistently? It looks like they are, right? This 4680, it keeps Q2 4680. So it looks like it's, yeah, not totally random, but we can... I mean, it's in your context, right? And I think... Exactly. But I wonder if I start another chat session, whether that would be... Yeah, it might be different based on how you phrased your question, I guess. Yeah. And I see that there's some quotes here that we might have trouble with. Hopefully there's more. Let's see. So we are adding this additional bunch of triples. And if everything works fine, now we should have, well, the graph growing, right? So, and that's what added now. So yeah, perfect. So if I, if i so yeah we have banco sabadell and and what is done is well it's added a location which i don't know why it's not coloring it nicely but it should if i do uh style set it should hopefully recolor things or make them more consistent anyway no for some reason it's not uh but well anyway we we can see the content here of the node so maybe it doesn't have uh it has a name but it doesn't have a label right i mean but it's linked things nicely right so it found that sabadell is located in in spain in a place called uh alicante it's a member of Spanish Bankers Association. So it's pretty cool. So it seems to be consistent in the naming of things, which was the objective that we were up to. But of course, the word of caution here is the one that you notice, which is the use of generated... I mean, you could probably use some kind of tasking framework like auto auto what's it called aldrigpt or something like that to make it actually go and look up these things and right yeah exactly so that that's that's the thing yeah because this this is what people call hallucinations right so it's when it's trying to complete to provide something that's plausible and apparently correct. But if we make a proper scrutiny, we realize that these ideas are actually and yes, that's actually an interesting exercise, right? So for example, because we can parse that and we're going to do it in now in integration with APOC, we could take these IDs, generate a request to Wikidata and eventually verify that they are the right thing. I mean, it might be a heavy process and I mean, the whole thing is kind of questionable in a way, right? Because ultimately what we're getting is you know we uh if we're getting wiki data uh fragments we might as well go directly to wiki data and run the queries in sparkle like we've done you know but i i guess the you know but the the assumption here is well first of all you know this this will be in theory i don't know if a super super set of of what's uh what's in in in wikidata and the other thing of course the most important is that uh well we're providing a natural language question so we're asking give me facts about banco sabadell without having to write the sparkle and being even aware of that of that query language so but anyway i think that that kind of um proves the the sort of the first point, right? I'm going to try to maybe bring back the slides that we were using at the beginning. But we've kind of shown how we can run these questions. I mean, in this case, it was ChatGPT, not the API, which we're going to test in a minute. But we've seen how we can have it format the answers in formats that are better structured and that we could eventually consume in a relatively easy and straightforward fashion. And RDF in particular was especially convenient because the combination of Neo-Semantics made it really, really, really easy to ingest. But- You can actually make the graph grow with new questions as well. Exactly. Exactly, exactly. So that's the whole idea. And what I wanted to take it in the next 10ish minutes or so is exploring these new functions in APOC. functions, right? They did the indie in April. And I guess we can do a quick search. A for I don't know if that's going to be a good search. No, that's April. It's probably not indexed by Google yet. It's very recent, isn't it? April new VJ. So if we go to the that would be the documentation. Is this the, that's not the extended one. Yeah, you need to extend the version. OK, extended. That's one. And here we go. That's machine learning and OpenAI access. So for those of you who want to give it a try, you have all the three methods that are currently implemented. So we have one that generates embeddings. So that's something we're not going to touch on today, but it's a very interesting topic as well. So it takes some text and generates an embedding as a collection of numeric numeric values in in forming a vector uh text completion as well where we uh um pass some text and it will provide an answer and um and the one that we're going to be testing today which is kind of replicating what we've just done right so we're gonna have a chat completion api where we give the context might be just uh yeah some context and a question and we will have it uh produce some uh some response for us so that's what we're gonna do I'm going to actually copy this and let's go straight uh here so I'm going to um place that let's run a single test on this one it's going to of course complain because i have to define my key so let me um do that should i put your uh screen off for a second privately here don't worry i'll all right if you give me just uh just one one second i'll i'll take it from uh yeah i could have um actually what you said but okay so I have my API key and oops I think I've lost but we can copy it again so what this is going to do for us if I it's asking it to well you can you can see the actually the way I've done it and in order to make it easier from here on, let's take the prompt part and let's make these a parameter as well. So if I run that, it's going to complain because it doesn't have a prompt. But I'm going to define a parameter, which is the prompt, which will contain the value. In this case, it's just the context. So there's a system, which is the context for for the the way we want the the api to behave i want answers with a single word and the actual question is what planets do humans live on so if i set these as a as a parameter i can now come back to to my uh request which is very simple so as you can can see, it's the APOC ML OpenAI chat. And we pass the prompt and the key that I have set before. And if I run this, it might take a few seconds, but it returns us a structure that contains in the choices section the message, which actually contains the answer, which is the error. So pretty cool. So let's try that. Before that, let's prepare it a bit more. So we actually don't want, I mean, this is informative and it tells us the model that's being used by default and so on and so forth, but we actually really only want, we could say something like uh return or we can return the value just for information but what we really want is value dot um actually dot choices right we said so this is a json structure and we want the choices and in particular the first one because it's i think by default only returns one and we get the message and in particular the first one because it's I think by default only returns one and we get the message and in the message we get the content so if I've made no mistake so it's the value choices the first one message and uh content so if I redo that it will regenerate the request and yeah that's that's the actual content that we care about right good so now let's let's try our our thing right so um and for these i have kind of copied my my prompt here but what i want to do is actually define my own right so i'm going to copy it and it would look something like this which kind of replicates what we were doing before so we have some context uh in using the system role saying provide the answers in rdf serialize as turtle and using schema.org and wiki data for resources and then the actual question which is what are the which are the brands associated with rafa nadal right so that's that's our our prompt i mean we should not expect to get the same results because we're using different model right here by default is using a a different one so probably not it's not going to be as rich as the other one but let's uh let's see what that looks like so um if i uh run it um hopefully we will get something if not identical similar to what we were uh getting before it's taking a bit longer but ideally that would here we go produce oh wow so that's the whole thing but here i'm just selecting um oh that's interesting that's been quite different actually yeah because it's producing a sparkle query which is not really rdf that's uh you know being creative here or maybe it's uh oh it's generating a sparkle query followed by the answer but that's not what i want i want rdf serialized data so maybe we should adjust the prompt maybe you know we should say something i realized you could you could say like you are uh i guess you could say like you are uh yeah you're a triple store that answers only in our rdf and something like that would that be like i'm not super familiar with that but should i use the system role for that yeah exactly so the system role is basically um you can set up different roles for it to interact us. So you can say that it's an assistant or it's a... We pull us, we pull us, but no sparkle. Where is something like that? You can say only respond in RDF or something like that. Only respond in rdf or something like that only respond in rdf um use uh turtle civilization civilization and using schema.org and wikidata for use i don't know let's give that another try and see what happens now oh this is setting the prompt and now i have to call again um the actual method that will take that prompt and um and return the results that looks better but uh yeah it's a bit less rich than and i would expect something similar to what we saw before right so if we check these this is probably not going to be raffen at all this killing me not discography there you go so uh did you get uh other choices back or uh i don't think so normally i think by default it returns only the i don't think so. Normally, I think by default, it returns only the first. But anyway, in this case, what I wanted to show is what the integration would look like. So we understand that it's not perfect, and there would be ways. Actually, it's not perfect. It's far from perfect here. You have to engineer your prompt to give you back the exact kind of data that you want. Exactly. So maybe, I don't know would it be should we give some hints like the the the id but it didn't i guess that defeats the purpose right if i have to tell him uh rafa nadal's id is this one by the way and and then but still the brands that it connects to it would be um will be still still broken but i mean i mean you could do that if you have pre-existing data let's say you have an a graph right in your database that you can pull in that and say hey i want to know more about this id or something like that yeah yeah that that's that's a good point so instead of of it being a fully natural language question, it's driven by my, let's say I have some notes in my graph that are curated and I know that are using the right IDs. And I would say, hey, for this ID, can you provide representing Ruffin at all? Can you provide me additional facts? And then it would probably enrich it in a more meaningful way. Okay. So, but the good thing is that the use of schema.org seems to be more consistent. So if I click on that, that should take us, hopefully, to the definition of the plugin. So that's right. So this is using the right... So the use of the. So that's right. So this is using the right. So the use of vocabulary terms seems to be consistent. So that's good. And can you perhaps make it so that you get more properties and not just like the. Yeah, it's hard to tell. I mean, but anyway, well, let's look at what this integration could look like. But you know, that's so we're seeing that this is actually returning us a collection of triples. And when we get a collection of triples, I mean, we can instead of returning it, we can say with these as RDF payload, let's call it we can now call as we were saying before I can call my semantics RDF this RDF payload. Right. Indicating that it comes in turtle format, right? So that's the reason. Actually, if instead of importing it, I'm doing a preview. That should be good enough. And that would show without writing to the database it would return the nodes and relationships that it produces and uh and we can return everything right like this we get we get the whole context we get the value we get the the rdf that we're getting and we can debug if it doesn't make sense or if it doesn't do what we expect it to. But basically here's where we are chaining in... Of course, there's some wrong... What is it complaining about? It's column on the command. The problem is because it's thrown an exception, we't tell if this is should we expect it to be consistent i mean it's the fact that it has produced this before if we write it again it might be yeah so yeah i guess what we're learning from this session is that it's uh you know still far from being in in a you know in a place where we can use it to really i mean it does a number of things oh look at that. It's now producing something different, including actual natural language. Right. Okay. I think like with the API, usually you can set like parameters that kind of gauge how much it should, like the tolerance or like how much it should um um like the tolerance or like how much it should uh yeah yes and not guess so stuff like that right right right okay but look at that because now the thing is we said that it could only return in theory uh rdf and it seems to be adding this context where it's kind of explaining i mean right we could eventually but you know i guess because you can tell it to not return anything else but i think that's what we put is that not what we because we said you're yeah but responding rdf or and do not and do not respond without anything else that's an rdf we try this and and but um yeah i suppose here we're in kind of prompt engineering territory right where we have to kind of fit it until it returns exactly there you go so that's there you go it's a bit more like what we were getting before but i'm tempted to run it one more time because it you know that's what we got before but this time i guess this is never going to be consistent because it's you know it's not there you go so that's i i don't know but it depends on i, I think, the tolerance that you have. Or maybe it's temperature. I don't remember if it's temperature or tolerance. But even, yeah, because even the, like, here is generating associated with statements, whereas here is generating brand statements. And then, yeah, the IDs, they're entirely different, right? I think you have to kind of give, I mean, if you were to do the system command, you can engineer that a lot more. Like, you can tell it, like, and give it examples how you want it to kind of output. So you can give it, like, two or it examples how you want it to kind of output so you can give it like two or three examples and then say like okay okay i see i see so it's there's there's more work to be done and still doesn't like it so i don't know if you know what flavor of it it's returning but you know in theory if we were sure that um and um you know i was being a bit optimistic on how consistent or how predictable the RDF being generated. Oh, and that's still different again. But this looks like something that NeoSemantic should have been able to process. I wonder if, of course, we don't know because it's throwing an exception but if we did a antennas rdf preview in line and we paste it and with a turtle station not liking it so there's uh illegal carriage return it's interesting maybe you have like uh the quote here no that's that makes sense because i had it was my fault uh not removing the quotes here is that it there you go so now now it's um it's better so if it was that so it has what rougher well i suppose something that would have been rougher but probably will not be because again this is yeah in somewhere in ireland so not not rough at all but yeah the same same idea so well yeah so some some clear prompt engineering to be to be done here but once once we we get that right i mean we should be able to to chain the yeah as we were seeing here the the the the generation of the of the rdf directly from the api and then the input of the same rdf or at least the preview of the same rdf in um you know in in basically two lines of cypher but um but well yeah it's uh of wishful thinking so i have to be doing i was you know honest i was curious about because you know we there's been a lot of of uh uh discussion and and comments on on how the two you know how close the two are, how close the two should be. And I was thinking maybe it would be worth exploring how easy it is effectively to bring data from these API or from the chat GPT directly into Neo. And I guess, well, we've got a um i think i think if you add lookups and stuff like that where when when you can stop it from doing like hallucinations and stuff like that and have uh like system prompts that are like yeah i guess some people give you the rules of like it has to follow like it has to be a complete uh has to be a complete rdf statement yeah exactly so some some validations here like uh well first make sure that we get it to consistently produce just rdf and not text uh descriptions which that seems to be okay maybe there's some escaping or something like that yeah And then some, yeah, like you say, some validation of the URIs being used, especially if you want to use standards like the Wikidata ones. And then eventually if those validations pass, then you would be in a position to ingest it. But well, that's what we had for today let me stop sharing and maybe I don't know about any any questions from the attendees if not we can probably bring and bring it here and so, I think we have one question. I could put it up on screen here, but I'm not sure if that is. Okay, now it's a relationship. It's all fine. Oh, wow. Well, that seems to be an unrelated thing, right? Because this is about importing the data. So yes, I mean, you can... Yeah. Other than that, I don't think we have much more questions today. So there's... Oh, there you go. There's another one there on generating Sparkle queries with OpenAI and use that to query Wicked Data would be cool. That's a great one, but I'm tempted to think, and let's use two more minutes to test that quickly. Yeah, sure. In the same way it's managed to, let me present again. Why not? Yeah, I mean, so it would be like you would ask it to make a Wikidata or a Sparkle query. Exactly, a Sparkle. Can you see my screen again? Yep. So if, do I still have my, I should have my, here we go, that's my chat so if i instead of um i can hide that instead of uh asking it to produce rdf can you generate a sparkle theory um for or just to answer this question or something like that. We get the, I don't know, the, the, we said the brands, the products, excuse me, the commercial product. I think you could just ask like to answer this question and then give it a question. Let's try this one and see what he comes up with. Spark query, good, that's promising, but here we go. So that's, okay, so here it's using another ID for Rafa Nadal, hopefully that's the right one. And then it's um yeah well um i would guess that the ids are hallucinated here as well but i would not be surprised if that's the case but there's only one way to find out right yeah we go to wikidata and we paste that query as it is so this thing uh this is not rafanadal unfortunately yeah so this and um oh this is a this is not rough at all, unfortunately. So this is really rough. And, oh, this is a national library in Spain. Yeah, so the ideas seem to be... It's interesting because it seems to be decent at the predicates. Like, for example, it understands that it's looking for a hierarchy, for instance of, or so class of of but then it gets it completely wrong when it looks at things like products or or you know individuals like uh so i would not be surprised if this does not return any any answers because you know that's uh so very very good question but it looks like again it suffers from the same type of problem, right? So it still doesn't seem to be aware of these. Are you able to anchor these queries maybe in some way without the IDs? Like maybe look for a name or something like that? Or do they have to be anchored? No, it could be. I mean, can can you i would say but search by name instead of my id suppose the performance would be as good but still that could that's a good idea so let's copy this code so we copied it and if i come here and we so this is looking for a person with that name and right but again it's using a bad predicate so that's never going to work so let me let me comment that out so if i comment that and i said that this pro so oh let's if we get rid of all that we could uh and so but it's already changing quite a bit to be honest if i run that it doesn't now it doesn't find it so rough and adult it's probably not the label so it's not even finding a thing that has status label so maybe that would be there the name where you would use a different maybe rafael at all any chance there you go so maybe this guy is him that's it so so yeah it can be done as you can see max but it's still not generating something so so great great question and great idea but it looks like um still again suffering from the same type of of limitation I guess, in this context. Yeah, I think it needs to kind of validate that data in some sense if you want to pull it in and have it be specific with the right IDs and all of that. Yeah, yeah, cool. Anyway, that was an interesting one. Yeah, I think it was really interesting. And it's good to see that you're able to actually make these queries as well in the in the database that's that's right yeah good stuff okay well thank you then everyone all right thank you thanks max for for uh sending in this time exactly yeah all right thank you everybody goodbye cheers have a great evening everyone
Going Meta - Ep 17: RDF-ing between OpenAI and Neo4j
Episode 17 of Going Meta - RDF-ing between OpenAI and Neo4j

Jesús Barrasa: https://twitter.com/BarrasaDV
Repository: https://github.com/jbarrasa/goingmeta

Check out https://community.neo4j.com/ for questions and discussions around Neo4j

#neo4j #graphdatabase #semantic #knowledgegraph #rdf #semantics