hbatali2020 commited on
Commit
e55e1b4
ยท
verified ยท
1 Parent(s): 4762e5b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -43
app.py CHANGED
@@ -1,15 +1,15 @@
 
1
  import sys
2
  import types
3
  import importlib.util
4
 
5
- # โ”€โ”€โ”€ Mock flash_attn (ุถุฑูˆุฑูŠ ู„ู„ุชุดุบูŠู„ ุนู„ู‰ CPU ููŠ Hugging Face) โ”€โ”€โ”€โ”€โ”€โ”€โ”€
6
  flash_mock = types.ModuleType("flash_attn")
7
  flash_mock.__version__ = "2.0.0"
8
  flash_mock.__spec__ = importlib.util.spec_from_loader("flash_attn", loader=None)
9
  sys.modules["flash_attn"] = flash_mock
10
  sys.modules["flash_attn.flash_attn_interface"] = types.ModuleType("flash_attn.flash_attn_interface")
11
  sys.modules["flash_attn.bert_padding"] = types.ModuleType("flash_attn.bert_padding")
12
- # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
13
 
14
  import io
15
  import time
@@ -17,48 +17,56 @@ import torch
17
  from PIL import Image
18
  from transformers import AutoProcessor, AutoModelForCausalLM
19
  from fastapi import FastAPI, HTTPException, UploadFile, File
20
- from fastapi.responses import JSONResponse
21
  from contextlib import asynccontextmanager
22
 
23
- # ุงู„ุณุคุงู„ ุงู„ู…ูˆุฌู‡ ู„ู„ู†ู…ูˆุฐุฌ (ุชู… ุชุญุณูŠู†ู‡ ู„ูŠูƒูˆู† ุฃูƒุซุฑ ุฏู‚ุฉ)
24
- VQA_QUESTION = "Is there a woman, or any female body part like hair or skin in this image? Answer yes or no."
 
 
25
 
26
  MODEL_DATA = {}
27
 
28
  @asynccontextmanager
29
  async def lifespan(app: FastAPI):
30
  print("๐Ÿ“ฅ Loading Florence-2-large...")
 
31
  MODEL_DATA["processor"] = AutoProcessor.from_pretrained(
32
- "microsoft/Florence-2-large",
33
- trust_remote_code=True
34
  )
35
  MODEL_DATA["model"] = AutoModelForCausalLM.from_pretrained(
36
- "microsoft/Florence-2-large",
37
- trust_remote_code=True,
 
38
  attn_implementation="eager"
39
  ).eval()
40
- print("โœ… Model is ready!")
41
  yield
42
  MODEL_DATA.clear()
43
 
44
- app = FastAPI(title="Privacy Guard VQA", lifespan=lifespan)
 
 
 
 
45
 
46
  @app.post("/analyze")
47
  async def analyze_image(file: UploadFile = File(...)):
 
48
  if not file.content_type.startswith("image/"):
49
- raise HTTPException(status_code=400, detail="File is not an image")
 
 
 
 
 
50
 
51
  try:
52
- # ู‚ุฑุงุกุฉ ูˆู…ุนุงู„ุฌุฉ ุงู„ุตูˆุฑุฉ
53
- image_bytes = await file.read()
54
- image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
55
-
56
  processor = MODEL_DATA["processor"]
57
- model = MODEL_DATA["model"]
58
 
59
- # ุชุญุถูŠุฑ ุงู„ู…ุฏุฎู„ุงุช ู…ุน ู…ู‡ู…ุฉ VQA
60
- task = "<VQA>"
61
  prompt = f"{task}{VQA_QUESTION}"
 
62
  inputs = processor(text=prompt, images=image, return_tensors="pt")
63
 
64
  start_time = time.time()
@@ -66,41 +74,50 @@ async def analyze_image(file: UploadFile = File(...)):
66
  generated_ids = model.generate(
67
  input_ids=inputs["input_ids"],
68
  pixel_values=inputs["pixel_values"],
69
- max_new_tokens=50,
70
- num_beams=3 # ุฑูุน ุงู„ู€ beams ูŠุญุณู† ุฌูˆุฏุฉ "ุงู„ุชููƒูŠุฑ" ููŠ ุงู„ุณุคุงู„
 
71
  )
 
