google-cloud-pipeline-components 2.10.0__py3-none-any.whl → 2.12.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of google-cloud-pipeline-components might be problematic. Click here for more details.

Files changed (43) hide show
  1. google_cloud_pipeline_components/_implementation/llm/batch_prediction_pairwise.py +14 -4
  2. google_cloud_pipeline_components/_implementation/llm/bulk_inferrer.py +7 -0
  3. google_cloud_pipeline_components/_implementation/llm/deployment_graph.py +6 -1
  4. google_cloud_pipeline_components/_implementation/llm/function_based.py +74 -168
  5. google_cloud_pipeline_components/_implementation/llm/generated/refined_image_versions.py +1 -1
  6. google_cloud_pipeline_components/_implementation/llm/model_evaluation_text_generation_pairwise.py +45 -3
  7. google_cloud_pipeline_components/_implementation/llm/online_evaluation_pairwise.py +14 -2
  8. google_cloud_pipeline_components/_implementation/llm/private_text_comparison_importer.py +9 -2
  9. google_cloud_pipeline_components/_implementation/llm/private_text_importer.py +8 -1
  10. google_cloud_pipeline_components/_implementation/llm/reinforcement_learning_graph.py +14 -28
  11. google_cloud_pipeline_components/_implementation/llm/reinforcer.py +13 -0
  12. google_cloud_pipeline_components/_implementation/llm/reward_model_graph.py +36 -27
  13. google_cloud_pipeline_components/_implementation/llm/reward_model_trainer.py +17 -0
  14. google_cloud_pipeline_components/_implementation/llm/rlhf_preprocessor.py +60 -0
  15. google_cloud_pipeline_components/_implementation/llm/supervised_fine_tuner.py +1 -0
  16. google_cloud_pipeline_components/_implementation/llm/utils.py +25 -2
  17. google_cloud_pipeline_components/_implementation/llm/validate_pipeline.py +113 -0
  18. google_cloud_pipeline_components/_implementation/model_evaluation/__init__.py +2 -0
  19. google_cloud_pipeline_components/_implementation/model_evaluation/endpoint_batch_predict/component.py +1 -1
  20. google_cloud_pipeline_components/_implementation/model_evaluation/llm_evaluation/component.py +2 -2
  21. google_cloud_pipeline_components/_implementation/model_evaluation/llm_evaluation_preprocessor/component.py +2 -2
  22. google_cloud_pipeline_components/_implementation/model_evaluation/model_name_preprocessor/__init__.py +14 -0
  23. google_cloud_pipeline_components/_implementation/model_evaluation/model_name_preprocessor/component.py +74 -0
  24. google_cloud_pipeline_components/_implementation/model_evaluation/version.py +1 -1
  25. google_cloud_pipeline_components/container/_implementation/model_evaluation/import_model_evaluation.py +7 -7
  26. google_cloud_pipeline_components/preview/llm/infer/__init__.py +13 -0
  27. google_cloud_pipeline_components/preview/llm/infer/component.py +10 -10
  28. google_cloud_pipeline_components/preview/llm/rlaif/component.py +10 -3
  29. google_cloud_pipeline_components/preview/llm/rlhf/component.py +43 -22
  30. google_cloud_pipeline_components/preview/model_evaluation/__init__.py +2 -2
  31. google_cloud_pipeline_components/preview/model_evaluation/model_based_llm_evaluation/autosxs/autosxs_pipeline.py +45 -3
  32. google_cloud_pipeline_components/proto/preflight_validations_pb2.py +19 -30
  33. google_cloud_pipeline_components/v1/custom_job/utils.py +22 -22
  34. google_cloud_pipeline_components/v1/model/get_model/component.py +1 -1
  35. google_cloud_pipeline_components/v1/model_evaluation/__init__.py +4 -0
  36. google_cloud_pipeline_components/{preview → v1}/model_evaluation/evaluation_llm_classification_pipeline.py +14 -2
  37. google_cloud_pipeline_components/{preview → v1}/model_evaluation/evaluation_llm_text_generation_pipeline.py +29 -17
  38. google_cloud_pipeline_components/version.py +1 -1
  39. {google_cloud_pipeline_components-2.10.0.dist-info → google_cloud_pipeline_components-2.12.0.dist-info}/METADATA +1 -2
  40. {google_cloud_pipeline_components-2.10.0.dist-info → google_cloud_pipeline_components-2.12.0.dist-info}/RECORD +43 -39
  41. {google_cloud_pipeline_components-2.10.0.dist-info → google_cloud_pipeline_components-2.12.0.dist-info}/WHEEL +1 -1
  42. {google_cloud_pipeline_components-2.10.0.dist-info → google_cloud_pipeline_components-2.12.0.dist-info}/LICENSE +0 -0
  43. {google_cloud_pipeline_components-2.10.0.dist-info → google_cloud_pipeline_components-2.12.0.dist-info}/top_level.txt +0 -0
