-
Notifications
You must be signed in to change notification settings - Fork 45.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make Auto-GPT aware of its running cost (#762)
* Implemented running cost counter for chat completions This data is known to the AI as additional system context, and is printed out to the user * Added comments to api_manager.py * Added user-defined API budget. The user is now prompted if they want to give the AI a budget for API calls. If they enter nothing, there is no monetary limit, but if they define a budget then the AI will be told to shut down gracefully once it has come within 1 cent of its limit, and to shut down immediately once it has exceeded its limit. If a budget is defined, Auto-GPT is always aware of how much it was given and how much remains to be spent. * Chat completion calls are now done through api_manager. Total running cost is printed. * Implemented api budget setting and tracking User can now configure a maximum api budget, and the AI is aware of that and its remaining budget. The AI is instructed to shut down when exceeding the budget. * Update autogpt/api_manager.py Change "per token" to "per 1000 tokens" in a comment on the api cost Co-authored-by: Rob Luke <[email protected]> * Fixed lint errors * Include embedding costs * Add embedding completion cost * lint * Added 'requires_api_key' decorator to test_commands.py, switched to a valid chat completions model * Refactor API manager, add debug mode, and add tests - Extract model costs to to avoid duplication - Add debug mode parameter to ApiManager class - Move debug mode configuration to - Log AI response and budget messages in debug mode - Implement 'test_api_manager.py' * Fixed test_setup failing. An extra user input is needed for api budget * Linting --------- Co-authored-by: Rob Luke <[email protected]> Co-authored-by: Nicholas Tindle <[email protected]>
- Loading branch information
1 parent
bf895eb
commit d6ef9d1
Showing
11 changed files
with
401 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
from typing import List | ||
|
||
import openai | ||
|
||
from autogpt.config import Config | ||
from autogpt.logs import logger | ||
from autogpt.modelsinfo import COSTS | ||
|
||
cfg = Config() | ||
openai.api_key = cfg.openai_api_key | ||
print_total_cost = cfg.debug_mode | ||
|
||
|
||
class ApiManager: | ||
def __init__(self, debug=False): | ||
self.total_prompt_tokens = 0 | ||
self.total_completion_tokens = 0 | ||
self.total_cost = 0 | ||
self.total_budget = 0 | ||
self.debug = debug | ||
|
||
def reset(self): | ||
self.total_prompt_tokens = 0 | ||
self.total_completion_tokens = 0 | ||
self.total_cost = 0 | ||
self.total_budget = 0.0 | ||
|
||
def create_chat_completion( | ||
self, | ||
messages: list, # type: ignore | ||
model: str | None = None, | ||
temperature: float = cfg.temperature, | ||
max_tokens: int | None = None, | ||
deployment_id=None, | ||
) -> str: | ||
""" | ||
Create a chat completion and update the cost. | ||
Args: | ||
messages (list): The list of messages to send to the API. | ||
model (str): The model to use for the API call. | ||
temperature (float): The temperature to use for the API call. | ||
max_tokens (int): The maximum number of tokens for the API call. | ||
Returns: | ||
str: The AI's response. | ||
""" | ||
if deployment_id is not None: | ||
response = openai.ChatCompletion.create( | ||
deployment_id=deployment_id, | ||
model=model, | ||
messages=messages, | ||
temperature=temperature, | ||
max_tokens=max_tokens, | ||
) | ||
else: | ||
response = openai.ChatCompletion.create( | ||
model=model, | ||
messages=messages, | ||
temperature=temperature, | ||
max_tokens=max_tokens, | ||
) | ||
if self.debug: | ||
logger.debug(f"Response: {response}") | ||
prompt_tokens = response.usage.prompt_tokens | ||
completion_tokens = response.usage.completion_tokens | ||
self.update_cost(prompt_tokens, completion_tokens, model) | ||
return response | ||
|
||
def embedding_create( | ||
self, | ||
text_list: List[str], | ||
model: str = "text-embedding-ada-002", | ||
) -> List[float]: | ||
""" | ||
Create an embedding for the given input text using the specified model. | ||
Args: | ||
text_list (List[str]): Input text for which the embedding is to be created. | ||
model (str, optional): The model to use for generating the embedding. | ||
Returns: | ||
List[float]: The generated embedding as a list of float values. | ||
""" | ||
if cfg.use_azure: | ||
response = openai.Embedding.create( | ||
input=text_list, | ||
engine=cfg.get_azure_deployment_id_for_model(model), | ||
) | ||
else: | ||
response = openai.Embedding.create(input=text_list, model=model) | ||
|
||
self.update_cost(response.usage.prompt_tokens, 0, model) | ||
return response["data"][0]["embedding"] | ||
|
||
def update_cost(self, prompt_tokens, completion_tokens, model): | ||
""" | ||
Update the total cost, prompt tokens, and completion tokens. | ||
Args: | ||
prompt_tokens (int): The number of tokens used in the prompt. | ||
completion_tokens (int): The number of tokens used in the completion. | ||
model (str): The model used for the API call. | ||
""" | ||
self.total_prompt_tokens += prompt_tokens | ||
self.total_completion_tokens += completion_tokens | ||
self.total_cost += ( | ||
prompt_tokens * COSTS[model]["prompt"] | ||
+ completion_tokens * COSTS[model]["completion"] | ||
) / 1000 | ||
if print_total_cost: | ||
print(f"Total running cost: ${self.total_cost:.3f}") | ||
|
||
def set_total_budget(self, total_budget): | ||
""" | ||
Sets the total user-defined budget for API calls. | ||
Args: | ||
prompt_tokens (int): The number of tokens used in the prompt. | ||
""" | ||
self.total_budget = total_budget | ||
|
||
def get_total_prompt_tokens(self): | ||
""" | ||
Get the total number of prompt tokens. | ||
Returns: | ||
int: The total number of prompt tokens. | ||
""" | ||
return self.total_prompt_tokens | ||
|
||
def get_total_completion_tokens(self): | ||
""" | ||
Get the total number of completion tokens. | ||
Returns: | ||
int: The total number of completion tokens. | ||
""" | ||
return self.total_completion_tokens | ||
|
||
def get_total_cost(self): | ||
""" | ||
Get the total cost of API calls. | ||
Returns: | ||
float: The total cost of API calls. | ||
""" | ||
return self.total_cost | ||
|
||
def get_total_budget(self): | ||
""" | ||
Get the total user-defined budget for API calls. | ||
Returns: | ||
float: The total budget for API calls. | ||
""" | ||
return self.total_budget | ||
|
||
|
||
api_manager = ApiManager(cfg.debug_mode) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
COSTS = { | ||
"gpt-3.5-turbo": {"prompt": 0.002, "completion": 0.002}, | ||
"gpt-3.5-turbo-0301": {"prompt": 0.002, "completion": 0.002}, | ||
"gpt-4-0314": {"prompt": 0.03, "completion": 0.06}, | ||
"gpt-4": {"prompt": 0.03, "completion": 0.06}, | ||
"text-embedding-ada-002": {"prompt": 0.0004, "completion": 0.0}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.