metergraph-core 0.7.0__tar.gz → 0.7.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {metergraph_core-0.7.0/src/metergraph_core.egg-info → metergraph_core-0.7.1}/PKG-INFO +8 -3
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/README.md +7 -2
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/pyproject.toml +1 -1
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/__init__.py +3 -1
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/responses.py +50 -18
- {metergraph_core-0.7.0 → metergraph_core-0.7.1/src/metergraph_core.egg-info}/PKG-INFO +8 -3
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/MANIFEST.in +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/setup.cfg +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/billing.py +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/catalog.py +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/catalog_delta.py +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/data/models.yaml +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/data/prices.yaml +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/data/sources.yaml +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/extractors.py +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/loader.py +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/models.py +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/refresh.py +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/retrieval.py +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core/sources.py +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core.egg-info/SOURCES.txt +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core.egg-info/dependency_links.txt +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core.egg-info/requires.txt +0 -0
- {metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: metergraph-core
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Open, effective-dated LLM pricing catalog and deterministic cost calculator for popular models across major providers and gateways, including OpenAI, Anthropic, Google Gemini, AWS Bedrock, OpenRouter, Vercel AI Gateway, and more.
|
|
5
5
|
Author: Metergraph
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -225,7 +225,9 @@ It accepts the object a provider SDK returned or the same response as JSON:
|
|
|
225
225
|
| Bedrock Converse (pass `model=`, the response does not name one) | `bedrock` |
|
|
226
226
|
|
|
227
227
|
`provider` names who served the call and selects its direct channel unless
|
|
228
|
-
`channel` is given. The response
|
|
228
|
+
`channel` is given. The response format is detected from its fields; pass
|
|
229
|
+
`format=`, one of `RESPONSE_FORMATS`, for a response too sparse to detect.
|
|
230
|
+
`response_format(response)` returns the detected format, or `None`. Only the
|
|
229
231
|
model, usage counts, service tier and creation time are read; prompt and
|
|
230
232
|
output content never are.
|
|
231
233
|
|
|
@@ -240,7 +242,8 @@ The price in effect when the response was created applies, from `created`,
|
|
|
240
242
|
creation time is priced now. `catalog=` costs against a catalog you loaded;
|
|
241
243
|
the default is the bundled one.
|
|
242
244
|
|
|
243
|
-
A batch service tier bills at batch rates.
|
|
245
|
+
A batch service tier bills at batch rates. Pass `service_tier=` when the
|
|
246
|
+
response does not state its tier, such as an OpenAI batch output line. Any other tier besides standard,
|
|
244
247
|
such as `priority` or `flex`, returns `partial` with `service_tier` in
|
|
245
248
|
`missing_dimensions`, since the catalog carries no tier rates. Cost a streamed
|
|
246
249
|
call from its final response or final usage chunk. Fees outside token usage,
|
|
@@ -508,6 +511,7 @@ from metergraph_core import (
|
|
|
508
511
|
PriceResult,
|
|
509
512
|
PriceRowKey,
|
|
510
513
|
PriceSource,
|
|
514
|
+
RESPONSE_FORMATS,
|
|
511
515
|
RefreshResult,
|
|
512
516
|
ResolvedPrice,
|
|
513
517
|
SourceRegistry,
|
|
@@ -524,6 +528,7 @@ from metergraph_core import (
|
|
|
524
528
|
parse_catalog_delta,
|
|
525
529
|
plan_low_risk_refresh,
|
|
526
530
|
resolve_billing,
|
|
531
|
+
response_format,
|
|
527
532
|
structural_fingerprint,
|
|
528
533
|
validate_model_registry,
|
|
529
534
|
validate_source_registry,
|
|
@@ -195,7 +195,9 @@ It accepts the object a provider SDK returned or the same response as JSON:
|
|
|
195
195
|
| Bedrock Converse (pass `model=`, the response does not name one) | `bedrock` |
|
|
196
196
|
|
|
197
197
|
`provider` names who served the call and selects its direct channel unless
|
|
198
|
-
`channel` is given. The response
|
|
198
|
+
`channel` is given. The response format is detected from its fields; pass
|
|
199
|
+
`format=`, one of `RESPONSE_FORMATS`, for a response too sparse to detect.
|
|
200
|
+
`response_format(response)` returns the detected format, or `None`. Only the
|
|
199
201
|
model, usage counts, service tier and creation time are read; prompt and
|
|
200
202
|
output content never are.
|
|
201
203
|
|
|
@@ -210,7 +212,8 @@ The price in effect when the response was created applies, from `created`,
|
|
|
210
212
|
creation time is priced now. `catalog=` costs against a catalog you loaded;
|
|
211
213
|
the default is the bundled one.
|
|
212
214
|
|
|
213
|
-
A batch service tier bills at batch rates.
|
|
215
|
+
A batch service tier bills at batch rates. Pass `service_tier=` when the
|
|
216
|
+
response does not state its tier, such as an OpenAI batch output line. Any other tier besides standard,
|
|
214
217
|
such as `priority` or `flex`, returns `partial` with `service_tier` in
|
|
215
218
|
`missing_dimensions`, since the catalog carries no tier rates. Cost a streamed
|
|
216
219
|
call from its final response or final usage chunk. Fees outside token usage,
|
|
@@ -478,6 +481,7 @@ from metergraph_core import (
|
|
|
478
481
|
PriceResult,
|
|
479
482
|
PriceRowKey,
|
|
480
483
|
PriceSource,
|
|
484
|
+
RESPONSE_FORMATS,
|
|
481
485
|
RefreshResult,
|
|
482
486
|
ResolvedPrice,
|
|
483
487
|
SourceRegistry,
|
|
@@ -494,6 +498,7 @@ from metergraph_core import (
|
|
|
494
498
|
parse_catalog_delta,
|
|
495
499
|
plan_low_risk_refresh,
|
|
496
500
|
resolve_billing,
|
|
501
|
+
response_format,
|
|
497
502
|
structural_fingerprint,
|
|
498
503
|
validate_model_registry,
|
|
499
504
|
validate_source_registry,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "metergraph-core"
|
|
3
|
-
version = "0.7.
|
|
3
|
+
version = "0.7.1"
|
|
4
4
|
description = "Open, effective-dated LLM pricing catalog and deterministic cost calculator for popular models across major providers and gateways, including OpenAI, Anthropic, Google Gemini, AWS Bedrock, OpenRouter, Vercel AI Gateway, and more."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -59,7 +59,7 @@ from .catalog_delta import (
|
|
|
59
59
|
apply_catalog_delta,
|
|
60
60
|
parse_catalog_delta,
|
|
61
61
|
)
|
|
62
|
-
from .responses import cost_from_response
|
|
62
|
+
from .responses import RESPONSE_FORMATS, cost_from_response, response_format
|
|
63
63
|
from .extractors import (
|
|
64
64
|
ExtractedRate,
|
|
65
65
|
Extraction,
|
|
@@ -135,6 +135,8 @@ __all__ = [
|
|
|
135
135
|
"count_fetch_units",
|
|
136
136
|
"count_search_units",
|
|
137
137
|
"cost_from_response",
|
|
138
|
+
"response_format",
|
|
139
|
+
"RESPONSE_FORMATS",
|
|
138
140
|
"counts_cache_read_in_input",
|
|
139
141
|
"direct_channel_for_provider",
|
|
140
142
|
"normalize_provider",
|
|
@@ -12,7 +12,7 @@ from datetime import datetime, timezone
|
|
|
12
12
|
from functools import lru_cache
|
|
13
13
|
from typing import Any, Callable, Mapping
|
|
14
14
|
|
|
15
|
-
from .catalog import CostResult, ModelUsage
|
|
15
|
+
from .catalog import CostResult, ModelUsage, _coerce_datetime
|
|
16
16
|
from .loader import LoadedCatalog, load_catalog
|
|
17
17
|
|
|
18
18
|
_STANDARD_TIERS = frozenset({"default", "standard", "standard_only", "auto", "on_demand"})
|
|
@@ -188,23 +188,41 @@ def _bedrock_converse(response: Mapping[str, Any]) -> _Facts:
|
|
|
188
188
|
)
|
|
189
189
|
|
|
190
190
|
|
|
191
|
-
|
|
192
|
-
""
|
|
193
|
-
|
|
191
|
+
_READERS: dict[str, Callable[[Mapping[str, Any]], _Facts]] = {
|
|
192
|
+
"openai.chat_completions": _openai_chat_completions,
|
|
193
|
+
"openai.responses": _openai_responses,
|
|
194
|
+
"anthropic.messages": _anthropic_messages,
|
|
195
|
+
"gemini.generate_content": _gemini,
|
|
196
|
+
"bedrock.converse": _bedrock_converse,
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
# The response formats :func:`cost_from_response` reads.
|
|
200
|
+
RESPONSE_FORMATS = tuple(_READERS)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def _detect(response: Mapping[str, Any]) -> str | None:
|
|
204
|
+
"""The format of this response, told apart by the fields each API
|
|
205
|
+
always returns."""
|
|
194
206
|
if _first(response, "usage_metadata", "usageMetadata") is not None:
|
|
195
|
-
return
|
|
207
|
+
return "gemini.generate_content"
|
|
196
208
|
usage = _object(response.get("usage"))
|
|
197
209
|
if "prompt_tokens" in usage:
|
|
198
|
-
return
|
|
210
|
+
return "openai.chat_completions"
|
|
199
211
|
if "inputTokens" in usage:
|
|
200
|
-
return
|
|
212
|
+
return "bedrock.converse"
|
|
201
213
|
if response.get("type") == "message" or "cache_read_input_tokens" in usage:
|
|
202
|
-
return
|
|
214
|
+
return "anthropic.messages"
|
|
203
215
|
if response.get("object") == "response" or "input_tokens_details" in usage:
|
|
204
|
-
return
|
|
216
|
+
return "openai.responses"
|
|
205
217
|
return None
|
|
206
218
|
|
|
207
219
|
|
|
220
|
+
def response_format(response: Any) -> str | None:
|
|
221
|
+
"""The :data:`RESPONSE_FORMATS` entry ``response`` is in, or None when its
|
|
222
|
+
shape is not recognized."""
|
|
223
|
+
return _detect(_as_mapping(response))
|
|
224
|
+
|
|
225
|
+
|
|
208
226
|
def _as_mapping(response: Any) -> Mapping[str, Any]:
|
|
209
227
|
if isinstance(response, Mapping):
|
|
210
228
|
return response
|
|
@@ -270,6 +288,8 @@ def cost_from_response(
|
|
|
270
288
|
at: Any = None,
|
|
271
289
|
channel: str | None = None,
|
|
272
290
|
region: str | None = None,
|
|
291
|
+
service_tier: str | None = None,
|
|
292
|
+
format: str | None = None,
|
|
273
293
|
) -> CostResult:
|
|
274
294
|
"""The cost of one provider response, from the usage it reports.
|
|
275
295
|
|
|
@@ -280,24 +300,36 @@ def cost_from_response(
|
|
|
280
300
|
is given. ``model`` overrides the response's model id and is required for
|
|
281
301
|
Bedrock Converse, whose responses do not name one. ``at`` defaults to the
|
|
282
302
|
response's creation time when it reports one, else now. ``catalog``
|
|
283
|
-
defaults to the catalog bundled with this package.
|
|
303
|
+
defaults to the catalog bundled with this package. ``format``, one of
|
|
304
|
+
:data:`RESPONSE_FORMATS`, names the response's format; without it the
|
|
305
|
+
format is detected from the response's fields.
|
|
284
306
|
|
|
285
307
|
A streamed call is costed from its final response or final usage chunk.
|
|
286
|
-
Fees outside token usage, such as web search, are not included.
|
|
287
|
-
|
|
288
|
-
|
|
308
|
+
Fees outside token usage, such as web search, are not included.
|
|
309
|
+
``service_tier`` overrides the tier the response reports, for responses
|
|
310
|
+
that do not state it, such as an OpenAI batch output line. A tier other
|
|
311
|
+
than standard or batch turns the result ``partial`` with ``service_tier``
|
|
312
|
+
missing, since the catalog does not carry tier rates.
|
|
289
313
|
"""
|
|
290
314
|
data = _as_mapping(response)
|
|
291
|
-
|
|
292
|
-
|
|
315
|
+
if format is not None and format not in _READERS:
|
|
316
|
+
raise ValueError(f"format must be one of {', '.join(RESPONSE_FORMATS)}")
|
|
317
|
+
detected = format or _detect(data)
|
|
318
|
+
if detected is None:
|
|
293
319
|
raise ValueError("response carries no usage this function can read")
|
|
294
|
-
facts =
|
|
320
|
+
facts = _READERS[detected](data)
|
|
295
321
|
when = at if at is not None else facts.at or datetime.now(timezone.utc)
|
|
296
322
|
model_id = _text(model) or facts.model
|
|
297
|
-
tier = (facts.service_tier or "").lower() or None
|
|
323
|
+
tier = (_text(service_tier) or facts.service_tier or "").lower() or None
|
|
298
324
|
if model_id is None:
|
|
299
325
|
return CostResult(
|
|
300
|
-
None,
|
|
326
|
+
None,
|
|
327
|
+
None,
|
|
328
|
+
None,
|
|
329
|
+
"unpriced",
|
|
330
|
+
("missing_model",),
|
|
331
|
+
effective_at=_coerce_datetime(when),
|
|
332
|
+
missing_dimensions=("model",),
|
|
301
333
|
)
|
|
302
334
|
loaded = catalog if catalog is not None else _bundled_catalog()
|
|
303
335
|
batch = tier == _BATCH_TIER
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: metergraph-core
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Open, effective-dated LLM pricing catalog and deterministic cost calculator for popular models across major providers and gateways, including OpenAI, Anthropic, Google Gemini, AWS Bedrock, OpenRouter, Vercel AI Gateway, and more.
|
|
5
5
|
Author: Metergraph
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -225,7 +225,9 @@ It accepts the object a provider SDK returned or the same response as JSON:
|
|
|
225
225
|
| Bedrock Converse (pass `model=`, the response does not name one) | `bedrock` |
|
|
226
226
|
|
|
227
227
|
`provider` names who served the call and selects its direct channel unless
|
|
228
|
-
`channel` is given. The response
|
|
228
|
+
`channel` is given. The response format is detected from its fields; pass
|
|
229
|
+
`format=`, one of `RESPONSE_FORMATS`, for a response too sparse to detect.
|
|
230
|
+
`response_format(response)` returns the detected format, or `None`. Only the
|
|
229
231
|
model, usage counts, service tier and creation time are read; prompt and
|
|
230
232
|
output content never are.
|
|
231
233
|
|
|
@@ -240,7 +242,8 @@ The price in effect when the response was created applies, from `created`,
|
|
|
240
242
|
creation time is priced now. `catalog=` costs against a catalog you loaded;
|
|
241
243
|
the default is the bundled one.
|
|
242
244
|
|
|
243
|
-
A batch service tier bills at batch rates.
|
|
245
|
+
A batch service tier bills at batch rates. Pass `service_tier=` when the
|
|
246
|
+
response does not state its tier, such as an OpenAI batch output line. Any other tier besides standard,
|
|
244
247
|
such as `priority` or `flex`, returns `partial` with `service_tier` in
|
|
245
248
|
`missing_dimensions`, since the catalog carries no tier rates. Cost a streamed
|
|
246
249
|
call from its final response or final usage chunk. Fees outside token usage,
|
|
@@ -508,6 +511,7 @@ from metergraph_core import (
|
|
|
508
511
|
PriceResult,
|
|
509
512
|
PriceRowKey,
|
|
510
513
|
PriceSource,
|
|
514
|
+
RESPONSE_FORMATS,
|
|
511
515
|
RefreshResult,
|
|
512
516
|
ResolvedPrice,
|
|
513
517
|
SourceRegistry,
|
|
@@ -524,6 +528,7 @@ from metergraph_core import (
|
|
|
524
528
|
parse_catalog_delta,
|
|
525
529
|
plan_low_risk_refresh,
|
|
526
530
|
resolve_billing,
|
|
531
|
+
response_format,
|
|
527
532
|
structural_fingerprint,
|
|
528
533
|
validate_model_registry,
|
|
529
534
|
validate_source_registry,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{metergraph_core-0.7.0 → metergraph_core-0.7.1}/src/metergraph_core.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|