tdurzynski commited on
Commit
76aecb4
·
verified ·
1 Parent(s): f751af5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -68
app.py CHANGED
@@ -14,30 +14,34 @@ model = YOLO("yolov8n.pt") # Nano model for speed, fine-tune on food data later
14
  # Multi-label recognition model (placeholder - swap for fine-tuned multi-label later)
15
  recognizer = pipeline("image-classification", model=model)
16
 
17
- # Agent Definitions
18
  food_recognizer = AssistantAgent(
19
  name="FoodRecognizer",
20
- system_message="Identify all food items in the image and return a list of (label, probability) pairs."
 
21
  )
22
 
23
  size_estimator = AssistantAgent(
24
  name="SizeEstimator",
25
- system_message="Estimate portion sizes in grams for each recognized food based on the image."
 
26
  )
27
 
28
  nutrition_fetcher = AssistantAgent(
29
  name="NutritionFetcher",
30
- system_message="Fetch nutritional data from the Nutritionix API using the user's key."
 
31
  )
32
 
33
- advice_agent = AssistantAgent(
34
- name="NutritionAdvisor",
35
- system_message="Provide basic nutrition advice using the user's OpenAI/Grok key."
36
- )
37
 
38
  orchestrator = AssistantAgent(
39
  name="Orchestrator",
40
- system_message="Coordinate the workflow and format output."
 
41
  )
42
 
