lunar-sdk 0.1.0__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.
Files changed (60) hide show
  1. lunar_sdk-0.1.0/.gitignore +113 -0
  2. lunar_sdk-0.1.0/LICENSE +21 -0
  3. lunar_sdk-0.1.0/Makefile +29 -0
  4. lunar_sdk-0.1.0/PKG-INFO +275 -0
  5. lunar_sdk-0.1.0/README.md +230 -0
  6. lunar_sdk-0.1.0/docs/EVALUATIONS_DESIGN.md +671 -0
  7. lunar_sdk-0.1.0/examples/evaluations_tutorial.ipynb +1717 -0
  8. lunar_sdk-0.1.0/examples/rag_tutorial.ipynb +1232 -0
  9. lunar_sdk-0.1.0/examples/requirements.txt +5 -0
  10. lunar_sdk-0.1.0/examples/router_tutorial.ipynb +1143 -0
  11. lunar_sdk-0.1.0/examples/test_environments.py +77 -0
  12. lunar_sdk-0.1.0/lunar/__init__.py +169 -0
  13. lunar_sdk-0.1.0/lunar/_config.py +128 -0
  14. lunar_sdk-0.1.0/lunar/_exceptions.py +302 -0
  15. lunar_sdk-0.1.0/lunar/_http.py +449 -0
  16. lunar_sdk-0.1.0/lunar/client.py +521 -0
  17. lunar_sdk-0.1.0/lunar/evals/__init__.py +165 -0
  18. lunar_sdk-0.1.0/lunar/evals/_base.py +366 -0
  19. lunar_sdk-0.1.0/lunar/evals/_display.py +374 -0
  20. lunar_sdk-0.1.0/lunar/evals/_runner.py +579 -0
  21. lunar_sdk-0.1.0/lunar/evals/scorers/__init__.py +42 -0
  22. lunar_sdk-0.1.0/lunar/evals/scorers/default.py +405 -0
  23. lunar_sdk-0.1.0/lunar/evals/scorers/llm_judge.py +428 -0
  24. lunar_sdk-0.1.0/lunar/evals/types.py +473 -0
  25. lunar_sdk-0.1.0/lunar/integrations/__init__.py +13 -0
  26. lunar_sdk-0.1.0/lunar/integrations/langchain.py +289 -0
  27. lunar_sdk-0.1.0/lunar/integrations/llamaindex.py +253 -0
  28. lunar_sdk-0.1.0/lunar/py.typed +0 -0
  29. lunar_sdk-0.1.0/lunar/resources/__init__.py +57 -0
  30. lunar_sdk-0.1.0/lunar/resources/annotations.py +269 -0
  31. lunar_sdk-0.1.0/lunar/resources/auto_eval.py +176 -0
  32. lunar_sdk-0.1.0/lunar/resources/chat.py +390 -0
  33. lunar_sdk-0.1.0/lunar/resources/completions.py +255 -0
  34. lunar_sdk-0.1.0/lunar/resources/datasets.py +708 -0
  35. lunar_sdk-0.1.0/lunar/resources/eval_agent.py +79 -0
  36. lunar_sdk-0.1.0/lunar/resources/eval_models.py +38 -0
  37. lunar_sdk-0.1.0/lunar/resources/eval_settings.py +51 -0
  38. lunar_sdk-0.1.0/lunar/resources/evaluations.py +636 -0
  39. lunar_sdk-0.1.0/lunar/resources/experiments.py +154 -0
  40. lunar_sdk-0.1.0/lunar/resources/metrics.py +147 -0
  41. lunar_sdk-0.1.0/lunar/resources/models.py +137 -0
  42. lunar_sdk-0.1.0/lunar/resources/proposals.py +112 -0
  43. lunar_sdk-0.1.0/lunar/resources/rag.py +780 -0
  44. lunar_sdk-0.1.0/lunar/resources/trace_issues.py +116 -0
  45. lunar_sdk-0.1.0/lunar/resources/traces.py +102 -0
  46. lunar_sdk-0.1.0/lunar/types/__init__.py +69 -0
  47. lunar_sdk-0.1.0/lunar/types/chat.py +68 -0
  48. lunar_sdk-0.1.0/lunar/types/completion.py +28 -0
  49. lunar_sdk-0.1.0/lunar/types/models.py +58 -0
  50. lunar_sdk-0.1.0/lunar/types/rag.py +162 -0
  51. lunar_sdk-0.1.0/pyproject.toml +84 -0
  52. lunar_sdk-0.1.0/tests/__init__.py +1 -0
  53. lunar_sdk-0.1.0/tests/test_chat.py +216 -0
  54. lunar_sdk-0.1.0/tests/test_client.py +100 -0
  55. lunar_sdk-0.1.0/tests/test_evals_resources.py +1018 -0
  56. lunar_sdk-0.1.0/tests/test_evals_routing.py +81 -0
  57. lunar_sdk-0.1.0/tests/test_evals_types.py +196 -0
  58. lunar_sdk-0.1.0/tests/test_full_pipeline.py +410 -0
  59. lunar_sdk-0.1.0/tests/test_langchain.py +424 -0
  60. lunar_sdk-0.1.0/tests/test_llamaindex.py +394 -0
