Skip to content

Commit

Permalink
Add docs and function annotations
Browse files Browse the repository at this point in the history
Remove added CLI entrypoints for deprecated functions
  • Loading branch information
NeonDaniel committed Dec 6, 2023
1 parent df3862d commit 79d5a34
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 59 deletions.
34 changes: 2 additions & 32 deletions chatbot_core/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,36 +37,6 @@ def chatbot_core_cli(version: bool = False):
click.echo(f"chatbot-core version {__version__}")


@chatbot_core_cli.command(help="Start Klat v1 Connection")
@click.option("--domain", default="chatbotsforum.org",
help="Domain to connect to")
@click.option("--bot-dir", default="./", help="Path to legacy chatbots directory")
@click.option("--bot", help="Optional name of single bot to start")
@click.option("--credentials", help="Optional path to legacy credentials file")
@click.option("--username", help="Klat username for bot to login as")
@click.option("--password", help="Password to login with")
@click.option("--server", help="Klat server address/URL")
def start_klat_bots(domain, bot_dir, bot, credentials, username, password, server):
from chatbot_core.utils.bot_utils import start_bots
bot_dir = expanduser(relpath(bot_dir))
if credentials:
credentials = expanduser(relpath(credentials))
start_bots(domain, bot_dir, username, password, server, credentials, bot)


@chatbot_core_cli.command(help="Start a chatbot prompter")
@click.option("--bot-dir", default="./", help="Path to legacy chatbots directory")
@click.option("--bot", help="Name of prompter bot to start")
@click.option("--username", help="Klat username for bot to login as")
@click.option("--password", help="Password to login with")
@click.option("--server", help="Klat server address/URL")
def start_klat_prompter(bot_dir, bot, username, password, server):
from chatbot_core.utils.bot_utils import start_bots
bot_dir = expanduser(relpath(bot_dir))
start_bots("chatbotsforum.org", bot_dir, username, password,
server, None, bot, None, False, True)