43
  group_chat = GroupChat(
@@ -80,89 +84,86 @@ def fetch_nutrition(foods_with_sizes, nutritionix_key):
80
  if not nutritionix_key:
81
  return "Please provide a Nutritionix API key for nutrition data."
82
 
 
83
  url = "https://trackapi.nutritionix.com/v2/natural/nutrients"
84
  headers = {
85
- "x-app-id": "your_nutritionix_app_id", # Your app ID in HF Secrets
86
- "x-app-key": nutritionix_key, # User's key
87
  "Content-Type": "application/json"
88
  }
89
  # Build query from foods and sizes
90
  query = "\n".join([f"{size}g {food}" for food, size in foods_with_sizes.items()])
91
  body = {"query": query}
92
 
93
- response = requests.post(url, headers=headers, json=body)
94
- if response.status_code != 200:
95
- return f"Nutritionix API error: {response.text}"
96
-
97
- data = response.json().get("foods", [])
98
- nutrition_data = {}
99
- for item in data:
100
- food_name = item["food_name"]
101
- nutrition_data[food_name] = {
102
- "calories": item.get("nf_calories", 0),
103
- "protein": item.get("nf_protein", 0),
104
- "fat": item.get("nf_total_fat", 0),
105
- "carbs": item.get("nf_total_carbohydrate", 0)
106
- }
107
- return nutrition_data
108
-
109
- def get_nutrition_advice(nutrition_data, llm_key):
110
- if not llm_key:
111
- return "No OpenAI/Grok key provided—skipping advice."
112
  try:
113
- openai.api_key = llm_key
114
- prompt = "Given this nutritional data, suggest a dietary tip:\n"
115
- for food, data in nutrition_data.items():
116
- prompt += f"- {food}: {data['calories']} cal, {data['protein']}g protein, {data['fat']}g fat, {data['carbs']}g carbs\n"
117
 
118
- response = openai.Completion.create(
119
- model="text-davinci-003", # Swap for Grok if xAI API is available
120
- prompt=prompt,
121
- max_tokens=50
122
- )
123
- return response.choices[0].text.strip()
 
 
 
 
 
 
 
 
124
  except Exception as e:
125
- return f"Error with LLM key: {str(e)}"
126
 
127
- def orchestrate_workflow(image, nutritionix_key, llm_key):
128
- # Step 1: Recognize foods
129
- foods = recognize_foods(image)
130
- if not foods:
131
- return "No foods recognized. Try a clearer image!", ""
132
-
133
- # Step 2: Estimate sizes
134
- sizes = estimate_sizes(image, foods)
135
-
136
- # Step 3: Fetch nutrition with user's Nutritionix key
137
- nutrition = fetch_nutrition({food: size for food, _ in foods}, nutritionix_key)
138
- if isinstance(nutrition, str): # Error message
139
- return nutrition, ""
140
-
141
- # Step 4: Generate advice with user's LLM key
142
- #advice = get_nutrition_advice(nutrition, llm_key)
 
 
 
 
 
143
 
144
- # Format output
145
- result = "Food Analysis:\n"
146
- for food, prob in foods:
147
- if food in nutrition:
148
- data = nutrition[food]
149
- result += (f"- {food} ({sizes[food]}g, {prob:.2%} confidence): "
150
- f"{data['calories']} cal, {data['protein']:.1f}g protein, "
151
- f"{data['fat']:.1f}g fat, {data['carbs']:.1f}g carbs\n")
152
 
153
- return result #, advice
 
 
 
154
 
 
155
  # Gradio Interface
156
  interface = gr.Interface(
157
  fn=orchestrate_workflow,
158
  inputs=[
159
  gr.Image(type="numpy", label="Upload a Food Photo"),
160
  gr.Textbox(type="password", label="Your Nutritionix API Key (required)"),
161
- gr.Textbox(type="password", label="Your OpenAI/Grok API Key (optional for advice)")
162
  ],
163
  outputs=[
164
  gr.Textbox(label="Nutrition Breakdown"),
165
- gr.Textbox(label="Nutrition Advice")
166
  ],
167
  title="Food Nutrition Analyzer",
168
  description="Upload a food photo and provide your Nutritionix API key. Add an OpenAI/Grok key for advice."
 
14
  # Multi-label recognition model (placeholder - swap for fine-tuned multi-label later)
15
  recognizer = pipeline("image-classification", model=model)
16
 
17
+ # AutoGen Agent Definitions
18
  food_recognizer = AssistantAgent(
19
  name="FoodRecognizer",
20
+ system_message="Identify all food items in the image and return a list of (label, probability) pairs.",
21
+ function_map={"recognize_foods": recognize_foods}
22
  )
23
 
24
  size_estimator = AssistantAgent(
25
  name="SizeEstimator",
26
+ system_message="Estimate portion sizes in grams for each recognized food based on the image.",
27
+ function_map={"estimate_sizes": estimate_sizes}
28
  )
29
 
30
  nutrition_fetcher = AssistantAgent(
31
  name="NutritionFetcher",
32
+ system_message="Fetch nutritional data from the Nutritionix API using the user's key.",
33
+ function_map={"fetch_nutrition": fetch_nutrition}
34
  )
35
 
36
+ ##advice_agent = AssistantAgent(
37
+ ## name="NutritionAdvisor",
38
+ ## system_message="Provide basic nutrition advice using the user's OpenAI/Grok key."
39
+ ##)
40
 
41
  orchestrator = AssistantAgent(
42
  name="Orchestrator",
43
+ system_message="Coordinate the workflow, format the output, and return the final result as text.",
44
+ function_map={}
45
  )
46
 
47
  group_chat = GroupChat(
 
84
  if not nutritionix_key:
85
  return "Please provide a Nutritionix API key for nutrition data."
86
 
87
+ start = time.time()
88
  url = "https://trackapi.nutritionix.com/v2/natural/nutrients"
89
  headers = {
90
+ "x-app-id": os.getenv("NUTRITIONIX_APP_ID"), # From HF Secrets
91
+ "x-app-key": nutritionix_key, # User's key
92
  "Content-Type": "application/json"
93
  }
94
  # Build query from foods and sizes
95
  query = "\n".join([f"{size}g {food}" for food, size in foods_with_sizes.items()])
96
  body = {"query": query}
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  try:
99
+ response = requests.post(url, headers=headers, json=body, timeout=10)
100
+ if response.status_code != 200:
101
+ return f"Nutritionix API error: {response.text}"
 
102
 
103
+ data = response.json().get("foods", [])
104
+ nutrition_data = {}
105
+ for item in data:
106
+ food_name = item["food_name"]
107
+ nutrition_data[food_name] = {
108
+ "calories": item.get("nf_calories", 0),
109
+ "protein": item.get("nf_protein", 0),
110
+ "fat": item.get("nf_total_fat", 0),
111
+ "carbs": item.get("nf_total_carbohydrate", 0)
112
+ }
113
+ print(f"Nutrition fetch took {time.time() - start:.2f}s")
114
+ return nutrition_data
115
+ except requests.Timeout:
116
+ return "Nutritionix API timed out."
117
  except Exception as e:
118
+ return f"Nutritionix error: {str(e)}"
119
 
120
+ #def get_nutrition_advice(nutrition_data, llm_key):
121
+ # if not llm_key:
122
+ # return "No OpenAI/Grok key provided—skipping advice."
123
+ # try:
124
+ # openai.api_key = llm_key
125
+ # prompt = "Given this nutritional data, suggest a dietary tip:\n"
126
+ # for food, data in nutrition_data.items():
127
+ # prompt += f"- {food}: {data['calories']} cal, {data['protein']}g protein, {data['fat']}g fat, {data['carbs']}g carbs\n"
128
+ #
129
+ # response = openai.Completion.create(
130
+ # model="text-davinci-003", # Swap for Grok if xAI API is available
131
+ # prompt=prompt,
132
+ # max_tokens=50
133
+ # )
134
+ # return response.choices[0].text.strip()
135
+ # except Exception as e:
136
+ # return f"Error with LLM key: {str(e)}"
137
+
138
+ # Orchestrator Logic (via AutoGen chat)
139
+ def orchestrate_workflow(image, nutritionix_key):
140
+ start = time.time()
141
 
142
+ # Initiate chat with Orchestrator, passing image and key as message
143
+ message = f"Process this image: {image} with Nutritionix key: {nutritionix_key}"
144
+ response = manager.initiate_chat(
145
+ orchestrator,
146
+ message=message,
147
+ max_turns=10
148
+ )
 
149
 
150
+ # Extract and format the final response from the chat
151
+ result = response[-1].get("content", "No output from agents.")
152
+ print(f"Total time: {time.time() - start:.2f}s")
153
+ return result
154
 
155
+
156
  # Gradio Interface
157
  interface = gr.Interface(
158
  fn=orchestrate_workflow,
159
  inputs=[
160
  gr.Image(type="numpy", label="Upload a Food Photo"),
161
  gr.Textbox(type="password", label="Your Nutritionix API Key (required)"),
162
+ #gr.Textbox(type="password", label="Your OpenAI/Grok API Key (optional for advice)")
163
  ],
164
  outputs=[
165
  gr.Textbox(label="Nutrition Breakdown"),
166
+ #gr.Textbox(label="Nutrition Advice")
167
  ],
168
  title="Food Nutrition Analyzer",
169
  description="Upload a food photo and provide your Nutritionix API key. Add an OpenAI/Grok key for advice."