@@ -0,0 +1,113 @@
1
+ ### Terraform ###
2
+ **/.terraform/*
3
+
4
+ *.tfstate
5
+ *.tfstate.*
6
+
7
+ *.tfvars
8
+ *.tfvars.json
9
+ !*.tfvars.example
10
+ !terraform/environments/*/terraform.tfvars
11
+ *.pem
12
+
13
+
14
+ override.tf
15
+ override.tf.json
16
+ *_override.tf
17
+ *_override.tf.json
18
+
19
+ .terraformrc
20
+ terraform.rc
21
+
22
+ ### Python ###
23
+ # Byte-compiled / optimized / DLL files
24
+ __pycache__/
25
+ *.py[cod]
26
+ *$py.class
27
+
28
+ # C extensions
29
+ *.so
30
+
31
+ # Distribution / packaging
32
+ .Python
33
+ build/
34
+ develop-eggs/
35
+ dist/
36
+ downloads/
37
+ eggs/
38
+ .eggs/
39
+ lib/
40
+ lib64/
41
+ parts/
42
+ sdist/
43
+ var/
44
+ wheels/
45
+ *.egg-info/
46
+ .installed.cfg
47
+ *.egg
48
+
49
+ # Virtual environments
50
+ venv/
51
+ ENV/
52
+ env/
53
+ .venv
54
+
55
+ # PyCharm
56
+ .idea/
57
+
58
+ # VS Code
59
+ .vscode/
60
+
61
+ # Jupyter Notebook
62
+ .ipynb_checkpoints
63
+
64
+ # pyenv
65
+ .python-version
66
+
67
+ .env
68
+
69
+ # ===== Finetune API local site-packages =====
70
+ services/finetune-api/bin/
71
+ services/finetune-api/*.dist-info/
72
+ services/finetune-api/annotated_doc/
73
+ services/finetune-api/annotated_types/
74
+ services/finetune-api/anyio/
75
+ services/finetune-api/boto3/
76
+ services/finetune-api/botocore/
77
+ services/finetune-api/click/
78
+ services/finetune-api/dateutil/
79
+ services/finetune-api/fastapi/
80
+ services/finetune-api/h11/
81
+ services/finetune-api/idna/
82
+ services/finetune-api/jmespath/
83
+ services/finetune-api/mangum/
84
+ services/finetune-api/pydantic/
85
+ services/finetune-api/pydantic_core/
86
+ services/finetune-api/s3transfer/
87
+ services/finetune-api/six.py
88
+ services/finetune-api/starlette/
89
+ services/finetune-api/typing_extensions.py
90
+ services/finetune-api/typing_inspection/
91
+ services/finetune-api/urllib3/
92
+ services/finetune-api/uvicorn/
93
+
94
+ # ===== Local test model artifacts =====
95
+ local-test/final_model/
96
+ local-test/merged_model/
97
+ local-test/gguf_model/
98
+ local-test/outputs/
99
+ local-test/data/*.jsonl
100
+ *.gguf
101
+ tokenizer.json
102
+
103
+ ### Node / TypeScript ###
104
+ node_modules/
105
+ *.tsbuildinfo
106
+
107
+ ### Coverage ###
108
+ .coverage
109
+ htmlcov/
110
+ *.lcov
111
+
112
+ ### macOS ###
113
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Lunar
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,29 @@
1
+ .PHONY: install dev test lint format clean build publish
2
+
3
+ install:
4
+ pip install -e .
5
+
6
+ dev:
7
+ pip install -e ".[dev]"
8
+
9
+ test:
10
+ pytest -v
11
+
12
+ lint:
13
+ ruff check lunar/ tests/
14
+ mypy lunar/
15
+
16
+ format:
17
+ ruff format lunar/ tests/
18
+ ruff check --fix lunar/ tests/
19
+
20
+ clean:
21
+ rm -rf dist/ build/ *.egg-info
22
+ find . -type d -name __pycache__ -exec rm -rf {} +
23
+ find . -type f -name "*.pyc" -delete
24
+
25
+ build: clean
26
+ python -m build
27
+
28
+ publish: build
29
+ twine upload dist/*
@@ -0,0 +1,275 @@
1
+ Metadata-Version: 2.4
2
+ Name: lunar-sdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for Lunar LLM Inference API - OpenAI-compatible with fallbacks
5
+ Project-URL: Homepage, https://lunar-sys.com
6
+ Project-URL: Documentation, https://docs.lunar-sys.com
7
+ Project-URL: Repository, https://github.com/PureAI-Tools/autodestill
8
+ Project-URL: Issues, https://github.com/PureAI-Tools/autodestill/issues
9
+ Author-email: Lunar <dev@lunar-sys.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: ai,inference,llm,lunar,openai,sdk
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.9
24
+ Requires-Dist: httpx>=0.25.0
25
+ Requires-Dist: pydantic>=2.0.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: mypy>=1.0; extra == 'dev'
28
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
29
+ Requires-Dist: pytest>=7.0; extra == 'dev'
30
+ Requires-Dist: respx>=0.20; extra == 'dev'
31
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
32
+ Provides-Extra: evals
33
+ Requires-Dist: jsonschema>=4.0; extra == 'evals'
34
+ Requires-Dist: nest-asyncio>=1.5.0; extra == 'evals'
35
+ Requires-Dist: rich>=13.0.0; extra == 'evals'
36
+ Requires-Dist: tqdm>=4.0.0; extra == 'evals'
37
+ Provides-Extra: langchain
38
+ Requires-Dist: langchain-core>=0.2.0; extra == 'langchain'
39
+ Provides-Extra: llamaindex
40
+ Requires-Dist: llama-index-core>=0.11.0; extra == 'llamaindex'
41
+ Provides-Extra: notebook
42
+ Requires-Dist: jupyter>=1.0.0; extra == 'notebook'
43
+ Requires-Dist: nest-asyncio>=1.5.0; extra == 'notebook'
44
+ Description-Content-Type: text/markdown
45
+
46
+ # Lunar SDK
47
+
48
+ Python SDK for Lunar LLM Inference API - OpenAI-compatible with intelligent fallbacks.
49
+
50
+ ## Installation
51
+
52
+ ```bash
53
+ pip install lunar
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ ```python
59
+ from lunar import Lunar
60
+
61
+ # Initialize client (uses LUNAR_API_KEY env var)
62
+ client = Lunar()
63
+
64
+ # Chat completion
65
+ response = client.chat.completions.create(
66
+ model="gpt-4o-mini",
67
+ messages=[{"role": "user", "content": "Hello!"}]
68
+ )
69
+
70
+ print(response.choices[0].message.content)
71
+ print(f"Cost: ${response.usage.total_cost_usd}")
72
+ ```
73
+
74
+ ## Authentication
75
+
76
+ Set your API key via environment variable:
77
+
78
+ ```bash
79
+ export LUNAR_API_KEY="your-api-key"
80
+ ```
81
+
82
+ Or pass it directly:
83
+
84
+ ```python
85
+ client = Lunar(api_key="your-api-key")
86
+ ```
87
+
88
+ ## Features
89
+
90
+ ### Chat Completions
91
+
92
+ ```python
93
+ response = client.chat.completions.create(
94
+ model="gpt-4o-mini",
95
+ messages=[
96
+ {"role": "system", "content": "You are a helpful assistant."},
97
+ {"role": "user", "content": "What is the capital of France?"}
98
+ ]
99
+ )
100
+
101
+ print(response.choices[0].message.content)
102
+ ```
103
+
104
+ ### Streaming
105
+
106
+ Stream responses token by token:
107
+
108
+ ```python
109
+ # Synchronous streaming
110
+ stream = client.chat.completions.create(
111
+ model="gpt-4o-mini",
112
+ messages=[{"role": "user", "content": "Write a short story"}],
113
+ stream=True
114
+ )
115
+
116
+ for chunk in stream:
117
+ if chunk.choices[0].delta.content:
118
+ print(chunk.choices[0].delta.content, end="", flush=True)
119
+ ```
120
+
121
+ Async streaming:
122
+
123
+ ```python
124
+ from lunar import AsyncLunar
125
+
126
+ async with AsyncLunar() as client:
127
+ stream = await client.chat.completions.create(
128
+ model="gpt-4o-mini",
129
+ messages=[{"role": "user", "content": "Write a short story"}],
130
+ stream=True
131
+ )
132
+
133
+ async for chunk in stream:
134
+ if chunk.choices[0].delta.content:
135
+ print(chunk.choices[0].delta.content, end="", flush=True)
136
+ ```
137
+
138
+ ### Text Completions
139
+
140
+ ```python
141
+ response = client.completions.create(
142
+ model="gpt-4o-mini",
143
+ prompt="Once upon a time",
144
+ max_tokens=100
145
+ )
146
+
147
+ print(response.choices[0].text)
148
+ ```
149
+
150
+ ### Fallbacks
151
+
152
+ Lunar automatically falls back to alternative models when the primary model fails with infrastructure errors (5xx, rate limits, timeouts).
153
+
154
+ ```python
155
+ # Per-request fallbacks
156
+ response = client.chat.completions.create(
157
+ model="gpt-4o-mini",
158
+ messages=[{"role": "user", "content": "Hello!"}],
159
+ fallbacks=["claude-3-haiku", "llama-3.1-8b"]
160
+ )
161
+
162
+ # Global fallbacks via config
163
+ client = Lunar(
164
+ fallbacks={
165
+ "gpt-4o-mini": ["claude-3-haiku", "llama-3.1-8b"],
166
+ "gpt-4": ["claude-3-opus"]
167
+ }
168
+ )
169
+ ```
170
+
171
+ **Fallback behavior:**
172
+ - **Triggers fallback:** 5xx errors, 429 rate limit, connection errors, timeouts
173
+ - **Does NOT trigger fallback:** 400 bad request, 401 auth error, 403 forbidden (these are client errors that won't be fixed by another model)
174
+
175
+ ### Force Provider
176
+
177
+ ```python
178
+ # Force a specific provider
179
+ response = client.chat.completions.create(
180
+ model="openai/gpt-4o-mini", # Forces OpenAI provider
181
+ messages=[{"role": "user", "content": "Hello!"}]
182
+ )
183
+ ```
184
+
185
+ ### List Models and Providers
186
+
187
+ ```python
188
+ # List available models
189
+ models = client.models.list()
190
+ for model in models:
191
+ print(f"{model.id} (owned by {model.owned_by})")
192
+
193
+ # List providers for a model
194
+ providers = client.providers.list(model="gpt-4o-mini")
195
+ for provider in providers:
196
+ print(f"{provider.id}: {provider.type} (enabled: {provider.enabled})")
197
+ ```
198
+
199
+ ### Cost Tracking
200
+
201
+ Every response includes detailed cost information:
202
+
203
+ ```python
204
+ response = client.chat.completions.create(...)
205
+
206
+ print(f"Input tokens: {response.usage.prompt_tokens}")
207
+ print(f"Output tokens: {response.usage.completion_tokens}")
208
+ print(f"Input cost: ${response.usage.input_cost_usd}")
209
+ print(f"Output cost: ${response.usage.output_cost_usd}")
210
+ print(f"Total cost: ${response.usage.total_cost_usd}")
211
+ print(f"Latency: {response.usage.latency_ms}ms")
212
+ ```
213
+
214
+ ## Async Usage
215
+
216
+ ```python
217
+ from lunar import AsyncLunar
218
+
219
+ async with AsyncLunar() as client:
220
+ response = await client.chat.completions.create(
221
+ model="gpt-4o-mini",
222
+ messages=[{"role": "user", "content": "Hello!"}]
223
+ )
224
+ print(response.choices[0].message.content)
225
+ ```
226
+
227
+ ## Configuration
228
+
229
+ ```python
230
+ client = Lunar(
231
+ api_key="your-api-key", # Or use LUNAR_API_KEY env var
232
+ base_url="https://api.lunar-sys.com", # Custom API endpoint
233
+ timeout=60.0, # Request timeout in seconds
234
+ num_retries=3, # Retries for transient errors
235
+ max_connections=100, # Max concurrent connections
236
+ fallbacks={ # Global fallback configuration
237
+ "gpt-4o-mini": ["claude-3-haiku"]
238
+ }
239
+ )
240
+ ```
241
+
242
+ ## Error Handling
243
+
244
+ ```python
245
+ from lunar import (
246
+ Lunar,
247
+ LunarError,
248
+ APIError,
249
+ BadRequestError,
250
+ AuthenticationError,
251
+ RateLimitError,
252
+ ServerError,
253
+ )
254
+
255
+ client = Lunar()
256
+
257
+ try:
258
+ response = client.chat.completions.create(...)
259
+ except BadRequestError as e:
260
+ print(f"Invalid request: {e}")
261
+ except AuthenticationError as e:
262
+ print(f"Auth failed: {e}")
263
+ except RateLimitError as e:
264
+ print(f"Rate limited: {e}")
265
+ except ServerError as e:
266
+ print(f"Server error: {e}")
267
+ except APIError as e:
268
+ print(f"API error [{e.status_code}]: {e}")
269
+ except LunarError as e:
270
+ print(f"Lunar error: {e}")
271
+ ```
272
+
273
+ ## License
274
+
275
+ MIT
@@ -0,0 +1,230 @@
1
+ # Lunar SDK
2
+
3
+ Python SDK for Lunar LLM Inference API - OpenAI-compatible with intelligent fallbacks.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install lunar
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from lunar import Lunar
15
+
16
+ # Initialize client (uses LUNAR_API_KEY env var)
17
+ client = Lunar()
18
+
19
+ # Chat completion
20
+ response = client.chat.completions.create(
21
+ model="gpt-4o-mini",
22
+ messages=[{"role": "user", "content": "Hello!"}]
23
+ )
24
+
25
+ print(response.choices[0].message.content)
26
+ print(f"Cost: ${response.usage.total_cost_usd}")
27
+ ```
28
+
29
+ ## Authentication
30
+
31
+ Set your API key via environment variable:
32
+
33
+ ```bash
34
+ export LUNAR_API_KEY="your-api-key"
35
+ ```
36
+
37
+ Or pass it directly:
38
+
39
+ ```python
40
+ client = Lunar(api_key="your-api-key")
41
+ ```
42
+
43
+ ## Features
44
+
45
+ ### Chat Completions
46
+
47
+ ```python
48
+ response = client.chat.completions.create(
49
+ model="gpt-4o-mini",
50
+ messages=[
51
+ {"role": "system", "content": "You are a helpful assistant."},
52
+ {"role": "user", "content": "What is the capital of France?"}
53
+ ]
54
+ )
55
+
56
+ print(response.choices[0].message.content)
57
+ ```
58
+
59
+ ### Streaming
60
+
61
+ Stream responses token by token:
62
+
63
+ ```python
64
+ # Synchronous streaming
65
+ stream = client.chat.completions.create(
66
+ model="gpt-4o-mini",
67
+ messages=[{"role": "user", "content": "Write a short story"}],
68
+ stream=True
69
+ )
70
+
71
+ for chunk in stream:
72
+ if chunk.choices[0].delta.content:
73
+ print(chunk.choices[0].delta.content, end="", flush=True)
74
+ ```
75
+
76
+ Async streaming:
77
+
78
+ ```python
79
+ from lunar import AsyncLunar
80
+
81
+ async with AsyncLunar() as client:
82
+ stream = await client.chat.completions.create(
83
+ model="gpt-4o-mini",
84
+ messages=[{"role": "user", "content": "Write a short story"}],
85
+ stream=True
86
+ )
87
+
88
+ async for chunk in stream:
89
+ if chunk.choices[0].delta.content:
90
+ print(chunk.choices[0].delta.content, end="", flush=True)
91
+ ```
92
+
93
+ ### Text Completions
94
+
95
+ ```python
96
+ response = client.completions.create(
97
+ model="gpt-4o-mini",
98
+ prompt="Once upon a time",
99
+ max_tokens=100
100
+ )
101
+
102
+ print(response.choices[0].text)
103
+ ```
104
+
105
+ ### Fallbacks
106
+
107
+ Lunar automatically falls back to alternative models when the primary model fails with infrastructure errors (5xx, rate limits, timeouts).
108
+
109
+ ```python
110
+ # Per-request fallbacks
111
+ response = client.chat.completions.create(
112
+ model="gpt-4o-mini",
113
+ messages=[{"role": "user", "content": "Hello!"}],
114
+ fallbacks=["claude-3-haiku", "llama-3.1-8b"]
115
+ )
116
+
117
+ # Global fallbacks via config
118
+ client = Lunar(
119
+ fallbacks={
120
+ "gpt-4o-mini": ["claude-3-haiku", "llama-3.1-8b"],
121
+ "gpt-4": ["claude-3-opus"]
122
+ }
123
+ )
124
+ ```
125
+
126
+ **Fallback behavior:**
127
+ - **Triggers fallback:** 5xx errors, 429 rate limit, connection errors, timeouts
128
+ - **Does NOT trigger fallback:** 400 bad request, 401 auth error, 403 forbidden (these are client errors that won't be fixed by another model)
129
+
130
+ ### Force Provider
131
+
132
+ ```python
133
+ # Force a specific provider
134
+ response = client.chat.completions.create(
135
+ model="openai/gpt-4o-mini", # Forces OpenAI provider
136
+ messages=[{"role": "user", "content": "Hello!"}]
137
+ )
138
+ ```
139
+
140
+ ### List Models and Providers
141
+
142
+ ```python
143
+ # List available models
144
+ models = client.models.list()
145
+ for model in models:
146
+ print(f"{model.id} (owned by {model.owned_by})")
147
+
148
+ # List providers for a model
149
+ providers = client.providers.list(model="gpt-4o-mini")
150
+ for provider in providers:
151
+ print(f"{provider.id}: {provider.type} (enabled: {provider.enabled})")
152
+ ```
153
+
154
+ ### Cost Tracking
155
+
156
+ Every response includes detailed cost information:
157
+
158
+ ```python
159
+ response = client.chat.completions.create(...)
160
+
161
+ print(f"Input tokens: {response.usage.prompt_tokens}")
162
+ print(f"Output tokens: {response.usage.completion_tokens}")
163
+ print(f"Input cost: ${response.usage.input_cost_usd}")
164
+ print(f"Output cost: ${response.usage.output_cost_usd}")
165
+ print(f"Total cost: ${response.usage.total_cost_usd}")
166
+ print(f"Latency: {response.usage.latency_ms}ms")
167
+ ```
168
+
169
+ ## Async Usage
170
+
171
+ ```python
172
+ from lunar import AsyncLunar
173
+
174
+ async with AsyncLunar() as client:
175
+ response = await client.chat.completions.create(
176
+ model="gpt-4o-mini",
177
+ messages=[{"role": "user", "content": "Hello!"}]
178
+ )
179
+ print(response.choices[0].message.content)
180
+ ```
181
+
182
+ ## Configuration
183
+
184
+ ```python
185
+ client = Lunar(
186
+ api_key="your-api-key", # Or use LUNAR_API_KEY env var
187
+ base_url="https://api.lunar-sys.com", # Custom API endpoint
188
+ timeout=60.0, # Request timeout in seconds
189
+ num_retries=3, # Retries for transient errors
190
+ max_connections=100, # Max concurrent connections
191
+ fallbacks={ # Global fallback configuration
192
+ "gpt-4o-mini": ["claude-3-haiku"]
193
+ }
194
+ )
195
+ ```
196
+
197
+ ## Error Handling
198
+
199
+ ```python
200
+ from lunar import (
201
+ Lunar,
202
+ LunarError,
203
+ APIError,
204
+ BadRequestError,
205
+ AuthenticationError,
206
+ RateLimitError,
207
+ ServerError,
208
+ )
209
+
210
+ client = Lunar()
211
+
212
+ try:
213
+ response = client.chat.completions.create(...)
214
+ except BadRequestError as e:
215
+ print(f"Invalid request: {e}")
216
+ except AuthenticationError as e:
217
+ print(f"Auth failed: {e}")
218
+ except RateLimitError as e:
219
+ print(f"Rate limited: {e}")
220
+ except ServerError as e:
221
+ print(f"Server error: {e}")
222
+ except APIError as e:
223
+ print(f"API error [{e.status_code}]: {e}")
224
+ except LunarError as e:
225
+ print(f"Lunar error: {e}")
226
+ ```
227
+
228
+ ## License
229
+
230
+ MIT