airia 0.1.2__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.
airia/__init__.py ADDED
@@ -0,0 +1,6 @@
1
+ from .logs import configure_logging
2
+ from .client import AiriaClient, AiriaAsyncClient
3
+ from .exceptions import AiriaAPIError
4
+
5
+ __version__ = "0.1.0"
6
+ __all__ = ["AiriaClient", "AiriaAsyncClient", "AiriaAPIError", "configure_logging"]
airia/exceptions.py ADDED
@@ -0,0 +1,33 @@
1
+ class AiriaAPIError(Exception):
2
+ '''
3
+ Custom exception for Airia API errors.
4
+
5
+ This exception is raised when an API request to the Airia service fails.
6
+ It contains both the HTTP status code and error message to help with
7
+ debugging and proper error handling.
8
+
9
+ Attributes:
10
+ status_code (int): The HTTP status code returned by the API
11
+ message (str): The error message describing what went wrong
12
+ '''
13
+
14
+ def __init__(self, status_code: int, message: str):
15
+ """
16
+ Initialize the exception with a status code and error message.
17
+
18
+ Args:
19
+ status_code (int): The HTTP status code of the failed request
20
+ message (str): A descriptive error message
21
+ """
22
+ super().__init__(f"{status_code}: {message}")
23
+ self.status_code = status_code
24
+ self.message = message
25
+
26
+ def __str__(self) -> str:
27
+ """
28
+ Return a string representation of the exception.
29
+
30
+ Returns:
31
+ str: A formatted string containing the status code and message
32
+ """
33
+ return f"{self.status_code}: {self.message}"
airia/logs.py ADDED
@@ -0,0 +1,159 @@
1
+ import os
2
+ import sys
3
+ import uuid
4
+ from contextvars import ContextVar
5
+ from typing import BinaryIO, Optional, TextIO, Union, overload
6
+
7
+ import loguru
8
+ from loguru import logger
9
+
10
+ # Create a context variable to store correlation ID
11
+ correlation_id_context: ContextVar[str] = ContextVar('correlation_id', default='')
12
+
13
+
14
+ def get_correlation_id() -> str:
15
+ """
16
+ Get the current correlation ID from context or return empty string if not set.
17
+
18
+ Returns:
19
+ str: The current correlation ID
20
+ """
21
+ return correlation_id_context.get()
22
+
23
+
24
+ def set_correlation_id(correlation_id: Optional[str] = None) -> str:
25
+ """
26
+ Set a correlation ID in the current context.
27
+
28
+ Args:
29
+ correlation_id (Optional[str]): The correlation ID to set. If None, a new UUID will be generated.
30
+
31
+ Returns:
32
+ str: The correlation ID that was set
33
+ """
34
+ if correlation_id is None:
35
+ correlation_id = str(uuid.uuid4())
36
+ correlation_id_context.set(correlation_id)
37
+ return correlation_id
38
+
39
+
40
+ def clear_correlation_id() -> None:
41
+ """Clear the correlation ID from the current context."""
42
+ correlation_id_context.set('')
43
+
44
+
45
+ # Define a function to be used as a filter to inject correlation_id
46
+ def correlation_id_filter(record):
47
+ record["extra"]["correlation_id"] = get_correlation_id() or "no-correlation-id"
48
+ return record
49
+
50
+
51
+ @overload
52
+ def configure_logging(
53
+ format_string: str = "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
54
+ level: str = "INFO",
55
+ sink: Union[TextIO, BinaryIO] = ...,
56
+ rotation: None = None,
57
+ retention: None = None,
58
+ include_correlation_id: bool = True,
59
+ ) -> "loguru.Logger": ...
60
+
61
+
62
+ @overload
63
+ def configure_logging(
64
+ format_string: str = "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
65
+ level: str = "INFO",
66
+ sink: Union[str, os.PathLike[str]] = ...,
67
+ rotation: Optional[str] = None,
68
+ retention: Optional[str] = None,
69
+ include_correlation_id: bool = True,
70
+ ) -> "loguru.Logger": ...
71
+
72
+
73
+ def configure_logging(
74
+ format_string: str = "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
75
+ level: str = "INFO",
76
+ sink: Union[os.PathLike[str], TextIO, BinaryIO] = sys.stderr,
77
+ rotation: Optional[str] = None,
78
+ retention: Optional[str] = None,
79
+ include_correlation_id: bool = True,
80
+ ) -> "loguru.Logger":
81
+ """
82
+ Configure the loguru logger with custom settings.
83
+ Check [Loguru Documentation](https://loguru.readthedocs.io/en/stable/api/logger.html) for more details.
84
+
85
+ Args:
86
+ format_string (str): The format string for log messages.
87
+ level (str): The minimum logging level. Default: "INFO"
88
+ sink: Where to send the log. Default: sys.stderr
89
+ rotation (str, optional): When to rotate the log file.
90
+ Example: "10 MB", "1 day"
91
+ Only used when sink is a file path.
92
+ retention (str, optional): How long to keep log files.
93
+ Example: "1 week", "10 days"
94
+ Only used when sink is a file path.
95
+ include_correlation_id (bool): Whether to include correlation ID in log messages.
96
+ Default: True
97
+
98
+ Returns:
99
+ The configured logger object
100
+ """
101
+ # Remove any existing handlers
102
+ logger.remove()
103
+
104
+ # Modify format string to include correlation ID if requested
105
+ if include_correlation_id:
106
+ format_string = "<magenta>[{extra[correlation_id]}]</magenta> " + format_string
107
+
108
+ # Add rotation and retention only for file paths
109
+ kwargs = {
110
+ "format": format_string,
111
+ "level": level,
112
+ "filter": correlation_id_filter, # Add the filter for each handler
113
+ }
114
+
115
+ if isinstance(sink, (str, os.PathLike)):
116
+ if rotation is not None:
117
+ kwargs["rotation"] = rotation
118
+ if retention is not None:
119
+ kwargs["retention"] = retention
120
+
121
+ # Add the new handler
122
+ logger.add(sink, **kwargs)
123
+
124
+ return logger
125
+
126
+
127
+ # Example usage:
128
+ if __name__ == "__main__":
129
+ # Basic configuration (uses sys.stderr)
130
+ log = configure_logging()
131
+ log.info("Basic logging configured successfully")
132
+
133
+ # Set a correlation ID
134
+ set_correlation_id("request-123")
135
+ log.info("This log has a correlation ID")
136
+
137
+ # Change correlation ID
138
+ set_correlation_id("request-456")
139
+ log.info("This log has a different correlation ID")
140
+
141
+ # Use auto-generated correlation ID
142
+ set_correlation_id()
143
+ log.info("This log has an auto-generated correlation ID")
144
+
145
+ # File-based logging with rotation and retention
146
+ file_log = configure_logging(
147
+ format_string="[{time:YYYY-MM-DD HH:mm:ss}] [{level}] {message}",
148
+ level="DEBUG",
149
+ sink="app.log",
150
+ rotation="10 MB",
151
+ retention="1 week",
152
+ )
153
+ file_log.debug("File logging configured successfully")
154
+
155
+ # Stream-based logging
156
+ stream_log = configure_logging(
157
+ format_string="[{time:HH:mm:ss}] {message}", level="INFO", sink=sys.stdout
158
+ )
159
+ stream_log.info("Stream logging configured successfully")
@@ -0,0 +1,422 @@
1
+ Metadata-Version: 2.4
2
+ Name: airia
3
+ Version: 0.1.2
4
+ Summary: Python SDK for Airia API
5
+ Author-email: Airia LLC <support@airia.com>
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.9
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: requests>=2.32.3
19
+ Requires-Dist: aiohttp>=3.11.14
20
+ Requires-Dist: loguru>=0.7.3
21
+ Requires-Dist: pydantic>=2.11.0
22
+ Provides-Extra: anthropic
23
+ Requires-Dist: anthropic>=0.49.0; extra == "anthropic"
24
+ Provides-Extra: openai
25
+ Requires-Dist: openai>=1.74.0; extra == "openai"
26
+ Provides-Extra: all
27
+ Requires-Dist: anthropic>=0.49.0; extra == "all"
28
+ Requires-Dist: openai>=1.74.0; extra == "all"
29
+ Dynamic: license-file
30
+
31
+ # Airia Python API Library
32
+
33
+ Airia Python API Library that provides a clean and intuitive interface to interact with the Airia AI platform API. The library offers both synchronous and asynchronous clients for maximum flexibility in your applications.
34
+
35
+ ## Features
36
+
37
+ - **Dual Client Support**: Choose between synchronous (`AiriaClient`) and asynchronous (`AiriaAsyncClient`) implementations
38
+ - **Pipeline Execution**: Easily run AI pipelines with customizable parameters
39
+ - **Gateway Support**: Seamlessly integrate with OpenAI and Anthropic services through Airia gateways
40
+ - **Error Handling**: Comprehensive error handling with custom exceptions
41
+ - **Logging**: Built-in configurable logging with correlation ID support for request tracing
42
+ - **API Key Management**: Flexible API key configuration via parameters or environment variables
43
+
44
+ ## Installation
45
+
46
+ Clone the repository:
47
+
48
+ ```bash
49
+ git clone https://github.com/AiriaLLC/airia-python.git
50
+ cd airia-python
51
+ ```
52
+
53
+ You can install the package using pip or uv:
54
+
55
+ <table>
56
+ <tr>
57
+ <th>pip</th>
58
+ <th>uv</th>
59
+ </tr>
60
+ <tr>
61
+ <td>
62
+
63
+ ```bash
64
+ pip install -e .
65
+ ```
66
+
67
+ </td>
68
+ <td>
69
+
70
+ ```bash
71
+ uv sync --frozen
72
+ ```
73
+
74
+ </td>
75
+ </tr>
76
+ </table>
77
+
78
+ ### Install with optional dependencies
79
+
80
+ The package supports optional dependencies for gateway functionality:
81
+
82
+ <table>
83
+ <tr>
84
+ <th>OpenAI Gateway</th>
85
+ <th>Anthropic Gateway</th>
86
+ <th>All Gateways</th>
87
+ </tr>
88
+ <tr>
89
+ <td>
90
+
91
+ ```bash
92
+ pip install -e .[openai]
93
+ ```
94
+
95
+ </td>
96
+ <td>
97
+
98
+ ```bash
99
+ pip install -e .[anthropic]
100
+ ```
101
+
102
+ </td>
103
+ <td>
104
+
105
+ ```bash
106
+ pip install -e .[all]
107
+ ```
108
+
109
+ </td>
110
+ </tr>
111
+ </table>
112
+
113
+ ### Install with development dependencies
114
+
115
+ <table>
116
+ <tr>
117
+ <th>pip</th>
118
+ <th>uv</th>
119
+ </tr>
120
+ <tr>
121
+ <td>
122
+
123
+ ```bash
124
+ pip install dependency-groups
125
+ dev=$(python -m dependency_groups dev)
126
+ pip install -e .
127
+ pip install $dev
128
+ ```
129
+
130
+ </td>
131
+ <td>
132
+
133
+ ```bash
134
+ uv sync --frozen --group dev
135
+ ```
136
+
137
+ </td>
138
+ </tr>
139
+ </table>
140
+
141
+ ## Building from Source
142
+
143
+ To build the package from source:
144
+
145
+ <table>
146
+ <tr>
147
+ <th>pip</th>
148
+ <th>uv</th>
149
+ </tr>
150
+ <tr>
151
+ <td>
152
+
153
+ ```bash
154
+ pip install build
155
+ python -m build
156
+ ```
157
+
158
+ </td>
159
+ <td>
160
+
161
+ ```bash
162
+ uv build
163
+ ```
164
+
165
+ </td>
166
+ </tr>
167
+ </table>
168
+
169
+ This will create both wheel and source distribution in the `dist/` directory.
170
+
171
+ ## Quick Start
172
+
173
+ ### Synchronous Usage
174
+
175
+ ```python
176
+ from airia import AiriaClient
177
+
178
+ # Initialize client (API key can be passed directly or via AIRIA_API_KEY environment variable)
179
+ client = AiriaClient(api_key="your_api_key")
180
+
181
+ # Execute a pipeline
182
+ response = client.execute_pipeline(
183
+ pipeline_id="your_pipeline_id",
184
+ user_input="Tell me about quantum computing"
185
+ )
186
+
187
+ print(response.result)
188
+ ```
189
+
190
+ #### Synchronous Streaming
191
+
192
+ ```python
193
+ from airia import AiriaClient
194
+
195
+ # Initialize client (API key can be passed directly or via AIRIA_API_KEY environment variable)
196
+ client = AiriaClient(api_key="your_api_key")
197
+
198
+ # Execute a pipeline
199
+ response = client.execute_pipeline(
200
+ pipeline_id="your_pipeline_id",
201
+ user_input="Tell me about quantum computing",
202
+ async_output=True
203
+ )
204
+
205
+ for c in resp.stream:
206
+ print(c, end="")
207
+ ```
208
+
209
+ ### Asynchronous Usage
210
+
211
+ ```python
212
+ import asyncio
213
+ from airia import AiriaAsyncClient
214
+
215
+ async def main():
216
+ # Use async context manager for proper session handling
217
+ async with AiriaAsyncClient(api_key="your_api_key") as client:
218
+ response = await client.execute_pipeline(
219
+ pipeline_id="your_pipeline_id",
220
+ user_input="Tell me about quantum computing"
221
+ )
222
+ print(response.result)
223
+
224
+ asyncio.run(main())
225
+ ```
226
+
227
+ #### Asynchronous Streaming
228
+
229
+ ```python
230
+ import asyncio
231
+ from airia import AiriaAsyncClient
232
+
233
+ async def main():
234
+ # Use async context manager for proper session handling
235
+ async with AiriaAsyncClient(api_key="your_api_key") as client:
236
+ response = await client.execute_pipeline(
237
+ pipeline_id="your_pipeline_id",
238
+ user_input="Tell me about quantum computing",
239
+ async_output=True
240
+ )
241
+ async for c in resp.stream:
242
+ print(c, end="")
243
+
244
+ asyncio.run(main())
245
+ ```
246
+
247
+ ## Gateway Usage
248
+
249
+ Airia provides gateway capabilities for popular AI services like OpenAI and Anthropic, allowing you to use your Airia API key with these services.
250
+
251
+ ### OpenAI Gateway
252
+
253
+ ```python
254
+ from airia import AiriaClient
255
+
256
+ # Initialize client with OpenAI gateway support
257
+ client = AiriaClient.with_openai_gateway(api_key="your_airia_api_key")
258
+
259
+ # Use OpenAI's API through Airia's gateway
260
+ response = client.openai.chat.completions.create(
261
+ model="gpt-4.1-nano",
262
+ messages=[
263
+ {"role": "system", "content": "You are a helpful assistant."},
264
+ {"role": "user", "content": "Hello!"},
265
+ ]
266
+ )
267
+
268
+ print(response.choices[0].message.content)
269
+ ```
270
+
271
+ ### Anthropic Gateway
272
+
273
+ ```python
274
+ from airia import AiriaClient
275
+
276
+ # Initialize client with Anthropic gateway support
277
+ client = AiriaClient.with_anthropic_gateway(api_key="your_airia_api_key")
278
+
279
+ # Use Anthropic's API through Airia's gateway
280
+ response = client.anthropic.messages.create(
281
+ model="claude-3-5-haiku-20241022",
282
+ max_tokens=1000,
283
+ messages=[{"role": "user", "content": "Hello!"}]
284
+ )
285
+
286
+ print(response.content[0].text)
287
+ ```
288
+
289
+ ### Asynchronous Gateway Usage
290
+
291
+ Both gateways also support asynchronous usage:
292
+
293
+ ```python
294
+ import asyncio
295
+ from airia import AiriaAsyncClient
296
+
297
+ async def main():
298
+ # Initialize async client with gateway support
299
+ client = AiriaAsyncClient.with_openai_gateway(api_key="your_airia_api_key")
300
+
301
+ # Use OpenAI's API asynchronously through Airia's gateway
302
+ response = await client.openai.chat.completions.create(
303
+ model="gpt-4.1-nano",
304
+ messages=[
305
+ {"role": "system", "content": "You are a helpful assistant."},
306
+ {"role": "user", "content": "Hello!"},
307
+ ]
308
+ )
309
+
310
+ print(response.choices[0].message.content)
311
+
312
+ asyncio.run(main())
313
+ ```
314
+
315
+ ## Advanced Usage
316
+
317
+ ### Pipeline Execution with All Options
318
+
319
+ ```python
320
+ response = client.execute_pipeline(
321
+ pipeline_id="pipeline_id",
322
+ user_input="Your input text",
323
+ debug=True, # Enable debug mode
324
+ user_id="user_guid", # User identifier
325
+ conversation_id="conversation_guid", # Conversation identifier
326
+ async_output=False, # Stream response (async mode)
327
+ include_tools_response=True, # Return the initial LLM tool result
328
+ images=["base64_encoded_image"], # Include image data
329
+ files=["base64_encoded_file"], # Include file data
330
+ data_source_folders={}, # Data source folders configuration
331
+ data_source_files={}, # Data source files configuration
332
+ in_memory_messages=[ # Context messages for conversation
333
+ {"role": "user", "message": "Previous message"}
334
+ ],
335
+ current_date_time="2025-03-26T21:00:00", # Override current date/time
336
+ save_history=True, # Save to conversation history
337
+ additional_info=["extra data"], # Additional metadata
338
+ prompt_variables={"var1": "value1"}, # Variables for prompt templating
339
+ correlation_id="request-123", # Request tracing ID
340
+ api_version="v2" # API version for the request
341
+ )
342
+ ```
343
+
344
+ ### Configuring Logging
345
+
346
+ ```python
347
+ import sys
348
+ from airia import configure_logging
349
+
350
+ # Basic configuration
351
+ logger = configure_logging()
352
+
353
+ # Advanced configuration
354
+ file_logger = configure_logging(
355
+ format_string="[{time:YYYY-MM-DD HH:mm:ss}] [{level}] {message}",
356
+ level="DEBUG",
357
+ sink="app.log",
358
+ rotation="10 MB",
359
+ retention="1 week",
360
+ include_correlation_id=True
361
+ )
362
+
363
+ # Console output with custom format
364
+ console_logger = configure_logging(
365
+ format_string="[{time:HH:mm:ss}] {message}",
366
+ level="INFO",
367
+ sink=sys.stdout
368
+ )
369
+ ```
370
+
371
+ ## Error Handling
372
+
373
+ The SDK uses custom exceptions to provide clear error messages:
374
+
375
+ ```python
376
+ from airia import AiriaAPIError
377
+
378
+ try:
379
+ response = client.execute_pipeline(
380
+ pipeline_id="invalid_id",
381
+ user_input="test"
382
+ )
383
+ except AiriaAPIError as e:
384
+ print(f"API error: {e.status_code} - {e.message}")
385
+ ```
386
+
387
+ ## Requirements
388
+
389
+ - Python 3.9 or higher
390
+ - Core dependencies:
391
+ - requests
392
+ - aiohttp
393
+ - loguru
394
+ - pydantic
395
+
396
+ - Optional dependencies:
397
+ - OpenAI gateway: `openai>=1.74.0`
398
+ - Anthropic gateway: `anthropic>=0.49.0`
399
+
400
+ ## Development
401
+
402
+ To run tests (make sure you have development dependencies installed):
403
+
404
+ ```bash
405
+ pytest
406
+ ```
407
+
408
+ For testing gateway functionality, install the optional dependencies:
409
+
410
+ ```bash
411
+ # For OpenAI gateway tests
412
+ pip install -e .[openai]
413
+ pytest tests/test_openai_gateway.py
414
+
415
+ # For Anthropic gateway tests
416
+ pip install -e .[anthropic]
417
+ pytest tests/test_anthropic_gateway.py
418
+
419
+ # For all tests
420
+ pip install -e .[all]
421
+ pytest
422
+ ```
@@ -0,0 +1,8 @@
1
+ airia/__init__.py,sha256=T39gO8E5T5zxlw-JP78ruxOu7-LeKOJCJzz6t40kdQo,231
2
+ airia/exceptions.py,sha256=4Z55n-cRJrtTa5-pZBIK2oZD4-Z99aUtKx_kfTFYY5o,1146
3
+ airia/logs.py,sha256=17YZ4IuzOF0m5bgofj9-QYlJ2BYR2kRZbBVQfFSLFEk,5441
4
+ airia-0.1.2.dist-info/licenses/LICENSE,sha256=R3ClUMMKPRItIcZ0svzyj2taZZnFYw568YDNzN9KQ1Q,1066
5
+ airia-0.1.2.dist-info/METADATA,sha256=P6kEfX-udLEj3GNG1qvZcq4SEPOS_rFB_DNuuX2X3QQ,9578
6
+ airia-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
+ airia-0.1.2.dist-info/top_level.txt,sha256=qUQEKfs_hdOYTwjKj1JZbRhS5YeXDNaKQaVTrzabS6w,6
8
+ airia-0.1.2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Airia LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ airia