offlineisbetter 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.
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: offlineisbetter
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Offline is better.
|
|
5
|
+
Author: offlineisbetter
|
|
6
|
+
Author-email: offlineisbetter <dev@offlineisbetter.com>
|
|
7
|
+
Requires-Dist: fastapi>=0.142.2
|
|
8
|
+
Requires-Dist: numpy>=2.5.3
|
|
9
|
+
Requires-Dist: onnxruntime>=1.30.0
|
|
10
|
+
Requires-Dist: requests>=2.34.2
|
|
11
|
+
Requires-Dist: tokenizers>=0.23.2
|
|
12
|
+
Requires-Dist: uvicorn>=0.54.0
|
|
13
|
+
Requires-Python: >=3.13
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# _offlineisbetter_
|
|
17
|
+
|
|
18
|
+
_More coming soon!_
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "offlineisbetter"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Offline is better."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"fastapi>=0.142.2",
|
|
9
|
+
"numpy>=2.5.3",
|
|
10
|
+
"onnxruntime>=1.30.0",
|
|
11
|
+
"requests>=2.34.2",
|
|
12
|
+
"tokenizers>=0.23.2",
|
|
13
|
+
"uvicorn>=0.54.0",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[[project.authors]]
|
|
17
|
+
name = "offlineisbetter"
|
|
18
|
+
email = "dev@offlineisbetter.com"
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
offlineisbetter = "offlineisbetter:main"
|
|
22
|
+
|
|
23
|
+
[build-system]
|
|
24
|
+
requires = ["uv_build>=0.12.19,<0.13.0"]
|
|
25
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "offlineisbetter"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Offline is better."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "offlineisbetter", email = "dev@offlineisbetter.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.13"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"fastapi>=0.142.2",
|
|
12
|
+
"numpy>=2.5.3",
|
|
13
|
+
"onnxruntime>=1.30.0",
|
|
14
|
+
"requests>=2.34.2",
|
|
15
|
+
"tokenizers>=0.23.2",
|
|
16
|
+
"uvicorn>=0.54.0",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[project.scripts]
|
|
20
|
+
offlineisbetter = "offlineisbetter:main"
|
|
21
|
+
|
|
22
|
+
[build-system]
|
|
23
|
+
requires = ["uv_build>=0.12.19,<0.13.0"]
|
|
24
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# offlineisbetter
|
|
2
|
+
# Copyright (c) 2026- offlineisbetter
|
|
3
|
+
#
|
|
4
|
+
# Server for offlineisbetter
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import requests
|
|
10
|
+
import sys
|
|
11
|
+
import tarfile
|
|
12
|
+
|
|
13
|
+
from fastapi import FastAPI
|
|
14
|
+
import onnxruntime as ort
|
|
15
|
+
import numpy as np
|
|
16
|
+
from tokenizers import Tokenizer
|
|
17
|
+
import uvicorn
|
|
18
|
+
|
|
19
|
+
# Global variables
|
|
20
|
+
model = None
|
|
21
|
+
tokenizer = None
|
|
22
|
+
classes = None
|
|
23
|
+
|
|
24
|
+
# Cache directory
|
|
25
|
+
CACHE_DIR = Path.home() / ".cache" / "offlineisbetter"
|
|
26
|
+
|
|
27
|
+
# API application
|
|
28
|
+
app = FastAPI()
|
|
29
|
+
|
|
30
|
+
def load_model(model_triple):
|
|
31
|
+
"""
|
|
32
|
+
Load a model from its triple.
|
|
33
|
+
"""
|
|
34
|
+
global model
|
|
35
|
+
global tokenizer
|
|
36
|
+
global classes
|
|
37
|
+
|
|
38
|
+
# Check if model exists already
|
|
39
|
+
checkpoint = CACHE_DIR / model_triple
|
|
40
|
+
tar = f"{model_triple}.tar"
|
|
41
|
+
check = os.path.exists(checkpoint)
|
|
42
|
+
|
|
43
|
+
if not check:
|
|
44
|
+
# Download release metadata
|
|
45
|
+
url = f"https://api.github.com/repos/offlineisbetter/offlineisbetter/releases/latest"
|
|
46
|
+
response = requests.get(url)
|
|
47
|
+
response.raise_for_status()
|
|
48
|
+
metadata = response.json()
|
|
49
|
+
|
|
50
|
+
# Find download URL
|
|
51
|
+
download_url = None
|
|
52
|
+
for asset in metadata.get("assets", []):
|
|
53
|
+
if asset["name"] == tar:
|
|
54
|
+
download_url = asset["browser_download_url"]
|
|
55
|
+
break
|
|
56
|
+
if download_url is None:
|
|
57
|
+
raise ValueError(f"invalid model triple '{model_triple}'")
|
|
58
|
+
|
|
59
|
+
# Stream to file
|
|
60
|
+
checkpoint.mkdir(parents=True, exist_ok=True)
|
|
61
|
+
with requests.get(download_url, stream=True) as r:
|
|
62
|
+
r.raise_for_status()
|
|
63
|
+
with open(CACHE_DIR / tar, "wb") as f:
|
|
64
|
+
for chunk in r.iter_content(chunk_size=8192):
|
|
65
|
+
f.write(chunk)
|
|
66
|
+
|
|
67
|
+
# Inflate the archive
|
|
68
|
+
with tarfile.open(CACHE_DIR / tar, "r:*") as tar:
|
|
69
|
+
tar.extractall(path=CACHE_DIR, filter="data")
|
|
70
|
+
|
|
71
|
+
# Load model
|
|
72
|
+
model = ort.InferenceSession(checkpoint / "model_quantized.pt", providers=["CPUExecutionProvider"])
|
|
73
|
+
tokenizer = Tokenizer.from_file(
|
|
74
|
+
str(checkpoint / "tokenizer.json")
|
|
75
|
+
)
|
|
76
|
+
with open(checkpoint / "offlineisbetter.json", "r") as f:
|
|
77
|
+
classes = json.load(f)
|
|
78
|
+
|
|
79
|
+
@app.post("/classify")
|
|
80
|
+
def offlineisbetter(data: dict):
|
|
81
|
+
"""
|
|
82
|
+
Run the offlineisbetter classification model.
|
|
83
|
+
"""
|
|
84
|
+
global model
|
|
85
|
+
global tokenizer
|
|
86
|
+
global classes
|
|
87
|
+
enc = tokenizer.encode(data["text"])
|
|
88
|
+
tok = {
|
|
89
|
+
"input_ids": np.array(enc.ids),
|
|
90
|
+
"attention_mask": np.array(enc.attention_mask),
|
|
91
|
+
}
|
|
92
|
+
results = model.run(None, tok)[0]
|
|
93
|
+
c = {v: k for k, v in classes.items()}
|
|
94
|
+
return {
|
|
95
|
+
"label": c[int(np.argmax(results))],
|
|
96
|
+
"text": data["text"],
|
|
97
|
+
"logits": [float(f) for f in results.flatten()],
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
def main():
|
|
101
|
+
"""
|
|
102
|
+
Run the offlineisbetter server.
|
|
103
|
+
"""
|
|
104
|
+
if len(sys.argv) < 4:
|
|
105
|
+
print(f"offlineisbetter [host] [port] [triple]")
|
|
106
|
+
return
|
|
107
|
+
|
|
108
|
+
# Get command line arguments
|
|
109
|
+
_, host, port, triple = sys.argv[:4]
|
|
110
|
+
try:
|
|
111
|
+
port = int(port)
|
|
112
|
+
except:
|
|
113
|
+
print(f"offlineisbetter [host] [port] [triple]")
|
|
114
|
+
print(f"[port] must be an integer")
|
|
115
|
+
|
|
116
|
+
# Load model
|
|
117
|
+
load_model(triple)
|
|
118
|
+
|
|
119
|
+
# Run
|
|
120
|
+
try:
|
|
121
|
+
uvicorn.run(app, host=host, port=port)
|
|
122
|
+
except:
|
|
123
|
+
print(f"offlineisbetter [host] [port] [triple]")
|
|
124
|
+
print(f"[host] must be a valid IP address")
|