Changes to environment loading.

- Move Some environment loading code to EnvService.
- Attempt loading of env file from multiple locations & names
- Provide a path fetching + fallback function for reading
  paths from environment vars.
- For Docker;
  - Create /opt/gpt3discord/{etc,bin,shared}
  - Copy .txt shared data into shared
  - Copy main .py into bin
Justin McPherson 2 years ago
parent 4e325221b4
commit ddbe356e2a

@ -23,5 +23,7 @@ RUN pip install --target="/install" /src
FROM python:${PY_VERSION}-slim FROM python:${PY_VERSION}-slim
ARG PY_VERSION ARG PY_VERSION
COPY --from=builder /install /usr/local/lib/python${PY_VERSION}/site-packages COPY --from=builder /install /usr/local/lib/python${PY_VERSION}/site-packages
COPY gpt3discord.py /bin/gpt3discord RUN mkdir -p /opt/gpt3discord/etc
CMD ["python3", "/bin/gpt3discord"] COPY gpt3discord.py /opt/gpt3discord/bin/
COPY image_optimizer_pretext.txt conversation_starter_pretext.txt conversation_starter_pretext_minimal.txt /opt/gpt3discord/share/
CMD ["python3", "/opt/gpt3discord/bin/gpt3discord.py"]

@ -155,7 +155,7 @@ To build:
- Optional: Make a data directory + bind mount it - Optional: Make a data directory + bind mount it
- Add `DATA_DIR=/data` to env file - Add `DATA_DIR=/data` to env file
- Run via docker: - Run via docker:
- `docker run [-d] --name gpt3discord -v env_file:/bin/.env [-v /containers/gpt3discord:/data] gpt3discord` - `docker run [-d] --name gpt3discord -v env_file:/opt/gpt3discord/etc/environment [-v /containers/gpt3discord:/data] gpt3discord`
- You can also mount a second volume and set `DATA_DIR` in the env file to keep persistent data - You can also mount a second volume and set `DATA_DIR` in the env file to keep persistent data
This can also be run via screen/tmux or detached like a daemon. This can also be run via screen/tmux or detached like a daemon.

@ -31,9 +31,11 @@ class GPT3ComCon(commands.Cog, name="GPT3ComCon"):
DEBUG_GUILD, DEBUG_GUILD,
DEBUG_CHANNEL, DEBUG_CHANNEL,
data_path: Path, data_path: Path,
share_path: Path,
): ):
super().__init__() super().__init__()
self.data_path = data_path self.data_path = data_path
self.share_path = share_path
self.debug_channel = None self.debug_channel = None
self.bot = bot self.bot = bot
self._last_member_ = None self._last_member_ = None
@ -57,7 +59,7 @@ class GPT3ComCon(commands.Cog, name="GPT3ComCon"):
self.awaiting_responses = [] self.awaiting_responses = []
try: try:
conversation_file_path = data_path / "conversation_starter_pretext.txt" conversation_file_path = share_path / "conversation_starter_pretext.txt"
# Attempt to read a conversation starter text string from the file. # Attempt to read a conversation starter text string from the file.
with conversation_file_path.open("r") as f: with conversation_file_path.open("r") as f:
self.CONVERSATION_STARTER_TEXT = f.read() self.CONVERSATION_STARTER_TEXT = f.read()
@ -67,7 +69,7 @@ class GPT3ComCon(commands.Cog, name="GPT3ComCon"):
assert self.CONVERSATION_STARTER_TEXT is not None assert self.CONVERSATION_STARTER_TEXT is not None
conversation_file_path_minimal = ( conversation_file_path_minimal = (
data_path / "conversation_starter_pretext_minimal.txt" share_path / "conversation_starter_pretext_minimal.txt"
) )
with conversation_file_path_minimal.open("r") as f: with conversation_file_path_minimal.open("r") as f:
self.CONVERSATION_STARTER_TEXT_MINIMAL = f.read() self.CONVERSATION_STARTER_TEXT_MINIMAL = f.read()

