lang-model/naive-nlu/tree_nlu/knowledge_evaluation.py

294 lines
8.9 KiB
Python
Raw Normal View History

import logging
2017-05-23 17:04:10 +00:00
from .modifiable_property import (
ModifiableProperty,
ModifiablePropertyWithAst,
is_modifiable_property,
)
def resolve(knowledge_base, elements, value):
if isinstance(value, int):
return elements[value]
2017-05-11 18:36:49 +00:00
elif isinstance(value, tuple) or isinstance(value, list):
print("V:", value, elements)
return integrate_information(knowledge_base, {
"elements": elements,
"parsed": value,
})
return value
# TODO: improve typing
def infer_type(result):
if isinstance(result, bool):
return "bool"
elif isinstance(result, int):
return "int"
else:
raise Exception("Unknown type for value: {}".format(result))
def get_subquery_type(knowledge_base, atom):
subquery_result = integrate_information(knowledge_base,
{
"parsed": atom,
"elements": [],
})
assert (subquery_result is not None)
result = subquery_result.getter()
result_type = infer_type(result)
return result_type
def property_for_value(knowledge_base, value):
if value in knowledge_base:
# Annotate the property as property
2017-05-23 21:29:34 +00:00
groups = knowledge_base[value].get('groups', {'property'})
groups.add('property')
knowledge_base[value]['groups'] = groups
# And find the property "name"
if 'as_property' in knowledge_base[value]:
return knowledge_base[value]['as_property']
2017-05-23 21:29:34 +00:00
return knowledge_base[value].get('groups', {'property'})
else:
# Consider that any property is... a property
knowledge_base[value] = {'groups': {'property'}}
return {'property'}
def modifiable_property_from_property(prop, path, value):
def getter():
nonlocal prop, path, value
if isinstance(path, set):
# If the property is from a set, it's true if any possible
# path has a element as true
return any(map(lambda possible_path: ((possible_path in prop)
and
(prop[possible_path] == value)),
path))
else:
return (path in prop) and prop[path] == value
def setter():
nonlocal prop, path, value
if isinstance(path, set):
for possible_path in path:
prop[possible_path] = value
else:
prop[path] = value
return ModifiableProperty(
getter=getter,
setter=setter,
)
def exists_property_with_value(knowledge_base, elements, subj, value):
subj = resolve(knowledge_base, elements, subj)
value = resolve(knowledge_base, elements, value)
if subj not in knowledge_base:
knowledge_base[subj] = {}
return modifiable_property_from_property(
prop=knowledge_base[subj],
path=property_for_value(knowledge_base, value),
value=value
)
def modifiable_element_for_existance_in_set(container, set_name, element):
print("-----({} {} {})".format(container, set_name, element))
import traceback
# traceback.print_stack()
def getter():
nonlocal container, set_name, element
print(" get({} {} {})".format(container, set_name, element))
return (set_name in container) and (element in container[set_name])
def setter():
print(" add({} {} {})".format(container, set_name, element))
nonlocal container, set_name, element
return container[set_name].add(element)
return ModifiableProperty(
getter=getter,
setter=setter,
)
2017-05-24 20:05:46 +00:00
def modifiable_element_for_existance_in_group(container, element, backlink, set_name='groups'):
def getter():
nonlocal container, element, backlink, set_name
return (set_name in container) and (element in container[set_name])
def setter():
nonlocal container, set_name, element
backlink['groups'].add(set_name)
return container[set_name].add(element)
return ModifiableProperty(
getter=getter,
setter=setter,
)
def pertenence_to_group(knowledge_base, elements, subj, group):
subj = resolve(knowledge_base, elements, subj)
group = resolve(knowledge_base, elements, group)
if subj not in knowledge_base:
knowledge_base[subj] = {'groups': set()}
if "groups" not in knowledge_base[subj]:
knowledge_base[subj]["groups"] = set()
if group not in knowledge_base:
knowledge_base[group] = {'groups': set()}
if "groups" not in knowledge_base[group]:
knowledge_base[group]["groups"] = set()
return modifiable_element_for_existance_in_group(
container=knowledge_base[subj],
element=group,
backlink=knowledge_base[group],
)
def has_capacity(knowledge_base, elements, subj, capacity):
subj = resolve(knowledge_base, elements, subj)
capacity = resolve(knowledge_base, elements, capacity)
if subj not in knowledge_base:
knowledge_base[subj] = {}
if "capacities" not in knowledge_base[subj]:
knowledge_base[subj]["capacities"] = set()
return modifiable_element_for_existance_in_set(
container=knowledge_base[subj],
set_name="capacities",
element=capacity
)
2017-05-11 18:36:49 +00:00
def question(knowledge_base, elements, subj):
subj = resolve(knowledge_base, elements, subj)
if is_modifiable_property(subj):
2017-05-11 18:36:49 +00:00
return subj.getter()
return subj
2017-05-24 18:13:42 +00:00
def implies(knowledge_base, elements, precedent, consequent):
precedent = resolve(knowledge_base, elements, precedent)
consequent = resolve(knowledge_base, elements, consequent)
if precedent not in knowledge_base:
knowledge_base[precedent] = {'groups': set()}
2017-05-24 18:13:42 +00:00
if "implications" not in knowledge_base[precedent]:
knowledge_base[precedent]["implications"] = set()
return modifiable_element_for_existance_in_set(
container=knowledge_base[precedent],
set_name="implications",
element=consequent
)
2017-05-11 18:36:49 +00:00
2017-05-24 18:42:15 +00:00
def property_has_value(knowledge_base, elements, subj, prop, value):
subj = resolve(knowledge_base, elements, subj)
prop = resolve(knowledge_base, elements, prop)
value = resolve(knowledge_base, elements, value)
if subj not in knowledge_base:
knowledge_base[subj] = {'groups': set()}
2017-05-24 18:42:15 +00:00
if prop not in knowledge_base[subj]:
knowledge_base[subj][prop] = set()
return modifiable_element_for_existance_in_set(
container=knowledge_base[subj],
set_name=prop,
element=value
)
def perform_verb_over_object(knowledge_base, elements, subj, verb, obj):
subj = resolve(knowledge_base, elements, subj)
verb = resolve(knowledge_base, elements, verb)
obj = resolve(knowledge_base, elements, obj)
logging.debug("({} {} {})".format(verb, subj, obj))
if subj not in knowledge_base:
knowledge_base[subj] = {'groups': set()}
if 'performs-over' not in knowledge_base[subj]:
knowledge_base[subj]['performs-over'] = {}
if verb not in knowledge_base[subj]['performs-over']:
knowledge_base[subj]['performs-over'][verb] = set()
return modifiable_element_for_existance_in_set(
container=knowledge_base[subj]['performs-over'],
set_name=verb,
element=obj
)
2017-05-24 18:42:15 +00:00
knowledge_ingestion = {
"exists-property-with-value": exists_property_with_value,
"pertenence-to-group": pertenence_to_group,
"has-capacity": has_capacity,
2017-05-11 18:36:49 +00:00
"question": question,
2017-05-24 18:13:42 +00:00
"implies": implies,
2017-05-24 18:42:15 +00:00
"property-has-value": property_has_value,
"perform-verb-over-object": perform_verb_over_object,
}
def tagged_with_ast(ast, elements, modifiable_property):
if not isinstance(modifiable_property, ModifiableProperty):
return modifiable_property
return ModifiablePropertyWithAst(modifiable_property.getter,
modifiable_property.setter,
ast, elements)
def integrate_information(knowledge_base, example):
ast = example['parsed']
method = ast[0]
args = ast[1:]
elements = example.get('elements', None)
logging.debug("Integrating:")
logging.debug("AST: {}".format(ast))
logging.debug("ARG: {}".format(elements))
logging.debug("------------")
return tagged_with_ast(
ast, elements,
knowledge_ingestion[method](knowledge_base, elements, *args))
def can_be_used_in_place(knowledge, token, minisegment):
if token not in knowledge.knowledge:
return False
info = knowledge.knowledge[token]
info_groups = info.get('groups', set())
minisegment_groups = minisegment.get('groups', set())
# Common group
if len(info_groups & minisegment_groups) > 0:
return True
# Neither has a group
elif len(info_groups) == 0 == len(minisegment_groups):
return True
return False