recursive web loading
All checks were successful
studiorailgun/trpg/pipeline/head This commit looks good

This commit is contained in:
austin 2024-12-29 17:47:12 -05:00
parent d451906ea8
commit 482ca48927
8 changed files with 264 additions and 4 deletions

View File

@ -1,4 +1,5 @@
{
"tag" : "root",
"selfId": 2,
"nodes" : {
"0" : {
@ -32,6 +33,10 @@
"7" : {
"id" : 7,
"name" : "CurrentConversation"
},
"8" : {
"id" : 8,
"name" : "Hat"
}
},
"relations" : {
@ -70,6 +75,12 @@
"name" : "ParticipantOf",
"parent" : 7,
"child" : 2
},
"6" : {
"id" : 6,
"name" : "Possession",
"parent" : 2,
"child" : 8
}
}
}

View File

@ -0,0 +1,85 @@
{
"selfId": 2,
"nodes" : {
"0" : {
"id" : 0,
"name" : "Bert"
},
"1" : {
"id" : 1,
"name" : "Name"
},
"2" : {
"id" : 2,
"name" : "Self"
},
"3" : {
"id" : 3,
"name" : "Person"
},
"4" : {
"id" : 4,
"name" : "Other"
},
"5" : {
"id" : 5,
"name" : "Quote"
},
"6" : {
"id" : 6,
"name" : "Conversation"
},
"7" : {
"id" : 7,
"name" : "CurrentConversation"
},
"8" : {
"id" : 8,
"name" : "Hat"
}
},
"relations" : {
"0" : {
"id" : 0,
"name" : "Name",
"parent" : 0,
"child" : 2
},
"1" : {
"id" : 1,
"name" : "InstanceOf",
"parent" : 3,
"child" : 2
},
"2" : {
"id" : 2,
"name" : "InstanceOf",
"parent" : 1,
"child" : 0
},
"3" : {
"id" : 3,
"name" : "InstanceOf",
"parent" : 3,
"child" : 4
},
"4" : {
"id" : 4,
"name" : "ParticipantOf",
"parent" : 7,
"child" : 4
},
"5" : {
"id" : 5,
"name" : "ParticipantOf",
"parent" : 7,
"child" : 2
},
"6" : {
"id" : 6,
"name" : "Possession",
"parent" : 2,
"child" : 8
}
}
}

24
data/webs/color.json Normal file
View File

@ -0,0 +1,24 @@
{
"tag" : "color",
"nodes" : {
"0" : {
"id" : 0,
"name" : "Color"
},
"1" : {
"id" : 1,
"name" : "Blue"
}
},
"relations" : {
"0" : {
"id" : 0,
"name" : "InstanceOf",
"parent" : 0,
"child" : 1
}
},
"crossRelations" : [
]
}

View File

