diff --git a/instrumentation-genai/opentelemetry-instrumentation-vertexai/CHANGELOG.md b/instrumentation-genai/opentelemetry-instrumentation-vertexai/CHANGELOG.md index 0fae39d7d0..172196b40d 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-vertexai/CHANGELOG.md +++ b/instrumentation-genai/opentelemetry-instrumentation-vertexai/CHANGELOG.md @@ -17,3 +17,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#3203](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3203)) - Add Vertex gen AI response span attributes ([#3227](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3227)) +- VertexAI stop serializing unset fields into event + ([#3236](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3236)) diff --git a/instrumentation-genai/opentelemetry-instrumentation-vertexai/src/opentelemetry/instrumentation/vertexai/utils.py b/instrumentation-genai/opentelemetry-instrumentation-vertexai/src/opentelemetry/instrumentation/vertexai/utils.py index 36c90d5929..fc1a3e8e8f 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-vertexai/src/opentelemetry/instrumentation/vertexai/utils.py +++ b/instrumentation-genai/opentelemetry-instrumentation-vertexai/src/opentelemetry/instrumentation/vertexai/utils.py @@ -257,7 +257,10 @@ def _parts_to_any_value( return None return [ - cast("dict[str, AnyValue]", type(part).to_dict(part)) # type: ignore[reportUnknownMemberType] + cast( + "dict[str, AnyValue]", + type(part).to_dict(part, including_default_value_fields=False), # type: ignore[reportUnknownMemberType] + ) for part in parts ] diff --git a/instrumentation-genai/opentelemetry-instrumentation-vertexai/test-requirements-0.txt b/instrumentation-genai/opentelemetry-instrumentation-vertexai/test-requirements-0.txt index 3450e980ad..340ad3ac5f 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-vertexai/test-requirements-0.txt +++ b/instrumentation-genai/opentelemetry-instrumentation-vertexai/test-requirements-0.txt @@ -7,7 +7,7 @@ docstring_parser==0.16 exceptiongroup==1.2.2 google-api-core==2.23.0 google-auth==2.36.0 -google-cloud-aiplatform==1.74.0 +google-cloud-aiplatform==1.79.0 google-cloud-bigquery==3.27.0 google-cloud-core==2.4.1 google-cloud-resource-manager==1.13.1 diff --git a/instrumentation-genai/opentelemetry-instrumentation-vertexai/test-requirements-1.txt b/instrumentation-genai/opentelemetry-instrumentation-vertexai/test-requirements-1.txt index 9980561fb5..96ee7fd47e 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-vertexai/test-requirements-1.txt +++ b/instrumentation-genai/opentelemetry-instrumentation-vertexai/test-requirements-1.txt @@ -8,7 +8,7 @@ docstring_parser==0.16 exceptiongroup==1.2.2 google-api-core==2.23.0 google-auth==2.36.0 -google-cloud-aiplatform==1.74.0 +google-cloud-aiplatform==1.79.0 google-cloud-bigquery==3.27.0 google-cloud-core==2.4.1 google-cloud-resource-manager==1.13.1 diff --git a/instrumentation-genai/opentelemetry-instrumentation-vertexai/tests/cassettes/test_preview_generate_content_all_input_events.yaml b/instrumentation-genai/opentelemetry-instrumentation-vertexai/tests/cassettes/test_preview_generate_content_all_input_events.yaml new file mode 100644 index 0000000000..23c749e6fe --- /dev/null +++ b/instrumentation-genai/opentelemetry-instrumentation-vertexai/tests/cassettes/test_preview_generate_content_all_input_events.yaml @@ -0,0 +1,108 @@ +interactions: +- request: + body: |- + { + "contents": [ + { + "role": "user", + "parts": [ + { + "text": "My name is OpenTelemetry" + } + ] + }, + { + "role": "model", + "parts": [ + { + "text": "Hello OpenTelemetry!" + } + ] + }, + { + "role": "user", + "parts": [ + { + "text": "Address me by name and say this is a test" + } + ] + } + ], + "systemInstruction": { + "role": "user", + "parts": [ + { + "text": "You are a clever language model" + } + ] + } + } + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '548' + Content-Type: + - application/json + User-Agent: + - python-requests/2.32.3 + method: POST + uri: https://us-central1-aiplatform.googleapis.com/v1beta1/projects/fake-project/locations/us-central1/publishers/google/models/gemini-1.5-flash-002:generateContent?%24alt=json%3Benum-encoding%3Dint + response: + body: + string: |- + { + "candidates": [ + { + "content": { + "role": "model", + "parts": [ + { + "text": "OpenTelemetry, this is a test.\n" + } + ] + }, + "finishReason": 1, + "avgLogprobs": -1.1655389850299496e-06 + } + ], + "usageMetadata": { + "promptTokenCount": 25, + "candidatesTokenCount": 9, + "totalTokenCount": 34, + "promptTokensDetails": [ + { + "modality": 1, + "tokenCount": 25 + } + ], + "candidatesTokensDetails": [ + { + "modality": 1, + "tokenCount": 9 + } + ] + }, + "modelVersion": "gemini-1.5-flash-002", + "createTime": "2025-02-03T22:15:35.089616Z", + "responseId": "B0ChZ5C8BbXInvgP19PTyA4" + } + headers: + Content-Type: + - application/json; charset=UTF-8 + Transfer-Encoding: + - chunked + Vary: + - Origin + - X-Origin + - Referer + content-length: + - '715' + status: + code: 200 + message: OK +version: 1 diff --git a/instrumentation-genai/opentelemetry-instrumentation-vertexai/tests/test_chat_completions.py b/instrumentation-genai/opentelemetry-instrumentation-vertexai/tests/test_chat_completions.py index dc99632263..211289396f 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-vertexai/tests/test_chat_completions.py +++ b/instrumentation-genai/opentelemetry-instrumentation-vertexai/tests/test_chat_completions.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from google.api_core.exceptions import BadRequest, NotFound from vertexai.generative_models import ( @@ -6,6 +8,9 @@ GenerativeModel, Part, ) +from vertexai.preview.generative_models import ( + GenerativeModel as PreviewGenerativeModel, +) from opentelemetry.instrumentation.vertexai import VertexAIInstrumentor from opentelemetry.sdk._logs._internal.export.in_memory_log_exporter import ( @@ -321,10 +326,37 @@ def test_generate_content_all_events( log_exporter: InMemoryLogExporter, instrument_with_content: VertexAIInstrumentor, ): - model = GenerativeModel( - "gemini-1.5-flash-002", - system_instruction=Part.from_text("You are a clever language model"), + generate_content_all_input_events( + GenerativeModel( + "gemini-1.5-flash-002", + system_instruction=Part.from_text( + "You are a clever language model" + ), + ), + log_exporter, ) + + +@pytest.mark.vcr +def test_preview_generate_content_all_input_events( + log_exporter: InMemoryLogExporter, + instrument_with_content: VertexAIInstrumentor, +): + generate_content_all_input_events( + PreviewGenerativeModel( + "gemini-1.5-flash-002", + system_instruction=Part.from_text( + "You are a clever language model" + ), + ), + log_exporter, + ) + + +def generate_content_all_input_events( + model: GenerativeModel | PreviewGenerativeModel, + log_exporter: InMemoryLogExporter, +): model.generate_content( [ Content(