package edu.stanford.nlp.sempre.tables.features; import java.util.*; import java.util.concurrent.ExecutionException; import com.google.common.cache.*; import edu.stanford.nlp.sempre.*; import edu.stanford.nlp.sempre.FuzzyMatchFn.FuzzyMatchFnMode; import edu.stanford.nlp.sempre.tables.TableKnowledgeGraph; import fig.basic.*; /** * Represents a phrase in the utterance. * * Also contains additional information such as POS and NER tags. * * @author ppasupat */ public class PhraseInfo { public static class Options { @Option(gloss = "Maximum number of tokens in a phrase") public int maxPhraseLength = 3; @Option(gloss = "Fuzzy match predicates") public boolean computeFuzzyMatchPredicates = false; } public static Options opts = new Options(); public final int start, end, endOffset; public final String text; public final String lemmaText; public final List<String> tokens; public final List<String> lemmaTokens; public final List<String> posTags; public final List<String> nerTags; public final String normalizedNerSpan; public final String canonicalPosSeq; public final List<String> fuzzyMatchedPredicates; public PhraseInfo(Example ex, int start, int end) { this.start = start; this.end = end; LanguageInfo languageInfo = ex.languageInfo; this.endOffset = end - languageInfo.numTokens(); tokens = languageInfo.tokens.subList(start, end); lemmaTokens = languageInfo.tokens.subList(start, end); posTags = languageInfo.posTags.subList(start, end); nerTags = languageInfo.nerTags.subList(start, end); if (nerTags.get(0) == null) normalizedNerSpan = null; else normalizedNerSpan = languageInfo.getNormalizedNerSpan(nerTags.get(0), start, end); text = languageInfo.phrase(start, end).toLowerCase(); lemmaText = languageInfo.lemmaPhrase(start, end).toLowerCase(); canonicalPosSeq = languageInfo.canonicalPosSeq(start, end); fuzzyMatchedPredicates = opts.computeFuzzyMatchPredicates ? getFuzzyMatchedPredicates(ex.context) : null; } private List<String> getFuzzyMatchedPredicates(ContextValue context) { if (context == null || context.graph == null || !(context.graph instanceof TableKnowledgeGraph)) return null; TableKnowledgeGraph graph = (TableKnowledgeGraph) context.graph; List<String> matchedPredicates = new ArrayList<>(); // Assume everything is ValueFormula with NameValue inside List<Formula> formulas = new ArrayList<>(); formulas.addAll(graph.getFuzzyMatchedFormulas(text, FuzzyMatchFnMode.ENTITY)); formulas.addAll(graph.getFuzzyMatchedFormulas(text, FuzzyMatchFnMode.BINARY)); for (Formula formula : formulas) { if (formula instanceof ValueFormula) { Value value = ((ValueFormula<?>) formula).value; if (value instanceof NameValue) { matchedPredicates.add(((NameValue) value).id); } } } return matchedPredicates; } @Override public String toString() { return "\"" + text + "\""; } // Caching private static final LoadingCache<Example, List<PhraseInfo>> cache = CacheBuilder.newBuilder() .maximumSize(20) .build( new CacheLoader<Example, List<PhraseInfo>>() { @Override public List<PhraseInfo> load(Example ex) throws Exception { List<PhraseInfo> phraseInfos = new ArrayList<>(); List<String> tokens = ex.languageInfo.tokens; for (int s = 1; s <= opts.maxPhraseLength; s++) { for (int i = 0; i <= tokens.size() - s; i++) { phraseInfos.add(new PhraseInfo(ex, i, i + s)); } } return phraseInfos; } }); public static List<PhraseInfo> getPhraseInfos(Example ex) { try { return cache.get(ex); } catch (ExecutionException e) { throw new RuntimeException(e.getCause()); } } }