initial pass at first query parsing
All checks were successful
studiorailgun/trpg/pipeline/head This commit looks good
All checks were successful
studiorailgun/trpg/pipeline/head This commit looks good
This commit is contained in:
parent
3781c73d88
commit
ee5f4eab86
@ -8,8 +8,8 @@ sitting in a tavern by a fireplace
|
|||||||
|
|
||||||
|
|
||||||
Respond to "What color is your hat?"
|
Respond to "What color is your hat?"
|
||||||
- determine sentence function
|
|
||||||
- determine what is being queried for
|
- determine what is being queried for
|
||||||
|
- respond with the correct information
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
31
data/webs/bert.json
Normal file
31
data/webs/bert.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"tag" : "bert",
|
||||||
|
"nodes" : {
|
||||||
|
"0" : {
|
||||||
|
"id" : 0,
|
||||||
|
"name" : "Bert"
|
||||||
|
},
|
||||||
|
"9" : {
|
||||||
|
"id" : 9,
|
||||||
|
"name" : "Bert's Hat"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations" : {
|
||||||
|
"0" : {
|
||||||
|
"id" : 0,
|
||||||
|
"name" : "nameOf",
|
||||||
|
"parent" : 0,
|
||||||
|
"child" : 2,
|
||||||
|
"childWeb" : "root"
|
||||||
|
},
|
||||||
|
"1" : {
|
||||||
|
"id" : 1,
|
||||||
|
"name" : "qualiaOf",
|
||||||
|
"parent" : 1,
|
||||||
|
"parentWeb" : "color",
|
||||||
|
"child" : 9
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children" : [
|
||||||
|
]
|
||||||
|
}
|
||||||
24
data/webs/qualia/qualia.json
Normal file
24
data/webs/qualia/qualia.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"tag" : "qualia",
|
||||||
|
"nodes" : {
|
||||||
|
"0" : {
|
||||||
|
"id" : 0,
|
||||||
|
"name" : "qualia"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations" : {
|
||||||
|
"0" : {
|
||||||
|
"id" : 0,
|
||||||
|
"name" : "instanceOf",
|
||||||
|
"parent" : 0,
|
||||||
|
"child" : 0,
|
||||||
|
"childWeb" : "color"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"anchors" : {
|
||||||
|
"qualia" : 0
|
||||||
|
},
|
||||||
|
"children" : [
|
||||||
|
"./data/webs/qualia/color.json"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,11 +1,6 @@
|
|||||||
{
|
{
|
||||||
"tag" : "root",
|
"tag" : "root",
|
||||||
"selfId": 2,
|
|
||||||
"nodes" : {
|
"nodes" : {
|
||||||
"0" : {
|
|
||||||
"id" : 0,
|
|
||||||
"name" : "Bert"
|
|
||||||
},
|
|
||||||
"1" : {
|
"1" : {
|
||||||
"id" : 1,
|
"id" : 1,
|
||||||
"name" : "Name"
|
"name" : "Name"
|
||||||
@ -37,53 +32,71 @@
|
|||||||
"8" : {
|
"8" : {
|
||||||
"id" : 8,
|
"id" : 8,
|
||||||
"name" : "Hat"
|
"name" : "Hat"
|
||||||
|
},
|
||||||
|
"10" : {
|
||||||
|
"id" : 10,
|
||||||
|
"name" : "concept"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations" : {
|
"relations" : {
|
||||||
"0" : {
|
|
||||||
"id" : 0,
|
|
||||||
"name" : "Name",
|
|
||||||
"parent" : 0,
|
|
||||||
"child" : 2
|
|
||||||
},
|
|
||||||
"1" : {
|
"1" : {
|
||||||
"id" : 1,
|
"id" : 1,
|
||||||
"name" : "InstanceOf",
|
"name" : "instanceOf",
|
||||||
"parent" : 3,
|
"parent" : 3,
|
||||||
"child" : 2
|
"child" : 2
|
||||||
},
|
},
|
||||||
"2" : {
|
"2" : {
|
||||||
"id" : 2,
|
"id" : 2,
|
||||||
"name" : "InstanceOf",
|
"name" : "instanceOf",
|
||||||
"parent" : 1,
|
"parent" : 1,
|
||||||
"child" : 0
|
"child" : 0,
|
||||||
|
"childWeb" : "bert"
|
||||||
},
|
},
|
||||||
"3" : {
|
"3" : {
|
||||||
"id" : 3,
|
"id" : 3,
|
||||||
"name" : "InstanceOf",
|
"name" : "instanceOf",
|
||||||
"parent" : 3,
|
"parent" : 3,
|
||||||
"child" : 4
|
"child" : 4
|
||||||
},
|
},
|
||||||
"4" : {
|
"4" : {
|
||||||
"id" : 4,
|
"id" : 4,
|
||||||
"name" : "ParticipantOf",
|
"name" : "participantOf",
|
||||||
"parent" : 7,
|
"parent" : 7,
|
||||||
"child" : 4
|
"child" : 4
|
||||||
},
|
},
|
||||||
"5" : {
|
"5" : {
|
||||||
"id" : 5,
|
"id" : 5,
|
||||||
"name" : "ParticipantOf",
|
"name" : "participantOf",
|
||||||
"parent" : 7,
|
"parent" : 7,
|
||||||
"child" : 2
|
"child" : 2
|
||||||
},
|
},
|
||||||
"6" : {
|
"6" : {
|
||||||
"id" : 6,
|
"id" : 6,
|
||||||
"name" : "Possession",
|
"name" : "possessionOf",
|
||||||
"parent" : 2,
|
"parent" : 2,
|
||||||
|
"child" : 9,
|
||||||
|
"childWeb" : "bert"
|
||||||
|
},
|
||||||
|
"7" : {
|
||||||
|
"id" : 7,
|
||||||
|
"name" : "instanceOf",
|
||||||
|
"parent" : 8,
|
||||||
|
"child" : 9,
|
||||||
|
"childWeb" : "bert"
|
||||||
|
},
|
||||||
|
"8" : {
|
||||||
|
"id" : 8,
|
||||||
|
"name" : "instanceOf",
|
||||||
|
"parent" : 10,
|
||||||
"child" : 8
|
"child" : 8
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"anchors" : {
|
||||||
|
"self" : 2,
|
||||||
|
"concept" : 10
|
||||||
|
},
|
||||||
"children" : [
|
"children" : [
|
||||||
"./data/webs/color.json"
|
"./data/webs/qualia/qualia.json",
|
||||||
|
"./data/webs/bert.json"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"tag" : "root",
|
"tag" : "root",
|
||||||
"selfId": 2,
|
|
||||||
"children" : [
|
"children" : [
|
||||||
"./data/webs/root.json"
|
"./data/webs/root.json"
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package org.studiorailgun.conversation.evaluators.goal;
|
package org.studiorailgun.conversation.evaluators.goal;
|
||||||
|
|
||||||
|
import org.studiorailgun.conversation.evaluators.query.QueryData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data about the AI's goal in the conversation
|
* Data about the AI's goal in the conversation
|
||||||
*/
|
*/
|
||||||
@ -21,6 +23,18 @@ public class GoalData {
|
|||||||
*/
|
*/
|
||||||
ConversationGoal goal;
|
ConversationGoal goal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The query data
|
||||||
|
*/
|
||||||
|
QueryData queryData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The query data for the conversation
|
||||||
|
*/
|
||||||
|
public GoalData(){
|
||||||
|
this.queryData = new QueryData();
|
||||||
|
}
|
||||||
|
|
||||||
public ConversationGoal getGoal() {
|
public ConversationGoal getGoal() {
|
||||||
return goal;
|
return goal;
|
||||||
}
|
}
|
||||||
@ -29,6 +43,8 @@ public class GoalData {
|
|||||||
this.goal = goal;
|
this.goal = goal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryData getQueryData() {
|
||||||
|
return queryData;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,15 @@
|
|||||||
package org.studiorailgun.conversation.evaluators.query;
|
package org.studiorailgun.conversation.evaluators.query;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.studiorailgun.Globals;
|
||||||
|
import org.studiorailgun.conversation.tracking.Conversation;
|
||||||
|
import org.studiorailgun.conversation.tracking.Quote;
|
||||||
|
import org.studiorailgun.knowledge.Node;
|
||||||
|
import org.studiorailgun.knowledge.query.InstanceQuery;
|
||||||
|
import org.studiorailgun.knowledge.query.QualiaQuery;
|
||||||
|
import org.studiorailgun.knowledge.query.filter.PossessionQueryFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interrogatives available
|
* Interrogatives available
|
||||||
*/
|
*/
|
||||||
@ -25,4 +35,60 @@ public class Interrogative {
|
|||||||
WHEN,
|
WHEN,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates a query of "which"
|
||||||
|
* @param conversation The conversation
|
||||||
|
* @param quote The quote
|
||||||
|
* @param interrogative The interrogative noun
|
||||||
|
* @param items The items noun
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public static void evalWhichQuery(Conversation conversation, Quote quote, NounStack interrogative, NounStack items){
|
||||||
|
if(QualiaQuery.isQualiaClarificationQuery(interrogative)){
|
||||||
|
Node finalQualifier = InstanceQuery.getConcept(items.indexedWord.originalText());
|
||||||
|
|
||||||
|
if(items.possessive != null){
|
||||||
|
List<Node> qualifierInstances = InstanceQuery.getInstances(finalQualifier);
|
||||||
|
finalQualifier = PossessionQueryFilter.withPossessor(qualifierInstances, Globals.web.getAnchors().getSelfNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Node> qualiaOfInstance = QualiaQuery.getQualiaOfInstance(finalQualifier);
|
||||||
|
|
||||||
|
Node qualiaType = QualiaQuery.getRequestedQualiaType(interrogative);
|
||||||
|
|
||||||
|
conversation.addQuote(quote);
|
||||||
|
conversation.getGoalData().getQueryData().getRecentQueries().add(quote);
|
||||||
|
} else {
|
||||||
|
throw new Error("Unknown query type!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates a query of "what"
|
||||||
|
* @param conversation The conversation
|
||||||
|
* @param quote The quote
|
||||||
|
* @param interrogative The interrogative noun
|
||||||
|
* @param items The items noun
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public static void evalWhatQuery(Conversation conversation, Quote quote, NounStack interrogative, NounStack items){
|
||||||
|
if(QualiaQuery.isQualiaClarificationQuery(interrogative)){
|
||||||
|
Node finalQualifier = InstanceQuery.getConcept(items.indexedWord.originalText());
|
||||||
|
|
||||||
|
if(items.possessive != null){
|
||||||
|
List<Node> qualifierInstances = InstanceQuery.getInstances(finalQualifier);
|
||||||
|
finalQualifier = PossessionQueryFilter.withPossessor(qualifierInstances, Globals.web.getAnchors().getSelfNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Node> qualiaOfInstance = QualiaQuery.getQualiaOfInstance(finalQualifier);
|
||||||
|
|
||||||
|
Node qualiaType = QualiaQuery.getRequestedQualiaType(interrogative);
|
||||||
|
|
||||||
|
conversation.addQuote(quote);
|
||||||
|
conversation.getGoalData().getQueryData().getRecentQueries().add(quote);
|
||||||
|
} else {
|
||||||
|
throw new Error("Unknown query type!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -77,4 +77,18 @@ public class NounStack {
|
|||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getInterrogative() {
|
||||||
|
return interrogative;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPossessive() {
|
||||||
|
return possessive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexedWord getIndexedWord() {
|
||||||
|
return indexedWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
package org.studiorailgun.conversation.evaluators.query;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.studiorailgun.conversation.tracking.Quote;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data about recent queries in the conversation
|
||||||
|
*/
|
||||||
|
public class QueryData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The recent queries
|
||||||
|
*/
|
||||||
|
List<Quote> recentQueries = new LinkedList<Quote>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the recent queries in the conversation
|
||||||
|
* @return The recent queries
|
||||||
|
*/
|
||||||
|
public List<Quote> getRecentQueries(){
|
||||||
|
return recentQueries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the quote to the recent queries
|
||||||
|
* @param quote The quote
|
||||||
|
*/
|
||||||
|
public void addQuery(Quote quote){
|
||||||
|
recentQueries.add(quote);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,12 +1,17 @@
|
|||||||
package org.studiorailgun.conversation.evaluators.query;
|
package org.studiorailgun.conversation.evaluators.query;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.studiorailgun.Globals;
|
||||||
import org.studiorailgun.conversation.parser.NLPParser;
|
import org.studiorailgun.conversation.parser.NLPParser;
|
||||||
import org.studiorailgun.conversation.parser.PennTreebankTagSet;
|
import org.studiorailgun.conversation.parser.PennTreebankTagSet;
|
||||||
import org.studiorailgun.conversation.tracking.Conversation;
|
import org.studiorailgun.conversation.tracking.Conversation;
|
||||||
import org.studiorailgun.conversation.tracking.Quote;
|
import org.studiorailgun.conversation.tracking.Quote;
|
||||||
|
import org.studiorailgun.knowledge.Node;
|
||||||
|
import org.studiorailgun.knowledge.query.InstanceQuery;
|
||||||
|
import org.studiorailgun.knowledge.query.filter.PossessionQueryFilter;
|
||||||
|
|
||||||
import edu.stanford.nlp.ling.IndexedWord;
|
import edu.stanford.nlp.ling.IndexedWord;
|
||||||
import edu.stanford.nlp.semgraph.SemanticGraph;
|
import edu.stanford.nlp.semgraph.SemanticGraph;
|
||||||
@ -57,13 +62,38 @@ public class QueryEval {
|
|||||||
//get the two things we're comparing
|
//get the two things we're comparing
|
||||||
SemanticGraph graph = quote.getGraph();
|
SemanticGraph graph = quote.getGraph();
|
||||||
IndexedWord root = graph.getFirstRoot();
|
IndexedWord root = graph.getFirstRoot();
|
||||||
Set<IndexedWord> dependents = graph.descendants(root);
|
|
||||||
Set<IndexedWord> children = graph.getChildren(root);
|
Set<IndexedWord> children = graph.getChildren(root);
|
||||||
Iterator<IndexedWord> iterator = children.iterator();
|
Iterator<IndexedWord> iterator = children.iterator();
|
||||||
IndexedWord firstItem = iterator.next();
|
IndexedWord firstItem = iterator.next();
|
||||||
IndexedWord secondItem = iterator.next();
|
IndexedWord secondItem = iterator.next();
|
||||||
NounStack firstNoun = NounStack.parse(graph, firstItem);
|
NounStack firstNoun = NounStack.parse(graph, firstItem);
|
||||||
NounStack secondNoun = NounStack.parse(graph, secondItem);
|
NounStack secondNoun = NounStack.parse(graph, secondItem);
|
||||||
|
|
||||||
|
//interrogative error checking
|
||||||
|
if(firstNoun.interrogative != null && secondNoun.interrogative != null){
|
||||||
|
String message = "Comparing two interrogatives!";
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
//handle interrogative solving
|
||||||
|
if(firstNoun.interrogative != null || secondNoun.interrogative != null){
|
||||||
|
NounStack interrogativeStack = firstNoun.interrogative != null ? firstNoun : secondNoun;
|
||||||
|
NounStack qualifierStack = firstNoun.interrogative != null ? secondNoun : firstNoun;
|
||||||
|
|
||||||
|
switch(interrogativeStack.interrogative.toLowerCase()){
|
||||||
|
case "which": {
|
||||||
|
Interrogative.evalWhichQuery(conversation, quote, interrogativeStack, qualifierStack);
|
||||||
|
} break;
|
||||||
|
case "what": {
|
||||||
|
Interrogative.evalWhatQuery(conversation, quote, interrogativeStack, qualifierStack);
|
||||||
|
} break;
|
||||||
|
default : {
|
||||||
|
throw new Error("Unhandled interrogative type! " + interrogativeStack.interrogative.toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Turn this into a query");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
package org.studiorailgun.conversation.tracking;
|
package org.studiorailgun.conversation.tracking;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.studiorailgun.conversation.evaluators.goal.GoalData;
|
import org.studiorailgun.conversation.evaluators.goal.GoalData;
|
||||||
import org.studiorailgun.conversation.evaluators.greet.GreetingData;
|
import org.studiorailgun.conversation.evaluators.greet.GreetingData;
|
||||||
|
import org.studiorailgun.conversation.evaluators.query.QueryData;
|
||||||
import org.studiorailgun.knowledge.KnowledgeWeb;
|
import org.studiorailgun.knowledge.KnowledgeWeb;
|
||||||
import org.studiorailgun.knowledge.Node;
|
import org.studiorailgun.knowledge.Node;
|
||||||
|
|
||||||
@ -35,6 +39,11 @@ public class Conversation {
|
|||||||
*/
|
*/
|
||||||
GoalData goalData;
|
GoalData goalData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The history of the conversation
|
||||||
|
*/
|
||||||
|
List<Quote> history;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the current conversation's data from the knowledge web
|
* Parses the current conversation's data from the knowledge web
|
||||||
* @param web The web
|
* @param web The web
|
||||||
@ -44,7 +53,7 @@ public class Conversation {
|
|||||||
Node node = web.getNode(7);
|
Node node = web.getNode(7);
|
||||||
|
|
||||||
//find the self
|
//find the self
|
||||||
ConvParticipant self = new ConvParticipant(web.getSelf());
|
ConvParticipant self = new ConvParticipant(web.getAnchors().getSelfNode());
|
||||||
|
|
||||||
//find the other participant
|
//find the other participant
|
||||||
ConvParticipant other = new ConvParticipant(web.getNode(4));
|
ConvParticipant other = new ConvParticipant(web.getNode(4));
|
||||||
@ -65,6 +74,7 @@ public class Conversation {
|
|||||||
this.other = other;
|
this.other = other;
|
||||||
this.greetingData = new GreetingData();
|
this.greetingData = new GreetingData();
|
||||||
this.goalData = new GoalData();
|
this.goalData = new GoalData();
|
||||||
|
this.history = new LinkedList<Quote>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -99,6 +109,22 @@ public class Conversation {
|
|||||||
this.goalData = goalData;
|
this.goalData = goalData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the history of the conversation
|
||||||
|
* @return The history of the conversation
|
||||||
|
*/
|
||||||
|
public List<Quote> getHistory(){
|
||||||
|
return history;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a quote to the conversation
|
||||||
|
* @param quote The quote
|
||||||
|
*/
|
||||||
|
public void addQuote(Quote quote){
|
||||||
|
this.history.add(quote);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import java.util.Map.Entry;
|
|||||||
|
|
||||||
import org.studiorailgun.FileUtils;
|
import org.studiorailgun.FileUtils;
|
||||||
import org.studiorailgun.Globals;
|
import org.studiorailgun.Globals;
|
||||||
|
import org.studiorailgun.knowledge.anchor.AnchorNodes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A knowledge web
|
* A knowledge web
|
||||||
@ -38,9 +39,15 @@ public class KnowledgeWeb {
|
|||||||
transient Map<String,List<Integer>> typeRelationLookup;
|
transient Map<String,List<Integer>> typeRelationLookup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The node that represents the current ai
|
* Map of node -> relations where that node is the parent
|
||||||
*/
|
*/
|
||||||
int selfId;
|
transient Map<Node,List<Relation>> parentRelations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The anchor nodes
|
||||||
|
*/
|
||||||
|
AnchorNodes anchors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Child webs
|
* Child webs
|
||||||
*/
|
*/
|
||||||
@ -53,6 +60,7 @@ public class KnowledgeWeb {
|
|||||||
this.nodes = new HashMap<Integer,Node>();
|
this.nodes = new HashMap<Integer,Node>();
|
||||||
this.relations = new HashMap<Integer,Relation>();
|
this.relations = new HashMap<Integer,Relation>();
|
||||||
this.typeRelationLookup = new HashMap<String,List<Integer>>();
|
this.typeRelationLookup = new HashMap<String,List<Integer>>();
|
||||||
|
this.parentRelations = new HashMap<Node,List<Relation>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,7 +78,12 @@ public class KnowledgeWeb {
|
|||||||
Globals.web = rVal;
|
Globals.web = rVal;
|
||||||
//fix the IDs referenced by the links
|
//fix the IDs referenced by the links
|
||||||
for(Relation relation : rVal.relations.values()){
|
for(Relation relation : rVal.relations.values()){
|
||||||
String lookupId = "node-" + relation.webTag + relation.parent;
|
String lookupId = "";
|
||||||
|
if(relation.parentWeb != null){
|
||||||
|
lookupId = "node-" + relation.parentWeb + relation.parent;
|
||||||
|
} else {
|
||||||
|
lookupId = "node-" + relation.webTag + relation.parent;
|
||||||
|
}
|
||||||
int nodeId = crossRelationLookupMap.get(lookupId);
|
int nodeId = crossRelationLookupMap.get(lookupId);
|
||||||
relation.parent = nodeId;
|
relation.parent = nodeId;
|
||||||
|
|
||||||
@ -85,6 +98,20 @@ public class KnowledgeWeb {
|
|||||||
}
|
}
|
||||||
relation.child = nodeId;
|
relation.child = nodeId;
|
||||||
}
|
}
|
||||||
|
//populate lookup acceleration structures
|
||||||
|
for(Relation relation : rVal.relations.values()){
|
||||||
|
Node parent = relation.getParent();
|
||||||
|
if(rVal.parentRelations.containsKey(parent)){
|
||||||
|
List<Relation> relations = rVal.parentRelations.get(parent);
|
||||||
|
relations.add(relation);
|
||||||
|
} else {
|
||||||
|
List<Relation> relations = new LinkedList<Relation>();
|
||||||
|
relations.add(relation);
|
||||||
|
rVal.parentRelations.put(parent,relations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//error check that all anchors are defined
|
||||||
|
Globals.web.getAnchors().errorCheck();
|
||||||
return rVal;
|
return rVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,6 +144,29 @@ public class KnowledgeWeb {
|
|||||||
Relation.idIncrementer++;
|
Relation.idIncrementer++;
|
||||||
}
|
}
|
||||||
rVal.relations = newRelations;
|
rVal.relations = newRelations;
|
||||||
|
//make sure anchors object exists and any values are valid
|
||||||
|
if(rVal.anchors == null){
|
||||||
|
rVal.anchors = new AnchorNodes();
|
||||||
|
} else {
|
||||||
|
if(rVal.anchors.getSelf() != null){
|
||||||
|
int oldId = rVal.anchors.getSelf();
|
||||||
|
String lookupId = "node-" + rVal.getTag() + oldId;
|
||||||
|
int newNodeId = crossRelationLookupMap.get(lookupId);
|
||||||
|
rVal.anchors.setSelf(newNodeId);
|
||||||
|
}
|
||||||
|
if(rVal.anchors.getConcept() != null){
|
||||||
|
int oldId = rVal.anchors.getConcept();
|
||||||
|
String lookupId = "node-" + rVal.getTag() + oldId;
|
||||||
|
int newNodeId = crossRelationLookupMap.get(lookupId);
|
||||||
|
rVal.anchors.setConcept(newNodeId);
|
||||||
|
}
|
||||||
|
if(rVal.anchors.getQualia() != null){
|
||||||
|
int oldId = rVal.anchors.getQualia();
|
||||||
|
String lookupId = "node-" + rVal.getTag() + oldId;
|
||||||
|
int newNodeId = crossRelationLookupMap.get(lookupId);
|
||||||
|
rVal.anchors.setQualia(newNodeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
//parse children
|
//parse children
|
||||||
if(rVal.getChildren() != null && rVal.getChildren().size() > 0){
|
if(rVal.getChildren() != null && rVal.getChildren().size() > 0){
|
||||||
for(String child : rVal.getChildren()){
|
for(String child : rVal.getChildren()){
|
||||||
@ -142,6 +192,9 @@ public class KnowledgeWeb {
|
|||||||
for(Relation relation : child.getRelations()){
|
for(Relation relation : child.getRelations()){
|
||||||
parent.relations.put(relation.getId(),relation);
|
parent.relations.put(relation.getId(),relation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//hoist anchors from children
|
||||||
|
AnchorNodes.copyToParent(parent.anchors, child.anchors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -217,14 +270,6 @@ public class KnowledgeWeb {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the node that represents the ai
|
|
||||||
* @return The node
|
|
||||||
*/
|
|
||||||
public Node getSelf(){
|
|
||||||
return this.getNode(this.selfId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the child webs of this web
|
* Gets the child webs of this web
|
||||||
@ -238,4 +283,25 @@ public class KnowledgeWeb {
|
|||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the relations where the provided node is the parent of the relationship
|
||||||
|
* @param node The node
|
||||||
|
* @return The list of relations
|
||||||
|
*/
|
||||||
|
public List<Relation> getRelationsOfParentNode(Node node){
|
||||||
|
if(this.parentRelations.containsKey(node)){
|
||||||
|
return this.parentRelations.get(node);
|
||||||
|
} else {
|
||||||
|
return new LinkedList<Relation>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the anchor nodes for the web
|
||||||
|
* @return The anchor nodes
|
||||||
|
*/
|
||||||
|
public AnchorNodes getAnchors(){
|
||||||
|
return anchors;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,11 @@ public class Relation {
|
|||||||
*/
|
*/
|
||||||
int parent;
|
int parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The web that contains the parent node
|
||||||
|
*/
|
||||||
|
String parentWeb;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The child of the relationship
|
* The child of the relationship
|
||||||
*/
|
*/
|
||||||
@ -77,6 +82,14 @@ public class Relation {
|
|||||||
return this.childWeb;
|
return this.childWeb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the tag for the web the parent 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 getParentWeb(){
|
||||||
|
return this.parentWeb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,136 @@
|
|||||||
|
package org.studiorailgun.knowledge.anchor;
|
||||||
|
|
||||||
|
import org.studiorailgun.Globals;
|
||||||
|
import org.studiorailgun.knowledge.Node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Anchor nodes for the rest of the web
|
||||||
|
*/
|
||||||
|
public class AnchorNodes {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The node that represents the self
|
||||||
|
*/
|
||||||
|
Integer self;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The node that represents the idea of a concept
|
||||||
|
*/
|
||||||
|
Integer concept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The concept of a qualia
|
||||||
|
*/
|
||||||
|
Integer qualia;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the self
|
||||||
|
* @return The self node
|
||||||
|
*/
|
||||||
|
public Node getSelfNode() {
|
||||||
|
if(self == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Globals.web.getNode(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the self node ID
|
||||||
|
* @param id The self node's ID
|
||||||
|
*/
|
||||||
|
public void setSelf(int id) {
|
||||||
|
this.self = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id for the self node
|
||||||
|
* @return The id
|
||||||
|
*/
|
||||||
|
public Integer getSelf(){
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the idea of a concept
|
||||||
|
* @return The idea of a concept
|
||||||
|
*/
|
||||||
|
public Node getConceptNode() {
|
||||||
|
if(concept == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Globals.web.getNode(concept);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the concept node
|
||||||
|
* @param id The concept node
|
||||||
|
*/
|
||||||
|
public void setConcept(int id){
|
||||||
|
this.concept = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id for the concept node
|
||||||
|
* @return The id for the concept node
|
||||||
|
*/
|
||||||
|
public Integer getConcept(){
|
||||||
|
return concept;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the idea of a qualia
|
||||||
|
* @return The idea of a qualia
|
||||||
|
*/
|
||||||
|
public Node getQualiaNode() {
|
||||||
|
if(qualia == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Globals.web.getNode(qualia);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the qualia node
|
||||||
|
* @param id The qualia node
|
||||||
|
*/
|
||||||
|
public void setQualia(int id){
|
||||||
|
this.qualia = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id for the qualia node
|
||||||
|
* @return The id for the qualia node
|
||||||
|
*/
|
||||||
|
public Integer getQualia(){
|
||||||
|
return qualia;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies anchor nodes from the child to the parent
|
||||||
|
* @param parentAnchors The parent anchors
|
||||||
|
* @param childAnchors The child anchors
|
||||||
|
*/
|
||||||
|
public static void copyToParent(AnchorNodes parentAnchors, AnchorNodes childAnchors){
|
||||||
|
if(childAnchors.getConcept() != null){
|
||||||
|
parentAnchors.setConcept(childAnchors.getConcept());
|
||||||
|
}
|
||||||
|
if(childAnchors.getSelf() != null){
|
||||||
|
parentAnchors.setSelf(childAnchors.getSelf());
|
||||||
|
}
|
||||||
|
if(childAnchors.getQualia() != null){
|
||||||
|
parentAnchors.setQualia(childAnchors.getQualia());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for errors in the anchor definitions
|
||||||
|
*/
|
||||||
|
public void errorCheck(){
|
||||||
|
if(self == null){
|
||||||
|
throw new Error("Self undefined!");
|
||||||
|
}
|
||||||
|
if(concept == null){
|
||||||
|
throw new Error("Concept undefined!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package org.studiorailgun.knowledge.query;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.studiorailgun.Globals;
|
||||||
|
import org.studiorailgun.knowledge.KnowledgeWeb;
|
||||||
|
import org.studiorailgun.knowledge.Node;
|
||||||
|
import org.studiorailgun.knowledge.Relation;
|
||||||
|
import org.studiorailgun.knowledge.query.filter.NameQueryFilter;
|
||||||
|
import org.studiorailgun.knowledge.types.RelationTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries for dealing with instances of nodes
|
||||||
|
*/
|
||||||
|
public class InstanceQuery {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the instances of a node
|
||||||
|
* @param web The web
|
||||||
|
* @param parent The parent node
|
||||||
|
* @return The list of instances of that node
|
||||||
|
*/
|
||||||
|
public static List<Node> getInstances(Node parent){
|
||||||
|
List<Relation> relations = Globals.web.getRelationsOfParentNode(parent);
|
||||||
|
return relations.stream().filter(relation -> relation.getName().equals(RelationTypes.INSTANCE_OF)).map(relation -> relation.getChild()).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a concept by its name
|
||||||
|
* @param web The web
|
||||||
|
* @param conceptName The name of the concept
|
||||||
|
* @return The concept
|
||||||
|
*/
|
||||||
|
public static Node getConcept(String conceptName){
|
||||||
|
Node concept = Globals.web.getAnchors().getConceptNode();
|
||||||
|
List<Node> concepts = InstanceQuery.getInstances(concept);
|
||||||
|
return NameQueryFilter.withNodeName(concepts, conceptName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package org.studiorailgun.knowledge.query;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.studiorailgun.Globals;
|
||||||
|
import org.studiorailgun.knowledge.Node;
|
||||||
|
import org.studiorailgun.knowledge.types.RelationTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries based around possession
|
||||||
|
*/
|
||||||
|
public class PossessionQuery {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all the child nodes that this node possesses
|
||||||
|
* @param parent The parent node
|
||||||
|
* @return The child nodes that are possessed by this node
|
||||||
|
*/
|
||||||
|
public static List<Node> getPossessions(Node parent){
|
||||||
|
return Globals.web.getRelationsOfParentNode(parent).stream().filter(relation -> relation.getName().equals(RelationTypes.POSSESSION_OF)).map(relation -> relation.getChild()).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package org.studiorailgun.knowledge.query;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.studiorailgun.Globals;
|
||||||
|
import org.studiorailgun.conversation.evaluators.query.NounStack;
|
||||||
|
import org.studiorailgun.knowledge.Node;
|
||||||
|
import org.studiorailgun.knowledge.query.filter.NameQueryFilter;
|
||||||
|
import org.studiorailgun.knowledge.types.RelationTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a qualia query
|
||||||
|
*/
|
||||||
|
public class QualiaQuery {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this noun stack is querying for a qualia
|
||||||
|
* @param interrogativeStack The interrogative noun stack
|
||||||
|
* @return true if it is a qualia query, false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean isQualiaClarificationQuery(NounStack interrogativeStack){
|
||||||
|
String originalWord = interrogativeStack.getIndexedWord().originalText();
|
||||||
|
List<Node> nodes = InstanceQuery.getInstances(Globals.web.getAnchors().getQualiaNode());
|
||||||
|
Node rVal = NameQueryFilter.withNodeName(nodes, originalWord);
|
||||||
|
return rVal != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the type of qualia requested by the interrogative stack
|
||||||
|
* @param interrogativeStack The noun stack containing the qualia type
|
||||||
|
* @return The qualia type
|
||||||
|
*/
|
||||||
|
public static Node getRequestedQualiaType(NounStack interrogativeStack){
|
||||||
|
String originalWord = interrogativeStack.getIndexedWord().originalText();
|
||||||
|
List<Node> nodes = InstanceQuery.getInstances(Globals.web.getAnchors().getQualiaNode());
|
||||||
|
return NameQueryFilter.withNodeName(nodes, originalWord);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all the qualia of an instance
|
||||||
|
* @param inst The instance
|
||||||
|
* @return The qualia
|
||||||
|
*/
|
||||||
|
public static List<Node> getQualiaOfInstance(Node inst){
|
||||||
|
return Globals.web.getRelationsOfParentNode(inst).stream().filter(relation -> relation.getName().equals(RelationTypes.QUALIA_OF)).map(relation -> relation.getChild()).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package org.studiorailgun.knowledge.query.filter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.studiorailgun.knowledge.Node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Node query filters based around names
|
||||||
|
*/
|
||||||
|
public class NameQueryFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters a set of nodes to a singleton based on a name
|
||||||
|
*/
|
||||||
|
public static Node withNodeName(List<Node> nodes, String name){
|
||||||
|
List<Node> filtered = nodes.stream().filter(node -> !node.getName().equals(name)).collect(Collectors.toList());
|
||||||
|
if(filtered.size() != 1){
|
||||||
|
throw new UnsupportedOperationException("TODO: handle ambiguous case");
|
||||||
|
}
|
||||||
|
return filtered.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package org.studiorailgun.knowledge.query.filter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.studiorailgun.knowledge.Node;
|
||||||
|
import org.studiorailgun.knowledge.query.PossessionQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query filters based on possession relationships
|
||||||
|
*/
|
||||||
|
public class PossessionQueryFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters a set of nodes to a singleton based on a name
|
||||||
|
*/
|
||||||
|
public static Node withPossessor(List<Node> nodes, Node possessor){
|
||||||
|
List<Node> possessions = PossessionQuery.getPossessions(possessor);
|
||||||
|
List<Node> filtered = nodes.stream().filter(node -> {
|
||||||
|
return possessions.contains(node);
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
if(filtered.size() != 1){
|
||||||
|
throw new UnsupportedOperationException("TODO: handle ambiguous case");
|
||||||
|
}
|
||||||
|
return filtered.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package org.studiorailgun.knowledge.types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All relation types
|
||||||
|
*/
|
||||||
|
public class RelationTypes {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An instance relationship
|
||||||
|
*/
|
||||||
|
public static final String INSTANCE_OF = "instanceOf";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A possession relationship
|
||||||
|
*/
|
||||||
|
public static final String POSSESSION_OF = "possessionOf";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A qualia of instance relationship
|
||||||
|
*/
|
||||||
|
public static final String QUALIA_OF = "qualiaOf";
|
||||||
|
|
||||||
|
}
|
||||||
@ -12,8 +12,8 @@ public class ConvLoadingTests {
|
|||||||
@Test
|
@Test
|
||||||
public void testLoadConversation(){
|
public void testLoadConversation(){
|
||||||
Globals.init("./data/webs/test/web.json");
|
Globals.init("./data/webs/test/web.json");
|
||||||
assertEquals(Globals.web.getSelf(), Globals.conversation.getSelf().getData());
|
assertEquals(Globals.web.getAnchors().getSelfNode(), Globals.conversation.getSelf().getData());
|
||||||
assertNotEquals(Globals.web.getSelf(), Globals.conversation.getOther().getData());
|
assertNotEquals(Globals.web.getAnchors().getSelfNode(), Globals.conversation.getOther().getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user