Skip to content

Commit

Permalink
Adjustments in TUI. Add new assistive Icon
Browse files Browse the repository at this point in the history
  • Loading branch information
yorevs committed Nov 22, 2024
1 parent f252f58 commit 3ae978b
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/main/askai/core/askai.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class AskAi:
@staticmethod
def _abort():
"""Abort the execution and exit."""
terminal.restore()
sys.exit(ExitStatus.FAILED.val)

def __init__(
Expand Down Expand Up @@ -134,7 +135,6 @@ def abort(self, signals: Any | None = None, frame: Any | None = None) -> None:
self._abort()
events.abort.emit(message="User interrupted [ctrl+c]")
threading.Timer(1, lambda: setattr(self, "_abort_count", 0)).start()
terminal.restore()

def run(self) -> None:
"""Run the application."""
Expand Down
1 change: 1 addition & 0 deletions src/main/askai/core/askai_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def run(self) -> None:
elif output:
cache.save_reply(question, output)
cache.save_input_history()
# FIXME This is only writing the final answer to the markdown file.
with open(self.console_path, "a+", encoding=Charset.UTF_8.val) as f_console:
f_console.write(f"{shared.username_md}{question}\n\n")
f_console.write(f"{shared.nickname_md}{output}\n\n")
Expand Down
9 changes: 9 additions & 0 deletions src/main/askai/core/commander/commander.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,15 @@ def help(command: str | None) -> None:
display_text(commander_help(command.replace("/", "")))


@ask_commander.command()
def assistive() -> None:
"""Toggle assistive mode ON/OFF."""
configs.is_assistive = not configs.is_assistive
text_formatter.commander_print(
f"`Assistive responses` is {'%GREEN%ON' if configs.is_assistive else '%RED%OFF'}%NC%"
)


@ask_commander.command()
def debug() -> None:
"""Toggle debug mode ON/OFF."""
Expand Down
4 changes: 2 additions & 2 deletions src/main/askai/core/engine/openai/openai_vision.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def create_image_caption_chain(inputs: dict) -> MessageContent:
:param inputs: Dictionary containing the image and prompt information.
:return: MessageContent object with the generated caption.
"""
model: BaseChatModel = ChatOpenAI(temperature=0.8, model="gpt-4o-mini", max_tokens=1024)
model: BaseChatModel = ChatOpenAI(model="gpt-4o-mini")
msg: BaseMessage = model.invoke(
[
HumanMessage(
Expand Down Expand Up @@ -99,7 +99,7 @@ def caption(
check_argument(len((final_path := str(find_file(final_path) or ""))) > 0, f"Invalid image path: {final_path}")
vision_prompt: str = self._get_vision_prompt(query, image_type)
load_image_chain = TransformChain(
input_variables=["image_path", "parser_guides"], output_variables=["image"], transform=self._encode_image
input_variables=["image_path", "parser_guides"], output_variables=["image"], transform_cb=self._encode_image
)
out_parser: JsonOutputParser = self._get_out_parser(image_type)
vision_chain = load_image_chain | self.create_image_caption_chain | out_parser
Expand Down
14 changes: 10 additions & 4 deletions src/main/askai/tui/app_header.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,10 @@ class HeaderNotifications(Widget):
"""Display a notification widget on the right of the header."""

speaking = Reactive(configs.is_speak)
assistive = Reactive(configs.is_assistive)
debugging = Reactive(configs.is_debug)
caching = Reactive(configs.is_cache)
rag = Reactive(configs.is_rag)
listening = Reactive(False)
headphones = Reactive(False)
idiom = Reactive(f"{configs.language.name} ({configs.language.idiom})")
Expand All @@ -141,16 +143,18 @@ def __init__(self):
def __str__(self):
device_info: str = f"{recorder.input_device[1]}" if recorder.input_device else "-"
voice: str = shared.engine.configs().tts_voice
return dedent(
f"""
# fmt: off
return dedent(f"""\
Assistive: {'' if self.assistive else ''}
Debugging: {'' if self.debugging else ''}
Listening: {'' if self.listening else ''}
Speaking: {'  ' + voice if self.speaking else ''}
Caching: {'' if self.caching else ''}
RAG: {'' if self.rag else ''}
Audio In: {device_info}
Idiom:  {self.idiom}
"""
).strip()
""").strip()
# fmt: on

def _on_mount(self, _: Mount) -> None:
self.set_interval(1, callback=self.refresh, name="update clock")
Expand All @@ -162,6 +166,7 @@ def render(self) -> RenderResult:
f"{AppIcons.HEADPHONES if self.headphones else AppIcons.BUILT_IN_SPEAKER} "
f"{AppIcons.LISTENING_ON if self.listening else AppIcons.LISTENING_OFF} "
f"{AppIcons.SPEAKING_ON if self.speaking else AppIcons.SPEAKING_OFF} "
f"{AppIcons.ASSISTIVE_ON if self.assistive else AppIcons.ASSISTIVE_OFF} "
f"{AppIcons.CACHING_ON if self.caching else AppIcons.CACHING_OFF} "
f"{AppIcons.DEBUG_ON if self.debugging else AppIcons.DEBUG_OFF} "
f"{AppIcons.SEPARATOR_V} {now(f'%a %d %b %X')}",
Expand All @@ -172,6 +177,7 @@ def render(self) -> RenderResult:
def refresh_icons(self) -> None:
"""Update the application widgets."""
self.headphones = recorder.is_headphones()
self.assistive = configs.is_assistive
self.debugging = configs.is_debug
self.caching = configs.is_cache
self.speaking = configs.is_speak
Expand Down
2 changes: 2 additions & 0 deletions src/main/askai/tui/app_icons.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class AppIcons(Enumeration):
SPEAKING_OFF = "婢"
CACHING_ON = "凌"
CACHING_OFF = "稜"
ASSISTIVE_ON = ""
ASSISTIVE_OFF = ""
SEPARATOR_V = ""
SEPARATOR_H = ""
LISTENING_ON = ""
Expand Down
17 changes: 11 additions & 6 deletions src/main/askai/tui/askai_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,14 +209,19 @@ def check_action(self, action: str, _) -> Optional[bool]:
# All other keys display as normal
return True

@work(thread=True)
def enable_controls(self, enable: bool = True) -> None:
"""Enable or disable all UI controls, including the header, input, and footer.
:param enable: Whether to enable (True) or disable (False) the UI controls (default is True).
"""
self.input_actions.set_class(not enable, "-hidden")
self.header.disabled = not enable
self.line_input.loading = not enable
self.footer.disabled = not enable

def _invoke_later_(arg: bool = True) -> None:
self.input_actions.set_class(not arg, "-hidden")
self.header.disabled = not arg
self.line_input.loading = not arg
self.footer.disabled = not arg

self.call_from_thread(_invoke_later_, enable)

def activate_markdown(self) -> None:
"""Activate the markdown console widget."""
Expand Down Expand Up @@ -381,9 +386,9 @@ def ask_and_reply(self, question: str) -> tuple[bool, Optional[str]]:
:param question: The question to ask the AI engine.
:return: A tuple containing a boolean indicating success or failure, and the AI's reply as an optional string.
"""
self.call_from_thread(self.enable_controls, False)
self.enable_controls(False)
status, reply = self.askai.ask_and_reply(question)
self.call_from_thread(self.enable_controls)
self.enable_controls()

return status, reply

Expand Down

0 comments on commit 3ae978b

Please sign in to comment.