@ -1,11 +1,10 @@
package org.studiorailgun;
import java.io.File;
import org.studiorailgun.conversation.categorization.SentenceFunctionCategorizor;
import org.studiorailgun.conversation.evaluators.greet.GreetingEval;
import org.studiorailgun.conversation.parser.NLPParser;
import org.studiorailgun.conversation.tracking.Conversation;
import org.studiorailgun.knowledge.CSVExport;
import org.studiorailgun.knowledge.KnowledgeWeb;
/**
@ -35,9 +34,11 @@ public class Globals {
NLPParser.init();
//init web
Globals.web = FileUtils.loadObjectFromFile(new File(webPath), KnowledgeWeb.class);
Globals.web = KnowledgeWeb.load(webPath);
Globals.web.initLinks();
CSVExport.export("temp");
//init convo
Globals.conversation = Conversation.parse(Globals.web);
}

View File

@ -1,5 +1,6 @@
package org.studiorailgun.knowledge;
import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
@ -7,11 +8,19 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.studiorailgun.FileUtils;
import org.studiorailgun.Globals;
/**
* A knowledge web
*/
public class KnowledgeWeb {
/**
* A unique tag to identify this web
*/
String tag;
/**
* The nodes;
@ -32,6 +41,10 @@ public class KnowledgeWeb {
* The node that represents the current ai
*/
int selfId;
/**
* Child webs
*/
List<String> children;
/**
* Constructor
@ -42,6 +55,95 @@ public class KnowledgeWeb {
this.typeRelationLookup = new HashMap<String,List<Integer>>();
}
/**
* Loads the knowledge web starting with the root provided
* @param startPoint The starting point
* @return The full web
*/
public static KnowledgeWeb load(String startPoint){
Map<String,Integer> crossRelationLookupMap = new HashMap<String,Integer>();
List<String> webTagList = new LinkedList<String>();
KnowledgeWeb rVal = KnowledgeWeb.recursivelyLoad(crossRelationLookupMap, webTagList, startPoint);
if(rVal.getTag() == null){
throw new UnsupportedOperationException("Web without tag defined! " + startPoint);
}
Globals.web = rVal;
//fix the IDs referenced by the links
for(Relation relation : rVal.relations.values()){
String lookupId = "node-" + relation.webTag + relation.parent;
int nodeId = crossRelationLookupMap.get(lookupId);
relation.parent = nodeId;
if(relation.childWeb != null){
lookupId = "node-" + relation.childWeb + relation.child;
} else {
lookupId = "node-" + relation.webTag + relation.child;
}
nodeId = crossRelationLookupMap.get(lookupId);
if(nodeId == relation.parent){
throw new Error("Child node id same as parent! " + relation.parent + " " + nodeId + " " + relation.child);
}
relation.child = nodeId;
}
return rVal;
}
/**
* Recursively loads knowledge webs based on the root
* @param root The path to the current root knowledge web
* @return Merged knowledge web
*/
private static KnowledgeWeb recursivelyLoad(Map<String,Integer> crossRelationLookupMap, List<String> foundTags, String startPoint){
KnowledgeWeb rVal = FileUtils.loadObjectFromFile(new File(startPoint), KnowledgeWeb.class);;
if(foundTags.contains(rVal.getTag())){
throw new UnsupportedOperationException("Trying to load two webs with the same tag! " + rVal.getTag());
}
//add nodes to crossrelational lookup map
HashMap<Integer,Node> newNodeMap = new HashMap<Integer,Node>();
for(Node node : rVal.nodes.values()){
String lookupId = "node-" + rVal.getTag() + node.getId();
crossRelationLookupMap.put(lookupId,Node.idIncrementer);
node.id = Node.idIncrementer;
newNodeMap.put(node.id,node);
Node.idIncrementer++;
}
rVal.nodes = newNodeMap;
//read in relations and assign them new IDs
HashMap<Integer,Relation> newRelations = new HashMap<Integer,Relation>();
for(Relation relation : rVal.getRelations()){
relation.webTag = rVal.getTag();
relation.id = Relation.idIncrementer;
newRelations.put(relation.id,relation);
Relation.idIncrementer++;
}
rVal.relations = newRelations;
//parse children
if(rVal.getChildren() != null && rVal.getChildren().size() > 0){
for(String child : rVal.getChildren()){
KnowledgeWeb childWeb = KnowledgeWeb.recursivelyLoad(crossRelationLookupMap, foundTags, child);
KnowledgeWeb.registerChildItems(crossRelationLookupMap, rVal, childWeb);
}
}
return rVal;
}
/**
* Adds the children to the cross relational lookup map
* @param parent The parent web
* @param child The child web
*/
private static void registerChildItems(Map<String,Integer> crossRelationLookupMap, KnowledgeWeb parent, KnowledgeWeb child){
//read in nodes and assign them new IDs
for(Node node : child.getNodes()){
parent.nodes.put(node.getId(),node);
}
//read in relations and assign them new IDs
for(Relation relation : child.getRelations()){
parent.relations.put(relation.getId(),relation);
}
}
/**
* Initializes the linked datastructures between items
*/
@ -124,5 +226,16 @@ public class KnowledgeWeb {
return this.getNode(this.selfId);
}
/**
* Gets the child webs of this web
* @return The list of child webs
*/
public List<String> getChildren(){
return children;
}
public String getTag(){
return tag;
}
}

View File

@ -14,6 +14,11 @@ public class Relation {
*/
int id;
/**
* Tag of the web that contains this relation
*/
transient String webTag;
/**
* The name of the relationship
*/
@ -29,6 +34,11 @@ public class Relation {
*/
int child;
/**
* The web that contains this child
*/
String childWeb;
/**
* Constructor
* @param name The name of the relation
@ -59,6 +69,14 @@ public class Relation {
return Globals.web.getNode(this.child);
}
/**
* Gets the tag for the web the child belongs to (can be null or empty string if the web is the same as the parent)
* @return The tag for the web
*/
public String getChildWeb(){
return this.childWeb;
}
}

View File

@ -33,4 +33,11 @@ public class LoadingTests {
});
}
@Test
public void testNoTag(){
assertThrows(UnsupportedOperationException.class, () -> {
KnowledgeWeb.load("./data/test/webs/web_no_tag.json");
});
}
}

View File

@ -1,4 +1,5 @@
{
"tag" : "root",
"selfId": 2,
"nodes" : {
"0" : {