Merge branch 'bobloy:master' into master

pull/189/head
aleclol 4 years ago committed by GitHub
commit a7ce815e14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -74,77 +74,35 @@ If you get an error at this step, stop and skip to one of the manual methods bel
#### Step 2: Install additional dependencies #### Step 2: Install additional dependencies
Assuming the previous commands had no error, you can now use `pipinstall` to add the remaining dependencies. Here you need to decide which training models you want to have available to you.
NOTE: This method is not the intended use case for `pipinstall` and may stop working in the future. Shutdown the bot and run any number of these in the console:
``` ```
[p]pipinstall --no-deps chatterbot>=1.1 python -m spacy download en_core_web_sm # ~15 MB
```
#### Step 3: Load the cog and get started
```
[p]load chatter
```
### Windows - Manually python -m spacy download en_core_web_md # ~50 MB
#### Step 1: Built-in Downloader
You need to get a copy of the requirements.txt provided with chatter, I recommend this method. python -m spacy download en_core_web_lg # ~750 MB (CPU Optimized)
``` python -m spacy download en_core_web_trf # ~500 MB (GPU Optimized)
[p]repo add Fox https://github.com/bobloy/Fox-V3
``` ```
#### Step 2: Install Requirements #### Step 3: Load the cog and get started
Make sure you have your virtual environment that you installed Red on activated before starting this step. See the Red Docs for details on how.
In a terminal running as an admin, navigate to the directory containing this repo.
I've used my install directory as an example.
```
cd C:\Users\Bobloy\AppData\Local\Red-DiscordBot\Red-DiscordBot\data\bobbot\cogs\RepoManager\repos\Fox\chatter
pip install -r requirements.txt
pip install --no-deps "chatterbot>=1.1"
```
#### Step 3: Load Chatter
``` ```
[p]repo add Fox https://github.com/bobloy/Fox-V3 # If you didn't already do this in step 1
[p]cog install Fox chatter
[p]load chatter [p]load chatter
``` ```
### Linux - Manually ### Windows - Manually
Deprecated
#### Step 1: Built-in Downloader
```
[p]repo add Fox https://github.com/bobloy/Fox-V3
[p]cog install Fox chatter
```
#### Step 2: Install Requirements
In your console with your virtual environment activated:
```
pip install --no-deps "chatterbot>=1.1"
```
### Step 3: Load Chatter
``` ### Linux - Manually
[p]load chatter Deprecated
```
# Configuration # Configuration
Chatter works out the the box without any training by learning as it goes, Chatter works out the box without any training by learning as it goes,
but will have very poor and repetitive responses at first. but will have very poor and repetitive responses at first.
Initial training is recommended to speed up its learning. Initial training is recommended to speed up its learning.

@ -1,8 +1,10 @@
from .chat import Chatter from .chat import Chatter
def setup(bot): async def setup(bot):
bot.add_cog(Chatter(bot)) cog = Chatter(bot)
await cog.initialize()
bot.add_cog(cog)
# __all__ = ( # __all__ = (