@@ -37,10 +37,11 @@ def private_text_importer(
37
37
  imported_data_path: dsl.OutputPath(str), # pytype: disable=invalid-annotation
38
38
  gcp_resources: dsl.OutputPath(str), # pytype: disable=invalid-annotation
39
39
  instruction: str = '',
40
- image_uri: str = utils.get_default_image_uri('text_importer_backup'),
40
+ image_uri: str = utils.get_default_image_uri('refined_cpu', ''),
41
41
  machine_type: str = 'e2-highmem-8',
42
42
  output_split_name: str = 'all',
43
43
  max_num_input_examples: Optional[int] = None,
44
+ encryption_spec_key_name: str = '',
44
45
  ) -> dsl.ContainerSpec: # pylint: disable=g-doc-args
45
46
  """Import a text dataset.
46
47
 
@@ -59,6 +60,10 @@ def private_text_importer(
59
60
  output_split_name: The created seqio task has 1 split, its name is specified
60
61
  by this argument.
61
62
  max_num_input_examples: Maximum number of examples to import.
63
+ encryption_spec_key_name: Customer-managed encryption key. If this is set,
64
+ then all resources created by the CustomJob will be encrypted with the
65
+ provided encryption key. Note that this is not supported for TPU at the
66
+ moment.
62
67
 
63
68
  Returns:
64
69
  imported_data: Artifact representing the imported data and cached Tasks.
@@ -76,6 +81,7 @@ def private_text_importer(
76
81
  machine_type=machine_type,
77
82
  image_uri=_resolve_image(image_uri),
78
83
  args=[
84
+ '--app_name=text_importer',
79
85
  f'--input_text={input_text}',
80
86
  f'--inputs_field_name={inputs_field_name}',
81
87
  f'--targets_field_name={targets_field_name}',
@@ -88,6 +94,7 @@ def private_text_importer(
88
94
  f'--max_num_input_examples={max_num_input_examples}',
89
95
  '--executor_input={{$.json_escape[1]}}',
90
96
  ],
97
+ encryption_spec_key_name=encryption_spec_key_name,
91
98
  ),
92
99
  gcp_resources=gcp_resources,
93
100
  )
@@ -51,8 +51,10 @@ def pipeline(
51
51
  kl_coeff: float = 0.1,
52
52
  instruction: Optional[str] = None,
53
53
  project: str = _placeholders.PROJECT_ID_PLACEHOLDER,
54
+ accelerator_type: str = 'GPU',
54
55
  location: str = _placeholders.LOCATION_PLACEHOLDER,
55
- tensorboard_resource_id: Optional[str] = None,
56
+ tensorboard_resource_id: str = '',
57
+ encryption_spec_key_name: str = '',
56
58
  ) -> PipelineOutput:
57
59
  # fmt: off
58
60
  """Trains a reward model.
