chatlas 0.9.2__tar.gz → 0.11.0__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.2 → chatlas-0.11.0}/CHANGELOG.md +35 -0
- chatlas-0.11.0/CLAUDE.md +167 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/PKG-INFO +3 -3
- {chatlas-0.9.2 → chatlas-0.11.0}/README.md +2 -2
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/__init__.py +25 -1
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_chat.py +95 -14
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_content.py +8 -1
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_provider.py +43 -1
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_provider_anthropic.py +51 -5
- chatlas-0.11.0/chatlas/_provider_cloudflare.py +173 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_provider_databricks.py +18 -0
- chatlas-0.11.0/chatlas/_provider_deepseek.py +171 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_provider_github.py +63 -3
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_provider_google.py +26 -2
- chatlas-0.11.0/chatlas/_provider_huggingface.py +155 -0
- chatlas-0.11.0/chatlas/_provider_mistral.py +181 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_provider_ollama.py +40 -9
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_provider_openai.py +38 -7
- chatlas-0.11.0/chatlas/_provider_openrouter.py +149 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_provider_perplexity.py +9 -1
- chatlas-0.11.0/chatlas/_provider_portkey.py +131 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_provider_snowflake.py +6 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_tokens.py +5 -5
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_tools.py +12 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_typing_extensions.py +3 -3
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_version.py +16 -3
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/data/prices.json +329 -18
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/types/__init__.py +2 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/types/anthropic/_client.py +1 -1
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/types/anthropic/_client_bedrock.py +1 -1
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/types/openai/_client.py +1 -1
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/types/openai/_client_azure.py +1 -1
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/types/openai/_submit.py +3 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/.gitignore +5 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/_quarto.yml +12 -1
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/get-started/debug.qmd +3 -3
- chatlas-0.11.0/docs/get-started/models.qmd +114 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/get-started/monitor.qmd +3 -5
- {chatlas-0.9.2 → chatlas-0.11.0}/scripts/_generate_google_types.py +2 -1
- {chatlas-0.9.2 → chatlas-0.11.0}/scripts/_generate_openai_types.py +3 -3
- {chatlas-0.9.2 → chatlas-0.11.0}/scripts/_utils.py +19 -1
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/conftest.py +29 -1
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_content_tools.py +9 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_provider_anthropic.py +6 -0
- chatlas-0.11.0/tests/test_provider_bedrock.py +78 -0
- chatlas-0.11.0/tests/test_provider_cloudflare.py +79 -0
- chatlas-0.11.0/tests/test_provider_deepseek.py +68 -0
- chatlas-0.11.0/tests/test_provider_github.py +114 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_provider_google.py +5 -0
- chatlas-0.11.0/tests/test_provider_huggingface.py +104 -0
- chatlas-0.11.0/tests/test_provider_mistral.py +77 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_provider_openai.py +6 -0
- chatlas-0.11.0/tests/test_provider_openrouter.py +74 -0
- chatlas-0.11.0/tests/test_provider_portkey.py +91 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_tokens.py +32 -2
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_tool_from_mcp.py +55 -2
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_tools_enhanced.py +26 -7
- chatlas-0.9.2/docs/get-started/models.qmd +0 -66
- chatlas-0.9.2/docs/reference/Chat.qmd +0 -560
- chatlas-0.9.2/docs/reference/ChatAnthropic.qmd +0 -99
- chatlas-0.9.2/docs/reference/ChatAuto.qmd +0 -78
- chatlas-0.9.2/docs/reference/ChatAzureOpenAI.qmd +0 -55
- chatlas-0.9.2/docs/reference/ChatBedrockAnthropic.qmd +0 -123
- chatlas-0.9.2/docs/reference/ChatDatabricks.qmd +0 -63
- chatlas-0.9.2/docs/reference/ChatGithub.qmd +0 -97
- chatlas-0.9.2/docs/reference/ChatGoogle.qmd +0 -91
- chatlas-0.9.2/docs/reference/ChatGroq.qmd +0 -95
- chatlas-0.9.2/docs/reference/ChatOllama.qmd +0 -66
- chatlas-0.9.2/docs/reference/ChatOpenAI.qmd +0 -94
- chatlas-0.9.2/docs/reference/ChatPerplexity.qmd +0 -97
- chatlas-0.9.2/docs/reference/ChatSnowflake.qmd +0 -62
- chatlas-0.9.2/docs/reference/ChatVertex.qmd +0 -61
- chatlas-0.9.2/docs/reference/Provider.qmd +0 -16
- chatlas-0.9.2/docs/reference/Tool.qmd +0 -74
- chatlas-0.9.2/docs/reference/ToolRejectError.qmd +0 -51
- chatlas-0.9.2/docs/reference/Turn.qmd +0 -56
- chatlas-0.9.2/docs/reference/content_image_file.qmd +0 -43
- chatlas-0.9.2/docs/reference/content_image_plot.qmd +0 -46
- chatlas-0.9.2/docs/reference/content_image_url.qmd +0 -41
- chatlas-0.9.2/docs/reference/content_pdf_file.qmd +0 -22
- chatlas-0.9.2/docs/reference/content_pdf_url.qmd +0 -22
- chatlas-0.9.2/docs/reference/image_file.qmd +0 -43
- chatlas-0.9.2/docs/reference/image_plot.qmd +0 -46
- chatlas-0.9.2/docs/reference/image_url.qmd +0 -41
- chatlas-0.9.2/docs/reference/index.qmd +0 -106
- chatlas-0.9.2/docs/reference/interpolate.qmd +0 -37
- chatlas-0.9.2/docs/reference/interpolate_file.qmd +0 -39
- chatlas-0.9.2/docs/reference/token_usage.qmd +0 -16
- chatlas-0.9.2/docs/reference/types.ChatResponse.qmd +0 -41
- chatlas-0.9.2/docs/reference/types.ChatResponseAsync.qmd +0 -41
- chatlas-0.9.2/docs/reference/types.Content.qmd +0 -7
- chatlas-0.9.2/docs/reference/types.ContentImage.qmd +0 -11
- chatlas-0.9.2/docs/reference/types.ContentImageInline.qmd +0 -18
- chatlas-0.9.2/docs/reference/types.ContentImageRemote.qmd +0 -17
- chatlas-0.9.2/docs/reference/types.ContentJson.qmd +0 -16
- chatlas-0.9.2/docs/reference/types.ContentText.qmd +0 -7
- chatlas-0.9.2/docs/reference/types.ContentToolRequest.qmd +0 -33
- chatlas-0.9.2/docs/reference/types.ContentToolResult.qmd +0 -57
- chatlas-0.9.2/docs/reference/types.ImageContentTypes.qmd +0 -5
- chatlas-0.9.2/docs/reference/types.MISSING.qmd +0 -4
- chatlas-0.9.2/docs/reference/types.MISSING_TYPE.qmd +0 -7
- chatlas-0.9.2/docs/reference/types.SubmitInputArgsT.qmd +0 -6
- chatlas-0.9.2/docs/reference/types.TokenUsage.qmd +0 -7
- chatlas-0.9.2/tests/test_provider_bedrock.py +0 -72
- {chatlas-0.9.2 → chatlas-0.11.0}/.github/workflows/check-update-types.yml +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/.github/workflows/docs-publish.yml +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/.github/workflows/release.yml +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/.github/workflows/test.yml +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/.github/workflows/update-pricing.yml +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/.gitignore +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/.vscode/extensions.json +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/.vscode/settings.json +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/LICENSE +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/Makefile +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_auto.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_callbacks.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_content_image.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_content_pdf.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_display.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_interpolate.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_live_render.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_logging.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_mcp_manager.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_merge.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_provider_groq.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_tokens_old.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_turn.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/_utils.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/py.typed +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/types/anthropic/__init__.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/types/anthropic/_submit.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/types/google/__init__.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/types/google/_client.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/types/google/_submit.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/chatlas/types/openai/__init__.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/_extensions/machow/interlinks/.gitignore +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/_extensions/machow/interlinks/_extension.yml +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/_extensions/machow/interlinks/interlinks.lua +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/_sidebar.yml +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/congressional-assets.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/get-started/async.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/get-started/chat.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/get-started/chatbots.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/get-started/parameters.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/get-started/stream.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/get-started/structured-data.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/get-started/system-prompt.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/get-started/tools.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/chat-app.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/chat-console.mp4 +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/chat-console.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/chat-notebook.mp4 +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/chat-parameters.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/chatbot-gradio.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/chatbot-shiny.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/chatbot-streamlit.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/chatbot-textual.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/chatlas-hello.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/client-parameters.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/congressional-assets.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/hello-chat-console.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/model-parameters.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/model-type-hints.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/posit-logo.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/shiny-mcp-run-python.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/shiny-tool-call-display.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/shiny-tool-call-map.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/tool-calling-right.svg +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/images/tool-calling-wrong.svg +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/index.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/logos/hero/hero-old.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/logos/hero/hero.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/logos/hex/logo.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/logos/small/logo.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/misc/RAG.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/misc/examples.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/misc/mcp-tools.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/misc/vocabulary.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/structured-data/article-summary.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/structured-data/classification.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/structured-data/entity-recognition.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/structured-data/multi-modal.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/structured-data/sentiment-analysis.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/styles.scss +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/tool-calling/approval.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/tool-calling/displays.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/tool-calling/how-it-works.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/docs/why-chatlas.qmd +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/pyproject.toml +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/pytest.ini +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/scripts/_generate_anthropic_types.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/scripts/main.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/__init__.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/__snapshots__/test_chat.ambr +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/apples.pdf +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/images/dice.png +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/mcp_servers/http_add.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/mcp_servers/http_current_date.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/mcp_servers/stdio_current_date.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/mcp_servers/stdio_subtract_multiply.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_auto.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_callbacks.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_chat.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_content.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_content_html.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_content_image.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_content_pdf.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_interpolate.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_mcp_client.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_provider_azure.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_provider_databricks.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_provider_snowflake.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_set_model_params.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_turns.py +0 -0
- {chatlas-0.9.2 → chatlas-0.11.0}/tests/test_utils_merge.py +0 -0
|
@@ -7,6 +7,41 @@ 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.11.0] - 2025-08-26
|
|
11
|
+
|
|
12
|
+
### New features
|
|
13
|
+
|
|
14
|
+
* The `Chat` class gains a new `.list_models()` method for obtaining a list of model ids/names, pricing info, and more. (#155)
|
|
15
|
+
* `Chat`'s `.register_tool()` method gains an `annotations` parameter, which is useful for describing the tool and its behavior. This information is attached to `ContentToolRequest()` and `ContentToolResult()` (via the `.request` parameter) objects when tool calls occur. To include these objects in streaming content, make sure to set `.stream(content="all")`. (#156)
|
|
16
|
+
|
|
17
|
+
### Improvements
|
|
18
|
+
|
|
19
|
+
* Tools registered via MCP (e.g., `.register_mcp_tools_http_stream_async()`) now automatically pick up on tool annotations. (#156)
|
|
20
|
+
|
|
21
|
+
### Changes
|
|
22
|
+
|
|
23
|
+
* `ChatGithub()` changed its default for `base_url` from <https://models.inference.ai.azure.com> to <https://models.github.ai/inference/>. As a result, more models are available (by default). (#155)
|
|
24
|
+
|
|
25
|
+
## [0.10.0] - 2025-08-19
|
|
26
|
+
|
|
27
|
+
### New features
|
|
28
|
+
|
|
29
|
+
* Added `ChatCloudflare()` for chatting via [Cloudflare AI](https://developers.cloudflare.com/workers-ai/get-started/rest-api/). (#150)
|
|
30
|
+
* Added `ChatDeepSeek()` for chatting via [DeepSeek](https://www.deepseek.com/). (#147)
|
|
31
|
+
* Added `ChatOpenRouter()` for chatting via [Open Router](https://openrouter.ai/). (#148)
|
|
32
|
+
* Added `ChatHuggingFace()` for chatting via [Hugging Face](https://huggingface.co/). (#144)
|
|
33
|
+
* Added `ChatMistral()` for chatting via [Mistral AI](https://mistral.ai/). (#145)
|
|
34
|
+
* Added `ChatPortkey()` for chatting via [Portkey AI](https://portkey.ai/). (#143)
|
|
35
|
+
|
|
36
|
+
### Changes
|
|
37
|
+
|
|
38
|
+
* `ChatAnthropic()` and `ChatBedrockAnthropic()` now default to Claude Sonnet 4.0.
|
|
39
|
+
|
|
40
|
+
### Bug fixes
|
|
41
|
+
|
|
42
|
+
* Fixed an issue where chatting with some models was leading to `KeyError: 'cached_input'`. (#149)
|
|
43
|
+
|
|
44
|
+
|
|
10
45
|
## [0.9.2] - 2025-08-08
|
|
11
46
|
|
|
12
47
|
### Improvements
|
chatlas-0.11.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Development Commands
|
|
6
|
+
|
|
7
|
+
The project uses `uv` for package management and Make for common tasks:
|
|
8
|
+
|
|
9
|
+
- **Setup environment**: `make setup` (installs all dependencies with `uv sync --all-extras`)
|
|
10
|
+
- **Run tests**: `make check-tests` or `uv run pytest`
|
|
11
|
+
- **Type checking**: `make check-types` or `uv run pyright`
|
|
12
|
+
- **Linting/formatting**: `make check-format` (check) or `make format` (fix)
|
|
13
|
+
- **Full checks**: `make check` (runs format, type, and test checks)
|
|
14
|
+
- **Build package**: `make build` (creates dist/ with built package)
|
|
15
|
+
- **Run single test**: `uv run pytest tests/test_specific_file.py::TestClass::test_method -v`
|
|
16
|
+
- **Update snapshots**: `make update-snaps` (for syrupy snapshot tests)
|
|
17
|
+
- **Documentation**: `make docs` (build) or `make docs-preview` (serve locally)
|
|
18
|
+
|
|
19
|
+
## Project Architecture
|
|
20
|
+
|
|
21
|
+
### Core Components
|
|
22
|
+
|
|
23
|
+
**Chat System**: The main `Chat` class in `_chat.py` manages conversation state and provider interactions. It's a generic class that works with different providers through the `Provider` abstract base class.
|
|
24
|
+
|
|
25
|
+
**Provider Pattern**: All LLM providers (OpenAI, Anthropic, Google, etc.) inherit from `Provider` in `_provider.py`. Each provider (e.g., `_provider_openai.py`) implements:
|
|
26
|
+
- Model-specific parameter handling
|
|
27
|
+
- API client configuration
|
|
28
|
+
- Request/response transformation
|
|
29
|
+
- Tool calling integration
|
|
30
|
+
|
|
31
|
+
**Content System**: The `_content.py` module defines structured content types:
|
|
32
|
+
- `ContentText`: Plain text messages
|
|
33
|
+
- `ContentImage`: Image content (inline, remote, or file-based)
|
|
34
|
+
- `ContentToolRequest`/`ContentToolResult`: Tool interaction messages
|
|
35
|
+
- `ContentJson`: Structured data responses
|
|
36
|
+
|
|
37
|
+
**Tool System**: Tools are defined in `_tools.py` and allow LLMs to call Python functions. The system supports:
|
|
38
|
+
- Function registration with automatic schema generation
|
|
39
|
+
- Tool approval workflows
|
|
40
|
+
- MCP (Model Context Protocol) server integration via `_mcp_manager.py`
|
|
41
|
+
|
|
42
|
+
**Turn Management**: `Turn` objects in `_turn.py` represent individual conversation exchanges, containing sequences of `Content` objects.
|
|
43
|
+
|
|
44
|
+
### Key Patterns
|
|
45
|
+
|
|
46
|
+
1. **Provider Abstraction**: All providers implement the same interface but handle model-specific details internally
|
|
47
|
+
2. **Generic Typing**: Heavy use of TypeVars and generics for type safety across providers
|
|
48
|
+
3. **Streaming Support**: Both sync and async streaming responses via `ChatResponse`/`ChatResponseAsync`
|
|
49
|
+
4. **Content-Based Messaging**: All communication uses structured `Content` objects rather than raw strings
|
|
50
|
+
5. **Tool Integration**: Seamless function calling with automatic JSON schema generation from Python type hints
|
|
51
|
+
|
|
52
|
+
### Testing Structure
|
|
53
|
+
|
|
54
|
+
- Tests are organized by component (e.g., `test_provider_openai.py`, `test_tools.py`)
|
|
55
|
+
- Snapshot testing with `syrupy` for response validation
|
|
56
|
+
- MCP server tests use local test servers in `tests/mcp_servers/`
|
|
57
|
+
- Async tests configured via `pytest.ini` with `asyncio_mode=strict`
|
|
58
|
+
|
|
59
|
+
### Documentation
|
|
60
|
+
|
|
61
|
+
Documentation is built with Quarto and quartodoc:
|
|
62
|
+
- API reference generated from docstrings in `chatlas/` modules
|
|
63
|
+
- Guides and examples in `docs/` as `.qmd` files
|
|
64
|
+
- Type definitions in `chatlas/types/` provide provider-specific parameter types
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
## Adding New Providers
|
|
68
|
+
|
|
69
|
+
When implementing a new LLM provider, follow this systematic approach:
|
|
70
|
+
|
|
71
|
+
### 1. Research Phase
|
|
72
|
+
- **Check ellmer first**: Look in `../ellmer/R/provider-*.R` for existing implementations
|
|
73
|
+
- **Identify base provider**: Most providers inherit from either `OpenAIProvider` (for OpenAI-compatible APIs) or implement `Provider` directly
|
|
74
|
+
- **Check existing patterns**: Review similar providers in `chatlas/_provider_*.py`
|
|
75
|
+
|
|
76
|
+
### 2. Implementation Steps
|
|
77
|
+
1. **Create provider file**: `chatlas/_provider_[name].py`
|
|
78
|
+
- Use PascalCase for class names (e.g., `MistralProvider`)
|
|
79
|
+
- Use snake_case for function names (e.g., `ChatMistral`)
|
|
80
|
+
- Follow existing docstring patterns with Prerequisites, Examples, Parameters, Returns sections
|
|
81
|
+
|
|
82
|
+
2. **Provider class structure**:
|
|
83
|
+
```python
|
|
84
|
+
class [Name]Provider(OpenAIProvider): # or Provider if custom
|
|
85
|
+
def __init__(self, ...):
|
|
86
|
+
super().__init__(...)
|
|
87
|
+
# Provider-specific initialization
|
|
88
|
+
|
|
89
|
+
def _chat_perform_args(self, ...):
|
|
90
|
+
# Customize request parameters if needed
|
|
91
|
+
kwargs = super()._chat_perform_args(...)
|
|
92
|
+
# Apply provider-specific modifications
|
|
93
|
+
return kwargs
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
3. **Chat function signature**:
|
|
97
|
+
```python
|
|
98
|
+
def Chat[Name](
|
|
99
|
+
*,
|
|
100
|
+
system_prompt: Optional[str] = None,
|
|
101
|
+
model: Optional[str] = None,
|
|
102
|
+
api_key: Optional[str] = None,
|
|
103
|
+
base_url: str = "https://...",
|
|
104
|
+
seed: int | None | MISSING_TYPE = MISSING,
|
|
105
|
+
kwargs: Optional["ChatClientArgs"] = None,
|
|
106
|
+
) -> Chat["SubmitInputArgs", ChatCompletion]:
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 3. Testing Setup
|
|
110
|
+
1. **Create test file**: `tests/test_provider_[name].py`
|
|
111
|
+
2. **Add environment variable skip pattern**:
|
|
112
|
+
```python
|
|
113
|
+
import os
|
|
114
|
+
import pytest
|
|
115
|
+
|
|
116
|
+
do_test = os.getenv("TEST_[NAME]", "true")
|
|
117
|
+
if do_test.lower() == "false":
|
|
118
|
+
pytest.skip("Skipping [Name] tests", allow_module_level=True)
|
|
119
|
+
```
|
|
120
|
+
3. **Use standard test patterns**:
|
|
121
|
+
- `test_[name]_simple_request()`
|
|
122
|
+
- `test_[name]_simple_streaming_request()`
|
|
123
|
+
- `test_[name]_respects_turns_interface()`
|
|
124
|
+
- `test_[name]_tool_variations()` (if supported)
|
|
125
|
+
- `test_data_extraction()`
|
|
126
|
+
- `test_[name]_images()` (if vision supported)
|
|
127
|
+
|
|
128
|
+
### 4. Package Integration
|
|
129
|
+
1. **Update `chatlas/__init__.py`**:
|
|
130
|
+
- Add import: `from ._provider_[name] import Chat[Name]`
|
|
131
|
+
- Add to `__all__` tuple: `"Chat[Name]"`
|
|
132
|
+
|
|
133
|
+
2. **Run validation**:
|
|
134
|
+
```bash
|
|
135
|
+
uv run pyright chatlas/_provider_[name].py
|
|
136
|
+
TEST_[NAME]=false uv run pytest tests/test_provider_[name].py -v
|
|
137
|
+
uv run python -c "from chatlas import Chat[Name]; print('Import successful')"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 5. Provider-Specific Customizations
|
|
141
|
+
|
|
142
|
+
**OpenAI-Compatible Providers**:
|
|
143
|
+
- Inherit from `OpenAIProvider`
|
|
144
|
+
- Override `_chat_perform_args()` for API differences
|
|
145
|
+
- Common customizations: remove `stream_options`, adjust parameter names, modify headers
|
|
146
|
+
|
|
147
|
+
**Custom API Providers**:
|
|
148
|
+
- Inherit from `Provider` directly
|
|
149
|
+
- Implement all abstract methods: `chat_perform()`, `chat_perform_async()`, `stream_text()`, etc.
|
|
150
|
+
- Handle model-specific response formats
|
|
151
|
+
|
|
152
|
+
### 6. Common Patterns
|
|
153
|
+
- **Environment variables**: Use `[PROVIDER]_API_KEY` format
|
|
154
|
+
- **Default models**: Use provider's recommended general-purpose model
|
|
155
|
+
- **Seed handling**: `seed = 1014 if is_testing() else None` when MISSING
|
|
156
|
+
- **Error handling**: Provider APIs often return different error formats
|
|
157
|
+
- **Rate limiting**: Consider implementing client-side throttling for providers that need it
|
|
158
|
+
|
|
159
|
+
### 7. Documentation Requirements
|
|
160
|
+
- Include provider description and prerequisites
|
|
161
|
+
- Document known limitations (tool calling, vision support, etc.)
|
|
162
|
+
- Provide working examples with environment variable usage
|
|
163
|
+
- Note any special model requirements (e.g., vision models for images)
|
|
164
|
+
|
|
165
|
+
## Connections to ellmer
|
|
166
|
+
|
|
167
|
+
This project is the Python equivalent of the R package ellmer. The source code for ellmer is available in a sibling directory to this project. Before implementing new features or bug fixes in chatlas, it may be useful to consult the ellmer codebase to: (1) check whether the feature/fix already exists on the R side and (2) make sure the projects are aligned in terms of stylistic approaches. Note also that ellmer itself has a CLAUDE.md file which has a useful overview of the project.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chatlas
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Summary: A simple and consistent interface for chatting with LLMs
|
|
5
5
|
Project-URL: Homepage, https://posit-dev.github.io/chatlas
|
|
6
6
|
Project-URL: Documentation, https://posit-dev.github.io/chatlas
|
|
@@ -79,7 +79,7 @@ Provides-Extra: vertex
|
|
|
79
79
|
Requires-Dist: google-genai>=1.14.0; extra == 'vertex'
|
|
80
80
|
Description-Content-Type: text/markdown
|
|
81
81
|
|
|
82
|
-
# chatlas <a href="https://posit-dev.github.io/chatlas"><img src="
|
|
82
|
+
# chatlas <a href="https://posit-dev.github.io/chatlas"><img src="https://posit-dev.github.io/chatlas/logos/hex/logo.png" align="right" height="138" alt="chatlas website" /></a>
|
|
83
83
|
|
|
84
84
|
<p>
|
|
85
85
|
<!-- badges start -->
|
|
@@ -135,7 +135,7 @@ chat.chat("How's the weather in San Francisco?")
|
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
<img src="
|
|
138
|
+
<img src="https://posit-dev.github.io/chatlas/images/chatlas-hello.png" alt="Model response output to the user query: 'How's the weather in San Francisco?'" width="67%" style="display: block; margin-left: auto; margin-right: auto">
|
|
139
139
|
|
|
140
140
|
|
|
141
141
|
Learn more at <https://posit-dev.github.io/chatlas>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# chatlas <a href="https://posit-dev.github.io/chatlas"><img src="
|
|
1
|
+
# chatlas <a href="https://posit-dev.github.io/chatlas"><img src="https://posit-dev.github.io/chatlas/logos/hex/logo.png" align="right" height="138" alt="chatlas website" /></a>
|
|
2
2
|
|
|
3
3
|
<p>
|
|
4
4
|
<!-- badges start -->
|
|
@@ -54,7 +54,7 @@ chat.chat("How's the weather in San Francisco?")
|
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
<img src="
|
|
57
|
+
<img src="https://posit-dev.github.io/chatlas/images/chatlas-hello.png" alt="Model response output to the user query: 'How's the weather in San Francisco?'" width="67%" style="display: block; margin-left: auto; margin-right: auto">
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
Learn more at <https://posit-dev.github.io/chatlas>
|
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
from . import types
|
|
2
2
|
from ._auto import ChatAuto
|
|
3
3
|
from ._chat import Chat
|
|
4
|
-
from ._content import
|
|
4
|
+
from ._content import (
|
|
5
|
+
ContentToolRequest,
|
|
6
|
+
ContentToolResult,
|
|
7
|
+
ContentToolResultImage,
|
|
8
|
+
ContentToolResultResource,
|
|
9
|
+
)
|
|
5
10
|
from ._content_image import content_image_file, content_image_plot, content_image_url
|
|
6
11
|
from ._content_pdf import content_pdf_file, content_pdf_url
|
|
7
12
|
from ._interpolate import interpolate, interpolate_file
|
|
8
13
|
from ._provider import Provider
|
|
9
14
|
from ._provider_anthropic import ChatAnthropic, ChatBedrockAnthropic
|
|
15
|
+
from ._provider_cloudflare import ChatCloudflare
|
|
10
16
|
from ._provider_databricks import ChatDatabricks
|
|
17
|
+
from ._provider_deepseek import ChatDeepSeek
|
|
11
18
|
from ._provider_github import ChatGithub
|
|
12
19
|
from ._provider_google import ChatGoogle, ChatVertex
|
|
13
20
|
from ._provider_groq import ChatGroq
|
|
21
|
+
from ._provider_huggingface import ChatHuggingFace
|
|
22
|
+
from ._provider_mistral import ChatMistral
|
|
14
23
|
from ._provider_ollama import ChatOllama
|
|
15
24
|
from ._provider_openai import ChatAzureOpenAI, ChatOpenAI
|
|
25
|
+
from ._provider_openrouter import ChatOpenRouter
|
|
16
26
|
from ._provider_perplexity import ChatPerplexity
|
|
27
|
+
from ._provider_portkey import ChatPortkey
|
|
17
28
|
from ._provider_snowflake import ChatSnowflake
|
|
18
29
|
from ._tokens import token_usage
|
|
19
30
|
from ._tools import Tool, ToolRejectError
|
|
@@ -28,14 +39,20 @@ __all__ = (
|
|
|
28
39
|
"ChatAnthropic",
|
|
29
40
|
"ChatAuto",
|
|
30
41
|
"ChatBedrockAnthropic",
|
|
42
|
+
"ChatCloudflare",
|
|
31
43
|
"ChatDatabricks",
|
|
44
|
+
"ChatDeepSeek",
|
|
32
45
|
"ChatGithub",
|
|
33
46
|
"ChatGoogle",
|
|
34
47
|
"ChatGroq",
|
|
48
|
+
"ChatHuggingFace",
|
|
49
|
+
"ChatMistral",
|
|
35
50
|
"ChatOllama",
|
|
36
51
|
"ChatOpenAI",
|
|
52
|
+
"ChatOpenRouter",
|
|
37
53
|
"ChatAzureOpenAI",
|
|
38
54
|
"ChatPerplexity",
|
|
55
|
+
"ChatPortkey",
|
|
39
56
|
"ChatSnowflake",
|
|
40
57
|
"ChatVertex",
|
|
41
58
|
"Chat",
|
|
@@ -47,6 +64,7 @@ __all__ = (
|
|
|
47
64
|
"ContentToolRequest",
|
|
48
65
|
"ContentToolResult",
|
|
49
66
|
"ContentToolResultImage",
|
|
67
|
+
"ContentToolResultResource",
|
|
50
68
|
"interpolate",
|
|
51
69
|
"interpolate_file",
|
|
52
70
|
"Provider",
|
|
@@ -56,3 +74,9 @@ __all__ = (
|
|
|
56
74
|
"Turn",
|
|
57
75
|
"types",
|
|
58
76
|
)
|
|
77
|
+
|
|
78
|
+
# Rebuild content models to resolve forward references to ToolAnnotation
|
|
79
|
+
ContentToolRequest.model_rebuild()
|
|
80
|
+
ContentToolResult.model_rebuild()
|
|
81
|
+
ContentToolResultImage.model_rebuild()
|
|
82
|
+
ContentToolResultResource.model_rebuild()
|
|
@@ -9,6 +9,7 @@ import warnings
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from threading import Thread
|
|
11
11
|
from typing import (
|
|
12
|
+
TYPE_CHECKING,
|
|
12
13
|
Any,
|
|
13
14
|
AsyncGenerator,
|
|
14
15
|
AsyncIterator,
|
|
@@ -43,13 +44,16 @@ from ._display import (
|
|
|
43
44
|
)
|
|
44
45
|
from ._logging import log_tool_error
|
|
45
46
|
from ._mcp_manager import MCPSessionManager
|
|
46
|
-
from ._provider import Provider, StandardModelParams, SubmitInputArgsT
|
|
47
|
+
from ._provider import ModelInfo, Provider, StandardModelParams, SubmitInputArgsT
|
|
47
48
|
from ._tokens import compute_cost, get_token_pricing
|
|
48
49
|
from ._tools import Tool, ToolRejectError
|
|
49
50
|
from ._turn import Turn, user_turn
|
|
50
51
|
from ._typing_extensions import TypedDict, TypeGuard
|
|
51
52
|
from ._utils import MISSING, MISSING_TYPE, html_escape, wrap_async
|
|
52
53
|
|
|
54
|
+
if TYPE_CHECKING:
|
|
55
|
+
from mcp.types import ToolAnnotations
|
|
56
|
+
|
|
53
57
|
|
|
54
58
|
class TokensDict(TypedDict):
|
|
55
59
|
"""
|
|
@@ -128,6 +132,78 @@ class Chat(Generic[SubmitInputArgsT, CompletionT]):
|
|
|
128
132
|
self._standard_model_params: StandardModelParams = {}
|
|
129
133
|
self._submit_input_kwargs: Optional[SubmitInputArgsT] = None
|
|
130
134
|
|
|
135
|
+
def list_models(self) -> list[ModelInfo]:
|
|
136
|
+
"""
|
|
137
|
+
List all models available for the provider.
|
|
138
|
+
|
|
139
|
+
This method returns detailed information about all models supported by the provider,
|
|
140
|
+
including model IDs, pricing information, creation dates, and other metadata. This is
|
|
141
|
+
useful for discovering available models and their characteristics without needing to
|
|
142
|
+
consult provider documentation.
|
|
143
|
+
|
|
144
|
+
Examples
|
|
145
|
+
--------
|
|
146
|
+
Get all available models:
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from chatlas import ChatOpenAI
|
|
150
|
+
|
|
151
|
+
chat = ChatOpenAI()
|
|
152
|
+
models = chat.list_models()
|
|
153
|
+
print(f"Found {len(models)} models")
|
|
154
|
+
print(f"First model: {models[0]['id']}")
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
View models in a table format:
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
import pandas as pd
|
|
161
|
+
from chatlas import ChatAnthropic
|
|
162
|
+
|
|
163
|
+
chat = ChatAnthropic()
|
|
164
|
+
df = pd.DataFrame(chat.list_models())
|
|
165
|
+
print(df[["id", "input", "output"]].head()) # Show pricing info
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Find models by criteria:
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
from chatlas import ChatGoogle
|
|
172
|
+
|
|
173
|
+
chat = ChatGoogle()
|
|
174
|
+
models = chat.list_models()
|
|
175
|
+
|
|
176
|
+
# Find cheapest input model
|
|
177
|
+
cheapest = min(models, key=lambda m: m.get("input", float("inf")))
|
|
178
|
+
print(f"Cheapest model: {cheapest['id']}")
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
list[ModelInfo]
|
|
184
|
+
A list of ModelInfo dictionaries containing model information. Each dictionary
|
|
185
|
+
contains:
|
|
186
|
+
|
|
187
|
+
- `id` (str): The model identifier to use with the Chat constructor
|
|
188
|
+
- `name` (str, optional): Human-readable model name
|
|
189
|
+
- `input` (float, optional): Cost per input token in USD per million tokens
|
|
190
|
+
- `output` (float, optional): Cost per output token in USD per million tokens
|
|
191
|
+
- `cached_input` (float, optional): Cost per cached input token in USD per million tokens
|
|
192
|
+
- `created_at` (date, optional): Date the model was created
|
|
193
|
+
- `owned_by` (str, optional): Organization that owns the model
|
|
194
|
+
- `provider` (str, optional): Model provider name
|
|
195
|
+
- `size` (int, optional): Model size in bytes
|
|
196
|
+
- `url` (str, optional): URL with more information about the model
|
|
197
|
+
|
|
198
|
+
The list is typically sorted by creation date (most recent first).
|
|
199
|
+
|
|
200
|
+
Note
|
|
201
|
+
----
|
|
202
|
+
Not all providers support this method. Some providers may raise NotImplementedError
|
|
203
|
+
with information about where to find model listings online.
|
|
204
|
+
"""
|
|
205
|
+
return self.provider.list_models()
|
|
206
|
+
|
|
131
207
|
def get_turns(
|
|
132
208
|
self,
|
|
133
209
|
*,
|
|
@@ -395,8 +471,8 @@ class Chat(Generic[SubmitInputArgsT, CompletionT]):
|
|
|
395
471
|
)
|
|
396
472
|
|
|
397
473
|
input_token_price = price_token["input"] / 1e6
|
|
398
|
-
output_token_price = price_token
|
|
399
|
-
cached_token_price = price_token
|
|
474
|
+
output_token_price = price_token.get("output", 0) / 1e6
|
|
475
|
+
cached_token_price = price_token.get("cached_input", 0) / 1e6
|
|
400
476
|
|
|
401
477
|
if len(turns_tokens) == 0:
|
|
402
478
|
return 0.0
|
|
@@ -1462,6 +1538,7 @@ class Chat(Generic[SubmitInputArgsT, CompletionT]):
|
|
|
1462
1538
|
*,
|
|
1463
1539
|
force: bool = False,
|
|
1464
1540
|
model: Optional[type[BaseModel]] = None,
|
|
1541
|
+
annotations: "Optional[ToolAnnotations]" = None,
|
|
1465
1542
|
):
|
|
1466
1543
|
"""
|
|
1467
1544
|
Register a tool (function) with the chat.
|
|
@@ -1539,13 +1616,16 @@ class Chat(Generic[SubmitInputArgsT, CompletionT]):
|
|
|
1539
1616
|
The primary reason why you might want to provide a model in
|
|
1540
1617
|
Note that the name and docstring of the model takes precedence over the
|
|
1541
1618
|
name and docstring of the function.
|
|
1619
|
+
annotations
|
|
1620
|
+
Additional properties that describe the tool and its behavior.
|
|
1621
|
+
Should be a `from mcp.types import ToolAnnotations` instance.
|
|
1542
1622
|
|
|
1543
1623
|
Raises
|
|
1544
1624
|
------
|
|
1545
1625
|
ValueError
|
|
1546
1626
|
If a tool with the same name already exists and `force` is `False`.
|
|
1547
1627
|
"""
|
|
1548
|
-
tool = Tool.from_func(func, model=model)
|
|
1628
|
+
tool = Tool.from_func(func, model=model, annotations=annotations)
|
|
1549
1629
|
if tool.name in self._tools and not force:
|
|
1550
1630
|
raise ValueError(
|
|
1551
1631
|
f"Tool with name '{tool.name}' is already registered. "
|
|
@@ -1853,6 +1933,7 @@ class Chat(Generic[SubmitInputArgsT, CompletionT]):
|
|
|
1853
1933
|
all_results: list[ContentToolResult] = []
|
|
1854
1934
|
for x in turn.contents:
|
|
1855
1935
|
if isinstance(x, ContentToolRequest):
|
|
1936
|
+
x.tool = self._tools.get(x.name)
|
|
1856
1937
|
if echo == "output":
|
|
1857
1938
|
self._echo_content(f"\n\n{x}\n\n")
|
|
1858
1939
|
if content == "all":
|
|
@@ -1913,6 +1994,7 @@ class Chat(Generic[SubmitInputArgsT, CompletionT]):
|
|
|
1913
1994
|
all_results: list[ContentToolResult] = []
|
|
1914
1995
|
for x in turn.contents:
|
|
1915
1996
|
if isinstance(x, ContentToolRequest):
|
|
1997
|
+
x.tool = self._tools.get(x.name)
|
|
1916
1998
|
if echo == "output":
|
|
1917
1999
|
self._echo_content(f"\n\n{x}\n\n")
|
|
1918
2000
|
if content == "all":
|
|
@@ -2070,8 +2152,8 @@ class Chat(Generic[SubmitInputArgsT, CompletionT]):
|
|
|
2070
2152
|
self._turns.extend([user_turn, turn])
|
|
2071
2153
|
|
|
2072
2154
|
def _invoke_tool(self, request: ContentToolRequest):
|
|
2073
|
-
|
|
2074
|
-
func =
|
|
2155
|
+
tool = request.tool
|
|
2156
|
+
func = tool.func if tool is not None else None
|
|
2075
2157
|
|
|
2076
2158
|
if func is None:
|
|
2077
2159
|
yield self._handle_tool_error_result(
|
|
@@ -2118,21 +2200,20 @@ class Chat(Generic[SubmitInputArgsT, CompletionT]):
|
|
|
2118
2200
|
yield self._handle_tool_error_result(request, e)
|
|
2119
2201
|
|
|
2120
2202
|
async def _invoke_tool_async(self, request: ContentToolRequest):
|
|
2121
|
-
|
|
2122
|
-
func = None
|
|
2123
|
-
if tool_def:
|
|
2124
|
-
if tool_def._is_async:
|
|
2125
|
-
func = tool_def.func
|
|
2126
|
-
else:
|
|
2127
|
-
func = wrap_async(tool_def.func)
|
|
2203
|
+
tool = request.tool
|
|
2128
2204
|
|
|
2129
|
-
if
|
|
2205
|
+
if tool is None:
|
|
2130
2206
|
yield self._handle_tool_error_result(
|
|
2131
2207
|
request,
|
|
2132
2208
|
error=RuntimeError("Unknown tool."),
|
|
2133
2209
|
)
|
|
2134
2210
|
return
|
|
2135
2211
|
|
|
2212
|
+
if tool._is_async:
|
|
2213
|
+
func = tool.func
|
|
2214
|
+
else:
|
|
2215
|
+
func = wrap_async(tool.func)
|
|
2216
|
+
|
|
2136
2217
|
# First, invoke the request callbacks. If a ToolRejectError is raised,
|
|
2137
2218
|
# treat it like a tool failure (i.e., gracefully handle it).
|
|
2138
2219
|
result: ContentToolResult | None = None
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from pprint import pformat
|
|
4
|
-
from typing import Any, Literal, Optional, Union
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, Union
|
|
5
5
|
|
|
6
6
|
import orjson
|
|
7
7
|
from pydantic import BaseModel, ConfigDict
|
|
8
8
|
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from ._tools import Tool
|
|
11
|
+
|
|
9
12
|
ImageContentTypes = Literal[
|
|
10
13
|
"image/png",
|
|
11
14
|
"image/jpeg",
|
|
@@ -171,11 +174,15 @@ class ContentToolRequest(Content):
|
|
|
171
174
|
The name of the tool/function to call.
|
|
172
175
|
arguments
|
|
173
176
|
The arguments to pass to the tool/function.
|
|
177
|
+
tool
|
|
178
|
+
The tool/function to be called. This is set internally by chatlas's tool
|
|
179
|
+
calling loop.
|
|
174
180
|
"""
|
|
175
181
|
|
|
176
182
|
id: str
|
|
177
183
|
name: str
|
|
178
184
|
arguments: object
|
|
185
|
+
tool: Optional["Tool"] = None
|
|
179
186
|
|
|
180
187
|
content_type: ContentTypeEnum = "tool_request"
|
|
181
188
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
|
+
from datetime import date
|
|
4
5
|
from typing import (
|
|
5
6
|
AsyncIterable,
|
|
6
7
|
Generic,
|
|
@@ -16,7 +17,7 @@ from pydantic import BaseModel
|
|
|
16
17
|
from ._content import Content
|
|
17
18
|
from ._tools import Tool
|
|
18
19
|
from ._turn import Turn
|
|
19
|
-
from ._typing_extensions import TypedDict
|
|
20
|
+
from ._typing_extensions import NotRequired, TypedDict
|
|
20
21
|
|
|
21
22
|
ChatCompletionT = TypeVar("ChatCompletionT")
|
|
22
23
|
ChatCompletionChunkT = TypeVar("ChatCompletionChunkT")
|
|
@@ -35,6 +36,40 @@ submitting input to a model provider.
|
|
|
35
36
|
"""
|
|
36
37
|
|
|
37
38
|
|
|
39
|
+
class ModelInfo(TypedDict):
|
|
40
|
+
"Information returned from the `.list_models()` method"
|
|
41
|
+
|
|
42
|
+
id: str
|
|
43
|
+
"The model ID (this gets passed to the `model` parameter of the `Chat` constructor)"
|
|
44
|
+
|
|
45
|
+
cached_input: NotRequired[float | None]
|
|
46
|
+
"The cost per user token in USD per million tokens for cached input"
|
|
47
|
+
|
|
48
|
+
input: NotRequired[float | None]
|
|
49
|
+
"The cost per user token in USD per million tokens"
|
|
50
|
+
|
|
51
|
+
output: NotRequired[float | None]
|
|
52
|
+
"The cost per assistant token in USD per million tokens"
|
|
53
|
+
|
|
54
|
+
created_at: NotRequired[date]
|
|
55
|
+
"The date the model was created"
|
|
56
|
+
|
|
57
|
+
name: NotRequired[str]
|
|
58
|
+
"The model name"
|
|
59
|
+
|
|
60
|
+
owned_by: NotRequired[str]
|
|
61
|
+
"The owner of the model"
|
|
62
|
+
|
|
63
|
+
size: NotRequired[int]
|
|
64
|
+
"The size of the model in bytes"
|
|
65
|
+
|
|
66
|
+
provider: NotRequired[str]
|
|
67
|
+
"The provider of the model"
|
|
68
|
+
|
|
69
|
+
url: NotRequired[str]
|
|
70
|
+
"A URL to learn more about the model"
|
|
71
|
+
|
|
72
|
+
|
|
38
73
|
class StandardModelParams(TypedDict, total=False):
|
|
39
74
|
"""
|
|
40
75
|
A TypedDict representing the standard model parameters that can be set
|
|
@@ -102,6 +137,13 @@ class Provider(
|
|
|
102
137
|
"""
|
|
103
138
|
return self._model
|
|
104
139
|
|
|
140
|
+
@abstractmethod
|
|
141
|
+
def list_models(self) -> list[ModelInfo]:
|
|
142
|
+
"""
|
|
143
|
+
List all available models for the provider.
|
|
144
|
+
"""
|
|
145
|
+
pass
|
|
146
|
+
|
|
105
147
|
@overload
|
|
106
148
|
@abstractmethod
|
|
107
149
|
def chat_perform(
|