mwauranjorogekelvin commited on
Commit
c87f20d
Β·
verified Β·
1 Parent(s): 8cca8ae

Update app.py

Browse files

updates with quantization

Files changed (1) hide show
  1. app.py +23 -13
app.py CHANGED
@@ -20,7 +20,7 @@ logger = logging.getLogger(__name__)
20
 
21
  # ── Config ────────────────────────────────────────────────────────────────────
22
  API_KEY = os.environ.get("API_KEY", "changeme")
23
- DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
24
 
25
  # ── API Key Auth ──────────────────────────────────────────────────────────────
26
  api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
@@ -30,14 +30,19 @@ def verify_key(key: str = Security(api_key_header)):
30
  raise HTTPException(status_code=401, detail="Invalid or missing API key")
31
  return key
32
 
33
- # ── Model β€” loaded once from local folder ─────────────────────────────────────
34
  @lru_cache(maxsize=1)
35
  def load_model():
36
- logger.info(f"Loading model from ./model on {DEVICE}...")
37
  processor = TrOCRProcessor.from_pretrained('./model')
38
- model = VisionEncoderDecoderModel.from_pretrained('./model').to(DEVICE)
 
 
 
 
 
39
  model.eval()
40
- logger.info("βœ… Model ready")
41
  return processor, model
42
 
43
  # ── Schemas ───────────────────────────────────────────────────────────────────
@@ -60,7 +65,7 @@ app.add_middleware(
60
  allow_headers=["*"],
61
  )
62
 
63
- # ── Pre-warm on startup ───────────────────────────────────────────────────────
64
  @app.on_event("startup")
65
  async def startup():
66
  logger.info("Pre-warming model...")
@@ -74,31 +79,37 @@ def health():
74
  "status": "ok",
75
  "device": DEVICE,
76
  "model": "anuashok/ocr-captcha-v3 (local)",
77
- "quantized": False
78
  }
79
 
80
  @app.post("/solve-captcha-base64", response_model=SolveResponse)
81
  def solve(req: SolveRequest, _: str = Depends(verify_key)):
82
  start = time.time()
83
  try:
84
- # Decode image
85
  raw = req.image_base64
86
  if "," in raw:
87
  raw = raw.split(",", 1)[1]
88
 
89
  image = Image.open(io.BytesIO(base64.b64decode(raw))).convert("RGB")
90
 
91
- # Run inference
92
  processor, model = load_model()
93
  with torch.no_grad():
94
- pixel_values = processor(image, return_tensors="pt").pixel_values.to(DEVICE)
 
 
 
 
95
  generated_ids = model.generate(
96
  pixel_values,
97
  max_new_tokens=10,
98
  num_beams=1,
99
  do_sample=False
100
  )
101
- text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
 
 
 
 
102
 
103
  elapsed = time.time() - start
104
  logger.info(f"βœ… Solved: '{text}' in {elapsed:.2f}s")
@@ -117,6 +128,5 @@ def solve(req: SolveRequest, _: str = Depends(verify_key)):
117
  processing_time=time.time() - start
118
  )
119
 
120
- # ── Launch ────────────────────────────────────────────────────────────────────
121
  if __name__ == "__main__":
122
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
20
 
21
  # ── Config ────────────────────────────────────────────────────────────────────
22
  API_KEY = os.environ.get("API_KEY", "changeme")
23
+ DEVICE = "cpu" # quantized models only run on CPU
24
 
25
  # ── API Key Auth ──────────────────────────────────────────────────────────────
26
  api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
 
30
  raise HTTPException(status_code=401, detail="Invalid or missing API key")
31
  return key
32
 
33
+ # ── Model ─────────────────────────────────────────────────────────────────────
34
  @lru_cache(maxsize=1)
35
  def load_model():
36
+ logger.info("Loading quantized model from ./model...")
37
  processor = TrOCRProcessor.from_pretrained('./model')
38
+ model = VisionEncoderDecoderModel.from_pretrained('./model')
39
+ model = torch.quantization.quantize_dynamic(
40
+ model,
41
+ {torch.nn.Linear},
42
+ dtype=torch.qint8
43
+ )
44
  model.eval()
45
+ logger.info("βœ… Quantized model ready")
46
  return processor, model
47
 
48
  # ── Schemas ───────────────────────────────────────────────────────────────────
 
65
  allow_headers=["*"],
66
  )
67
 
68
+ # ── Startup ───────────────────────────────────────────────────────────────────
69
  @app.on_event("startup")
70
  async def startup():
71
  logger.info("Pre-warming model...")
 
79
  "status": "ok",
80
  "device": DEVICE,
81
  "model": "anuashok/ocr-captcha-v3 (local)",
82
+ "quantized": True
83
  }
84
 
85
  @app.post("/solve-captcha-base64", response_model=SolveResponse)
86
  def solve(req: SolveRequest, _: str = Depends(verify_key)):
87
  start = time.time()
88
  try:
 
89
  raw = req.image_base64
90
  if "," in raw:
91
  raw = raw.split(",", 1)[1]
92
 
93
  image = Image.open(io.BytesIO(base64.b64decode(raw))).convert("RGB")
94
 
 
95
  processor, model = load_model()
96
  with torch.no_grad():
97
+ pixel_values = processor(
98
+ image,
99
+ return_tensors="pt"
100
+ ).pixel_values
101
+
102
  generated_ids = model.generate(
103
  pixel_values,
104
  max_new_tokens=10,
105
  num_beams=1,
106
  do_sample=False
107
  )
108
+
109
+ text = processor.batch_decode(
110
+ generated_ids,
111
+ skip_special_tokens=True
112
+ )[0]
113
 
114
  elapsed = time.time() - start
115
  logger.info(f"βœ… Solved: '{text}' in {elapsed:.2f}s")
 
128
  processing_time=time.time() - start
129
  )
130
 
 
131
  if __name__ == "__main__":
132
+ uvicorn.run(app, host="0.0.0.0", port=7860)