mineai 0.1.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.
- mineai/__init__.py +22 -0
- mineai/client.py +98 -0
- mineai/errors.py +26 -0
- mineai/models.py +6 -0
- mineai/resources/chat/completions.py +116 -0
- mineai-0.1.0.dist-info/METADATA +132 -0
- mineai-0.1.0.dist-info/RECORD +9 -0
- mineai-0.1.0.dist-info/WHEEL +5 -0
- mineai-0.1.0.dist-info/top_level.txt +1 -0
mineai/__init__.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from .client import MineAI, AsyncMineAI
|
|
2
|
+
from .models import Models
|
|
3
|
+
from .errors import (
|
|
4
|
+
MineAIError,
|
|
5
|
+
AuthenticationError,
|
|
6
|
+
BadRequestError,
|
|
7
|
+
RateLimitError,
|
|
8
|
+
InternalServerError,
|
|
9
|
+
APIConnectionError
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"MineAI",
|
|
14
|
+
"AsyncMineAI",
|
|
15
|
+
"Models",
|
|
16
|
+
"MineAIError",
|
|
17
|
+
"AuthenticationError",
|
|
18
|
+
"BadRequestError",
|
|
19
|
+
"RateLimitError",
|
|
20
|
+
"InternalServerError",
|
|
21
|
+
"APIConnectionError",
|
|
22
|
+
]
|
mineai/client.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from typing import Optional, Dict, Any
|
|
3
|
+
from .errors import (
|
|
4
|
+
AuthenticationError,
|
|
5
|
+
BadRequestError,
|
|
6
|
+
RateLimitError,
|
|
7
|
+
InternalServerError,
|
|
8
|
+
APIConnectionError,
|
|
9
|
+
MineAIError
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
class BaseClient:
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
api_key: str,
|
|
16
|
+
base_url: str = "https://api.mineai.dev",
|
|
17
|
+
timeout: float = 60.0,
|
|
18
|
+
):
|
|
19
|
+
if not api_key:
|
|
20
|
+
raise AuthenticationError("API key is required")
|
|
21
|
+
|
|
22
|
+
self.api_key = api_key
|
|
23
|
+
self.base_url = base_url.rstrip("/")
|
|
24
|
+
self.timeout = timeout
|
|
25
|
+
|
|
26
|
+
def _get_headers(self, memory: bool = False, memory_path: Optional[str] = None) -> Dict[str, str]:
|
|
27
|
+
headers = {
|
|
28
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
29
|
+
"Content-Type": "application/json",
|
|
30
|
+
}
|
|
31
|
+
if memory:
|
|
32
|
+
headers["Memory"] = "true"
|
|
33
|
+
if memory_path:
|
|
34
|
+
headers["Memory-Path"] = memory_path
|
|
35
|
+
return headers
|
|
36
|
+
|
|
37
|
+
def _handle_response(self, response: httpx.Response) -> Any:
|
|
38
|
+
if response.is_success:
|
|
39
|
+
try:
|
|
40
|
+
return response.json()
|
|
41
|
+
except Exception:
|
|
42
|
+
return response.text
|
|
43
|
+
|
|
44
|
+
status_code = response.status_code
|
|
45
|
+
try:
|
|
46
|
+
error_data = response.json()
|
|
47
|
+
message = error_data.get("error", response.text)
|
|
48
|
+
except Exception:
|
|
49
|
+
message = response.text
|
|
50
|
+
|
|
51
|
+
if status_code == 401:
|
|
52
|
+
raise AuthenticationError(message, status_code, response)
|
|
53
|
+
elif status_code == 400:
|
|
54
|
+
raise BadRequestError(message, status_code, response)
|
|
55
|
+
elif status_code == 429:
|
|
56
|
+
raise RateLimitError(message, status_code, response)
|
|
57
|
+
elif status_code >= 500:
|
|
58
|
+
raise InternalServerError(message, status_code, response)
|
|
59
|
+
else:
|
|
60
|
+
raise MineAIError(message, status_code, response)
|
|
61
|
+
|
|
62
|
+
class MineAI(BaseClient):
|
|
63
|
+
def __init__(
|
|
64
|
+
self,
|
|
65
|
+
api_key: str,
|
|
66
|
+
base_url: str = "https://api.mineai.dev",
|
|
67
|
+
timeout: float = 60.0,
|
|
68
|
+
):
|
|
69
|
+
super().__init__(api_key, base_url, timeout)
|
|
70
|
+
self.client = httpx.Client(base_url=self.base_url, timeout=self.timeout)
|
|
71
|
+
|
|
72
|
+
# Resources
|
|
73
|
+
from .resources.chat.completions import Completions
|
|
74
|
+
self.chat = Chat(self)
|
|
75
|
+
|
|
76
|
+
class Chat:
|
|
77
|
+
def __init__(self, client: MineAI):
|
|
78
|
+
from .resources.chat.completions import Completions
|
|
79
|
+
self.completions = Completions(client)
|
|
80
|
+
|
|
81
|
+
class AsyncMineAI(BaseClient):
|
|
82
|
+
def __init__(
|
|
83
|
+
self,
|
|
84
|
+
api_key: str,
|
|
85
|
+
base_url: str = "https://api.mineai.dev",
|
|
86
|
+
timeout: float = 60.0,
|
|
87
|
+
):
|
|
88
|
+
super().__init__(api_key, base_url, timeout)
|
|
89
|
+
self.client = httpx.AsyncClient(base_url=self.base_url, timeout=self.timeout)
|
|
90
|
+
|
|
91
|
+
# Resources
|
|
92
|
+
from .resources.chat.completions import AsyncCompletions
|
|
93
|
+
self.chat = AsyncChat(self)
|
|
94
|
+
|
|
95
|
+
class AsyncChat:
|
|
96
|
+
def __init__(self, client: AsyncMineAI):
|
|
97
|
+
from .resources.chat.completions import AsyncCompletions
|
|
98
|
+
self.completions = AsyncCompletions(client)
|
mineai/errors.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class MineAIError(Exception):
|
|
2
|
+
"""Base class for all MineAI SDK errors."""
|
|
3
|
+
def __init__(self, message: str, status_code: int = None, response: any = None):
|
|
4
|
+
super().__init__(message)
|
|
5
|
+
self.status_code = status_code
|
|
6
|
+
self.response = response
|
|
7
|
+
|
|
8
|
+
class AuthenticationError(MineAIError):
|
|
9
|
+
"""Raised when the API key is invalid or missing."""
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
class BadRequestError(MineAIError):
|
|
13
|
+
"""Raised when the request is invalid."""
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
class RateLimitError(MineAIError):
|
|
17
|
+
"""Raised when the rate limit is exceeded."""
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
class InternalServerError(MineAIError):
|
|
21
|
+
"""Raised when the server encounters an error."""
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
class APIConnectionError(MineAIError):
|
|
25
|
+
"""Raised when there is a problem connecting to the API."""
|
|
26
|
+
pass
|
mineai/models.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import List, Dict, Any, Optional, Union, Iterator, AsyncIterator
|
|
3
|
+
import httpx
|
|
4
|
+
from ...errors import APIConnectionError
|
|
5
|
+
|
|
6
|
+
class Completions:
|
|
7
|
+
def __init__(self, client):
|
|
8
|
+
self._client = client
|
|
9
|
+
|
|
10
|
+
def create(
|
|
11
|
+
self,
|
|
12
|
+
model: str,
|
|
13
|
+
messages: List[Dict[str, str]],
|
|
14
|
+
stream: bool = False,
|
|
15
|
+
memory: bool = False,
|
|
16
|
+
memory_path: Optional[str] = None,
|
|
17
|
+
**kwargs
|
|
18
|
+
) -> Union[Dict[str, Any], Iterator[Dict[str, Any]]]:
|
|
19
|
+
"""
|
|
20
|
+
Create a chat completion.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
model: The ID of the model to use.
|
|
24
|
+
messages: A list of messages comprising the conversation.
|
|
25
|
+
stream: If True, partial message deltas will be sent as SSE.
|
|
26
|
+
memory: If True, enables conversation memory.
|
|
27
|
+
memory_path: Optional path for file-based memory.
|
|
28
|
+
**kwargs: Additional parameters to pass to the API.
|
|
29
|
+
"""
|
|
30
|
+
url = "/v1/chat/completions"
|
|
31
|
+
headers = self._client._get_headers(memory=memory, memory_path=memory_path)
|
|
32
|
+
data = {
|
|
33
|
+
"model": model,
|
|
34
|
+
"messages": messages,
|
|
35
|
+
"stream": stream,
|
|
36
|
+
**kwargs
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if stream:
|
|
40
|
+
return self._stream_request(url, headers, data)
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
response = self._client.client.post(url, headers=headers, json=data)
|
|
44
|
+
return self._client._handle_response(response)
|
|
45
|
+
except httpx.RequestError as e:
|
|
46
|
+
raise APIConnectionError(f"Error connecting to API: {str(e)}")
|
|
47
|
+
|
|
48
|
+
def _stream_request(self, url: str, headers: Dict[str, str], data: Dict[str, Any]) -> Iterator[Dict[str, Any]]:
|
|
49
|
+
try:
|
|
50
|
+
with self._client.client.stream("POST", url, headers=headers, json=data) as response:
|
|
51
|
+
if not response.is_success:
|
|
52
|
+
self._client._handle_response(response)
|
|
53
|
+
|
|
54
|
+
for line in response.iter_lines():
|
|
55
|
+
if line.startswith("data: "):
|
|
56
|
+
content = line[6:].strip()
|
|
57
|
+
if content == "[DONE]":
|
|
58
|
+
break
|
|
59
|
+
try:
|
|
60
|
+
yield json.loads(content)
|
|
61
|
+
except json.JSONDecodeError:
|
|
62
|
+
continue
|
|
63
|
+
except httpx.RequestError as e:
|
|
64
|
+
raise APIConnectionError(f"Error connecting to API: {str(e)}")
|
|
65
|
+
|
|
66
|
+
class AsyncCompletions:
|
|
67
|
+
def __init__(self, client):
|
|
68
|
+
self._client = client
|
|
69
|
+
|
|
70
|
+
async def create(
|
|
71
|
+
self,
|
|
72
|
+
model: str,
|
|
73
|
+
messages: List[Dict[str, str]],
|
|
74
|
+
stream: bool = False,
|
|
75
|
+
memory: bool = False,
|
|
76
|
+
memory_path: Optional[str] = None,
|
|
77
|
+
**kwargs
|
|
78
|
+
) -> Union[Dict[str, Any], AsyncIterator[Dict[str, Any]]]:
|
|
79
|
+
"""
|
|
80
|
+
Create a chat completion asynchronously.
|
|
81
|
+
"""
|
|
82
|
+
url = "/v1/chat/completions"
|
|
83
|
+
headers = self._client._get_headers(memory=memory, memory_path=memory_path)
|
|
84
|
+
data = {
|
|
85
|
+
"model": model,
|
|
86
|
+
"messages": messages,
|
|
87
|
+
"stream": stream,
|
|
88
|
+
**kwargs
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if stream:
|
|
92
|
+
return self._stream_request(url, headers, data)
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
response = await self._client.client.post(url, headers=headers, json=data)
|
|
96
|
+
return self._client._handle_response(response)
|
|
97
|
+
except httpx.RequestError as e:
|
|
98
|
+
raise APIConnectionError(f"Error connecting to API: {str(e)}")
|
|
99
|
+
|
|
100
|
+
async def _stream_request(self, url: str, headers: Dict[str, str], data: Dict[str, Any]) -> AsyncIterator[Dict[str, Any]]:
|
|
101
|
+
try:
|
|
102
|
+
async with self._client.client.stream("POST", url, headers=headers, json=data) as response:
|
|
103
|
+
if not response.is_success:
|
|
104
|
+
self._client._handle_response(response)
|
|
105
|
+
|
|
106
|
+
async for line in response.aiter_lines():
|
|
107
|
+
if line.startswith("data: "):
|
|
108
|
+
content = line[6:].strip()
|
|
109
|
+
if content == "[DONE]":
|
|
110
|
+
break
|
|
111
|
+
try:
|
|
112
|
+
yield json.loads(content)
|
|
113
|
+
except json.JSONDecodeError:
|
|
114
|
+
continue
|
|
115
|
+
except httpx.RequestError as e:
|
|
116
|
+
raise APIConnectionError(f"Error connecting to API: {str(e)}")
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mineai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The official Python SDK for MineAI
|
|
5
|
+
Author-email: MineAI Team <support@getmineai.site>
|
|
6
|
+
Project-URL: Homepage, https://studio.getmineai.site
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/OfficalMinecore/mineai-sdk-python/issues
|
|
8
|
+
Project-URL: Repository, https://github.com/OfficalMinecore/mineai-sdk-python
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.7
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: httpx>=0.20.0
|
|
15
|
+
|
|
16
|
+
# MineAI Python SDK
|
|
17
|
+
|
|
18
|
+
The official Python SDK from [MineAI-Studio](https://studio.getmineai.site).
|
|
19
|
+
|
|
20
|
+
Powered by [http://getmineai.site/](http://getmineai.site/)
|
|
21
|
+
|
|
22
|
+
- [Github](https://github.com/OfficalMinecore/mineai-sdk)
|
|
23
|
+
- [Discord Server](https://discord.gg/fbfdwpHctb) – Join the server for Support.
|
|
24
|
+
|
|
25
|
+
### Integrations:
|
|
26
|
+
|
|
27
|
+
- Go To [MineAI-Studio](https://studio.getmineai.site/)
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install mineai
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
### Sync Client
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from mineai import MineAI, Models
|
|
41
|
+
|
|
42
|
+
client = MineAI(api_key="YOUR_API_KEY")
|
|
43
|
+
|
|
44
|
+
response = client.chat.completions.create(
|
|
45
|
+
model=Models.R3_RT_Y,
|
|
46
|
+
messages=[
|
|
47
|
+
{"role": "user", "content": "Hello MineAI!"}
|
|
48
|
+
]
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
print(response['choices'][0]['message']['content'])
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Async Client
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import asyncio
|
|
58
|
+
from mineai import AsyncMineAI, Models
|
|
59
|
+
|
|
60
|
+
async def main():
|
|
61
|
+
client = AsyncMineAI(api_key="YOUR_API_KEY")
|
|
62
|
+
|
|
63
|
+
response = await client.chat.completions.create(
|
|
64
|
+
model=Models.R3_RT_Z,
|
|
65
|
+
messages=[
|
|
66
|
+
{"role": "user", "content": "Tell me a joke."}
|
|
67
|
+
]
|
|
68
|
+
)
|
|
69
|
+
print(response['choices'][0]['message']['content'])
|
|
70
|
+
|
|
71
|
+
asyncio.run(main())
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Streaming
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from mineai import MineAI, Models
|
|
78
|
+
|
|
79
|
+
client = MineAI(api_key="YOUR_API_KEY")
|
|
80
|
+
|
|
81
|
+
stream = client.chat.completions.create(
|
|
82
|
+
model=Models.O1_FREE,
|
|
83
|
+
messages=[
|
|
84
|
+
{"role": "user", "content": "Write a long story."}
|
|
85
|
+
],
|
|
86
|
+
stream=True
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
for chunk in stream:
|
|
90
|
+
if 'choices' in chunk:
|
|
91
|
+
content = chunk['choices'][0].get('delta', {}).get('content', '')
|
|
92
|
+
print(content, end='', flush=True)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Memory Support
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from mineai import MineAI, Models
|
|
99
|
+
|
|
100
|
+
client = MineAI(api_key="YOUR_API_KEY")
|
|
101
|
+
|
|
102
|
+
# Enable database-backed memory
|
|
103
|
+
response = client.chat.completions.create(
|
|
104
|
+
model=Models.R3_RT_Y,
|
|
105
|
+
messages=[
|
|
106
|
+
{"role": "user", "content": "My name is John."}
|
|
107
|
+
],
|
|
108
|
+
memory=True
|
|
109
|
+
)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Error Handling
|
|
113
|
+
|
|
114
|
+
The SDK provides custom exception classes for different API error scenarios:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from mineai import MineAI, AuthenticationError, RateLimitError
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
client = MineAI(api_key="INVALID_KEY")
|
|
121
|
+
client.chat.completions.create(...)
|
|
122
|
+
except AuthenticationError:
|
|
123
|
+
print("Invalid API key provided.")
|
|
124
|
+
except RateLimitError:
|
|
125
|
+
print("Rate limit exceeded.")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Supported Models
|
|
129
|
+
|
|
130
|
+
- `Models.R3_RT_Y` (`mine:r3-rt-y`)
|
|
131
|
+
- `Models.R3_RT_Z` (`mine:r3-rt-z`)
|
|
132
|
+
- `Models.O1_FREE` (`mine:o1-free`)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
mineai/__init__.py,sha256=og9p8irF5zMOyhte8xQLPgQ3EegRKmfRgY7w46mh1Og,428
|
|
2
|
+
mineai/client.py,sha256=kSpOw_ZyIYxAWS7Wa-EjLvRTIo5vlUnOxYYyXQTc5h4,3086
|
|
3
|
+
mineai/errors.py,sha256=jVqSkAqdxNtGBOsSerBV9aoNZeiM1dL-m4ficKjoxIA,780
|
|
4
|
+
mineai/models.py,sha256=DNo7r46t-nVqjDYmzuQp5MIz8XqID8UBLanIlHJ3P3g,155
|
|
5
|
+
mineai/resources/chat/completions.py,sha256=5JCYWT7GrtB1MPhYkleEs8n82-r_foMWzc-FEozgbjU,4397
|
|
6
|
+
mineai-0.1.0.dist-info/METADATA,sha256=MNRetIN_yujHyXDdOmHFndBSUQB4Q6Xfalf5GfVSpwE,3028
|
|
7
|
+
mineai-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
+
mineai-0.1.0.dist-info/top_level.txt,sha256=TCTINwTbVDu8CrOXaosKbf9l92X2vTRTbbfB0r-tVBw,7
|
|
9
|
+
mineai-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mineai
|