Skip to content

Commit

Permalink
Query subsystem updated to support plug-in query handler modules in t…
Browse files Browse the repository at this point in the history
…he queries/ directory; currently works for plain text queries only
  • Loading branch information
vthorsteinsson committed Jun 6, 2019
1 parent daae0f3 commit 0cb8c58
Show file tree
Hide file tree
Showing 5 changed files with 346 additions and 191 deletions.
30 changes: 16 additions & 14 deletions processor.py
Expand Up @@ -48,9 +48,24 @@
from db.models import Article, Person
from tree import Tree


_PROFILING = False


def modules_in_dir(directory):
""" Find all python modules in a given directory """
files = os.listdir(directory)
modnames = list()
for fname in files:
if not fname.endswith(".py"):
continue
if fname.startswith("_"): # Skip any files starting with _
continue
mod = directory.replace("/", ".") + "." + fname[:-3] # Cut off .py
modnames.append(mod)
return modnames


class TokenContainer: # Better name wanted. Open to suggestions.
""" Class wrapper around tokens """

Expand Down Expand Up @@ -142,19 +157,6 @@ def cleanup(cls):
""" Perform any cleanup """
cls._db = None

def modules_in_dir(self, directory):
""" Find all python modules in a given directory """
files = os.listdir(directory)
modnames = list()
for fname in files:
if not fname.endswith(".py"):
continue
if fname.startswith("_"): # Skip any files starting with _
continue
mod = directory.replace("/", ".") + "." + fname[:-3] # Cut off .py
modnames.append(mod)
return modnames

def __init__(self, processor_directory, single_processor=None, num_workers=None):

Processor._init_class()
Expand All @@ -164,7 +166,7 @@ def __init__(self, processor_directory, single_processor=None, num_workers=None)
self.pmodules = None

# Find .py files in the processor directory
modnames = self.modules_in_dir(processor_directory)
modnames = modules_in_dir(processor_directory)

if single_processor:
# Remove all except the single processor specified
Expand Down
54 changes: 54 additions & 0 deletions queries/clock.py
@@ -0,0 +1,54 @@
"""
Reynir: Natural language processing for Icelandic
Clock query response module
Copyright (C) 2019 Miðeind ehf.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
This module is an example of a plug-in query response module
for the Greynir query subsystem. It handles plain text queries, i.e.
ones that do not require parsing the query text. For this purpose
it only needs to implement the handle_plain_text() function, as
shown below.
"""

from datetime import datetime


def handle_plain_text(q):
""" Handle a plain text query, contained in the q parameter
which is an instance of the query.Query class.
Returns True if the query was handled, and in that case
the appropriate properties on the Query instance have
been set, such as the answer and the query type (qtype).
If the query is not recognized, returns False. """
ql = q.query_lower
if ql.endswith("?"):
ql = ql[:-1]
if ql == "hvað er klukkan":
# This is a query we recognize and handle
q.set_qtype("Special")
# A non-voice answer is usually a dict or a list
now = datetime.utcnow()
answer = dict(answer="{0:02}:{1:02}".format(now.hour, now.minute))
# A voice answer is always a plain string
voice = "Klukkan er {0} {1:02}".format(now.hour, now.minute)
q.set_answer(answer, voice)
return True

return False
129 changes: 129 additions & 0 deletions queries/frivolous.py
@@ -0,0 +1,129 @@
"""
Reynir: Natural language processing for Icelandic
Frivolous query response module
Copyright (C) 2019 Miðeind ehf.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
This module is an example of a plug-in query response module
for the Greynir query subsystem. It handles plain text queries, i.e.
ones that do not require parsing the query text. For this purpose
it only needs to implement the handle_plain_text() function, as
shown below.
"""

_SPECIAL_QUERIES = {
"er þetta spurning?": {
"answer": "Er þetta svar?"
},
"er þetta svar?": {
"answer": "Er þetta spurning?"
},
"hvað er svarið?": {
"answer": "42.",
"voice": "Fjörutíu og tveir."
},
"hvert er svarið?": {
"answer": "42.",
"voice": "Fjörutíu og tveir."
},
"veistu allt?": {
"answer": "Nei, því miður."
},
"hvað veistu?": {
"answer": "Spurðu mig!"
},
"veistu svarið?": {
"answer": "Spurðu mig!"
},
"hvað heitir þú?": {
"answer": "Greynir. Ég er grey sem reynir að greina íslensku.",
"voice": "Ég heiti Greynir. Ég er grey sem reynir að greina íslensku."
},
"hver ert þú?": {
"answer": "Ég er grey sem reynir að greina íslensku."
},
"hver bjó þig til?": {
"answer": "Flotta teymið hjá Miðeind.",
},
"hver skapaði þig?": {
"answer": "Flotta teymið hjá Miðeind."
},
"hver er skapari þinn?": {
"answer": "Flotta teymið hjá Miðeind."
},
"hver er flottastur?": {
"answer": "Teymið hjá Miðeind."
},
"hver er sætastur?": {
"answer": "Tumi Þorsteinsson.",
"voice": "Tumi Þorsteinsson er langsætastur."
},
"hver er langsætastur?": {
"answer": "Tumi Þorsteinsson.",
"voice": "Tumi Þorsteinsson er langsætastur."
},
"hver er ég?": {
"answer": "Þú ert þú."
},
"hvar er ég?": {
"answer": "Þú ert hérna."
},
"er guð til?": {
"answer": "Ég held ekki."
},
"hver skapaði guð?": {
"answer": "Enginn sem ég þekki."
},
"hver skapaði heiminn?": {
"answer": "Enginn sem ég þekki."
},
"hver er tilgangur lífsins?": {
"answer": "42.",
"voice": "Fjörutíu og tveir."
},
"hvar endar alheimurinn?": {
"answer": "Inni í þér."
},
}


def handle_plain_text(q):
""" Handle a plain text query, contained in the q parameter
which is an instance of the query.Query class.
Returns True if the query was handled, and in that case
the appropriate properties on the Query instance have
been set, such as the answer and the query type (qtype).
If the query is not recognized, returns False. """
ql = q.query_lower

if ql in _SPECIAL_QUERIES or (ql + "?") in _SPECIAL_QUERIES:
# This is a query we recognize and handle
q.set_qtype("Special")
if ql in _SPECIAL_QUERIES:
response = _SPECIAL_QUERIES[ql]
else:
response = _SPECIAL_QUERIES[ql + "?"]
# A non-voice answer is usually a dict or a list
answer = dict(answer=response.get("answer"))
# A voice answer is always a plain string
voice = response.get("voice")
q.set_answer(answer, voice)
return True

return False

0 comments on commit 0cb8c58

Please sign in to comment.