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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -56
app.py CHANGED
@@ -1,15 +1,15 @@
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,69 +17,48 @@ import torch
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
- # โ”€โ”€โ”€ ุงู„ุณุคุงู„ ุงู„ู…ุจุงุดุฑ ู„ู„ู†ู…ูˆุฐุฌ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
23
- VQA_QUESTION = (
24
- "Is there a woman or any part of a woman's body in this image? "
25
- "Answer yes or no only."
26
- )
27
 
28
- # โ”€โ”€โ”€ ุชุญู…ูŠู„ ุงู„ู†ู…ูˆุฐุฌ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
29
  MODEL_DATA = {}
30
 
31
  @asynccontextmanager
32
  async def lifespan(app: FastAPI):
33
  print("๐Ÿ“ฅ Loading Florence-2-large...")
34
- start = time.time()
35
-
36
  MODEL_DATA["processor"] = AutoProcessor.from_pretrained(
37
- "microsoft/Florence-2-large",
38
  trust_remote_code=True
39
  )
40
  MODEL_DATA["model"] = AutoModelForCausalLM.from_pretrained(
41
- "microsoft/Florence-2-large",
42
- torch_dtype=torch.float32,
43
- trust_remote_code=True,
44
  attn_implementation="eager"
45
  ).eval()
46
-
47
- print(f"โœ… Model ready in {time.time()-start:.1f}s")
48
  yield
49
  MODEL_DATA.clear()
50
 
51
- # โ”€โ”€โ”€ FastAPI โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
52
- app = FastAPI(
53
- title="Female Detection API - VQA",
54
- description="Detects women in images using Florence-2-large VQA",
55
- version="2.0.0",
56
- lifespan=lifespan
57
- )
58
-
59
- @app.get("/health")
60
- def health():
61
- return {"status": "ok", "model_loaded": "model" in MODEL_DATA}
62
 
63
- # โ”€โ”€โ”€ POST /analyze โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
64
  @app.post("/analyze")
65
  async def analyze_image(file: UploadFile = File(...)):
66
-
67
  if not file.content_type.startswith("image/"):
68
- raise HTTPException(status_code=400, detail="ุงู„ู…ู„ู ุงู„ู…ุฑููˆุน ู„ูŠุณ ุตูˆุฑุฉ")
69
 
70
  try:
 
71
  image_bytes = await file.read()
72
  image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
73
- except Exception as e:
74
- raise HTTPException(status_code=400, detail=f"ุฎุทุฃ ููŠ ู‚ุฑุงุกุฉ ุงู„ุตูˆุฑุฉ: {str(e)}")
75
-
76
- try:
77
  processor = MODEL_DATA["processor"]
78
- model = MODEL_DATA["model"]
79
 
80
- task = "<VQA>"
 
81
  prompt = f"{task}{VQA_QUESTION}"
82
-
83
  inputs = processor(text=prompt, images=image, return_tensors="pt")
84
 
85
  start_time = time.time()
@@ -87,36 +66,41 @@ async def analyze_image(file: UploadFile = File(...)):
87
  generated_ids = model.generate(
88
  input_ids=inputs["input_ids"],
89
  pixel_values=inputs["pixel_values"],
90
- max_new_tokens=10,
91
- num_beams=1,
92
- do_sample=False
93
  )
94
 
95
- # โœ… ุงู„ุทุฑูŠู‚ุฉ ุงู„ุตุญูŠุญุฉ: ู†ูุณ ุฃุณู„ูˆุจ ุจุงู‚ูŠ ุงู„ู…ู‡ุงู…
96
  generated_text = processor.batch_decode(generated_ids, skip_special_tokens=False)[0]
97
- parsed = processor.post_process_generation(
98
- generated_text,
99
- task=task,
 
 
100
  image_size=(image.width, image.height)
101
  )
102
-
103
- # parsed ูŠุนูŠุฏ dict ู…ุซู„: {"<VQA>": "yes"} ุฃูˆ {"<VQA>": "no"}
104
- raw_answer = parsed.get(task, "").strip().lower()
105
- elapsed = round(time.time() - start_time, 2)
106
-
107
- decision = "block" if "yes" in raw_answer else "allow"
 
 
108
 
109
  return {
110
- "decision": decision,
111
- "vqa_answer": raw_answer,
112
- "question": VQA_QUESTION,
113
- "execution_time": elapsed,
114
- "status": "success"
115
  }
116
 
117
  except Exception as e:
118
- raise HTTPException(status_code=500, detail=f"ุฎุทุฃ ููŠ ุงู„ุงุณุชุฏู„ุงู„: {str(e)}")
119
 
 
 
 
120
 
121
  if __name__ == "__main__":
122
  import uvicorn
 
 
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
  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
  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