Liori25 commited on
Commit
7fa4837
·
verified ·
1 Parent(s): 1c97a89

Upload recipe_pipeline.py

Browse files
Files changed (1) hide show
  1. recipe_pipeline.py +130 -0
recipe_pipeline.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import base64
4
+ import io
5
+ from PIL import Image
6
+ from huggingface_hub import InferenceClient
7
+
8
+ # ==========================================
9
+ # RECIPE DIGITALIZER PIPELINE (Image -> JSON)
10
+ # ==========================================
11
+
12
+ class RecipeDigitalizerPipeline:
13
+ def __init__(self):
14
+ print("Connecting to Hugging Face API (Qwen Mode)...")
15
+ # Ensure HF_TOKEN is set in your environment
16
+ self.token = os.getenv("HF_TOKEN")
17
+
18
+ if not self.token:
19
+ print("⚠️ WARNING: HF_TOKEN is missing. The API call will likely fail.")
20
+
21
+ # --- WE ARE STICKING TO QWEN ---
22
+ # If 2.5 gives you trouble, you can try "Qwen/Qwen2-VL-7B-Instruct"
23
+ self.model_id = "Qwen/Qwen2.5-VL-7B-Instruct"
24
+
25
+ self.client = InferenceClient(token=self.token)
26
+
27
+ def compress_image(self, image_path):
28
+ """
29
+ Resizes the image so it doesn't crash the Free API.
30
+ """
31
+ with Image.open(image_path) as img:
32
+ if img.mode != 'RGB':
33
+ img = img.convert('RGB')
34
+
35
+ # Resize: Free API often rejects images larger than 1024x1024
36
+ max_size = 1024
37
+ if max(img.size) > max_size:
38
+ img.thumbnail((max_size, max_size))
39
+
40
+ # Save to memory as JPEG
41
+ buffer = io.BytesIO()
42
+ img.save(buffer, format="JPEG", quality=70) # Quality 70 is enough for text
43
+
44
+ # Convert to Base64
45
+ encoded_string = base64.b64encode(buffer.getvalue()).decode('utf-8')
46
+ return f"data:image/jpeg;base64,{encoded_string}"
47
+
48
+ def run_pipeline(self, image_path):
49
+ prompt = """Extract the recipe from this image.
50
+ Output strictly valid JSON with keys: title, ingredients (list), instructions (list), cuisine_type, difficulty.
51
+ Do not include markdown formatting like ```json, just the raw JSON."""
52
+
53
+ try:
54
+ # 1. Compress Image (Solves 400 Bad Request)
55
+ image_url = self.compress_image(image_path)
56
+
57
+ # 2. Call Qwen API
58
+ response = self.client.chat.completions.create(
59
+ model=self.model_id,
60
+ messages=[
61
+ {
62
+ "role": "user",
63
+ "content": [
64
+ {
65
+ "type": "image_url",
66
+ "image_url": {"url": image_url}
67
+ },
68
+ {"type": "text", "text": prompt}
69
+ ]
70
+ }
71
+ ],
72
+ max_tokens=1024
73
+ )
74
+
75
+ # 3. Clean Output
76
+ raw_text = response.choices[0].message.content
77
+ # Remove potential markdown fences
78
+ clean_json = raw_text.replace("```json", "").replace("```", "").strip()
79
+
80
+ # Extra safety: Find the first { and last }
81
+ start = clean_json.find('{')
82
+ end = clean_json.rfind('}') + 1
83
+ if start != -1 and end != -1:
84
+ clean_json = clean_json[start:end]
85
+
86
+ return json.loads(clean_json)
87
+
88
+ except Exception as e:
89
+ return {"error": f"Qwen API Error: {str(e)}"}
90
+
91
+ # --- PART 4: EXECUTION EXAMPLE ---
92
+
93
+ if __name__ == "__main__":
94
+
95
+ # 1. AUTHENTICATION FIX (For Colab / Local Env)
96
+ try:
97
+ # If running in Colab, try to fetch from secrets
98
+ try:
99
+ from google.colab import userdata
100
+ hf1_secret = userdata.get('HF_TOKEN')
101
+ os.environ["HF_TOKEN"] = hf1_secret
102
+ print(f"✅ Successfully loaded token from secret HF_TOKEN")
103
+ except ImportError:
104
+ # If running locally, assume env var is already set or manually set here
105
+ pass
106
+
107
+ except Exception as e:
108
+ print(f"⚠️ Warning: Could not load secret 'HF_TOKEN'. Make sure the name in the Key icon is exactly 'HF_TOKEN'.")
109
+ print(f"Error details: {e}")
110
+
111
+ # 2. INITIALIZE PIPELINE
112
+ try:
113
+ app = RecipeDigitalizerPipeline()
114
+
115
+ # 3. USER INPUT (Update this path to your actual image)
116
+ user_image = "Recipe.jfif"
117
+
118
+ # 4. RUN PIPELINE
119
+ if os.path.exists(user_image):
120
+ print(f"Processing {user_image}...")
121
+ ai_output = app.run_pipeline(user_image)
122
+
123
+ # 5. AI OUTPUT
124
+ print("\n--- FINAL DIGITAL OUTPUT ---")
125
+ print(json.dumps(ai_output, indent=4))
126
+ else:
127
+ print(f"❌ Error: Image not found at {user_image}")
128
+
129
+ except Exception as e:
130
+ print(f"❌ Application Error: {e}")