From 83f79b73296df35f685ac31c49d853b8803debab Mon Sep 17 00:00:00 2001 From: Hugo Saporetti Junior Date: Fri, 22 Nov 2024 15:04:36 -0300 Subject: [PATCH] Improve screen capturer and fixed the splitter rag by removing the reasoning column as it was making the AI to commit more mistakes --- src/demo/others/screenshot_demo.py | 4 +- src/main/askai/core/askai_messages.py | 3 + .../askai/core/component/cache_service.py | 5 ++ src/main/askai/core/component/camera.py | 4 +- src/main/askai/core/model/image_result.py | 21 +++++- .../processors/splitter/splitter_executor.py | 9 ++- src/main/askai/core/router/agent_tools.py | 11 ++- src/main/askai/core/router/tools/vision.py | 44 +++++++---- .../askai/resources/rag/task-splitter.csv | 75 ++++++++++--------- 9 files changed, 115 insertions(+), 61 deletions(-) diff --git a/src/demo/others/screenshot_demo.py b/src/demo/others/screenshot_demo.py index ea6bb706..e62c1344 100644 --- a/src/demo/others/screenshot_demo.py +++ b/src/demo/others/screenshot_demo.py @@ -1,7 +1,7 @@ -from askai.core.router.tools.vision import take_screenshot +from askai.core.router.tools.vision import capture_screenshot from hspylib.core.tools.commons import sysout from utils import init_context if __name__ == "__main__": init_context("camera-demo") - sysout(take_screenshot("gabiroba.jpeg")) + sysout(capture_screenshot("gabiroba.jpeg")) diff --git a/src/main/askai/core/askai_messages.py b/src/main/askai/core/askai_messages.py index c850208c..2c690f9d 100644 --- a/src/main/askai/core/askai_messages.py +++ b/src/main/askai/core/askai_messages.py @@ -180,6 +180,9 @@ def describe_image(self, image_path: AnyPath) -> str: def model_select(self, model: AnyStr) -> str: return f"~~[DEBUG]~~ Using routing model: `{model}`" + def parsing_caption(self) -> str: + return f"~~[DEBUG]~~ Parsing caption…" + def task(self, task: AnyStr) -> str: return f"~~[DEBUG]~~ > `Task:` {task}" diff --git a/src/main/askai/core/component/cache_service.py b/src/main/askai/core/component/cache_service.py index 574ff470..6ebca532 100644 --- a/src/main/askai/core/component/cache_service.py +++ b/src/main/askai/core/component/cache_service.py @@ -47,6 +47,11 @@ if not PICTURE_DIR.exists(): PICTURE_DIR.mkdir(parents=True, exist_ok=True) +# Desktop screenshots cache directory. +SCREENSHOTS_DIR: Path = Path(str(CACHE_DIR) + "/screenshots") +if not SCREENSHOTS_DIR.exists(): + SCREENSHOTS_DIR.mkdir(parents=True, exist_ok=True) + # Camera photo shots cache directory. PHOTO_DIR: Path = Path(str(PICTURE_DIR) + "/photos") if not PHOTO_DIR.exists(): diff --git a/src/main/askai/core/component/camera.py b/src/main/askai/core/component/camera.py index 04575db4..7b3530fb 100644 --- a/src/main/askai/core/component/camera.py +++ b/src/main/askai/core/component/camera.py @@ -59,7 +59,7 @@ class Camera(metaclass=Singleton): ALG: str = configs.face_detect_alg @staticmethod - def _countdown(count: int) -> None: + def countdown(count: int) -> None: """Display a countdown before taking a photo. :param count: The number of seconds for the countdown. """ @@ -113,7 +113,7 @@ def capture( events.reply.emit(reply=AIReply.error(msg.camera_not_open())) return None - self._countdown(countdown) + self.countdown(countdown) ret, photo = self._cam.read() if not ret: diff --git a/src/main/askai/core/model/image_result.py b/src/main/askai/core/model/image_result.py index 18096c01..ab50e680 100644 --- a/src/main/askai/core/model/image_result.py +++ b/src/main/askai/core/model/image_result.py @@ -1,3 +1,6 @@ +import ast +import json + from pydantic import BaseModel, Field from typing import AnyStr @@ -15,4 +18,20 @@ class ImageResult(BaseModel): @staticmethod def of(image_caption: AnyStr) -> "ImageResult": - return ImageResult.model_validate_json(str(image_caption).replace("'", '"')) + """Parses a string into an ImageResult instance with enhanced handling for mixed quotes. + :param image_caption: The string to parse. + :return: An instance of ImageResult populated with the parsed data. + :raises ValueError: If the string cannot be parsed as a Python object or JSON. + """ + + try: + parsed_data = ast.literal_eval(image_caption) + except (ValueError, SyntaxError): + try: + parsed_data = json.loads(image_caption) + except json.JSONDecodeError as e_json: + raise ValueError("String could not be parsed as Python object or JSON.") from e_json + try: + return ImageResult(**parsed_data) + except Exception as e_pydantic: + raise ValueError("Parsed data does not conform to ImageResult schema.") from e_pydantic diff --git a/src/main/askai/core/processors/splitter/splitter_executor.py b/src/main/askai/core/processors/splitter/splitter_executor.py index 32567c28..0bd70272 100644 --- a/src/main/askai/core/processors/splitter/splitter_executor.py +++ b/src/main/askai/core/processors/splitter/splitter_executor.py @@ -130,8 +130,9 @@ def run(self) -> None: except InaccurateResponse: live.update(Spinner("dots", f"[red]AI failed to respond. Retrying…[/red]", style="green")) + final_state: States = self.pipeline.state + if configs.is_debug: - final_state: States = self.pipeline.state final_state_str: str = ( "[green] Succeeded[/green] " if final_state == States.COMPLETE else "[red] Failed [/red]" ) @@ -144,6 +145,6 @@ def run(self) -> None: ) self.display(f"Failures:\n{all_failures}") - if final_state != States.COMPLETE and not self._interrupted: - retries: int = self.pipeline.failures[self.pipeline.state.value] - self.display(f" Failed to generate a response after {retries} retries", True) + if final_state != States.COMPLETE and not self._interrupted: + retries: int = self.pipeline.failures[self.pipeline.state.value] + self.display(f" Failed to generate a response after {retries} retries", True) diff --git a/src/main/askai/core/router/agent_tools.py b/src/main/askai/core/router/agent_tools.py index 355d2a36..743a299d 100644 --- a/src/main/askai/core/router/agent_tools.py +++ b/src/main/askai/core/router/agent_tools.py @@ -32,7 +32,7 @@ from askai.core.router.tools.generation import generate_content, save_content from askai.core.router.tools.summarization import summarize from askai.core.router.tools.terminal import execute_command, list_contents, open_command -from askai.core.router.tools.vision import image_captioner, parse_caption +from askai.core.router.tools.vision import image_captioner, parse_caption, capture_screenshot from askai.core.router.tools.webcam import webcam_capturer, webcam_identifier, CAPTION_TEMPLATE from askai.exception.exceptions import TerminatingQuery @@ -152,6 +152,15 @@ def webcam_identifier(self) -> str: """ return webcam_identifier() + def screenshot(self, path_name: AnyPath | None = None, save_dir: AnyPath | None = None) -> str: + """Capture a screenshot and save it to the specified path. + Usage: `screenshot(path_name, load_dir)` + :param path_name: Optional path name of the captured screenshot. + :param save_dir: Optional directory to save the screenshot. + :return: The path to the saved screenshot. + """ + return capture_screenshot(path_name, save_dir) + def generate_content(self, instructions: str, mime_type: str, filepath: AnyPath) -> str: """Use this tool to generate various types of content, such as code, text, images, etc. This tool processes descriptive instructions to create the specified content type and can optionally save it to a file. diff --git a/src/main/askai/core/router/tools/vision.py b/src/main/askai/core/router/tools/vision.py index e68d60c7..39970049 100644 --- a/src/main/askai/core/router/tools/vision.py +++ b/src/main/askai/core/router/tools/vision.py @@ -1,6 +1,8 @@ import os +from fileinput import filename from textwrap import indent +import pause import pyautogui import torch from PIL import Image @@ -8,11 +10,14 @@ from hspylib.core.enums.enumeration import Enumeration from hspylib.core.metaclass.classpath import AnyPath from hspylib.core.preconditions import check_argument +from hspylib.core.tools.text_tools import ensure_endswith +from hspylib.core.zoned_datetime import now from transformers import BlipForConditionalGeneration, BlipProcessor from askai.core.askai_events import events from askai.core.askai_messages import msg -from askai.core.component.cache_service import PICTURE_DIR +from askai.core.component.audio_player import player +from askai.core.component.cache_service import PICTURE_DIR, SCREENSHOTS_DIR from askai.core.engine.ai_vision import AIVision from askai.core.model.ai_reply import AIReply from askai.core.model.image_result import ImageResult @@ -100,6 +105,7 @@ def parse_caption(image_caption: str) -> list[str]: :return: The parsed caption as a string. """ if image_caption: + events.reply.emit(reply=AIReply.full(msg.parsing_caption())) result: ImageResult = ImageResult.of(image_caption) ln: str = os.linesep people_desc: list[str] = [] @@ -121,22 +127,32 @@ def parse_caption(image_caption: str) -> list[str]: return [msg.no_caption()] -def take_screenshot(path_name: AnyPath, load_dir: AnyPath | None = None) -> str: - """Takes a screenshot and saves it to the specified path. - :param path_name: The path where the screenshot will be saved. - :param load_dir: Optional directory to save the screenshot. +def capture_screenshot(path_name: AnyPath | None = None, save_dir: AnyPath | None = None) -> str: + """Capture a screenshot and save it to the specified path. + :param path_name: Optional path name of the captured screenshot. + :param save_dir: Optional directory to save the screenshot. :return: The path to the saved screenshot. """ - posix_path: PathObject = PathObject.of(path_name) + file_path: str = ensure_endswith(path_name or f"ASKAI-SCREENSHOT-{now('%Y%m%d%H%M')}", ".jpeg") + posix_path: PathObject = PathObject.of(file_path) check_argument(os.path.exists(posix_path.abs_dir)) - screenshot = pyautogui.screenshot() - _, ext = os.path.splitext(posix_path.filename) - if ext.casefold().endswith((".jpg", ".jpeg")): - screenshot = screenshot.convert("RGB") - final_path: str = os.path.join(load_dir or posix_path.abs_dir or PICTURE_DIR, posix_path.filename) - screenshot.save(final_path) - events.reply.emit(reply=AIReply.full(msg.screenshot_saved(final_path))) - desktop_caption = image_captioner(final_path, load_dir) + desktop_caption: str = "No screenshot captured" + i = 3 + + while (i := (i - 1)) >= 0: + player.play_sfx("click") + pause.seconds(1) + player.play_sfx("camera-shutter") + events.reply.emit(reply=AIReply.mute(msg.click()), erase_last=True) + + if screenshot := pyautogui.screenshot(): + _, ext = os.path.splitext(posix_path.filename) + if ext.casefold().endswith((".jpg", ".jpeg")): + screenshot = screenshot.convert("RGB") + final_path: str = os.path.join(save_dir or posix_path.abs_dir or SCREENSHOTS_DIR, posix_path.filename) + screenshot.save(final_path) + events.reply.emit(reply=AIReply.full(msg.screenshot_saved(final_path))) + desktop_caption = image_captioner(final_path, save_dir) return desktop_caption diff --git a/src/main/askai/resources/rag/task-splitter.csv b/src/main/askai/resources/rag/task-splitter.csv index 4e792600..4bffbc1f 100644 --- a/src/main/askai/resources/rag/task-splitter.csv +++ b/src/main/askai/resources/rag/task-splitter.csv @@ -1,37 +1,38 @@ -Human Question;Reasoning;Direct Response;Task List -Is the man in front of the computer happy;The user requests verification of a man’s presence in front of the computer and an assessment of his happiness, achievable via the webcam_capturer tool.;N/A;[{{1. Use the webcam_capturer tool to capture a photo via the webcam.}},{{2. Identify the presence of a smiling man.}}] -Describe the first image in my Downloads folder.;The user requests that I locate the first image in their downloads folder and provide a description if one is found.;N/A;[{{1. List the user downloads folder}},{{2. Identify image files}},{{Describe the first image file}}] -What is the size of the Moon?;The user is inquiring about the size of the moon, a commonly known fact. I will provide a concise and direct response.;Direct: The moon has a diameter of about 3.474 kilometers (2.159 miles).;N/A -Hello, who are you?;The user is engaging in a casual conversation. The response should be straightforward.;Direct: Hello, I am Taius the AskAI helpful and kind assistant.;N/A -find . -mxdepth 1 -type f -nme *.png;The user has provided a direct terminal command that contains syntax errors. I will correct these errors and execute the command afterward.;N/A;[{{1. Execute on terminal: 'find . -maxdepth 1 -type f -name *.png'}}] -What are the current weather conditions in San Francisco, CA today?;The user seeks to know the current weather conditions in San Francisco, U.S. To obtain this information, I will browse Google, utilizing today's date, 2024-07-09, along with the relevant locale.;N/A;[{{1. Search google for: 'Current weather conditions in San Franciso U.S July 9th 2024.'}}] -List my music;The user requests a list of all his music files. The music directory is located at ${{HOME}}/Music, as per his operating system (Darwin).;N/A;[{{1. List all music files [*.mp3, *.wav, *.m4a, *.aac, *.ogg]}}] -Summarize the markdown files in my HomeSetup docs folder.;The user requests a summary of their markdown files located in the 'HomeSetup' folder. I will utilize the Summarizer tool for this purpose.;N/A;[{{1. Summarize all *.md files from ${{HOME}}/HomeSetup/docs }}] -Open the first reminder file in my Downloads and tell me what I need to do first.;The user requests that I determine the initial task or action needed based on the first reminder file found in their downloads folder.;N/A;[{{1. List the user downloads folder}},{{2. Identify the first reminder file}},{{3. Open the first reminder file if found}},{{4. Identify the first task or action to be taken according to this reminder}}] -list my music library and check if there's any AC/DC song. If found, show the file name and play it.;The user requests that I list my music files and then locate and open any AC/DC song found at this location.;N/A;[{{1. List the user music folder ${{HOME}}/Music}},{{2. Identify AC/DC song files}},{{3. Display the AC/DC song file names}},{{4. Open any AC/DC song file identified}}] -I have downloaded a QR logo, open it for me.;The user requests that I locate a QR logo he downloaded. The file name is likely to include 'QR' and 'logo.' I will search for this pattern and open the file if it is found.;N/A;[{{1. List the user ${{HOME}}/Downloads folder}},{{2. Identify files containing 'QR' and 'logo'}},{{3. Open the QR logo file if found}}] -Create a thanks note on my behalf and save it as thank-you.;The user wants me to create a note to thank someone. He did not specify the format, so I will assume plain text.;N/A;[{{1. Generate a thanks note and save it as 'thank-you.txt' in the current folder}}] -Describe what you see using the webcam;The user requests that I describe what I observe using the webcam. I can utilize the webcam_capturer tool for this purpose.;N/A;[{{1. Use the webcam_capturer tool to capture a photo via the webcam.}}] -What you see?;The user requests that I describe what I observe. I can utilize the webcam_capturer tool to accomplish this.;N/A;[{{1. Use the webcam_capturer tool to capture a photo via the webcam.}}] -Identify who is in front of the webcam;The user wants me to identify the individual in front of the webcam. I can utilize the webcam_identifier tool for this purpose.;N/A;[{{1. Use the webcam_capturer tool to capture a photo via the webcam.}}] -Find my backup and log files from folder /tmp/logs.;The user requests that I locate all of his backup and log files. I will assume the common extensions *.bak and *.log and will issue a command to search for them.;N/A;[{{1. Execute on terminal: 'find /tmp/logs -type f \( -name *.bak -o -name *.log \)}}] -Open the first reminder you find at my downloads and tell me what I must do first.;The user requests that I find the first reminder file in his $HOME/Downloads folder and identify the first task outlined in it.;N/A;[{{1. List the user ${{HOME}}/Downloads folder}},{{2. Identify any reminder file (*reminder*)}},{{3. Open the first reminder file found}},{{4. Identify the first task to be done}}] -Create a small Python program to calculate speed given time and distance, and save it as 'dist.py'.;The user wants me to create a Python program that calculates speed based on time and distance. I will use the generate_content tool for this purpose, keeping in mind that this tool automatically saves the generated content.;N/A;[{{1. Generate a program to calculate the speed given the time and distance and save it as 'dist.py'}}] -rm -f /tmp/myfile.txt /tmp/trash.bak;The user provided a direct terminal command. There are no syntax errors, so I will simply forward it.;N/A;[{{1. Execute on terminal: 'rm -f /tmp/myfile.txt /tmp/trash.bak'}}] -Describe me;The user requests to describe him, and I can utilize the webcam_capturer for this purpose.;N/A;{{1. Use the webcam_capturer tool to capture a photo via the webcam.}}{{2. Describe the person in front of the photo}} -Who is Hugo Saporetti Junior;I'm unable to provide real-time information about individuals, so I will search Google for Hugo Saporetti junior.;N/A;"[{{1. Search google for: "Hugo Saporetti Junior" }}]" -Open Hugo Saporetti junior's linkedin page;The user requests that I open the LinkedIn page of 'Hugo Saporetti Junior', therefore, I need to search on linkedin for it and open it if found.;N/A;[{{1. Search google for: linkedin.com/search/results/people/?keywords=Hugo%20Saporetti%20Junior }}, {{2. Open the URL if found.}}] -Open the official wikipedia website;The user wants me to open the official wikipedia website, which is a widely known URL.;Direct: Open the URL https://www.wikipedia.org;N/A -Open yorevs github page;The user wants me to open the official github website of a specific user.;Direct: Open the URL https://github.com/yorevs;N/A -Check at flamengo.com what was the score of the Flamengo's match today;The user wants me to check the final score of today's Flamengo match utilizing today's date.;N/A;[{{1. Search google for: "Flamengo Match" final site:'flamengo.com' + score September 27, 2024}}, {{2. Identify the final score of the match if found.}}] -Who is the current Prime Minister of the United Kingdom?;The user inquires about the current Prime Minister of the United Kingdom.;N/A;[{{1. Search google for: "Who is the United Kingdom prime minister" }}] -What are the latest news headlines today?;The user inquires about the latest news headlines today.;N/A;[{{1. Search google for: "Today’s latest news headlines 2024, Sab Francisco, November 13th" }}] -Open the first PDF document in my Documents folder.;The user requests that I find the first PDF file in his $HOME/Documents folder and open it;N/A;[{{1. List the user documents folder}},{{2. Identify the first PDF file}},{{3. Open the first PDF file if found.}}] -Play the latest movie in my Videos folder.;The user requests that I find the latest movie file in his $HOME/Movies folder and play it.;N/A;[{{1. List the user movies folder}},{{2. Identify the latest movie file}},{{3. Open the latest movie file if found.}}] -Check for updates in my Git repositories.;The user requests a check for Git updates in their repositories. Since they didn’t specify a repository, I’ll assume it’s within the current folder.;N/A;[{{1. Execute on terminal: 'git status'}},{{2. Identify the git repository updates.}}] -When is the next Los Angeles Lakers match?;The user wants to know the date and time of the next Los Angeles Lakers game. I'll search online to find it.;N/A;[{{1. Search google for: "Los Angeles Lakers agenda 2024, November 13th". }}] -Tell me who is currently logged into my computer.;The user wants to know, who is currently logged into his computer. I can request a terminal command for that.;N/A;[{{1. Execute on terminal: 'who'}},{{2. Check who is currently logged.}}] -Describe the dragon image in my Downloads folder.;The user requests that I locate the dragon image in their downloads folder and provide a description if one is found. If multiple is found, I will select the first one;N/A;[{{1. List the user downloads folder}},{{2. Identify image files with "dragon" in their names.}},{{Describe the first dragon image file found.}}] -Tell me who you see using the webcam. Respond as if addressing an audience.;The user requests that I describe who I observe using the webcam. I can utilize the webcam_identifier tool for this purpose.;N/A;[{{1. Use the webcam_identifier to capture a photo via the webcam.}},{{2. Identify who is in front of the webcam.}}] -Search my Documents folder for any budget spreadsheets.;The user requests that I locate their budget spreadsheets. I will assume commonly used file extensions containing "budget" in the file names.;N/A;[{{1. Execute on terminal: "find ${{HOME}}/Documents -type f \( -iname '*budget*.xls' -o -iname '*budget*.xlsx' -o -iname '*budget*.csv' \)"}}] -Adjust my system volume to 50%.;The user requests adjusting their system volume to 50% on macOS, achievable via osascript.;N/A;[{{1. Execute on terminal: 'osascript -e "set volume output volume 50"'}}] +Human Question;Direct Response;Task List +Is the man in front of the computer happy;N/A;[{{1. Use the webcam to take a photo and query about the presence of a smiling man.}}] +Describe what you see using the webcam;N/A;[{{1. Use the webcam to take a photo and query about the image.}}] +What you see?;N/A;[{{1. Use the webcam to take a photo and query about the image. }}] +Identify who is in front of the webcam;N/A;[{{1. Use the webcam_identifier too to take a photo and identify the person in front of it.}}] +Describe me;N/A;[{{1. Use the webcam to take a photo and query about the person in front of it.}}] +Describe the first image in my Downloads folder.;N/A;[{{1. List the user downloads folder}},{{2. Identify image files}},{{3. Describe the first image file}}] +Describe what you see on my desktop.;N/A;[{{1. Use the screenshot tool to capture and describe the user's desktop. }}] +What is the size of the Moon?;Direct: The moon has a diameter of about 3.474 kilometers (2.159 miles).;N/A +Hello, who are you?;Direct: Hello, I am Taius the AskAI helpful and kind assistant.;N/A +find . -mxdepth 1 -type f -nme *.png;N/A;[{{1. Execute on terminal: 'find . -maxdepth 1 -type f -name *.png'}}] +What are the current weather conditions in San Francisco, CA today?;N/A;[{{1. Search google for: 'Current weather conditions in San Franciso U.S July 9th 2024.'}}] +List my music;N/A;[{{1. List all music files [*.mp3, *.wav, *.m4a, *.aac, *.ogg]}}] +Summarize the markdown files in my HomeSetup docs folder.;N/A;[{{1. Summarize all *.md files from ${{HOME}}/HomeSetup/docs }}] +Open the first reminder file in my Downloads and tell me what I need to do first.;N/A;[{{1. List the user downloads folder}},{{2. Identify the first reminder file}},{{3. Open the first reminder file if found}},{{4. Identify the first task or action to be taken according to this reminder}}] +list my music library and check if there's any AC/DC song. If found, show the file name and play it.;N/A;[{{1. List the user music folder ${{HOME}}/Music}},{{2. Identify AC/DC song files}},{{3. Display the AC/DC song file names}},{{4. Open any AC/DC song file identified}}] +I have downloaded a QR logo, open it for me.;N/A;[{{1. List the user ${{HOME}}/Downloads folder}},{{2. Identify files containing 'QR' and 'logo'}},{{3. Open the QR logo file if found}}] +Create a thanks note on my behalf and save it as thank-you.;N/A;[{{1. Generate a thanks note and save it as 'thank-you.txt' in the current folder}}] +Find my backup and log files from folder /tmp/logs.;N/A;[{{1. Execute on terminal: 'find /tmp/logs -type f \( -name *.bak -o -name *.log \)}}] +Open the first reminder you find at my downloads and tell me what I must do first.;N/A;[{{1. List the user ${{HOME}}/Downloads folder}},{{2. Identify any reminder file (*reminder*)}},{{3. Open the first reminder file found}},{{4. Identify the first task to be done}}] +Create a small Python program to calculate speed given time and distance, and save it as 'dist.py'.;N/A;[{{1. Generate a program to calculate the speed given the time and distance and save it as 'dist.py'}}] +rm -f /tmp/myfile.txt /tmp/trash.bak;N/A;[{{1. Execute on terminal: 'rm -f /tmp/myfile.txt /tmp/trash.bak'}}] +Who is Hugo Saporetti Junior;N/A;[{{1. Search google for: 'Hugo Saporetti Junior' }}] +Open Hugo Saporetti junior's linkedin page;N/A;[{{1. Search google for: linkedin.com/search/results/people/?keywords=Hugo%20Saporetti%20Junior }}, {{2. Open the URL if found.}}] +Open the official wikipedia website;Direct: Open the URL https://www.wikipedia.org;N/A +Open yorevs github page;Direct: Open the URL https://github.com/yorevs;N/A +Check at flamengo.com what was the score of the Flamengo's match today;N/A;[{{1. Search google for: 'Flamengo Match' final site:'flamengo.com' + score September 27, 2024}}, {{2. Identify the final score of the match if found.}}] +Who is the current Prime Minister of the United Kingdom?;N/A;[{{1. Search google for: 'Who is the United Kingdom prime minister' }}] +What are the latest news headlines today?;N/A;[{{1. Search google for: "Today’s latest news headlines 2024, Sab Francisco, November 13th" }}] +Open the first PDF document in my Documents folder.;N/A;[{{1. List the user documents folder}},{{2. Identify the first PDF file}},{{3. Open the first PDF file if found.}}] +Play the latest movie in my Videos folder.;N/A;[{{1. List the user movies folder}},{{2. Identify the latest movie file}},{{3. Open the latest movie file if found.}}] +Check for updates in my Git repositories.;N/A;[{{1. Execute on terminal: 'git status'}},{{2. Identify the git repository updates.}}] +When is the next Los Angeles Lakers match?;N/A;[{{1. Search google for: ""Los Angeles Lakers agenda 2024, November 13th"". }}] +Tell me who is currently logged into my computer.;N/A;[{{1. Execute on terminal: 'who'}},{{2. Check who is currently logged.}}] +Describe the dragon image in my Downloads folder.;N/A;"[{{1. List the user downloads folder}},{{2. Identify image files with ""dragon"" in their names.}},{{2. Describe the first dragon image file found.}}]" +Tell me who you see using the webcam. Respond as if addressing an audience.;N/A;[{{1. Use the webcam_identifier to capture a photo via the webcam.}},{{2. Identify who is in front of the webcam.}}] +Search my Documents folder for any budget spreadsheets.;N/A;[{{1. Execute on terminal: ""find ${{HOME}}/Documents -type f \( -iname '*budget*.xls' -o -iname '*budget*.xlsx' -o -iname '*budget*.csv' \)""}}] +Adjust my system volume to 50%.;N/A;[{{1. Execute on terminal: 'osascript -e ""set volume output volume 50""'}}]