@chatbot_core_cli.command(help="Start an MQ chatbot")
@click.argument("bot_entrypoint")
def start_mq_bot(bot_entrypoint):
Expand Down Expand Up @@ -103,7 +73,7 @@ def cli_start_bots():
Entry Point to start bots from a Console Script
"""
from chatbot_core.utils.bot_utils import SERVER, start_bots
log_deprecation("Use `chatbots start-klat-bots`", "3.0.0")
log_deprecation("This CLI command is deprecated", "3.0.0")

parser = argparse.ArgumentParser(description="Start some chatbots")
parser.add_argument("--domain", dest="domain", default="chatbotsforum.org",
Expand Down Expand Up @@ -182,7 +152,7 @@ def cli_start_prompter():
"""
Entry Point to start a prompter bot
"""
log_deprecation("Use `chatbots start-klat-prompter`", "3.0.0")
log_deprecation("This CLI command is deprecated", "3.0.0")

from chatbot_core.utils.bot_utils import SERVER, start_bots
parser = argparse.ArgumentParser(description="Start a prompter chatbot")
Expand Down
74 changes: 47 additions & 27 deletions chatbot_core/utils/bot_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import sys
import yaml

from typing import Optional, Callable, Dict

from multiprocessing import Process, Event, synchronize
from threading import Thread, current_thread
from ovos_bus_client import Message, MessageBusClient
Expand All @@ -36,9 +38,8 @@
from ovos_utils.log import LOG, log_deprecation
from neon_utils.net_utils import get_ip_address

# Causes circular imports
# from chatbot_core import ChatBot
# from chatbot_core.v2 import ChatBot as ChatBotV2
from chatbot_core.chatbot_abc import ChatBotABC
from chatbot_core.v2 import ChatBot as ChatBotV2


ip = get_ip_address()
Expand Down Expand Up @@ -289,6 +290,8 @@ def start_bots(domain: str = None, bot_dir: str = None, username: str = None, pa
processes = _start_bot_processes(bots_to_start, username, password, credentials, server, domain)

if handle_restart:
log_deprecation("Messagebus connections to Neon Core will be "
"deprecated", "3.0.0")
LOG.info(f"Setting restart listener for {server}")
_listen_for_restart_chatbots(server)
try:
Expand Down Expand Up @@ -323,18 +326,23 @@ def start_bots(domain: str = None, bot_dir: str = None, username: str = None, pa
p.join()


def debug_bots(bot_dir: str = os.getcwd()):
def debug_bots(bot_dir: str = None):
"""
Debug bots in the passed directory
:param bot_dir: directory containing the bot to test
"""
# TODO: Generalize this to testing different modules? Leave one method for selecting a bot and then create an
# options menu for this interactive testing, along with automated discusser and appraiser testing.
# Automated testing could use pre-built response objects, or run n other bots and handle their outputs offline
# TODO: Generalize this to testing different modules? Leave one method for
# selecting a bot and then create an options menu for this interactive
# testing, along with automated discusser and appraiser testing.
# Automated testing could use pre-built response objects, or run n
# other bots and handle their outputs offline
from klat_connector.mach_server import MachKlatServer
server = MachKlatServer()

if bot_dir:
log_deprecation("Bots should be installed so they may be accessed by "
"entrypoint. Specifying a local directory will no "
"longer be supported", "2.3.1")
subminds = get_bots_in_dir(bot_dir)
else:
subminds = _find_bot_modules()
Expand Down Expand Up @@ -395,7 +403,7 @@ def _restart_chatbots(message: Message):
Messagebus handler to restart chatbots on a server
:param message: Message associated with request
"""
# TODO: Deprecate
# TODO: Deprecate in 3.0.0
global runner
LOG.debug(f"Restart received: {message.data} | {message.context}")
runner.set()
Expand All @@ -406,7 +414,7 @@ def _listen_for_restart_chatbots(server: str):
Registers a messagebus listener to restart chatbots for the given server
:param server: base url of the klat server messagebus to listen to
"""
# TODO: Deprecate
# TODO: Deprecate in 3.0.0
if server == "2222.us":
host = "64.34.186.120"
elif server == "5555.us":
Expand All @@ -428,7 +436,8 @@ def init_message_bus(bus_config: dict = None) -> (Thread, MessageBusClient):
:param bus_config: messagebus configuration to use
:return: Thread, messagebus object
"""
# TODO: Deprecate
log_deprecation("Messagebus connections to Neon Core will be deprecated",
"3.0.0")
bus_config = bus_config or {"host": "167.172.112.7",
"port": 8181,
"ssl": False,
Expand All @@ -442,19 +451,22 @@ def init_message_bus(bus_config: dict = None) -> (Thread, MessageBusClient):

def generate_random_response(from_iterable: iter):
"""
Generates some random bot response from the given options or the default list
Generates some random bot response from the given options or the default list
:param from_iterable: source iterable to get random value from
:param from_iterable: source iterable to get random value from
"""
return random.choice(from_iterable)


def find_closest_answer(algorithm: str = 'random', sentence: str = None, options: dict = None):
def find_closest_answer(algorithm: str = 'random', sentence: str = None,
options: dict = None) -> Optional[str]:
"""
Handles an incoming shout into the current conversation
:param algorithm: algorithm considered
:param sentence: base sentence
:param options: options to pick best one from
Determines which option is most similar to an input sentence
:param algorithm: algorithm considered
:param sentence: base sentence
:param options: dict of option ID to response for comparison with `sentence`
:returns: `option` ID with a value closest to `sentence`, None if requested
algorithm fails
"""
if not sentence:
LOG.warning('Empty sentence supplied')
Expand All @@ -478,14 +490,19 @@ def find_closest_answer(algorithm: str = 'random', sentence: str = None, options
opinion_tokenized = word_tokenize(options[option].lower())
if len(opinion_tokenized) > 0:
if min(len(response_tokenized), len(opinion_tokenized)) < 4:
weighting = 1.0 / min(len(response_tokenized), len(opinion_tokenized))
weights = tuple([weighting] * min(len(response_tokenized), len(opinion_tokenized)))
weighting = 1.0 / min(len(response_tokenized),
len(opinion_tokenized))
weights = tuple([weighting] * min(len(response_tokenized),
len(opinion_tokenized)))
else:
weights = (0.25, 0.25, 0.25, 0.25)
bleu_scores.append(
(option, sentence_bleu([response_tokenized], opinion_tokenized, weights=weights)))
max_score = max([x[1] for x in bleu_scores]) if len(bleu_scores) > 0 else 0
closest_answer = random.choice(list(filter(lambda x: x[1] == max_score, bleu_scores)))[0]
bleu_scores.append((option, sentence_bleu([response_tokenized],
opinion_tokenized,
weights=weights)))
max_score = max([x[1] for x in
bleu_scores]) if len(bleu_scores) > 0 else 0
closest_answer = random.choice(list(filter(lambda x: x[1] == max_score,
bleu_scores)))[0]
LOG.info(f'Closest answer is {closest_answer}')
elif algorithm == 'damerau_levenshtein_distance':
closest_distance = None
Expand All @@ -510,9 +527,9 @@ def find_closest_answer(algorithm: str = 'random', sentence: str = None, options
return closest_answer


def grammar_check(func):
def grammar_check(func: Callable):
"""
Checks grammar for output of passed function
Decorator to add spelling/grammar checks to a function's output
:param func: function to consider
"""
try:
Expand All @@ -535,7 +552,10 @@ def wrapper(*args, **kwargs):
return wrapper


def _find_bot_modules():
def _find_bot_modules() -> Dict[str, type(ChatBotABC)]:
"""
Method for locating all installed chatbots by entrypoint.
"""
try:
from importlib_metadata import entry_points
bot_entrypoints = entry_points(group="neon.plugin.chatbot")
Expand All @@ -547,7 +567,7 @@ def _find_bot_modules():


def run_mq_bot(chatbot_name: str, vhost: str = '/chatbots',
run_kwargs: dict = None, init_kwargs: dict = None):
run_kwargs: dict = None, init_kwargs: dict = None) -> ChatBotV2:
"""
Get an initialized MQ Chatbot instance
@param chatbot_name: chatbot entrypoint name and configuration key
Expand Down

0 comments on commit 79d5a34

Please sign in to comment.