Skip to content

Commit

Permalink
Save geo loc file. Fixed default geo loc. Small improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
yorevs committed Nov 14, 2024
1 parent 1f0e790 commit 0288c07
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 128 deletions.
1 change: 1 addition & 0 deletions src/main/askai/__classpath__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import sys
import warnings


if not is_debugging():
warnings.simplefilter("ignore", category=FutureWarning)
warnings.simplefilter("ignore", category=UserWarning)
Expand Down
129 changes: 63 additions & 66 deletions src/main/askai/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,22 @@
Copyright (c) 2024, HomeSetup
"""

from askai.__classpath__ import classpath
from askai.core.askai_configs import configs
from askai.core.enums.run_modes import RunModes
from askai.core.support.shared_instances import LOGGER_NAME
import typing
import logging as log
import os
import re
import sys

from clitt.core.tui.tui_application import TUIApplication
from hspylib.core.enums.charset import Charset
from hspylib.core.tools.commons import syserr, to_bool
from hspylib.core.tools.dict_tools import get_or_default
from hspylib.core.zoned_datetime import now
from hspylib.modules.application.argparse.parser_action import ParserAction
from hspylib.modules.application.exit_status import ExitStatus
from hspylib.modules.application.version import Version
from textwrap import dedent
from typing import Any, AnyStr, Optional

import click
import logging as log
import os
import re
import sys
from askai.__classpath__ import classpath
from askai.core.support.utilities import QueryString


class Main(TUIApplication):
Expand All @@ -47,24 +43,37 @@ class Main(TUIApplication):
# The resources folder
RESOURCE_DIR: str = str(classpath.resource_path)

# Singleton instance
INSTANCE: "Main"

@staticmethod
def setup_logs() -> None:
"""TODO"""
# FIXME: Move this code to hspylib Application FW
log.basicConfig(level=log.WARNING)
logger = log.getLogger(LOGGER_NAME)
logger.setLevel(log.INFO)
logger.propagate = False
def _execute_command(command_str: typing.AnyStr) -> ExitStatus:
"""Execute an AskAI-commander command. This method avoids loading all AskAI context and modules.
:param command_str: The command string to be executed.
:return: The exit status of the command execution.
"""
import click
from askai.core.commander import commander

try:
if command := re.search(commander.RE_ASKAI_CMD, command_str):
args: list[str] = list(
filter(lambda a: a and a != "None", re.split(r"\s", f"{command.group(1)} {command.group(2)}"))
)
commander.ask_commander(args, standalone_mode=False)
# If no exception is raised, the command executed successfully
return ExitStatus.SUCCESS
except click.ClickException as ce:
ce.show()
syserr("Command failed due to a ClickException.")
return ExitStatus.FAILED

def __init__(self, app_name: str):
super().__init__(app_name, self.VERSION, self.DESCRIPTION.format(self.VERSION), resource_dir=self.RESOURCE_DIR)
self._askai: Any
Main.setup_logs()
self._askai: typing.Any

@property
def askai(self) -> Any:
def askai(self) -> typing.Any:
return self._askai

def _setup_arguments(self) -> None:
Expand All @@ -74,49 +83,51 @@ def _setup_arguments(self) -> None:
self._with_options() \
.option(
"interactive", "i", "interactive",
"whether you would like to run the program in an interactive mode.",
"Whether you would like to run the program in interactive mode.",
nargs="?", action=ParserAction.STORE_TRUE)\
.option(
"speak", "s", "speak",
"whether you want the AI to speak (audio out TTS).",
"Whether you want the AI to speak (audio out TTS).",
nargs="?", action=ParserAction.STORE_TRUE)\
.option(
"debug", "d", "debug",
"whether you want to run under debug mode.",
"Whether you want to run under debug mode.",
nargs="?", action=ParserAction.STORE_TRUE) \
.option(
"ui", "u", "ui",
"whether to use the new AskAI TUI (experimental).",
"Whether to use the new AskAI TUI (experimental).",
nargs="?", action=ParserAction.STORE_TRUE)\
.option(
"cache", "c", "cache",
"whether you want to cache AI replies.",
"Whether you want to cache AI replies.",
nargs="?") \
.option(
"tempo", "t", "tempo",
"specifies the playback and streaming speed.",
"Set the playback and streaming speed.",
choices=['1', '2', '3'],
nargs="?")\
.option(
"prompt", "p", "prompt",
"specifies the landing prompt file (not useful with interactive mode).",
"Set the landing prompt file (not useful with interactive mode).",
nargs="?")\
.option(
"engine", "e", "engine",
"specifies which AI engine to use. If not provided, the default engine wil be used.",
"Set which AI engine to use (if not provided, the default engine wil be used).",
choices=["openai", "gemini"],
nargs="?")\
.option(
"model", "m", "model",
"specifies which AI model to use (depends on the engine).",
"Set which AI-Engine model to use (depends on the engine).",
nargs="?") \
.option(
"router", "r", "router",
"specifies which router mode to use.",
"Set which router mode to use.",
nargs="?",
choices=["rag", "chat", "splitter"])
self._with_arguments() \
.argument("query_string", "what to ask to the AI engine", nargs="*")
.argument(
"query_string", "What to ask the AI engine",
nargs="*")
# fmt: on

def _main(self, *params, **kwargs) -> ExitStatus:
Expand All @@ -125,6 +136,11 @@ def _main(self, *params, **kwargs) -> ExitStatus:
:param kwargs: Keyword command line arguments.
:return: ExitStatus indicating the result of the application run.
"""
from askai.core.askai_configs import configs
from askai.core.enums.run_modes import RunModes
from hspylib.core.zoned_datetime import now
from textwrap import dedent

