From 0586ab2394b5a9039c6555ae4920d02f99ce583f Mon Sep 17 00:00:00 2001 From: Sampath Kumar Date: Fri, 14 Feb 2025 13:29:15 +0100 Subject: [PATCH] feat(genai): Add Content Cache example using Gemini 1.5 models (#13164) * feat(genai): Add Content Cache example using Gemini 1.5 models Example include how to create, update, delete and use Content Cache. * Update genai/content_cache/contentcache_list.py Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com> * Update genai/content_cache/contentcache_list.py Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com> * Update genai/content_cache/contentcache_list.py Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com> * Update genai/content_cache/contentcache_update.py Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com> * feat: Using `input` instead of `raw_input` * feat: Update imports order * fix: region tag mismatch * fix: Add required ENV vars * fix: using `v1beta1` instead of `v1` --------- Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com> --- .../contentcache_create_with_txt_gcs_pdf.py | 65 +++++++++++++++++++ genai/content_cache/contentcache_delete.py | 35 ++++++++++ genai/content_cache/contentcache_list.py | 42 ++++++++++++ genai/content_cache/contentcache_update.py | 59 +++++++++++++++++ .../contentcache_use_with_txt.py | 42 ++++++++++++ genai/content_cache/noxfile_config.py | 42 ++++++++++++ genai/content_cache/requirements-test.txt | 2 + genai/content_cache/requirements.txt | 1 + .../test_content_cache_examples.py | 49 ++++++++++++++ 9 files changed, 337 insertions(+) create mode 100644 genai/content_cache/contentcache_create_with_txt_gcs_pdf.py create mode 100644 genai/content_cache/contentcache_delete.py create mode 100644 genai/content_cache/contentcache_list.py create mode 100644 genai/content_cache/contentcache_update.py create mode 100644 genai/content_cache/contentcache_use_with_txt.py create mode 100644 genai/content_cache/noxfile_config.py create mode 100644 genai/content_cache/requirements-test.txt create mode 100644 genai/content_cache/requirements.txt create mode 100644 genai/content_cache/test_content_cache_examples.py diff --git a/genai/content_cache/contentcache_create_with_txt_gcs_pdf.py b/genai/content_cache/contentcache_create_with_txt_gcs_pdf.py new file mode 100644 index 000000000000..57d10e39e03c --- /dev/null +++ b/genai/content_cache/contentcache_create_with_txt_gcs_pdf.py @@ -0,0 +1,65 @@ +# 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 +# +# https://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. + + +def create_content_cache() -> str: + # [START googlegenaisdk_contentcache_create_with_txt_gcs_pdf] + from google import genai + from google.genai.types import Content, CreateCachedContentConfig, HttpOptions, Part + + client = genai.Client(http_options=HttpOptions(api_version="v1beta1")) + + system_instruction = """ + You are an expert researcher. You always stick to the facts in the sources provided, and never make up new facts. + Now look at these research papers, and answer the following questions. + """ + + contents = [ + Content( + role="user", + parts=[ + Part.from_uri( + file_uri="gs://cloud-samples-data/generative-ai/pdf/2312.11805v3.pdf", + mime_type="application/pdf", + ), + Part.from_uri( + file_uri="gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf", + mime_type="application/pdf", + ), + ], + ) + ] + + content_cache = client.caches.create( + model="gemini-1.5-pro-002", + config=CreateCachedContentConfig( + contents=contents, + system_instruction=system_instruction, + display_name="example-cache", + ttl="86400s", + ), + ) + + print(content_cache.name) + print(content_cache.usage_metadata) + # Example response: + # projects/111111111111/locations/us-central1/cachedContents/1111111111111111111 + # CachedContentUsageMetadata(audio_duration_seconds=None, image_count=167, + # text_count=153, total_token_count=43130, video_duration_seconds=None) + # [END googlegenaisdk_contentcache_create_with_txt_gcs_pdf] + return content_cache.name + + +if __name__ == "__main__": + create_content_cache() diff --git a/genai/content_cache/contentcache_delete.py b/genai/content_cache/contentcache_delete.py new file mode 100644 index 000000000000..9b8b33109447 --- /dev/null +++ b/genai/content_cache/contentcache_delete.py @@ -0,0 +1,35 @@ +# 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 +# +# https://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. + + +def delete_context_caches(cache_name: str) -> str: + # [START googlegenaisdk_contentcache_delete] + from google import genai + from google.genai.types import HttpOptions + + client = genai.Client(http_options=HttpOptions(api_version="v1beta1")) + + # Delete content cache using name + # E.g cache_name = 'projects/111111111111/locations/us-central1/cachedContents/1111111111111111111' + client.caches.delete(name=cache_name) + print("Deleted Cache", cache_name) + # Example response + # Deleted Cache projects/111111111111/locations/us-central1/cachedContents/1111111111111111111 + # [END googlegenaisdk_contentcache_delete] + return cache_name + + +if __name__ == "__main__": + cache_name = input("Cache Name: ") + delete_context_caches(cache_name) diff --git a/genai/content_cache/contentcache_list.py b/genai/content_cache/contentcache_list.py new file mode 100644 index 000000000000..112fc9c43df3 --- /dev/null +++ b/genai/content_cache/contentcache_list.py @@ -0,0 +1,42 @@ +# 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 +# +# https://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. + + +def list_context_caches() -> str: + # [START googlegenaisdk_contentcache_list] + from google import genai + from google.genai.types import HttpOptions + + client = genai.Client(http_options=HttpOptions(api_version="v1beta1")) + + content_cache_list = client.caches.list() + + # Access individual properties of a ContentCache object(s) + for content_cache in content_cache_list: + print(f"Cache `{content_cache.name}` for model `{content_cache.model}`") + print(f"Last updated at: {content_cache.update_time}") + print(f"Expires at: {content_cache.expire_time}") + + # Example response: + # * Cache `projects/111111111111/locations/us-central1/cachedContents/1111111111111111111` for + # model `projects/111111111111/locations/us-central1/publishers/google/models/gemini-XXX-pro-XXX` + # * Last updated at: 2025-02-13 14:46:42.620490+00:00 + # * CachedContentUsageMetadata(audio_duration_seconds=None, image_count=167, text_count=153, total_token_count=43130, video_duration_seconds=None) + # ... + # [END googlegenaisdk_contentcache_list] + return [content_cache.name for content_cache in content_cache_list] + + +if __name__ == "__main__": + list_context_caches() diff --git a/genai/content_cache/contentcache_update.py b/genai/content_cache/contentcache_update.py new file mode 100644 index 000000000000..56748ce7eff0 --- /dev/null +++ b/genai/content_cache/contentcache_update.py @@ -0,0 +1,59 @@ +# 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 +# +# https://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. + + +def update_content_cache(cache_name: str) -> str: + # [START googlegenaisdk_contentcache_update] + from datetime import datetime as dt + from datetime import timezone as tz + from datetime import timedelta + + from google import genai + from google.genai.types import HttpOptions, UpdateCachedContentConfig + + client = genai.Client(http_options=HttpOptions(api_version="v1beta1")) + + # Get content cache by name + # cache_name = "projects/111111111111/locations/us-central1/cachedContents/1111111111111111111" + content_cache = client.caches.get(name=cache_name) + print("Expire time", content_cache.expire_time) + # Example response + # Expire time 2025-02-20 15:50:18.434482+00:00 + + # Update expire time using TTL + content_cache = client.caches.update( + name=cache_name, config=UpdateCachedContentConfig(ttl="36000s") + ) + time_diff = content_cache.expire_time - dt.now(tz.utc) + print("Expire time(after update):", content_cache.expire_time) + print("Expire time(in seconds):", time_diff.seconds) + # Example response + # Expire time(after update): 2025-02-14 01:51:42.571696+00:00 + # Expire time(in seconds): 35999 + + # Update expire time using specific time stamp + next_week_utc = dt.now(tz.utc) + timedelta(days=7) + content_cache = client.caches.update( + name=cache_name, config=UpdateCachedContentConfig(expireTime=next_week_utc) + ) + print("Expire time(after update):", content_cache.expire_time) + # Example response + # Expire time(after update): 2025-02-20 15:51:42.614968+00:00 + # [END googlegenaisdk_contentcache_update] + return cache_name + + +if __name__ == "__main__": + cache_name = input("Cache Name: ") + update_content_cache(cache_name) diff --git a/genai/content_cache/contentcache_use_with_txt.py b/genai/content_cache/contentcache_use_with_txt.py new file mode 100644 index 000000000000..cd00bf4b08d8 --- /dev/null +++ b/genai/content_cache/contentcache_use_with_txt.py @@ -0,0 +1,42 @@ +# 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 +# +# https://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. + + +def generate_content(cache_name: str) -> str: + # [START googlegenaisdk_contentcache_use_with_txt] + from google import genai + from google.genai.types import GenerateContentConfig, HttpOptions + + client = genai.Client(http_options=HttpOptions(api_version="v1beta1")) + + # Use content cache to generate text response + # E.g cache_name = 'projects/111111111111/locations/us-central1/cachedContents/1111111111111111111' + response = client.models.generate_content( + model='gemini-1.5-pro-002', + contents='Summarize the pdfs', + config=GenerateContentConfig( + cached_content=cache_name, + ), + ) + print(response.text) + # Example response + # The Gemini family of multimodal models from Google DeepMind demonstrates remarkable capabilities across various + # modalities, including image, audio, video, and text.... + # [END googlegenaisdk_contentcache_use_with_txt] + return response.text + + +if __name__ == "__main__": + cache_name = input("Cache Name: ") + generate_content(cache_name) diff --git a/genai/content_cache/noxfile_config.py b/genai/content_cache/noxfile_config.py new file mode 100644 index 000000000000..2a0f115c38f2 --- /dev/null +++ b/genai/content_cache/noxfile_config.py @@ -0,0 +1,42 @@ +# Copyright 2021 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. + +# Default TEST_CONFIG_OVERRIDE for python repos. + +# You can copy this file into your directory, then it will be imported from +# the noxfile.py. + +# The source of truth: +# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/main/noxfile_config.py + +TEST_CONFIG_OVERRIDE = { + # You can opt out from the test for specific Python versions. + "ignored_versions": ["2.7", "3.7", "3.8", "3.10", "3.11", "3.12"], + # Old samples are opted out of enforcing Python type hints + # All new samples should feature them + "enforce_type_hints": True, + # An envvar key for determining the project id to use. Change it + # to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a + # build specific Cloud project. You can also use your own string + # to use your own Cloud project. + "gcloud_project_env": "GOOGLE_CLOUD_PROJECT", + # 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT', + # If you need to use a specific version of pip, + # change pip_version_override to the string representation + # of the version number, for example, "20.2.4" + "pip_version_override": None, + # A dictionary you want to inject into your test. Don't put any + # secrets here. These values will override predefined values. + "envs": {}, +} diff --git a/genai/content_cache/requirements-test.txt b/genai/content_cache/requirements-test.txt new file mode 100644 index 000000000000..e43b7792721d --- /dev/null +++ b/genai/content_cache/requirements-test.txt @@ -0,0 +1,2 @@ +google-api-core==2.24.0 +pytest==8.2.0 diff --git a/genai/content_cache/requirements.txt b/genai/content_cache/requirements.txt new file mode 100644 index 000000000000..7a2b80527c5b --- /dev/null +++ b/genai/content_cache/requirements.txt @@ -0,0 +1 @@ +google-genai==1.2.0 diff --git a/genai/content_cache/test_content_cache_examples.py b/genai/content_cache/test_content_cache_examples.py new file mode 100644 index 000000000000..d7d9e5abda43 --- /dev/null +++ b/genai/content_cache/test_content_cache_examples.py @@ -0,0 +1,49 @@ +# 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 +# +# https://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. + +import os + +import contentcache_create_with_txt_gcs_pdf +import contentcache_delete +import contentcache_list +import contentcache_update +import contentcache_use_with_txt + + +os.environ["GOOGLE_GENAI_USE_VERTEXAI"] = "True" +os.environ["GOOGLE_CLOUD_LOCATION"] = "us-central1" +# The project name is included in the CICD pipeline +# os.environ['GOOGLE_CLOUD_PROJECT'] = "add-your-project-name" + + +def test_content_cache() -> None: + # Create a Cache + cache_name = contentcache_create_with_txt_gcs_pdf.create_content_cache() + assert cache_name + + # List cache + assert contentcache_list.list_context_caches() + + # Update cache + assert contentcache_update.update_content_cache(cache_name) + + # Use cache + assert contentcache_use_with_txt.generate_content(cache_name) + + # Delete cache + assert contentcache_delete.delete_context_caches(cache_name) + + +if __name__ == "__main__": + test_content_cache()