Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion py/samples/menu/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,14 @@ build-backend = "hatchling.build"
requires = ["hatchling"]

[tool.hatch.build.targets.wheel]
packages = ["src/menu"]
packages = ["src"]

[tool.uv.sources]
genkit = { workspace = true }
genkit-plugin-dev-local-vectorstore = { workspace = true }
genkit-plugin-firebase = { workspace = true }
genkit-plugin-google-genai = { workspace = true }
genkit-plugin-google-cloud = { workspace = true }
genkit-plugin-ollama = { workspace = true }
genkit-plugin-vertex-ai = { workspace = true }

2 changes: 1 addition & 1 deletion py/samples/menu/src/case_02/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from .prompts import s02_dataMenuPrompt


@ai.flow(name='s02_menuQuestion')
@ai.flow(name='s02_menu_question')
async def s02_menuQuestionFlow(
my_input: MenuQuestionInputSchema,
) -> AnswerOutputSchema:
Expand Down
2 changes: 1 addition & 1 deletion py/samples/menu/src/case_03/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
)


@ai.flow(name='s03_multiTurnChat')
@ai.flow(name='s03_multi_turn_chat')
async def s03_multiTurnChatFlow(
my_input: ChatSessionInputSchema,
) -> ChatSessionOutputSchema:
Expand Down
14 changes: 12 additions & 2 deletions py/samples/menu/src/case_04/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#
# SPDX-License-Identifier: Apache-2.0

import json
import os

from menu_ai import ai
from menu_schemas import AnswerOutputSchema, MenuItemSchema, MenuQuestionInputSchema
from pydantic import BaseModel, Field
Expand All @@ -27,10 +30,17 @@ class IndexMenuItemsOutputSchema(BaseModel):
rows: int = Field(...)


@ai.flow(name='s04_indexMenuItems')
@ai.flow(name='s04_index_menu_items')
async def s04_indexMenuItemsFlow(
menu_items: list[MenuItemSchema],
) -> IndexMenuItemsOutputSchema:
# If empty list provided (e.g., from Dev UI default), load from example file
if not menu_items:
example_file = os.path.join(os.path.dirname(__file__), 'example.indexMenuItems.json')
with open(example_file, 'r') as f:
menu_data = json.load(f)
menu_items = [MenuItemSchema(**item) for item in menu_data]

