chatlas 0.6.1__py3-none-any.whl → 0.7.0__py3-none-any.whl

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/_snowflake.py CHANGED
@@ -1,14 +1,16 @@
1
- from typing import TYPE_CHECKING, Literal, Optional, TypedDict, overload
1
+ import asyncio
2
+ import json
3
+ from typing import TYPE_CHECKING, Iterable, Literal, Optional, TypedDict, cast, overload
2
4
 
3
5
  from pydantic import BaseModel
4
6
 
5
7
  from ._chat import Chat
6
- from ._content import Content
8
+ from ._content import Content, ContentJson, ContentText
7
9
  from ._logging import log_model_default
8
10
  from ._provider import Provider
9
- from ._tools import Tool
11
+ from ._tools import Tool, basemodel_to_param_schema
10
12
  from ._turn import Turn, normalize_turns
11
- from ._utils import drop_none
13
+ from ._utils import drop_none, wrap_async_iterable
12
14
 
13
15
  if TYPE_CHECKING:
14
16
  from snowflake.snowpark import Column
@@ -237,9 +239,18 @@ class SnowflakeProvider(Provider["Completion", "CompletionChunk", "CompletionChu
237
239
  data_model: Optional[type[BaseModel]] = None,
238
240
  kwargs: Optional["SubmitInputArgs"] = None,
239
241
  ):
240
- raise NotImplementedError(
241
- "Snowflake does not currently support async completions."
242
- )
242
+ from snowflake.cortex import complete
243
+
244
+ kwargs = self._chat_perform_args(stream, turns, tools, data_model, kwargs)
245
+
246
+ # Prevent the main thread from being blocked (Snowflake doesn't have native async support)
247
+ res = await asyncio.to_thread(complete, **kwargs)
248
+
249
+ # When streaming, res is an iterable of strings, but Chat() wants an async iterable
250
+ if stream:
251
+ res = wrap_async_iterable(cast(Iterable[str], res))
252
+
253
+ return res
243
254
 
244
255
  def _chat_perform_args(
245
256
  self,
@@ -249,27 +260,31 @@ class SnowflakeProvider(Provider["Completion", "CompletionChunk", "CompletionChu
249
260
  data_model: Optional[type[BaseModel]] = None,
250
261
  kwargs: Optional["SubmitInputArgs"] = None,
251
262
  ):
252
- # Cortex doesn't seem to support tools
253
- if tools:
254
- raise ValueError("Snowflake does not currently support tools.")
255
-
256
- # TODO: implement data_model when this PR makes it into snowflake-ml-python
257
- # https://github.com/snowflakedb/snowflake-ml-python/pull/141
258
- # https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-llm-rest-api#structured-output-example
259
- if data_model:
260
- raise NotImplementedError(
261
- "The snowflake-ml-python package currently doesn't support structured output. "
262
- "Upvote this PR to help prioritize it: "
263
- "https://github.com/snowflakedb/snowflake-ml-python/pull/141"
264
- )
265
-
266
263
  kwargs_full: "SubmitInputArgs" = {
267
264
  "stream": stream,
268
265
  "prompt": self._as_prompt_input(turns),
269
266
  "model": self._model,
267
+ "session": self._session,
270
268
  **(kwargs or {}),
271
269
  }
272
270
 
271
+ # TODO: get tools working
272
+ if tools:
273
+ raise ValueError("Snowflake does not currently support tools.")
274
+
275
+ if data_model is not None:
276
+ params = basemodel_to_param_schema(data_model)
277
+ opts = kwargs_full.get("options") or {}
278
+ opts["response_format"] = {
279
+ "type": "json",
280
+ "schema": {
281
+ "type": "object",
282
+ "properties": params["properties"],
283
+ "required": params["required"],
284
+ },
285
+ }
286
+ kwargs_full["options"] = opts
287
+
273
288
  return kwargs_full
274
289
 
275
290
  def stream_text(self, chunk):
@@ -312,10 +327,18 @@ class SnowflakeProvider(Provider["Completion", "CompletionChunk", "CompletionChu
312
327
  res.append(
313
328
  {
314
329
  "role": turn.role,
315
- "content": turn.text,
330
+ "content": str(turn),
316
331
  }
317
332
  )
318
333
  return res
319
334
 
320
335
  def _as_turn(self, completion, has_data_model) -> Turn:
321
- return Turn("assistant", completion)
336
+ completion = cast(str, completion)
337
+
338
+ if has_data_model:
339
+ data = json.loads(completion)
340
+ contents = [ContentJson(value=data)]
341
+ else:
342
+ contents = [ContentText(text=completion)]
343
+
344
+ return Turn("assistant", contents)
chatlas/_utils.py CHANGED
@@ -1,10 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import asyncio
3
4
  import functools
4
5
  import inspect
5
6
  import os
6
7
  import re
7
- from typing import Awaitable, Callable, TypeVar, cast
8
+ from typing import Any, AsyncIterable, Awaitable, Callable, Iterable, TypeVar, cast
8
9
 
9
10
  from ._typing_extensions import ParamSpec, TypeGuard
10
11
 
@@ -61,6 +62,40 @@ def is_async_callable(
61
62
  return False
62
63
 
63
64
 
65
+ def wrap_async_iterable(x: Iterable[Any] | AsyncIterable[Any]) -> AsyncIterable[Any]:
66
+ """
67
+ Given any iterable, return an async iterable. The async iterable will yield the
68
+ values of the original iterable, but will also yield control to the event loop
69
+ after each value. This is useful when you want to interleave processing with other
70
+ tasks, or when you want to simulate an async iterable from a regular iterable.
71
+ """
72
+
73
+ if isinstance(x, AsyncIterable):
74
+ return x
75
+
76
+ if not isinstance(x, Iterable):
77
+ raise TypeError("wrap_async_iterable requires an Iterable object.")
78
+
79
+ return MakeIterableAsync(x)
80
+
81
+
82
+ class MakeIterableAsync:
83
+ def __init__(self, iterable: Iterable[Any]):
84
+ self.iterable = iterable
85
+
86
+ def __aiter__(self):
87
+ self.iterator = iter(self.iterable)
88
+ return self
89
+
90
+ async def __anext__(self):
91
+ try:
92
+ value = next(self.iterator)
93
+ await asyncio.sleep(0) # Yield control to the event loop
94
+ return value
95
+ except StopIteration:
96
+ raise StopAsyncIteration
97
+
98
+
64
99
  T = TypeVar("T")
65
100
 
66
101
 
chatlas/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.6.1'
21
- __version_tuple__ = version_tuple = (0, 6, 1)
20
+ __version__ = version = '0.7.0'
21
+ __version_tuple__ = version_tuple = (0, 7, 0)
@@ -38,6 +38,16 @@ class SubmitInputArgs(TypedDict, total=False):
38
38
  model: Union[
39
39
  str,
40
40
  Literal[
41
+ "gpt-4.1",
42
+ "gpt-4.1-mini",
43
+ "gpt-4.1-nano",
44
+ "gpt-4.1-2025-04-14",
45
+ "gpt-4.1-mini-2025-04-14",
46
+ "gpt-4.1-nano-2025-04-14",
47
+ "o4-mini",
48
+ "o4-mini-2025-04-16",
49
+ "o3",
50
+ "o3-2025-04-16",
41
51
  "o3-mini",
42
52
  "o3-mini-2025-01-31",
43
53
  "o1",
@@ -119,7 +129,7 @@ class SubmitInputArgs(TypedDict, total=False):
119
129
  openai.NotGiven,
120
130
  ]
121
131
  seed: Union[int, None, openai.NotGiven]
122
- service_tier: Union[Literal["auto", "default"], None, openai.NotGiven]
132
+ service_tier: Union[Literal["auto", "default", "flex"], None, openai.NotGiven]
123
133
  stop: Union[str, None, list[str], openai.NotGiven]
124
134
  store: Union[bool, None, openai.NotGiven]
125
135
  stream: Union[Literal[False], None, Literal[True], openai.NotGiven]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chatlas
3
- Version: 0.6.1
3
+ Version: 0.7.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
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Programming Language :: Python :: 3.13
19
19
  Requires-Python: >=3.9
20
20
  Requires-Dist: jinja2
21
+ Requires-Dist: orjson
21
22
  Requires-Dist: pydantic>=2.0
22
23
  Requires-Dist: requests
23
24
  Requires-Dist: rich
@@ -27,9 +28,13 @@ Provides-Extra: azure-openai
27
28
  Requires-Dist: openai; extra == 'azure-openai'
28
29
  Provides-Extra: bedrock-anthropic
29
30
  Requires-Dist: anthropic[bedrock]; extra == 'bedrock-anthropic'
31
+ Provides-Extra: databricks
32
+ Requires-Dist: databricks-sdk[openai]; extra == 'databricks'
30
33
  Provides-Extra: dev
31
34
  Requires-Dist: anthropic[bedrock]; extra == 'dev'
35
+ Requires-Dist: databricks-sdk; extra == 'dev'
32
36
  Requires-Dist: google-genai>=1.2.0; extra == 'dev'
37
+ Requires-Dist: htmltools; extra == 'dev'
33
38
  Requires-Dist: matplotlib; extra == 'dev'
34
39
  Requires-Dist: numpy>1.24.4; extra == 'dev'
35
40
  Requires-Dist: openai; extra == 'dev'
@@ -38,6 +43,7 @@ Requires-Dist: python-dotenv; extra == 'dev'
38
43
  Requires-Dist: ruff>=0.6.5; extra == 'dev'
39
44
  Requires-Dist: shiny; extra == 'dev'
40
45
  Requires-Dist: snowflake-ml-python; extra == 'dev'
46
+ Requires-Dist: tenacity; extra == 'dev'
41
47
  Requires-Dist: tiktoken; extra == 'dev'
42
48
  Requires-Dist: torch; (python_version <= '3.11') and extra == 'dev'
43
49
  Provides-Extra: docs
@@ -123,6 +129,7 @@ It also supports the following enterprise cloud providers:
123
129
 
124
130
  * AWS Bedrock: [`ChatBedrockAnthropic()`](https://posit-dev.github.io/chatlas/reference/ChatBedrockAnthropic.html).
125
131
  * Azure OpenAI: [`ChatAzureOpenAI()`](https://posit-dev.github.io/chatlas/reference/ChatAzureOpenAI.html).
132
+ * Databricks: [`ChatDatabricks()`](https://posit-dev.github.io/chatlas/reference/ChatDatabricks.html).
126
133
  * Snowflake Cortex: [`ChatSnowflake()`](https://posit-dev.github.io/chatlas/reference/ChatSnowflake.html).
127
134
  * Vertex AI: [`ChatVertex()`](https://posit-dev.github.io/chatlas/reference/ChatVertex.html).
128
135
 
@@ -1,30 +1,31 @@
1
- chatlas/__init__.py,sha256=IVHVEEN6pspb-5WqWfBLc9wOQH-1R8vmi1Eeh-OSVFY,1358
2
- chatlas/_anthropic.py,sha256=IvTC1xJYeKi7Liz_Czt1wmkG_Tx12e2ME663xZTNpdI,24745
3
- chatlas/_auto.py,sha256=4tpwla09la4VA2PAh3phAMWs2Amgtp_4Qsjx6K02ib0,6032
4
- chatlas/_chat.py,sha256=czfSjsEbRX5bHLclF1IbYtfHlyZrAOH0xcP-1hzcNNk,46032
5
- chatlas/_content.py,sha256=yXB1IukyMfK9-Zc8ISm4h1p09O4i79YEJandzyT4UtM,8726
1
+ chatlas/__init__.py,sha256=5bHHZOdSM84VUD1WlUYH7vYxGiHygYEoRsQzGHHDXXk,1531
2
+ chatlas/_anthropic.py,sha256=VAtzRcrWPVe38wBBtDapxURISF2qn2yd6wg_8VY94Lk,24994
3
+ chatlas/_auto.py,sha256=HsAvVwpSOkI9fdC35YX8beaE2IBnWLWTzOzu0ny951o,6129
4
+ chatlas/_chat.py,sha256=wTkXu_AmL2frIHy-JZveuY44BigkrG21_06beyD3pIw,52691
5
+ chatlas/_content.py,sha256=VW1iKOWlzeoOjTg_TNQTj1zlmdWbDXqTjBy3fxddhdc,15767
6
6
  chatlas/_content_image.py,sha256=EUK6wAint-JatLsiwvaPDu4D3W-NcIsDCkzABkXgfDg,8304
7
7
  chatlas/_content_pdf.py,sha256=cffeuJxzhUDukQ-Srkmpy62M8X12skYpU_FVq-Wvya4,2420
8
- chatlas/_display.py,sha256=eqdRIwQenyJxswmTEjnJ1n9YxxSxsa8vHVmA79449_o,4439
8
+ chatlas/_databricks.py,sha256=G87AB6qWGxIlIP8tc6iHeaMpjXe47FuVZ00anPoM9ZI,4919
9
+ chatlas/_display.py,sha256=wyQzSc6z1VqrJfkTLkw1wQcti9s1Pr4qT8UxFJESn4U,4664
9
10
  chatlas/_github.py,sha256=8_vvUIBCprgrQ5UItky5yETfEQPG2fCMM57ga77p28E,4377
10
- chatlas/_google.py,sha256=lXqqLwXlqFoKh0GWx-OSgJ1pge0Dv7FH8Sg-MkcXpJs,19138
11
+ chatlas/_google.py,sha256=FfBnkXRtdJiBTViOqOg7qoConcRPLAKqWhUYKcfvhO4,19356
11
12
  chatlas/_groq.py,sha256=iuFvxeXkq81sDHxVV9zbVHjf2ZuNT94P-XkuXvqtGms,4160
12
13
  chatlas/_interpolate.py,sha256=ykwLP3x-ya9Q33U4knSU75dtk6pzJAeythEEIW-43Pc,3631
13
14
  chatlas/_live_render.py,sha256=UMZltE35LxziDKPMEeDwQ9meZ95SeqwhJi7j-y9pcro,4004
14
15
  chatlas/_logging.py,sha256=7a20sAl1PkW1qBNrfd_ieUbQXV8Gf4Vuf0Wn62LNBmk,2290
15
16
  chatlas/_merge.py,sha256=SGj_BetgA7gaOqSBKOhYmW3CYeQKTEehFrXvx3y4OYE,3924
16
- chatlas/_ollama.py,sha256=EgTwmphVwBV7xCIqmPC_cNlr4Uo9N5Xy4eDCb1sJoPI,3764
17
- chatlas/_openai.py,sha256=xnJPzZzVuRoH7al7Tq01J7SIgF7bZm3UwcO2noDENk4,24523
17
+ chatlas/_ollama.py,sha256=np7s43abaNKt4eSygerHugvtzHjCyOQjSo0ZIRkE8Yc,3769
18
+ chatlas/_openai.py,sha256=AIYZ6yc_euymi0OSE0ccPdA2nJLP-8wJSVSyPHckcBw,24653
18
19
  chatlas/_perplexity.py,sha256=j-jfOIYefZC5XzGjmya9GCCGQN003cRmiAv6vmo0rTQ,4454
19
20
  chatlas/_provider.py,sha256=YmdBbz_u5aP_kBxl6s26OPiSnWG_vZ_fvf9L2qvBmyI,3809
20
- chatlas/_snowflake.py,sha256=WUNdT3irxgLVqoc1TAeDmxnYsjBWiBw-CoH-dY4mFps,10944
21
+ chatlas/_snowflake.py,sha256=xlDdaM-YCmz3Y8KU6jxdCICuS-H4XLpQBHjqnaiEqKk,11576
21
22
  chatlas/_tokens.py,sha256=3W3EPUp9eWXUiwuzJwEPBv43AUznbK46pm59Htti7z4,2392
22
23
  chatlas/_tokens_old.py,sha256=L9d9oafrXvEx2u4nIn_Jjn7adnQyLBnYBuPwJUE8Pl8,5005
23
24
  chatlas/_tools.py,sha256=-qt4U1AFkebQoX9kpsBy5QXK8a2PpHX6Amgm44gcQ68,4113
24
25
  chatlas/_turn.py,sha256=7pve6YmD-L4c7Oxd6_ZAPkDudJ8AMpa6pP-pSroA1dM,5067
25
26
  chatlas/_typing_extensions.py,sha256=YdzmlyPSBpIEcsOkoz12e6jETT1XEMV2Q72haE4cfwY,1036
26
- chatlas/_utils.py,sha256=2TPy5_8dr9QDF1YShZN-CjxRVHeArSujRiaF0SKnI4o,2895
27
- chatlas/_version.py,sha256=a3_WODLDfpmAw3pMw7qGqmRuXHTCC3STyQd2R1iEOgA,511
27
+ chatlas/_utils.py,sha256=lli8ChbPUwEPebW8AoOoNoqiA95SVtoW2gb6ymj9gw4,4028
28
+ chatlas/_version.py,sha256=itvIHlqPKoO_13qf_yPD2pmcp0U4z1s19vvBGZM927Q,511
28
29
  chatlas/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
30
  chatlas/types/__init__.py,sha256=P_EDL4eqsigKwB-u2qRmKlYQS5Y65m7oWjGC3cYmxO4,719
30
31
  chatlas/types/anthropic/__init__.py,sha256=OwubA-DPHYpYo0XyRyAFwftOI0mOxtHzAyhUSLcDx54,417
@@ -37,9 +38,9 @@ chatlas/types/google/_submit.py,sha256=b-ZqMvI551Ia7pFlWdqUQJjov3neHmVwLFw-P2bgU
37
38
  chatlas/types/openai/__init__.py,sha256=Q2RAr1bSH1nHsxICK05nAmKmxdhKmhbBkWD_XHiVSrI,411
38
39
  chatlas/types/openai/_client.py,sha256=YGm_EHtRSSHeeOZe-CV7oNvMJpEblEta3UTuU7lSRO8,754
39
40
  chatlas/types/openai/_client_azure.py,sha256=jx8D_p46CLDGzTP-k-TtGzj-f3junj6or-86m8DD_0w,858
40
- chatlas/types/openai/_submit.py,sha256=mflYHZ5Q3dWBR2PdVEq6lhC9qNrQGNvyMiORglYLByE,6271
41
+ chatlas/types/openai/_submit.py,sha256=R0PUgXmhywLzRT_C3DYCsfbHCB1mD7cMY3zd8q7E-PU,6574
41
42
  chatlas/types/snowflake/__init__.py,sha256=NVKw_gLVnSlMNdE6BpikrQw8GV8LvIn5SR8eI8Afgbs,273
42
43
  chatlas/types/snowflake/_submit.py,sha256=Fgcb2Z4mXYwAR2b7Kn3SdEYFlO4gJiUvkDJ3lDoN0IY,799
43
- chatlas-0.6.1.dist-info/METADATA,sha256=9mB4Dz3d0zCabRMuZX6E-MG8RnT4M14dhncult9gMAQ,15085
44
- chatlas-0.6.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
45
- chatlas-0.6.1.dist-info/RECORD,,
44
+ chatlas-0.7.0.dist-info/METADATA,sha256=rb2oYfWSve7uDdoKouiZb2OAltvOMc-gXfucQRJ4skY,15425
45
+ chatlas-0.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
46
+ chatlas-0.7.0.dist-info/RECORD,,