コード例 #1
0
ファイル: generator.py プロジェクト: szroland/nlu
    def gen(self, store: Store) -> Iterable[Concept]:

        keep_searching = True
        while keep_searching:
            keep_searching = False

            # todo: do not explicitly list() items (need to handle concurrent store modifications)
            classes = list(
                filter(lambda c: c.relation == Relation.Class,
                       store.concepts()))

            for class_concept in classes:  # type: Concept
                source = class_concept.parents[0]
                target = class_concept.parents[1]
                logger.debug("Using class concept %s" % class_concept)
                target_children = collect_children(target)

                mapping = {}
                for tc in target_children:  # type: Concept
                    clone_concept_with_replacing_parent(
                        tc, mapping, target, source)

                for template, clone in mapping.items():
                    if store.get_concept(clone) is None:
                        keep_searching = True
                        logger.debug("Generated concept %s" % clone)
                        yield store.integrate(clone)
コード例 #2
0
ファイル: test_store.py プロジェクト: szroland/nlu
    def test_concept_storing(self):
        s = Store()
        s.add_concept(1)
        s.add_concept(2)

        l = set(s.concepts())

        self.assertEqual(l, {1, 2})
コード例 #3
0
ファイル: test_store.py プロジェクト: szroland/nlu
    def test_concept_iterator_includes_parent_concepts(self):
        parent = Store()
        child = Store(parent)

        parent.add_concept(Concept.word("p"))
        child.add_concept(Concept.word("c"))

        l = set(map(lambda c: c.name, child.concepts()))
        self.assertEqual(l, {"p", "c"})
コード例 #4
0
ファイル: graph.py プロジェクト: szroland/nlu
def graph(store: Store, words: bool = False, simplify: bool = True):
    s = "{ nodes: ["
    if words:
        for word in store.words():
            s += "\n" + node(id(word), word.word, 50, '#F5A45D', 'octagon')

    for concept in store.concepts():
        if concept.relation == Relation.Word:
            s += "\n" + node(id(concept), concept.name, 50, "#6FB1FC",
                             'ellipse')
        else:
            if not simplify or not is_simple_2arg_concept(concept):
                l = concept.name
                if l is None:
                    l = str(concept)
                s += "\n" + node(id(concept), l, 50, "#86B342", 'triangle')

    s += "], edges: ["

    if words:
        for word in store.words():
            for meaning in word.meanings():
                s += "\n" + edge(id(word), id(meaning), None, "#6FB1FC", 10)

    for concept in store.concepts():
        if simplify and is_simple_2arg_concept(concept):
            p = ''
            if concept.probability < 1.0:
                p = ' (p=' + str(concept.probability) + ')'

            s += "\n" + edge(id(concept.parents[0]), id(concept.parents[1]),
                             concept.relation.name + p, "#EDA1ED", 50)
        else:
            for parent in concept.parents:
                s += "\n" + edge(id(concept), id(parent), None, "#EDA1ED", 50)

    s += "] }"
    return s
コード例 #5
0
ファイル: nlu.py プロジェクト: szroland/nlu
class NLU:
    def __init__(self):
        self.working_memory = Store(label='WM')
        self.question_store = Store(self.working_memory, label='Question')
        self.concepts = []  # type: list[Concept]
        self.text_parser = SpacyTranslator()

    def is_mentalase(self, expression: str):
        if '(' in expression and ')' in expression:
            return True
        if ' ' in expression:
            return False

        #single word
        return True

    def integrate(self,
                  expression: str,
                  label: str = None,
                  probability: float = 1.0) -> List[Concept]:
        # for now, only reset question_store when new statements are integrated into the working memory
        self.question_store = Store(self.working_memory, label='Question')

        parsed = []
        if self.is_mentalase(expression):
            concept = parse(expression, self.working_memory, label,
                            probability)
            parsed.append(concept)
            self.working_memory.integrate(concept)
        else:
            for concept in self.text_parser.parse(expression):
                parsed.append(concept)
                self.working_memory.integrate(concept)
        return parsed

    def ask(
        self, question: str
    ) -> (Concept, Optional[Mapping[Concept, Concept]], Optional[Concept]):

        if self.is_mentalase(question):
            q = parse(question, self.question_store)  # type: Concept
        else:
            q = next(self.text_parser.parse(question))

        for concept in self.working_memory.concepts():  # type: Concept
            match = concept.matches(q)
            if match is not None:
                return q, match, concept

        # todo: handle available generators in a more generic way
        generator = InheritFromParentClass()
        for concept in generator.gen(self.question_store):  # type: Concept
            match = concept.matches(q)
            if match is not None and abs(concept.probability - 0.5) > 0.0:
                return q, match, concept

        # another pass at all generated concepts to see if result was generated as part of larger compound concept
        # or, probability of result changed during generating concepts
        # todo: replace this with the ability to mark processed items in the store to be more efficient

        for concept in self.question_store.own_concepts():  # type: Concept
            match = concept.matches(q)
            if match is not None:
                return q, match, concept

        return q, None, None

    @staticmethod
    def create_answer(question: Concept, mapping: Mapping[Concept,
                                                          Concept]) -> Concept:
        if mapping is None:
            return None

        # simple
        if question.is_simple():
            if question in mapping:
                return mapping[question]
            return question

        # compound
        ap = []  # type: list[Concept]
        for p in question.parents:
            ap.append(NLU.create_answer(p, mapping))

        return Concept(question.name, question.relation, ap)

    def ask_question(self, question: str):

        parsed, match, matched_concept = self.ask(question)
        answer = self.create_answer(parsed, match)
        print("Question: %s" % parsed)

        direct = str(answer)
        p = ''
        if matched_concept is not None:
            p = '(p=%r)' % matched_concept.probability
        print("Answer: %s %s" % (direct, p))

        if matched_concept is not None:
            full = str(matched_concept)
            if direct != full:
                print("Full answer: %s" % full)