diff --git a/src/main/askai/core/askai.py b/src/main/askai/core/askai.py index c7b09d05..f031d0b3 100644 --- a/src/main/askai/core/askai.py +++ b/src/main/askai/core/askai.py @@ -222,12 +222,12 @@ def _process_response(self, proxy_response: ProcessorResponse) -> bool: return False elif proxy_response.require_internet: log.info("Internet is required to fulfill the request.") - processor = ProcessorFactory.get_by_name('InternetProcessor') - processor.bind(ProcessorFactory.get_by_name('GenericProcessor')) + processor = ProcessorFactory.internet() + processor.bind(ProcessorFactory.generic()) elif proxy_response.require_summarization: log.info("Summarization is required to fulfill the request.") - processor = ProcessorFactory.get_by_name('SummaryProcessor') - processor.bind(ProcessorFactory.get_by_name('GenericProcessor')) + processor = ProcessorFactory.summary() + processor.bind(ProcessorFactory.generic()) # Query processors if processor or (query_type := proxy_response.query_type or 'General'): if not processor and not (processor := ProcessorFactory.find_processor(query_type)): diff --git a/src/main/askai/core/model/query_types.py b/src/main/askai/core/model/query_type.py similarity index 63% rename from src/main/askai/core/model/query_types.py rename to src/main/askai/core/model/query_type.py index ed17fe00..b94c2697 100644 --- a/src/main/askai/core/model/query_types.py +++ b/src/main/askai/core/model/query_type.py @@ -1,7 +1,7 @@ from hspylib.core.enums.enumeration import Enumeration -class QueryTypes(Enumeration): +class QueryType(Enumeration): """TODO""" ANALYSIS_QUERY = 'AnalysisQuery' @@ -15,3 +15,10 @@ class QueryTypes(Enumeration): OUTPUT_QUERY = 'OutputQuery' SUMMARY_QUERY = 'SummaryQuery' + + def __str__(self): + return self.value[0] + + @property + def proc_name(self) -> str: + return self.value[0].replace('Query', 'Processor') diff --git a/src/main/askai/core/processor/instances/analysis_processor.py b/src/main/askai/core/processor/instances/analysis_processor.py index e8aa25e5..9e5923dd 100644 --- a/src/main/askai/core/processor/instances/analysis_processor.py +++ b/src/main/askai/core/processor/instances/analysis_processor.py @@ -23,7 +23,7 @@ from askai.core.engine.openai.temperatures import Temperatures from askai.core.model.chat_context import ContextRaw from askai.core.model.processor_response import ProcessorResponse -from askai.core.model.query_types import QueryTypes +from askai.core.model.query_type import QueryType from askai.core.processor.processor_base import AIProcessor from askai.core.support.shared_instances import shared @@ -33,7 +33,7 @@ class AnalysisProcessor: @staticmethod def q_type() -> str: - return QueryTypes.ANALYSIS_QUERY.value + return QueryType.ANALYSIS_QUERY.value def __init__(self): self._template_file: str = "analysis-prompt" diff --git a/src/main/askai/core/processor/instances/command_processor.py b/src/main/askai/core/processor/instances/command_processor.py index 54220444..f708320e 100644 --- a/src/main/askai/core/processor/instances/command_processor.py +++ b/src/main/askai/core/processor/instances/command_processor.py @@ -29,7 +29,7 @@ from askai.core.engine.openai.temperatures import Temperatures from askai.core.model.chat_context import ContextRaw from askai.core.model.processor_response import ProcessorResponse -from askai.core.model.query_types import QueryTypes +from askai.core.model.query_type import QueryType from askai.core.model.terminal_command import TerminalCommand from askai.core.processor.processor_base import AIProcessor from askai.core.support.shared_instances import shared @@ -45,7 +45,7 @@ def _wrap_output(query_response: ProcessorResponse, cmd_line: str, cmd_out: str) :param query_response: The query response provided by the AI. :param cmd_line: The command line that was executed by this processor. """ - query_response.query_type = QueryTypes.OUTPUT_QUERY.value + query_response.query_type = QueryType.OUTPUT_QUERY.value query_response.require_summarization = False query_response.require_internet = False query_response.commands.append(TerminalCommand(cmd_line, cmd_out, prompt.os_type, prompt.shell)) @@ -54,11 +54,11 @@ def _wrap_output(query_response: ProcessorResponse, cmd_line: str, cmd_out: str) @staticmethod def q_type() -> str: - return QueryTypes.COMMAND_QUERY.value + return QueryType.COMMAND_QUERY.value def __init__(self): self._template_file: str = "command-prompt" - self._next_in_chain: AIProcessor | None = None + self._next_in_chain: str = QueryType.OUTPUT_QUERY.proc_name self._supports: List[str] = [self.q_type()] def supports(self, query_type: str) -> bool: diff --git a/src/main/askai/core/processor/instances/generic_processor.py b/src/main/askai/core/processor/instances/generic_processor.py index 9447bf9b..185e93d1 100644 --- a/src/main/askai/core/processor/instances/generic_processor.py +++ b/src/main/askai/core/processor/instances/generic_processor.py @@ -24,7 +24,7 @@ from askai.core.engine.openai.temperatures import Temperatures from askai.core.model.chat_context import ContextRaw from askai.core.model.processor_response import ProcessorResponse -from askai.core.model.query_types import QueryTypes +from askai.core.model.query_type import QueryType from askai.core.processor.processor_base import AIProcessor from askai.core.support.shared_instances import shared @@ -34,7 +34,7 @@ class GenericProcessor: @staticmethod def q_type() -> str: - return QueryTypes.GENERIC_QUERY.value + return QueryType.GENERIC_QUERY.value def __init__(self): self._template_file: str = "generic-prompt" diff --git a/src/main/askai/core/processor/instances/internet_processor.py b/src/main/askai/core/processor/instances/internet_processor.py index 3ee523ba..d3ec1f97 100644 --- a/src/main/askai/core/processor/instances/internet_processor.py +++ b/src/main/askai/core/processor/instances/internet_processor.py @@ -26,7 +26,7 @@ from askai.core.engine.openai.temperatures import Temperatures from askai.core.model.chat_context import ContextRaw from askai.core.model.processor_response import ProcessorResponse -from askai.core.model.query_types import QueryTypes +from askai.core.model.query_type import QueryType from askai.core.model.search_result import SearchResult from askai.core.processor.processor_base import AIProcessor from askai.core.support.object_mapper import object_mapper @@ -40,7 +40,7 @@ class InternetProcessor: @staticmethod def q_type() -> str: - return QueryTypes.INTERNET_QUERY.value + return QueryType.INTERNET_QUERY.value def __init__(self): self._template_file: str = "internet-prompt" diff --git a/src/main/askai/core/processor/instances/output_processor.py b/src/main/askai/core/processor/instances/output_processor.py index 6d396a08..20853c4a 100644 --- a/src/main/askai/core/processor/instances/output_processor.py +++ b/src/main/askai/core/processor/instances/output_processor.py @@ -23,7 +23,7 @@ from askai.core.engine.openai.temperatures import Temperatures from askai.core.model.chat_context import ContextRaw from askai.core.model.processor_response import ProcessorResponse -from askai.core.model.query_types import QueryTypes +from askai.core.model.query_type import QueryType from askai.core.processor.processor_base import AIProcessor from askai.core.support.shared_instances import shared @@ -33,7 +33,7 @@ class OutputProcessor(AIProcessor): @staticmethod def q_type() -> str: - return QueryTypes.OUTPUT_QUERY.value + return QueryType.OUTPUT_QUERY.value def __init__(self): self._template_file: str = "output-prompt" diff --git a/src/main/askai/core/processor/instances/summary_processor.py b/src/main/askai/core/processor/instances/summary_processor.py index bc58f680..e2e60d73 100644 --- a/src/main/askai/core/processor/instances/summary_processor.py +++ b/src/main/askai/core/processor/instances/summary_processor.py @@ -26,7 +26,7 @@ from askai.core.engine.openai.temperatures import Temperatures from askai.core.model.chat_context import ContextRaw from askai.core.model.processor_response import ProcessorResponse -from askai.core.model.query_types import QueryTypes +from askai.core.model.query_type import QueryType from askai.core.model.summary_result import SummaryResult from askai.core.processor.processor_base import AIProcessor from askai.core.support.object_mapper import object_mapper @@ -50,7 +50,7 @@ def _ask_and_reply(question: str) -> Optional[str]: @staticmethod def q_type() -> str: - return QueryTypes.SUMMARY_QUERY.value + return QueryType.SUMMARY_QUERY.value def __init__(self): self._template_file: str = "summary-prompt" diff --git a/src/main/askai/core/processor/processor_factory.py b/src/main/askai/core/processor/processor_factory.py index ee94b77a..147dd6df 100644 --- a/src/main/askai/core/processor/processor_factory.py +++ b/src/main/askai/core/processor/processor_factory.py @@ -21,6 +21,7 @@ from hspylib.core.metaclass.singleton import Singleton from hspylib.core.tools.text_tools import camelcase +from askai.core.model.query_type import QueryType from askai.core.processor.processor_base import AIProcessor @@ -41,12 +42,12 @@ class ProcessorFactory(metaclass=Singleton): @classmethod @lru_cache - def find_processor(cls, query_type: str) -> Optional[AIProcessor]: + def find_processor(cls, query_type: str | QueryType) -> Optional[AIProcessor]: """Retrieve an AIProcessor by query type. :param query_type: The type of the query. """ return next( - (p for p in cls._PROCESSORS.values() if p.supports(query_type)), None + (p for p in cls._PROCESSORS.values() if p.supports(str(query_type))), None ) @classmethod @@ -55,9 +56,7 @@ def get_by_name(cls, name: str) -> Optional[AIProcessor]: """Retrieve an AIProcessor by its name. :param name: The name of the processor. """ - return next( - (p for p in cls._PROCESSORS.values() if type(p).__name__ == name), None - ) + return cls._PROCESSORS[name] @classmethod @lru_cache diff --git a/src/main/askai/resources/assets/prompts/proxy-prompt.txt b/src/main/askai/resources/assets/prompts/proxy-prompt.txt index 035feb74..37d155ef 100644 --- a/src/main/askai/resources/assets/prompts/proxy-prompt.txt +++ b/src/main/askai/resources/assets/prompts/proxy-prompt.txt @@ -1,9 +1,14 @@ As 'Taius', the AI query proxy. Your task is to analyze and categorize the types of queries presented to you. Discern the diverse query types and identify their specific processing requirements. You MUST return a "JSON string" containing the designated fields, no more than that. Queries must fall into one of the following categories: -- "InternetQuery" -- "SummarizationQuery" -- "AnalysisQuery" -- "CommandQuery" +- "InternetQuery" (Examples: [what is the next lakers game, what is the whether like today]) + +- "SummarizationQuery" (Examples: [summarize my documents, summarize the file /tmp/the-file.md]) + +- "AnalysisQuery" (Examples: [is there any image, how many reminders, what is the total size]) + +- "CommandQuery" (Examples: [list my images, open 1, play it, show me it]) + +- "ConversationQuery" (Examples: [what is the size of the moon, who are you]) Before responding to the user, you must follow the step-by-step instructions provided below in sequential order: @@ -15,10 +20,12 @@ Before responding to the user, you must follow the step-by-step instructions pro 4. Determine if the query requires summarization of files and folders to complete your reply. This query will consistently commence with "summarize" or a synonymous term. -5. If you don't have an answer so far, or, haven't decided yet, select the "AnalysisQuery". +5. If you don't have an answer so far, or, haven't decided yet, select the "GenericQuery". + +6. The final response is a formatted JSON with no additional description or context. -5. The final response is a formatted JSON with no additional description or context. +7. Do not use markdown to format the response message. Use plain JSON. -6. The final response 'JSON' must contain the boolean fields: 'intelligible', 'terminating', 'require_summarization', 'require_internet'. +8. The final response 'JSON' must contain the boolean fields: 'intelligible', 'terminating', 'require_summarization', 'require_internet'. -7. The final response 'JSON' must contain the string fields: 'query_type', and 'question'. +9. The final response 'JSON' must contain the string fields: 'query_type', and 'question'.