swarmauri_llm_xai 0.11.0.dev4__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.
@@ -0,0 +1,92 @@
1
+ Metadata-Version: 2.4
2
+ Name: swarmauri_llm_xai
3
+ Version: 0.11.0.dev4
4
+ Summary: Provider-native Swarmauri chat and tool-calling adapters for the xAI Inference API.
5
+ License-Expression: Apache-2.0
6
+ Keywords: swarmauri,llm,xai,grok,tool calling,streaming,inference api
7
+ Author: Jacob Stewart
8
+ Author-email: jacob@swarmauri.com
9
+ Requires-Python: >=3.10,<3.13
10
+ Classifier: Development Status :: 1 - Planning
11
+ Classifier: License :: OSI Approved :: Apache Software License
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Dist: swarmauri_base (>=0.11.0.dev5)
16
+ Requires-Dist: swarmauri_core (>=0.11.0.dev5)
17
+ Requires-Dist: swarmauri_provider_xai (>=0.1.0.dev3)
18
+ Requires-Dist: swarmauri_standard (>=0.11.0.dev6)
19
+ Requires-Dist: swarmauri_transport_httpx (>=0.1.0.dev5)
20
+ Requires-Dist: swarmauri_transport_retry (>=0.1.0.dev1)
21
+ Description-Content-Type: text/markdown
22
+
23
+ ![Swarmauri](https://raw.githubusercontent.com/swarmauri/swarmauri-sdk/3d4d1cfa949399d7019ae9d8f296afba773dfb7f/assets/swarmauri.brand.theme.svg)
24
+
25
+ <p align="center">
26
+ <a href="https://pepy.tech/project/swarmauri_llm_xai"><img src="https://static.pepy.tech/badge/swarmauri_llm_xai/month" alt="Downloads"></a>
27
+ <a href="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/community/swarmauri_llm_xai/"><img src="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/community/swarmauri_llm_xai.svg" alt="Hits"></a>
28
+ <a href="https://pypi.org/project/swarmauri_llm_xai/"><img src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue" alt="Python"></a>
29
+ <a href="https://pypi.org/project/swarmauri_llm_xai/"><img src="https://img.shields.io/pypi/l/swarmauri_llm_xai" alt="License"></a>
30
+ <a href="https://pypi.org/project/swarmauri_llm_xai/"><img src="https://img.shields.io/pypi/v/swarmauri_llm_xai" alt="Release"></a>
31
+ </p>
32
+
33
+ # Swarmauri xAI LLM
34
+
35
+ `swarmauri_llm_xai` provides provider-native Swarmauri adapters for xAI's Grok chat-completions API.
36
+
37
+ ## Features
38
+
39
+ - `XAIModel` directly implements the Swarmauri LLM base contract.
40
+ - `XAIToolModel` directly implements the tool-LLM base contract.
41
+ - Bearer-token authentication with credentials excluded from serialized state.
42
+ - Sync, async, incremental streaming, batch, and function-calling workflows.
43
+ - Optional model discovery through xAI's language-model catalog.
44
+ - Explicit provider, HTTP client, and retry-policy composition.
45
+ - Conservative chat retries that do not replay ambiguous connection failures.
46
+
47
+ ## Installation
48
+
49
+ ```bash
50
+ uv add swarmauri_llm_xai
51
+ ```
52
+
53
+ ```bash
54
+ pip install swarmauri_llm_xai
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ ```python
60
+ import os
61
+
62
+ from swarmauri_llm_xai import XAIModel
63
+ from swarmauri_standard.conversations.Conversation import Conversation
64
+ from swarmauri_standard.messages.HumanMessage import HumanMessage
65
+
66
+ conversation = Conversation(
67
+ messages=[HumanMessage(content="Explain orbital mechanics briefly.")]
68
+ )
69
+ model = XAIModel(api_key=os.environ["XAI_API_KEY"], name="grok-4.3")
70
+ model.predict(conversation)
71
+ print(conversation.get_last().content)
72
+ ```
73
+
74
+ For explicit composition:
75
+
76
+ ```python
77
+ from swarmauri_llm_xai import XAIChatRetryPolicy, XAIModel
78
+ from swarmauri_provider_xai import XAIProvider
79
+ from swarmauri_transport_httpx import HttpxClient
80
+
81
+ provider = XAIProvider(api_key=os.environ["XAI_API_KEY"])
82
+ model = XAIModel(
83
+ provider=provider,
84
+ http_client=HttpxClient(base_url=provider.base_url),
85
+ retry_policy=XAIChatRetryPolicy(max_attempts=3),
86
+ )
87
+ ```
88
+
89
+ Use `XAIToolModel` with a Swarmauri `Toolkit` for function calling. Set `discover_models=True` to populate allowed model IDs from the authenticated xAI language-model catalog.
90
+
91
+ See the [xAI inference reference](https://docs.x.ai/developers/rest-api-reference/inference), [chat endpoint](https://docs.x.ai/developers/rest-api-reference/inference/chat), and [function-calling guide](https://docs.x.ai/developers/tools/function-calling).
92
+
@@ -0,0 +1,69 @@
1
+ ![Swarmauri](https://raw.githubusercontent.com/swarmauri/swarmauri-sdk/3d4d1cfa949399d7019ae9d8f296afba773dfb7f/assets/swarmauri.brand.theme.svg)
2
+
3
+ <p align="center">
4
+ <a href="https://pepy.tech/project/swarmauri_llm_xai"><img src="https://static.pepy.tech/badge/swarmauri_llm_xai/month" alt="Downloads"></a>
5
+ <a href="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/community/swarmauri_llm_xai/"><img src="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/community/swarmauri_llm_xai.svg" alt="Hits"></a>
6
+ <a href="https://pypi.org/project/swarmauri_llm_xai/"><img src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue" alt="Python"></a>
7
+ <a href="https://pypi.org/project/swarmauri_llm_xai/"><img src="https://img.shields.io/pypi/l/swarmauri_llm_xai" alt="License"></a>
8
+ <a href="https://pypi.org/project/swarmauri_llm_xai/"><img src="https://img.shields.io/pypi/v/swarmauri_llm_xai" alt="Release"></a>
9
+ </p>
10
+
11
+ # Swarmauri xAI LLM
12
+
13
+ `swarmauri_llm_xai` provides provider-native Swarmauri adapters for xAI's Grok chat-completions API.
14
+
15
+ ## Features
16
+
17
+ - `XAIModel` directly implements the Swarmauri LLM base contract.
18
+ - `XAIToolModel` directly implements the tool-LLM base contract.
19
+ - Bearer-token authentication with credentials excluded from serialized state.
20
+ - Sync, async, incremental streaming, batch, and function-calling workflows.
21
+ - Optional model discovery through xAI's language-model catalog.
22
+ - Explicit provider, HTTP client, and retry-policy composition.
23
+ - Conservative chat retries that do not replay ambiguous connection failures.
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ uv add swarmauri_llm_xai
29
+ ```
30
+
31
+ ```bash
32
+ pip install swarmauri_llm_xai
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ ```python
38
+ import os
39
+
40
+ from swarmauri_llm_xai import XAIModel
41
+ from swarmauri_standard.conversations.Conversation import Conversation
42
+ from swarmauri_standard.messages.HumanMessage import HumanMessage
43
+
44
+ conversation = Conversation(
45
+ messages=[HumanMessage(content="Explain orbital mechanics briefly.")]
46
+ )
47
+ model = XAIModel(api_key=os.environ["XAI_API_KEY"], name="grok-4.3")
48
+ model.predict(conversation)
49
+ print(conversation.get_last().content)
50
+ ```
51
+
52
+ For explicit composition:
53
+
54
+ ```python
55
+ from swarmauri_llm_xai import XAIChatRetryPolicy, XAIModel
56
+ from swarmauri_provider_xai import XAIProvider
57
+ from swarmauri_transport_httpx import HttpxClient
58
+
59
+ provider = XAIProvider(api_key=os.environ["XAI_API_KEY"])
60
+ model = XAIModel(
61
+ provider=provider,
62
+ http_client=HttpxClient(base_url=provider.base_url),
63
+ retry_policy=XAIChatRetryPolicy(max_attempts=3),
64
+ )
65
+ ```
66
+
67
+ Use `XAIToolModel` with a Swarmauri `Toolkit` for function calling. Set `discover_models=True` to populate allowed model IDs from the authenticated xAI language-model catalog.
68
+
69
+ See the [xAI inference reference](https://docs.x.ai/developers/rest-api-reference/inference), [chat endpoint](https://docs.x.ai/developers/rest-api-reference/inference/chat), and [function-calling guide](https://docs.x.ai/developers/tools/function-calling).
@@ -0,0 +1,54 @@
1
+ [project]
2
+ name = "swarmauri_llm_xai"
3
+ version = "0.11.0.dev4"
4
+ description = "Provider-native Swarmauri chat and tool-calling adapters for the xAI Inference API."
5
+ license = "Apache-2.0"
6
+ readme = "README.md"
7
+ requires-python = ">=3.10,<3.13"
8
+ authors = [{ name = "Jacob Stewart", email = "jacob@swarmauri.com" }]
9
+ keywords = ["swarmauri", "llm", "xai", "grok", "tool calling", "streaming", "inference api"]
10
+ classifiers = [
11
+ "Development Status :: 1 - Planning",
12
+ "License :: OSI Approved :: Apache Software License",
13
+ "Programming Language :: Python :: 3.10",
14
+ "Programming Language :: Python :: 3.11",
15
+ "Programming Language :: Python :: 3.12",
16
+ ]
17
+ dependencies = [
18
+ "swarmauri_base>=0.11.0.dev5",
19
+ "swarmauri_core>=0.11.0.dev5",
20
+ "swarmauri_provider_xai>=0.1.0.dev3",
21
+ "swarmauri_standard>=0.11.0.dev6",
22
+ "swarmauri_transport_httpx>=0.1.0.dev5",
23
+ "swarmauri_transport_retry>=0.1.0.dev1",
24
+ ]
25
+
26
+ [tool.uv.sources]
27
+ swarmauri_base = { workspace = true }
28
+ swarmauri_core = { workspace = true }
29
+ swarmauri_provider_xai = { workspace = true }
30
+ swarmauri_standard = { workspace = true }
31
+ swarmauri_transport_httpx = { workspace = true }
32
+ swarmauri_transport_retry = { workspace = true }
33
+
34
+ [project.entry-points."swarmauri.llms"]
35
+ XAIModel = "swarmauri_llm_xai:XAIModel"
36
+
37
+ [project.entry-points."swarmauri.tool_llms"]
38
+ XAIToolModel = "swarmauri_llm_xai:XAIToolModel"
39
+
40
+ [build-system]
41
+ requires = ["poetry-core>=1.0.0"]
42
+ build-backend = "poetry.core.masonry.api"
43
+
44
+ [dependency-groups]
45
+ dev = ["pytest>=8.0", "pytest-asyncio>=0.24", "ruff>=0.9.9"]
46
+
47
+ [tool.pytest.ini_options]
48
+ markers = ["unit: Unit tests"]
49
+
50
+ [tool.ruff]
51
+ extend = "../../pyproject.toml"
52
+
53
+ [tool.ruff.lint]
54
+ ignore = ["N999"]
@@ -0,0 +1,34 @@
1
+ """Replay policy for xAI chat and model-discovery operations."""
2
+
3
+ from swarmauri_core.transports.i_http_response import IHttpResponse
4
+ from swarmauri_transport_retry import ExponentialBackoffRetryPolicy
5
+
6
+
7
+ class XAIChatRetryPolicy(ExponentialBackoffRetryPolicy):
8
+ """Retry xAI reads broadly and chat writes conservatively."""
9
+
10
+ def __init__(self, **kwargs) -> None:
11
+ kwargs.setdefault("retryable_methods", {"GET", "POST"})
12
+ super().__init__(**kwargs)
13
+
14
+ def should_retry(
15
+ self,
16
+ *,
17
+ method: str,
18
+ attempt: int,
19
+ response: IHttpResponse | None = None,
20
+ error: Exception | None = None,
21
+ ) -> bool:
22
+ if method.upper() == "POST":
23
+ return (
24
+ attempt < self.max_attempts
25
+ and error is None
26
+ and response is not None
27
+ and response.status_code == 429
28
+ )
29
+ return super().should_retry(
30
+ method=method,
31
+ attempt=attempt,
32
+ response=response,
33
+ error=error,
34
+ )
@@ -0,0 +1,104 @@
1
+ from typing import Any, ClassVar, Literal
2
+
3
+ from pydantic import PrivateAttr
4
+ from swarmauri_base.ComponentBase import ComponentBase
5
+ from swarmauri_base.llms.LLMBase import LLMBase
6
+ from swarmauri_core.transports.i_http_client import IHttpClient
7
+ from swarmauri_core.transports.i_http_retry_policy import IHttpRetryPolicy
8
+ from swarmauri_provider_xai import XAIProvider
9
+ from swarmauri_standard.utils.provider_chat_transport import (
10
+ abatch_chat,
11
+ apredict_chat,
12
+ astream_chat,
13
+ batch_chat,
14
+ predict_chat,
15
+ stream_chat,
16
+ )
17
+
18
+ from ._client import build_xai_client
19
+
20
+
21
+ @ComponentBase.register_type()
22
+ class XAIModel(LLMBase):
23
+ """Provider-native xAI chat-completions model."""
24
+
25
+ type: Literal["XAIModel"] = "XAIModel"
26
+ base_url: str = "https://api.x.ai/v1"
27
+ name: str = "grok-4.3"
28
+ discover_models: bool = False
29
+ capabilities: ClassVar[frozenset[str]] = frozenset(
30
+ {"chat_completions", "multimodal_input", "streaming", "tools"}
31
+ )
32
+ _provider: XAIProvider = PrivateAttr()
33
+ _http_client: IHttpClient = PrivateAttr()
34
+ _retry_owned_by_transport: bool = PrivateAttr(default=True)
35
+
36
+ predict = predict_chat
37
+ apredict = apredict_chat
38
+ stream = stream_chat
39
+ astream = astream_chat
40
+ batch = batch_chat
41
+ abatch = abatch_chat
42
+
43
+ def __init__(
44
+ self,
45
+ *,
46
+ provider: XAIProvider | None = None,
47
+ http_client: IHttpClient | None = None,
48
+ retry_policy: IHttpRetryPolicy | None = None,
49
+ **data: Any,
50
+ ) -> None:
51
+ selected_name = data.get(
52
+ "name", self.__class__.model_fields["name"].default
53
+ )
54
+ data.setdefault("allowed_models", [selected_name])
55
+ super().__init__(**data)
56
+ if self.api_key is None:
57
+ if provider is None or provider.api_key is None:
58
+ raise ValueError(
59
+ "api_key or an authenticated provider is required"
60
+ )
61
+ self._provider = provider or XAIProvider(
62
+ api_key=self.api_key,
63
+ base_url=self.base_url,
64
+ timeout=self.timeout,
65
+ max_retries=self.max_retries,
66
+ )
67
+ self.base_url = self._provider.base_url or self.base_url
68
+ self._http_client = build_xai_client(
69
+ provider=self._provider,
70
+ http_client=http_client,
71
+ retry_policy=retry_policy,
72
+ )
73
+ if self.discover_models:
74
+ self.allowed_models = self._get_models()
75
+ elif not self.allowed_models:
76
+ self.allowed_models = [self.name]
77
+
78
+ def _build_endpoint(self) -> str:
79
+ config = self._provider.connection_config(
80
+ "chat.completions", model=self.name
81
+ )
82
+ return str(config.endpoint)
83
+
84
+ def _build_headers(self) -> dict[str, str]:
85
+ config = self._provider.connection_config(
86
+ "chat.completions", model=self.name
87
+ )
88
+ return self._provider.authorize(config)
89
+
90
+ def _get_models(self) -> list[str]:
91
+ if not self.discover_models:
92
+ return [self.name]
93
+ config = self._provider.connection_config("models.list")
94
+ response = self._http_client.request(
95
+ "GET",
96
+ str(config.endpoint),
97
+ headers=self._provider.authorize(config),
98
+ )
99
+ response.raise_for_status()
100
+ return [
101
+ item["id"]
102
+ for item in response.json().get("models", [])
103
+ if item.get("id")
104
+ ]
@@ -0,0 +1,111 @@
1
+ from typing import Any, ClassVar, Literal
2
+
3
+ from pydantic import PrivateAttr
4
+ from swarmauri_base.ComponentBase import ComponentBase
5
+ from swarmauri_base.tool_llms.ToolLLMBase import ToolLLMBase
6
+ from swarmauri_core.transports.i_http_client import IHttpClient
7
+ from swarmauri_core.transports.i_http_retry_policy import IHttpRetryPolicy
8
+ from swarmauri_provider_xai import XAIProvider, XAIToolSchemaConverter
9
+ from swarmauri_standard.utils.provider_chat_transport import (
10
+ abatch_tools,
11
+ apredict_tools,
12
+ astream_tools,
13
+ batch_tools,
14
+ format_messages,
15
+ predict_tools,
16
+ stream_tools,
17
+ )
18
+
19
+ from ._client import build_xai_client
20
+
21
+
22
+ @ComponentBase.register_type()
23
+ class XAIToolModel(ToolLLMBase):
24
+ """Provider-native xAI tool-calling model."""
25
+
26
+ type: Literal["XAIToolModel"] = "XAIToolModel"
27
+ base_url: str = "https://api.x.ai/v1"
28
+ name: str = "grok-4.3"
29
+ discover_models: bool = False
30
+ capabilities: ClassVar[frozenset[str]] = frozenset(
31
+ {"chat_completions", "streaming", "tools"}
32
+ )
33
+ _provider: XAIProvider = PrivateAttr()
34
+ _http_client: IHttpClient = PrivateAttr()
35
+ _retry_owned_by_transport: bool = PrivateAttr(default=True)
36
+
37
+ predict = predict_tools
38
+ apredict = apredict_tools
39
+ stream = stream_tools
40
+ astream = astream_tools
41
+ batch = batch_tools
42
+ abatch = abatch_tools
43
+
44
+ def __init__(
45
+ self,
46
+ *,
47
+ provider: XAIProvider | None = None,
48
+ http_client: IHttpClient | None = None,
49
+ retry_policy: IHttpRetryPolicy | None = None,
50
+ **data: Any,
51
+ ) -> None:
52
+ selected_name = data.get(
53
+ "name", self.__class__.model_fields["name"].default
54
+ )
55
+ data.setdefault("allowed_models", [selected_name])
56
+ super().__init__(**data)
57
+ if self.api_key is None:
58
+ if provider is None or provider.api_key is None:
59
+ raise ValueError(
60
+ "api_key or an authenticated provider is required"
61
+ )
62
+ self._provider = provider or XAIProvider(
63
+ api_key=self.api_key,
64
+ base_url=self.base_url,
65
+ timeout=self.timeout,
66
+ max_retries=self.max_retries,
67
+ )
68
+ self.base_url = self._provider.base_url or self.base_url
69
+ self._http_client = build_xai_client(
70
+ provider=self._provider,
71
+ http_client=http_client,
72
+ retry_policy=retry_policy,
73
+ )
74
+ if self.discover_models:
75
+ self.allowed_models = self._get_models()
76
+ elif not self.allowed_models:
77
+ self.allowed_models = [self.name]
78
+
79
+ def get_schema_converter(self):
80
+ return XAIToolSchemaConverter()
81
+
82
+ def _format_messages(self, messages):
83
+ return format_messages(messages)
84
+
85
+ def _build_endpoint(self) -> str:
86
+ config = self._provider.connection_config(
87
+ "chat.completions", model=self.name
88
+ )
89
+ return str(config.endpoint)
90
+
91
+ def _build_headers(self) -> dict[str, str]:
92
+ config = self._provider.connection_config(
93
+ "chat.completions", model=self.name
94
+ )
95
+ return self._provider.authorize(config)
96
+
97
+ def _get_models(self) -> list[str]:
98
+ if not self.discover_models:
99
+ return [self.name]
100
+ config = self._provider.connection_config("models.list")
101
+ response = self._http_client.request(
102
+ "GET",
103
+ str(config.endpoint),
104
+ headers=self._provider.authorize(config),
105
+ )
106
+ response.raise_for_status()
107
+ return [
108
+ item["id"]
109
+ for item in response.json().get("models", [])
110
+ if item.get("id")
111
+ ]
@@ -0,0 +1,12 @@
1
+ from importlib.metadata import PackageNotFoundError, version
2
+
3
+ from .XAIModel import XAIModel
4
+ from .XAIChatRetryPolicy import XAIChatRetryPolicy
5
+ from .XAIToolModel import XAIToolModel
6
+
7
+ try:
8
+ __version__ = version("swarmauri_llm_xai")
9
+ except PackageNotFoundError:
10
+ __version__ = "0.0.0"
11
+
12
+ __all__ = ["XAIChatRetryPolicy", "XAIModel", "XAIToolModel"]
@@ -0,0 +1,27 @@
1
+ """Client composition for xAI model families."""
2
+
3
+ from swarmauri_core.transports.i_http_client import IHttpClient
4
+ from swarmauri_core.transports.i_http_retry_policy import IHttpRetryPolicy
5
+ from swarmauri_provider_xai import XAIProvider
6
+ from swarmauri_transport_httpx import HttpxClient
7
+ from swarmauri_transport_retry import RetryingHttpClient
8
+
9
+ from .XAIChatRetryPolicy import XAIChatRetryPolicy
10
+
11
+
12
+ def build_xai_client(
13
+ *,
14
+ provider: XAIProvider,
15
+ http_client: IHttpClient | None,
16
+ retry_policy: IHttpRetryPolicy | None,
17
+ ) -> IHttpClient:
18
+ concrete_client = http_client or HttpxClient(
19
+ base_url=provider.base_url,
20
+ timeout=provider.timeout,
21
+ )
22
+ return RetryingHttpClient(
23
+ client=concrete_client,
24
+ policy=retry_policy
25
+ or XAIChatRetryPolicy(max_attempts=max(provider.max_retries, 1)),
26
+ own_client=http_client is None,
27
+ )