@@ -72,8 +74,10 @@ def pipeline(
72
74
  kl_coeff: Coefficient for KL penalty. This regularizes the policy model and penalizes if it diverges from its initial distribution. If set to 0, the reference language model is not loaded into memory. Default value is 0.1.
73
75
  instruction: This field lets the model know what task it needs to perform. Base models have been trained over a large set of varied instructions. You can give a simple and intuitive description of the task and the model will follow it, e.g. "Classify this movie review as positive or negative" or "Translate this sentence to Danish". Do not specify this if your dataset already prepends the instruction to the inputs field.
74
76
  project: Project used to run custom jobs. If not specified the project used to run the pipeline will be used.
75
- location: Location used to run custom jobs. If not specified the location used to run the pipeline will be used.
77
+ accelerator_type: One of 'TPU' or 'GPU'. If 'TPU' is specified, tuning components run in europe-west4. Otherwise tuning components run in us-central1 on GPUs. Default is 'GPU'.
78
+ location: Location used to run non-tuning components, i.e. components that do not require accelerators. If not specified the location used to run the pipeline will be used.
76
79
  tensorboard_resource_id: Optional tensorboard resource id in format `projects/{project_number}/locations/{location}/tensorboards/{tensorboard_id}`. If provided, tensorboard metrics will be uploaded to this location.
80
+ encryption_spec_key_name: Customer-managed encryption key. If this is set, then all resources created by the CustomJob will be encrypted with the provided encryption key. Note that this is not supported for TPU at the moment.
77
81
 
78
82
  Returns:
79
83
  output_model_path: Path to the trained model checkpoint.
@@ -82,17 +86,14 @@ def pipeline(
82
86
  # fmt: on
83
87
  prompt_column = 'input_text'
84
88
  machine_spec = function_based.resolve_machine_spec(
85
- location=location, use_test_spec=env.get_use_test_machine_spec()
89
+ accelerator_type=accelerator_type,
90
+ use_test_spec=env.get_use_test_machine_spec(),
86
91
  ).set_display_name('Resolve Machine Spec')
87
92
 
88
93
  reference_model_metadata = function_based.resolve_reference_model_metadata(
89
94
  large_model_reference=large_model_reference,
90
95
  ).set_display_name('Resolve Model Metadata')
91
96
 
92
- prompt_dataset_image_uri = function_based.resolve_private_image_uri(
93
- image_name='text_importer'
94
- ).set_display_name('Resolve Prompt Dataset Image URI')
95
-
96
97
  processed_dataset = preprocess_chat_dataset.preprocess_chat_dataset(
97
98
  large_model_reference=large_model_reference,
98
99
  input_dataset_uri=prompt_dataset,
@@ -111,16 +112,14 @@ def pipeline(
111
112
  large_model_reference=reference_model_metadata.outputs[
112
113
  'large_model_reference'
113
114
  ],
114
- image_uri=prompt_dataset_image_uri.output,
115
115
  instruction=instruction,
116
+ encryption_spec_key_name=encryption_spec_key_name,
116
117
  )
117
118
  .set_display_name('Import Prompt Dataset')
118
119
  .set_caching_options(False)
119
120
  )
120
- rl_image_uri = function_based.resolve_private_image_uri(
121
- image_name='reinforcer',
121
+ rl_image_uri = function_based.resolve_private_refined_image_uri(
122
122
  accelerator_type=machine_spec.outputs['accelerator_type'],
123
- accelerator_count=machine_spec.outputs['accelerator_count'],
124
123
  ).set_display_name('Resolve Reinforcer Image URI')
125
124
  num_microbatches = function_based.resolve_num_microbatches(
126
125
  large_model_reference=reference_model_metadata.outputs[
@@ -130,7 +129,7 @@ def pipeline(
130
129
  rl_model = (
131
130
  reinforcer.reinforcer(
132
131
  project=project,
133
- location=location,
132
+ location=machine_spec.outputs['tuning_location'],
134
133
  input_reference_model_path=reference_model_metadata.outputs[
135
134
  'reference_model_path'
136
135
  ],
@@ -159,26 +158,13 @@ def pipeline(
159
158
  lora_dim=lora_dim,
160
159
  reward_lora_dim=reward_lora_dim,
161
160
  num_microbatches=num_microbatches.output,
161
+ encryption_spec_key_name=encryption_spec_key_name,
162
+ tensorboard_resource_id=tensorboard_resource_id,
162
163
  )
163
164
  .set_display_name('Reinforcer')
164
165
  .set_caching_options(False)
165
166
  )
166
- has_tensorboard_id = function_based.value_exists(
167
- value=tensorboard_resource_id
168
- ).set_display_name('Resolve Tensorboard Resource ID')
169
- with kfp.dsl.Condition( # pytype: disable=wrong-arg-types
170
- has_tensorboard_id.output == True, # pylint: disable=singleton-comparison, g-explicit-bool-comparison
171
- name='Upload Reinforcement Learning Tensorboard Metrics',
172
- ):
173
- _ = upload_tensorboard_metrics.upload_tensorboard_metrics(
174
- tensorboard_resource_id=tensorboard_resource_id,
175
- metrics_directory=rl_model.outputs['tensorboard_metrics'],
176
- experiment_name=(
177
- 'rl-model-tuner-'
178
- f'{kfp.dsl.PIPELINE_JOB_ID_PLACEHOLDER}-'
179
- f'{kfp.dsl.PIPELINE_TASK_ID_PLACEHOLDER}'
180
- ),
181
- ).set_display_name('Reinforcement Learning Tensorboard Metrics Uploader')
167
+
182
168
  return PipelineOutput(
183
169
  output_model_path=rl_model.outputs['output_model_path'],
184
170
  output_adapter_path=rl_model.outputs['output_adapter_path'],
@@ -47,6 +47,8 @@ def reinforcer(
47
47
  lora_dim: int = 0,
48
48
  reward_lora_dim: int = 4,
49
49
  num_microbatches: int = 0,
50
+ encryption_spec_key_name: str = '',
51
+ tensorboard_resource_id: str = '',
50
52
  ) -> kfp.dsl.ContainerSpec: # pylint: disable=g-doc-args
51
53
  """Trains a model using reinforcement learning.
52
54
 
@@ -86,6 +88,13 @@ def reinforcer(
86
88
  num_microbatches: Number of microbatches to break the total batch size into
87
89
  during training. If <= 1, the model is trained on the full batch size
88
90
  directly.
91
+ encryption_spec_key_name: Customer-managed encryption key. If this is set,
92
+ then all resources created by the CustomJob will be encrypted with the
93
+ provided encryption key. Note that this is not supported for TPU at the
94
+ moment.
95
+ tensorboard_resource_id: Optional tensorboard resource id. Format:
96
+ `projects/{project_number}/locations/{location}/tensorboards/{tensorboard_id}`.
97
+ If provided, tensorboard metrics will be uploaded to this location.
89
98
 
90
99
  Returns:
91
100
  output_model_path: Path to the trained model checkpoint.
@@ -105,6 +114,7 @@ def reinforcer(
105
114
  machine_type=machine_type,
106
115
  image_uri=image_uri,
107
116
  args=[
117
+ '--app_name=reinforcer',
108
118
  f'--input_reference_model_path={input_reference_model_path}',
109
119
  f'--input_reward_model_path={input_reward_model_path}',
110
120
  f'--input_reward_adapter_path={input_reward_adapter_path}',
@@ -126,6 +136,9 @@ def reinforcer(
126
136
  f'--reward_lora_dim={reward_lora_dim}',
127
137
  f'--num_microbatches={num_microbatches}',
128
138
  ],
139
+ encryption_spec_key_name=encryption_spec_key_name,
140
+ base_output_directory=tensorboard_metrics.uri,
141
+ tensorboard=tensorboard_resource_id,
129
142
  ),
130
143
  gcp_resources=gcp_resources,
131
144
  )
@@ -45,10 +45,13 @@ def pipeline(
45
45
  lora_dim: int = 4,
46
46
  reward_model_learning_rate_multiplier: float = 1.0,
47
47
  reward_model_train_steps: int = 1000,
48
+ eval_dataset: Optional[str] = None,
48
49
  instruction: Optional[str] = None,
49
50
  project: str = _placeholders.PROJECT_ID_PLACEHOLDER,
51
+ accelerator_type: str = 'GPU',
50
52
  location: str = _placeholders.LOCATION_PLACEHOLDER,
51
- tensorboard_resource_id: Optional[str] = None,
53
+ tensorboard_resource_id: str = '',
54
+ encryption_spec_key_name: str = '',
52
55
  ) -> PipelineOutput:
53
56
  # fmt: off
54
57
  """Trains a reward model.
@@ -64,8 +67,10 @@ def pipeline(
64
67
  reward_model_train_steps: Number of steps to use when training a reward model. Default value is 1000.
65
68
  instruction: This field lets the model know what task it needs to perform. Base models have been trained over a large set of varied instructions. You can give a simple and intuitive description of the task and the model will follow it, e.g. "Classify this movie review as positive or negative" or "Translate this sentence to Danish". Do not specify this if your dataset already prepends the instruction to the inputs field.
66
69
  project: Project used to run custom jobs. If not specified the project used to run the pipeline will be used.
67
- location: Location used to run custom jobs. If not specified the location used to run the pipeline will be used.
70
+ accelerator_type: One of 'TPU' or 'GPU'. If 'TPU' is specified, tuning components run in europe-west4. Otherwise tuning components run in us-central1 on GPUs. Default is 'GPU'.
71
+ location: Location used to run non-tuning components, i.e. components that do not require accelerators. If not specified the location used to run the pipeline will be used.
68
72
  tensorboard_resource_id: Optional tensorboard resource id in format `projects/{project_number}/locations/{location}/tensorboards/{tensorboard_id}`. If provided, tensorboard metrics will be uploaded to this location.
73
+ encryption_spec_key_name: Customer-managed encryption key. If this is set, then all resources created by the CustomJob will be encrypted with the provided encryption key. Note that this is not supported for TPU at the moment.
69
74
 
70
75
  Returns:
71
76
  reward_model_base_path: Path to the base model used by the reward model.
@@ -77,7 +82,8 @@ def pipeline(
77
82
  candidate_columns = ['candidate_0', 'candidate_1']
78
83
  choice_column = 'choice'
79
84
  machine_spec = function_based.resolve_machine_spec(
80
- location=location, use_test_spec=env.get_use_test_machine_spec()
85
+ accelerator_type=accelerator_type,
86
+ use_test_spec=env.get_use_test_machine_spec(),
81
87
  ).set_display_name('Resolve Machine Spec')
82
88
 
83
89
  reference_model_metadata = function_based.resolve_reference_model_metadata(
@@ -93,9 +99,6 @@ def pipeline(
93
99
  ).set_display_name('Preprocess Prompt Dataset')
94
100
  )
95
101
 
96
- preference_dataset_image_uri = function_based.resolve_private_image_uri(
97
- image_name='text_comparison_importer'
98
- ).set_display_name('Resolve Preference Dataset Image URI')
99
102
  comma_separated_candidates_field_names = (
100
103
  function_based.convert_to_delimited_string(items=candidate_columns)
101
104
  )
@@ -113,17 +116,34 @@ def pipeline(
113
116
  large_model_reference=reference_model_metadata.outputs[
114
117
  'reward_model_reference'
115
118
  ],
116
- image_uri=preference_dataset_image_uri.output,
117
119
  instruction=instruction,
120
+ encryption_spec_key_name=encryption_spec_key_name,
118
121
  )
119
122
  .set_display_name('Import Preference Dataset')
120
123
  .set_caching_options(False)
121
124
  )
122
125
 
123
- reward_model_image_uri = function_based.resolve_private_image_uri(
124
- image_name='reward_model',
126
+ preference_eval_dataset_importer = (
127
+ private_text_comparison_importer.private_text_comparison_importer(
128
+ project=project,
129
+ location=location,
130
+ input_text=eval_dataset,
131
+ inputs_field_name=prompt_column,
132
+ comma_separated_candidates_field_names=comma_separated_candidates_field_names.output,
133
+ choice_field_name=choice_column,
134
+ split=env.TRAIN_SPLIT,
135
+ large_model_reference=reference_model_metadata.outputs[
136
+ 'reward_model_reference'
137
+ ],
138
+ instruction=instruction,
139
+ encryption_spec_key_name=encryption_spec_key_name,
140
+ )
141
+ .set_display_name('Import Preference Eval Dataset')
142
+ .set_caching_options(False)
143
+ )
144
+
145
+ reward_model_image_uri = function_based.resolve_private_refined_image_uri(
125
146
  accelerator_type=machine_spec.outputs['accelerator_type'],
126
- accelerator_count=machine_spec.outputs['accelerator_count'],
127
147
  ).set_display_name('Resolve Reward Model Image URI')
128
148
  num_microbatches = function_based.resolve_num_microbatches(
129
149
  large_model_reference=reference_model_metadata.outputs[
@@ -133,13 +153,16 @@ def pipeline(
133
153
  reward_model = (
134
154
  reward_model_trainer.reward_model_trainer(
135
155
  project=project,
136
- location=location,
156
+ location=machine_spec.outputs['tuning_location'],
137
157
  input_model_path=reference_model_metadata.outputs[
138
158
  'reward_model_path'
139
159
  ],
140
160
  input_dataset_path=preference_dataset_importer.outputs[
141
161
  'output_dataset_path'
142
162
  ],
163
+ eval_dataset_path=preference_eval_dataset_importer.outputs[
164
+ 'output_dataset_path'
165
+ ],
143
166
  train_steps=reward_model_train_steps,
144
167
  accelerator_type=machine_spec.outputs['accelerator_type'],
145
168
  accelerator_count=machine_spec.outputs['accelerator_count'],
@@ -154,27 +177,13 @@ def pipeline(
154
177
  learning_rate_multiplier=reward_model_learning_rate_multiplier,
155
178
  lora_dim=lora_dim,
156
179
  num_microbatches=num_microbatches.output,
180
+ encryption_spec_key_name=encryption_spec_key_name,
181
+ tensorboard_resource_id=tensorboard_resource_id,
157
182
  )
158
183
  .set_display_name('Reward Model Trainer')
159
184
  .set_caching_options(False)
160
185
  )
161
186
 
162
- has_tensorboard_id = function_based.value_exists(
163
- value=tensorboard_resource_id
164
- ).set_display_name('Resolve TensorBoard Resource ID')
165
- with kfp.dsl.Condition( # pytype: disable=wrong-arg-types
166
- has_tensorboard_id.output == True, # pylint: disable=singleton-comparison, g-explicit-bool-comparison
167
- name='Upload Reward Model TensorBoard Metrics',
168
- ):
169
- _ = upload_tensorboard_metrics.upload_tensorboard_metrics(
170
- tensorboard_resource_id=tensorboard_resource_id,
171
- metrics_directory=reward_model.outputs['tensorboard_metrics'],
172
- experiment_name=(
173
- 'reward-model-tuner-'
174
- f'{kfp.dsl.PIPELINE_JOB_ID_PLACEHOLDER}-'
175
- f'{kfp.dsl.PIPELINE_TASK_ID_PLACEHOLDER}'
176
- ),
177
- ).set_display_name('Reward Model TensorBoard Metrics Uploader')
178
187
  return PipelineOutput(
179
188
  reward_model_base_path=reference_model_metadata.outputs[
180
189
  'reward_model_path'
@@ -35,11 +35,14 @@ def reward_model_trainer(
35
35
  output_adapter_path: kfp.dsl.OutputPath(str), # pytype: disable=invalid-annotation
36
36
  tensorboard_metrics: kfp.dsl.Output[kfp.dsl.Artifact], # pytype: disable=unsupported-operands
37
37
  gcp_resources: kfp.dsl.OutputPath(str), # pytype: disable=invalid-annotation
38
+ eval_dataset_path: str = '',
38
39
  train_split: str = 'train',
39
40
  batch_size: int = 64,
40
41
  learning_rate_multiplier: float = 1.0,
41
42
  lora_dim: int = 4,
42
43
  num_microbatches: int = 0,
44
+ encryption_spec_key_name: str = '',
45
+ tensorboard_resource_id: str = '',
43
46
  ) -> kfp.dsl.ContainerSpec: # pylint: disable=g-doc-args
44
47
  """Trains a reward model.
45
48
 
@@ -48,6 +51,8 @@ def reward_model_trainer(
48
51
  location: Location used to run the job.
49
52
  input_model_path: Path to the base model to fine tune.
50
53
  input_dataset_path: Path to dataset to use to train a reward model.
54
+ eval_dataset_path: Path to eval dataset to use during the reward model
55
+ training.
51
56
  train_steps: Number of training steps. These are the number of steps on top
52
57
  of any steps used to train the base model.
53
58
  accelerator_type: Type of TPU accelerator. Can be either TPU_V2 or TPU_V3.
@@ -68,6 +73,13 @@ def reward_model_trainer(
68
73
  num_microbatches: Number of microbatches to break the total batch size into
69
74
  during training. If <= 1, the model is trained on the full batch size
70
75
  directly.
76
+ encryption_spec_key_name: Customer-managed encryption key. If this is set,
77
+ then all resources created by the CustomJob will be encrypted with the
78
+ provided encryption key. Note that this is not supported for TPU at the
79
+ moment.
80
+ tensorboard_resource_id: Optional tensorboard resource id. Format:
81
+ `projects/{project_number}/locations/{location}/tensorboards/{tensorboard_id}`.
82
+ If provided, tensorboard metrics will be uploaded to this location.
71
83
 
72
84
  Returns:
73
85
  output_adapter_path: Trained reward LoRA adapter.
@@ -85,9 +97,11 @@ def reward_model_trainer(
85
97
  machine_type=machine_type,
86
98
  image_uri=image_uri,
87
99
  args=[
100
+ '--app_name=reward_model_trainer',
88
101
  f'--train_steps={train_steps}',
89
102
  f'--input_model_path={input_model_path}',
90
103
  f'--input_dataset_path={input_dataset_path}',
104
+ f'--eval_dataset_path={eval_dataset_path}',
91
105
  f'--output_adapter_path={output_adapter_path}',
92
106
  f'--tensorboard_metrics_path={tensorboard_metrics.path}',
93
107
  f'--large_model_reference={large_model_reference}',
@@ -99,6 +113,9 @@ def reward_model_trainer(
99
113
  f'--lora_dim={lora_dim}',
100
114
  f'--num_microbatches={num_microbatches}',
101
115
  ],
116
+ encryption_spec_key_name=encryption_spec_key_name,
117
+ base_output_directory=tensorboard_metrics.uri,
118
+ tensorboard=tensorboard_resource_id,
102
119
  ),
103
120
  gcp_resources=gcp_resources,
104
121
  )
@@ -0,0 +1,60 @@
1
+ # Copyright 2024 The Kubeflow Authors. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Component that preprocesses inputs for Reinforcement Learning from Human Feedback (RLHF)."""
15
+
16
+ import os
17
+
18
+ from google_cloud_pipeline_components import _placeholders
19
+ from google_cloud_pipeline_components import utils as gcpc_utils
20
+ from google_cloud_pipeline_components._implementation.llm import utils
21
+ from kfp import dsl
22
+
23
+
24
+ @dsl.container_component
25
+ def rlhf_preprocessor(
26
+ gcp_resources: dsl.OutputPath(str), # pytype: disable=invalid-annotation
27
+ has_tensorboard_id: dsl.OutputPath(bool), # pytype: disable=invalid-annotation
28
+ has_inference_dataset: dsl.OutputPath(bool), # pytype: disable=invalid-annotation
29
+ evaluation_dataset: str = '',
30
+ tensorboard_resource_id: str = '',
31
+ image_uri: str = utils.get_default_image_uri('refined_cpu', ''),
32
+ ) -> dsl.ContainerSpec: # pylint: disable=g-doc-args
33
+ """Preprocess RLHF pipeline inputs.
34
+
35
+ Args:
36
+ evaluation_dataset: Path to evaluation data.
37
+ tensorboard_resource_id: TensorBoard resource id.
38
+
39
+ Returns:
40
+ gcp_resources: GCP resources that can be used to track the custom job.
41
+ has_tensorboard_id: Whether a tensorboard id is provided.
42
+ has_inference_dataset: Whether inference data are provided.
43
+ """
44
+ return gcpc_utils.build_serverless_customjob_container_spec(
45
+ project=_placeholders.PROJECT_ID_PLACEHOLDER,
46
+ location=_placeholders.LOCATION_PLACEHOLDER,
47
+ custom_job_payload=utils.build_payload(
48
+ display_name='rlhf_preprocessor',
49
+ machine_type='n1-standard-4',
50
+ image_uri=image_uri,
51
+ args=[
52
+ '--app_name=rlhf_preprocessor',
53
+ f'--evaluation_dataset={evaluation_dataset}',
54
+ f'--tensorboard_resource_id={tensorboard_resource_id}',
55
+ f'--has_tensorboard_id_path={has_tensorboard_id}',
56
+ f'--has_inference_dataset_path={has_inference_dataset}',
57
+ ],
58
+ ),
59
+ gcp_resources=gcp_resources,
60
+ )
@@ -86,6 +86,7 @@ def supervised_fine_tuner(
86
86
  machine_type=machine_type,
87
87
  image_uri=image_uri,
88
88
  args=[
89
+ '--app_name=supervised_fine_tuner',
89
90
  f'--input_model_path={input_model_path}',
90
91
  f'--train_steps={train_steps}',
91
92
  f'--inputs_sequence_length={inputs_sequence_length}',
@@ -30,6 +30,8 @@ def build_payload(
30
30
  encryption_spec_key_name: str = '',
31
31
  labels: Optional[Dict[str, str]] = None,
32
32
  scheduling: Optional[Dict[str, Any]] = None,
33
+ base_output_directory: Optional[str] = None,
34
+ tensorboard: Optional[str] = None,
33
35
  ) -> Dict[str, Any]:
34
36
  """Generates payload for a custom training job.
35
37
 
@@ -50,6 +52,11 @@ def build_payload(
50
52
  moment.
51
53
  labels: The labels with user-defined metadata to organize CustomJobs.
52
54
  scheduling: Scheduling options for a CustomJob.
55
+ base_output_directory: Cloud Storage location to store the output of this
56
+ CustomJob
57
+ tensorboard: The name of a Vertex AI TensorBoard resource to which this
58
+ CustomJob will upload TensorBoard logs. Format:
59
+ ``projects/{project}/locations/{location}/tensorboards/{tensorboard}``
53
60
 
54
61
  Returns:
55
62
  Custom job payload.
@@ -96,6 +103,14 @@ def build_payload(
96
103
  if scheduling:
97
104
  payload['job_spec']['scheduling'] = scheduling
98
105
 
106
+ if base_output_directory:
107
+ payload['job_spec']['base_output_directory'] = {
108
+ 'output_uri_prefix': base_output_directory
109
+ }
110
+
111
+ if tensorboard:
112
+ payload['job_spec']['tensorboard'] = tensorboard
113
+
99
114
  return payload
100
115
 
101
116
 
@@ -109,7 +124,10 @@ def get_temp_location() -> str:
109
124
  )
110
125
 
111
126
 
112
- def get_default_image_uri(image_name: str) -> str:
127
+ def get_default_image_uri(
128
+ image_name: str,
129
+ image_name_prefix: Optional[str] = None,
130
+ ) -> str:
113
131
  """Gets the default image URI for a given image.
114
132
 
115
133
  The URI is resolved using environment variables that define the artifact
@@ -119,6 +137,8 @@ def get_default_image_uri(image_name: str) -> str:
119
137
 
120
138
  Args:
121
139
  image_name: Name of the image to resolve.
140
+ image_name_prefix: prefix to add to the image name when constructing the
141
+ URI. If `None`, `env.PRIVATE_IMAGE_NAME_PREFIX'` is used.
122
142
 
123
143
  Returns:
124
144
  URI of the image.
@@ -128,9 +148,12 @@ def get_default_image_uri(image_name: str) -> str:
128
148
  else:
129
149
  image_tag = env.get_private_image_tag()
130
150
 
151
+ if image_name_prefix is None:
152
+ image_name_prefix = env.PRIVATE_IMAGE_NAME_PREFIX
153
+
131
154
  return '/'.join([
132
155
  f'{env.PRIVATE_ARTIFACT_REGISTRY_LOCATION}-docker.pkg.dev',
133
156
  env.PRIVATE_ARTIFACT_REGISTRY_PROJECT,
134
157
  env.PRIVATE_ARTIFACT_REGISTRY,
135
- f'{env.PRIVATE_IMAGE_NAME_PREFIX}{image_name}:{image_tag}',
158
+ f'{image_name_prefix}{image_name}:{image_tag}',
136
159
  ])
@@ -0,0 +1,113 @@
1
+ # Copyright 2024 The Kubeflow Authors. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """KFP Component for validate_pipeline."""
15
+
16
+ from typing import NamedTuple, Optional
17
+
18
+ from google_cloud_pipeline_components import _image
19
+ from google_cloud_pipeline_components import _placeholders
20
+ from kfp import dsl
21
+
22
+
23
+ @dsl.component(base_image=_image.GCPC_IMAGE_TAG, install_kfp_package=False)
24
+ def validate_pipeline(
25
+ location: str,
26
+ encryption_spec_key_name: str = '',
27
+ accelerator_type: str = '',
28
+ eval_dataset: Optional[str] = None,
29
+ ) -> NamedTuple('PreprocessedInputs', reward_model_eval_dataset=str):
30
+ # fmt: off
31
+ """Validates and preprocesses RLHF pipeline parameters.
32
+
33
+ Args:
34
+ location: Location used to run non-tuning components, i.e. components
35
+ that do not require accelerators. If not specified the location used
36
+ to run the pipeline will be used.
37
+ encryption_spec_key_name: If set, CMEK support will be validated.
38
+ accelerator_type: One of 'TPU' or 'GPU'. If 'TPU' is specified, tuning
39
+ components run in europe-west4. Otherwise tuning components run in
40
+ us-central1 on GPUs. Default is 'GPU'.
41
+ eval_dataset: Optional Cloud storage path to an evaluation dataset. The
42
+ format should match that of the preference dataset.
43
+ """
44
+ # fmt: on
45
+ # pylint: disable=g-import-not-at-top,import-outside-toplevel
46
+ import json
47
+ import logging
48
+ import re
49
+ import sys
50
+ import glob
51
+ # pylint: enable=g-import-not-at-top,import-outside-toplevel
52
+ outputs = NamedTuple(
53
+ 'PreprocessedInputs',
54
+ reward_model_eval_dataset=str,
55
+ )
56
+
57
+ try:
58
+ # [ Set eval_dataset
59
+ eval_dataset = eval_dataset or ''
60
+ gcs_eval_dataset_uri = re.sub('^gs://', '/gcs/', eval_dataset)
61
+ files_in_folder = glob.glob(gcs_eval_dataset_uri)
62
+ if not files_in_folder:
63
+ eval_dataset = ''
64
+ else:
65
+ first_file = files_in_folder[0]
66
+ required_fields = ('candidate_0', 'candidate_1', 'choice')
67
+ oneof_fields = {'input_text', 'messages'}
68
+ max_lines_to_check = 100
69
+ with open(first_file, 'r') as inputs:
70
+ for i, line in enumerate(inputs):
71
+ json_data = json.loads(line)
72
+ is_valid_preference_data = all(
73
+ field in json_data for field in required_fields
74
+ ) and any(oneof_field in json_data for oneof_field in oneof_fields)
75
+ if not is_valid_preference_data:
76
+ eval_dataset = ''
77
+ if not eval_dataset or i >= max_lines_to_check:
78
+ break
79
+ # ]
80
+ # [ Check CMEK
81
+ supported_pipeline_regions = {
82
+ 'europe-west4',
83
+ 'us-central1',
84
+ }
85
+ if location not in supported_pipeline_regions:
86
+ raise ValueError(
87
+ f'Unsupported pipeline region: {location}. Must be one of'
88
+ f' {supported_pipeline_regions}.'
89
+ )
90
+
91
+ valid_cmek_accelerator_types = {
92
+ 'GPU',
93
+ 'CPU', # Only used for testing.
94
+ }
95
+ valid_cmek_config = (
96
+ location == 'us-central1'
97
+ and accelerator_type in valid_cmek_accelerator_types
98
+ )
99
+ if encryption_spec_key_name and not valid_cmek_config:
100
+ raise ValueError(
101
+ 'encryption_spec_key_name (CMEK) is only supported for GPU training'
102
+ ' in us-central1. Please either unset encryption_spec_key_name or'
103
+ ' create your pipeline in us-central1 to use GPU instead.'
104
+ )
105
+ # CMEK ]
106
+
107
+ return outputs(reward_model_eval_dataset=eval_dataset)
108
+
109
+ except Exception as e: # pylint: disable=broad-exception-caught
110
+ if isinstance(e, ValueError):
111
+ raise
112
+ logging.exception(str(e))
113
+ sys.exit(13)
@@ -37,6 +37,7 @@ from google_cloud_pipeline_components._implementation.model_evaluation.llm_safet
37
37
  from google_cloud_pipeline_components._implementation.model_evaluation.llm_safety_bias.evaluation_llm_safety_bias_pipeline import evaluation_llm_safety_bias_pipeline
38
38
  from google_cloud_pipeline_components._implementation.model_evaluation.model_inference.component import model_inference_and_evaluation_component
39
39
  from google_cloud_pipeline_components._implementation.model_evaluation.model_inference.component import model_inference_component
40
+ from google_cloud_pipeline_components._implementation.model_evaluation.model_name_preprocessor.component import model_name_preprocessor as ModelNamePreprocessorOp
40
41
  from google_cloud_pipeline_components._implementation.model_evaluation.target_field_data_remover.component import target_field_data_remover as TargetFieldDataRemoverOp
41
42
  from google_cloud_pipeline_components._implementation.model_evaluation.text2sql.evaluation_llm_text2sql_pipeline import evaluation_llm_text2sql_pipeline
42
43
 
@@ -63,6 +64,7 @@ __all__ = [
63
64
  'ModelEvaluationFeatureAttributionOp',
64
65
  'ModelImportEvaluatedAnnotationOp',
65
66
  'ModelImportEvaluationOp',
67
+ 'ModelNamePreprocessorOp',
66
68
  'TargetFieldDataRemoverOp',
67
69
  'model_inference_component',
68
70
  'model_inference_and_evaluation_component',
@@ -24,7 +24,7 @@ from kfp.dsl import Output
24
24
  from kfp.dsl import OutputPath
25
25
  from kfp.dsl import PIPELINE_ROOT_PLACEHOLDER
26
26
 
27
- _IMAGE_URI = 'us-docker.pkg.dev/vertex-evaluation/public/llm:wjess-fishfooding'
27
+ _IMAGE_URI = 'us-docker.pkg.dev/vertex-evaluation/public/llm:v0.5'
28
28
 
29
29
 
30
30
  @dsl.component(base_image=version.LLM_EVAL_IMAGE_TAG)