@ -36,7 +36,7 @@ class ImgPromptOptimizer(commands.Cog, name="ImgPromptOptimizer"):
try: try:
image_pretext_path = ( image_pretext_path = (
self.converser_cog.data_path / "image_optimizer_pretext.txt" self.converser_cog.share_path / "image_optimizer_pretext.txt"
) )
# Try to read the image optimizer pretext from # Try to read the image optimizer pretext from
# the file system # the file system

@ -5,7 +5,6 @@ from pathlib import Path
import discord import discord
from discord.ext import commands from discord.ext import commands
from dotenv import load_dotenv
import os import os
if sys.platform == "win32": if sys.platform == "win32":
@ -13,9 +12,6 @@ if sys.platform == "win32":
else: else:
separator = "/" separator = "/"
print("The environment file is located at " + os.getcwd() + separator + ".env")
load_dotenv(dotenv_path=os.getcwd() + separator + ".env")
from cogs.draw_image_generation import DrawDallEService from cogs.draw_image_generation import DrawDallEService
from cogs.gpt_3_commands_and_converser import GPT3ComCon from cogs.gpt_3_commands_and_converser import GPT3ComCon
from cogs.image_prompt_optimizer import ImgPromptOptimizer from cogs.image_prompt_optimizer import ImgPromptOptimizer
@ -23,6 +19,7 @@ from models.deletion_service_model import Deletion
from models.message_model import Message from models.message_model import Message
from models.openai_model import Model from models.openai_model import Model
from models.usage_service_model import UsageService from models.usage_service_model import UsageService
from models.env_service_model import EnvService
__version__ = "2.1.3" __version__ = "2.1.3"
@ -67,12 +64,16 @@ async def on_application_command_error(
async def main(): async def main():
data_path = Path(os.environ.get("DATA_DIR", os.getcwd())) share_path = EnvService.environment_path_with_fallback("SHARE_DIR", "share")
data_path = EnvService.environment_path_with_fallback("DATA_DIR")
debug_guild = int(os.getenv("DEBUG_GUILD")) debug_guild = int(os.getenv("DEBUG_GUILD"))
debug_channel = int(os.getenv("DEBUG_CHANNEL")) debug_channel = int(os.getenv("DEBUG_CHANNEL"))
if not data_path.exists(): if not data_path.exists():
raise OSError(f"{data_path} does not exist ... create it?") raise OSError(f"Data path: {data_path} does not exist ... create it?")
if not share_path.exists():
raise OSError(f"Share path: {share_path} does not exist ... create it?")
# Load the main GPT3 Bot service # Load the main GPT3 Bot service
bot.add_cog( bot.add_cog(
@ -85,6 +86,7 @@ async def main():
debug_guild, debug_guild,
debug_channel, debug_channel,
data_path, data_path,
share_path,
) )
) )

@ -1,7 +1,22 @@
import os
import sys
from pathlib import Path
from dotenv import load_dotenv from dotenv import load_dotenv
load_dotenv()
import os # <app/bin/main.py>/../../
def app_root_path():
try:
return Path(sys.argv[0]).resolve().parents[1]
except:
return Path()
# None will let direnv do its' thing
env_paths = [Path() / ".env", app_root_path() / "etc/environment", None]
for env_path in env_paths:
print("Loading environment from " + str(env_path))
load_dotenv(dotenv_path=env_path)
class EnvService: class EnvService:
@ -9,6 +24,19 @@ class EnvService:
def __init__(self): def __init__(self):
self.env = {} self.env = {}
@staticmethod
def environment_path_with_fallback(env_name, relative_fallback = None):
dir = os.getenv(env_name)
if dir != None:
return Path(dir).resolve()
if relative_fallback:
app_relative = (app_root_path() / relative_fallback).resolve()
if app_relative.exists:
return app_relative
return Path()
@staticmethod @staticmethod
def get_allowed_guilds(): def get_allowed_guilds():
# ALLOWED_GUILDS is a comma separated list of guild ids # ALLOWED_GUILDS is a comma separated list of guild ids

Loading…
Cancel
Save