skshimada commited on
Commit
993f3d0
·
verified ·
1 Parent(s): 6b342db

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +22 -18
app.py CHANGED
@@ -17,7 +17,6 @@ VISION_MODEL = "HuggingFaceTB/SmolVLM-Instruct"
17
 
18
  # --- SYSTEM INITIALIZATION ---
19
  print("⚙️ Loading Stable Vision Engine...")
20
- # We use float32 and CPU to ensure the app doesn't crash on the free tier
21
  vision_pipe = pipeline(
22
  "image-text-to-text",
23
  model=VISION_MODEL,
@@ -39,7 +38,11 @@ def get_bottle_crops(image_path):
39
  for box in r.boxes:
40
  if int(box.cls) == 39: # Bottle index
41
  x1, y1, x2, y2 = box.xyxy[0].tolist()
42
- found_crops.append(original_img.crop((x1-5, y1-5, x2+5, y2+5)))
 
 
 
 
43
  del yolo_model
44
  gc.collect()
45
  return found_crops
@@ -50,7 +53,6 @@ def get_bottle_crops(image_path):
50
  # --- RECIPE INGESTION ---
51
  def ingest_recipes(files):
52
  if not files: return "❌ No files uploaded."
53
-
54
  docs = []
55
  for f in files:
56
  try:
@@ -63,8 +65,7 @@ def ingest_recipes(files):
63
  except Exception as e:
64
  print(f"Error loading {f.name}: {e}")
65
 
66
- if not docs:
67
- return "❌ Could not extract text from files."
68
 
69
  vector_store = Chroma.from_documents(
70
  documents=docs,
@@ -83,20 +84,23 @@ def bartend(message, history, img_path, inventory):
83
  prompt_text = "User: <image>\nWhat is the brand and type of alcohol in this image? Answer briefly.\nAssistant:"
84
 
85
  try:
86
- output = vision_pipe(target_img, prompt=prompt_text, generate_kwargs={"max_new_tokens": 30})
87
  raw_label = output[0]['generated_text']
88
 
89
  if "Assistant:" in raw_label:
90
  inventory = raw_label.split("Assistant:")[-1].strip()
91
  else:
92
  inventory = raw_label.replace(prompt_text, "").strip()
 
 
 
93
  except Exception as e:
94
  print(f"Vision error: {e}")
95
  inventory = "Unknown Spirit"
96
 
97
  # 2. RAG (Recipe Search)
98
  recipe_context = ""
99
- if inventory and inventory != "Empty Shelf":
100
  try:
101
  if os.path.exists(CHROMA_PATH):
102
  vs = Chroma(persist_directory=CHROMA_PATH, embedding_function=embed_model)
@@ -107,20 +111,21 @@ def bartend(message, history, img_path, inventory):
107
  print(f"Search error: {e}")
108
 
109
  # 3. Create the Response
110
- if recipe_context:
111
- response = f"I see you have **{inventory}**. Here is a recipe I found in your collection:\n\n{recipe_context}"
 
 
112
  else:
113
- response = f"I see you have **{inventory}**! I don't have a specific recipe for that in the current library. Should I suggest a classic drink?"
114
 
115
- # --- UPDATED FOR NEW GRADIO FORMAT ---
116
- # We now use a dictionary format {role, content} instead of tuples
117
  history.append({"role": "user", "content": message})
118
  history.append({"role": "assistant", "content": response})
119
 
120
  return history, inventory
121
 
122
  # --- UI LAYOUT ---
123
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
124
  gr.Markdown("# 🍸 LocalAGI: The AI Sommelier")
125
  inv_state = gr.State("Empty Shelf")
126
 
@@ -133,17 +138,16 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
133
  img = gr.Image(type="filepath", label="2. Photo of your Bottle")
134
 
135
  with gr.Column(scale=2):
136
- # FIXED: Added type="messages" to tell Gradio we are using the new dictionary format
137
- chatbot = gr.Chatbot(height=500, label="Bartender Chat", type="messages")
138
  msg = gr.Textbox(label="3. Your Message", placeholder="Ask for a drink suggestion...")
139
  send_btn = gr.Button("Mix It Up", variant="primary")
140
 
141
  # Connect the buttons
142
  ingest_btn.click(ingest_recipes, file_up, status)
143
-
144
- # Connect Chat Events
145
  msg.submit(bartend, [msg, chatbot, img, inv_state], [chatbot, inv_state])
146
  send_btn.click(bartend, [msg, chatbot, img, inv_state], [chatbot, inv_state])
147
 
148
  if __name__ == "__main__":
149
- demo.launch()
 
 
17
 
18
  # --- SYSTEM INITIALIZATION ---
19
  print("⚙️ Loading Stable Vision Engine...")
 
20
  vision_pipe = pipeline(
21
  "image-text-to-text",
22
  model=VISION_MODEL,
 
38
  for box in r.boxes:
39
  if int(box.cls) == 39: # Bottle index
40
  x1, y1, x2, y2 = box.xyxy[0].tolist()
41
+ w, h = original_img.size
42
+ # Add margin for context
43
+ x1, y1 = max(0, x1 - 20), max(0, y1 - 20)
44
+ x2, y2 = min(w, x2 + 20), min(h, y2 + 20)
45
+ found_crops.append(original_img.crop((x1, y1, x2, y2)))
46
  del yolo_model
47
  gc.collect()
48
  return found_crops
 
53
  # --- RECIPE INGESTION ---
54
  def ingest_recipes(files):
55
  if not files: return "❌ No files uploaded."
 
56
  docs = []
57
  for f in files:
58
  try:
 
65
  except Exception as e:
66
  print(f"Error loading {f.name}: {e}")
67
 
68
+ if not docs: return "❌ Could not extract text."
 
69
 
70
  vector_store = Chroma.from_documents(
71
  documents=docs,
 
84
  prompt_text = "User: <image>\nWhat is the brand and type of alcohol in this image? Answer briefly.\nAssistant:"
85
 
86
  try:
87
+ output = vision_pipe(target_img, prompt=prompt_text, generate_kwargs={"max_new_tokens": 50})
88
  raw_label = output[0]['generated_text']
89
 
90
  if "Assistant:" in raw_label:
91
  inventory = raw_label.split("Assistant:")[-1].strip()
92
  else:
93
  inventory = raw_label.replace(prompt_text, "").strip()
94
+
95
+ inventory = re.sub(r'<.*?>', '', inventory).strip().split('.')[0]
96
+
97
  except Exception as e:
98
  print(f"Vision error: {e}")
99
  inventory = "Unknown Spirit"
100
 
101
  # 2. RAG (Recipe Search)
102
  recipe_context = ""
103
+ if inventory and inventory not in ["Empty Shelf", "Unknown Spirit", ""]:
104
  try:
105
  if os.path.exists(CHROMA_PATH):
106
  vs = Chroma(persist_directory=CHROMA_PATH, embedding_function=embed_model)
 
111
  print(f"Search error: {e}")
112
 
113
  # 3. Create the Response
114
+ if inventory == "Unknown Spirit":
115
+ response = "I'm having trouble reading that label. Try taking a closer photo of just the brand name."
116
+ elif recipe_context:
117
+ response = f"I see you have **{inventory}**. Here is a recipe from your collection:\n\n{recipe_context}"
118
  else:
119
+ response = f"I see you have **{inventory}**! I don't have a specific recipe for that in the library yet."
120
 
121
+ # Standard Dictionary Format for Gradio 6.0
 
122
  history.append({"role": "user", "content": message})
123
  history.append({"role": "assistant", "content": response})
124
 
125
  return history, inventory
126
 
127
  # --- UI LAYOUT ---
128
+ with gr.Blocks() as demo:
129
  gr.Markdown("# 🍸 LocalAGI: The AI Sommelier")
130
  inv_state = gr.State("Empty Shelf")
131
 
 
138
  img = gr.Image(type="filepath", label="2. Photo of your Bottle")
139
 
140
  with gr.Column(scale=2):
141
+ # FIXED LINE BELOW: Removed type="messages"
142
+ chatbot = gr.Chatbot(height=500, label="Bartender Chat")
143
  msg = gr.Textbox(label="3. Your Message", placeholder="Ask for a drink suggestion...")
144
  send_btn = gr.Button("Mix It Up", variant="primary")
145
 
146
  # Connect the buttons
147
  ingest_btn.click(ingest_recipes, file_up, status)
 
 
148
  msg.submit(bartend, [msg, chatbot, img, inv_state], [chatbot, inv_state])
149
  send_btn.click(bartend, [msg, chatbot, img, inv_state], [chatbot, inv_state])
150
 
151
  if __name__ == "__main__":
152
+ # Theme moved here for Gradio 6.0 compatibility
153
+ demo.launch(theme=gr.themes.Soft())