impossibl 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- impossibl-0.0.1/PKG-INFO +65 -0
- impossibl-0.0.1/PYTHON.md +56 -0
- impossibl-0.0.1/README.md +54 -0
- impossibl-0.0.1/pyproject.toml +17 -0
- impossibl-0.0.1/setup.cfg +4 -0
- impossibl-0.0.1/src/impossibl/__init__.py +19 -0
- impossibl-0.0.1/src/impossibl.egg-info/PKG-INFO +65 -0
- impossibl-0.0.1/src/impossibl.egg-info/SOURCES.txt +10 -0
- impossibl-0.0.1/src/impossibl.egg-info/dependency_links.txt +1 -0
- impossibl-0.0.1/src/impossibl.egg-info/requires.txt +1 -0
- impossibl-0.0.1/src/impossibl.egg-info/top_level.txt +1 -0
- impossibl-0.0.1/tests/test_client.py +61 -0
impossibl-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: impossibl
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A minimal Python client for the Impossibl AI API.
|
|
5
|
+
Project-URL: Homepage, https://impossibl.com
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: openai<3,>=2
|
|
9
|
+
|
|
10
|
+
# impossibl
|
|
11
|
+
|
|
12
|
+
Impossibl is an AI gateway with self-serve inference.
|
|
13
|
+
|
|
14
|
+
Build with models from OpenAI, Anthropic, Google, and xAI through one
|
|
15
|
+
OpenAI-compatible API. Change the model ID to try another provider, while
|
|
16
|
+
keeping the same integration.
|
|
17
|
+
|
|
18
|
+
[Impossibl](https://impossibl.com) brings your models together with one API key,
|
|
19
|
+
unified usage and billing, and automatic provider fallbacks.
|
|
20
|
+
|
|
21
|
+
## Python client
|
|
22
|
+
|
|
23
|
+
This package is a small client for the hosted Impossibl API. It extends the
|
|
24
|
+
OpenAI Python client with Impossibl's endpoint and the `IMPOSSIBL_API_KEY`
|
|
25
|
+
environment variable.
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
pip install impossibl
|
|
29
|
+
export IMPOSSIBL_API_KEY="your-api-key"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
List available models:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from impossibl import Impossibl
|
|
36
|
+
|
|
37
|
+
with Impossibl() as client:
|
|
38
|
+
for model in client.models.list():
|
|
39
|
+
print(model.id)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Generate a response using a model ID from the list:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
import os
|
|
46
|
+
from impossibl import Impossibl
|
|
47
|
+
|
|
48
|
+
with Impossibl() as client:
|
|
49
|
+
response = client.chat.completions.create(
|
|
50
|
+
model=os.environ["IMPOSSIBL_MODEL"],
|
|
51
|
+
messages=[{"role": "user", "content": "Hello!"}],
|
|
52
|
+
)
|
|
53
|
+
print(response.choices[0].message.content)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Set `IMPOSSIBL_MODEL` to your chosen model ID before running the second example.
|
|
57
|
+
Model availability, pricing, and API credentials are managed by Impossibl.
|
|
58
|
+
Generation requests may consume your account balance.
|
|
59
|
+
|
|
60
|
+
You can also pass `api_key` explicitly. OpenAI client options such as `timeout`,
|
|
61
|
+
`max_retries`, and `base_url` are forwarded unchanged. An explicit key takes
|
|
62
|
+
precedence over `IMPOSSIBL_API_KEY`; `OPENAI_API_KEY` is not used as a fallback.
|
|
63
|
+
|
|
64
|
+
This initial release provides a synchronous client. It does not create accounts
|
|
65
|
+
or manage billing. API compatibility is determined by the Impossibl service.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# impossibl
|
|
2
|
+
|
|
3
|
+
Impossibl is an AI gateway with self-serve inference.
|
|
4
|
+
|
|
5
|
+
Build with models from OpenAI, Anthropic, Google, and xAI through one
|
|
6
|
+
OpenAI-compatible API. Change the model ID to try another provider, while
|
|
7
|
+
keeping the same integration.
|
|
8
|
+
|
|
9
|
+
[Impossibl](https://impossibl.com) brings your models together with one API key,
|
|
10
|
+
unified usage and billing, and automatic provider fallbacks.
|
|
11
|
+
|
|
12
|
+
## Python client
|
|
13
|
+
|
|
14
|
+
This package is a small client for the hosted Impossibl API. It extends the
|
|
15
|
+
OpenAI Python client with Impossibl's endpoint and the `IMPOSSIBL_API_KEY`
|
|
16
|
+
environment variable.
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
pip install impossibl
|
|
20
|
+
export IMPOSSIBL_API_KEY="your-api-key"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
List available models:
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from impossibl import Impossibl
|
|
27
|
+
|
|
28
|
+
with Impossibl() as client:
|
|
29
|
+
for model in client.models.list():
|
|
30
|
+
print(model.id)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Generate a response using a model ID from the list:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
import os
|
|
37
|
+
from impossibl import Impossibl
|
|
38
|
+
|
|
39
|
+
with Impossibl() as client:
|
|
40
|
+
response = client.chat.completions.create(
|
|
41
|
+
model=os.environ["IMPOSSIBL_MODEL"],
|
|
42
|
+
messages=[{"role": "user", "content": "Hello!"}],
|
|
43
|
+
)
|
|
44
|
+
print(response.choices[0].message.content)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Set `IMPOSSIBL_MODEL` to your chosen model ID before running the second example.
|
|
48
|
+
Model availability, pricing, and API credentials are managed by Impossibl.
|
|
49
|
+
Generation requests may consume your account balance.
|
|
50
|
+
|
|
51
|
+
You can also pass `api_key` explicitly. OpenAI client options such as `timeout`,
|
|
52
|
+
`max_retries`, and `base_url` are forwarded unchanged. An explicit key takes
|
|
53
|
+
precedence over `IMPOSSIBL_API_KEY`; `OPENAI_API_KEY` is not used as a fallback.
|
|
54
|
+
|
|
55
|
+
This initial release provides a synchronous client. It does not create accounts
|
|
56
|
+
or manage billing. API compatibility is determined by the Impossibl service.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# impossibl
|
|
2
|
+
|
|
3
|
+
Impossibl is an AI gateway with self-serve inference.
|
|
4
|
+
|
|
5
|
+
Build with models from OpenAI, Anthropic, Google, and xAI through one
|
|
6
|
+
OpenAI-compatible API. Change the model ID to try another provider, while
|
|
7
|
+
keeping the same integration.
|
|
8
|
+
|
|
9
|
+
[Impossibl](https://impossibl.com) brings your models together with one API key,
|
|
10
|
+
unified usage and billing, and automatic provider fallbacks. Connect your existing
|
|
11
|
+
OpenAI SDK to `https://api.impossibl.com/v1` to get started.
|
|
12
|
+
|
|
13
|
+
Explore the API at [impossibl.com](https://impossibl.com).
|
|
14
|
+
|
|
15
|
+
## Packages
|
|
16
|
+
|
|
17
|
+
The Python package is a small client for the hosted API. It configures the
|
|
18
|
+
OpenAI Python SDK with Impossibl's endpoint and your `IMPOSSIBL_API_KEY`.
|
|
19
|
+
See [Python usage](PYTHON.md) for installation and examples.
|
|
20
|
+
|
|
21
|
+
The npm package is still a placeholder with no functionality.
|
|
22
|
+
|
|
23
|
+
## Publishing
|
|
24
|
+
|
|
25
|
+
Both packages use version `0.0.1`. Update `package.json`, `pyproject.toml`, and
|
|
26
|
+
`src/impossibl/__init__.py` together for future releases.
|
|
27
|
+
|
|
28
|
+
### npm
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
npm login
|
|
32
|
+
npm publish --access public
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### PyPI
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
python3 -m venv .venv
|
|
39
|
+
.venv/bin/python -m pip install build twine
|
|
40
|
+
.venv/bin/python -m build
|
|
41
|
+
.venv/bin/python -m twine check dist/*
|
|
42
|
+
.venv/bin/python -m twine upload dist/*
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Publishing requires an available package name and registry credentials.
|
|
46
|
+
|
|
47
|
+
## Python verification
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
.venv/bin/python -m pip install -e .
|
|
51
|
+
.venv/bin/python -m unittest discover -s tests
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Tests use mocked HTTP requests; they do not call the live API or spend credits.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "impossibl"
|
|
7
|
+
version = "0.0.1"
|
|
8
|
+
description = "A minimal Python client for the Impossibl AI API."
|
|
9
|
+
readme = "PYTHON.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
dependencies = ["openai>=2,<3"]
|
|
12
|
+
|
|
13
|
+
[project.urls]
|
|
14
|
+
Homepage = "https://impossibl.com"
|
|
15
|
+
|
|
16
|
+
[tool.setuptools.packages.find]
|
|
17
|
+
where = ["src"]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""A minimal Python client for the Impossibl AI API."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
|
|
6
|
+
from openai import OpenAI
|
|
7
|
+
|
|
8
|
+
__version__ = "0.0.1"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Impossibl(OpenAI):
|
|
12
|
+
"""OpenAI-compatible client using Impossibl's endpoint and API key."""
|
|
13
|
+
|
|
14
|
+
def __init__(self, *, api_key: Optional[str] = None, **kwargs: Any) -> None:
|
|
15
|
+
key = api_key if api_key is not None else os.environ.get("IMPOSSIBL_API_KEY")
|
|
16
|
+
if not key:
|
|
17
|
+
raise ValueError("Pass api_key or set the IMPOSSIBL_API_KEY environment variable.")
|
|
18
|
+
kwargs.setdefault("base_url", "https://api.impossibl.com/v1")
|
|
19
|
+
super().__init__(api_key=key, **kwargs)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: impossibl
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A minimal Python client for the Impossibl AI API.
|
|
5
|
+
Project-URL: Homepage, https://impossibl.com
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: openai<3,>=2
|
|
9
|
+
|
|
10
|
+
# impossibl
|
|
11
|
+
|
|
12
|
+
Impossibl is an AI gateway with self-serve inference.
|
|
13
|
+
|
|
14
|
+
Build with models from OpenAI, Anthropic, Google, and xAI through one
|
|
15
|
+
OpenAI-compatible API. Change the model ID to try another provider, while
|
|
16
|
+
keeping the same integration.
|
|
17
|
+
|
|
18
|
+
[Impossibl](https://impossibl.com) brings your models together with one API key,
|
|
19
|
+
unified usage and billing, and automatic provider fallbacks.
|
|
20
|
+
|
|
21
|
+
## Python client
|
|
22
|
+
|
|
23
|
+
This package is a small client for the hosted Impossibl API. It extends the
|
|
24
|
+
OpenAI Python client with Impossibl's endpoint and the `IMPOSSIBL_API_KEY`
|
|
25
|
+
environment variable.
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
pip install impossibl
|
|
29
|
+
export IMPOSSIBL_API_KEY="your-api-key"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
List available models:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from impossibl import Impossibl
|
|
36
|
+
|
|
37
|
+
with Impossibl() as client:
|
|
38
|
+
for model in client.models.list():
|
|
39
|
+
print(model.id)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Generate a response using a model ID from the list:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
import os
|
|
46
|
+
from impossibl import Impossibl
|
|
47
|
+
|
|
48
|
+
with Impossibl() as client:
|
|
49
|
+
response = client.chat.completions.create(
|
|
50
|
+
model=os.environ["IMPOSSIBL_MODEL"],
|
|
51
|
+
messages=[{"role": "user", "content": "Hello!"}],
|
|
52
|
+
)
|
|
53
|
+
print(response.choices[0].message.content)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Set `IMPOSSIBL_MODEL` to your chosen model ID before running the second example.
|
|
57
|
+
Model availability, pricing, and API credentials are managed by Impossibl.
|
|
58
|
+
Generation requests may consume your account balance.
|
|
59
|
+
|
|
60
|
+
You can also pass `api_key` explicitly. OpenAI client options such as `timeout`,
|
|
61
|
+
`max_retries`, and `base_url` are forwarded unchanged. An explicit key takes
|
|
62
|
+
precedence over `IMPOSSIBL_API_KEY`; `OPENAI_API_KEY` is not used as a fallback.
|
|
63
|
+
|
|
64
|
+
This initial release provides a synchronous client. It does not create accounts
|
|
65
|
+
or manage billing. API compatibility is determined by the Impossibl service.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
PYTHON.md
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/impossibl/__init__.py
|
|
5
|
+
src/impossibl.egg-info/PKG-INFO
|
|
6
|
+
src/impossibl.egg-info/SOURCES.txt
|
|
7
|
+
src/impossibl.egg-info/dependency_links.txt
|
|
8
|
+
src/impossibl.egg-info/requires.txt
|
|
9
|
+
src/impossibl.egg-info/top_level.txt
|
|
10
|
+
tests/test_client.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
openai<3,>=2
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
impossibl
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import unittest
|
|
4
|
+
from unittest.mock import patch
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
|
|
8
|
+
from impossibl import Impossibl
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ClientTests(unittest.TestCase):
|
|
12
|
+
@patch.dict(os.environ, {"IMPOSSIBL_API_KEY": "test-impossibl-key"}, clear=True)
|
|
13
|
+
def test_models_use_gateway_and_environment_key(self):
|
|
14
|
+
def handle(request):
|
|
15
|
+
self.assertEqual(request.method, "GET")
|
|
16
|
+
self.assertEqual(str(request.url), "https://api.impossibl.com/v1/models")
|
|
17
|
+
self.assertEqual(request.headers["authorization"], "Bearer test-impossibl-key")
|
|
18
|
+
return httpx.Response(200, json={
|
|
19
|
+
"object": "list",
|
|
20
|
+
"data": [{"id": "test/model", "object": "model", "created": 0,
|
|
21
|
+
"owned_by": "test"}],
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
with Impossibl(http_client=httpx.Client(transport=httpx.MockTransport(handle))) as client:
|
|
25
|
+
self.assertEqual(client.models.list().data[0].id, "test/model")
|
|
26
|
+
|
|
27
|
+
@patch.dict(os.environ, {"IMPOSSIBL_API_KEY": "environment-key"}, clear=True)
|
|
28
|
+
def test_completion_and_explicit_options(self):
|
|
29
|
+
def handle(request):
|
|
30
|
+
self.assertEqual(request.method, "POST")
|
|
31
|
+
self.assertEqual(str(request.url), "https://example.test/v1/chat/completions")
|
|
32
|
+
self.assertEqual(request.headers["authorization"], "Bearer explicit-key")
|
|
33
|
+
self.assertEqual(json.loads(request.content), {
|
|
34
|
+
"model": "test/model",
|
|
35
|
+
"messages": [{"role": "user", "content": "Hello!"}],
|
|
36
|
+
})
|
|
37
|
+
return httpx.Response(200, json={
|
|
38
|
+
"id": "test-completion", "object": "chat.completion", "created": 0,
|
|
39
|
+
"model": "test/model",
|
|
40
|
+
"choices": [{"index": 0, "finish_reason": "stop",
|
|
41
|
+
"message": {"role": "assistant", "content": "Hi!"}}],
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
with Impossibl(
|
|
45
|
+
api_key="explicit-key", base_url="https://example.test/v1",
|
|
46
|
+
http_client=httpx.Client(transport=httpx.MockTransport(handle)),
|
|
47
|
+
) as client:
|
|
48
|
+
response = client.chat.completions.create(
|
|
49
|
+
model="test/model", messages=[{"role": "user", "content": "Hello!"}],
|
|
50
|
+
)
|
|
51
|
+
self.assertEqual(response.choices[0].message.content, "Hi!")
|
|
52
|
+
|
|
53
|
+
@patch.dict(os.environ, {"OPENAI_API_KEY": "unrelated-key"}, clear=True)
|
|
54
|
+
def test_missing_key_does_not_fall_back_to_openai_key(self):
|
|
55
|
+
with self.assertRaisesRegex(ValueError, "IMPOSSIBL_API_KEY"):
|
|
56
|
+
Impossibl()
|
|
57
|
+
|
|
58
|
+
@patch.dict(os.environ, {"IMPOSSIBL_API_KEY": "environment-key"}, clear=True)
|
|
59
|
+
def test_empty_explicit_key_is_rejected(self):
|
|
60
|
+
with self.assertRaisesRegex(ValueError, "IMPOSSIBL_API_KEY"):
|
|
61
|
+
Impossibl(api_key="")
|