Configuration
conatus.models.base.ModelConfig
dataclass
¶
ModelConfig(
not_given_sentinel: object = CTUS_NOT_GIVEN,
api_key: OptionalArg[str] = CTUS_NOT_GIVEN,
model_name: OptionalArg[str] = CTUS_NOT_GIVEN,
max_tokens: OptionalArg[int] = CTUS_NOT_GIVEN,
stdout_mode: OptionalArg[
Literal["normal", "preview", "silent"]
] = CTUS_NOT_GIVEN,
temperature: OptionalArg[float] = CTUS_NOT_GIVEN,
computer_use_mode: OptionalArg[bool] = CTUS_NOT_GIVEN,
use_mock: OptionalArg[bool] = CTUS_NOT_GIVEN,
only_pass_new_messages: OptionalArg[
bool
] = CTUS_NOT_GIVEN,
previous_messages_id: OptionalArg[str] = CTUS_NOT_GIVEN,
truncation: OptionalArg[
Literal["auto", "disabled"]
] = CTUS_NOT_GIVEN,
)
The configuration for a BaseAIModel.
We're only showing some of the available arguments; if you need more, you
can always add them after instantiation. Or, even better, you can subclass
this class and add them there. See the OpenAIModelConfig
implementation for an example.
One method that might be useful is to_kwargs
, which returns a dictionary
of the configuration. In that method, you can provide a specification,
which is a TypedDict that matches some of the
arguments expected by the provider, as well as a not_given_sentinel,
which is an object that is used to represent a missing argument. See the
OpenAIModel implementation for
an example.
Another method that might be useful is apply_config
, which returns
a new instance of the configuration with the new values applied.
In both cases, because we use the not_given_sentinel
object to represent
missing arguments, this method can be used to ensure that only arguments
that are actually provided are included in the new configuration.
not_given_sentinel
class-attribute
instance-attribute
¶
not_given_sentinel: object = CTUS_NOT_GIVEN
The sentinel object to use for missing arguments.
This is used to represent a missing argument. If we encounter this sentinel object, we will not include it in the returned dictionary.
api_key
class-attribute
instance-attribute
¶
api_key: OptionalArg[str] = CTUS_NOT_GIVEN
The API key to use, if any.
If not provided, the API key will be taken from the environment variable
specified in the api_key_env_variable
attribute of the model.
model_name
class-attribute
instance-attribute
¶
model_name: OptionalArg[str] = CTUS_NOT_GIVEN
The name of the model to use.
max_tokens
class-attribute
instance-attribute
¶
max_tokens: OptionalArg[int] = CTUS_NOT_GIVEN
The maximum number of tokens to generate.
stdout_mode
class-attribute
instance-attribute
¶
stdout_mode: OptionalArg[
Literal["normal", "preview", "silent"]
] = CTUS_NOT_GIVEN
The mode to use for the standard output.
'normal': Notify the user that we're waiting for a response, and then that we're receiving the response, displaying the number of chunks received so far.
'preview': Preview the response with a fancy output that updates as the response chunks are received. Only works if the response is a stream. Ifpreviewis set and the response is not a stream, it will default to'normal'.
'silent': Do not print anything to the standard output.
Note that if we detect that we are running in a non TTY environment, we
will use a special mode called 'non_tty', unless the user asked for
'silent'.
temperature
class-attribute
instance-attribute
¶
temperature: OptionalArg[float] = CTUS_NOT_GIVEN
The temperature for the model.
computer_use_mode
class-attribute
instance-attribute
¶
computer_use_mode: OptionalArg[bool] = CTUS_NOT_GIVEN
Whether to use the computer use mode.
If set to True, the model will be configured to use the computer use
mode.
use_mock
class-attribute
instance-attribute
¶
use_mock: OptionalArg[bool] = CTUS_NOT_GIVEN
Whether to use a mock client or not.
This is useful for testing purposes.
only_pass_new_messages
class-attribute
instance-attribute
¶
only_pass_new_messages: OptionalArg[bool] = CTUS_NOT_GIVEN
Whether to only pass new messages to the model.
If set to True, the model will only pass new messages to the model,
and not the entire history. This is useful for "stateful" APIs, where
the history is not needed.
previous_messages_id
class-attribute
instance-attribute
¶
previous_messages_id: OptionalArg[str] = CTUS_NOT_GIVEN
The ID of the previous messages.
This is useful for "stateful" APIs, where the history is not needed.
This should only be used if only_pass_new_messages is True.
truncation
class-attribute
instance-attribute
¶
truncation: OptionalArg[Literal["auto", "disabled"]] = (
CTUS_NOT_GIVEN
)
The truncation to use.
to_kwargs
¶
to_kwargs(
specification: None = None,
not_given_sentinel: object = CTUS_NOT_GIVEN,
argument_mapping: dict[str, str] | None = None,
) -> ModelConfigTD
to_kwargs(
specification: type[TDSpec] | None = None,
not_given_sentinel: object = CTUS_NOT_GIVEN,
argument_mapping: dict[str, str] | None = None,
) -> ModelConfigTD | TDSpec
Return the configuration as a dictionary.
You can provide a specification, which is a dictionary that matches the arguments expected by the provider. If a specification is provided, the method will return a dictionary that matches the specification (i.e. with only the keys that are expected by the provider).
You can also provide a not_given_sentinel, which is an object
that is used to represent a missing argument. If we encounter this
sentinel object, we will not include it in the returned dictionary.
Example¶
Using a specification¶
from conatus.models.open_ai import OpenAIModel, OpenAIModelCCSpec
from openai import NOT_GIVEN
model = OpenAIModel()
args_to_pass = model.config.to_kwargs(
specification=OpenAIModelCCSpec,
not_given_sentinel=NOT_GIVEN,
)
assert args_to_pass == {'max_tokens': 4096}
# And now you can do something like:
# response = self.client.chat.completions.create(
# messages=messages,
# **args_to_pass
# )
Using an argument mapping¶
from conatus.models.open_ai import OpenAIModel, OpenAIModelResponseSpec
from openai import NOT_GIVEN
model = OpenAIModel()
args_to_pass = model.config.to_kwargs(
specification=OpenAIModelResponseSpec,
argument_mapping={"max_tokens": "max_output_tokens"},
not_given_sentinel=NOT_GIVEN,
)
assert args_to_pass == {'max_output_tokens': 4096, 'truncation': 'auto'}
| PARAMETER | DESCRIPTION |
|---|---|
specification
|
The specification to use. This should be a
TYPE:
|
not_given_sentinel
|
The sentinel object to use.
TYPE:
|
argument_mapping
|
A dictionary that maps the keys of the
configuration to the keys of the provider. The mapping is
of the form |
| RETURNS | DESCRIPTION |
|---|---|
ModelConfigTD | TDSpec
|
The configuration as a dictionary. |
| RAISES | DESCRIPTION |
|---|---|
TypeError
|
If the specification is not a |
Source code in conatus/models/config.py
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | |
from_dict
classmethod
¶
Create a new instance from a dictionary.
| PARAMETER | DESCRIPTION |
|---|---|
config
|
The configuration as a dictionary.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Self
|
The new instance. |
from_dict_instance_or_none
classmethod
¶
Create a new instance from a dictionary or an instance.
| PARAMETER | DESCRIPTION |
|---|---|
config
|
The configuration as a dictionary or an instance.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Self
|
The new instance. |
Source code in conatus/models/config.py
apply_config
¶
apply_config(
new_config: Self | ModelConfigTD | None,
*,
inplace: Literal[True]
) -> None
apply_config(
new_config: Self | ModelConfigTD | None,
*,
inplace: Literal[False] = False
) -> Self
apply_config(
new_config: Self | ModelConfigTD | None,
*,
inplace: bool = False
) -> Self | None
Copy the configuration and apply new values to it.
This ensures that you can create a hierarchy of configurations.
| PARAMETER | DESCRIPTION |
|---|---|
new_config
|
The new configuration.
TYPE:
|
inplace
|
Whether to update the instance in place, or return a new copy
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Self | None
|
None if the modification happens in place; otherwise, return a new instance with the modified configuration |
Source code in conatus/models/config.py
conatus.models.base.AIModelCallArgs
dataclass
¶
AIModelCallArgs(
model_config: ModelConfig,
system_message: MessageType | None,
messages: Iterable[MessageType],
tools: Iterable[ToolType] | None,
output_schema: OutputJSONSchemaType | None,
output_schema_was_converted_to_item_object: bool = False,
)
The arguments for the call to the AI model.
This class exists to be subclassed by the subclasses of BaseAIModel
.
system_message
instance-attribute
¶
system_message: MessageType | None
The system message for the AI model.
output_schema
instance-attribute
¶
The output schema for the AI model.
output_schema_was_converted_to_item_object
class-attribute
instance-attribute
¶
output_schema_was_converted_to_item_object: bool = False
Whether the output schema was converted to an object type.
This needs to be set to indicate to AIResponse
whether it needs
to convert the output schema back to the original type.
Retrieve an AI model from a name¶
We offer a few utilities to make it easier to create an AI model instance from a model name (as a string):
get_model_from_name, which takes a model name and returns an AI model instance.get_model_from_provider, which takes a provider name and a model name, and returns an AI model instance.
We do this by storing a few common model names in the conatus.models.names
module.
conatus.models.names.ModelName
module-attribute
¶
ModelName = Literal[
"openai:gpt-4o",
"openai:gpt-4.5-preview",
"openai:gpt-4o-mini",
"openai:gpt-4-turbo",
"openai:gpt-4",
"openai:gpt-4.1",
"openai:gpt-4.1-mini",
"openai:gpt-4.1-nano",
"openai:o1-mini",
"openai:o1",
"openai:o1-pro",
"openai:o3-mini",
"openai:o3",
"openai:o4-mini",
"openai:computer-use-preview",
"anthropic:claude-3-7-sonnet-latest",
"anthropic:claude-3-7-sonnet-20250219",
"anthropic:claude-3-5-haiku-latest",
"anthropic:claude-3-5-haiku-20241022",
"anthropic:claude-3-5-sonnet-latest",
"anthropic:claude-3-5-sonnet-20241022",
"anthropic:claude-3-5-sonnet-20240620",
"google:gemini-2.5-pro-preview-03-25",
"google:gemini-2.5-flash-preview-04-17",
"google:gemini-2.0-flash-lite",
"google:gemini-2.0-flash",
]
Known AI model names.
conatus.models.names.ModelType
module-attribute
¶
ModelType = Literal[
"execution", "chat", "computer_use", "reasoning"
]
The types of models that can be used.
This is used to determine which model to use for a given task.
conatus.models.names.ProviderName
module-attribute
¶
ProviderName = Literal[
"openai", "anthropic", "google", "other"
]
Known AI provider names.
This is used to determine which AI provider to use, and should be used by other classes to customize their behavior based on the provider.
conatus.models.names.unclean_model_names_to_model_name
module-attribute
¶
unclean_model_names_to_model_name: dict[str, ModelName] = {
"gpt-4o": "openai:gpt-4o",
"gpt-4o-mini": "openai:gpt-4o-mini",
"gpt-4.5-preview": "openai:gpt-4.5-preview",
"gpt-4-turbo": "openai:gpt-4-turbo",
"gpt-4": "openai:gpt-4",
"gpt4": "openai:gpt-4",
"gpt4o": "openai:gpt-4o",
"o1-mini": "openai:o1-mini",
"o1": "openai:o1",
"gpt-4.1": "openai:gpt-4.1",
"gpt-4.1-mini": "openai:gpt-4.1-mini",
"gpt-4.1-nano": "openai:gpt-4.1-nano",
"o3-mini": "openai:o3-mini",
"o3": "openai:o3",
"o4-mini": "openai:o4-mini",
"o1-pro": "openai:o1-pro",
"computer-use-preview": "openai:computer-use-preview",
"claude-3-7-sonnet": "anthropic:claude-3-7-sonnet-latest",
"claude-3-7-sonnet-20250219": "anthropic:claude-3-7-sonnet-20250219",
"claude-3-7-sonnet-latest": "anthropic:claude-3-7-sonnet-latest",
"claude-3-5-sonnet-20241022": "anthropic:claude-3-5-sonnet-20241022",
"claude-3-5-sonnet-20240620": "anthropic:claude-3-5-sonnet-20240620",
"claude-3-5-sonnet": "anthropic:claude-3-5-sonnet-latest",
"claude-3-5-sonnet-latest": "anthropic:claude-3-5-sonnet-latest",
"claude-3-5-haiku-20241022": "anthropic:claude-3-5-haiku-20241022",
"claude-3-5-haiku-latest": "anthropic:claude-3-5-haiku-latest",
"claude-3-5-haiku": "anthropic:claude-3-5-haiku-latest",
"claude-3-5": "anthropic:claude-3-5-sonnet-latest",
"claude-3-7": "anthropic:claude-3-7-sonnet-latest",
"gemini-2.5-pro": "google:gemini-2.5-pro-preview-03-25",
"gemini-2.5-flash": "google:gemini-2.5-flash-preview-04-17",
"gemini-2.0-flash-lite": "google:gemini-2.0-flash-lite",
"gemini-2.0-flash": "google:gemini-2.0-flash",
}
Retrieve an AI model from a name or provider¶
conatus.models.retrieval.get_model_from_name
¶
get_model_from_name(
model_name: str,
model_config: ModelConfig | ModelConfigTD | None = None,
) -> BaseAIModel
Get a model from a name.
Don't call this function often
This function will make some imports after being called. There's no real way around this, since we don't want to call every optional AI provider library just to get a model name.
Use this function sparingly.
| PARAMETER | DESCRIPTION |
|---|---|
model_name
|
The name of the model.
TYPE:
|
model_config
|
The configuration for the model.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
BaseAIModel
|
The model, with the proper provider class. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If the model name is unknown. |
Source code in conatus/models/retrieval.py
conatus.models.retrieval.get_model_from_provider
¶
get_model_from_provider(
provider_name: ProviderName,
model_name: ModelName | None = None,
model_config: ModelConfig | ModelConfigTD | None = None,
*,
model_type: ModelType | None = None
) -> BaseAIModel
Get a model from a provider and a name.
Don't call this function often
This function will make some imports after being called. There's no real way around this, since we don't want to call every optional AI provider library just to get a model name.
Use this function sparingly.
| PARAMETER | DESCRIPTION |
|---|---|
provider_name
|
The name of the provider.
TYPE:
|
model_name
|
The name of the model.
TYPE:
|
model_config
|
The configuration for the model.
TYPE:
|
model_type
|
The type of model to use. Useful if you need to differentiate between different types of models (e.g. chat, computer use, reasoning).
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
BaseAIModel
|
The model, with the proper provider class |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If the provider name is unknown. |
Source code in conatus/models/retrieval.py
Retrieve model prices¶
conatus.models.prices.calculate_cost
¶
calculate_cost(usage: CompletionUsage) -> float
Compute the cost of a CompletionUsage.
Drops the provider prefix, normalizes unclean names via
unclean_model_names_to_model_name,
and delegates to the appropriate
PricingStrategy.
| PARAMETER | DESCRIPTION |
|---|---|
usage
|
The
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Price in USD, or -1 when the model is unknown or usage was never reported. |
Source code in conatus/models/prices.py
conatus.models.prices.PricingStrategy
¶
Bases: Protocol
Defines the interface for pricing strategies.
cost
abstractmethod
¶
cost(usage: CompletionUsage) -> float
Compute the price of a single CompletionUsage.
| PARAMETER | DESCRIPTION |
|---|---|
usage
|
The usage record to evaluate.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Price in USD. Returns -1 when the model is unknown or
|
Source code in conatus/models/prices.py
conatus.models.prices.FlatPrice
dataclass
¶
Bases: PricingStrategy
Flat price (same $/token regardless of volume or cache status).
completion_per_m
instance-attribute
¶
completion_per_m: float
Price for every million completion tokens.
cost
¶
cost(usage: CompletionUsage) -> float
Compute cost using a flat rate per token.
| PARAMETER | DESCRIPTION |
|---|---|
usage
|
The usage record to evaluate.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Total cost in USD, or -1 if usage was never given. |
Source code in conatus/models/prices.py
conatus.models.prices.CachedAwarePrice
dataclass
¶
Bases: PricingStrategy
Flat price plus a single cache price for reads and writes.
completion_per_m
instance-attribute
¶
completion_per_m: float
Price for every million completion tokens.
cached_per_m
class-attribute
instance-attribute
¶
cached_per_m: float = 0.0
Price for every million cached tokens.
cost
¶
cost(usage: CompletionUsage) -> float
Compute cost including cache usage.
| PARAMETER | DESCRIPTION |
|---|---|
usage
|
The usage record to evaluate.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Total cost in USD, or -1 if usage was never given. |
Source code in conatus/models/prices.py
conatus.models.prices.MultiCachedPrice
dataclass
¶
MultiCachedPrice(
prompt_per_m: float,
completion_per_m: float,
cache_read_per_m: float,
cache_write_per_m: float,
)
Bases: PricingStrategy
Flat price plus separate prices for cache reads and writes.
completion_per_m
instance-attribute
¶
completion_per_m: float
Price for every million completion tokens.
cache_read_per_m
instance-attribute
¶
cache_read_per_m: float
Price for every million read cached tokens.
cache_write_per_m
instance-attribute
¶
cache_write_per_m: float
Price for every million write cached tokens.
cost
¶
cost(usage: CompletionUsage) -> float
Compute cost including separate cache read/write pricing.
| PARAMETER | DESCRIPTION |
|---|---|
usage
|
The usage record to evaluate.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Total cost in USD, or -1 if usage was never given. |
Source code in conatus/models/prices.py
conatus.models.prices.TieredPrice
dataclass
¶
Bases: PricingStrategy
Pricing strategy where rates change after token thresholds.
tiers
instance-attribute
¶
Ordered tuple of Tier from lowest threshold to highest.
The last tier should usually have up_to_tokens=None.
cost
¶
cost(usage: CompletionUsage) -> float
Compute cost across multiple tiers.
| PARAMETER | DESCRIPTION |
|---|---|
usage
|
The usage record to evaluate.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
float
|
Total cost in USD, or -1 if usage was never given. |
Source code in conatus/models/prices.py
conatus.models.prices.Tier
dataclass
¶
One tier of a TieredPrice.