diff --git a/py/packages/genkit/src/genkit/blocks/prompt.py b/py/packages/genkit/src/genkit/blocks/prompt.py index 6bd8dfe242..1778b69802 100644 --- a/py/packages/genkit/src/genkit/blocks/prompt.py +++ b/py/packages/genkit/src/genkit/blocks/prompt.py @@ -1008,7 +1008,10 @@ async def create_prompt_from_file(): 'type': 'prompt', 'lazy': True, 'source': 'file', - '_async_factory': create_prompt_from_file, + 'prompt': { + 'name': name, + 'variant': variant or '', + }, } # Create two separate action functions : diff --git a/py/pyproject.toml b/py/pyproject.toml index 3c6960da0e..2e03a106a9 100644 --- a/py/pyproject.toml +++ b/py/pyproject.toml @@ -113,6 +113,8 @@ genkit-plugin-ollama = { workspace = true } genkit-plugin-vertex-ai = { workspace = true } google-genai-hello = { workspace = true } google-genai-image = { workspace = true } +prompt-demo = { workspace = true } + [tool.uv.workspace] members = ["packages/*", "plugins/*", "samples/*"] diff --git a/py/samples/prompt_demo/data/_shared_partial.prompt b/py/samples/prompt_demo/data/_shared_partial.prompt new file mode 100644 index 0000000000..4a0b1623b4 --- /dev/null +++ b/py/samples/prompt_demo/data/_shared_partial.prompt @@ -0,0 +1,4 @@ +--- +model: googleai/gemini-1.5-flash +--- +This is a PARTIAL that says: {{my_helper "Partial content with helper"}} diff --git a/py/samples/prompt_demo/data/dot.name.test.prompt b/py/samples/prompt_demo/data/dot.name.test.prompt new file mode 100644 index 0000000000..d92138d493 --- /dev/null +++ b/py/samples/prompt_demo/data/dot.name.test.prompt @@ -0,0 +1 @@ +Hello {{name}}, I am a dot name test! diff --git a/py/samples/prompt_demo/data/hello.prompt b/py/samples/prompt_demo/data/hello.prompt new file mode 100644 index 0000000000..6cb905fab4 --- /dev/null +++ b/py/samples/prompt_demo/data/hello.prompt @@ -0,0 +1 @@ +Hello {{name}}! diff --git a/py/samples/prompt_demo/data/hello.variant.prompt b/py/samples/prompt_demo/data/hello.variant.prompt new file mode 100644 index 0000000000..508ee21263 --- /dev/null +++ b/py/samples/prompt_demo/data/hello.variant.prompt @@ -0,0 +1 @@ +Hola {{name}}! diff --git a/py/samples/prompt_demo/data/nested/nested_hello.prompt b/py/samples/prompt_demo/data/nested/nested_hello.prompt new file mode 100644 index 0000000000..f2b4e13366 --- /dev/null +++ b/py/samples/prompt_demo/data/nested/nested_hello.prompt @@ -0,0 +1,9 @@ +--- +model: googleai/gemini-1.5-flash +input: + schema: + name: string +--- + +This is a nested prompt, hello {{name}}! +{{> shared_partial}} diff --git a/py/samples/prompt_demo/pyproject.toml b/py/samples/prompt_demo/pyproject.toml new file mode 100644 index 0000000000..37ef4a2eda --- /dev/null +++ b/py/samples/prompt_demo/pyproject.toml @@ -0,0 +1,55 @@ +# Copyright 2025 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 + +[project] +authors = [{ name = "Google" }] +classifiers = [ + "Development Status :: 3 - Alpha", + "Environment :: Console", + "Environment :: Web Environment", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Topic :: Software Development :: Libraries", +] +dependencies = ["genkit", "structlog>=25.2.0", "genkit-plugin-google-genai"] +description = "Genkit prompt demo" +license = { text = "Apache-2.0" } +name = "prompt-demo" +requires-python = ">=3.10" +version = "0.0.1" + +[build-system] +build-backend = "hatchling.build" +requires = ["hatchling"] + +[tool.hatch.build.targets.wheel] +packages = ["src"] + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.uv.sources] +genkit = { workspace = true } +genkit-plugin-google-genai = { workspace = true } diff --git a/py/samples/prompt_demo/src/prompt_demo.py b/py/samples/prompt_demo/src/prompt_demo.py new file mode 100644 index 0000000000..1fb160644f --- /dev/null +++ b/py/samples/prompt_demo/src/prompt_demo.py @@ -0,0 +1,53 @@ +# Copyright 2025 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 + +import asyncio +from pathlib import Path + +import structlog + +from genkit.ai import Genkit +from genkit.blocks.prompt import load_prompt_folder +from genkit.plugins.google_genai import GoogleAI + +logger = structlog.get_logger(__name__) + + +# Initialize with GoogleAI plugin +ai = Genkit(plugins=[GoogleAI()]) + + +async def main(): + # Load the prompts from the directory (data) + current_dir = Path(__file__).resolve().parent + prompts_path = current_dir.parent / 'data' + load_prompt_folder(ai.registry, prompts_path) + + # List actions to verify loading + actions = ai.registry.list_serializable_actions() + + # Filter for prompts to be specific + # Keys start with /prompt + prompts = [key for key in actions.keys() if key.startswith(('/prompt/', '/executable-prompt/'))] + + await logger.ainfo('Registry Status', total_actions=len(actions), loaded_prompts=prompts) + + if not prompts: + await logger.awarning('No prompts found! Check directory structure.') + + +if __name__ == '__main__': + ai.run_main(main()) diff --git a/py/uv.lock b/py/uv.lock index b65ac572d3..2e5ce52fa8 100644 --- a/py/uv.lock +++ b/py/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.14'", @@ -38,6 +38,7 @@ members = [ "multi-server", "ollama-hello", "ollama-simple-embed", + "prompt-demo", "short-n-long", "tool-interrupts", "vertex-ai-vector-search-bigquery", @@ -3817,6 +3818,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/ae/ec06af4fe3ee72d16973474f122541746196aaa16cea6f66d18b963c6177/prometheus_client-0.22.1-py3-none-any.whl", hash = "sha256:cca895342e308174341b2cbf99a56bef291fbc0ef7b9e5412a0f26d653ba7094", size = 58694, upload-time = "2025-06-02T14:29:00.068Z" }, ] +[[package]] +name = "prompt-demo" +version = "0.0.1" +source = { editable = "samples/prompt_demo" } +dependencies = [ + { name = "genkit" }, + { name = "genkit-plugin-google-genai" }, + { name = "structlog" }, +] + +[package.metadata] +requires-dist = [ + { name = "genkit", editable = "packages/genkit" }, + { name = "genkit-plugin-google-genai", editable = "plugins/google-genai" }, + { name = "structlog", specifier = ">=25.2.0" }, +] + [[package]] name = "prompt-toolkit" version = "3.0.51"