chatlas 0.9.0__tar.gz → 0.9.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.
Potentially problematic release.
This version of chatlas might be problematic. Click here for more details.
- {chatlas-0.9.0 → chatlas-0.9.1}/CHANGELOG.md +8 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/PKG-INFO +1 -1
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_chat.py +28 -5
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_tokens.py +4 -12
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_version.py +2 -2
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_chat.py +1 -1
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_tokens.py +5 -12
- {chatlas-0.9.0 → chatlas-0.9.1}/.github/workflows/check-update-types.yml +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/.github/workflows/docs-publish.yml +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/.github/workflows/release.yml +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/.github/workflows/test.yml +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/.github/workflows/update-pricing.yml +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/.gitignore +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/.vscode/extensions.json +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/.vscode/settings.json +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/LICENSE +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/Makefile +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/README.md +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/__init__.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_anthropic.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_auto.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_callbacks.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_content.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_content_image.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_content_pdf.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_databricks.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_display.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_github.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_google.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_groq.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_interpolate.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_live_render.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_logging.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_mcp_manager.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_merge.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_ollama.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_openai.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_perplexity.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_provider.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_snowflake.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_tokens_old.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_tools.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_turn.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_typing_extensions.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/_utils.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/data/prices.json +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/py.typed +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/types/__init__.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/types/anthropic/__init__.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/types/anthropic/_client.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/types/anthropic/_client_bedrock.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/types/anthropic/_submit.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/types/google/__init__.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/types/google/_client.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/types/google/_submit.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/types/openai/__init__.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/types/openai/_client.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/types/openai/_client_azure.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/chatlas/types/openai/_submit.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/.gitignore +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/_extensions/machow/interlinks/.gitignore +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/_extensions/machow/interlinks/_extension.yml +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/_extensions/machow/interlinks/interlinks.lua +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/_quarto.yml +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/_sidebar.yml +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/congressional-assets.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/get-started/async.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/get-started/chat.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/get-started/chatbots.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/get-started/debug.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/get-started/models.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/get-started/monitor.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/get-started/parameters.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/get-started/stream.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/get-started/structured-data.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/get-started/system-prompt.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/get-started/tools.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/chat-app.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/chat-console.mp4 +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/chat-console.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/chat-notebook.mp4 +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/chat-parameters.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/chatbot-gradio.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/chatbot-shiny.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/chatbot-streamlit.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/chatbot-textual.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/chatlas-hello.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/client-parameters.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/congressional-assets.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/hello-chat-console.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/model-parameters.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/model-type-hints.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/posit-logo.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/shiny-mcp-run-python.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/shiny-tool-call-display.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/shiny-tool-call-map.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/tool-calling-right.svg +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/images/tool-calling-wrong.svg +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/index.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/logos/hero/hero-old.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/logos/hero/hero.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/logos/hex/logo.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/logos/small/logo.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/misc/RAG.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/misc/examples.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/misc/mcp-tools.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/misc/vocabulary.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/Chat.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatAnthropic.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatAuto.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatAzureOpenAI.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatBedrockAnthropic.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatDatabricks.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatGithub.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatGoogle.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatGroq.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatOllama.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatOpenAI.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatPerplexity.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatSnowflake.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ChatVertex.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/Provider.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/Tool.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/ToolRejectError.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/Turn.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/content_image_file.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/content_image_plot.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/content_image_url.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/content_pdf_file.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/content_pdf_url.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/image_file.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/image_plot.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/image_url.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/index.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/interpolate.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/interpolate_file.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/token_usage.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.ChatResponse.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.ChatResponseAsync.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.Content.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.ContentImage.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.ContentImageInline.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.ContentImageRemote.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.ContentJson.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.ContentText.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.ContentToolRequest.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.ContentToolResult.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.ImageContentTypes.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.MISSING.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.MISSING_TYPE.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.SubmitInputArgsT.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/reference/types.TokenUsage.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/structured-data/article-summary.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/structured-data/classification.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/structured-data/entity-recognition.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/structured-data/multi-modal.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/structured-data/sentiment-analysis.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/styles.scss +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/tool-calling/approval.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/tool-calling/displays.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/tool-calling/how-it-works.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/docs/why-chatlas.qmd +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/pyproject.toml +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/pytest.ini +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/scripts/_generate_anthropic_types.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/scripts/_generate_google_types.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/scripts/_generate_openai_types.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/scripts/_utils.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/scripts/main.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/__init__.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/__snapshots__/test_chat.ambr +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/apples.pdf +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/conftest.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/images/dice.png +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/mcp_servers/http_add.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/mcp_servers/http_current_date.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/mcp_servers/stdio_current_date.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/mcp_servers/stdio_subtract_multiply.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_auto.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_callbacks.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_content.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_content_html.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_content_image.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_content_pdf.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_content_tools.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_interpolate.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_mcp_client.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_provider_anthropic.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_provider_azure.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_provider_bedrock.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_provider_databricks.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_provider_google.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_provider_openai.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_provider_snowflake.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_set_model_params.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_tool_from_mcp.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_tools_enhanced.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_turns.py +0 -0
- {chatlas-0.9.0 → chatlas-0.9.1}/tests/test_utils_merge.py +0 -0
|
@@ -7,6 +7,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
7
7
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
8
|
-->
|
|
9
9
|
|
|
10
|
+
## [0.9.1] - 2025-07-09
|
|
11
|
+
|
|
12
|
+
### Bug fixes
|
|
13
|
+
|
|
14
|
+
* Fixed an issue where `.chat()` wasn't streaming output properly in (the latest build of) Positron's Jupyter notebook. (#131)
|
|
15
|
+
|
|
16
|
+
* Needless warnings and errors are no longer thrown when model pricing info is unavailable. (#132)
|
|
17
|
+
|
|
10
18
|
## [0.9.0] - 2025-07-02
|
|
11
19
|
|
|
12
20
|
### New features
|
|
@@ -44,7 +44,7 @@ from ._display import (
|
|
|
44
44
|
from ._logging import log_tool_error
|
|
45
45
|
from ._mcp_manager import MCPSessionManager
|
|
46
46
|
from ._provider import Provider, StandardModelParams, SubmitInputArgsT
|
|
47
|
-
from ._tokens import get_token_pricing
|
|
47
|
+
from ._tokens import compute_cost, get_token_pricing
|
|
48
48
|
from ._tools import Tool, ToolRejectError
|
|
49
49
|
from ._turn import Turn, user_turn
|
|
50
50
|
from ._typing_extensions import TypedDict, TypeGuard
|
|
@@ -2170,10 +2170,10 @@ class Chat(Generic[SubmitInputArgsT, CompletionT]):
|
|
|
2170
2170
|
return ChatMarkdownDisplay(MockMarkdownDisplay(), self)
|
|
2171
2171
|
|
|
2172
2172
|
# rich does a lot to detect a notebook environment, but it doesn't
|
|
2173
|
-
# detect Quarto
|
|
2173
|
+
# detect Quarto, or a Positron notebook
|
|
2174
2174
|
from rich.console import Console
|
|
2175
2175
|
|
|
2176
|
-
is_web = Console().is_jupyter or
|
|
2176
|
+
is_web = Console().is_jupyter or is_quarto() or is_positron_notebook()
|
|
2177
2177
|
|
|
2178
2178
|
opts = self._echo_options
|
|
2179
2179
|
|
|
@@ -2222,11 +2222,22 @@ class Chat(Generic[SubmitInputArgsT, CompletionT]):
|
|
|
2222
2222
|
def __repr__(self):
|
|
2223
2223
|
turns = self.get_turns(include_system_prompt=True)
|
|
2224
2224
|
tokens = self.get_tokens()
|
|
2225
|
-
cost = self.get_cost()
|
|
2226
2225
|
tokens_asst = sum(u["tokens_total"] for u in tokens if u["role"] == "assistant")
|
|
2227
2226
|
tokens_user = sum(u["tokens_total"] for u in tokens if u["role"] == "user")
|
|
2228
2227
|
|
|
2229
|
-
res = f"<Chat {self.provider.name}/{self.provider.model} turns={len(turns)} tokens={tokens_user}/{tokens_asst}
|
|
2228
|
+
res = f"<Chat {self.provider.name}/{self.provider.model} turns={len(turns)} tokens={tokens_user}/{tokens_asst}"
|
|
2229
|
+
|
|
2230
|
+
# Add cost info only if we can compute it
|
|
2231
|
+
cost = compute_cost(
|
|
2232
|
+
self.provider.name,
|
|
2233
|
+
self.provider.model,
|
|
2234
|
+
tokens_user,
|
|
2235
|
+
tokens_asst,
|
|
2236
|
+
)
|
|
2237
|
+
if cost is not None:
|
|
2238
|
+
res += f" ${round(cost, ndigits=2)}"
|
|
2239
|
+
|
|
2240
|
+
res += ">"
|
|
2230
2241
|
for turn in turns:
|
|
2231
2242
|
res += "\n" + turn.__repr__(indent=2)
|
|
2232
2243
|
return res + "\n"
|
|
@@ -2421,3 +2432,15 @@ class ToolFailureWarning(RuntimeWarning):
|
|
|
2421
2432
|
|
|
2422
2433
|
# By default warnings are shown once; we want to always show them.
|
|
2423
2434
|
warnings.simplefilter("always", ToolFailureWarning)
|
|
2435
|
+
|
|
2436
|
+
|
|
2437
|
+
def is_quarto():
|
|
2438
|
+
return os.getenv("QUARTO_PYTHON", None) is not None
|
|
2439
|
+
|
|
2440
|
+
|
|
2441
|
+
def is_positron_notebook():
|
|
2442
|
+
try:
|
|
2443
|
+
mode = get_ipython().session_mode # noqa: F821 # type: ignore
|
|
2444
|
+
return mode == "notebook"
|
|
2445
|
+
except Exception:
|
|
2446
|
+
return False
|
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import copy
|
|
4
4
|
import importlib.resources as resources
|
|
5
|
-
import warnings
|
|
6
5
|
from threading import Lock
|
|
7
6
|
from typing import TYPE_CHECKING
|
|
8
7
|
|
|
@@ -47,12 +46,12 @@ class ThreadSafeTokenCounter:
|
|
|
47
46
|
"model": model,
|
|
48
47
|
"input": input_tokens,
|
|
49
48
|
"output": output_tokens,
|
|
50
|
-
"cost":
|
|
49
|
+
"cost": compute_cost(name, model, input_tokens, output_tokens),
|
|
51
50
|
}
|
|
52
51
|
else:
|
|
53
52
|
self._tokens[name]["input"] += input_tokens
|
|
54
53
|
self._tokens[name]["output"] += output_tokens
|
|
55
|
-
price =
|
|
54
|
+
price = compute_cost(name, model, input_tokens, output_tokens)
|
|
56
55
|
if price is not None:
|
|
57
56
|
cost = self._tokens[name]["cost"]
|
|
58
57
|
if cost is None:
|
|
@@ -122,7 +121,7 @@ def get_token_pricing(name: str, model: str) -> TokenPrice | None:
|
|
|
122
121
|
-------
|
|
123
122
|
TokenPrice | None
|
|
124
123
|
"""
|
|
125
|
-
|
|
124
|
+
return next(
|
|
126
125
|
(
|
|
127
126
|
item
|
|
128
127
|
for item in pricing_list
|
|
@@ -130,16 +129,9 @@ def get_token_pricing(name: str, model: str) -> TokenPrice | None:
|
|
|
130
129
|
),
|
|
131
130
|
None,
|
|
132
131
|
)
|
|
133
|
-
if result is None:
|
|
134
|
-
warnings.warn(
|
|
135
|
-
f"Token pricing for the provider '{name}' and model '{model}' you selected is not available. "
|
|
136
|
-
"Please check the provider's documentation."
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
return result
|
|
140
132
|
|
|
141
133
|
|
|
142
|
-
def
|
|
134
|
+
def compute_cost(
|
|
143
135
|
name: str, model: str, input_tokens: int, output_tokens: int
|
|
144
136
|
) -> float | None:
|
|
145
137
|
"""
|
|
@@ -310,7 +310,7 @@ def test_get_cost():
|
|
|
310
310
|
"Expected `options` to be one of 'all' or 'last', not 'bad_option'"
|
|
311
311
|
),
|
|
312
312
|
):
|
|
313
|
-
chat.get_cost(options="bad_option")
|
|
313
|
+
chat.get_cost(options="bad_option") # type: ignore
|
|
314
314
|
|
|
315
315
|
# Checking that these have the right form vs. the actual calculation because the price may change
|
|
316
316
|
cost = chat.get_cost(options="all")
|
|
@@ -2,7 +2,7 @@ import pytest
|
|
|
2
2
|
from chatlas import ChatAnthropic, ChatGoogle, ChatOpenAI, Turn
|
|
3
3
|
from chatlas._openai import OpenAIAzureProvider, OpenAIProvider
|
|
4
4
|
from chatlas._tokens import (
|
|
5
|
-
|
|
5
|
+
compute_cost,
|
|
6
6
|
get_token_pricing,
|
|
7
7
|
token_usage,
|
|
8
8
|
tokens_log,
|
|
@@ -59,29 +59,22 @@ def test_token_count_method():
|
|
|
59
59
|
def test_get_token_prices():
|
|
60
60
|
chat = ChatOpenAI(model="o1-mini")
|
|
61
61
|
pricing = get_token_pricing(chat.provider.name, chat.provider.model)
|
|
62
|
+
assert pricing is not None
|
|
62
63
|
assert pricing["provider"] == "OpenAI"
|
|
63
64
|
assert pricing["model"] == "o1-mini"
|
|
64
65
|
assert isinstance(pricing["cached_input"], float)
|
|
65
66
|
assert isinstance(pricing["input"], float)
|
|
66
67
|
assert isinstance(pricing["output"], float)
|
|
67
68
|
|
|
68
|
-
with pytest.warns(
|
|
69
|
-
match="Token pricing for the provider 'OpenAI' and model 'ABCD' you selected is not available. "
|
|
70
|
-
"Please check the provider's documentation."
|
|
71
|
-
):
|
|
72
|
-
chat = ChatOpenAI(model="ABCD")
|
|
73
|
-
pricing = get_token_pricing(chat.provider.name, chat.provider.model)
|
|
74
|
-
assert pricing is None
|
|
75
69
|
|
|
76
|
-
|
|
77
|
-
def test_compute_price():
|
|
70
|
+
def test_compute_cost():
|
|
78
71
|
chat = ChatOpenAI(model="o1-mini")
|
|
79
|
-
price =
|
|
72
|
+
price = compute_cost(chat.provider.name, chat.provider.model, 10, 50)
|
|
80
73
|
assert isinstance(price, float)
|
|
81
74
|
assert price > 0
|
|
82
75
|
|
|
83
76
|
chat = ChatOpenAI(model="ABCD")
|
|
84
|
-
price =
|
|
77
|
+
price = compute_cost(chat.provider.name, chat.provider.model, 10, 50)
|
|
85
78
|
assert price is None
|
|
86
79
|
|
|
87
80
|
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|