Skip to content

agent

dandy.processor.agent.agent

Agent dataclass

Bases: BaseProcessor, LlmServiceMixin, HttpServiceMixin, IntelServiceMixin, VisionProcessorMixin

plan_time_limit_seconds = settings.DEFAULT_AGENT_PLAN_TIME_LIMIT_SECONDS class-attribute instance-attribute

plan_task_count_limit = settings.DEFAULT_AGENT_PLAN_TASK_COUNT_LIMIT class-attribute instance-attribute

processors = (Bot,) class-attribute instance-attribute

services = AgentService() class-attribute

__init_subclass__

Source code in dandy/processor/agent/agent.py
def __init_subclass__(cls, **kwargs):
    if cls.processors is None or len(cls.processors) == 0:
        message = f'{cls.__name__} must have a sequence of "BaseProcessor" sub classes defined on the "processors" class attribute.'
        raise AgentCriticalException(message)

    if cls._processors_strategy_class is None:
        message = f'{cls.__name__} must have a "BaseProcessorsStrategy" sub class defined on the "_processors_strategy_class" class attribute.'
        raise AgentCriticalException(message)

__post_init__

Source code in dandy/processor/agent/agent.py
def __post_init__(self):
    if self._processors_strategy is None:
        self._processors_strategy = self._processors_strategy_class(
            self.processors
        )

process

Source code in dandy/processor/agent/agent.py
def process(
        self,
        prompt: PromptOrStr,
        intel_class: Type[IntelType] | None = None,
        intel_object: IntelType | None = None,
        images: List[str] | None = None,
        image_files: List[str | Path] | None = None,
        include_fields: IncEx | None = None,
        exclude_fields: IncEx | None = None,
        postfix_system_prompt: PromptOrStrOrNone = None,
        message_history: MessageHistory | None = None,
) -> IntelType:

    recorder_event_id = self._recorder_event_id

    recorder_add_llm_agent_create_plan_event(
        prompt,
        self._processors_strategy,
        recorder_event_id
    )

    plan = self._create_plan(prompt)

    recorder_add_llm_agent_finished_creating_plan_event(
        plan,
        recorder_event_id
    )

    recorder_add_llm_agent_running_plan_event(
        plan,
        recorder_event_id
    )

    while plan.is_incomplete:
        if plan.has_exceeded_time_limit:
            message = f'{self.__class__.__name__} exceeded the time limit of {self.plan_time_limit_seconds} seconds running a plan.'
            raise AgentOverThoughtRecoverableException(message)

        task = plan.active_task

        recorder_add_llm_agent_start_task_event(
            task,
            self._processors_strategy,
            recorder_event_id
        )

        resource = self._processors_strategy.get_processor_from_key(task.processors_key)

        updated_task = resource.use(
            prompt=agent_do_task_prompt(task),
            intel_object=task,
            include_fields={'actual_result'}
        )

        task.actual_result = updated_task.actual_result
        plan.set_active_task_complete()

        recorder_add_llm_agent_completed_task_event(
            task,
            self._processors_strategy,
            recorder_event_id
        )

    recorder_add_llm_agent_done_executing_plan_event(
        plan,
        recorder_event_id
    )

    recorder_add_llm_agent_processing_final_result_event(
        plan,
        recorder_event_id
    )

    if postfix_system_prompt is None:
        postfix_system_prompt = Prompt()

    postfix_system_prompt.text(f'Use the results of the below simulated plan to accomplish the user request:')
    postfix_system_prompt.line_break()
    postfix_system_prompt.prompt(plan.to_prompt())

    return self.llm.prompt_to_intel(
        prompt=prompt,
        intel_class=intel_class,
        intel_object=intel_object,
        images=images,
        image_files=image_files,
        include_fields=include_fields,
        exclude_fields=exclude_fields,
        postfix_system_prompt=postfix_system_prompt,
        message_history=message_history,
    )