@ -19,6 +19,7 @@ from redbot.core.utils.predicates import MessagePredicate
from chatter.trainers import MovieTrainer, TwitterCorpusTrainer, UbuntuCorpusTrainer2 from chatter.trainers import MovieTrainer, TwitterCorpusTrainer, UbuntuCorpusTrainer2
chatterbot_log = logging.getLogger("red.fox_v3.chatterbot")
log = logging.getLogger("red.fox_v3.chatter") log = logging.getLogger("red.fox_v3.chatter")
@ -29,6 +30,12 @@ def my_local_get_prefix(prefixes, content):
return None return None
class ENG_TRF:
ISO_639_1 = "en_core_web_trf"
ISO_639 = "eng"
ENGLISH_NAME = "English"
class ENG_LG: class ENG_LG:
ISO_639_1 = "en_core_web_lg" ISO_639_1 = "en_core_web_lg"
ISO_639 = "eng" ISO_639 = "eng"
@ -52,12 +59,15 @@ class Chatter(Cog):
This cog trains a chatbot that will talk like members of your Guild This cog trains a chatbot that will talk like members of your Guild
""" """
models = [ENG_SM, ENG_MD, ENG_LG, ENG_TRF]
algos = [SpacySimilarity, JaccardSimilarity, LevenshteinDistance]
def __init__(self, bot): def __init__(self, bot):
super().__init__() super().__init__()
self.bot = bot self.bot = bot
self.config = Config.get_conf(self, identifier=6710497116116101114) self.config = Config.get_conf(self, identifier=6710497116116101114)
default_global = {"learning": True} default_global = {"learning": True, "model_number": 0, "algo_number": 0, "threshold": 0.90}
default_guild = { self.default_guild = {
"whitelist": None, "whitelist": None,
"days": 1, "days": 1,
"convo_delta": 15, "convo_delta": 15,
@ -70,16 +80,16 @@ class Chatter(Cog):
# TODO: Move training_model and similarity_algo to config # TODO: Move training_model and similarity_algo to config
# TODO: Add an option to see current settings # TODO: Add an option to see current settings
self.tagger_language = ENG_MD self.tagger_language = ENG_SM
self.similarity_algo = SpacySimilarity self.similarity_algo = SpacySimilarity
self.similarity_threshold = 0.90 self.similarity_threshold = 0.90
self.chatbot = self._create_chatbot() self.chatbot = None
# self.chatbot.set_trainer(ListTrainer) # self.chatbot.set_trainer(ListTrainer)
# self.trainer = ListTrainer(self.chatbot) # self.trainer = ListTrainer(self.chatbot)
self.config.register_global(**default_global) self.config.register_global(**default_global)
self.config.register_guild(**default_guild) self.config.register_guild(**self.default_guild)
self.loop = asyncio.get_event_loop() self.loop = asyncio.get_event_loop()
@ -92,6 +102,18 @@ class Chatter(Cog):
"""Nothing to delete""" """Nothing to delete"""
return return
async def initialize(self):
all_config = dict(self.config.defaults["GLOBAL"])
all_config.update(await self.config.all())
model_number = all_config["model_number"]
algo_number = all_config["algo_number"]
threshold = all_config["threshold"]
self.tagger_language = self.models[model_number]
self.similarity_algo = self.algos[algo_number]
self.similarity_threshold = threshold
self.chatbot = self._create_chatbot()
def _create_chatbot(self): def _create_chatbot(self):
return ChatBot( return ChatBot(
@ -104,7 +126,7 @@ class Chatter(Cog):
logic_adapters=["chatterbot.logic.BestMatch"], logic_adapters=["chatterbot.logic.BestMatch"],
maximum_similarity_threshold=self.similarity_threshold, maximum_similarity_threshold=self.similarity_threshold,
tagger_language=self.tagger_language, tagger_language=self.tagger_language,
logger=log, logger=chatterbot_log,
) )
async def _get_conversation(self, ctx, in_channels: List[discord.TextChannel]): async def _get_conversation(self, ctx, in_channels: List[discord.TextChannel]):
@ -328,15 +350,12 @@ class Chatter(Cog):
self, ctx: commands.Context, algo_number: int, threshold: float = None self, ctx: commands.Context, algo_number: int, threshold: float = None
): ):
""" """
Switch the active logic algorithm to one of the three. Default after reload is Spacy Switch the active logic algorithm to one of the three. Default is Spacy
0: Spacy 0: Spacy
1: Jaccard 1: Jaccard
2: Levenshtein 2: Levenshtein
""" """
algos = [SpacySimilarity, JaccardSimilarity, LevenshteinDistance]
if algo_number < 0 or algo_number > 2: if algo_number < 0 or algo_number > 2:
await ctx.send_help() await ctx.send_help()
return return
@ -349,8 +368,11 @@ class Chatter(Cog):
return return
else: else:
self.similarity_threshold = threshold self.similarity_threshold = threshold
await self.config.threshold.set(self.similarity_threshold)
self.similarity_algo = self.algos[algo_number]
await self.config.algo_number.set(algo_number)
self.similarity_algo = algos[algo_number]
async with ctx.typing(): async with ctx.typing():
self.chatbot = self._create_chatbot() self.chatbot = self._create_chatbot()
@ -360,20 +382,18 @@ class Chatter(Cog):
@chatter.command(name="model") @chatter.command(name="model")
async def chatter_model(self, ctx: commands.Context, model_number: int): async def chatter_model(self, ctx: commands.Context, model_number: int):
""" """
Switch the active model to one of the three. Default after reload is Medium Switch the active model to one of the three. Default is Small
0: Small 0: Small
1: Medium 1: Medium (Requires additional setup)
2: Large (Requires additional setup) 2: Large (Requires additional setup)
3. Accurate (Requires additional setup)
""" """
if model_number < 0 or model_number > 3:
models = [ENG_SM, ENG_MD, ENG_LG]
if model_number < 0 or model_number > 2:
await ctx.send_help() await ctx.send_help()
return return
if model_number == 2: if model_number >= 0:
await ctx.maybe_send_embed( await ctx.maybe_send_embed(
"Additional requirements needed. See guide before continuing.\n" "Continue?" "Additional requirements needed. See guide before continuing.\n" "Continue?"
) )
@ -386,7 +406,8 @@ class Chatter(Cog):
if not pred.result: if not pred.result:
return return
self.tagger_language = models[model_number] self.tagger_language = self.models[model_number]
await self.config.model_number.set(model_number)
async with ctx.typing(): async with ctx.typing():
self.chatbot = self._create_chatbot() self.chatbot = self._create_chatbot()
@ -395,7 +416,13 @@ class Chatter(Cog):
) )
@commands.is_owner() @commands.is_owner()
@chatter.command(name="minutes") @chatter.group(name="trainset")
async def chatter_trainset(self, ctx: commands.Context):
"""Commands for configuring training"""
pass
@commands.is_owner()
@chatter_trainset.command(name="minutes")
async def minutes(self, ctx: commands.Context, minutes: int): async def minutes(self, ctx: commands.Context, minutes: int):
""" """
Sets the number of minutes the bot will consider a break in a conversation during training Sets the number of minutes the bot will consider a break in a conversation during training
@ -411,7 +438,7 @@ class Chatter(Cog):
await ctx.tick() await ctx.tick()
@commands.is_owner() @commands.is_owner()
@chatter.command(name="age") @chatter_trainset.command(name="age")
async def age(self, ctx: commands.Context, days: int): async def age(self, ctx: commands.Context, days: int):
""" """
Sets the number of days to look back Sets the number of days to look back
@ -630,7 +657,7 @@ class Chatter(Cog):
guild: discord.Guild = getattr(message, "guild", None) guild: discord.Guild = getattr(message, "guild", None)
if await self.bot.cog_disabled_in_guild(self, guild): if guild is None or await self.bot.cog_disabled_in_guild(self, guild):
return return
ctx: commands.Context = await self.bot.get_context(message) ctx: commands.Context = await self.bot.get_context(message)
@ -705,7 +732,9 @@ class Chatter(Cog):
) )
replying = None replying = None
if self._guild_cache[guild.id]["reply"]: if (
"reply" not in self._guild_cache[guild.id] and self.default_guild["reply"]
) or self._guild_cache[guild.id]["reply"]:
if message != ctx.channel.last_message: if message != ctx.channel.last_message:
replying = message replying = message

