Files
Auto-GPT/autogpt/models/agent_actions.py
Reinier van der Leer 3fe2246468 Agent loop v2: Prompting improvements & WIP planning (#5077)
* Add categories to command registry

* Fix tests

* Clean up prompt generation

* Rename Performance Evaluations to Best Practices
* Move specification of response format from system prompt to Agent.construct_base_prompt
* Clean up PromptGenerator class

* Add debug logging to AIConfig autogeneration

* Clarify prompting and add support for multiple thought processes to Agent

* WIP: PlanningAgent

* Disable message history by default on BaseAgent

* Add CommandOutput and ThoughtProcessOutput type aliases

* Fix interrupts in main.py

* Use custom exceptions and clean up exception/error handling

* Remove duplicate agent_history.py

* Update PlanningAgent from upstream

* WIP: Support for dynamic in-prompt context

* WIP: response formats for PlanningAgent three-stage cycle

* Remove browsing overlay & separate browsing from extraction code

* Fix human feedback

* Fix tests

* Include history in Agent prompt generation

* Code improvements in agent.py

* Add ask_user command and revise system prompt
2023-08-19 17:44:50 +02:00

97 lines
2.5 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Iterator, Literal, Optional
@dataclass
class Action:
name: str
args: dict[str, Any]
reasoning: str
def format_call(self) -> str:
return f"{self.name}({', '.join([f'{a}={repr(v)}' for a, v in self.args.items()])})"
@dataclass
class ActionSuccessResult:
results: Any
status: Literal["success"] = "success"
def __str__(self) -> str:
return f"Action succeeded and returned: `{self.results}`"
@dataclass
class ActionErrorResult:
reason: str
error: Optional[Exception] = None
status: Literal["error"] = "error"
def __str__(self) -> str:
return f"Action failed: `{self.reason}`"
@dataclass
class ActionInterruptedByHuman:
feedback: str
status: Literal["interrupted_by_human"] = "interrupted_by_human"
def __str__(self) -> str:
return f'The user interrupted the action with the following feedback: "{self.feedback}"'
ActionResult = ActionSuccessResult | ActionErrorResult | ActionInterruptedByHuman
class ActionHistory:
"""Utility container for an action history"""
@dataclass
class CycleRecord:
action: Action | None
result: ActionResult | None
cursor: int
cycles: list[CycleRecord]
def __init__(self, cycles: list[CycleRecord] = []):
self.cycles = cycles
self.cursor = len(self.cycles)
@property
def current_record(self) -> CycleRecord | None:
if self.cursor == len(self):
return None
return self[self.cursor]
def __getitem__(self, key: int) -> CycleRecord:
return self.cycles[key]
def __iter__(self) -> Iterator[CycleRecord]:
return iter(self.cycles)
def __len__(self) -> int:
return len(self.cycles)
def __bool__(self) -> bool:
return len(self.cycles) > 0
def register_action(self, action: Action) -> None:
if not self.current_record:
self.cycles.append(self.CycleRecord(None, None))
assert self.current_record
elif self.current_record.action:
raise ValueError("Action for current cycle already set")
self.current_record.action = action
def register_result(self, result: ActionResult) -> None:
if not self.current_record:
raise RuntimeError("Cannot register result for cycle without action")
elif self.current_record.result:
raise ValueError("Result for current cycle already set")
self.current_record.result = result