os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
is_new_ui: bool = to_bool(self._get_argument("ui", False))
query_string: str | None = self._get_query_string()
Expand Down Expand Up @@ -164,17 +180,15 @@ def _main(self, *params, **kwargs) -> ExitStatus:
os.environ["ASKAI_APP"] = RunModes.ASKAI_CMD.value
return self._execute_command(query_string)

log.debug(
dedent(
f"""
# fmt: off
log.debug(dedent(f"""\
{os.environ.get("ASKAI_APP")} v{self._app_version}
Settings ==============================
Application Settings ==============================
STARTED: {now("%Y-%m-%d %H:%M:%S")}
{self.configs}
"""
)
)
"""))
# fmt: on
return self._exec_application()

def _exec_application(self) -> ExitStatus:
Expand All @@ -188,7 +202,7 @@ def _exec_application(self) -> ExitStatus:

return ExitStatus.SUCCESS

def _get_argument(self, arg_name: str, default: Any = None) -> Optional[Any]:
def _get_argument(self, arg_name: str, default: typing.Any = None) -> typing.Optional[typing.Any]:
"""Get a command line argument, converting to the appropriate type.
:param arg_name: The name of the command line argument to retrieve.
:param default: The default value to return if the argument is not found. Defaults to None.
Expand All @@ -207,12 +221,12 @@ def _get_argument(self, arg_name: str, default: Any = None) -> Optional[Any]:

return None

def _get_query_string(self) -> Optional[str]:
def _get_query_string(self) -> typing.Optional[str]:
"""Return the query_string parameter.
:return: The query_string if it exists, otherwise None.
:return: The query_string if it exists, None otherwise.
"""
query_string: str | list[str] = self.get_arg("query_string")
return query_string if isinstance(query_string, str) else " ".join(query_string)
query_string: QueryString = self._get_argument("query_string")
return " ".join(query_string) if isinstance(query_string, list) else query_string

def _get_mode_str(self) -> str:
"""Return the router mode according to the specified arguments or from configs.
Expand All @@ -221,31 +235,14 @@ def _get_mode_str(self) -> str:
return self._get_argument("router", "default")

def _get_interactive(self, query_string: str) -> bool:
"""TODO"""
"""Return the interactive parameter if query_string is not specified; False otherwise.
:param query_string: The query string to check for interactivity.
:return: The value of the interactive parameter or False based on query_string presence.
"""
interactive: bool = to_bool(self._get_argument("interactive", False))
interactive = interactive if not query_string else False
return interactive

def _execute_command(self, command_str: AnyStr) -> ExitStatus:
"""Execute an AskAI-commander command. This method avoids loading all AskAI context and modules.
:param command_str: The command string to be executed.
:return: The exit status of the command execution.
"""
from askai.core.commander import commander

try:
if command := re.search(commander.RE_ASKAI_CMD, command_str):
args: list[str] = list(
filter(lambda a: a and a != "None", re.split(r"\s", f"{command.group(1)} {command.group(2)}"))
)
commander.ask_commander(args, standalone_mode=False)
# If no exception is raised, the command executed successfully
return ExitStatus.SUCCESS
except click.ClickException as ce:
ce.show()
syserr("Command failed due to a ClickException.")
return ExitStatus.FAILED