@ -7,17 +7,7 @@
"hidden": false, "hidden": false,
"install_msg": "Thank you for installing Chatter! Please make sure you check the install instructions at https://github.com/bobloy/Fox-V3/blob/master/chatter/README.md\nAfter that, get started ith `[p]load chatter` and `[p]help Chatter`", "install_msg": "Thank you for installing Chatter! Please make sure you check the install instructions at https://github.com/bobloy/Fox-V3/blob/master/chatter/README.md\nAfter that, get started ith `[p]load chatter` and `[p]help Chatter`",
"requirements": [ "requirements": [
"git+git://github.com/gunthercox/chatterbot-corpus@master#egg=chatterbot_corpus", "git+git://github.com/bobloy/ChatterBot@fox#egg=ChatterBot",
"mathparse>=0.1,<0.2",
"nltk>=3.2,<4.0",
"pint>=0.8.1",
"python-dateutil>=2.8,<2.9",
"pyyaml>=5.3,<5.4",
"sqlalchemy>=1.3,<1.4",
"pytz",
"https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.3.1/en_core_web_sm-2.3.1.tar.gz#egg=en_core_web_sm",
"https://github.com/explosion/spacy-models/releases/download/en_core_web_md-2.3.1/en_core_web_md-2.3.1.tar.gz#egg=en_core_web_md",
"spacy>=2.3,<2.4",
"kaggle" "kaggle"
], ],
"short": "Local Chatbot run on machine learning", "short": "Local Chatbot run on machine learning",

