pnotp 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.
- pnotp-0.1.0/PKG-INFO +65 -0
- pnotp-0.1.0/README.md +49 -0
- pnotp-0.1.0/dev.db +0 -0
- pnotp-0.1.0/plat/PnotP Brand Identity Design /342/200/223 Figma Make.pdf +0 -0
- pnotp-0.1.0/plat/exports/CONSTRUCTION-GUIDE.md +226 -0
- pnotp-0.1.0/plat/exports/horizontal-lockup-black.svg +16 -0
- pnotp-0.1.0/plat/exports/horizontal-lockup-white.svg +16 -0
- pnotp-0.1.0/plat/exports/icon-128.svg +10 -0
- pnotp-0.1.0/plat/exports/icon-16.svg +10 -0
- pnotp-0.1.0/plat/exports/icon-256.svg +10 -0
- pnotp-0.1.0/plat/exports/icon-32.svg +10 -0
- pnotp-0.1.0/plat/exports/icon-64.svg +10 -0
- pnotp-0.1.0/plat/exports/logo.png +0 -0
- pnotp-0.1.0/plat/exports/monogram-black.svg +15 -0
- pnotp-0.1.0/plat/exports/monogram-white.svg +15 -0
- pnotp-0.1.0/plat/exports/wordmark-black.svg +3 -0
- pnotp-0.1.0/plat/exports/wordmark-white.svg +3 -0
- pnotp-0.1.0/plat/exports.zip +0 -0
- pnotp-0.1.0/pnotp/__init__.py +23 -0
- pnotp-0.1.0/pnotp/client.py +76 -0
- pnotp-0.1.0/pnotp/exceptions.py +13 -0
- pnotp-0.1.0/pnotp/models.py +87 -0
- pnotp-0.1.0/pnotp_api/__init__.py +4 -0
- pnotp-0.1.0/pnotp_api/db.py +118 -0
- pnotp-0.1.0/pnotp_api/main.py +171 -0
- pnotp-0.1.0/pnotp_api/models_registry.py +102 -0
- pnotp-0.1.0/pnotp_api/pathovision_bridge.py +463 -0
- pnotp-0.1.0/pnotp_api/schemas.py +22 -0
- pnotp-0.1.0/pnotp_api/security.py +40 -0
- pnotp-0.1.0/pnotp_api.db +0 -0
- pnotp-0.1.0/pnotp_api.db-shm +0 -0
- pnotp-0.1.0/pnotp_api.db-wal +0 -0
- pnotp-0.1.0/pyproject.toml +30 -0
pnotp-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pnotp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: PnotP client and API wrappers for PathoVision models.
|
|
5
|
+
Project-URL: Homepage, https://pnotp.ai
|
|
6
|
+
Author-email: PnotP <support@pnotp.ai>
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Requires-Dist: httpx<0.29,>=0.24
|
|
9
|
+
Provides-Extra: server
|
|
10
|
+
Requires-Dist: fastapi<1.0,>=0.110; extra == 'server'
|
|
11
|
+
Requires-Dist: pillow>=9.0; extra == 'server'
|
|
12
|
+
Requires-Dist: pydantic<3.0,>=2.0; extra == 'server'
|
|
13
|
+
Requires-Dist: python-multipart>=0.0.6; extra == 'server'
|
|
14
|
+
Requires-Dist: uvicorn<0.29,>=0.23; extra == 'server'
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# PnotP
|
|
18
|
+
|
|
19
|
+
Unified API and Python client for PathoVision vision models.
|
|
20
|
+
|
|
21
|
+
## Packages
|
|
22
|
+
- `pnotp_api`: FastAPI service that wraps PathoVision ensembles under a consistent `/v1` surface with API-key auth.
|
|
23
|
+
- `pnotp`: Python client for calling the PnotP API.
|
|
24
|
+
|
|
25
|
+
## Install (client only)
|
|
26
|
+
```bash
|
|
27
|
+
pip install pnotp
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Install (client + server extra)
|
|
31
|
+
```bash
|
|
32
|
+
pip install "pnotp[server]"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Usage (client)
|
|
36
|
+
```python
|
|
37
|
+
import pnotp as pnp
|
|
38
|
+
|
|
39
|
+
client = pnp.client(api_key="YOUR_KEY") # default base URL is production
|
|
40
|
+
client.models()
|
|
41
|
+
model = client.models("pneumonia_binary_classification")
|
|
42
|
+
result = model.predict("image.jpg")
|
|
43
|
+
heatmap = model.attention_map("image.jpg")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Set your key once per shell:
|
|
47
|
+
```bash
|
|
48
|
+
export PNOTP_API_KEY="your_api_key_here"
|
|
49
|
+
python your_script.py # pnp.client() will read the env var automatically
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Run the API locally
|
|
53
|
+
```bash
|
|
54
|
+
export PNOTP_INTERNAL_SECRET="dev-secret"
|
|
55
|
+
export PATHOVISION_ROOT="/absolute/path/to/PathoVision" # if not default
|
|
56
|
+
uvicorn pnotp_api.main:app --host 0.0.0.0 --port 8000
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Issue an API key (internal)
|
|
60
|
+
```bash
|
|
61
|
+
curl -X POST http://127.0.0.1:8000/internal/api-keys \
|
|
62
|
+
-H "X-Internal-Secret: $PNOTP_INTERNAL_SECRET" \
|
|
63
|
+
-H "Content-Type: application/json" \
|
|
64
|
+
-d '{"user_external_id":"demo-user","plan_code":"pathovision_starter"}'
|
|
65
|
+
```
|
pnotp-0.1.0/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# PnotP
|
|
2
|
+
|
|
3
|
+
Unified API and Python client for PathoVision vision models.
|
|
4
|
+
|
|
5
|
+
## Packages
|
|
6
|
+
- `pnotp_api`: FastAPI service that wraps PathoVision ensembles under a consistent `/v1` surface with API-key auth.
|
|
7
|
+
- `pnotp`: Python client for calling the PnotP API.
|
|
8
|
+
|
|
9
|
+
## Install (client only)
|
|
10
|
+
```bash
|
|
11
|
+
pip install pnotp
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Install (client + server extra)
|
|
15
|
+
```bash
|
|
16
|
+
pip install "pnotp[server]"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage (client)
|
|
20
|
+
```python
|
|
21
|
+
import pnotp as pnp
|
|
22
|
+
|
|
23
|
+
client = pnp.client(api_key="YOUR_KEY") # default base URL is production
|
|
24
|
+
client.models()
|
|
25
|
+
model = client.models("pneumonia_binary_classification")
|
|
26
|
+
result = model.predict("image.jpg")
|
|
27
|
+
heatmap = model.attention_map("image.jpg")
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Set your key once per shell:
|
|
31
|
+
```bash
|
|
32
|
+
export PNOTP_API_KEY="your_api_key_here"
|
|
33
|
+
python your_script.py # pnp.client() will read the env var automatically
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Run the API locally
|
|
37
|
+
```bash
|
|
38
|
+
export PNOTP_INTERNAL_SECRET="dev-secret"
|
|
39
|
+
export PATHOVISION_ROOT="/absolute/path/to/PathoVision" # if not default
|
|
40
|
+
uvicorn pnotp_api.main:app --host 0.0.0.0 --port 8000
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Issue an API key (internal)
|
|
44
|
+
```bash
|
|
45
|
+
curl -X POST http://127.0.0.1:8000/internal/api-keys \
|
|
46
|
+
-H "X-Internal-Secret: $PNOTP_INTERNAL_SECRET" \
|
|
47
|
+
-H "Content-Type: application/json" \
|
|
48
|
+
-d '{"user_external_id":"demo-user","plan_code":"pathovision_starter"}'
|
|
49
|
+
```
|
pnotp-0.1.0/dev.db
ADDED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# P¬P Brand Identity Construction Guide
|
|
2
|
+
|
|
3
|
+
## Monogram Construction
|
|
4
|
+
|
|
5
|
+
The P¬P monogram is built on a 64×64px viewBox using geometric precision.
|
|
6
|
+
|
|
7
|
+
### Construction Grid
|
|
8
|
+
```
|
|
9
|
+
ViewBox: 0 0 64 64
|
|
10
|
+
Stroke width: 1.5px
|
|
11
|
+
Stroke linecap: square
|
|
12
|
+
Stroke linejoin: miter
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Element Coordinates
|
|
16
|
+
|
|
17
|
+
**P Shape (Inverted-L Bracket Skeleton):**
|
|
18
|
+
1. Left vertical stem: (18, 14) → (18, 50)
|
|
19
|
+
2. Top horizontal: (18, 14) → (38, 14)
|
|
20
|
+
3. Right vertical (P bowl): (38, 14) → (38, 32)
|
|
21
|
+
4. Bottom horizontal (P bowl): (38, 32) → (18, 32)
|
|
22
|
+
|
|
23
|
+
**Negation Mark (¬):**
|
|
24
|
+
1. Horizontal line: (42, 14) → (46, 14)
|
|
25
|
+
2. Vertical line: (42, 14) → (42, 18)
|
|
26
|
+
|
|
27
|
+
### Visual Representation
|
|
28
|
+
```
|
|
29
|
+
¬
|
|
30
|
+
┌───────┐
|
|
31
|
+
│ │
|
|
32
|
+
│ │ (P bowl)
|
|
33
|
+
├───────┘
|
|
34
|
+
│
|
|
35
|
+
│ (stem)
|
|
36
|
+
│
|
|
37
|
+
│
|
|
38
|
+
└
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Wordmark Construction
|
|
44
|
+
|
|
45
|
+
**Typography:**
|
|
46
|
+
- Font: Inter Medium (500 weight)
|
|
47
|
+
- Letter spacing: +2% (0.96px at 48px font size)
|
|
48
|
+
- Characters: P¬P (using Unicode ¬ character: U+00AC)
|
|
49
|
+
|
|
50
|
+
**Specifications:**
|
|
51
|
+
- Font family: Inter, system-ui, sans-serif
|
|
52
|
+
- Font weight: 500
|
|
53
|
+
- Letter spacing: 0.02em
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Icon Sizes
|
|
58
|
+
|
|
59
|
+
All icons use the same viewBox (0 0 64 64) but scale to different display sizes:
|
|
60
|
+
|
|
61
|
+
- **16×16px** - Favicons, small UI elements
|
|
62
|
+
- **32×32px** - Toolbar icons, small badges
|
|
63
|
+
- **64×64px** - Standard icons, medium usage
|
|
64
|
+
- **128×128px** - Large icons, app icons
|
|
65
|
+
- **256×256px** - High-resolution displays, app stores
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Color Variants
|
|
70
|
+
|
|
71
|
+
### Black Version
|
|
72
|
+
- Stroke: #000000
|
|
73
|
+
- Background: transparent or #FFFFFF
|
|
74
|
+
|
|
75
|
+
### White Version
|
|
76
|
+
- Stroke: #FFFFFF
|
|
77
|
+
- Background: #000000
|
|
78
|
+
|
|
79
|
+
### No other colors permitted
|
|
80
|
+
- Pure monochrome only
|
|
81
|
+
- Optional gray (#C6C6C6) for dividers only, never for logo
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Converting to Base64
|
|
86
|
+
|
|
87
|
+
### Method 1: Command Line
|
|
88
|
+
```bash
|
|
89
|
+
# For macOS/Linux
|
|
90
|
+
base64 -i monogram-black.svg -o monogram-black-base64.txt
|
|
91
|
+
|
|
92
|
+
# For Windows PowerShell
|
|
93
|
+
[Convert]::ToBase64String([IO.File]::ReadAllBytes("monogram-black.svg"))
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Method 2: Online Tools
|
|
97
|
+
1. Visit: https://base64.guru/converter/encode/image/svg
|
|
98
|
+
2. Upload the SVG file
|
|
99
|
+
3. Copy the Base64 output
|
|
100
|
+
|
|
101
|
+
### Method 3: JavaScript/Node
|
|
102
|
+
```javascript
|
|
103
|
+
const fs = require('fs');
|
|
104
|
+
const svg = fs.readFileSync('monogram-black.svg', 'utf8');
|
|
105
|
+
const base64 = Buffer.from(svg).toString('base64');
|
|
106
|
+
console.log(base64);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Usage in HTML/CSS
|
|
110
|
+
```html
|
|
111
|
+
<!-- As img src -->
|
|
112
|
+
<img src="data:image/svg+xml;base64,[YOUR_BASE64_HERE]" alt="P¬P Logo" />
|
|
113
|
+
|
|
114
|
+
<!-- As CSS background -->
|
|
115
|
+
<style>
|
|
116
|
+
.logo {
|
|
117
|
+
background-image: url('data:image/svg+xml;base64,[YOUR_BASE64_HERE]');
|
|
118
|
+
}
|
|
119
|
+
</style>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## File Inventory
|
|
125
|
+
|
|
126
|
+
### Monogram Files
|
|
127
|
+
- `monogram-black.svg` - Black stroke, transparent background
|
|
128
|
+
- `monogram-white.svg` - White stroke, transparent background
|
|
129
|
+
|
|
130
|
+
### Icon Files (All Black)
|
|
131
|
+
- `icon-16.svg` - 16×16px display size
|
|
132
|
+
- `icon-32.svg` - 32×32px display size
|
|
133
|
+
- `icon-64.svg` - 64×64px display size
|
|
134
|
+
- `icon-128.svg` - 128×128px display size
|
|
135
|
+
- `icon-256.svg` - 256×256px display size
|
|
136
|
+
|
|
137
|
+
### Wordmark Files
|
|
138
|
+
- `wordmark-black.svg` - Black text
|
|
139
|
+
- `wordmark-white.svg` - White text
|
|
140
|
+
|
|
141
|
+
### Lockup Files
|
|
142
|
+
- `horizontal-lockup-black.svg` - Monogram + wordmark, black
|
|
143
|
+
- `horizontal-lockup-white.svg` - Monogram + wordmark, white
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Technical Specifications
|
|
148
|
+
|
|
149
|
+
### Minimum Clear Space
|
|
150
|
+
- All sides: Equal to the height of the P stem (36px in a 64×64 viewBox)
|
|
151
|
+
- Ratio: Minimum 56% of logo height as clear space
|
|
152
|
+
|
|
153
|
+
### Minimum Size
|
|
154
|
+
- Digital: 16×16px
|
|
155
|
+
- Print: 0.5 inch (12.7mm)
|
|
156
|
+
|
|
157
|
+
### Stroke Weight
|
|
158
|
+
- Always: 1.5px at base viewBox
|
|
159
|
+
- Scales proportionally with size
|
|
160
|
+
- Never adjust stroke weight manually
|
|
161
|
+
|
|
162
|
+
### Export Settings
|
|
163
|
+
- Format: SVG (vector)
|
|
164
|
+
- Additional: PNG at 2400px width minimum for raster needs
|
|
165
|
+
- Color mode: RGB for digital, CMYK for print
|
|
166
|
+
- Background: Transparent
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Construction Principles
|
|
171
|
+
|
|
172
|
+
1. **Geometric Precision**: All coordinates are integers. No sub-pixel positioning.
|
|
173
|
+
2. **Right Angles Only**: No curves, no rounded corners.
|
|
174
|
+
3. **Mathematical Alignment**: Elements align to grid intersections.
|
|
175
|
+
4. **Minimal Strokes**: Constructed from 6 lines total.
|
|
176
|
+
5. **Binary Structure**: P and ¬P represent logical opposition.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Usage Notes
|
|
181
|
+
|
|
182
|
+
- The negation mark (¬) must always appear in the upper-right
|
|
183
|
+
- Maintain exact proportions when scaling
|
|
184
|
+
- Never distort, rotate, or add effects
|
|
185
|
+
- Use only in black or white—no color variants
|
|
186
|
+
- Preserve stroke width ratio when scaling
|
|
187
|
+
- Export at multiple sizes from the same base vector
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Quick Reference: Base Monogram SVG
|
|
192
|
+
|
|
193
|
+
```xml
|
|
194
|
+
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
195
|
+
<g stroke-width="1.5" stroke="#000000" stroke-linecap="square" stroke-linejoin="miter">
|
|
196
|
+
<line x1="18" y1="14" x2="18" y2="50" />
|
|
197
|
+
<line x1="18" y1="14" x2="38" y2="14" />
|
|
198
|
+
<line x1="38" y1="14" x2="38" y2="32" />
|
|
199
|
+
<line x1="38" y1="32" x2="18" y2="32" />
|
|
200
|
+
<line x1="42" y1="14" x2="46" y2="14" />
|
|
201
|
+
<line x1="42" y1="14" x2="42" y2="18" />
|
|
202
|
+
</g>
|
|
203
|
+
</svg>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
To change to white, replace `stroke="#000000"` with `stroke="#FFFFFF"`.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Platform-Specific Exports
|
|
211
|
+
|
|
212
|
+
### Favicon
|
|
213
|
+
Use `icon-32.svg` or convert to ICO format
|
|
214
|
+
|
|
215
|
+
### Social Media
|
|
216
|
+
- Twitter/X: 400×400px PNG (export from icon-256.svg)
|
|
217
|
+
- LinkedIn: 300×300px PNG
|
|
218
|
+
- Facebook: 180×180px PNG
|
|
219
|
+
|
|
220
|
+
### API/SDK
|
|
221
|
+
Use horizontal-lockup for documentation
|
|
222
|
+
Use monogram for API badges and small UI elements
|
|
223
|
+
|
|
224
|
+
### Presentations
|
|
225
|
+
Use horizontal-lockup-black.svg or horizontal-lockup-white.svg
|
|
226
|
+
Export at 2400px width for high-resolution displays
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg width="300" height="80" viewBox="0 0 300 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<!-- Monogram -->
|
|
3
|
+
<g transform="translate(20, 8)">
|
|
4
|
+
<g stroke-width="1.5" stroke="#000000" stroke-linecap="square" stroke-linejoin="miter">
|
|
5
|
+
<line x1="18" y1="14" x2="18" y2="50" />
|
|
6
|
+
<line x1="18" y1="14" x2="38" y2="14" />
|
|
7
|
+
<line x1="38" y1="14" x2="38" y2="32" />
|
|
8
|
+
<line x1="38" y1="32" x2="18" y2="32" />
|
|
9
|
+
<line x1="42" y1="14" x2="46" y2="14" />
|
|
10
|
+
<line x1="42" y1="14" x2="42" y2="18" />
|
|
11
|
+
</g>
|
|
12
|
+
</g>
|
|
13
|
+
|
|
14
|
+
<!-- Wordmark -->
|
|
15
|
+
<text x="120" y="50%" dominant-baseline="middle" font-family="Inter, system-ui, sans-serif" font-size="48" font-weight="500" fill="#000000" letter-spacing="0.96">P¬P</text>
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg width="300" height="80" viewBox="0 0 300 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<!-- Monogram -->
|
|
3
|
+
<g transform="translate(20, 8)">
|
|
4
|
+
<g stroke-width="1.5" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="miter">
|
|
5
|
+
<line x1="18" y1="14" x2="18" y2="50" />
|
|
6
|
+
<line x1="18" y1="14" x2="38" y2="14" />
|
|
7
|
+
<line x1="38" y1="14" x2="38" y2="32" />
|
|
8
|
+
<line x1="38" y1="32" x2="18" y2="32" />
|
|
9
|
+
<line x1="42" y1="14" x2="46" y2="14" />
|
|
10
|
+
<line x1="42" y1="14" x2="42" y2="18" />
|
|
11
|
+
</g>
|
|
12
|
+
</g>
|
|
13
|
+
|
|
14
|
+
<!-- Wordmark -->
|
|
15
|
+
<text x="120" y="50%" dominant-baseline="middle" font-family="Inter, system-ui, sans-serif" font-size="48" font-weight="500" fill="#FFFFFF" letter-spacing="0.96">P¬P</text>
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg width="128" height="128" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g stroke-width="1.5" stroke="#000000" stroke-linecap="square" stroke-linejoin="miter">
|
|
3
|
+
<line x1="18" y1="14" x2="18" y2="50" />
|
|
4
|
+
<line x1="18" y1="14" x2="38" y2="14" />
|
|
5
|
+
<line x1="38" y1="14" x2="38" y2="32" />
|
|
6
|
+
<line x1="38" y1="32" x2="18" y2="32" />
|
|
7
|
+
<line x1="42" y1="14" x2="46" y2="14" />
|
|
8
|
+
<line x1="42" y1="14" x2="42" y2="18" />
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg width="16" height="16" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g stroke-width="1.5" stroke="#000000" stroke-linecap="square" stroke-linejoin="miter">
|
|
3
|
+
<line x1="18" y1="14" x2="18" y2="50" />
|
|
4
|
+
<line x1="18" y1="14" x2="38" y2="14" />
|
|
5
|
+
<line x1="38" y1="14" x2="38" y2="32" />
|
|
6
|
+
<line x1="38" y1="32" x2="18" y2="32" />
|
|
7
|
+
<line x1="42" y1="14" x2="46" y2="14" />
|
|
8
|
+
<line x1="42" y1="14" x2="42" y2="18" />
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg width="256" height="256" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g stroke-width="1.5" stroke="#000000" stroke-linecap="square" stroke-linejoin="miter">
|
|
3
|
+
<line x1="18" y1="14" x2="18" y2="50" />
|
|
4
|
+
<line x1="18" y1="14" x2="38" y2="14" />
|
|
5
|
+
<line x1="38" y1="14" x2="38" y2="32" />
|
|
6
|
+
<line x1="38" y1="32" x2="18" y2="32" />
|
|
7
|
+
<line x1="42" y1="14" x2="46" y2="14" />
|
|
8
|
+
<line x1="42" y1="14" x2="42" y2="18" />
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg width="32" height="32" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g stroke-width="1.5" stroke="#000000" stroke-linecap="square" stroke-linejoin="miter">
|
|
3
|
+
<line x1="18" y1="14" x2="18" y2="50" />
|
|
4
|
+
<line x1="18" y1="14" x2="38" y2="14" />
|
|
5
|
+
<line x1="38" y1="14" x2="38" y2="32" />
|
|
6
|
+
<line x1="38" y1="32" x2="18" y2="32" />
|
|
7
|
+
<line x1="42" y1="14" x2="46" y2="14" />
|
|
8
|
+
<line x1="42" y1="14" x2="42" y2="18" />
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g stroke-width="1.5" stroke="#000000" stroke-linecap="square" stroke-linejoin="miter">
|
|
3
|
+
<line x1="18" y1="14" x2="18" y2="50" />
|
|
4
|
+
<line x1="18" y1="14" x2="38" y2="14" />
|
|
5
|
+
<line x1="38" y1="14" x2="38" y2="32" />
|
|
6
|
+
<line x1="38" y1="32" x2="18" y2="32" />
|
|
7
|
+
<line x1="42" y1="14" x2="46" y2="14" />
|
|
8
|
+
<line x1="42" y1="14" x2="42" y2="18" />
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
Binary file
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g stroke-width="1.5" stroke="#000000" stroke-linecap="square" stroke-linejoin="miter">
|
|
3
|
+
<!-- Left vertical stem -->
|
|
4
|
+
<line x1="18" y1="14" x2="18" y2="50" />
|
|
5
|
+
<!-- Top horizontal -->
|
|
6
|
+
<line x1="18" y1="14" x2="38" y2="14" />
|
|
7
|
+
<!-- Right vertical for P bowl -->
|
|
8
|
+
<line x1="38" y1="14" x2="38" y2="32" />
|
|
9
|
+
<!-- Bottom horizontal of P bowl -->
|
|
10
|
+
<line x1="38" y1="32" x2="18" y2="32" />
|
|
11
|
+
<!-- Negation mark (¬) in upper-right -->
|
|
12
|
+
<line x1="42" y1="14" x2="46" y2="14" />
|
|
13
|
+
<line x1="42" y1="14" x2="42" y2="18" />
|
|
14
|
+
</g>
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g stroke-width="1.5" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="miter">
|
|
3
|
+
<!-- Left vertical stem -->
|
|
4
|
+
<line x1="18" y1="14" x2="18" y2="50" />
|
|
5
|
+
<!-- Top horizontal -->
|
|
6
|
+
<line x1="18" y1="14" x2="38" y2="14" />
|
|
7
|
+
<!-- Right vertical for P bowl -->
|
|
8
|
+
<line x1="38" y1="14" x2="38" y2="32" />
|
|
9
|
+
<!-- Bottom horizontal of P bowl -->
|
|
10
|
+
<line x1="38" y1="32" x2="18" y2="32" />
|
|
11
|
+
<!-- Negation mark (¬) in upper-right -->
|
|
12
|
+
<line x1="42" y1="14" x2="46" y2="14" />
|
|
13
|
+
<line x1="42" y1="14" x2="42" y2="18" />
|
|
14
|
+
</g>
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="200" height="80" viewBox="0 0 200 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-family="Inter, system-ui, sans-serif" font-size="48" font-weight="500" fill="#000000" letter-spacing="0.96">P¬P</text>
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="200" height="80" viewBox="0 0 200 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-family="Inter, system-ui, sans-serif" font-size="48" font-weight="500" fill="#FFFFFF" letter-spacing="0.96">P¬P</text>
|
|
3
|
+
</svg>
|
|
Binary file
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Public entrypoint for the pnotp client library."""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
from .client import Client as _Client, DEFAULT_BASE_URL
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def client(api_key: str | None = None, base_url: str | None = None) -> _Client:
|
|
11
|
+
"""
|
|
12
|
+
Factory for the PnotP client.
|
|
13
|
+
|
|
14
|
+
If no api_key is provided, the loader will pull it from the environment
|
|
15
|
+
using (in order): PNOTP_API_KEY, pnotp_API_KEY.
|
|
16
|
+
The base URL defaults to the production endpoint unless explicitly overridden.
|
|
17
|
+
"""
|
|
18
|
+
resolved_key = api_key or os.getenv("PNOTP_API_KEY") or os.getenv("pnotp_API_KEY")
|
|
19
|
+
resolved_base = base_url or DEFAULT_BASE_URL
|
|
20
|
+
return _Client(api_key=resolved_key, base_url=resolved_base)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
__all__ = ["client"]
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import List, Optional, Union
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from .models import RemoteModel
|
|
8
|
+
|
|
9
|
+
DEFAULT_BASE_URL = "https://api.pnotp.ai/v1"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Client:
|
|
13
|
+
"""
|
|
14
|
+
Main PnotP client.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
import pnotp as pnp
|
|
18
|
+
client = pnp.client(api_key="API_KEY", base_url="http://127.0.0.1:8000/v1")
|
|
19
|
+
client.models() # list models
|
|
20
|
+
model = client.models("pneumonia_binary_classification")
|
|
21
|
+
result = model.predict("image.jpg")
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
api_key: str | None,
|
|
27
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
28
|
+
timeout: float = 30.0,
|
|
29
|
+
) -> None:
|
|
30
|
+
if not api_key:
|
|
31
|
+
raise ValueError("api_key is required. Pass it explicitly or set PNOTP_API_KEY.")
|
|
32
|
+
base = base_url.rstrip("/")
|
|
33
|
+
base_for_httpx = base if base.endswith("/") else f"{base}/"
|
|
34
|
+
|
|
35
|
+
self.api_key = api_key
|
|
36
|
+
self.base_url = base
|
|
37
|
+
self._http = httpx.Client(
|
|
38
|
+
base_url=base_for_httpx,
|
|
39
|
+
timeout=timeout,
|
|
40
|
+
headers={"X-API-Key": self.api_key},
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def close(self) -> None:
|
|
44
|
+
self._http.close()
|
|
45
|
+
|
|
46
|
+
def __enter__(self) -> "Client":
|
|
47
|
+
return self
|
|
48
|
+
|
|
49
|
+
def __exit__(self, exc_type, exc, tb) -> None:
|
|
50
|
+
self.close()
|
|
51
|
+
|
|
52
|
+
def models(
|
|
53
|
+
self,
|
|
54
|
+
model: Optional[str] = None,
|
|
55
|
+
) -> Union[List[str], RemoteModel]:
|
|
56
|
+
"""
|
|
57
|
+
- If called with no args: lists all available model ids.
|
|
58
|
+
- If `model` is provided: returns a RemoteModel handle.
|
|
59
|
+
"""
|
|
60
|
+
if model is None:
|
|
61
|
+
resp = self._http.get("models")
|
|
62
|
+
resp.raise_for_status()
|
|
63
|
+
data = resp.json() # {"models": [{...}, ...]}
|
|
64
|
+
|
|
65
|
+
model_ids = [m["id"] for m in data.get("models", [])]
|
|
66
|
+
|
|
67
|
+
print("You have access to the following models:")
|
|
68
|
+
for mid in model_ids:
|
|
69
|
+
print(f"- {mid}")
|
|
70
|
+
|
|
71
|
+
return model_ids
|
|
72
|
+
|
|
73
|
+
return RemoteModel(name=model, http_client=self._http)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
__all__ = ["Client", "DEFAULT_BASE_URL"]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Custom exceptions for the pnotp client."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PnotPError(Exception):
|
|
5
|
+
"""Base error for all pnotp client exceptions."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class VisionOnlyError(PnotPError):
|
|
9
|
+
"""Raised when attention maps are requested for non-vision models."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
__all__ = ["PnotPError", "VisionOnlyError"]
|
|
13
|
+
|