72
 
73
- # ููƒ ุงู„ุชุดููŠุฑ ุงู„ุฎุงู…
74
- generated_text = processor.batch_decode(generated_ids, skip_special_tokens=False)[0]
75
-
76
- # ุงู„ู…ุนุงู„ุฌุฉ ุงู„ุจุนุฏูŠุฉ ุงู„ุฐูƒูŠุฉ (ู‡ุฐู‡ ู‡ูŠ ุงู„ุฎุทูˆุฉ ุงู„ุชูŠ ูƒุงู†ุช ุชู†ู‚ุตูƒ)
77
- parsed_answer = processor.post_process_generation(
78
- generated_text,
79
- task=task,
80
  image_size=(image.width, image.height)
81
  )
82
-
83
- # ุงุณุชุฎุฑุงุฌ ุงู„ุฅุฌุงุจุฉ ุงู„ู†ุธูŠูุฉ (yes ุฃูˆ no)
84
- clean_answer = parsed_answer[task].strip().lower()
85
-
86
- # ุงุชุฎุงุฐ ุงู„ู‚ุฑุงุฑ
87
- # ู†ุณุชุฎุฏู… "yes" ูƒุดุฑุท ู„ู„ุญุฌุจุŒ ูˆุฃูŠ ุดูŠุก ุขุฎุฑ (ุฃูˆ ุฅุฐุง ุงุฑุชุจูƒ ุงู„ู†ู…ูˆุฐุฌ) ู†ุนุชุจุฑู‡ "allow"
88
- # ุฃูˆ ูŠู…ูƒู†ูƒ ุนูƒุณ ุงู„ู…ู†ุทู‚ ู„ูŠูƒูˆู† ุฃูƒุซุฑ ุชุดุฏุฏุงู‹
89
- decision = "block" if "yes" in clean_answer else "allow"
90
 
91
  return {
92
- "decision": decision,
93
- "vqa_answer": clean_answer,
94
- "execution_time": round(time.time() - start_time, 2),
 
 
 
 
 
 
 
 
 
 
95
  "status": "success"
96
  }
97
 
98
  except Exception as e:
99
- return JSONResponse(status_code=500, content={"error": str(e)})
100
 
101
- @app.get("/")
102
- def home():
103
- return {"status": "running", "question_active": VQA_QUESTION}
104
 
105
  if __name__ == "__main__":
106
  import uvicorn
 
1
+ # โ”€โ”€โ”€ flash_attn Mock โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
2
  import sys
3
  import types
4
  import importlib.util
5
 
 
6
  flash_mock = types.ModuleType("flash_attn")
7
  flash_mock.__version__ = "2.0.0"
8
  flash_mock.__spec__ = importlib.util.spec_from_loader("flash_attn", loader=None)
9
  sys.modules["flash_attn"] = flash_mock
10
  sys.modules["flash_attn.flash_attn_interface"] = types.ModuleType("flash_attn.flash_attn_interface")
11
  sys.modules["flash_attn.bert_padding"] = types.ModuleType("flash_attn.bert_padding")
12
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
13
 
14
  import io
15
  import time
 
17
  from PIL import Image
18
  from transformers import AutoProcessor, AutoModelForCausalLM
19
  from fastapi import FastAPI, HTTPException, UploadFile, File
 
20
  from contextlib import asynccontextmanager
21
 
22
+ VQA_QUESTION = (
23
+ "Is there a woman or any part of a woman's body in this image? "
24
+ "Answer yes or no only."
25
+ )
26
 
27
  MODEL_DATA = {}
28
 
29
  @asynccontextmanager
30
  async def lifespan(app: FastAPI):
31
  print("๐Ÿ“ฅ Loading Florence-2-large...")
