chatlas 0.4.0__tar.gz → 0.5.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.

Files changed (164) hide show
  1. {chatlas-0.4.0 → chatlas-0.5.0}/.gitignore +3 -0
  2. {chatlas-0.4.0 → chatlas-0.5.0}/CHANGELOG.md +19 -0
  3. {chatlas-0.4.0 → chatlas-0.5.0}/Makefile +1 -1
  4. {chatlas-0.4.0 → chatlas-0.5.0}/PKG-INFO +26 -1
  5. {chatlas-0.4.0 → chatlas-0.5.0}/README.md +1 -0
  6. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/__init__.py +9 -0
  7. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_anthropic.py +5 -5
  8. chatlas-0.5.0/chatlas/_auto.py +183 -0
  9. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_chat.py +3 -1
  10. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_content.py +13 -10
  11. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_display.py +12 -2
  12. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_github.py +1 -1
  13. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_google.py +4 -6
  14. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_groq.py +1 -1
  15. chatlas-0.5.0/chatlas/_live_render.py +116 -0
  16. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_ollama.py +1 -1
  17. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_openai.py +3 -2
  18. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_perplexity.py +1 -1
  19. chatlas-0.5.0/chatlas/_snowflake.py +321 -0
  20. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_utils.py +7 -0
  21. chatlas-0.5.0/chatlas/_version.py +21 -0
  22. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/types/anthropic/_submit.py +23 -1
  23. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/types/openai/_submit.py +6 -1
  24. chatlas-0.5.0/chatlas/types/snowflake/__init__.py +8 -0
  25. chatlas-0.5.0/chatlas/types/snowflake/_submit.py +24 -0
  26. {chatlas-0.4.0 → chatlas-0.5.0}/docs/_quarto.yml +2 -0
  27. {chatlas-0.4.0 → chatlas-0.5.0}/docs/get-started.qmd +1 -1
  28. {chatlas-0.4.0 → chatlas-0.5.0}/pyproject.toml +18 -0
  29. {chatlas-0.4.0 → chatlas-0.5.0}/scripts/_generate_openai_types.py +3 -3
  30. chatlas-0.5.0/scripts/_generate_snowflake_types.py +33 -0
  31. {chatlas-0.4.0 → chatlas-0.5.0}/scripts/main.py +1 -0
  32. chatlas-0.5.0/tests/test_auto.py +109 -0
  33. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_provider_anthropic.py +7 -2
  34. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_provider_azure.py +3 -2
  35. {chatlas-0.4.0 → chatlas-0.5.0}/.github/workflows/check-update-types.yml +0 -0
  36. {chatlas-0.4.0 → chatlas-0.5.0}/.github/workflows/docs-publish.yml +0 -0
  37. {chatlas-0.4.0 → chatlas-0.5.0}/.github/workflows/release.yml +0 -0
  38. {chatlas-0.4.0 → chatlas-0.5.0}/.github/workflows/test.yml +0 -0
  39. {chatlas-0.4.0 → chatlas-0.5.0}/.vscode/extensions.json +0 -0
  40. {chatlas-0.4.0 → chatlas-0.5.0}/.vscode/settings.json +0 -0
  41. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_content_image.py +0 -0
  42. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_interpolate.py +0 -0
  43. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_logging.py +0 -0
  44. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_merge.py +0 -0
  45. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_provider.py +0 -0
  46. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_tokens.py +0 -0
  47. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_tokens_old.py +0 -0
  48. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_tools.py +0 -0
  49. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_turn.py +0 -0
  50. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/_typing_extensions.py +0 -0
  51. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/py.typed +0 -0
  52. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/types/__init__.py +0 -0
  53. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/types/anthropic/__init__.py +0 -0
  54. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/types/anthropic/_client.py +0 -0
  55. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/types/anthropic/_client_bedrock.py +0 -0
  56. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/types/google/__init__.py +0 -0
  57. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/types/google/_client.py +0 -0
  58. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/types/google/_submit.py +0 -0
  59. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/types/openai/__init__.py +0 -0
  60. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/types/openai/_client.py +0 -0
  61. {chatlas-0.4.0 → chatlas-0.5.0}/chatlas/types/openai/_client_azure.py +0 -0
  62. {chatlas-0.4.0 → chatlas-0.5.0}/docs/.gitignore +0 -0
  63. {chatlas-0.4.0 → chatlas-0.5.0}/docs/_extensions/machow/interlinks/.gitignore +0 -0
  64. {chatlas-0.4.0 → chatlas-0.5.0}/docs/_extensions/machow/interlinks/_extension.yml +0 -0
  65. {chatlas-0.4.0 → chatlas-0.5.0}/docs/_extensions/machow/interlinks/interlinks.lua +0 -0
  66. {chatlas-0.4.0 → chatlas-0.5.0}/docs/_sidebar.yml +0 -0
  67. {chatlas-0.4.0 → chatlas-0.5.0}/docs/congressional-assets.png +0 -0
  68. {chatlas-0.4.0 → chatlas-0.5.0}/docs/examples/third-party-testing.txt +0 -0
  69. {chatlas-0.4.0 → chatlas-0.5.0}/docs/images/congressional-assets.png +0 -0
  70. {chatlas-0.4.0 → chatlas-0.5.0}/docs/images/logo.png +0 -0
  71. {chatlas-0.4.0 → chatlas-0.5.0}/docs/images/posit-logo.png +0 -0
  72. {chatlas-0.4.0 → chatlas-0.5.0}/docs/images/tool-calling-right.svg +0 -0
  73. {chatlas-0.4.0 → chatlas-0.5.0}/docs/images/tool-calling-wrong.svg +0 -0
  74. {chatlas-0.4.0 → chatlas-0.5.0}/docs/index.py +0 -0
  75. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/favicon/android-chrome-192x192.png +0 -0
  76. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/favicon/android-chrome-512x512.png +0 -0
  77. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/favicon/apple-touch-icon.png +0 -0
  78. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/favicon/favicon-16x16.png +0 -0
  79. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/favicon/favicon-32x32.png +0 -0
  80. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/favicon/favicon.ico +0 -0
  81. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/icon/brand-yml-icon-black.png +0 -0
  82. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/icon/brand-yml-icon-black.svg +0 -0
  83. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/icon/brand-yml-icon-color.png +0 -0
  84. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/icon/brand-yml-icon-color.svg +0 -0
  85. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/icon/brand-yml-icon-white.png +0 -0
  86. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/icon/brand-yml-icon-white.svg +0 -0
  87. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/tall/brand-yml-tall-black.png +0 -0
  88. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/tall/brand-yml-tall-black.svg +0 -0
  89. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/tall/brand-yml-tall-color.png +0 -0
  90. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/tall/brand-yml-tall-color.svg +0 -0
  91. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/tall/brand-yml-tall-white.png +0 -0
  92. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/tall/brand-yml-tall-white.svg +0 -0
  93. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/wide/brand-yml-wide-black.png +0 -0
  94. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/wide/brand-yml-wide-black.svg +0 -0
  95. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/wide/brand-yml-wide-color.png +0 -0
  96. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/wide/brand-yml-wide-color.svg +0 -0
  97. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/wide/brand-yml-wide-large-black.png +0 -0
  98. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/wide/brand-yml-wide-large-color.png +0 -0
  99. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/wide/brand-yml-wide-large-white.png +0 -0
  100. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/wide/brand-yml-wide-white.png +0 -0
  101. {chatlas-0.4.0 → chatlas-0.5.0}/docs/logos/wide/brand-yml-wide-white.svg +0 -0
  102. {chatlas-0.4.0 → chatlas-0.5.0}/docs/prompt-design.qmd +0 -0
  103. {chatlas-0.4.0 → chatlas-0.5.0}/docs/rag.qmd +0 -0
  104. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/Chat.qmd +0 -0
  105. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/ChatAnthropic.qmd +0 -0
  106. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/ChatAzureOpenAI.qmd +0 -0
  107. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/ChatBedrockAnthropic.qmd +0 -0
  108. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/ChatGithub.qmd +0 -0
  109. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/ChatGoogle.qmd +0 -0
  110. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/ChatGroq.qmd +0 -0
  111. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/ChatOllama.qmd +0 -0
  112. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/ChatOpenAI.qmd +0 -0
  113. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/ChatPerplexity.qmd +0 -0
  114. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/ChatVertex.qmd +0 -0
  115. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/Provider.qmd +0 -0
  116. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/Tool.qmd +0 -0
  117. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/Turn.qmd +0 -0
  118. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/content_image_file.qmd +0 -0
  119. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/content_image_plot.qmd +0 -0
  120. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/content_image_url.qmd +0 -0
  121. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/image_file.qmd +0 -0
  122. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/image_plot.qmd +0 -0
  123. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/image_url.qmd +0 -0
  124. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/index.qmd +0 -0
  125. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/interpolate.qmd +0 -0
  126. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/interpolate_file.qmd +0 -0
  127. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/token_usage.qmd +0 -0
  128. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.ChatResponse.qmd +0 -0
  129. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.ChatResponseAsync.qmd +0 -0
  130. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.Content.qmd +0 -0
  131. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.ContentImage.qmd +0 -0
  132. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.ContentImageInline.qmd +0 -0
  133. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.ContentImageRemote.qmd +0 -0
  134. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.ContentJson.qmd +0 -0
  135. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.ContentText.qmd +0 -0
  136. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.ContentToolRequest.qmd +0 -0
  137. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.ContentToolResult.qmd +0 -0
  138. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.ImageContentTypes.qmd +0 -0
  139. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.MISSING.qmd +0 -0
  140. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.MISSING_TYPE.qmd +0 -0
  141. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.SubmitInputArgsT.qmd +0 -0
  142. {chatlas-0.4.0 → chatlas-0.5.0}/docs/reference/types.TokenUsage.qmd +0 -0
  143. {chatlas-0.4.0 → chatlas-0.5.0}/docs/structured-data.qmd +0 -0
  144. {chatlas-0.4.0 → chatlas-0.5.0}/docs/styles.scss +0 -0
  145. {chatlas-0.4.0 → chatlas-0.5.0}/docs/tool-calling.qmd +0 -0
  146. {chatlas-0.4.0 → chatlas-0.5.0}/docs/web-apps.qmd +0 -0
  147. {chatlas-0.4.0 → chatlas-0.5.0}/pytest.ini +0 -0
  148. {chatlas-0.4.0 → chatlas-0.5.0}/scripts/_generate_anthropic_types.py +0 -0
  149. {chatlas-0.4.0 → chatlas-0.5.0}/scripts/_generate_google_types.py +0 -0
  150. {chatlas-0.4.0 → chatlas-0.5.0}/scripts/_utils.py +0 -0
  151. {chatlas-0.4.0 → chatlas-0.5.0}/tests/__init__.py +0 -0
  152. {chatlas-0.4.0 → chatlas-0.5.0}/tests/__snapshots__/test_chat.ambr +0 -0
  153. {chatlas-0.4.0 → chatlas-0.5.0}/tests/conftest.py +0 -0
  154. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_chat.py +0 -0
  155. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_content.py +0 -0
  156. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_content_image.py +0 -0
  157. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_content_tools.py +0 -0
  158. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_interpolate.py +0 -0
  159. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_provider_bedrock.py +0 -0
  160. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_provider_google.py +0 -0
  161. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_provider_openai.py +0 -0
  162. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_tokens.py +0 -0
  163. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_turns.py +0 -0
  164. {chatlas-0.4.0 → chatlas-0.5.0}/tests/test_utils_merge.py +0 -0
