def _assert_field_types_not_changed(self, id: str, vespa_fields: dict,
                                        excluded_fields: List[Tuple[str, MarqoFieldTypes]]):
        """
        Verify that field types remain unchanged except for the specified excluded fields.

        This helper method checks that all field types in the document match their expected values,
        excluding the fields that were intentionally modified during the test.

        Args:
            id (str): The document ID to check.
            vespa_fields (dict): The fields from the Vespa document.
            excluded_fields (List[Tuple[str, MarqoFieldTypes]]): List of field names that were intentionally modified and should be excluded from verification.
        """
        # Get the actual field types from the Vespa document
        actual_field_types = vespa_fields.get('marqo__field_types')
        # Get the expected field types from our mapping
        doc_to_field_type = self.doc_to_field_type_map[id]

        # Create a copy of the expected field types and remove excluded fields
        expected_field_types = copy.deepcopy(doc_to_field_type)

        # Process each excluded field
        for field_name, field_value in excluded_fields:
            # If field value is None, remove the field from expected types if it exists. We do this because 
            # fields of type None signify that the field was supposed to be removed from the document
            if field_value is None:
                if field_name in expected_field_types:
                    del expected_field_types[field_name]
            # Otherwise update the expected type with the new value. We do this because 
            # this field signifies a new field that has been added to the document. 
            else:
                if field_name not in expected_field_types:
                    expected_field_types[field_name] = field_value.value

        # Compare actual and expected field types
        is_expected_and_actual_equal = actual_field_types == expected_field_types
        # If they don't match, find and report the differences
        if not is_expected_and_actual_equal:
            # Find common fields between actual and expected
            intersection = set(actual_field_types.items()) & set(expected_field_types.items())
            # Find fields that are in expected but not in actual
            fields_present_in_expected_but_not_in_actual = set(expected_field_types.items()) - intersection
            # Find fields that are in actual but not in expected  
            fields_present_in_actual_but_not_in_expected = set(actual_field_types.items()) - intersection
            # Report any missing fields that should be present
            for field, _ in fields_present_in_expected_but_not_in_actual:
                self.fail(f"Field {field} is present in expected field types but not in actual field types")
            # Report any extra fields that shouldn't be present
            for field, _ in fields_present_in_actual_but_not_in_expected:
                self.fail(f"Field {field} is present in actual field types but not in expected field types")

        Verify that field types remain unchanged except for the specified excluded fields.

        This helper method checks that all field types in the document match their expected values,
        excluding the fields that were intentionally modified during the test.

        Args:
            id (str): The document ID to check.
            vespa_fields (dict): The fields from the Vespa document.
            excluded_fields (List[Tuple[str, MarqoFieldTypes]]): List of field names that were intentionally modified and should be excluded from verification.
        
tests/integ_tests/core/document/test_partial_update_semi_structured.py