# Application entry point
if __name__ == "__main__":
Expand Down
37 changes: 18 additions & 19 deletions src/main/askai/core/askai.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,22 @@
Copyright (c) 2024, HomeSetup
"""
from pathlib import Path
from typing import Any, Optional
import logging as log
import os
import re
import sys
import threading

from click import UsageError
from clitt.core.term.terminal import terminal
from hspylib.core.enums.charset import Charset
from hspylib.core.tools.commons import file_is_not_empty, is_debugging
from hspylib.core.zoned_datetime import DATE_FORMAT, now, TIME_FORMAT
from hspylib.modules.application.exit_status import ExitStatus
from openai import RateLimitError

from askai.__classpath__ import classpath
from askai.core.askai_configs import configs
from askai.core.askai_events import events
Expand All @@ -28,23 +44,6 @@
from askai.core.support.utilities import display_text, read_stdin
from askai.exception.exceptions import *
from askai.tui.app_icons import AppIcons
from click import UsageError
from clitt.core.term.terminal import terminal
from hspylib.core.enums.charset import Charset
from hspylib.core.tools.commons import file_is_not_empty, is_debugging
from hspylib.core.zoned_datetime import DATE_FORMAT, now, TIME_FORMAT
from hspylib.modules.application.exit_status import ExitStatus
from openai import RateLimitError
from pathlib import Path
from typing import Any, List, Optional, TypeAlias

import logging as log
import os
import re
import sys
import threading

QueryString: TypeAlias = str | List[str] | None


class AskAi:
Expand Down Expand Up @@ -111,7 +110,6 @@ def console_path(self) -> Path:

@property
def session_id(self) -> str:
"""Get the Session id."""
return self._session_id

@property
Expand All @@ -123,7 +121,8 @@ def app_settings(self) -> list[tuple[str, ...]]:
return all_settings

def abort(self, signals: Any, frame: Any) -> None:
"""Hook the SIGINT signal for cleanup or execution interruption. If two signals arrive within 1 second, exit the application.
"""Hook the SIGINT signal for cleanup or execution interruption. If two signals arrive within 1 second,
abort the application execution.
:param signals: Signal number from the operating system.
:param frame: Current stack frame at the time of signal interruption.
"""
Expand Down
29 changes: 14 additions & 15 deletions src/main/askai/core/askai_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
import signal
from pathlib import Path
from threading import Thread
from typing import List, Optional, TypeAlias
from typing import Optional

import nltk
import pause
from clitt.core.term.cursor import cursor
from clitt.core.term.screen import screen
from clitt.core.tui.line_input.keyboard_input import KeyboardInput
from hspylib.core.decorator.decorators import profiled
from hspylib.core.enums.charset import Charset
from hspylib.core.tools.commons import console_out
from hspylib.core.zoned_datetime import now, TIME_FORMAT
Expand All @@ -46,8 +47,6 @@
from askai.core.support.utilities import display_text
from askai.tui.app_icons import AppIcons

QueryString: TypeAlias = str | List[str] | None


class AskAiCli(AskAi):
"""The AskAI CLI application."""
Expand All @@ -61,15 +60,14 @@ def __init__(
query_prompt: str,
engine_name: str,
model_name: str,
query_string: QueryString,
query_string: str | None,
mode: RouterMode,
):

super().__init__(speak, debug, cacheable, tempo, engine_name, model_name, mode)
self._ready: bool = False
self._progress = Progress()
self._query_prompt = query_prompt
self._query_string: QueryString = query_string if isinstance(query_string, str) else " ".join(query_string)
self._query_prompt: str = query_prompt
self._query_string: str | None = query_string
self._startup()

def run(self) -> None:
Expand Down Expand Up @@ -174,6 +172,7 @@ def _splash(self, interval: int = 250) -> None:

def _startup(self) -> None:
"""Initialize the application components."""
progress: Progress = Progress()
# List of tasks for progress tracking
tasks = [
"Downloading nltk data",
Expand All @@ -189,21 +188,21 @@ def _startup(self) -> None:
if configs.is_interactive:
splash_thread: Thread = Thread(daemon=True, target=self._splash)
splash_thread.start()
task = self._progress.add_task(f'[green] {msg.t("Starting up...")}', total=len(tasks))
with self._progress:
task = progress.add_task(f'[green] {msg.t("Starting up...")}', total=len(tasks))
with progress:
os.chdir(Path.home())
self._progress.update(task, advance=1, description=f'[green] {msg.t("Downloading nltk data")}')
progress.update(task, advance=1, description=f'[green] {msg.t("Downloading nltk data")}')
nltk.download("averaged_perceptron_tagger", quiet=True, download_dir=CACHE_DIR)
cache.cache_enable = configs.is_cache
self._progress.update(task, advance=1, description=f'[green] {msg.t("Loading input history")}')
progress.update(task, advance=1, description=f'[green] {msg.t("Loading input history")}')
KeyboardInput.preload_history(cache.load_input_history(commands()))
self._progress.update(task, advance=1, description=f'[green] {msg.t("Starting scheduler")}')
progress.update(task, advance=1, description=f'[green] {msg.t("Starting scheduler")}')
scheduler.start()
self._progress.update(task, advance=1, description=f'[green] {msg.t("Setting up recorder")}')
progress.update(task, advance=1, description=f'[green] {msg.t("Setting up recorder")}')
recorder.setup()
self._progress.update(task, advance=1, description=f'[green] {msg.t("Starting player delay")}')
progress.update(task, advance=1, description=f'[green] {msg.t("Starting player delay")}')
player.start_delay()
self._progress.update(task, advance=1, description=f'[green] {msg.t("Finalizing startup")}')
progress.update(task, advance=1, description=f'[green] {msg.t("Finalizing startup")}')
pause.seconds(1)
self._ready = True
splash_thread.join()
Expand Down
Loading

0 comments on commit 0288c07

Please sign in to comment.