costly
Estimate costs and running times of complex LLM workflows/experiments/pipelines in advance before spending money, via simulations. Just put @costly() on the load-bearing function; make sure all functions that call it pass **kwargs to it and call your complex function with simulate=True and some cost_log: Costlog object. See examples.ipynb for more details.
(Actually you don't have to pass cost_log and simulate throughout; you can just define a global cost_log and simulate at the top of the file that contains your @costly functions and pass them as defaults to your @costly functions.)
(Pass @costly(disable_costly=True) to disable costly for a function. E.g. you may set disable_costly to be a global variable and pass it to your @costly decorators.)
https://github.com/abhimanyupallavisudhir/costly
Installation
pip install costly
Usage
See examples.ipynb for a full walkthrough; some examples below.
from costly import Costlog, costly, CostlyResponse
from costly.estimators.llm_api_estimation import LLM_API_Estimation as estimator
@costly()
def chatgpt(input_string: str, model: str) -> str:
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model=model, messages=[{"role": "user", "content": input_string}]
)
output_string = response.choices[0].message.content
return output_string
@costly(
input_tokens=lambda kwargs: LLM_API_Estimation.messages_to_input_tokens(
kwargs["messages"], kwargs["model"]
),
)
def chatgpt_messages(messages: list[dict[str, str]], model: str) -> str:
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(model=model, messages=messages)
output_string = response.choices[0].message.content
return output_string
@costly()
def chatgpt(input_string: str, model: str) -> str:
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model=model,
messages=[
{"role": "user", "content": input_string},
],
)
return CostlyResponse(
output=response.choices[0].message.content,
cost_info={
"input_tokens": response.usage.prompt_tokens,
"output_tokens": response.usage.completion_tokens,
},
) # in usage, this will still just return the output, not the whole CostlyResponse object
Testing
poetry run pytest -s -m "not slow"
poetry run pytest -s -m "slow"
Tests for instructor currently fail.
TODO
- Make it work with async
- Decide and document what the best way to "propagate"
description(for breakdown purposes) through function calls is. Have the user manually writedef f(...): ... g(description = kwargs.get("description") + ["f"]? Add a@description("blabla")decorator? Add a@descriptiondecorator that automatically appends the function name and arguments intodescription? - Better solution for token counting for Chat messages (search
HACKin the repo) - make instructor tests pass https://community.openai.com/t/how-to-calculate-the-tokens-when-using-function-call/266573/11
- Support for locally run LLMs -- ideally need a cost & time estimator that takes into account your machine details, GPU pricing etc.
- support more models
Instructor tests don't really pass but I can kinda live with this. Lmk if anyone has a good way to count tokens from messages that includes tool calling (I'm using this).
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[PERSONINFO_gpt-4o] - AssertionError: ['Input tokens estimate 65 not within 20pc of truth 83']
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[PERSONINFO_gpt-4o-mini] - AssertionError: ['Input tokens estimate 65 not within 20pc of truth 83']
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[PERSONINFO_gpt-4-turbo] - AssertionError: ['Input tokens estimate 65 not within 20pc of truth 85']
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[PERSONINFO_gpt-3.5-turbo] - AssertionError: ['Input tokens estimate 65 not within 20pc of truth 85']
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[FOOMODEL_gpt-4o] - AssertionError: ['Input tokens estimate 77 not within 20pc of truth 108']
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[FOOMODEL_gpt-4o-mini] - AssertionError: ['Input tokens estimate 77 not within 20pc of truth 108']
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[FOOMODEL_gpt-4-turbo] - AssertionError: ['Input tokens estimate 77 not within 20pc of truth 113']
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[FOOMODEL_gpt-3.5-turbo] - AssertionError: ['Input tokens estimate 77 not within 20pc of truth 113']
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[BARMODEL_gpt-4o] - AssertionError: ['Input tokens estimate 70 not within 20pc of truth 168']
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[BARMODEL_gpt-4o-mini] - AssertionError: ['Input tokens estimate 70 not within 20pc of truth 168']
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[BARMODEL_gpt-4-turbo] - AssertionError: ['Input tokens estimate 70 not within 20pc of truth 178']
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[BARMODEL_gpt-4] - AssertionError: ['Input tokens estimate 70 not within 20pc of truth 126']
FAILED tests/test_estimators/test_llm_api_estimation.py::test_estimate_contains_exact_instructor[BARMODEL_gpt-3.5-turbo] - AssertionError: ['Input tokens estimate 70 not within 20pc of truth 178']
Metadata
Release files for costly 2.3.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| costly-2.3.7.tar.gz | 151.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| costly-2.3.7-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 168.6 kB
Release files / costly-2.3.7.tar.gz
| Download URL | costly-2.3.7.tar.gz |
|---|---|
| Size | 151.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f5e7d2c414868f357c2cc4ccb9c036249d4723e5e5d8a90fe8c7166fb0013cba
|
|
BLAKE2b-256 checksum How to use checksums |
9fa505758cf1a295fc5e4ccc1ecff3cad55d54faba6cbe0eaa6efe0c3340f73f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.14.2 Linux/6.11.0-1018-azure
|
Release files / costly-2.3.7-py3-none-any.whl
| Download URL | costly-2.3.7-py3-none-any.whl |
|---|---|
| Size | 17.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
78e10e2a5135d4cb313f3bcc6901762b1decb40c1d79b73f86fe2aa4105098fc
|
|
BLAKE2b-256 checksum How to use checksums |
3ff47b4d97ed98040b93e8ddb0c1c8ec1640187d83b41e78f14cb2a6288f26e0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.2.1 CPython/3.14.2 Linux/6.11.0-1018-azure
|
Security for costly 2.3.7
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.