AGAZO_Final_Assignment / botanical_classification_tool.py
Alexandre Gazola
codigo agente
f66d8b7
from langchain_core.tools import tool
@tool
def get_botanical_classification(item_name):
"""
Provides the botanical classification (fruit, vegetable, or other)
for a given food item, adhering to botanical definitions.
Args:
item_name (str): The name of the food item (e.g., "bell pepper", "sweet potato").
Returns:
dict: A dictionary containing:
- 'item': The normalized item name.
- 'botanical_category': 'fruit', 'vegetable', 'other', or 'unclassified'.
- 'botanical_part': The botanical part of the plant (e.g., 'matured ovary', 'root', 'leaf'),
or 'N/A' if not applicable/unknown.
- 'notes': Any additional botanical notes or clarifications.
"""
# --- Curated Botanical Database ---
# This dictionary holds the botanical classifications.
# It's crucial this data is accurate according to botanical science.
# You will need to expand this as needed for your full grocery list.
botanical_data = {
"sweet potatoes": {
"botanical_category": "vegetable",
"botanical_part": "root/tuber",
"notes": "Edible root of the plant."
},
"fresh basil": {
"botanical_category": "vegetable",
"botanical_part": "leaf",
"notes": "Edible leaves of the herb."
},
"plums": {
"botanical_category": "fruit",
"botanical_part": "matured ovary",
"notes": "Simple fleshy fruit (drupe)."
},
"green beans": {
"botanical_category": "fruit",
"botanical_part": "matured ovary (legume)",
"notes": "Botanically a fruit (legume) containing seeds."
},
"rice": {
"botanical_category": "fruit",
"botanical_part": "matured ovary (caryopsis)",
"notes": "A grain, which is botanically a dry fruit (caryopsis)."
},
"corn": {
"botanical_category": "fruit",
"botanical_part": "matured ovary (caryopsis)",
"notes": "A grain, which is botanically a dry fruit (caryopsis)."
},
"bell pepper": {
"botanical_category": "fruit",
"botanical_part": "matured ovary",
"notes": "Developed from the flower's ovary and contains seeds."
},
"whole allspice": { # Allspice berries
"botanical_category": "fruit",
"botanical_part": "dried berry",
"notes": "Dried unripe berries of the Pimenta dioica plant."
},
"acorns": {
"botanical_category": "fruit",
"botanical_part": "nut (type of dry fruit)",
"notes": "A nut, which is botanically a type of dry fruit."
},
"broccoli": {
"botanical_category": "vegetable",
"botanical_part": "flower/stem",
"notes": "Edible flower heads and stalks."
},
"celery": {
"botanical_category": "vegetable",
"botanical_part": "stem/petiole",
"notes": "Edible leaf stalks."
},
"zucchini": {
"botanical_category": "fruit",
"botanical_part": "matured ovary",
"notes": "A type of berry (pepo) from a flowering plant."
},
"lettuce": {
"botanical_category": "vegetable",
"botanical_part": "leaf",
"notes": "Edible leaves."
},
"peanuts": {
"botanical_category": "fruit",
"botanical_part": "legume (matured ovary)",
"notes": "Botanically a fruit (legume), despite growing underground."
},
# Non-plant items or items not strictly fruit/vegetable botanically
"milk": {
"botanical_category": "other",
"botanical_part": "N/A",
"notes": "Dairy product (animal)."
},
"eggs": {
"botanical_category": "other",
"botanical_part": "N/A",
"notes": "Animal product."
},
"flour": {
"botanical_category": "other",
"botanical_part": "N/A",
"notes": "Processed grain product (typically wheat, which is a fruit)."
},
"whole bean coffee": {
"botanical_category": "other", # The bean itself is a seed, not the entire fruit
"botanical_part": "seed",
"notes": "The coffee 'bean' is botanically the seed of the coffee cherry (a fruit)."
},
"oreos": {
"botanical_category": "other",
"botanical_part": "N/A",
"notes": "Processed food item."
}
}
# Normalize the input item name for lookup
normalized_item = item_name.strip().lower()
# Handle pluralization/singularization for common cases if not explicitly in data
# This is a simple approach; for more robustness, you'd need a proper NLP library.
if normalized_item.endswith("s") and normalized_item[:-1] in botanical_data:
normalized_item = normalized_item[:-1]
elif normalized_item + "s" in botanical_data:
# Check if the plural form exists if input is singular
if item_name.strip().lower() + "s" in botanical_data:
normalized_item = item_name.strip().lower() + "s"
# Retrieve classification
classification = botanical_data.get(normalized_item)
if classification:
return {
"item": item_name,
"botanical_category": classification["botanical_category"],
"botanical_part": classification["botanical_part"],
"notes": classification["notes"]
}
else:
# If the item is not found in the database
return {
"item": item_name,
"botanical_category": "unclassified",
"botanical_part": "N/A",
"notes": "Classification not found in the current database."
}
# --- Example Usage ---
if __name__ == "__main__":
grocery_list = [
"milk", "eggs", "flour", "whole bean coffee", "Oreos", "sweet potatoes",
"fresh basil", "plums", "green beans", "rice", "corn", "bell pepper",
"whole allspice", "acorns", "broccoli", "celery", "zucchini", "lettuce",
"peanuts"
]
botanical_fruits = []
botanical_vegetables = []
other_items = []
unclassified_items = []
print("--- Botanical Classifications ---")
for item in grocery_list:
classification = get_botanical_classification(item)
print(f"'{classification['item']}' -> Category: {classification['botanical_category']}, Part: {classification['botanical_part']} ({classification['notes']})")
if classification['botanical_category'] == 'fruit':
botanical_fruits.append(classification['item'])
elif classification['botanical_category'] == 'vegetable':
botanical_vegetables.append(classification['item'])
elif classification['botanical_category'] == 'other':
other_items.append(classification['item'])
else: # unclassified
unclassified_items.append(classification['item'])
print("\n--- Summary ---")
print(f"Botanical Fruits: {', '.join(sorted(botanical_fruits))}")
print(f"Botanical Vegetables: {', '.join(sorted(botanical_vegetables))}")
print(f"Other Groceries: {', '.join(sorted(other_items))}")
if unclassified_items:
print(f"Unclassified Items: {', '.join(sorted(unclassified_items))}")
print(get_botanical_classification('fresh basil'))