-
Notifications
You must be signed in to change notification settings - Fork 44k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(agent/core): Add Anthropic Claude 3 support #7085
Changes from 27 commits
76e9fd1
7ecc459
95bbda0
001fe75
8beaedd
d5eb79f
0594653
651c99d
2da125d
9d38dbd
70c97ca
dcd1685
2aa4ca5
a60854e
1ae07a5
92ff5a4
933ec93
72d0248
e492258
d5d8bfc
a62ec0f
6503b9e
e65b57f
b32778b
fd067a0
c10fafa
338986d
32fe727
d2a9be0
2e197eb
207957b
94985ef
1ca8d20
bb4f8a2
0f778e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -69,16 +69,7 @@ | |||||||||||||
"{best_practices}" | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
DEFAULT_CHOOSE_ACTION_INSTRUCTION: str = ( | ||||||||||||||
"Determine exactly one command to use next based on the given goals " | ||||||||||||||
"and the progress you have made so far, " | ||||||||||||||
"and respond using the JSON schema specified previously:" | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
body_template: str = UserConfigurable(default=DEFAULT_BODY_TEMPLATE) | ||||||||||||||
choose_action_instruction: str = UserConfigurable( | ||||||||||||||
default=DEFAULT_CHOOSE_ACTION_INSTRUCTION | ||||||||||||||
) | ||||||||||||||
use_functions_api: bool = UserConfigurable(default=False) | ||||||||||||||
|
||||||||||||||
######### | ||||||||||||||
|
@@ -122,33 +113,40 @@ | |||||||||||||
1. System prompt | ||||||||||||||
3. `cycle_instruction` | ||||||||||||||
""" | ||||||||||||||
system_prompt = self.build_system_prompt( | ||||||||||||||
system_prompt, response_prefill = self.build_system_prompt( | ||||||||||||||
ai_profile=ai_profile, | ||||||||||||||
ai_directives=ai_directives, | ||||||||||||||
commands=commands, | ||||||||||||||
include_os_info=include_os_info, | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
final_instruction_msg = ChatMessage.user(self.config.choose_action_instruction) | ||||||||||||||
|
||||||||||||||
prompt = ChatPrompt( | ||||||||||||||
return ChatPrompt( | ||||||||||||||
messages=[ | ||||||||||||||
ChatMessage.system(system_prompt), | ||||||||||||||
ChatMessage.user(f'"""{task}"""'), | ||||||||||||||
*messages, | ||||||||||||||
final_instruction_msg, | ||||||||||||||
], | ||||||||||||||
prefill_response=response_prefill, | ||||||||||||||
functions=commands if self.config.use_functions_api else [], | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
return prompt | ||||||||||||||
|
||||||||||||||
def build_system_prompt( | ||||||||||||||
self, | ||||||||||||||
ai_profile: AIProfile, | ||||||||||||||
ai_directives: AIDirectives, | ||||||||||||||
commands: list[CompletionModelFunction], | ||||||||||||||
include_os_info: bool, | ||||||||||||||
) -> str: | ||||||||||||||
) -> tuple[str, str]: | ||||||||||||||
""" | ||||||||||||||
Builds the system prompt. | ||||||||||||||
|
||||||||||||||
Returns: | ||||||||||||||
str: The system prompt body | ||||||||||||||
str: The desired start for the LLM's response; used to steer the output | ||||||||||||||
""" | ||||||||||||||
response_fmt_instruction, response_prefill = self.response_format_instruction( | ||||||||||||||
self.config.use_functions_api | ||||||||||||||
) | ||||||||||||||
system_prompt_parts = ( | ||||||||||||||
self._generate_intro_prompt(ai_profile) | ||||||||||||||
+ (self._generate_os_info() if include_os_info else []) | ||||||||||||||
|
@@ -169,16 +167,16 @@ | |||||||||||||
" in the next message. Your job is to complete the task while following" | ||||||||||||||
" your directives as given above, and terminate when your task is done." | ||||||||||||||
] | ||||||||||||||
+ [ | ||||||||||||||
"## RESPONSE FORMAT\n" | ||||||||||||||
+ self.response_format_instruction(self.config.use_functions_api) | ||||||||||||||
] | ||||||||||||||
+ ["## RESPONSE FORMAT\n" + response_fmt_instruction] | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
# Join non-empty parts together into paragraph format | ||||||||||||||
return "\n\n".join(filter(None, system_prompt_parts)).strip("\n") | ||||||||||||||
return ( | ||||||||||||||
"\n\n".join(filter(None, system_prompt_parts)).strip("\n"), | ||||||||||||||
response_prefill, | ||||||||||||||
) | ||||||||||||||
Comment on lines
+187
to
+189
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: The method
Suggested change
|
||||||||||||||
|
||||||||||||||
def response_format_instruction(self, use_functions_api: bool) -> str: | ||||||||||||||
def response_format_instruction(self, use_functions_api: bool) -> tuple[str, str]: | ||||||||||||||
response_schema = self.response_schema.copy(deep=True) | ||||||||||||||
if ( | ||||||||||||||
use_functions_api | ||||||||||||||
|
@@ -193,11 +191,15 @@ | |||||||||||||
"\n", | ||||||||||||||
response_schema.to_typescript_object_interface(_RESPONSE_INTERFACE_NAME), | ||||||||||||||
) | ||||||||||||||
response_prefill = f'{{\n "{list(response_schema.properties.keys())[0]}":' | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: The method
Suggested change
|
||||||||||||||
|
||||||||||||||
return ( | ||||||||||||||
f"YOU MUST ALWAYS RESPOND WITH A JSON OBJECT OF THE FOLLOWING TYPE:\n" | ||||||||||||||
f"{response_format}" | ||||||||||||||
+ ("\n\nYOU MUST ALSO INVOKE A TOOL!" if use_functions_api else "") | ||||||||||||||
( | ||||||||||||||
f"YOU MUST ALWAYS RESPOND WITH A JSON OBJECT OF THE FOLLOWING TYPE:\n" | ||||||||||||||
f"{response_format}" | ||||||||||||||
+ ("\n\nYOU MUST ALSO INVOKE A TOOL!" if use_functions_api else "") | ||||||||||||||
), | ||||||||||||||
response_prefill, | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
def _generate_intro_prompt(self, ai_profile: AIProfile) -> list[str]: | ||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -34,7 +34,6 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from autogpt.app.utils import is_port_free | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from autogpt.config import Config | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from autogpt.core.resource.model_providers import ChatModelProvider, ModelProviderBudget | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from autogpt.core.resource.model_providers.openai import OpenAIProvider | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from autogpt.file_storage import FileStorage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from autogpt.models.action_history import ActionErrorResult, ActionSuccessResult | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from autogpt.utils.exceptions import AgentFinished | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -464,20 +463,18 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if task.additional_input and (user_id := task.additional_input.get("user_id")): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_extra_request_headers["AutoGPT-UserID"] = user_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
task_llm_provider = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if isinstance(self.llm_provider, OpenAIProvider): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
settings = self.llm_provider._settings.copy() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
settings.budget = task_llm_budget | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
settings.configuration = task_llm_provider_config # type: ignore | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
task_llm_provider = OpenAIProvider( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
settings=settings, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
logger=logger.getChild(f"Task-{task.task_id}_OpenAIProvider"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if task_llm_provider and task_llm_provider._budget: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self._task_budgets[task.task_id] = task_llm_provider._budget | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
settings = self.llm_provider._settings.copy() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
settings.budget = task_llm_budget | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
settings.configuration = task_llm_provider_config | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
task_llm_provider = self.llm_provider.__class__( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
settings=settings, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
logger=logger.getChild( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f"Task-{task.task_id}_{self.llm_provider.__class__.__name__}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self._task_budgets[task.task_id] = task_llm_provider._budget # type: ignore | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return task_llm_provider or self.llm_provider | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return task_llm_provider | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+466
to
+477
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: Refactor the method
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def task_agent_id(task_id: str | int) -> str: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -35,7 +35,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ConfigBuilder, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
assert_config_has_openai_api_key, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from autogpt.core.resource.model_providers.openai import OpenAIProvider | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from autogpt.core.resource.model_providers import MultiProvider | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from autogpt.core.runner.client_lib.utils import coroutine | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from autogpt.file_storage import FileStorageBackendName, get_storage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from autogpt.logs.config import configure_logging | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -123,7 +123,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
skip_news=skip_news, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llm_provider = _configure_openai_provider(config) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llm_provider = _configure_llm_provider(config) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
logger = logging.getLogger(__name__) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -399,7 +399,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
allow_downloads=allow_downloads, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llm_provider = _configure_openai_provider(config) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llm_provider = _configure_llm_provider(config) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Set up & start server | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
database = AgentDB( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -421,24 +421,12 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def _configure_openai_provider(config: Config) -> OpenAIProvider: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Create a configured OpenAIProvider object. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
config: The program's configuration. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
A configured OpenAIProvider object. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if config.openai_credentials is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise RuntimeError("OpenAI key is not configured") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
openai_settings = OpenAIProvider.default_settings.copy(deep=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
openai_settings.credentials = config.openai_credentials | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return OpenAIProvider( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
settings=openai_settings, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
logger=logging.getLogger("OpenAIProvider"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def _configure_llm_provider(config: Config) -> MultiProvider: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
multi_provider = MultiProvider() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for model in [config.smart_llm, config.fast_llm]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Ensure model providers for configured LLMs are available | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
multi_provider.get_model_provider(model) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return multi_provider | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+424
to
+429
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: The function
Suggested change
Comment on lines
+424
to
+429
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: The method
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def _get_cycle_budget(continuous_mode: bool, continuous_limit: int) -> int | float: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: The conditional logic for setting
use_functions_api
in theOneShotAgentPromptStrategy
configuration is based on the provider name being "anthropic". This is a string comparison that should be case-insensitive to avoid potential bugs due to case variations. [best practice]