@@ -12,3 +12,6 @@ sandbox/
12
12
 
13
13
  # Automatically generated by docs/index.py
14
14
  docs/index.qmd
15
+
16
+ # setuptools_scm
17
+ chatlas/_version.py
@@ -7,6 +7,25 @@ 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.5.0] - 2025-03-18
11
+
12
+ ### New features
13
+
14
+ * Added a `ChatSnowflake()` class to interact with [Snowflake Cortex LLM](https://docs.snowflake.com/en/user-guide/snowflake-cortex/llm-functions). (#54)
15
+ * Added a `ChatAuto()` class, allowing for configuration of chat providers and models via environment variables. (#38, thanks @mconflitti-pbc)
16
+
17
+ ### Improvements
18
+
19
+ * Updated `ChatAnthropic()`'s `model` default to `"claude-3-7-sonnet-latest"`. (#62)
20
+ * The version is now accessible as `chatlas.__version__`. (#64)
21
+ * All provider-specific `Chat` subclasses now have an associated extras in chatlas. For example, `ChatOpenAI` has `chatlas[openai]`, `ChatPerplexity` has `chatlas[perplexity]`, `ChatBedrockAnthropic` has `chatlas[bedrock-anthropic]`, and so forth for the other `Chat` classes. (#66)
22
+
23
+ ### Bug fixes
24
+
25
+ * Fixed an issue with content getting duplicated when it overflows in a `Live()` console. (#71)
26
+ * Fix an issue with tool calls not working with `ChatVertex()`. (#61)
27
+
28
+
10
29
  ## [0.4.0] - 2025-02-19
11
30
 
12
31
  ### New features
@@ -9,7 +9,7 @@ build: ## [py] Build python package
9
9
  uv build
10
10
 
11
11
  .PHONY: check
12
- check: check-tests check-format check-types ## [py] Run python checks
12
+ check: check-format check-types check-tests ## [py] Run python checks
13
13
 
14
14
  .PHONY: check-tests
15
15
  check-tests: ## [py] Run python tests
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chatlas
3
- Version: 0.4.0
3
+ Version: 0.5.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
@@ -20,6 +20,12 @@ Requires-Python: >=3.9
20
20
  Requires-Dist: jinja2
21
21
  Requires-Dist: pydantic>=2.0
22
22
  Requires-Dist: rich
23
+ Provides-Extra: anthropic
24
+ Requires-Dist: anthropic; extra == 'anthropic'
25
+ Provides-Extra: azure-openai
26
+ Requires-Dist: openai; extra == 'azure-openai'
27
+ Provides-Extra: bedrock-anthropic
28
+ Requires-Dist: anthropic[bedrock]; extra == 'bedrock-anthropic'
23
29
  Provides-Extra: dev
24
30
  Requires-Dist: anthropic[bedrock]; extra == 'dev'
25
31
  Requires-Dist: google-genai>=1.2.0; extra == 'dev'
@@ -30,7 +36,9 @@ Requires-Dist: pillow; extra == 'dev'
30
36
  Requires-Dist: python-dotenv; extra == 'dev'
31
37
  Requires-Dist: ruff>=0.6.5; extra == 'dev'
32
38
  Requires-Dist: shiny; extra == 'dev'
39
+ Requires-Dist: snowflake-ml-python; extra == 'dev'
33
40
  Requires-Dist: tiktoken; extra == 'dev'
41
+ Requires-Dist: torch; (python_version <= '3.11') and extra == 'dev'
34
42
  Provides-Extra: docs
35
43
  Requires-Dist: griffe>=1; extra == 'docs'
36
44
  Requires-Dist: ipykernel; extra == 'docs'
@@ -42,11 +50,27 @@ Requires-Dist: pandas; extra == 'docs'
42
50
  Requires-Dist: pyyaml; extra == 'docs'
43
51
  Requires-Dist: quartodoc>=0.7; extra == 'docs'
44
52
  Requires-Dist: sentence-transformers; extra == 'docs'
53
+ Provides-Extra: github
54
+ Requires-Dist: openai; extra == 'github'
55
+ Provides-Extra: google
56
+ Requires-Dist: google-genai; extra == 'google'
57
+ Provides-Extra: groq
58
+ Requires-Dist: openai; extra == 'groq'
59
+ Provides-Extra: ollama
60
+ Requires-Dist: openai; extra == 'ollama'
61
+ Provides-Extra: openai
62
+ Requires-Dist: openai; extra == 'openai'
63
+ Provides-Extra: perplexity
64
+ Requires-Dist: openai; extra == 'perplexity'
65
+ Provides-Extra: snowflake
66
+ Requires-Dist: snowflake-ml-python; extra == 'snowflake'
45
67
  Provides-Extra: test
46
68
  Requires-Dist: pyright>=1.1.379; extra == 'test'
47
69
  Requires-Dist: pytest-asyncio; extra == 'test'
48
70
  Requires-Dist: pytest>=8.3.2; extra == 'test'
49
71
  Requires-Dist: syrupy>=4; extra == 'test'
72
+ Provides-Extra: vertex
73
+ Requires-Dist: google-genai; extra == 'vertex'
50
74
  Description-Content-Type: text/markdown
51
75
 
52
76
  <h1 class="unnumbered unlisted"> chatlas <a href="https://posit-dev.github.io/chatlas"><img src="docs/images/logo.png" align="right" height="138" alt="chatlas website" /></a> </h1>
@@ -98,6 +122,7 @@ It also supports the following enterprise cloud providers:
98
122
 
99
123
  * AWS Bedrock: [`ChatBedrockAnthropic()`](https://posit-dev.github.io/chatlas/reference/ChatBedrockAnthropic.html).
100
124
  * Azure OpenAI: [`ChatAzureOpenAI()`](https://posit-dev.github.io/chatlas/reference/ChatAzureOpenAI.html).
125
+ * Snowflake Cortex: [`ChatSnowflake()`](https://posit-dev.github.io/chatlas/reference/ChatSnowflake.html).
101
126
  * Vertex AI: [`ChatVertex()`](https://posit-dev.github.io/chatlas/reference/ChatVertex.html).
102
127
 
103
128
  To use a model provider that isn't listed here, you have two options:
@@ -47,6 +47,7 @@ It also supports the following enterprise cloud providers:
47
47
 
48
48
  * AWS Bedrock: [`ChatBedrockAnthropic()`](https://posit-dev.github.io/chatlas/reference/ChatBedrockAnthropic.html).
49
49
  * Azure OpenAI: [`ChatAzureOpenAI()`](https://posit-dev.github.io/chatlas/reference/ChatAzureOpenAI.html).
50
+ * Snowflake Cortex: [`ChatSnowflake()`](https://posit-dev.github.io/chatlas/reference/ChatSnowflake.html).
50
51
  * Vertex AI: [`ChatVertex()`](https://posit-dev.github.io/chatlas/reference/ChatVertex.html).
51
52
 
52
53
  To use a model provider that isn't listed here, you have two options:
@@ -1,5 +1,6 @@
1
1
  from . import types
2
2
  from ._anthropic import ChatAnthropic, ChatBedrockAnthropic
3
+ from ._auto import ChatAuto
3
4
  from ._chat import Chat
4
5
  from ._content_image import content_image_file, content_image_plot, content_image_url
5
6
  from ._github import ChatGithub
@@ -10,12 +11,19 @@ from ._ollama import ChatOllama
10
11
  from ._openai import ChatAzureOpenAI, ChatOpenAI
11
12
  from ._perplexity import ChatPerplexity
12
13
  from ._provider import Provider
14
+ from ._snowflake import ChatSnowflake
13
15
  from ._tokens import token_usage
14
16
  from ._tools import Tool
15
17
  from ._turn import Turn
16
18
 
19
+ try:
20
+ from ._version import version as __version__
21
+ except ImportError: # pragma: no cover
22
+ __version__ = "0.0.0" # stub value for docs
23
+
17
24
  __all__ = (
18
25
  "ChatAnthropic",
26
+ "ChatAuto",
19
27
  "ChatBedrockAnthropic",
20
28
  "ChatGithub",
21
29
  "ChatGoogle",
@@ -24,6 +32,7 @@ __all__ = (
24
32
  "ChatOpenAI",
25
33
  "ChatAzureOpenAI",
26
34
  "ChatPerplexity",
35
+ "ChatSnowflake",
27
36
  "ChatVertex",
28
37
  "Chat",
29
38
  "content_image_file",
@@ -72,7 +72,7 @@ def ChatAnthropic(
72
72
  ::: {.callout-note}
73
73
  ## API key
74
74
 
75
- Note that a Claude Prop membership does not give you the ability to call
75
+ Note that a Claude Pro membership does not give you the ability to call
76
76
  models via the API. You will need to go to the [developer
77
77
  console](https://console.anthropic.com/account/keys) to sign up (and pay
78
78
  for) a developer account that will give you an API key that you can use with
@@ -82,7 +82,7 @@ def ChatAnthropic(
82
82
  ::: {.callout-note}
83
83
  ## Python requirements
84
84
 
85
- `ChatAnthropic` requires the `anthropic` package (e.g., `pip install anthropic`).
85
+ `ChatAnthropic` requires the `anthropic` package: `pip install "chatlas[anthropic]"`.
86
86
  :::
87
87
 
88
88
  Examples
@@ -164,7 +164,7 @@ def ChatAnthropic(
164
164
  """
165
165
 
166
166
  if model is None:
167
- model = log_model_default("claude-3-5-sonnet-latest")
167
+ model = log_model_default("claude-3-7-sonnet-latest")
168
168
 
169
169
  return Chat(
170
170
  provider=AnthropicProvider(
@@ -572,8 +572,8 @@ def ChatBedrockAnthropic(
572
572
  ::: {.callout-note}
573
573
  ## Python requirements
574
574
 
575
- `ChatBedrockAnthropic`, requires the `anthropic` package with the `bedrock` extras
576
- (e.g., `pip install anthropic[bedrock]`).
575
+ `ChatBedrockAnthropic`, requires the `anthropic` package with the `bedrock` extras:
576
+ `pip install "chatlas[bedrock-anthropic]"`
577
577
  :::
578
578
 
579
579
  Examples
@@ -0,0 +1,183 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ from typing import Callable, Literal, Optional
6
+
7
+ from ._anthropic import ChatAnthropic, ChatBedrockAnthropic
8
+ from ._chat import Chat
9
+ from ._github import ChatGithub
10
+ from ._google import ChatGoogle, ChatVertex
11
+ from ._groq import ChatGroq
12
+ from ._ollama import ChatOllama
13
+ from ._openai import ChatAzureOpenAI, ChatOpenAI
14
+ from ._perplexity import ChatPerplexity
15
+ from ._snowflake import ChatSnowflake
16
+ from ._turn import Turn
17
+
18
+ AutoProviders = Literal[
19
+ "anthropic",
20
+ "bedrock-anthropic",
21
+ "github",
22
+ "google",
23
+ "groq",
24
+ "ollama",
25
+ "openai",
26
+ "azure-openai",
27
+ "perplexity",
28
+ "snowflake",
29
+ "vertex",
30
+ ]
31
+
32
+ _provider_chat_model_map: dict[AutoProviders, Callable[..., Chat]] = {
33
+ "anthropic": ChatAnthropic,
34
+ "bedrock-anthropic": ChatBedrockAnthropic,
35
+ "github": ChatGithub,
36
+ "google": ChatGoogle,
37
+ "groq": ChatGroq,
38
+ "ollama": ChatOllama,
39
+ "openai": ChatOpenAI,
40
+ "azure-openai": ChatAzureOpenAI,
41
+ "perplexity": ChatPerplexity,
42
+ "snowflake": ChatSnowflake,
43
+ "vertex": ChatVertex,
44
+ }
45
+
46
+
47
+ def ChatAuto(
48
+ system_prompt: Optional[str] = None,
49
+ turns: Optional[list[Turn]] = None,
50
+ *,
51
+ provider: Optional[AutoProviders] = None,
52
+ model: Optional[str] = None,
53
+ **kwargs,
54
+ ) -> Chat:
55
+ """
56
+ Use environment variables (env vars) to configure the Chat provider and model.
57
+
58
+ Creates a `:class:~chatlas.Chat` instance based on the specified provider.
59
+ The provider may be specified through the `provider` parameter and/or the
60
+ `CHATLAS_CHAT_PROVIDER` env var. If both are set, the env var takes
61
+ precedence. Similarly, the provider's model may be specified through the
62
+ `model` parameter and/or the `CHATLAS_CHAT_MODEL` env var. Also, additional
63
+ configuration may be provided through the `kwargs` parameter and/or the
64
+ `CHATLAS_CHAT_ARGS` env var (as a JSON string). In this case, when both are
65
+ set, they are merged, with the env var arguments taking precedence.
66
+
67
+ As a result, `ChatAuto()` provides a convenient way to set a default
68
+ provider and model in your Python code, while allowing you to override
69
+ these settings through env vars (i.e., without modifying your code).
70
+
71
+ Prerequisites
72
+ -------------
73
+
74
+ ::: {.callout-note}
75
+ ## API key
76
+
77
+ Follow the instructions for the specific provider to obtain an API key.
78
+ :::
79
+
80
+ ::: {.callout-note}
81
+ ## Python requirements
82
+
83
+ Follow the instructions for the specific provider to install the required
84
+ Python packages.
85
+ :::
86
+
87
+
88
+ Examples
89
+ --------
90
+ First, set the environment variables for the provider, arguments, and API key:
91
+
92
+ ```bash
93
+ export CHATLAS_CHAT_PROVIDER=anthropic
94
+ export CHATLAS_CHAT_MODEL=claude-3-haiku-20240229
95
+ export CHATLAS_CHAT_ARGS='{"kwargs": {"max_retries": 3}}'
96
+ export ANTHROPIC_API_KEY=your_api_key
97
+ ```
98
+
99
+ Then, you can use the `ChatAuto` function to create a Chat instance:
100
+
101
+ ```python
102
+ from chatlas import ChatAuto
103
+
104
+ chat = ChatAuto()
105
+ chat.chat("What is the capital of France?")
106
+ ```
107
+
108
+ Parameters
109
+ ----------
110
+ provider
111
+ The name of the default chat provider to use. Providers are strings
112
+ formatted in kebab-case, e.g. to use `ChatBedrockAnthropic` set
113
+ `provider="bedrock-anthropic"`.
114
+
115
+ This value can also be provided via the `CHATLAS_CHAT_PROVIDER`
116
+ environment variable, which takes precedence over `provider`
117
+ when set.
118
+ model
119
+ The name of the default model to use. This value can also be provided
120
+ via the `CHATLAS_CHAT_MODEL` environment variable, which takes
121
+ precedence over `model` when set.
122
+ system_prompt
123
+ A system prompt to set the behavior of the assistant.
124
+ turns
125
+ A list of turns to start the chat with (i.e., continuing a previous
126
+ conversation). If not provided, the conversation begins from scratch. Do
127
+ not provide non-`None` values for both `turns` and `system_prompt`. Each
128
+ message in the list should be a dictionary with at least `role` (usually
129
+ `system`, `user`, or `assistant`, but `tool` is also possible). Normally
130
+ there is also a `content` field, which is a string.
131
+ **kwargs
132
+ Additional keyword arguments to pass to the Chat constructor. See the
133
+ documentation for each provider for more details on the available
134
+ options.
135
+
136
+ These arguments can also be provided via the `CHATLAS_CHAT_ARGS`
137
+ environment variable as a JSON string. When provided, the options
138
+ in the `CHATLAS_CHAT_ARGS` envvar take precedence over the options
139
+ passed to `kwargs`.
140
+
141
+ Note that `system_prompt` and `turns` in `kwargs` or in
142
+ `CHATLAS_CHAT_ARGS` are ignored.
143
+
144
+ Returns
145
+ -------
146
+ Chat
147
+ A chat instance using the specified provider.
148
+
149
+ Raises
150
+ ------
151
+ ValueError
152
+ If no valid provider is specified either through parameters or
153
+ environment variables.
154
+ """
155
+ the_provider = os.environ.get("CHATLAS_CHAT_PROVIDER", provider)
156
+
157
+ if the_provider is None:
158
+ raise ValueError(
159
+ "Provider name is required as parameter or `CHATLAS_CHAT_PROVIDER` must be set."
160
+ )
161
+ if the_provider not in _provider_chat_model_map:
162
+ raise ValueError(
163
+ f"Provider name '{the_provider}' is not a known chatlas provider: "
164
+ f"{', '.join(_provider_chat_model_map.keys())}"
165
+ )
166
+
167
+ # `system_prompt` and `turns` always come from `ChatAuto()`
168
+ base_args = {"system_prompt": system_prompt, "turns": turns}
169
+
170
+ if env_model := os.environ.get("CHATLAS_CHAT_MODEL"):
171
+ model = env_model
172
+
173
+ if model:
174
+ base_args["model"] = model
175
+
176
+ env_kwargs = {}
177
+ if env_kwargs_str := os.environ.get("CHATLAS_CHAT_ARGS"):
178
+ env_kwargs = json.loads(env_kwargs_str)
179
+
180
+ kwargs = {**kwargs, **env_kwargs, **base_args}
181
+ kwargs = {k: v for k, v in kwargs.items() if v is not None}
182
+
183
+ return _provider_chat_model_map[the_provider](**kwargs)
@@ -408,7 +408,9 @@ class Chat(Generic[SubmitInputArgsT, CompletionT]):
408
408
  Whether to run the app in a background thread. If `None`, the app will
409
409
  run in a background thread if the current environment is a notebook.
410
410
  echo
411
- Whether to echo text content, all content (i.e., tool calls), or no content. Defaults to `"none"` when `stream=True` and `"text"` when `stream=False`.
411
+ Whether to echo text content, all content (i.e., tool calls), or no
412
+ content. Defaults to `"none"` when `stream=True` and `"text"` when
413
+ `stream=False`.
412
414
  kwargs
413
415
  Additional keyword arguments to pass to the method used for requesting
414
416
  the response.
@@ -199,21 +199,24 @@ class ContentToolResult(Content):
199
199
  name: Optional[str] = None
200
200
  error: Optional[str] = None
201
201
 
202
- def _get_value_and_language(self) -> tuple[str, str]:
202
+ def _get_value(self, pretty: bool = False) -> str:
203
203
  if self.error:
204
- return f"Tool calling failed with error: '{self.error}'", ""
204
+ return f"Tool calling failed with error: '{self.error}'"
205
+ if not pretty:
206
+ return str(self.value)
205
207
  try:
206
- json_val = json.loads(self.value)
207
- return pformat(json_val, indent=2, sort_dicts=False), "python"
208
+ json_val = json.loads(self.value) # type: ignore
209
+ return pformat(json_val, indent=2, sort_dicts=False)
208
210
  except: # noqa: E722
209
- return str(self.value), ""
211
+ return str(self.value)
210
212
 
213
+ # Primarily used for `echo="all"`...
211
214
  def __str__(self):
212
215
  comment = f"# tool result ({self.id})"
213
- value, language = self._get_value_and_language()
214
-
215
- return f"""```{language}\n{comment}\n{value}\n```"""
216
+ value = self._get_value(pretty=True)
217
+ return f"""```python\n{comment}\n{value}\n```"""
216
218
 
219
+ # ... and for displaying in the notebook
217
220
  def _repr_markdown_(self):
218
221
  return self.__str__()
219
222
 
@@ -224,9 +227,9 @@ class ContentToolResult(Content):
224
227
  res += f" error='{self.error}'"
225
228
  return res + ">"
226
229
 
230
+ # The actual value to send to the model
227
231
  def get_final_value(self) -> str:
228
- value, _language = self._get_value_and_language()
229
- return value
232
+ return self._get_value()
230
233
 
231
234
 
232
235
  @dataclass
@@ -6,6 +6,7 @@ from uuid import uuid4
6
6
  from rich.live import Live
7
7
  from rich.logging import RichHandler
8
8
 
9
+ from ._live_render import LiveRender
9
10
  from ._logging import logger
10
11
  from ._typing_extensions import TypedDict
11
12
 
@@ -44,13 +45,22 @@ class LiveMarkdownDisplay(MarkdownDisplay):
44
45
  from rich.console import Console
45
46
 
46
47
  self.content: str = ""
47
- self.live = Live(
48
+ live = Live(
48
49
  auto_refresh=False,
49
- vertical_overflow="visible",
50
50
  console=Console(
51
51
  **echo_options["rich_console"],
52
52
  ),
53
53
  )
54
+
55
+ # Monkeypatch LiveRender() with our own version that add "crop_above"
56
+ # https://github.com/Textualize/rich/blob/43d3b047/rich/live.py#L87-L89
57
+ live.vertical_overflow = "crop_above"
58
+ live._live_render = LiveRender( # pyright: ignore[reportAttributeAccessIssue]
59
+ live.get_renderable(), vertical_overflow="crop_above"
60
+ )
61
+
62
+ self.live = live
63
+
54
64
  self._markdown_options = echo_options["rich_markdown"]
55
65
 
56
66
  def update(self, content: str):
@@ -43,7 +43,7 @@ def ChatGithub(
43
43
  ::: {.callout-note}
44
44
  ## Python requirements
45
45
 
46
- `ChatGithub` requires the `openai` package (e.g., `pip install openai`).
46
+ `ChatGithub` requires the `openai` package: `pip install "chatlas[github]"`.
47
47
  :::
48
48
 
49
49
 
@@ -61,8 +61,7 @@ def ChatGoogle(
61
61
  ::: {.callout-note}
62
62
  ## Python requirements
63
63
 
64
- `ChatGoogle` requires the `google-genai` package
65
- (e.g., `pip install google-genai`).
64
+ `ChatGoogle` requires the `google-genai` package: `pip install "chatlas[google]"`.
66
65
  :::
67
66
 
68
67
  Examples
@@ -413,7 +412,7 @@ class GoogleProvider(
413
412
  elif isinstance(content, ContentToolRequest):
414
413
  return Part(
415
414
  function_call=FunctionCall(
416
- id=content.id,
415
+ id=content.id if content.name != content.id else None,
417
416
  name=content.name,
418
417
  # Goes in a dict, so should come out as a dict
419
418
  args=cast(dict[str, Any], content.arguments),
@@ -428,7 +427,7 @@ class GoogleProvider(
428
427
  # TODO: seems function response parts might need role='tool'???
429
428
  # https://github.com/googleapis/python-genai/blame/c8cfef85c/README.md#L344
430
429
  function_response=FunctionResponse(
431
- id=content.id,
430
+ id=content.id if content.name != content.id else None,
432
431
  name=content.name,
433
432
  response=resp,
434
433
  )
@@ -530,8 +529,7 @@ def ChatVertex(
530
529
  ::: {.callout-note}
531
530
  ## Python requirements
532
531
 
533
- `ChatGoogle` requires the `google-genai` package
534
- (e.g., `pip install google-genai`).
532
+ `ChatGoogle` requires the `google-genai` package: `pip install "chatlas[vertex]"`.
535
533
  :::
536
534
 
537
535
  ::: {.callout-note}
@@ -41,7 +41,7 @@ def ChatGroq(
41
41
  ::: {.callout-note}
42
42
  ## Python requirements
43
43
 
44
- `ChatGroq` requires the `openai` package (e.g., `pip install openai`).
44
+ `ChatGroq` requires the `openai` package: `pip install "chatlas[groq]"`.
45
45
  :::
46
46
 
47
47
  Examples
@@ -0,0 +1,116 @@
1
+ # A 'patched' version of LiveRender that adds the 'crop_above' vertical overflow method.
2
+ # Derives from https://github.com/Textualize/rich/pull/3637
3
+ import sys
4
+ from typing import Optional, Tuple
5
+
6
+ if sys.version_info >= (3, 8):
7
+ from typing import Literal
8
+ else:
9
+ from typing_extensions import Literal # pragma: no cover
10
+
11
+ from rich._loop import loop_last
12
+ from rich.console import Console, ConsoleOptions, RenderableType, RenderResult
13
+ from rich.control import Control
14
+ from rich.segment import ControlType, Segment
15
+ from rich.style import StyleType
16
+ from rich.text import Text
17
+
18
+ VerticalOverflowMethod = Literal["crop", "crop_above", "ellipsis", "visible"]
19
+
20
+
21
+ class LiveRender:
22
+ """Creates a renderable that may be updated.
23
+
24
+ Args:
25
+ renderable (RenderableType): Any renderable object.
26
+ style (StyleType, optional): An optional style to apply to the renderable. Defaults to "".
27
+ """
28
+
29
+ def __init__(
30
+ self,
31
+ renderable: RenderableType,
32
+ style: StyleType = "",
33
+ vertical_overflow: VerticalOverflowMethod = "ellipsis",
34
+ ) -> None:
35
+ self.renderable = renderable
36
+ self.style = style
37
+ self.vertical_overflow = vertical_overflow
38
+ self._shape: Optional[Tuple[int, int]] = None
39
+
40
+ def set_renderable(self, renderable: RenderableType) -> None:
41
+ """Set a new renderable.
42
+
43
+ Args:
44
+ renderable (RenderableType): Any renderable object, including str.
45
+ """
46
+ self.renderable = renderable
47
+
48
+ def position_cursor(self) -> Control:
49
+ """Get control codes to move cursor to beginning of live render.
50
+
51
+ Returns:
52
+ Control: A control instance that may be printed.
53
+ """
54
+ if self._shape is not None:
55
+ _, height = self._shape
56
+ return Control(
57
+ ControlType.CARRIAGE_RETURN,
58
+ (ControlType.ERASE_IN_LINE, 2),
59
+ *(
60
+ (
61
+ (ControlType.CURSOR_UP, 1),
62
+ (ControlType.ERASE_IN_LINE, 2),
63
+ )
64
+ * (height - 1)
65
+ ),
66
+ )
67
+ return Control()
68
+
69
+ def restore_cursor(self) -> Control:
70
+ """Get control codes to clear the render and restore the cursor to its previous position.
71
+
72
+ Returns:
73
+ Control: A Control instance that may be printed.
74
+ """
75
+ if self._shape is not None:
76
+ _, height = self._shape
77
+ return Control(
78
+ ControlType.CARRIAGE_RETURN,
79
+ *((ControlType.CURSOR_UP, 1), (ControlType.ERASE_IN_LINE, 2)) * height,
80
+ )
81
+ return Control()
82
+
83
+ def __rich_console__(
84
+ self, console: Console, options: ConsoleOptions
85
+ ) -> RenderResult:
86
+ renderable = self.renderable
87
+ style = console.get_style(self.style)
88
+ lines = console.render_lines(renderable, options, style=style, pad=False)
89
+ shape = Segment.get_shape(lines)
90
+
91
+ _, height = shape
92
+ if height > options.size.height:
93
+ if self.vertical_overflow == "crop":
94
+ lines = lines[: options.size.height]
95
+ shape = Segment.get_shape(lines)
96
+ elif self.vertical_overflow == "crop_above":
97
+ lines = lines[-(options.size.height) :]
98
+ shape = Segment.get_shape(lines)
99
+ elif self.vertical_overflow == "ellipsis":
100
+ lines = lines[: (options.size.height - 1)]
101
+ overflow_text = Text(
102
+ "...",
103
+ overflow="crop",
104
+ justify="center",
105
+ end="",
106
+ style="live.ellipsis",
107
+ )
108
+ lines.append(list(console.render(overflow_text)))
109
+ shape = Segment.get_shape(lines)
110
+ self._shape = shape
111
+
112
+ new_line = Segment.line()
113
+ for last, line in loop_last(lines):
114
+ yield from line
115
+ if not last:
116
+ yield new_line
@@ -51,7 +51,7 @@ def ChatOllama(
51
51
  ::: {.callout-note}
52
52
  ## Python requirements
53
53
 
54
- `ChatOllama` requires the `openai` package (e.g., `pip install openai`).
54
+ `ChatOllama` requires the `openai` package: `pip install "chatlas[ollama]"`.
55
55
  :::
56
56
 
57
57
 
@@ -79,7 +79,7 @@ def ChatOpenAI(
79
79
  ::: {.callout-note}
80
80
  ## Python requirements
81
81
 
82
- `ChatOpenAI` requires the `openai` package (e.g., `pip install openai`).
82
+ `ChatOpenAI` requires the `openai` package: `pip install "chatlas[openai]"`.
83
83
  :::
84
84
 
85
85
  Examples
@@ -592,7 +592,8 @@ def ChatAzureOpenAI(
592
592
  ::: {.callout-note}
593
593
  ## Python requirements
594
594
 
595
- `ChatAzureOpenAI` requires the `openai` package (e.g., `pip install openai`).
595
+ `ChatAzureOpenAI` requires the `openai` package:
596
+ `pip install "chatlas[azure-openai]"`.
596
597
  :::
597
598
 
598
599
  Examples