Skip to content

Commit 1f8fd02

Browse files
committed
Use all cpus for workers to run evaluators in parallel for supporting many pii detection calls at the same time and remove unsupported en piis
1 parent 948fc27 commit 1f8fd02

File tree

6 files changed

+91
-99
lines changed

6 files changed

+91
-99
lines changed

evaluators/presidio/langevals_presidio/pii_detection.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ class PresidioEntities(BaseModel):
3939
us_ssn: bool = False
4040
uk_nhs: bool = False
4141
sg_nric_fin: bool = False
42-
sg_uen: bool = False
4342
au_abn: bool = False
4443
au_acn: bool = False
4544
au_tfn: bool = False
@@ -49,7 +48,6 @@ class PresidioEntities(BaseModel):
4948
in_vehicle_registration: bool = False
5049
in_voter: bool = False
5150
in_passport: bool = False
52-
fi_personal_identity_code: bool = False
5351

5452

5553
class PresidioPIIDetectionSettings(EvaluatorSettings):

langevals/server.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
import dotenv
44

55
from langevals.utils import (
6+
get_cpu_count,
67
get_evaluator_classes,
78
get_evaluator_definitions,
89
load_evaluator_packages,
910
)
1011

1112
dotenv.load_dotenv()
1213

13-
import asyncio
1414
from fastapi import FastAPI, HTTPException, Request
1515
from typing import List, Optional
1616
from langevals_core.base_evaluator import (
@@ -106,16 +106,39 @@ def main():
106106
f.write(json.dumps(app.openapi(), indent=2))
107107
print("openapi.json exported")
108108
return
109-
from hypercorn.config import Config
110-
from hypercorn.asyncio import serve
109+
import gunicorn.app.base
110+
111+
class StandaloneApplication(gunicorn.app.base.BaseApplication):
112+
def __init__(self, app, options=None):
113+
self.options = options or {}
114+
self.application = app
115+
super().__init__()
116+
117+
def load_config(self):
118+
config = {key: value for key, value in self.options.items()
119+
if key in self.cfg.settings and value is not None} # type: ignore
120+
for key, value in config.items():
121+
self.cfg.set(key.lower(), value) # type: ignore
122+
123+
def load(self):
124+
return self.application
125+
111126

112127
host = "0.0.0.0"
113128
port = int(os.getenv("PORT", 8000))
129+
workers = get_cpu_count()
130+
131+
print(f"Starting server with {workers} workers")
114132

115-
config = Config()
116-
config.bind = [f"{host}:{port}"]
133+
options = {
134+
'bind': f'{host}:{port}',
135+
'workers': workers,
136+
'worker_class': 'uvicorn.workers.UvicornWorker',
137+
'preload_app': True,
138+
'forwarded_allow_ips': '*',
139+
}
117140

118-
asyncio.run(serve(app, config)) # type: ignore
141+
StandaloneApplication(app, options).run()
119142

120143

121144
if __name__ == "__main__":

langevals/utils.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import importlib
22
import importlib.metadata
3+
import math
4+
import os
35
import pkgutil
46
import re
57
import textwrap
@@ -99,3 +101,21 @@ def get_evaluator_definitions(evaluator_cls: BaseEvaluator):
99101
is_guardrail=is_guardrail,
100102
category=category,
101103
)
104+
105+
106+
def get_cpu_count():
107+
cpu_count = os.getenv("CPU_COUNT", None)
108+
if cpu_count is not None:
109+
return int(cpu_count)
110+
try:
111+
# Kubernetes
112+
with open("/sys/fs/cgroup/cpu/cpu.shares") as f:
113+
cpu_shares = int(f.read().strip())
114+
return max(1, math.ceil(cpu_shares / 1024))
115+
except FileNotFoundError:
116+
try:
117+
# Local for UNIX
118+
return len(os.sched_getaffinity(0))
119+
except AttributeError:
120+
# Local fallback
121+
return os.cpu_count() or 4

poetry.lock

Lines changed: 40 additions & 86 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ priority = "explicit"
1717
pytest = "^8.1.2"
1818
python = "^3.11"
1919
fastapi = "^0.110.0"
20-
hypercorn = "^0.16.0"
2120
pydantic = "^2.6.4"
2221
python-dotenv = "1.0.1"
2322
mangum = "^0.17.0"
2423
pandas = "^2.2.2"
2524
markdown = "^3.6"
25+
uvicorn = "^0.30.6"
26+
gunicorn = "^23.0.0"
2627
[[tool.poetry.dependencies.torch]]
2728
version = "^2.2.2+cpu"
2829
optional = true

ts-integration/evaluators.generated.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,6 @@ export type Evaluators = {
286286
us_ssn: boolean;
287287
uk_nhs: boolean;
288288
sg_nric_fin: boolean;
289-
sg_uen: boolean;
290289
au_abn: boolean;
291290
au_acn: boolean;
292291
au_tfn: boolean;
@@ -296,7 +295,6 @@ export type Evaluators = {
296295
in_vehicle_registration: boolean;
297296
in_voter: boolean;
298297
in_passport: boolean;
299-
fi_personal_identity_code: boolean;
300298
};
301299
min_threshold: number;
302300
};
@@ -897,7 +895,6 @@ social security numbers. It allows customization of the detection threshold and
897895
us_ssn: false,
898896
uk_nhs: false,
899897
sg_nric_fin: false,
900-
sg_uen: false,
901898
au_abn: false,
902899
au_acn: false,
903900
au_tfn: false,
@@ -907,7 +904,6 @@ social security numbers. It allows customization of the detection threshold and
907904
in_vehicle_registration: false,
908905
in_voter: false,
909906
in_passport: false,
910-
fi_personal_identity_code: false,
911907
},
912908
},
913909
min_threshold: {

0 commit comments

Comments
 (0)