@ -1,12 +0,0 @@
git+git://github.com/gunthercox/chatterbot-corpus@master#egg=chatterbot_corpus
mathparse>=0.1,<0.2
nltk>=3.2,<4.0
pint>=0.8.1
python-dateutil>=2.8,<2.9
pyyaml>=5.3,<5.4
sqlalchemy>=1.3,<1.4
pytz
spacy>=2.3,<2.4
https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.3.1/en_core_web_sm-2.3.1.tar.gz#egg=en_core_web_sm
https://github.com/explosion/spacy-models/releases/download/en_core_web_md-2.3.1/en_core_web_md-2.3.1.tar.gz#egg=en_core_web_md
# https://github.com/explosion/spacy-models/releases/download/en_core_web_lg-2.3.1/en_core_web_lg-2.3.1.tar.gz#egg=en_core_web_lg

@ -5,7 +5,7 @@ class MyDumbSQLStorageAdapter(SQLStorageAdapter):
def __init__(self, **kwargs): def __init__(self, **kwargs):
super(SQLStorageAdapter, self).__init__(**kwargs) super(SQLStorageAdapter, self).__init__(**kwargs)
from sqlalchemy import create_engine from sqlalchemy import create_engine, inspect
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
self.database_uri = kwargs.get("database_uri", False) self.database_uri = kwargs.get("database_uri", False)
@ -18,9 +18,7 @@ class MyDumbSQLStorageAdapter(SQLStorageAdapter):
if not self.database_uri: if not self.database_uri:
self.database_uri = "sqlite:///db.sqlite3" self.database_uri = "sqlite:///db.sqlite3"
self.engine = create_engine( self.engine = create_engine(self.database_uri, connect_args={"check_same_thread": False})
self.database_uri, convert_unicode=True, connect_args={"check_same_thread": False}
)
if self.database_uri.startswith("sqlite://"): if self.database_uri.startswith("sqlite://"):
from sqlalchemy.engine import Engine from sqlalchemy.engine import Engine
@ -31,7 +29,7 @@ class MyDumbSQLStorageAdapter(SQLStorageAdapter):
dbapi_connection.execute("PRAGMA journal_mode=WAL") dbapi_connection.execute("PRAGMA journal_mode=WAL")
dbapi_connection.execute("PRAGMA synchronous=NORMAL") dbapi_connection.execute("PRAGMA synchronous=NORMAL")
if not self.engine.dialect.has_table(self.engine, "Statement"): if not inspect(self.engine).has_table("Statement"):
self.create_database() self.create_database()
self.Session = sessionmaker(bind=self.engine, expire_on_commit=True) self.Session = sessionmaker(bind=self.engine, expire_on_commit=True)

@ -32,6 +32,7 @@ class RecyclingPlant(Cog):
x = 0 x = 0
reward = 0 reward = 0
timeoutcount = 0
await ctx.send( await ctx.send(
"{0} has signed up for a shift at the Recycling Plant! Type ``exit`` to terminate it early.".format( "{0} has signed up for a shift at the Recycling Plant! Type ``exit`` to terminate it early.".format(
ctx.author.display_name ctx.author.display_name
@ -53,14 +54,25 @@ class RecyclingPlant(Cog):
return m.author == ctx.author and m.channel == ctx.channel return m.author == ctx.author and m.channel == ctx.channel
try: try:
answer = await self.bot.wait_for("message", timeout=120, check=check) answer = await self.bot.wait_for("message", timeout=20, check=check)
except asyncio.TimeoutError: except asyncio.TimeoutError:
answer = None answer = None
if answer is None: if answer is None:
if timeoutcount == 2:
await ctx.send( await ctx.send(
"``{}`` fell down the conveyor belt to be sorted again!".format(used["object"]) "{} slacked off at work, so they were sacked with no pay.".format(
ctx.author.display_name
)
)
break
else:
await ctx.send(
"{} is slacking, and if they carry on not working, they'll be fired.".format(
ctx.author.display_name
)
) )
timeoutcount += 1
elif answer.content.lower().strip() == used["action"]: elif answer.content.lower().strip() == used["action"]:
await ctx.send( await ctx.send(
"Congratulations! You put ``{}`` down the correct chute! (**+50**)".format( "Congratulations! You put ``{}`` down the correct chute! (**+50**)".format(

Loading…
Cancel
Save