prismer 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.
- prismer-0.1.0/PKG-INFO +361 -0
- prismer-0.1.0/README.md +331 -0
- prismer-0.1.0/prismer/__init__.py +35 -0
- prismer-0.1.0/prismer/client.py +397 -0
- prismer-0.1.0/prismer/types.py +208 -0
- prismer-0.1.0/prismer.egg-info/PKG-INFO +361 -0
- prismer-0.1.0/prismer.egg-info/SOURCES.txt +10 -0
- prismer-0.1.0/prismer.egg-info/dependency_links.txt +1 -0
- prismer-0.1.0/prismer.egg-info/requires.txt +8 -0
- prismer-0.1.0/prismer.egg-info/top_level.txt +3 -0
- prismer-0.1.0/pyproject.toml +55 -0
- prismer-0.1.0/setup.cfg +4 -0
prismer-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: prismer
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official Python SDK for Prismer Cloud API
|
|
5
|
+
Author-email: Prismer <dev@prismer.io>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://prismer.io
|
|
8
|
+
Project-URL: Documentation, https://docs.prismer.io
|
|
9
|
+
Project-URL: Repository, https://github.com/prismer-io/prismer-sdk-python
|
|
10
|
+
Keywords: prismer,ai,context,sdk,api
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: httpx>=0.24.0
|
|
24
|
+
Requires-Dist: pydantic>=2.0.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
29
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
30
|
+
|
|
31
|
+
# prismer
|
|
32
|
+
|
|
33
|
+
Official Python SDK for Prismer Cloud Context API.
|
|
34
|
+
|
|
35
|
+
Prismer Cloud provides AI agents with fast, cached access to web content. Load URLs or search queries, get compressed high-quality content (HQCC) optimized for LLM consumption.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install prismer
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from prismer import PrismerClient
|
|
47
|
+
|
|
48
|
+
client = PrismerClient(api_key="sk-prismer-...")
|
|
49
|
+
|
|
50
|
+
# Load content from a URL
|
|
51
|
+
result = client.load("https://example.com")
|
|
52
|
+
if result.success and result.result:
|
|
53
|
+
print(result.result.hqcc) # Compressed content for LLM
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Async Support
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from prismer import AsyncPrismerClient
|
|
60
|
+
|
|
61
|
+
async with AsyncPrismerClient(api_key="sk-prismer-...") as client:
|
|
62
|
+
result = await client.load("https://example.com")
|
|
63
|
+
print(result.result.hqcc if result.result else None)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## API Reference
|
|
69
|
+
|
|
70
|
+
### Constructor
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
client = PrismerClient(
|
|
74
|
+
api_key="sk-prismer-...", # Required
|
|
75
|
+
base_url="https://api.prismer.io", # Optional
|
|
76
|
+
timeout=30.0, # Optional, seconds
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## `load(input, **options)`
|
|
83
|
+
|
|
84
|
+
Load content from URL(s) or search query. The API auto-detects input type.
|
|
85
|
+
|
|
86
|
+
### Input Types
|
|
87
|
+
|
|
88
|
+
| Input | Mode | Description |
|
|
89
|
+
|-------|------|-------------|
|
|
90
|
+
| `"https://..."` | `single_url` | Fetch single URL, check cache first |
|
|
91
|
+
| `["url1", "url2"]` | `batch_urls` | Batch cache lookup |
|
|
92
|
+
| `"search query"` | `query` | Search → cache check → compress → rank |
|
|
93
|
+
|
|
94
|
+
### Examples
|
|
95
|
+
|
|
96
|
+
#### Single URL
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
result = client.load("https://example.com")
|
|
100
|
+
|
|
101
|
+
# Result structure:
|
|
102
|
+
# LoadResult(
|
|
103
|
+
# success=True,
|
|
104
|
+
# request_id="load_abc123",
|
|
105
|
+
# mode="single_url",
|
|
106
|
+
# result=LoadResultItem(
|
|
107
|
+
# url="https://example.com",
|
|
108
|
+
# title="Example Domain",
|
|
109
|
+
# hqcc="# Example Domain\n\nThis domain is for...",
|
|
110
|
+
# cached=True,
|
|
111
|
+
# cached_at="2024-01-15T10:30:00Z",
|
|
112
|
+
# ),
|
|
113
|
+
# cost={"credits": 0, "cached": True},
|
|
114
|
+
# processing_time=45
|
|
115
|
+
# )
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### Batch URLs
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
# Cache check only (default)
|
|
122
|
+
result = client.load(["url1", "url2", "url3"])
|
|
123
|
+
|
|
124
|
+
# With processing for uncached URLs
|
|
125
|
+
result = client.load(
|
|
126
|
+
["url1", "url2", "url3"],
|
|
127
|
+
process_uncached=True,
|
|
128
|
+
processing={
|
|
129
|
+
"strategy": "fast", # "auto" | "fast" | "quality"
|
|
130
|
+
"maxConcurrent": 5 # Parallel compression limit
|
|
131
|
+
}
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Result:
|
|
135
|
+
# result.results = [
|
|
136
|
+
# LoadResultItem(url="url1", found=True, cached=True, hqcc="..."),
|
|
137
|
+
# LoadResultItem(url="url2", found=True, cached=False, processed=True, hqcc="..."),
|
|
138
|
+
# LoadResultItem(url="url3", found=False, cached=False, hqcc=None),
|
|
139
|
+
# ]
|
|
140
|
+
# result.summary = {"total": 3, "found": 2, "notFound": 1, "cached": 1, "processed": 1}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### Search Query
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
result = client.load(
|
|
147
|
+
"latest developments in AI agents 2024",
|
|
148
|
+
search={"topK": 15}, # Search results to fetch
|
|
149
|
+
processing={
|
|
150
|
+
"strategy": "quality",
|
|
151
|
+
"maxConcurrent": 3
|
|
152
|
+
},
|
|
153
|
+
return_config={
|
|
154
|
+
"topK": 5, # Results to return
|
|
155
|
+
"format": "both" # "hqcc" | "raw" | "both"
|
|
156
|
+
},
|
|
157
|
+
ranking={
|
|
158
|
+
"preset": "cache_first" # Prefer cached results
|
|
159
|
+
# Or custom weights:
|
|
160
|
+
# "custom": {"cacheHit": 0.3, "relevance": 0.4, "freshness": 0.2, "quality": 0.1}
|
|
161
|
+
}
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Result:
|
|
165
|
+
# result.results = [
|
|
166
|
+
# LoadResultItem(
|
|
167
|
+
# rank=1,
|
|
168
|
+
# url="https://...",
|
|
169
|
+
# title="AI Agents in 2024",
|
|
170
|
+
# hqcc="...",
|
|
171
|
+
# raw="...",
|
|
172
|
+
# cached=True,
|
|
173
|
+
# ranking=RankingInfo(
|
|
174
|
+
# score=0.85,
|
|
175
|
+
# factors=RankingFactors(cache=0.3, relevance=0.35, freshness=0.15, quality=0.05)
|
|
176
|
+
# )
|
|
177
|
+
# ),
|
|
178
|
+
# ...
|
|
179
|
+
# ]
|
|
180
|
+
# result.cost = {
|
|
181
|
+
# "searchCredits": 1,
|
|
182
|
+
# "compressionCredits": 3.5,
|
|
183
|
+
# "totalCredits": 4.5,
|
|
184
|
+
# "savedByCache": 4.0
|
|
185
|
+
# }
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Load Parameters
|
|
189
|
+
|
|
190
|
+
| Parameter | Type | Description |
|
|
191
|
+
|-----------|------|-------------|
|
|
192
|
+
| `input` | `str \| list[str]` | URL, URLs, or search query |
|
|
193
|
+
| `input_type` | `str` | Force type: `"url"`, `"urls"`, `"query"` |
|
|
194
|
+
| `process_uncached` | `bool` | Process uncached URLs in batch mode |
|
|
195
|
+
| `search` | `dict` | `{"topK": 15}` - search results to fetch |
|
|
196
|
+
| `processing` | `dict` | `{"strategy": "auto", "maxConcurrent": 3}` |
|
|
197
|
+
| `return_config` | `dict` | `{"format": "hqcc", "topK": 5}` |
|
|
198
|
+
| `ranking` | `dict` | `{"preset": "cache_first"}` or `{"custom": {...}}` |
|
|
199
|
+
|
|
200
|
+
### Ranking Presets
|
|
201
|
+
|
|
202
|
+
| Preset | Description | Best For |
|
|
203
|
+
|--------|-------------|----------|
|
|
204
|
+
| `cache_first` | Strongly prefer cached results | Cost optimization |
|
|
205
|
+
| `relevance_first` | Prioritize search relevance | Accuracy-critical tasks |
|
|
206
|
+
| `balanced` | Equal weight to all factors | General use |
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## `save()` / `save_batch()`
|
|
211
|
+
|
|
212
|
+
Save content to Prismer's global cache. Requires authentication.
|
|
213
|
+
|
|
214
|
+
### Single Save
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
result = client.save(
|
|
218
|
+
url="https://example.com/article",
|
|
219
|
+
hqcc="Compressed content for LLM...",
|
|
220
|
+
raw="Original HTML/text content...", # Optional
|
|
221
|
+
meta={ # Optional
|
|
222
|
+
"source": "my-crawler",
|
|
223
|
+
"crawledAt": "2024-01-15T10:30:00Z"
|
|
224
|
+
}
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
# Result:
|
|
228
|
+
# SaveResult(success=True, status="created", url="...")
|
|
229
|
+
# Or if already exists:
|
|
230
|
+
# SaveResult(success=True, status="exists", url="...")
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Batch Save (max 50 items)
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
result = client.save(items=[
|
|
237
|
+
{"url": "url1", "hqcc": "content1"},
|
|
238
|
+
{"url": "url2", "hqcc": "content2", "raw": "raw2"},
|
|
239
|
+
{"url": "url3", "hqcc": "content3", "meta": {"source": "bot"}},
|
|
240
|
+
])
|
|
241
|
+
|
|
242
|
+
# Or use SaveOptions for type safety:
|
|
243
|
+
from prismer import SaveOptions
|
|
244
|
+
|
|
245
|
+
result = client.save_batch([
|
|
246
|
+
SaveOptions(url="url1", hqcc="content1"),
|
|
247
|
+
SaveOptions(url="url2", hqcc="content2"),
|
|
248
|
+
])
|
|
249
|
+
|
|
250
|
+
# Result:
|
|
251
|
+
# SaveResult(
|
|
252
|
+
# success=True,
|
|
253
|
+
# results=[
|
|
254
|
+
# SaveResultItem(url="url1", status="created"),
|
|
255
|
+
# SaveResultItem(url="url2", status="exists"),
|
|
256
|
+
# ],
|
|
257
|
+
# summary=SaveSummary(total=2, created=1, exists=1)
|
|
258
|
+
# )
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Error Handling
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
result = client.load("https://example.com")
|
|
267
|
+
|
|
268
|
+
if not result.success:
|
|
269
|
+
print(f"Error [{result.error.code}]: {result.error.message}")
|
|
270
|
+
|
|
271
|
+
# Handle specific errors:
|
|
272
|
+
if result.error.code == "UNAUTHORIZED":
|
|
273
|
+
# Invalid or missing API key
|
|
274
|
+
pass
|
|
275
|
+
elif result.error.code == "INVALID_INPUT":
|
|
276
|
+
# Bad request parameters
|
|
277
|
+
pass
|
|
278
|
+
elif result.error.code == "TIMEOUT":
|
|
279
|
+
# Request timed out
|
|
280
|
+
pass
|
|
281
|
+
elif result.error.code == "NETWORK_ERROR":
|
|
282
|
+
# Network connectivity issue
|
|
283
|
+
pass
|
|
284
|
+
return
|
|
285
|
+
|
|
286
|
+
# Safe to use result
|
|
287
|
+
print(result.result.hqcc if result.result else None)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Type Hints
|
|
293
|
+
|
|
294
|
+
Full type hints with Pydantic models:
|
|
295
|
+
|
|
296
|
+
```python
|
|
297
|
+
from prismer import (
|
|
298
|
+
PrismerClient,
|
|
299
|
+
AsyncPrismerClient,
|
|
300
|
+
LoadResult,
|
|
301
|
+
LoadResultItem,
|
|
302
|
+
SaveResult,
|
|
303
|
+
SaveOptions,
|
|
304
|
+
PrismerError,
|
|
305
|
+
)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Best Practices
|
|
311
|
+
|
|
312
|
+
### 1. Use Context Manager for Async Client
|
|
313
|
+
|
|
314
|
+
```python
|
|
315
|
+
# ✅ Properly closes connection
|
|
316
|
+
async with AsyncPrismerClient(api_key="...") as client:
|
|
317
|
+
result = await client.load("https://example.com")
|
|
318
|
+
|
|
319
|
+
# Or manually close:
|
|
320
|
+
client = AsyncPrismerClient(api_key="...")
|
|
321
|
+
try:
|
|
322
|
+
result = await client.load("https://example.com")
|
|
323
|
+
finally:
|
|
324
|
+
await client.close()
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### 2. Batch URLs When Possible
|
|
328
|
+
|
|
329
|
+
```python
|
|
330
|
+
# ❌ Multiple individual requests
|
|
331
|
+
for url in urls:
|
|
332
|
+
client.load(url)
|
|
333
|
+
|
|
334
|
+
# ✅ Single batch request
|
|
335
|
+
client.load(urls, process_uncached=True)
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### 3. Use Cache-First Ranking for Cost Savings
|
|
339
|
+
|
|
340
|
+
```python
|
|
341
|
+
result = client.load("AI news", ranking={"preset": "cache_first"})
|
|
342
|
+
print(f"Saved {result.cost.get('savedByCache', 0)} credits from cache")
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Environment Variables
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
# Optional: Set default API key
|
|
351
|
+
export PRISMER_API_KEY=sk-prismer-...
|
|
352
|
+
|
|
353
|
+
# Optional: Custom API endpoint
|
|
354
|
+
export PRISMER_BASE_URL=https://api.prismer.io
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## License
|
|
360
|
+
|
|
361
|
+
MIT
|
prismer-0.1.0/README.md
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
# prismer
|
|
2
|
+
|
|
3
|
+
Official Python SDK for Prismer Cloud Context API.
|
|
4
|
+
|
|
5
|
+
Prismer Cloud provides AI agents with fast, cached access to web content. Load URLs or search queries, get compressed high-quality content (HQCC) optimized for LLM consumption.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install prismer
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from prismer import PrismerClient
|
|
17
|
+
|
|
18
|
+
client = PrismerClient(api_key="sk-prismer-...")
|
|
19
|
+
|
|
20
|
+
# Load content from a URL
|
|
21
|
+
result = client.load("https://example.com")
|
|
22
|
+
if result.success and result.result:
|
|
23
|
+
print(result.result.hqcc) # Compressed content for LLM
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Async Support
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from prismer import AsyncPrismerClient
|
|
30
|
+
|
|
31
|
+
async with AsyncPrismerClient(api_key="sk-prismer-...") as client:
|
|
32
|
+
result = await client.load("https://example.com")
|
|
33
|
+
print(result.result.hqcc if result.result else None)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## API Reference
|
|
39
|
+
|
|
40
|
+
### Constructor
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
client = PrismerClient(
|
|
44
|
+
api_key="sk-prismer-...", # Required
|
|
45
|
+
base_url="https://api.prismer.io", # Optional
|
|
46
|
+
timeout=30.0, # Optional, seconds
|
|
47
|
+
)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## `load(input, **options)`
|
|
53
|
+
|
|
54
|
+
Load content from URL(s) or search query. The API auto-detects input type.
|
|
55
|
+
|
|
56
|
+
### Input Types
|
|
57
|
+
|
|
58
|
+
| Input | Mode | Description |
|
|
59
|
+
|-------|------|-------------|
|
|
60
|
+
| `"https://..."` | `single_url` | Fetch single URL, check cache first |
|
|
61
|
+
| `["url1", "url2"]` | `batch_urls` | Batch cache lookup |
|
|
62
|
+
| `"search query"` | `query` | Search → cache check → compress → rank |
|
|
63
|
+
|
|
64
|
+
### Examples
|
|
65
|
+
|
|
66
|
+
#### Single URL
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
result = client.load("https://example.com")
|
|
70
|
+
|
|
71
|
+
# Result structure:
|
|
72
|
+
# LoadResult(
|
|
73
|
+
# success=True,
|
|
74
|
+
# request_id="load_abc123",
|
|
75
|
+
# mode="single_url",
|
|
76
|
+
# result=LoadResultItem(
|
|
77
|
+
# url="https://example.com",
|
|
78
|
+
# title="Example Domain",
|
|
79
|
+
# hqcc="# Example Domain\n\nThis domain is for...",
|
|
80
|
+
# cached=True,
|
|
81
|
+
# cached_at="2024-01-15T10:30:00Z",
|
|
82
|
+
# ),
|
|
83
|
+
# cost={"credits": 0, "cached": True},
|
|
84
|
+
# processing_time=45
|
|
85
|
+
# )
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
#### Batch URLs
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
# Cache check only (default)
|
|
92
|
+
result = client.load(["url1", "url2", "url3"])
|
|
93
|
+
|
|
94
|
+
# With processing for uncached URLs
|
|
95
|
+
result = client.load(
|
|
96
|
+
["url1", "url2", "url3"],
|
|
97
|
+
process_uncached=True,
|
|
98
|
+
processing={
|
|
99
|
+
"strategy": "fast", # "auto" | "fast" | "quality"
|
|
100
|
+
"maxConcurrent": 5 # Parallel compression limit
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Result:
|
|
105
|
+
# result.results = [
|
|
106
|
+
# LoadResultItem(url="url1", found=True, cached=True, hqcc="..."),
|
|
107
|
+
# LoadResultItem(url="url2", found=True, cached=False, processed=True, hqcc="..."),
|
|
108
|
+
# LoadResultItem(url="url3", found=False, cached=False, hqcc=None),
|
|
109
|
+
# ]
|
|
110
|
+
# result.summary = {"total": 3, "found": 2, "notFound": 1, "cached": 1, "processed": 1}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### Search Query
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
result = client.load(
|
|
117
|
+
"latest developments in AI agents 2024",
|
|
118
|
+
search={"topK": 15}, # Search results to fetch
|
|
119
|
+
processing={
|
|
120
|
+
"strategy": "quality",
|
|
121
|
+
"maxConcurrent": 3
|
|
122
|
+
},
|
|
123
|
+
return_config={
|
|
124
|
+
"topK": 5, # Results to return
|
|
125
|
+
"format": "both" # "hqcc" | "raw" | "both"
|
|
126
|
+
},
|
|
127
|
+
ranking={
|
|
128
|
+
"preset": "cache_first" # Prefer cached results
|
|
129
|
+
# Or custom weights:
|
|
130
|
+
# "custom": {"cacheHit": 0.3, "relevance": 0.4, "freshness": 0.2, "quality": 0.1}
|
|
131
|
+
}
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Result:
|
|
135
|
+
# result.results = [
|
|
136
|
+
# LoadResultItem(
|
|
137
|
+
# rank=1,
|
|
138
|
+
# url="https://...",
|
|
139
|
+
# title="AI Agents in 2024",
|
|
140
|
+
# hqcc="...",
|
|
141
|
+
# raw="...",
|
|
142
|
+
# cached=True,
|
|
143
|
+
# ranking=RankingInfo(
|
|
144
|
+
# score=0.85,
|
|
145
|
+
# factors=RankingFactors(cache=0.3, relevance=0.35, freshness=0.15, quality=0.05)
|
|
146
|
+
# )
|
|
147
|
+
# ),
|
|
148
|
+
# ...
|
|
149
|
+
# ]
|
|
150
|
+
# result.cost = {
|
|
151
|
+
# "searchCredits": 1,
|
|
152
|
+
# "compressionCredits": 3.5,
|
|
153
|
+
# "totalCredits": 4.5,
|
|
154
|
+
# "savedByCache": 4.0
|
|
155
|
+
# }
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Load Parameters
|
|
159
|
+
|
|
160
|
+
| Parameter | Type | Description |
|
|
161
|
+
|-----------|------|-------------|
|
|
162
|
+
| `input` | `str \| list[str]` | URL, URLs, or search query |
|
|
163
|
+
| `input_type` | `str` | Force type: `"url"`, `"urls"`, `"query"` |
|
|
164
|
+
| `process_uncached` | `bool` | Process uncached URLs in batch mode |
|
|
165
|
+
| `search` | `dict` | `{"topK": 15}` - search results to fetch |
|
|
166
|
+
| `processing` | `dict` | `{"strategy": "auto", "maxConcurrent": 3}` |
|
|
167
|
+
| `return_config` | `dict` | `{"format": "hqcc", "topK": 5}` |
|
|
168
|
+
| `ranking` | `dict` | `{"preset": "cache_first"}` or `{"custom": {...}}` |
|
|
169
|
+
|
|
170
|
+
### Ranking Presets
|
|
171
|
+
|
|
172
|
+
| Preset | Description | Best For |
|
|
173
|
+
|--------|-------------|----------|
|
|
174
|
+
| `cache_first` | Strongly prefer cached results | Cost optimization |
|
|
175
|
+
| `relevance_first` | Prioritize search relevance | Accuracy-critical tasks |
|
|
176
|
+
| `balanced` | Equal weight to all factors | General use |
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## `save()` / `save_batch()`
|
|
181
|
+
|
|
182
|
+
Save content to Prismer's global cache. Requires authentication.
|
|
183
|
+
|
|
184
|
+
### Single Save
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
result = client.save(
|
|
188
|
+
url="https://example.com/article",
|
|
189
|
+
hqcc="Compressed content for LLM...",
|
|
190
|
+
raw="Original HTML/text content...", # Optional
|
|
191
|
+
meta={ # Optional
|
|
192
|
+
"source": "my-crawler",
|
|
193
|
+
"crawledAt": "2024-01-15T10:30:00Z"
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# Result:
|
|
198
|
+
# SaveResult(success=True, status="created", url="...")
|
|
199
|
+
# Or if already exists:
|
|
200
|
+
# SaveResult(success=True, status="exists", url="...")
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Batch Save (max 50 items)
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
result = client.save(items=[
|
|
207
|
+
{"url": "url1", "hqcc": "content1"},
|
|
208
|
+
{"url": "url2", "hqcc": "content2", "raw": "raw2"},
|
|
209
|
+
{"url": "url3", "hqcc": "content3", "meta": {"source": "bot"}},
|
|
210
|
+
])
|
|
211
|
+
|
|
212
|
+
# Or use SaveOptions for type safety:
|
|
213
|
+
from prismer import SaveOptions
|
|
214
|
+
|
|
215
|
+
result = client.save_batch([
|
|
216
|
+
SaveOptions(url="url1", hqcc="content1"),
|
|
217
|
+
SaveOptions(url="url2", hqcc="content2"),
|
|
218
|
+
])
|
|
219
|
+
|
|
220
|
+
# Result:
|
|
221
|
+
# SaveResult(
|
|
222
|
+
# success=True,
|
|
223
|
+
# results=[
|
|
224
|
+
# SaveResultItem(url="url1", status="created"),
|
|
225
|
+
# SaveResultItem(url="url2", status="exists"),
|
|
226
|
+
# ],
|
|
227
|
+
# summary=SaveSummary(total=2, created=1, exists=1)
|
|
228
|
+
# )
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Error Handling
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
result = client.load("https://example.com")
|
|
237
|
+
|
|
238
|
+
if not result.success:
|
|
239
|
+
print(f"Error [{result.error.code}]: {result.error.message}")
|
|
240
|
+
|
|
241
|
+
# Handle specific errors:
|
|
242
|
+
if result.error.code == "UNAUTHORIZED":
|
|
243
|
+
# Invalid or missing API key
|
|
244
|
+
pass
|
|
245
|
+
elif result.error.code == "INVALID_INPUT":
|
|
246
|
+
# Bad request parameters
|
|
247
|
+
pass
|
|
248
|
+
elif result.error.code == "TIMEOUT":
|
|
249
|
+
# Request timed out
|
|
250
|
+
pass
|
|
251
|
+
elif result.error.code == "NETWORK_ERROR":
|
|
252
|
+
# Network connectivity issue
|
|
253
|
+
pass
|
|
254
|
+
return
|
|
255
|
+
|
|
256
|
+
# Safe to use result
|
|
257
|
+
print(result.result.hqcc if result.result else None)
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Type Hints
|
|
263
|
+
|
|
264
|
+
Full type hints with Pydantic models:
|
|
265
|
+
|
|
266
|
+
```python
|
|
267
|
+
from prismer import (
|
|
268
|
+
PrismerClient,
|
|
269
|
+
AsyncPrismerClient,
|
|
270
|
+
LoadResult,
|
|
271
|
+
LoadResultItem,
|
|
272
|
+
SaveResult,
|
|
273
|
+
SaveOptions,
|
|
274
|
+
PrismerError,
|
|
275
|
+
)
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Best Practices
|
|
281
|
+
|
|
282
|
+
### 1. Use Context Manager for Async Client
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
# ✅ Properly closes connection
|
|
286
|
+
async with AsyncPrismerClient(api_key="...") as client:
|
|
287
|
+
result = await client.load("https://example.com")
|
|
288
|
+
|
|
289
|
+
# Or manually close:
|
|
290
|
+
client = AsyncPrismerClient(api_key="...")
|
|
291
|
+
try:
|
|
292
|
+
result = await client.load("https://example.com")
|
|
293
|
+
finally:
|
|
294
|
+
await client.close()
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### 2. Batch URLs When Possible
|
|
298
|
+
|
|
299
|
+
```python
|
|
300
|
+
# ❌ Multiple individual requests
|
|
301
|
+
for url in urls:
|
|
302
|
+
client.load(url)
|
|
303
|
+
|
|
304
|
+
# ✅ Single batch request
|
|
305
|
+
client.load(urls, process_uncached=True)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### 3. Use Cache-First Ranking for Cost Savings
|
|
309
|
+
|
|
310
|
+
```python
|
|
311
|
+
result = client.load("AI news", ranking={"preset": "cache_first"})
|
|
312
|
+
print(f"Saved {result.cost.get('savedByCache', 0)} credits from cache")
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## Environment Variables
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
# Optional: Set default API key
|
|
321
|
+
export PRISMER_API_KEY=sk-prismer-...
|
|
322
|
+
|
|
323
|
+
# Optional: Custom API endpoint
|
|
324
|
+
export PRISMER_BASE_URL=https://api.prismer.io
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## License
|
|
330
|
+
|
|
331
|
+
MIT
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Prismer Cloud SDK for Python
|
|
3
|
+
|
|
4
|
+
Official Python SDK for Prismer Cloud API.
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
>>> from prismer import PrismerClient
|
|
8
|
+
>>> client = PrismerClient(api_key="sk-prismer-...")
|
|
9
|
+
>>> result = client.load("https://example.com")
|
|
10
|
+
>>> print(result.result.hqcc)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from .client import PrismerClient, AsyncPrismerClient
|
|
14
|
+
from .types import (
|
|
15
|
+
LoadOptions,
|
|
16
|
+
LoadResult,
|
|
17
|
+
LoadResultItem,
|
|
18
|
+
SaveOptions,
|
|
19
|
+
SaveBatchOptions,
|
|
20
|
+
SaveResult,
|
|
21
|
+
PrismerError,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
__version__ = "0.1.0"
|
|
25
|
+
__all__ = [
|
|
26
|
+
"PrismerClient",
|
|
27
|
+
"AsyncPrismerClient",
|
|
28
|
+
"LoadOptions",
|
|
29
|
+
"LoadResult",
|
|
30
|
+
"LoadResultItem",
|
|
31
|
+
"SaveOptions",
|
|
32
|
+
"SaveBatchOptions",
|
|
33
|
+
"SaveResult",
|
|
34
|
+
"PrismerError",
|
|
35
|
+
]
|