What's next for Alexa+ (voice/ Ai agent code in python
"""Pantry Pal - Alexa+ skill (Python, ask-sdk-core). Deploy as AWS Lambda.""" from ask_sdk_core.skill_builder import SkillBuilder from ask_sdk_core.dispatch_components import ( AbstractRequestHandler, AbstractExceptionHandler) from ask_sdk_core.utils import is_request_type, is_intent_name, get_slot_value from pantry import Pantry
sb = SkillBuilder()
def pantry_for(h): return Pantry(h.request_envelope.session.user.user_id)
def say(h, text, end=False): r = h.response_builder.speak(text) if not end: r = r.ask("What would you like to do next?") return r.response
def join(words): return ", ".join(words[:-1]) + " and " + words[-1] if len(words) > 1 else words[0]
class Launch(AbstractRequestHandler): def can_handle(self, h): return is_request_type("LaunchRequest")(h) def handle(self, h): return say(h, "Welcome to Pantry Pal. Tell me what you bought, " "or ask what to cook today.")
class AddItem(AbstractRequestHandler): def can_handle(self, h): return is_intent_name("AddItemIntent")(h) def handle(self, h): item = get_slot_value(h.request_envelope, "item") days = get_slot_value(h.request_envelope, "days") or 7 if not item: return say(h, "Which item should I add?") pantry_for(h).add(item, days) return say(h, f"Added {item}. I'll flag it when it's close to expiring " f"in about {days} days.")
class RemoveItem(AbstractRequestHandler): def can_handle(self, h): return is_intent_name("RemoveItemIntent")(h) def handle(self, h): item = get_slot_value(h.request_envelope, "item") or "" ok = pantry_for(h).remove(item) return say(h, f"Removed {item}." if ok else f"I couldn't find {item}.")
class ListItems(AbstractRequestHandler): def can_handle(self, h): return is_intent_name("ListPantryIntent")(h) def handle(self, h): names = [i["name"] for i in pantry_for(h).items] if not names: return say(h, "Your pantry is empty.") return say(h, f"You have {join(names)}.")
class Expiring(AbstractRequestHandler): def can_handle(self, h): return is_intent_name("ExpiringIntent")(h) def handle(self, h): p = pantry_for(h) soon = p.expiring() if not soon: return say(h, "Nothing is expiring soon. Nice!") parts = [f"{i['name']} in {max(p.days_left(i), 0)} days" for i in soon] return say(h, f"Use these soon: {join(parts)}.")
class Recipe(AbstractRequestHandler): def can_handle(self, h): return is_intent_name("SuggestRecipeIntent")(h) def handle(self, h): s = pantry_for(h).suggest() if not s: return say(h, "Add a few more items and I'll suggest a recipe.") name, missing = s extra = f" You're missing {join(missing)}." if missing else " You have everything!" return say(h, f"Try {name}.{extra}")
class Help(AbstractRequestHandler): def can_handle(self, h): return is_intent_name("AMAZON.HelpIntent")(h) def handle(self, h): return say(h, "Say: add tomato for 3 days, what's expiring, " "what's in my pantry, or what should I cook.")
class Stop(AbstractRequestHandler): def can_handle(self, h): return (is_intent_name("AMAZON.StopIntent")(h) or is_intent_name("AMAZON.CancelIntent")(h)) def handle(self, h): return say(h, "Goodbye!", end=True)
class Fallback(AbstractRequestHandler): def can_handle(self, h): return is_intent_name("AMAZON.FallbackIntent")(h) def handle(self, h): return say(h, "Sorry, I didn't get that. Try asking for help.")
class SessionEnded(AbstractRequestHandler): def can_handle(self, h): return is_request_type("SessionEndedRequest")(h) def handle(self, h): return h.response_builder.response
class Errors(AbstractExceptionHandler): def can_handle(self, h, e): return True def handle(self, h, e): print(repr(e)) return say(h, "Something went wrong. Please try again.")
for c in (Launch, AddItem, RemoveItem, ListItems, Expiring, Recipe, Help, Stop, Fallback, SessionEnded): sb.add_request_handler(c()) sb.add_exception_handler(Errors()) lambda_handler = sb.lambda_handler() """Core logic for Pantry Pal - pure Python, no Alexa dependency, easy to test.""" import os import json import datetime as dt
RECIPES = { "egg fried rice": {"rice", "egg", "onion"}, "veg omelette": {"egg", "onion", "tomato"}, "tomato pasta": {"pasta", "tomato", "garlic"}, "paneer bhurji": {"paneer", "onion", "tomato"}, "aloo paratha": {"potato", "flour", "onion"}, "cheese sandwich": {"bread", "cheese", "tomato"}, "dal tadka": {"dal", "onion", "tomato", "garlic"}, }
class MemoryStore: _data = {}
def load(self, uid):
return self._data.get(uid, [])
def save(self, uid, items):
self._data[uid] = items
class DynamoStore: """Used automatically when env var PANTRY_TABLE is set (partition key: uid)."""
def __init__(self, table_name):
import boto3
self.table = boto3.resource("dynamodb").Table(table_name)
def load(self, uid):
r = self.table.get_item(Key={"uid": uid}).get("Item")
return json.loads(r["items"]) if r else []
def save(self, uid, items):
self.table.put_item(Item={"uid": uid, "items": json.dumps(items)})
def get_store(): t = os.environ.get("PANTRY_TABLE") return DynamoStore(t) if t else MemoryStore()
class Pantry: def init(self, uid, store=None, today=None): self.uid, self.store = uid, store or get_store() self.today = today or dt.date.today() self.items = self.store.load(uid)
def add(self, name, days=7):
name = name.lower().strip()
self.items = [i for i in self.items if i["name"] != name]
exp = (self.today + dt.timedelta(days=int(days))).isoformat()
self.items.append({"name": name, "expires": exp})
self.store.save(self.uid, self.items)
return exp
def remove(self, name):
name = name.lower().strip()
before = len(self.items)
self.items = [i for i in self.items if i["name"] != name]
self.store.save(self.uid, self.items)
return len(self.items) < before
def days_left(self, item):
return (dt.date.fromisoformat(item["expires"]) - self.today).days
def expiring(self, within=2):
return sorted(
(i for i in self.items if self.days_left(i) <= within),
key=self.days_left,
)
def suggest(self):
"""Best recipe: most ingredients owned, expiring items weigh extra."""
have = {i["name"] for i in self.items}
urgent = {i["name"] for i in self.expiring()}
best = None
for name, need in RECIPES.items():
got = need & have
if len(got) < 2:
continue
score = len(got) / len(need) + 0.5 * len(got & urgent)
if best is None or score > best[0]:
best = (score, name, need - have)
return (best[1], sorted(best[2])) if best else None
Built With
- hindi
- python
Log in or sign up for Devpost to join the conversation.