documents = [
Document.from_text(f'{item.title} {item.price} \n {item.description}', metadata=item.model_dump())
for item in menu_items
Expand All @@ -43,7 +53,7 @@ async def s04_indexMenuItemsFlow(
return IndexMenuItemsOutputSchema(rows=len(menu_items))


@ai.flow(name='s04_ragMenuQuestion')
@ai.flow(name='s04_rag_menu_question')
async def s04_ragMenuQuestionFlow(
my_input: MenuQuestionInputSchema,
) -> AnswerOutputSchema:
Expand Down
16 changes: 10 additions & 6 deletions py/samples/menu/src/case_05/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import os

from case_05.prompts import s05_readMenuPrompt, s05_textMenuPrompt
from constants import DEFAULT_MENU_QUESTION
from menu_ai import ai
from menu_schemas import (
AnswerOutputSchema,
Expand All @@ -27,32 +28,35 @@
)


@ai.flow(name='s05_readMenu')
@ai.flow(name='s05_read_menu')
async def s05_readMenuFlow(_: None = None) -> str:
image_data_url = inline_data_url('menu.jpeg', 'image/jpeg')
response = await s05_readMenuPrompt({'imageUrl': image_data_url})
return response.text


@ai.flow(name='s05_textMenuQuestion')
@ai.flow(name='s05_text_menu_question')
async def s05_textMenuQuestionFlow(
my_input: TextMenuQuestionInputSchema,
) -> AnswerOutputSchema:
response = await s05_textMenuPrompt({'menuText': my_input.menuText, 'question': my_input.question})
response = await s05_textMenuPrompt({'menuText': my_input.menu_text, 'question': my_input.question})
return AnswerOutputSchema(
answer=response.text,
)


@ai.flow(name='s05_visionMenuQuestion')
@ai.flow(name='s05_vision_menu_question')
async def s05_visionMenuQuestionFlow(
my_input: MenuQuestionInputSchema,
) -> AnswerOutputSchema:
# If empty question provided (e.g., from Dev UI default), use the default question
question = my_input.question if my_input.question else DEFAULT_MENU_QUESTION

menu_text = await s05_readMenuFlow()
return await s05_textMenuQuestionFlow(
TextMenuQuestionInputSchema(
question=my_input.question,
menuText=menu_text,
question=question,
menu_text=menu_text,
)
)

Expand Down
36 changes: 36 additions & 0 deletions py/samples/menu/src/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

"""Constants used across the menu sample."""

# Default question for menu-related flows
DEFAULT_MENU_QUESTION = 'What kind of burger buns do you have?'

# Default menu text for text-based menu flows
DEFAULT_MENU_TEXT = """APPETIZERS
- Mozzarella Sticks $8 - Crispy fried mozzarella sticks served with marinara sauce
- Chicken Wings $10 - Crispy fried chicken wings tossed in your choice of sauce
- Nachos $12 - Crispy tortilla chips topped with melted cheese, chili, sour cream, and salsa

BURGERS & SANDWICHES
- Classic Cheeseburger $12 - A juicy beef patty topped with melted American cheese, lettuce, tomato, and onion on a toasted bun
- Bacon Cheeseburger $14 - A classic cheeseburger with the addition of crispy bacon
- Mushroom Swiss Burger $15 - A beef patty topped with sautéed mushrooms, melted Swiss cheese, and a creamy horseradish sauce
- Chicken Sandwich $13 - A crispy chicken breast on a toasted bun with lettuce, tomato, and your choice of sauce

SALADS
- House Salad $8 - Mixed greens with your choice of dressing
- Caesar Salad $9 - Romaine lettuce with croutons, Parmesan cheese, and Caesar dressing"""
8 changes: 7 additions & 1 deletion py/samples/menu/src/menu_ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@
from genkit.plugins.google_genai import GoogleAI

if 'GEMINI_API_KEY' not in os.environ:
os.environ['GEMINI_API_KEY'] = input('Please enter your GEMINI_API_KEY: ')
raise ValueError(
'GEMINI_API_KEY environment variable is required to run this sample.\n'
'Please set it before starting the application:\n'
' export GEMINI_API_KEY=your_api_key_here\n'
'You can get an API key from https://aistudio.google.com/'
)


ai = Genkit(plugins=[GoogleAI()])

Expand Down
11 changes: 8 additions & 3 deletions py/samples/menu/src/menu_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# SPDX-License-Identifier: Apache-2.0


from constants import DEFAULT_MENU_QUESTION, DEFAULT_MENU_TEXT
from pydantic import BaseModel, Field


Expand All @@ -29,7 +30,7 @@ class MenuItemSchema(BaseModel):
class MenuQuestionInputSchema(BaseModel):
"""Input schema for the menu question prompt."""

question: str = Field(..., description='A question about the menu')
question: str = Field(default=DEFAULT_MENU_QUESTION, description='A question about the menu')


class AnswerOutputSchema(BaseModel):
Expand All @@ -48,8 +49,12 @@ class DataMenuQuestionInputSchema(BaseModel):
class TextMenuQuestionInputSchema(BaseModel):
"""Input schema for the text menu question prompt."""

menu_text: str = Field(...)
question: str = Field(..., description='A question about the menu')
menu_text: str = Field(
default=DEFAULT_MENU_TEXT,
description='The menu text content',
alias='menuText',
)
question: str = Field(default=DEFAULT_MENU_QUESTION, description='A question about the menu')


class MenuToolOutputSchema(BaseModel):
Expand Down
Loading