32
+ start = time.time()
33
  MODEL_DATA["processor"] = AutoProcessor.from_pretrained(
34
+ "microsoft/Florence-2-large", trust_remote_code=True
 
35
  )
36
  MODEL_DATA["model"] = AutoModelForCausalLM.from_pretrained(
37
+ "microsoft/Florence-2-large",
38
+ torch_dtype=torch.float32,
39
+ trust_remote_code=True,
40
  attn_implementation="eager"
41
  ).eval()
42
+ print(f"โœ… Model ready in {time.time()-start:.1f}s")
43
  yield
44
  MODEL_DATA.clear()
45
 
46
+ app = FastAPI(lifespan=lifespan)
47
+
48
+ @app.get("/health")
49
+ def health():
50
+ return {"status": "ok", "model_loaded": "model" in MODEL_DATA}
51
 
52
  @app.post("/analyze")
53
  async def analyze_image(file: UploadFile = File(...)):
54
+
55
  if not file.content_type.startswith("image/"):
56
+ raise HTTPException(status_code=400, detail="ู„ูŠุณ ุตูˆุฑุฉ")
57
+
58
+ try:
59
+ image = Image.open(io.BytesIO(await file.read())).convert("RGB")
60
+ except Exception as e:
61
+ raise HTTPException(status_code=400, detail=str(e))
62
 
63
  try:
 
 
 
 
64
  processor = MODEL_DATA["processor"]
65
+ model = MODEL_DATA["model"]
66
 
67
+ task = "<VQA>"
 
68
  prompt = f"{task}{VQA_QUESTION}"
69
+
70
  inputs = processor(text=prompt, images=image, return_tensors="pt")
71
 
72
  start_time = time.time()
 
74
  generated_ids = model.generate(
75
  input_ids=inputs["input_ids"],
76
  pixel_values=inputs["pixel_values"],
77
+ max_new_tokens=10,
78
+ num_beams=1,
79
+ do_sample=False
80
  )
81
+ elapsed = round(time.time() - start_time, 2)
82
 
83
+ # โ”€โ”€โ”€ DEBUG: ู†ุฑู‰ ูƒู„ ุงู„ุตูŠุบ ุงู„ู…ู…ูƒู†ุฉ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
84
+ raw_with_special = processor.batch_decode(generated_ids, skip_special_tokens=False)[0]
85
+ raw_without_special = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
86
+
87
+ parsed = processor.post_process_generation(
88
+ raw_with_special,
89
+ task=task,
90
  image_size=(image.width, image.height)
91
  )
92
+
93
+ # ุงุณุชุฎุฑุงุฌ ุงู„ุฅุฌุงุจุฉ ู…ู† ูƒู„ ุงู„ุทุฑู‚
94
+ answer_from_parsed = parsed.get(task, "").strip().lower()
95
+ answer_from_raw = raw_without_special.strip().lower()
96
+
97
+ # ุงู„ู‚ุฑุงุฑ ุจู†ุงุกู‹ ุนู„ู‰ ุฃูุถู„ ู†ุชูŠุฌุฉ
98
+ best_answer = answer_from_parsed if answer_from_parsed else answer_from_raw
99
+ decision = "block" if "yes" in best_answer else "allow"
100
 
101
  return {
102
+ "decision": decision,
103
+ "best_answer": best_answer,
104
+
105
+ # DEBUG - ู„ู†ุฑู‰ ู…ุงุฐุง ูŠุนูŠุฏ ุงู„ู†ู…ูˆุฐุฌ ูุนู„ุงู‹
106
+ "debug": {
107
+ "raw_with_special": raw_with_special,
108
+ "raw_without_special": raw_without_special,
109
+ "parsed": str(parsed),
110
+ "answer_from_parsed": answer_from_parsed,
111
+ "answer_from_raw": answer_from_raw,
112
+ },
113
+
114
+ "execution_time": elapsed,
115
  "status": "success"
116
  }
117
 
118
  except Exception as e:
119
+ raise HTTPException(status_code=500, detail=str(e))
120
 
 
 
 
121
 
122
  if __name__ == "__main__":
123
  import uvicorn