mira-network 0.1.0__tar.gz → 0.1.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.
- mira_network-0.1.1/PKG-INFO +107 -0
- mira_network-0.1.1/README.md +94 -0
- mira_network-0.1.1/pyproject.toml +34 -0
- mira_network-0.1.1/src/mira_sdk/__init__.py +21 -0
- mira_network-0.1.1/src/mira_sdk/client.py +180 -0
- mira_network-0.1.1/src/mira_sdk/models.py +67 -0
- mira_network-0.1.1/tests/test_client.py +109 -0
- mira_network-0.1.1/tests/test_integration.py +48 -0
- mira_network-0.1.1/tests/test_models.py +109 -0
- mira_network-0.1.0/PKG-INFO +0 -10
- mira_network-0.1.0/README.md +0 -1
- mira_network-0.1.0/pyproject.toml +0 -19
- mira_network-0.1.0/setup.cfg +0 -4
- mira_network-0.1.0/src/mira_network/client.py +0 -8
- mira_network-0.1.0/src/mira_network.egg-info/PKG-INFO +0 -10
- mira_network-0.1.0/src/mira_network.egg-info/SOURCES.txt +0 -9
- mira_network-0.1.0/src/mira_network.egg-info/dependency_links.txt +0 -1
- mira_network-0.1.0/src/mira_network.egg-info/top_level.txt +0 -1
- mira_network-0.1.0/tests/test_client.py +0 -26
- {mira_network-0.1.0/src/mira_network → mira_network-0.1.1/tests}/__init__.py +0 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: mira-network
|
3
|
+
Version: 0.1.1
|
4
|
+
Summary: Python SDK for Mira Network API
|
5
|
+
Author-Email: sarim2000 <sarimbleedblue@gmail.com>
|
6
|
+
License: MIT
|
7
|
+
Requires-Python: ==3.10.*
|
8
|
+
Requires-Dist: httpx>=0.28.1
|
9
|
+
Requires-Dist: pydantic>=2.10.4
|
10
|
+
Requires-Dist: typing-extensions>=4.8.0
|
11
|
+
Requires-Dist: requests>=2.32.3
|
12
|
+
Description-Content-Type: text/markdown
|
13
|
+
|
14
|
+
# Mira SDK
|
15
|
+
|
16
|
+
A Python SDK for interacting with the Mira Network API. This SDK provides a simple interface to access all Mira API endpoints including model inference, flow management, and credit system.
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
```bash
|
21
|
+
pip install mira-sdk
|
22
|
+
```
|
23
|
+
|
24
|
+
## Quick Start
|
25
|
+
|
26
|
+
```python
|
27
|
+
import asyncio
|
28
|
+
from mira_sdk import MiraClient, Message, AiRequest
|
29
|
+
|
30
|
+
async def main():
|
31
|
+
# Initialize client
|
32
|
+
client = MiraClient(
|
33
|
+
base_url="https://api.mira.example.com",
|
34
|
+
api_token="your-api-token"
|
35
|
+
)
|
36
|
+
|
37
|
+
# List available models
|
38
|
+
models = await client.list_models()
|
39
|
+
print("Available models:", models)
|
40
|
+
|
41
|
+
# Generate text
|
42
|
+
request = AiRequest(
|
43
|
+
model="mira/llama3.1",
|
44
|
+
messages=[
|
45
|
+
Message(role="system", content="You are a helpful assistant."),
|
46
|
+
Message(role="user", content="Hello!")
|
47
|
+
],
|
48
|
+
model_provider=None
|
49
|
+
)
|
50
|
+
|
51
|
+
response = await client.generate(request)
|
52
|
+
print("Response:", response)
|
53
|
+
|
54
|
+
if __name__ == "__main__":
|
55
|
+
asyncio.run(main())
|
56
|
+
```
|
57
|
+
|
58
|
+
## Features
|
59
|
+
|
60
|
+
- Asynchronous API using `httpx`
|
61
|
+
- Full type hints support
|
62
|
+
- Pydantic models for request/response validation
|
63
|
+
- Support for all Mira API endpoints:
|
64
|
+
- Model inference
|
65
|
+
- Flow management
|
66
|
+
- API token management
|
67
|
+
- Credit system
|
68
|
+
|
69
|
+
## API Reference
|
70
|
+
|
71
|
+
### Models
|
72
|
+
|
73
|
+
- `Message`: Represents a chat message
|
74
|
+
- `ModelProvider`: Configuration for custom model providers
|
75
|
+
- `AiRequest`: Request for model inference
|
76
|
+
- `FlowChatCompletion`: Request for flow-based chat completion
|
77
|
+
- `FlowRequest`: Request for creating/updating flows
|
78
|
+
- `ApiTokenRequest`: Request for creating API tokens
|
79
|
+
- `AddCreditRequest`: Request for adding credits
|
80
|
+
|
81
|
+
### Client Methods
|
82
|
+
|
83
|
+
#### Model Operations
|
84
|
+
- `list_models()`: List available models
|
85
|
+
- `generate(request: AiRequest)`: Generate text using specified model
|
86
|
+
|
87
|
+
#### Flow Operations
|
88
|
+
- `list_flows()`: List all flows
|
89
|
+
- `get_flow(flow_id: str)`: Get flow details
|
90
|
+
- `create_flow(request: FlowRequest)`: Create new flow
|
91
|
+
- `update_flow(flow_id: str, request: FlowRequest)`: Update flow
|
92
|
+
- `delete_flow(flow_id: str)`: Delete flow
|
93
|
+
- `generate_with_flow(flow_id: str, request: FlowChatCompletion)`: Generate using flow
|
94
|
+
|
95
|
+
#### Token Operations
|
96
|
+
- `create_api_token(request: ApiTokenRequest)`: Create API token
|
97
|
+
- `list_api_tokens()`: List API tokens
|
98
|
+
- `delete_api_token(token: str)`: Delete API token
|
99
|
+
|
100
|
+
#### Credit Operations
|
101
|
+
- `get_user_credits()`: Get credit information
|
102
|
+
- `add_credit(request: AddCreditRequest)`: Add credits
|
103
|
+
- `get_credits_history()`: Get credit history
|
104
|
+
|
105
|
+
## License
|
106
|
+
|
107
|
+
MIT License
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# Mira SDK
|
2
|
+
|
3
|
+
A Python SDK for interacting with the Mira Network API. This SDK provides a simple interface to access all Mira API endpoints including model inference, flow management, and credit system.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```bash
|
8
|
+
pip install mira-sdk
|
9
|
+
```
|
10
|
+
|
11
|
+
## Quick Start
|
12
|
+
|
13
|
+
```python
|
14
|
+
import asyncio
|
15
|
+
from mira_sdk import MiraClient, Message, AiRequest
|
16
|
+
|
17
|
+
async def main():
|
18
|
+
# Initialize client
|
19
|
+
client = MiraClient(
|
20
|
+
base_url="https://api.mira.example.com",
|
21
|
+
api_token="your-api-token"
|
22
|
+
)
|
23
|
+
|
24
|
+
# List available models
|
25
|
+
models = await client.list_models()
|
26
|
+
print("Available models:", models)
|
27
|
+
|
28
|
+
# Generate text
|
29
|
+
request = AiRequest(
|
30
|
+
model="mira/llama3.1",
|
31
|
+
messages=[
|
32
|
+
Message(role="system", content="You are a helpful assistant."),
|
33
|
+
Message(role="user", content="Hello!")
|
34
|
+
],
|
35
|
+
model_provider=None
|
36
|
+
)
|
37
|
+
|
38
|
+
response = await client.generate(request)
|
39
|
+
print("Response:", response)
|
40
|
+
|
41
|
+
if __name__ == "__main__":
|
42
|
+
asyncio.run(main())
|
43
|
+
```
|
44
|
+
|
45
|
+
## Features
|
46
|
+
|
47
|
+
- Asynchronous API using `httpx`
|
48
|
+
- Full type hints support
|
49
|
+
- Pydantic models for request/response validation
|
50
|
+
- Support for all Mira API endpoints:
|
51
|
+
- Model inference
|
52
|
+
- Flow management
|
53
|
+
- API token management
|
54
|
+
- Credit system
|
55
|
+
|
56
|
+
## API Reference
|
57
|
+
|
58
|
+
### Models
|
59
|
+
|
60
|
+
- `Message`: Represents a chat message
|
61
|
+
- `ModelProvider`: Configuration for custom model providers
|
62
|
+
- `AiRequest`: Request for model inference
|
63
|
+
- `FlowChatCompletion`: Request for flow-based chat completion
|
64
|
+
- `FlowRequest`: Request for creating/updating flows
|
65
|
+
- `ApiTokenRequest`: Request for creating API tokens
|
66
|
+
- `AddCreditRequest`: Request for adding credits
|
67
|
+
|
68
|
+
### Client Methods
|
69
|
+
|
70
|
+
#### Model Operations
|
71
|
+
- `list_models()`: List available models
|
72
|
+
- `generate(request: AiRequest)`: Generate text using specified model
|
73
|
+
|
74
|
+
#### Flow Operations
|
75
|
+
- `list_flows()`: List all flows
|
76
|
+
- `get_flow(flow_id: str)`: Get flow details
|
77
|
+
- `create_flow(request: FlowRequest)`: Create new flow
|
78
|
+
- `update_flow(flow_id: str, request: FlowRequest)`: Update flow
|
79
|
+
- `delete_flow(flow_id: str)`: Delete flow
|
80
|
+
- `generate_with_flow(flow_id: str, request: FlowChatCompletion)`: Generate using flow
|
81
|
+
|
82
|
+
#### Token Operations
|
83
|
+
- `create_api_token(request: ApiTokenRequest)`: Create API token
|
84
|
+
- `list_api_tokens()`: List API tokens
|
85
|
+
- `delete_api_token(token: str)`: Delete API token
|
86
|
+
|
87
|
+
#### Credit Operations
|
88
|
+
- `get_user_credits()`: Get credit information
|
89
|
+
- `add_credit(request: AddCreditRequest)`: Add credits
|
90
|
+
- `get_credits_history()`: Get credit history
|
91
|
+
|
92
|
+
## License
|
93
|
+
|
94
|
+
MIT License
|
@@ -0,0 +1,34 @@
|
|
1
|
+
[project]
|
2
|
+
name = "mira-network"
|
3
|
+
version = "0.1.1"
|
4
|
+
description = "Python SDK for Mira Network API"
|
5
|
+
authors = [
|
6
|
+
{ name = "sarim2000", email = "sarimbleedblue@gmail.com" },
|
7
|
+
]
|
8
|
+
dependencies = [
|
9
|
+
"httpx>=0.28.1",
|
10
|
+
"pydantic>=2.10.4",
|
11
|
+
"typing-extensions>=4.8.0",
|
12
|
+
"requests>=2.32.3",
|
13
|
+
]
|
14
|
+
requires-python = "==3.10.*"
|
15
|
+
readme = "README.md"
|
16
|
+
|
17
|
+
[project.license]
|
18
|
+
text = "MIT"
|
19
|
+
|
20
|
+
[build-system]
|
21
|
+
requires = [
|
22
|
+
"pdm-backend",
|
23
|
+
]
|
24
|
+
build-backend = "pdm.backend"
|
25
|
+
|
26
|
+
[tool.pdm]
|
27
|
+
distribution = true
|
28
|
+
|
29
|
+
[dependency-groups]
|
30
|
+
test = [
|
31
|
+
"pytest>=8.3.4",
|
32
|
+
"pytest-asyncio>=0.25.0",
|
33
|
+
"pytest-cov>=6.0.0",
|
34
|
+
]
|
@@ -0,0 +1,21 @@
|
|
1
|
+
from .client import MiraClient
|
2
|
+
from .models import (
|
3
|
+
Message,
|
4
|
+
ModelProvider,
|
5
|
+
AiRequest,
|
6
|
+
FlowChatCompletion,
|
7
|
+
FlowRequest,
|
8
|
+
ApiTokenRequest,
|
9
|
+
AddCreditRequest,
|
10
|
+
)
|
11
|
+
|
12
|
+
__all__ = [
|
13
|
+
"MiraClient",
|
14
|
+
"Message",
|
15
|
+
"ModelProvider",
|
16
|
+
"AiRequest",
|
17
|
+
"FlowChatCompletion",
|
18
|
+
"FlowRequest",
|
19
|
+
"ApiTokenRequest",
|
20
|
+
"AddCreditRequest",
|
21
|
+
]
|
@@ -0,0 +1,180 @@
|
|
1
|
+
from typing import Optional, List, Dict, AsyncGenerator, Union
|
2
|
+
import httpx
|
3
|
+
from src.mira_sdk.models import (
|
4
|
+
Message,
|
5
|
+
ModelProvider,
|
6
|
+
AiRequest,
|
7
|
+
FlowChatCompletion,
|
8
|
+
FlowRequest,
|
9
|
+
ApiTokenRequest,
|
10
|
+
AddCreditRequest,
|
11
|
+
)
|
12
|
+
|
13
|
+
|
14
|
+
class MiraClient:
|
15
|
+
def __init__(self, base_url: str, api_token: Optional[str] = None):
|
16
|
+
"""Initialize Mira client.
|
17
|
+
|
18
|
+
Args:
|
19
|
+
base_url: Base URL of the Mira API
|
20
|
+
api_token: Optional API token for authentication
|
21
|
+
"""
|
22
|
+
self.base_url = base_url
|
23
|
+
self.api_token = api_token
|
24
|
+
self._client = httpx.AsyncClient()
|
25
|
+
|
26
|
+
async def __aenter__(self):
|
27
|
+
return self
|
28
|
+
|
29
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
30
|
+
await self._client.aclose()
|
31
|
+
|
32
|
+
def _get_headers(self) -> Dict[str, str]:
|
33
|
+
headers = {"Content-Type": "application/json"}
|
34
|
+
if self.api_token:
|
35
|
+
headers["Authorization"] = f"Bearer {self.api_token}"
|
36
|
+
return headers
|
37
|
+
|
38
|
+
async def list_models(self) -> List[str]:
|
39
|
+
"""List available models."""
|
40
|
+
response = await self._client.get(
|
41
|
+
f"{self.base_url}/v1/models",
|
42
|
+
headers=self._get_headers(),
|
43
|
+
)
|
44
|
+
response.raise_for_status()
|
45
|
+
return response.json()
|
46
|
+
|
47
|
+
async def generate(
|
48
|
+
self, request: AiRequest
|
49
|
+
) -> Union[str, AsyncGenerator[str, None]]:
|
50
|
+
"""Generate text using the specified model."""
|
51
|
+
response = await self._client.post(
|
52
|
+
f"{self.base_url}/v1/chat/completions",
|
53
|
+
headers=self._get_headers(),
|
54
|
+
json=request.model_dump(),
|
55
|
+
)
|
56
|
+
|
57
|
+
response.raise_for_status()
|
58
|
+
|
59
|
+
if request.stream:
|
60
|
+
|
61
|
+
async def stream_response():
|
62
|
+
async for chunk in response.aiter_text():
|
63
|
+
yield chunk
|
64
|
+
|
65
|
+
return stream_response()
|
66
|
+
else:
|
67
|
+
return response.json()
|
68
|
+
|
69
|
+
async def generate_with_flow(
|
70
|
+
self, flow_id: str, request: FlowChatCompletion
|
71
|
+
) -> Union[str, AsyncGenerator[str, None]]:
|
72
|
+
"""Generate text using a specific flow."""
|
73
|
+
response = await self._client.post(
|
74
|
+
f"{self.base_url}/v1/flows/{flow_id}/chat/completions",
|
75
|
+
headers=self._get_headers(),
|
76
|
+
json=request.model_dump(),
|
77
|
+
)
|
78
|
+
response.raise_for_status()
|
79
|
+
return response.json()
|
80
|
+
|
81
|
+
async def list_flows(self) -> List[Dict]:
|
82
|
+
"""List all flows."""
|
83
|
+
response = await self._client.get(
|
84
|
+
f"{self.base_url}/flows",
|
85
|
+
headers=self._get_headers(),
|
86
|
+
)
|
87
|
+
response.raise_for_status()
|
88
|
+
return response.json()
|
89
|
+
|
90
|
+
async def get_flow(self, flow_id: str) -> Dict:
|
91
|
+
"""Get details of a specific flow."""
|
92
|
+
response = await self._client.get(
|
93
|
+
f"{self.base_url}/flows/{flow_id}",
|
94
|
+
headers=self._get_headers(),
|
95
|
+
)
|
96
|
+
response.raise_for_status()
|
97
|
+
return response.json()
|
98
|
+
|
99
|
+
async def create_flow(self, request: FlowRequest) -> Dict:
|
100
|
+
"""Create a new flow."""
|
101
|
+
response = await self._client.post(
|
102
|
+
f"{self.base_url}/flows",
|
103
|
+
headers=self._get_headers(),
|
104
|
+
json=request.model_dump(),
|
105
|
+
)
|
106
|
+
response.raise_for_status()
|
107
|
+
return response.json()
|
108
|
+
|
109
|
+
async def update_flow(self, flow_id: str, request: FlowRequest) -> Dict:
|
110
|
+
"""Update an existing flow."""
|
111
|
+
response = await self._client.put(
|
112
|
+
f"{self.base_url}/flows/{flow_id}",
|
113
|
+
headers=self._get_headers(),
|
114
|
+
json=request.model_dump(),
|
115
|
+
)
|
116
|
+
response.raise_for_status()
|
117
|
+
return response.json()
|
118
|
+
|
119
|
+
async def delete_flow(self, flow_id: str) -> None:
|
120
|
+
"""Delete a flow."""
|
121
|
+
response = await self._client.delete(
|
122
|
+
f"{self.base_url}/flows/{flow_id}",
|
123
|
+
headers=self._get_headers(),
|
124
|
+
)
|
125
|
+
response.raise_for_status()
|
126
|
+
|
127
|
+
async def create_api_token(self, request: ApiTokenRequest) -> Dict:
|
128
|
+
"""Create a new API token."""
|
129
|
+
response = await self._client.post(
|
130
|
+
f"{self.base_url}/tokens",
|
131
|
+
headers=self._get_headers(),
|
132
|
+
json=request.model_dump(),
|
133
|
+
)
|
134
|
+
response.raise_for_status()
|
135
|
+
return response.json()
|
136
|
+
|
137
|
+
async def list_api_tokens(self) -> List[Dict]:
|
138
|
+
"""List all API tokens."""
|
139
|
+
response = await self._client.get(
|
140
|
+
f"{self.base_url}/tokens",
|
141
|
+
headers=self._get_headers(),
|
142
|
+
)
|
143
|
+
response.raise_for_status()
|
144
|
+
return response.json()
|
145
|
+
|
146
|
+
async def delete_api_token(self, token: str) -> None:
|
147
|
+
"""Delete an API token."""
|
148
|
+
response = await self._client.delete(
|
149
|
+
f"{self.base_url}/tokens/{token}",
|
150
|
+
headers=self._get_headers(),
|
151
|
+
)
|
152
|
+
response.raise_for_status()
|
153
|
+
|
154
|
+
async def get_user_credits(self) -> Dict:
|
155
|
+
"""Get user credits information."""
|
156
|
+
response = await self._client.get(
|
157
|
+
f"{self.base_url}/credits",
|
158
|
+
headers=self._get_headers(),
|
159
|
+
)
|
160
|
+
response.raise_for_status()
|
161
|
+
return response.json()
|
162
|
+
|
163
|
+
async def add_credit(self, request: AddCreditRequest) -> Dict:
|
164
|
+
"""Add credits to a user account."""
|
165
|
+
response = await self._client.post(
|
166
|
+
f"{self.base_url}/credits",
|
167
|
+
headers=self._get_headers(),
|
168
|
+
json=request.model_dump(),
|
169
|
+
)
|
170
|
+
response.raise_for_status()
|
171
|
+
return response.json()
|
172
|
+
|
173
|
+
async def get_credits_history(self) -> List[Dict]:
|
174
|
+
"""Get user credits history."""
|
175
|
+
response = await self._client.get(
|
176
|
+
f"{self.base_url}/credits/history",
|
177
|
+
headers=self._get_headers(),
|
178
|
+
)
|
179
|
+
response.raise_for_status()
|
180
|
+
return response.json()
|
@@ -0,0 +1,67 @@
|
|
1
|
+
from typing import Optional, List, Dict
|
2
|
+
from pydantic import BaseModel, Field, field_validator
|
3
|
+
|
4
|
+
|
5
|
+
class Message(BaseModel):
|
6
|
+
role: str
|
7
|
+
content: str
|
8
|
+
|
9
|
+
@field_validator("role")
|
10
|
+
@classmethod
|
11
|
+
def validate_role(cls, v: str) -> str:
|
12
|
+
valid_roles = ["system", "user", "assistant"]
|
13
|
+
if v not in valid_roles:
|
14
|
+
raise ValueError(f"Invalid role. Must be one of: {valid_roles}")
|
15
|
+
return v
|
16
|
+
|
17
|
+
|
18
|
+
class ModelProvider(BaseModel):
|
19
|
+
base_url: str
|
20
|
+
api_key: str
|
21
|
+
|
22
|
+
|
23
|
+
class AiRequest(BaseModel):
|
24
|
+
model: str = Field("mira/llama3.1", title="Model")
|
25
|
+
model_provider: Optional[ModelProvider] = Field(None, title="Model Provider (optional)")
|
26
|
+
messages: List[Message] = Field([], title="Messages")
|
27
|
+
stream: Optional[bool] = Field(False, title="Stream")
|
28
|
+
|
29
|
+
@field_validator("messages")
|
30
|
+
@classmethod
|
31
|
+
def validate_messages(cls, v: List[Message]) -> List[Message]:
|
32
|
+
if not v:
|
33
|
+
raise ValueError("Messages list cannot be empty")
|
34
|
+
return v
|
35
|
+
|
36
|
+
|
37
|
+
class FlowChatCompletion(BaseModel):
|
38
|
+
variables: Optional[Dict] = Field(None, title="Variables")
|
39
|
+
|
40
|
+
|
41
|
+
class FlowRequest(BaseModel):
|
42
|
+
system_prompt: str
|
43
|
+
name: str
|
44
|
+
|
45
|
+
|
46
|
+
class ApiTokenRequest(BaseModel):
|
47
|
+
description: Optional[str] = None
|
48
|
+
|
49
|
+
|
50
|
+
class AddCreditRequest(BaseModel):
|
51
|
+
user_id: str
|
52
|
+
amount: float
|
53
|
+
description: Optional[str] = None
|
54
|
+
|
55
|
+
@field_validator("amount")
|
56
|
+
@classmethod
|
57
|
+
def validate_amount(cls, v: float) -> float:
|
58
|
+
if v <= 0:
|
59
|
+
raise ValueError("Amount must be greater than 0")
|
60
|
+
return v
|
61
|
+
|
62
|
+
@field_validator("user_id")
|
63
|
+
@classmethod
|
64
|
+
def validate_user_id(cls, v: str) -> str:
|
65
|
+
if not v.strip():
|
66
|
+
raise ValueError("User ID cannot be empty")
|
67
|
+
return v
|
@@ -0,0 +1,109 @@
|
|
1
|
+
import pytest
|
2
|
+
import httpx
|
3
|
+
from src.mira_sdk.client import MiraClient
|
4
|
+
from src.mira_sdk.models import (
|
5
|
+
Message,
|
6
|
+
AiRequest,
|
7
|
+
FlowRequest,
|
8
|
+
ApiTokenRequest,
|
9
|
+
AddCreditRequest,
|
10
|
+
)
|
11
|
+
|
12
|
+
|
13
|
+
@pytest.fixture
|
14
|
+
def client():
|
15
|
+
return MiraClient(
|
16
|
+
base_url="https://mira-client-balancer.alts.dev",
|
17
|
+
api_token="sk-mira-8ac810228d32ff68fc93266fb9a0ba612724119ffab16dcc"
|
18
|
+
)
|
19
|
+
|
20
|
+
|
21
|
+
@pytest.mark.asyncio
|
22
|
+
async def test_list_models(client):
|
23
|
+
result = await client.list_models()
|
24
|
+
assert isinstance(result, list)
|
25
|
+
# assert len(result) > 0
|
26
|
+
|
27
|
+
|
28
|
+
@pytest.mark.asyncio
|
29
|
+
async def test_generate(client):
|
30
|
+
request = AiRequest(
|
31
|
+
model="mira/llama3.1",
|
32
|
+
messages=[Message(role="user", content="Hi Who are you!")],
|
33
|
+
stream=False,
|
34
|
+
model_provider=None
|
35
|
+
)
|
36
|
+
|
37
|
+
result = await client.generate(request)
|
38
|
+
assert isinstance(result, str)
|
39
|
+
assert len(result) > 0
|
40
|
+
|
41
|
+
|
42
|
+
@pytest.mark.asyncio
|
43
|
+
async def test_generate_stream(client):
|
44
|
+
request = AiRequest(
|
45
|
+
model="mira/llama3.1",
|
46
|
+
messages=[Message(role="user", content="Hi!")],
|
47
|
+
stream=True,
|
48
|
+
model_provider=None
|
49
|
+
)
|
50
|
+
|
51
|
+
stream = await client.generate(request)
|
52
|
+
chunks = []
|
53
|
+
async for chunk in stream:
|
54
|
+
chunks.append(chunk)
|
55
|
+
assert len(chunks) > 0
|
56
|
+
|
57
|
+
|
58
|
+
@pytest.mark.asyncio
|
59
|
+
async def test_list_flows(client):
|
60
|
+
result = await client.list_flows()
|
61
|
+
assert isinstance(result, list)
|
62
|
+
|
63
|
+
|
64
|
+
@pytest.mark.asyncio
|
65
|
+
async def test_create_and_delete_flow(client):
|
66
|
+
# Create flow
|
67
|
+
request = FlowRequest(
|
68
|
+
system_prompt="You are a helpful assistant",
|
69
|
+
name="test_flow"
|
70
|
+
)
|
71
|
+
|
72
|
+
flow = await client.create_flow(request)
|
73
|
+
assert flow.get("name") == "test_flow"
|
74
|
+
|
75
|
+
# Delete the created flow
|
76
|
+
flow_id = flow.get("id")
|
77
|
+
await client.delete_flow(flow_id)
|
78
|
+
|
79
|
+
|
80
|
+
@pytest.mark.asyncio
|
81
|
+
async def test_create_api_token(client):
|
82
|
+
request = ApiTokenRequest(description="Test token")
|
83
|
+
result = await client.create_api_token(request)
|
84
|
+
assert "token" in result
|
85
|
+
|
86
|
+
|
87
|
+
@pytest.mark.asyncio
|
88
|
+
async def test_get_user_credits(client):
|
89
|
+
result = await client.get_user_credits()
|
90
|
+
assert "amount" in result
|
91
|
+
|
92
|
+
|
93
|
+
@pytest.mark.asyncio
|
94
|
+
async def test_error_handling(client):
|
95
|
+
with pytest.raises(httpx.HTTPError):
|
96
|
+
# Test with invalid model name to trigger error
|
97
|
+
request = AiRequest(
|
98
|
+
model="invalid_model",
|
99
|
+
messages=[Message(role="user", content="Hi!")],
|
100
|
+
stream=False,
|
101
|
+
model_provider=None
|
102
|
+
)
|
103
|
+
await client.generate(request)
|
104
|
+
|
105
|
+
|
106
|
+
@pytest.mark.asyncio
|
107
|
+
async def test_client_context_manager():
|
108
|
+
async with MiraClient("https://mira-client-balancer.alts.dev") as client:
|
109
|
+
assert isinstance(client._client, httpx.AsyncClient)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import pytest
|
2
|
+
from src.mira_sdk.client import MiraClient
|
3
|
+
from src.mira_sdk.models import Message, AiRequest, ModelProvider
|
4
|
+
|
5
|
+
|
6
|
+
@pytest.mark.asyncio
|
7
|
+
async def test_real_generate():
|
8
|
+
"""This test makes a real API call to generate text."""
|
9
|
+
client = MiraClient(
|
10
|
+
base_url="https://mira-client-balancer.alts.dev",
|
11
|
+
api_token="sk-mira-8ac810228d32ff68fc93266fb9a0ba612724119ffab16dcc"
|
12
|
+
)
|
13
|
+
|
14
|
+
request = AiRequest(
|
15
|
+
model="mira/llama3.1",
|
16
|
+
messages=[Message(role="user", content="Hi Who are you!")],
|
17
|
+
stream=False,
|
18
|
+
model_provider=None
|
19
|
+
)
|
20
|
+
|
21
|
+
async with client:
|
22
|
+
result = await client.generate(request)
|
23
|
+
print("Real API Response:", result)
|
24
|
+
# assert len(result) > 0
|
25
|
+
|
26
|
+
|
27
|
+
# @pytest.mark.asyncio
|
28
|
+
# async def test_real_generate_stream():
|
29
|
+
# """This test makes a real API call with streaming enabled."""
|
30
|
+
# client = MiraClient(
|
31
|
+
# base_url="https://mira-client-balancer.alts.dev",
|
32
|
+
# api_token="sk-mira-8ac810228d32ff68fc93266fb9a0ba612724119ffab16dcc"
|
33
|
+
# )
|
34
|
+
|
35
|
+
# request = AiRequest(
|
36
|
+
# messages=[Message(role="user", content="Count from 1 to 5")],
|
37
|
+
# stream=True
|
38
|
+
# )
|
39
|
+
|
40
|
+
# async with client:
|
41
|
+
# stream = await client.generate(request)
|
42
|
+
# response = ""
|
43
|
+
# async for chunk in stream:
|
44
|
+
# print("Chunk:", chunk)
|
45
|
+
# response += chunk
|
46
|
+
# print("Final Response:", response)
|
47
|
+
# assert isinstance(response, str)
|
48
|
+
# assert len(response) > 0
|
@@ -0,0 +1,109 @@
|
|
1
|
+
import pytest
|
2
|
+
from src.mira_sdk.models import (
|
3
|
+
Message,
|
4
|
+
ModelProvider,
|
5
|
+
AiRequest,
|
6
|
+
FlowChatCompletion,
|
7
|
+
FlowRequest,
|
8
|
+
ApiTokenRequest,
|
9
|
+
AddCreditRequest,
|
10
|
+
)
|
11
|
+
|
12
|
+
|
13
|
+
def test_message_model():
|
14
|
+
message = Message(role="user", content="Hello!")
|
15
|
+
assert message.role == "user"
|
16
|
+
assert message.content == "Hello!"
|
17
|
+
|
18
|
+
|
19
|
+
def test_model_provider():
|
20
|
+
provider = ModelProvider(base_url="https://mira-client-balancer.alts.dev", api_key="sk-mira-8ac810228d32ff68fc93266fb9a0ba612724119ffab16dcc")
|
21
|
+
assert provider.base_url == "https://mira-client-balancer.alts.dev"
|
22
|
+
assert provider.api_key == "sk-mira-8ac810228d32ff68fc93266fb9a0ba612724119ffab16dcc"
|
23
|
+
|
24
|
+
|
25
|
+
def test_ai_request():
|
26
|
+
messages = [Message(role="user", content="Hello!")]
|
27
|
+
provider = ModelProvider(base_url="https://mira-client-balancer.alts.dev", api_key="sk-mira-8ac810228d32ff68fc93266fb9a0ba612724119ffab16dcc")
|
28
|
+
|
29
|
+
# Test with default values
|
30
|
+
request = AiRequest(messages=messages)
|
31
|
+
assert request.model == "mira/llama3.1"
|
32
|
+
assert request.stream is False
|
33
|
+
assert request.model_provider is None
|
34
|
+
assert request.messages == messages
|
35
|
+
|
36
|
+
# Test with custom values
|
37
|
+
request = AiRequest(
|
38
|
+
model="custom/model",
|
39
|
+
messages=messages,
|
40
|
+
model_provider=provider,
|
41
|
+
stream=True
|
42
|
+
)
|
43
|
+
assert request.model == "custom/model"
|
44
|
+
assert request.stream is True
|
45
|
+
assert request.model_provider == provider
|
46
|
+
assert request.messages == messages
|
47
|
+
|
48
|
+
|
49
|
+
def test_flow_chat_completion():
|
50
|
+
# Test with no variables
|
51
|
+
completion = FlowChatCompletion()
|
52
|
+
assert completion.variables is None
|
53
|
+
|
54
|
+
# Test with variables
|
55
|
+
variables = {"key": "value"}
|
56
|
+
completion = FlowChatCompletion(variables=variables)
|
57
|
+
assert completion.variables == variables
|
58
|
+
|
59
|
+
|
60
|
+
def test_flow_request():
|
61
|
+
request = FlowRequest(
|
62
|
+
system_prompt="You are a helpful assistant",
|
63
|
+
name="test-flow"
|
64
|
+
)
|
65
|
+
assert request.system_prompt == "You are a helpful assistant"
|
66
|
+
assert request.name == "test-flow"
|
67
|
+
|
68
|
+
|
69
|
+
def test_api_token_request():
|
70
|
+
# Test with no description
|
71
|
+
request = ApiTokenRequest()
|
72
|
+
assert request.description is None
|
73
|
+
|
74
|
+
# Test with description
|
75
|
+
request = ApiTokenRequest(description="Test token")
|
76
|
+
assert request.description == "Test token"
|
77
|
+
|
78
|
+
|
79
|
+
def test_add_credit_request():
|
80
|
+
# Test required fields
|
81
|
+
request = AddCreditRequest(user_id="user123", amount=100.0)
|
82
|
+
assert request.user_id == "user123"
|
83
|
+
assert request.amount == 100.0
|
84
|
+
assert request.description is None
|
85
|
+
|
86
|
+
# Test with description
|
87
|
+
request = AddCreditRequest(
|
88
|
+
user_id="user123",
|
89
|
+
amount=100.0,
|
90
|
+
description="Test credit"
|
91
|
+
)
|
92
|
+
assert request.user_id == "user123"
|
93
|
+
assert request.amount == 100.0
|
94
|
+
assert request.description == "Test credit"
|
95
|
+
|
96
|
+
|
97
|
+
def test_invalid_message():
|
98
|
+
with pytest.raises(ValueError):
|
99
|
+
Message(role="invalid", content="") # Invalid role
|
100
|
+
|
101
|
+
|
102
|
+
def test_invalid_ai_request():
|
103
|
+
with pytest.raises(ValueError):
|
104
|
+
AiRequest(messages=[]) # Empty messages list
|
105
|
+
|
106
|
+
|
107
|
+
def test_invalid_add_credit_request():
|
108
|
+
with pytest.raises(ValueError):
|
109
|
+
AddCreditRequest(user_id="", amount=-100) # Negative amount
|
mira_network-0.1.0/PKG-INFO
DELETED
mira_network-0.1.0/README.md
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
# mira-network
|
@@ -1,19 +0,0 @@
|
|
1
|
-
[project]
|
2
|
-
name = "mira-network"
|
3
|
-
version = "0.1.0"
|
4
|
-
description = "Default template for PDM package"
|
5
|
-
authors = [
|
6
|
-
{name = "Hamid Raza", email = "contact@hamidraza.com"},
|
7
|
-
]
|
8
|
-
dependencies = []
|
9
|
-
requires-python = ">=3.11"
|
10
|
-
readme = "README.md"
|
11
|
-
license = {text = "MIT"}
|
12
|
-
|
13
|
-
[build-system]
|
14
|
-
requires = ["setuptools>=61"]
|
15
|
-
build-backend = "setuptools.build_meta"
|
16
|
-
|
17
|
-
|
18
|
-
[tool.pdm]
|
19
|
-
distribution = true
|
mira_network-0.1.0/setup.cfg
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
README.md
|
2
|
-
pyproject.toml
|
3
|
-
src/mira_network/__init__.py
|
4
|
-
src/mira_network/client.py
|
5
|
-
src/mira_network.egg-info/PKG-INFO
|
6
|
-
src/mira_network.egg-info/SOURCES.txt
|
7
|
-
src/mira_network.egg-info/dependency_links.txt
|
8
|
-
src/mira_network.egg-info/top_level.txt
|
9
|
-
tests/test_client.py
|
@@ -1 +0,0 @@
|
|
1
|
-
|
@@ -1 +0,0 @@
|
|
1
|
-
mira_network
|
@@ -1,26 +0,0 @@
|
|
1
|
-
import unittest
|
2
|
-
from mira_network.client import MiraNetwork
|
3
|
-
|
4
|
-
|
5
|
-
class TestMiraNetwork(unittest.TestCase):
|
6
|
-
def test_init(self):
|
7
|
-
api_key = "test_api_key"
|
8
|
-
client = MiraNetwork(api_key)
|
9
|
-
self.assertEqual(client.api_key, api_key)
|
10
|
-
|
11
|
-
def test_generate_with_valid_api_key(self):
|
12
|
-
api_key = "test_api_key"
|
13
|
-
client = MiraNetwork(api_key)
|
14
|
-
result = client.generate()
|
15
|
-
self.assertIsInstance(result, dict)
|
16
|
-
|
17
|
-
def test_generate_with_invalid_api_key(self):
|
18
|
-
client = MiraNetwork("")
|
19
|
-
with self.assertRaises(ValueError):
|
20
|
-
client.generate()
|
21
|
-
|
22
|
-
|
23
|
-
if __name__ == "__main__":
|
24
|
-
unittest.main()
|
25
|
-
|
26
|
-
# pypi-AgEIcHlwaS5vcmcCJGUzODI5NjhjLWQ4MTQtNDFhZi1iYjhlLTlmYWYyNDcyZjQ3ZgACKlszLCJjMzJhNWQ1NS1kYjYyLTRiYzEtOWZlMS0xNzEzNGIyZjVjNmQiXQAABiBQXeHWfLbWZOZA8Yw9XyZmDdyy_OonAp3XUeqCJTwBwA
|
File without changes
|