AdityaAjithKumar commited on
Commit
aed0fc2
·
1 Parent(s): c6b63dc

changed the model

Browse files
Files changed (2) hide show
  1. app.py +21 -34
  2. requirements.txt +2 -2
app.py CHANGED
@@ -1,30 +1,35 @@
1
  import logging
 
2
  from fastapi import FastAPI, UploadFile, File, Form
3
- from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
4
- from qwen_vl_utils import process_vision_info # pip install qwen-vl-utils
5
  from PIL import Image
6
- import io
7
  import torch
8
 
9
  logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s")
10
  logger = logging.getLogger(__name__)
11
 
12
- app = FastAPI(title="Qwen2.5-VL OCR API")
13
 
14
- # ✅ Use a vision-language model, NOT Qwen3.5-0.8B (text-only)
15
- model_id = "Qwen/Qwen2.5-VL-3B-Instruct"
16
 
17
  logger.info("=== LOADING MODEL ===")
18
- model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
19
  model_id,
20
- torch_dtype=torch.float32, # float16 if GPU
21
- device_map="cpu"
 
22
  )
23
- processor = AutoProcessor.from_pretrained(model_id)
24
  model.eval()
25
  logger.info("✅ Model loaded!")
26
 
27
 
 
 
 
 
 
28
  @app.get("/health")
29
  async def health():
30
  return {"status": "healthy", "model": model_id}
@@ -33,34 +38,16 @@ async def health():
33
  @app.post("/ocr")
34
  async def ocr(
35
  image: UploadFile = File(...),
36
- prompt: str = Form("Extract all text from this image accurately")
37
  ):
38
  logger.info(f"📸 OCR request | file: {image.filename}")
39
  try:
40
  img = Image.open(io.BytesIO(await image.read())).convert("RGB")
41
 
42
- messages = [{"role": "user", "content": [
43
- {"type": "image", "image": img},
44
- {"type": "text", "text": prompt}
45
- ]}]
46
-
47
- # ✅ Correct Qwen2.5-VL pipeline
48
- text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
49
- image_inputs, video_inputs = process_vision_info(messages)
50
-
51
- inputs = processor(
52
- text=[text],
53
- images=image_inputs,
54
- videos=video_inputs,
55
- return_tensors="pt"
56
- ).to("cpu")
57
 
58
  with torch.inference_mode():
59
- outputs = model.generate(**inputs, max_new_tokens=512, do_sample=False)
60
-
61
- # ✅ Decode only the newly generated tokens
62
- input_len = inputs["input_ids"].shape[1]
63
- response = processor.decode(outputs[0][input_len:], skip_special_tokens=True).strip()
64
 
65
  logger.info("✅ OCR done")
66
  return {"extracted_text": response}
@@ -70,6 +57,6 @@ async def ocr(
70
  return {"error": str(e)}
71
 
72
 
73
- @app.get("/")
74
- async def root():
75
- return {"message": "Qwen2.5-VL OCR API ready! Try POST /ocr"}
 
1
  import logging
2
+ import io
3
  from fastapi import FastAPI, UploadFile, File, Form
 
 
4
  from PIL import Image
5
+ from transformers import AutoModelForCausalLM, AutoTokenizer
6
  import torch
7
 
8
  logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s")
9
  logger = logging.getLogger(__name__)
10
 
11
+ app = FastAPI(title="Moondream2 OCR API")
12
 
13
+ model_id = "vikhyatk/moondream2"
14
+ revision = "2025-01-09" # pin to a stable release
15
 
16
  logger.info("=== LOADING MODEL ===")
17
+ model = AutoModelForCausalLM.from_pretrained(
18
  model_id,
19
+ revision=revision,
20
+ trust_remote_code=True,
21
+ torch_dtype=torch.float32,
22
  )
23
+ tokenizer = AutoTokenizer.from_pretrained(model_id, revision=revision)
24
  model.eval()
25
  logger.info("✅ Model loaded!")
26
 
27
 
28
+ @app.get("/")
29
+ async def root():
30
+ return {"message": "Moondream2 OCR API ready! POST /ocr"}
31
+
32
+
33
  @app.get("/health")
34
  async def health():
35
  return {"status": "healthy", "model": model_id}
 
38
  @app.post("/ocr")
39
  async def ocr(
40
  image: UploadFile = File(...),
41
+ prompt: str = Form("Extract all text from this image accurately.")
42
  ):
43
  logger.info(f"📸 OCR request | file: {image.filename}")
44
  try:
45
  img = Image.open(io.BytesIO(await image.read())).convert("RGB")
46
 
47
+ enc = model.encode_image(img)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
  with torch.inference_mode():
50
+ response = model.answer_question(enc, prompt, tokenizer)
 
 
 
 
51
 
52
  logger.info("✅ OCR done")
53
  return {"extracted_text": response}
 
57
  return {"error": str(e)}
58
 
59
 
60
+ if __name__ == "__main__":
61
+ import uvicorn
62
+ uvicorn.run("app:app", host="0.0.0.0", port=7860, reload=False)
requirements.txt CHANGED
@@ -2,6 +2,6 @@ fastapi
2
  uvicorn
3
  transformers
4
  pillow
5
- accelerate
6
  python-multipart
7
- qwen-vl-utils
 
 
2
  uvicorn
3
  transformers
4
  pillow
 
5
  python-multipart
6
+ einops # required by moondream2
7
+ torch --index-url https://download.pytorch.org/whl/cpu