Skip to content

Commit

Permalink
Fix the emit problems due to the spinner
Browse files Browse the repository at this point in the history
  • Loading branch information
yorevs committed Oct 30, 2024
1 parent f86c390 commit 94c26e2
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 67 deletions.
3 changes: 3 additions & 0 deletions src/main/askai/core/askai_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ def goodbye(self) -> str:
def smile(self, countdown: int) -> str:
return f"\nSmile {str(countdown)} "

def look_at_camera(self) -> str:
return "Look at the camera…"

def cmd_success(self, command_line: AnyStr) -> str:
return f"OK, command `{command_line}` succeeded"

Expand Down
17 changes: 10 additions & 7 deletions src/main/askai/core/model/ai_reply.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@
Copyright (c) 2024, HomeSetup
"""
from rich.console import ConsoleRenderable

from askai.core.enums.verbosity import Verbosity
from dataclasses import dataclass
from typing import AnyStr
from typing import AnyStr, TypeAlias

AnyText: TypeAlias = AnyStr | ConsoleRenderable


@dataclass(frozen=True)
Expand All @@ -38,7 +41,7 @@ def __str__(self) -> str:
return self.message

@staticmethod
def info(message: AnyStr, verbosity: Verbosity = Verbosity.NORMAL, speakable: bool = True) -> "AIReply":
def info(message: AnyText, verbosity: Verbosity = Verbosity.NORMAL, speakable: bool = True) -> "AIReply":
"""Creates an info reply.
:param message: The reply message.
:param verbosity: The verbosity level of the reply.
Expand All @@ -48,7 +51,7 @@ def info(message: AnyStr, verbosity: Verbosity = Verbosity.NORMAL, speakable: bo
return AIReply(str(message), True, False, verbosity, speakable)

@staticmethod
def detailed(message: AnyStr, speakable: bool = False) -> "AIReply":
def detailed(message: AnyText, speakable: bool = False) -> "AIReply":
"""Creates a detailed verbosity reply.
:param message: The reply message.
:param speakable: Indicates whether the reply is speakable.
Expand All @@ -57,7 +60,7 @@ def detailed(message: AnyStr, speakable: bool = False) -> "AIReply":
return AIReply(str(message), True, False, Verbosity.DETAILED, speakable)

@staticmethod
def full(message: AnyStr, speakable: bool = False) -> "AIReply":
def full(message: AnyText, speakable: bool = False) -> "AIReply":
"""Creates a full verbose reply.
:param message: The reply message.
:param speakable: Indicates whether the reply is speakable.
Expand All @@ -66,23 +69,23 @@ def full(message: AnyStr, speakable: bool = False) -> "AIReply":
return AIReply(str(message), True, False, Verbosity.FULL, speakable)

@staticmethod
def error(message: AnyStr) -> "AIReply":
def error(message: AnyText) -> "AIReply":
"""Creates an error reply.
:param message: The reply message.
:return: An AIReply instance with error settings.
"""
return AIReply(str(message), False, False, Verbosity.MINIMUM, False)

@staticmethod
def debug(message: AnyStr) -> "AIReply":
def debug(message: AnyText) -> "AIReply":
"""Creates a debug reply.
:param message: The reply message.
:return: An AIReply instance with debug settings.
"""
return AIReply(str(message), True, True, Verbosity.NORMAL, False)

@staticmethod
def mute(message: AnyStr, verbosity: Verbosity = Verbosity.NORMAL) -> "AIReply":
def mute(message: AnyText, verbosity: Verbosity = Verbosity.NORMAL) -> "AIReply":
"""Creates a mute reply.
:param message: The reply message.
:param verbosity: The verbosity level of the reply.
Expand Down
7 changes: 5 additions & 2 deletions src/main/askai/core/processors/splitter/splitter_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
Copyright (c) 2024, HomeSetup
"""
from askai.core.askai_configs import configs
from askai.core.askai_events import events
from askai.core.askai_messages import msg
from askai.core.askai_prompt import prompt
from askai.core.component.geo_location import geo_location
from askai.core.component.rag_provider import RAGProvider
from askai.core.engine.openai.temperature import Temperature
from askai.core.enums.response_model import ResponseModel
from askai.core.model.acc_response import AccResponse
from askai.core.model.action_plan import ActionPlan
from askai.core.model.ai_reply import AIReply
from askai.core.model.model_result import ModelResult
from askai.core.router.agent_tools import features
from askai.core.router.task_agent import agent
Expand Down Expand Up @@ -54,7 +57,7 @@ def wrap_answer(question: str, answer: str, model_result: ModelResult = ModelRes
args = {"user": prompt.user.title(), "idiom": shared.idiom, "context": answer, "question": question}
prompt_args: list[str] = [k for k in args.keys()]
model: ResponseModel = ResponseModel.of_model(model_result.mid)
# events.reply.emit(reply=AIReply.full(msg.model_select(model)))
events.reply.emit(reply=AIReply.full(msg.model_select(model)))

match model, configs.is_speak:
case ResponseModel.TERMINAL_COMMAND, True:
Expand Down Expand Up @@ -87,7 +90,7 @@ def refine_answer(question: str, answer: str, acc_response: AccResponse | None =
"question": question,
}
prompt_args = [k for k in args.keys()]
# events.reply.emit(reply=AIReply.debug(msg.refine_answer(answer)))
events.reply.emit(reply=AIReply.debug(msg.refine_answer(answer)))
return final_answer("taius-refiner", prompt_args, **args)

return answer
Expand Down
38 changes: 23 additions & 15 deletions src/main/askai/core/processors/splitter/splitter_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@
Copyright (c) 2024, HomeSetup
"""
import os
from textwrap import indent
from threading import Thread

from hspylib.core.tools.commons import is_debugging
from rich.live import Live
from rich.spinner import Spinner
from rich.text import Text

from askai.core.askai_configs import configs
from askai.core.enums.acc_color import AccColor
from askai.core.processors.splitter.splitter_pipeline import SplitterPipeline
from askai.core.processors.splitter.splitter_states import States
from rich.console import Console
from textwrap import indent
from threading import Thread

import os
from askai.core.support.text_formatter import text_formatter as tf, text_formatter


class SplitterExecutor(Thread):
Expand All @@ -29,26 +34,27 @@ class SplitterExecutor(Thread):
def __init__(self, query: str):
super().__init__()
self._pipeline = SplitterPipeline(query)
self._console = Console()

@property
def pipeline(self) -> SplitterPipeline:
return self._pipeline

def display(self, message: str) -> None:
def display(self, reply: str) -> None:
"""TODO"""
if configs.is_debug:
self._console.print(message)
if is_debugging():
text_formatter.console.print(Text.from_markup(reply))

def run(self) -> None:
with self._console.status(f"[green]{self.pipeline.state}[/green]", spinner="dots") as spinner:
with Live(Spinner("dots", f"[green]{self.pipeline.state}[/green]", style="green"), console=tf.console) as live:
while not self.pipeline.state == States.COMPLETE:
self.pipeline.track_previous()
if 1 < configs.max_router_retries < 1 + self.pipeline.failures[self.pipeline.state.value]:
self.display(f"\n[red] Max retries exceeded: {configs.max_agent_retries}[/red]\n")
self.display(
f"\n[red] Max retries exceeded: {configs.max_agent_retries}[/red]\n")
break
if 1 < configs.max_iteractions < 1 + self.pipeline.iteractions:
self.display(f"\n[red] Max iteractions exceeded: {configs.max_iteractions}[/red]\n")
self.display(
f"\n[red] Max iteractions exceeded: {configs.max_iteractions}[/red]\n")
break
match self.pipeline.state:
case States.STARTUP:
Expand All @@ -71,7 +77,8 @@ def run(self) -> None:
case States.ACC_CHECK:
acc_color: AccColor = self.pipeline.st_accuracy_check()
c_name: str = acc_color.color.casefold()
self.display(f"[green]√ Accuracy check: [{c_name}]{c_name.upper()}[/{c_name}][/green]")
self.display(
f"[green]√ Accuracy check: [{c_name}]{c_name.upper()}[/{c_name}][/green]")
if acc_color.passed(AccColor.GOOD):
self.pipeline.ev_accuracy_passed()
elif acc_color.passed(AccColor.MODERATE):
Expand All @@ -85,7 +92,8 @@ def run(self) -> None:
if self.pipeline.st_final_answer():
self.pipeline.ev_final_answer()
case _:
self.display(f"[red] Error: Machine halted before complete!({self.pipeline.state})[/red]")
self.display(
f"[red] Error: Machine halted before complete!({self.pipeline.state})[/red]")
break

execution_status: bool = self.pipeline.previous != self.pipeline.state
Expand All @@ -95,7 +103,7 @@ def run(self) -> None:
)
self.pipeline.failures[self.pipeline.state.value] += 1 if not execution_status else 0
self.display(f"[green]{execution_status_str}[/green]")
spinner.update(f"[green]{self.pipeline.state.value}…[/green]")
live.update(Spinner("dots", f"[green]{self.pipeline.state}…[/green]", style="green"))
self.pipeline.iteractions += 1

if configs.is_debug:
Expand Down
12 changes: 6 additions & 6 deletions src/main/askai/core/processors/splitter/splitter_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,27 +83,27 @@ def question(self) -> str:

@property
def last_query(self) -> Optional[str]:
return self.responses[-1].query if self.responses else None
return self.responses[-1].query if len(self.responses) > 0 else None

@last_query.setter
def last_query(self, value: str) -> None:
self.responses[-1].query = value if self.responses else None
self.responses[-1].query = value if len(self.responses) > 0 else None

@property
def last_answer(self) -> Optional[str]:
return self.responses[-1].answer if self.responses else None
return self.responses[-1].answer if len(self.responses) > 0 else None

@last_answer.setter
def last_answer(self, value: str) -> None:
self.responses[-1].answer = value if self.responses else None
self.responses[-1].answer = value if len(self.responses) > 0 else None

@property
def last_accuracy(self) -> Optional[AccResponse]:
return self.responses[-1].accuracy if self.responses else None
return self.responses[-1].accuracy if len(self.responses) > 0 else None

@last_accuracy.setter
def last_accuracy(self, value: AccResponse) -> None:
self.responses[-1].accuracy = value if self.responses else None
self.responses[-1].accuracy = value if len(self.responses) > 0 else None

@property
def plan(self) -> ActionPlan:
Expand Down
5 changes: 4 additions & 1 deletion src/main/askai/core/router/tools/webcam.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from askai.core.askai_configs import configs
from askai.core.askai_events import events
from askai.core.askai_messages import msg
from askai.core.component.camera import camera
from askai.core.model.ai_reply import AIReply
from askai.core.router.tools.vision import image_captioner, parse_caption
from askai.core.support.utilities import display_text
from hspylib.core.tools.text_tools import ensure_endswith, ensure_startswith
Expand Down Expand Up @@ -53,7 +56,7 @@ def webcam_identifier(max_distance: int = configs.max_id_distance) -> str:
:return: A description of the identified person.
"""
identity: str = "%ORANGE% No identification was possible!%NC%"
display_text("Look at the camera...")
events.reply.emit(reply=AIReply.debug(msg.look_at_camera()))
if photo := camera.identify(3, max_distance):
# fmt: off
identity = ensure_endswith(ensure_startswith(
Expand Down
29 changes: 15 additions & 14 deletions src/main/askai/core/support/shared_instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@
Copyright (c) 2024, HomeSetup
"""
import os
from pathlib import Path
from textwrap import dedent
from typing import Any, Optional

from clitt.core.term.terminal import terminal
from clitt.core.tui.line_input.line_input import line_input
from hspylib.core.metaclass.singleton import Singleton
from hspylib.core.preconditions import check_state
from hspylib.core.tools.text_tools import elide_text
from hspylib.modules.application.version import Version
from hspylib.modules.cli.keyboard import Keyboard
from langchain.memory import ConversationBufferWindowMemory
from langchain.memory.chat_memory import BaseChatMemory

from askai.__classpath__ import classpath
from askai.core.askai_configs import configs
from askai.core.askai_messages import msg
Expand All @@ -23,20 +38,6 @@
from askai.core.engine.engine_factory import EngineFactory
from askai.core.support.chat_context import ChatContext
from askai.core.support.utilities import display_text
from clitt.core.term.terminal import terminal
from clitt.core.tui.line_input.line_input import line_input
from hspylib.core.metaclass.singleton import Singleton
from hspylib.core.preconditions import check_state
from hspylib.core.tools.text_tools import elide_text
from hspylib.modules.application.version import Version
from hspylib.modules.cli.keyboard import Keyboard
from langchain.memory import ConversationBufferWindowMemory
from langchain.memory.chat_memory import BaseChatMemory
from pathlib import Path
from textwrap import dedent
from typing import Any, Optional

import os

LOGGER_NAME: str = 'Askai-Taius'

Expand Down
29 changes: 18 additions & 11 deletions src/main/askai/core/support/text_formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@
Copyright (c) 2024, HomeSetup
"""

from clitt.core.term.cursor import cursor
import os
import re
from textwrap import dedent
from typing import Any, AnyStr

from hspylib.core.metaclass.singleton import Singleton
from hspylib.core.tools.text_tools import ensure_endswith, ensure_startswith, strip_escapes
from hspylib.modules.cli.vt100.vt_code import VtCode
from hspylib.modules.cli.vt100.vt_color import VtColor
from textwrap import dedent
from typing import Any, AnyStr

import os
import re
from rich.console import Console
from rich.markdown import Markdown
from rich.text import Text


class TextFormatter(metaclass=Singleton):
Expand Down Expand Up @@ -102,13 +104,19 @@ def strip_format(text: AnyStr) -> str:
"""
return strip_escapes(TextFormatter.remove_markdown(text))

def __init__(self):
self._console: Console = Console(log_time=False, log_path=False)

@property
def console(self) -> Console:
return self._console

def beautify(self, text: Any) -> str:
"""Beautify the provided text with icons and other formatting enhancements.
:param text: The text to be beautified.
:return: The beautified text as a string with applied icons and formatting improvements.
"""
# fmt: off

text = dedent(str(text))
text = re.sub(self.RE_TYPES[''], self.CHAT_ICONS[''], text)
text = re.sub(self.RE_TYPES[''], self.CHAT_ICONS[''], text)
Expand All @@ -123,7 +131,6 @@ def beautify(self, text: Any) -> str:
text = re.sub(r'```(.+)```\s+', r"\n```\1```\n", text)
text = re.sub(rf"(\s+)({os.getenv('USER', 'user')})", r'\1*\2*', text)
text = re.sub(r"(\s+)([Tt]aius)", r'\1**\2**', text)

# fmt: on

return text
Expand All @@ -133,20 +140,20 @@ def display_markdown(self, text: AnyStr) -> None:
:param text: The markdown-formatted text to be displayed.
"""
colorized: str = VtColor.colorize(VtCode.decode(self.beautify(str(text))))
cursor.write(colorized, markdown=True)
self.console.print(Markdown(colorized))

def display_text(self, text: AnyStr) -> None:
"""Display a VT100 formatted text.
:param text: The VT100 formatted text to be displayed.
"""
colorized: str = VtColor.colorize(VtCode.decode(self.beautify(str(text))))
cursor.write(colorized)
self.console.print(Text.from_ansi(colorized))

def commander_print(self, text: AnyStr) -> None:
"""Display an AskAI-commander formatted text.
:param text: The text to be displayed.
"""
self.display_markdown(f"%ORANGE% Commander%NC%: {self.beautify(str(text))}")
self.display_markdown(f"%ORANGE% Commander%NC%: {str(text)}")


assert (text_formatter := TextFormatter().INSTANCE) is not None
Loading

0 comments on commit 94c26e2

Please sign in to comment.