From 33817780b72bdc09d78f5b331d6a4fc87a547978 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 30 Jul 2026 10:26:44 +0000 Subject: [PATCH 1/4] Allow prediction/label to be text (generative tasks), not just numeric Adds first-class support for string predictions/labels (e.g. an LLM's generated reply as "prediction", a reference/target string as "label") throughout the framework, additive alongside the existing numeric classification/segmentation/detection path so nothing there changes. - src.py: save_signals' to_numpy/normalize no longer force strings through the classification-label uint16 cast (which raised ValueError on non-numeric text) -- native str values pass through unwrapped. - trainer_tools.py: get_data_set_representation routes string label/prediction values to new RecordMetadata.sample_label_text / sample_prediction_text proto fields instead of crashing on int(target)/int(pred). Numeric tasks are unaffected. - data_service.py: _process_sample_row's classification/tabular label/prediction branches emit a string DataStat (type="string", value_string=...) for text values instead of silently dropping them after a failed float() cast. Also fixes a latent bug in the "is this label empty" file-path heuristic that misclassified ordinary multi-sentence text (any string with a non-trailing '.') as an empty label to be reloaded -- extracted to looks_like_file_path_label() and narrowed to require a short alphanumeric extension, so it still detects real file paths (e.g. "mask.png") without misfiring on text. - experiment_service.proto: additive repeated string sample_label_text/sample_prediction_text fields on RecordMetadata; regenerated pb2 stubs with the pinned grpcio-tools~=1.68 toolchain (matches this repo's documented Colab-compatibility constraint). Full test suite passes (1018 passed, 133 skipped, 0 failures). --- tests/general/test_signals.py | 37 +++ .../test_data_service_text_predictions.py | 148 ++++++++++++ tests/trainer/test_trainer_tools.py | 51 ++++ weightslab/proto/experiment_service.proto | 7 + weightslab/proto/experiment_service_pb2.py | 222 +++++++++--------- .../proto/experiment_service_pb2_grpc.py | 4 +- weightslab/src.py | 14 ++ weightslab/trainer/services/data_service.py | 57 ++++- weightslab/trainer/trainer_tools.py | 30 ++- 9 files changed, 454 insertions(+), 116 deletions(-) create mode 100644 tests/trainer/services/test_data_service_text_predictions.py diff --git a/tests/general/test_signals.py b/tests/general/test_signals.py index f9281417..c2942a85 100644 --- a/tests/general/test_signals.py +++ b/tests/general/test_signals.py @@ -641,6 +641,43 @@ def test_save_signals_with_dict_predictions(self, mock_gm, mock_get_dataframe): self.assertTrue(mock_df.enqueue_batch.called) + @patch("weightslab.src.get_dataframe") + @patch("weightslab.src._gm") + def test_save_signals_with_string_predictions(self, mock_gm, mock_get_dataframe): + """Test save_signals with TEXT predictions/labels (e.g. a generative + model's reply and its reference/target text). Must not crash (the + pre-fix behavior raised ValueError from the classification-label + uint16 cast on non-numeric strings) and must forward native Python + str values, unwrapped, so downstream RecordMetadata/DataStat + construction sees a real str rather than a 0-d numpy array.""" + mock_df = MagicMock() + mock_get_dataframe.return_value = mock_df + + mock_model = MagicMock() + mock_model.current_step = 1 + mock_gm.return_value = mock_model + + with patch("weightslab.src.DATAFRAME_M", mock_df): + batch_ids = torch.tensor([1, 2]) + signals = {"loss": torch.tensor(0.5)} + preds = ["Certainly! Here is the answer to your question.", "I don't know."] + targets = ["The expected reference answer.", "Another reference answer."] + + wl.save_signals( + signals=signals, + batch_ids=batch_ids, + preds=preds, + targets=targets, + log=True + ) + + self.assertTrue(mock_df.enqueue_batch.called) + _, kwargs = mock_df.enqueue_batch.call_args + self.assertEqual(kwargs["preds"], preds) + self.assertEqual(kwargs["targets"], targets) + for value in kwargs["preds"] + kwargs["targets"]: + self.assertIsInstance(value, str) + # ========================================================================= # Signal Composition and Combination Tests # ========================================================================= diff --git a/tests/trainer/services/test_data_service_text_predictions.py b/tests/trainer/services/test_data_service_text_predictions.py new file mode 100644 index 00000000..a8ac43da --- /dev/null +++ b/tests/trainer/services/test_data_service_text_predictions.py @@ -0,0 +1,148 @@ +"""Unit tests for TEXT label/prediction support in data_service.py. + +Covers two things added for generative tasks (e.g. an LLM's generated reply +as "prediction", a reference/target string as "label"): + +1. `looks_like_file_path_label` -- the heuristic that decides whether a + string label is "empty" (a segmentation mask path with nothing loaded + yet) vs. real text that must be preserved as-is. +2. `DataService._process_sample_row`'s classification/tabular branches, + which must emit a string DataStat (name='target'/'pred', type='string', + value_string=...) for text values instead of crashing on float(label)/ + float(pred) and silently dropping the stat. +""" + +import unittest + +from weightslab.data.sample_stats import SampleStatsEx +from weightslab.proto import experiment_service_pb2 as pb2 +from weightslab.trainer.services.data_service import ( + DataService, + looks_like_file_path_label, +) + + +class TestLooksLikeFilePathLabel(unittest.TestCase): + def test_true_for_segmentation_mask_paths(self): + self.assertTrue(looks_like_file_path_label("mask.png")) + self.assertTrue(looks_like_file_path_label("/data/masks/sample_001.jpg")) + self.assertTrue(looks_like_file_path_label("label.tif")) + + def test_false_for_free_text_without_trailing_period(self): + # The exact regression this heuristic used to misfire on: ordinary + # multi-sentence text that doesn't end with a period. + self.assertFalse(looks_like_file_path_label( + "Certainly! Let's break this down. Here is more info")) + self.assertFalse(looks_like_file_path_label("See section 2.5 for details")) + + def test_false_for_free_text_with_trailing_period(self): + self.assertFalse(looks_like_file_path_label("The reference answer.")) + + def test_false_for_non_string_or_no_period(self): + self.assertFalse(looks_like_file_path_label(None)) + self.assertFalse(looks_like_file_path_label(42)) + self.assertFalse(looks_like_file_path_label("no period here")) + + +class _StubDataService: + """Minimal duck-typed stand-in for DataService -- _process_sample_row + only touches self._ctx / self._get_dataset / self._is_metadata_only_request + / self._is_nan_value, so a full instance with real gRPC/context wiring + isn't needed to exercise its label/pred string-handling branches.""" + + def __init__(self): + self._ctx = None + + def _get_dataset(self, origin): + return None + + def _is_metadata_only_request(self, request): + return DataService._is_metadata_only_request(self, request) + + def _is_nan_value(self, value): + return DataService._is_nan_value(self, value) + + +def _find_stat(data_stats, name): + return next((s for s in data_stats if s.name == name), None) + + +class TestProcessSampleRowTextLabelPrediction(unittest.TestCase): + def setUp(self): + self.service = _StubDataService() + # resize_width/height > 0 so _is_metadata_only_request returns False + # and the label/prediction branches actually run (an all-defaults + # request is treated as a metadata-only histogram sweep that skips + # them entirely). + self.request = pb2.DataSamplesRequest(resize_width=32, resize_height=32) + + def _process(self, row): + data_record = DataService._process_sample_row(self.service, (row, self.request, None)) + self.assertIsNotNone(data_record, "record processing raised internally (see logged exception)") + return list(data_record.data_stats) + + def test_text_label_and_prediction_become_string_data_stats(self): + row = { + SampleStatsEx.SAMPLE_ID.value: "1", + SampleStatsEx.ORIGIN.value: "train_loader", + SampleStatsEx.TASK_TYPE.value: "classification", + SampleStatsEx.TARGET.value: "The reference/target answer.", + SampleStatsEx.PREDICTION.value: "The model's generated reply.", + } + data_stats = self._process(row) + + target_stat = _find_stat(data_stats, "target") + pred_stat = _find_stat(data_stats, "pred") + + self.assertIsNotNone(target_stat) + self.assertEqual(target_stat.type, "string") + self.assertEqual(target_stat.value_string, "The reference/target answer.") + + self.assertIsNotNone(pred_stat) + self.assertEqual(pred_stat.type, "string") + self.assertEqual(pred_stat.value_string, "The model's generated reply.") + + def test_multi_sentence_text_without_trailing_period_is_not_dropped(self): + # Regression: the old is_label_empty heuristic would misclassify + # this as a "file path" (contains a '.', doesn't end in one) and + # treat it as empty, discarding it instead of emitting a stat. + row = { + SampleStatsEx.SAMPLE_ID.value: "2", + SampleStatsEx.ORIGIN.value: "train_loader", + SampleStatsEx.TASK_TYPE.value: "classification", + SampleStatsEx.TARGET.value: "Sure. Here is a multi-sentence answer without a period at the end", + SampleStatsEx.PREDICTION.value: "Sure. Here is the reply without a period at the end", + } + data_stats = self._process(row) + + target_stat = _find_stat(data_stats, "target") + pred_stat = _find_stat(data_stats, "pred") + self.assertIsNotNone(target_stat) + self.assertEqual(target_stat.type, "string") + self.assertIsNotNone(pred_stat) + self.assertEqual(pred_stat.type, "string") + + def test_numeric_classification_label_and_prediction_unaffected(self): + """Backward-compat guard: existing numeric classification labels + must still produce scalar DataStats, unaffected by the text path.""" + row = { + SampleStatsEx.SAMPLE_ID.value: "3", + SampleStatsEx.ORIGIN.value: "train_loader", + SampleStatsEx.TASK_TYPE.value: "classification", + SampleStatsEx.TARGET.value: 1, + SampleStatsEx.PREDICTION.value: 0, + } + data_stats = self._process(row) + + target_stat = _find_stat(data_stats, "target") + pred_stat = _find_stat(data_stats, "pred") + self.assertIsNotNone(target_stat) + self.assertEqual(target_stat.type, "scalar") + self.assertEqual(list(target_stat.value), [1.0]) + self.assertIsNotNone(pred_stat) + self.assertEqual(pred_stat.type, "scalar") + self.assertEqual(list(pred_stat.value), [0.0]) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/trainer/test_trainer_tools.py b/tests/trainer/test_trainer_tools.py index d1e60908..6f9eb85f 100644 --- a/tests/trainer/test_trainer_tools.py +++ b/tests/trainer/test_trainer_tools.py @@ -12,6 +12,7 @@ _class_ids, _get_input_tensor_for_sample, _labels_from_mask_path_histogram, + _numeric_or_text_list, execute_df_operation, force_kill_all_python_processes, generate_overview, @@ -110,6 +111,8 @@ def __init__(self, **kwargs): self.task_type = kwargs.get("task_type", "") self.sample_label = [] self.sample_prediction = [] + self.sample_label_text = [] + self.sample_prediction_text = [] class _FakeSampleStats: def __init__(self): @@ -143,6 +146,54 @@ def __init__(self): self.assertEqual(list(seg_stats.records[0].sample_label), [0, 1, 2]) self.assertEqual(list(seg_stats.records[0].sample_prediction), [1, 2, 4]) + def test_numeric_or_text_list(self): + self.assertEqual(_numeric_or_text_list("a generated reply"), ([], ["a generated reply"])) + self.assertEqual(_numeric_or_text_list(3), ([3], [])) + self.assertEqual(_numeric_or_text_list([3]), ([3], [])) + self.assertEqual(_numeric_or_text_list(np.array([3])), ([3], [])) + self.assertEqual(_numeric_or_text_list(["only one string in a list"]), ([], ["only one string in a list"])) + + def test_get_data_set_representation_text_label_and_prediction(self): + """A generative task (e.g. an LLM's reply as prediction, a reference + string as label) must route through the new text fields instead of + crashing on int(target)/int(pred).""" + exp = _Experiment() + + class _FakeRecord: + def __init__(self, **kwargs): + self.sample_id = kwargs.get("sample_id") + self.sample_last_loss = kwargs.get("sample_last_loss", -1.0) + self.sample_discarded = kwargs.get("sample_discarded", False) + self.task_type = kwargs.get("task_type", "") + self.sample_label = [] + self.sample_prediction = [] + self.sample_label_text = [] + self.sample_prediction_text = [] + + class _FakeSampleStats: + def __init__(self): + self.sample_count = 0 + self.task_type = "" + self.records = [] + + text_rows = [ + { + "sample_id": "30", + "prediction_loss": 0.1, + "label": "The reference/target answer.", + "prediction_raw": "The model's generated reply.", + "discarded": False, + }, + ] + + with patch("weightslab.trainer.trainer_tools.pb2.SampleStatistics", side_effect=_FakeSampleStats), \ + patch("weightslab.trainer.trainer_tools.pb2.RecordMetadata", side_effect=lambda **kw: _FakeRecord(**kw)): + text_stats = get_data_set_representation(_SimpleDataset(text_rows), exp) + self.assertEqual(list(text_stats.records[0].sample_label), []) + self.assertEqual(list(text_stats.records[0].sample_prediction), []) + self.assertEqual(list(text_stats.records[0].sample_label_text), ["The reference/target answer."]) + self.assertEqual(list(text_stats.records[0].sample_prediction_text), ["The model's generated reply."]) + def test_load_raw_image_from_images_and_tensor_input(self): with tempfile.TemporaryDirectory() as tmp: p = os.path.join(tmp, "img.png") diff --git a/weightslab/proto/experiment_service.proto b/weightslab/proto/experiment_service.proto index 1ef26108..5af5e9dd 100644 --- a/weightslab/proto/experiment_service.proto +++ b/weightslab/proto/experiment_service.proto @@ -278,6 +278,13 @@ message RecordMetadata { repeated TaskField extra_fields = 7; bytes prediction_raw = 9; string task_type = 10; + // Text label/prediction (e.g. a generative model's target/reference text + // and its generated reply) -- additive, alongside the int32 fields above + // rather than replacing them, so existing classification/segmentation/ + // detection consumers that populate sample_label/sample_prediction are + // completely unaffected. Empty/unset for numeric-label tasks. + repeated string sample_label_text = 11; + repeated string sample_prediction_text = 12; } message SampleStatistics { diff --git a/weightslab/proto/experiment_service_pb2.py b/weightslab/proto/experiment_service_pb2.py index 2b1bb54a..cc5a26a9 100644 --- a/weightslab/proto/experiment_service_pb2.py +++ b/weightslab/proto/experiment_service_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: weightslab/proto/experiment_service.proto -# Protobuf Python Version: 6.31.1 +# Protobuf Python Version: 5.28.1 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -11,8 +11,8 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, - 6, - 31, + 5, + 28, 1, '', 'weightslab/proto/experiment_service.proto' @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n)weightslab/proto/experiment_service.proto\"\x89\x01\n\x1aGetLatestLoggerDataRequest\x12\x1c\n\x14request_full_history\x18\x01 \x01(\x08\x12\x12\n\nmax_points\x18\x02 \x01(\x05\x12\x17\n\x0f\x62reak_by_slices\x18\x03 \x01(\x08\x12\x0c\n\x04tags\x18\x04 \x03(\t\x12\x12\n\ngraph_name\x18\x05 \x01(\t\"\x81\x02\n\x0fLoggerDataPoint\x12\x13\n\x0bmetric_name\x18\x01 \x01(\t\x12\x11\n\tmodel_age\x18\x02 \x01(\x05\x12\x14\n\x0cmetric_value\x18\x03 \x01(\x02\x12\x17\n\x0f\x65xperiment_hash\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x03\x12\x11\n\tsample_id\x18\x06 \x01(\t\x12\x1c\n\x14is_evaluation_marker\x18\x07 \x01(\x08\x12\x12\n\nsplit_name\x18\x08 \x01(\t\x12\x17\n\x0f\x65valuation_tags\x18\t \x03(\t\x12\x12\n\npoint_note\x18\n \x01(\t\x12\x12\n\naudit_mode\x18\x0b \x01(\x08\"[\n\x1bGetLatestLoggerDataResponse\x12 \n\x06points\x18\x01 \x03(\x0b\x32\x10.LoggerDataPoint\x12\x1a\n\x12weightslab_version\x18\x02 \x01(\t\"\x07\n\x05\x45mpty\"/\n\x08NeuronId\x12\x10\n\x08layer_id\x18\x01 \x01(\x05\x12\x11\n\tneuron_id\x18\x02 \x01(\x05\"\x91\x02\n\x0fWeightOperation\x12*\n\x07op_type\x18\x01 \x01(\x0e\x32\x14.WeightOperationTypeH\x00\x88\x01\x01\x12\x15\n\x08layer_id\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x1d\n\nneuron_ids\x18\x03 \x03(\x0b\x32\t.NeuronId\x12\x16\n\x0eneurons_to_add\x18\t \x01(\x05\x12 \n\x18zerofy_from_incoming_ids\x18\x0b \x03(\x05\x12\x1c\n\x14zerofy_to_neuron_ids\x18\x0c \x03(\x05\x12+\n\x11zerofy_predicates\x18\r \x03(\x0e\x32\x10.ZerofyPredicateB\n\n\x08_op_typeB\x0b\n\t_layer_id\"_\n\x17WeightsOperationRequest\x12/\n\x10weight_operation\x18\x01 \x01(\x0b\x32\x10.WeightOperationH\x00\x88\x01\x01\x42\x13\n\x11_weight_operation\"<\n\x18WeightsOperationResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"\xc1\x05\n\x0fHyperParameters\x12\x1c\n\x0f\x65xperiment_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12!\n\x14training_steps_to_do\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x1a\n\rlearning_rate\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x17\n\nbatch_size\x18\x04 \x01(\x05H\x03\x88\x01\x01\x12 \n\x13\x66ull_eval_frequency\x18\x05 \x01(\x05H\x04\x88\x01\x01\x12 \n\x13\x63heckpont_frequency\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x18\n\x0bis_training\x18\x07 \x01(\x08H\x06\x88\x01\x01\x12\x15\n\x08nb_steps\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x19\n\x0c\x61uditor_mode\x18\t \x01(\x08H\x08\x88\x01\x01\x12\x1d\n\x10train_batch_size\x18\n \x01(\x05H\t\x88\x01\x01\x12\x1b\n\x0eval_batch_size\x18\x0b \x01(\x05H\n\x88\x01\x01\x12\x1c\n\x0ftest_batch_size\x18\x0c \x01(\x05H\x0b\x88\x01\x01\x12\x1c\n\x0f\x65valuation_mode\x18\r \x01(\x08H\x0c\x88\x01\x01\x12\x1e\n\x11\x65valuation_config\x18\x0e \x01(\tH\r\x88\x01\x01\x42\x12\n\x10_experiment_nameB\x17\n\x15_training_steps_to_doB\x10\n\x0e_learning_rateB\r\n\x0b_batch_sizeB\x16\n\x14_full_eval_frequencyB\x16\n\x14_checkpont_frequencyB\x0e\n\x0c_is_trainingB\x0b\n\t_nb_stepsB\x0f\n\r_auditor_modeB\x13\n\x11_train_batch_sizeB\x11\n\x0f_val_batch_sizeB\x12\n\x10_test_batch_sizeB\x12\n\x10_evaluation_modeB\x14\n\x12_evaluation_config\",\n\rMetricsStatus\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02\"~\n\rAnnotatStatus\x12\x0c\n\x04name\x18\x01 \x01(\t\x12.\n\x08metadata\x18\x02 \x03(\x0b\x32\x1c.AnnotatStatus.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\"\x90\x02\n\x10TrainingStatusEx\x12\x16\n\ttimestamp\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x65xperiment_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x16\n\tmodel_age\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12+\n\x0emetrics_status\x18\x04 \x01(\x0b\x32\x0e.MetricsStatusH\x03\x88\x01\x01\x12+\n\x0e\x61nnotat_status\x18\x05 \x01(\x0b\x32\x0e.AnnotatStatusH\x04\x88\x01\x01\x42\x0c\n\n_timestampB\x12\n\x10_experiment_nameB\x0c\n\n_model_ageB\x11\n\x0f_metrics_statusB\x11\n\x0f_annotat_status\"]\n\x15HyperParameterCommand\x12/\n\x10hyper_parameters\x18\x01 \x01(\x0b\x32\x10.HyperParametersH\x00\x88\x01\x01\x42\x13\n\x11_hyper_parameters\">\n\x14\x44\x65nySamplesOperation\x12\x12\n\nsample_ids\x18\x01 \x03(\t\x12\x12\n\naccumulate\x18\x02 \x01(\x08\"0\n\x17LoadCheckpointOperation\x12\x15\n\rcheckpoint_id\x18\x01 \x01(\x05\"b\n\x11PlotNoteOperation\x12\x13\n\x0bmetric_name\x18\x01 \x01(\t\x12\x17\n\x0f\x65xperiment_hash\x18\x02 \x01(\t\x12\x11\n\tmodel_age\x18\x03 \x01(\x05\x12\x0c\n\x04note\x18\x04 \x01(\t\"L\n\x17SaveCheckpointOperation\x12\x19\n\x11save_architecture\x18\x01 \x01(\x08\x12\x16\n\x0esave_optimizer\x18\x02 \x01(\x08\"\x1a\n\x18RestartInstanceOperation\"\x8d\x08\n\x0eTrainerCommand\x12\x1c\n\x14get_hyper_parameters\x18\x04 \x01(\x08\x12\x1e\n\x16get_interactive_layers\x18\x05 \x01(\x08\x12\x1d\n\x10get_data_records\x18\x06 \x01(\tH\x00\x88\x01\x01\x12%\n\x18get_single_layer_info_id\x18\x08 \x01(\x05H\x01\x88\x01\x01\x12;\n\x16hyper_parameter_change\x18\x01 \x01(\x0b\x32\x16.HyperParameterCommandH\x02\x88\x01\x01\x12:\n\x16\x64\x65ny_samples_operation\x18\x07 \x01(\x0b\x32\x15.DenySamplesOperationH\x03\x88\x01\x01\x12?\n\x1b\x64\x65ny_eval_samples_operation\x18\n \x01(\x0b\x32\x15.DenySamplesOperationH\x04\x88\x01\x01\x12@\n\x19load_checkpoint_operation\x18\t \x01(\x0b\x32\x18.LoadCheckpointOperationH\x05\x88\x01\x01\x12\x42\n\x1eremove_from_denylist_operation\x18\x0b \x01(\x0b\x32\x15.DenySamplesOperationH\x06\x88\x01\x01\x12G\n#remove_eval_from_denylist_operation\x18\x0c \x01(\x0b\x32\x15.DenySamplesOperationH\x07\x88\x01\x01\x12\x34\n\x13plot_note_operation\x18\r \x01(\x0b\x32\x12.PlotNoteOperationH\x08\x88\x01\x01\x12@\n\x19save_checkpoint_operation\x18\x0e \x01(\x0b\x32\x18.SaveCheckpointOperationH\t\x88\x01\x01\x12\x39\n\x11restart_operation\x18\x0f \x01(\x0b\x32\x19.RestartInstanceOperationH\n\x88\x01\x01\x42\x13\n\x11_get_data_recordsB\x1b\n\x19_get_single_layer_info_idB\x19\n\x17_hyper_parameter_changeB\x19\n\x17_deny_samples_operationB\x1e\n\x1c_deny_eval_samples_operationB\x1c\n\x1a_load_checkpoint_operationB!\n\x1f_remove_from_denylist_operationB&\n$_remove_eval_from_denylist_operationB\x16\n\x14_plot_note_operationB\x1c\n\x1a_save_checkpoint_operationB\x14\n\x12_restart_operation\"\x9d\x01\n\x12HyperParameterDesc\x12\r\n\x05label\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0c\n\x04type\x18\x03 \x01(\t\x12\x1c\n\x0fnumerical_value\x18\x04 \x01(\x02H\x00\x88\x01\x01\x12\x19\n\x0cstring_value\x18\x05 \x01(\tH\x01\x88\x01\x01\x42\x12\n\x10_numerical_valueB\x0f\n\r_string_value\"\xf2\x02\n\x10NeuronStatistics\x12!\n\tneuron_id\x18\x01 \x01(\x0b\x32\t.NeuronIdH\x00\x88\x01\x01\x12\x17\n\nneuron_age\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x1f\n\x12train_trigger_rate\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x1e\n\x11\x65val_trigger_rate\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x1a\n\rlearning_rate\x18\x07 \x01(\x02H\x04\x88\x01\x01\x12\x36\n\x0bincoming_lr\x18\x08 \x03(\x0b\x32!.NeuronStatistics.IncomingLrEntry\x1a\x31\n\x0fIncomingLrEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x42\x0c\n\n_neuron_idB\r\n\x0b_neuron_ageB\x15\n\x13_train_trigger_rateB\x14\n\x12_eval_trigger_rateB\x10\n\x0e_learning_rate\"\xf0\x02\n\x13LayerRepresentation\x12\x15\n\x08layer_id\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x17\n\nlayer_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x17\n\nlayer_type\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1a\n\rneurons_count\x18\x04 \x01(\x05H\x03\x88\x01\x01\x12#\n\x16incoming_neurons_count\x18\x05 \x01(\x05H\x04\x88\x01\x01\x12\x18\n\x0bkernel_size\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x13\n\x06stride\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12-\n\x12neurons_statistics\x18\n \x03(\x0b\x32\x11.NeuronStatisticsB\x0b\n\t_layer_idB\r\n\x0b_layer_nameB\r\n\x0b_layer_typeB\x10\n\x0e_neurons_countB\x19\n\x17_incoming_neurons_countB\x0e\n\x0c_kernel_sizeB\t\n\x07_stride\"H\n\x11\x41\x63tivationRequest\x12\x10\n\x08layer_id\x18\x01 \x01(\x05\x12\x11\n\tsample_id\x18\x02 \x01(\t\x12\x0e\n\x06origin\x18\x03 \x01(\t\"H\n\rActivationMap\x12\x11\n\tneuron_id\x18\x01 \x01(\x05\x12\x0e\n\x06values\x18\x02 \x03(\x02\x12\t\n\x01H\x18\x03 \x01(\x05\x12\t\n\x01W\x18\x04 \x01(\x05\"d\n\x12\x41\x63tivationResponse\x12\x12\n\nlayer_type\x18\x01 \x01(\t\x12\x15\n\rneurons_count\x18\x02 \x01(\x05\x12#\n\x0b\x61\x63tivations\x18\x03 \x03(\x0b\x32\x0e.ActivationMap\"\x93\x01\n\tTaskField\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x15\n\x0b\x66loat_value\x18\x02 \x01(\x02H\x00\x12\x13\n\tint_value\x18\x03 \x01(\x05H\x00\x12\x16\n\x0cstring_value\x18\x04 \x01(\tH\x00\x12\x15\n\x0b\x62ytes_value\x18\x05 \x01(\x0cH\x00\x12\x14\n\nbool_value\x18\x06 \x01(\x08H\x00\x42\x07\n\x05value\"\xcc\x02\n\x0eRecordMetadata\x12\x11\n\tsample_id\x18\x01 \x01(\t\x12\x14\n\x0csample_label\x18\x02 \x03(\x05\x12\x19\n\x11sample_prediction\x18\x03 \x03(\x05\x12=\n\x10sample_last_loss\x18\x04 \x03(\x0b\x32#.RecordMetadata.SampleLastLossEntry\x12\x19\n\x11sample_encounters\x18\x05 \x01(\x05\x12\x18\n\x10sample_discarded\x18\x06 \x01(\x08\x12 \n\x0c\x65xtra_fields\x18\x07 \x03(\x0b\x32\n.TaskField\x12\x16\n\x0eprediction_raw\x18\t \x01(\x0c\x12\x11\n\ttask_type\x18\n \x01(\t\x1a\x35\n\x13SampleLastLossEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\"\x93\x01\n\x10SampleStatistics\x12\x13\n\x06origin\x18\x06 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0csample_count\x18\x07 \x01(\x05H\x01\x88\x01\x01\x12\x11\n\ttask_type\x18\t \x01(\t\x12 \n\x07records\x18\x08 \x03(\x0b\x32\x0f.RecordMetadataB\t\n\x07_originB\x0f\n\r_sample_count\"\xe6\x01\n\x0f\x43ommandResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x33\n\x16hyper_parameters_descs\x18\x03 \x03(\x0b\x32\x13.HyperParameterDesc\x12\x33\n\x15layer_representations\x18\x04 \x03(\x0b\x32\x14.LayerRepresentation\x12\x31\n\x11sample_statistics\x18\x05 \x01(\x0b\x32\x11.SampleStatisticsH\x00\x88\x01\x01\x42\x14\n\x12_sample_statistics\"U\n\rSampleRequest\x12\x16\n\tsample_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06origin\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x0c\n\n_sample_idB\t\n\x07_origin\"\xad\x02\n\x15SampleRequestResponse\x12\x16\n\tsample_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06origin\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x12\n\x05label\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x11\n\x04\x64\x61ta\x18\x04 \x01(\x0cH\x03\x88\x01\x01\x12\x1a\n\rerror_message\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x15\n\x08raw_data\x18\x06 \x01(\x0cH\x05\x88\x01\x01\x12\x11\n\x04mask\x18\x07 \x01(\x0cH\x06\x88\x01\x01\x12\x17\n\nprediction\x18\x08 \x01(\x0cH\x07\x88\x01\x01\x42\x0c\n\n_sample_idB\t\n\x07_originB\x08\n\x06_labelB\x07\n\x05_dataB\x10\n\x0e_error_messageB\x0b\n\t_raw_dataB\x07\n\x05_maskB\r\n\x0b_prediction\"\x92\x01\n\x12\x42\x61tchSampleRequest\x12\x12\n\nsample_ids\x18\x01 \x03(\t\x12\x0e\n\x06origin\x18\x02 \x01(\t\x12\x19\n\x0cresize_width\x18\x03 \x01(\x05H\x00\x88\x01\x01\x12\x1a\n\rresize_height\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\x0f\n\r_resize_widthB\x10\n\x0e_resize_height\">\n\x13\x42\x61tchSampleResponse\x12\'\n\x07samples\x18\x01 \x03(\x0b\x32\x16.SampleRequestResponse\".\n\x0eWeightsRequest\x12\x1c\n\tneuron_id\x18\x01 \x01(\x0b\x32\t.NeuronId\"\x9d\x02\n\x0fWeightsResponse\x12\x1c\n\tneuron_id\x18\x01 \x01(\x0b\x32\t.NeuronId\x12\x17\n\nlayer_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nlayer_type\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x10\n\x08incoming\x18\x04 \x01(\x05\x12\x10\n\x08outgoing\x18\x05 \x01(\x05\x12\x18\n\x0bkernel_size\x18\x06 \x01(\x05H\x02\x88\x01\x01\x12\x0f\n\x07weights\x18\x07 \x03(\x02\x12\x0f\n\x07success\x18\x0b \x01(\x08\x12\x1a\n\rerror_message\x18\x0c \x01(\tH\x03\x88\x01\x01\x42\r\n\x0b_layer_nameB\r\n\x0b_layer_typeB\x0e\n\x0c_kernel_sizeB\x10\n\x0e_error_message\"R\n\x10\x44\x61taQueryRequest\x12\r\n\x05query\x18\x01 \x01(\t\x12\x12\n\naccumulate\x18\x02 \x01(\x08\x12\x1b\n\x13is_natural_language\x18\x03 \x01(\x08\"5\n\x11\x43\x61tegoricalTagDef\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\ncategories\x18\x02 \x03(\t\"\xa9\x02\n\x11\x44\x61taQueryResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x1d\n\x15number_of_all_samples\x18\x03 \x01(\x05\x12%\n\x1dnumber_of_samples_in_the_loop\x18\x04 \x01(\x05\x12#\n\x1bnumber_of_discarded_samples\x18\x05 \x01(\x05\x12\x13\n\x0bunique_tags\x18\x06 \x03(\t\x12+\n\x11\x61gent_intent_type\x18\x07 \x01(\x0e\x32\x10.AgentIntentType\x12\x17\n\x0f\x61nalysis_result\x18\x08 \x01(\t\x12,\n\x10\x63\x61tegorical_tags\x18\t \x03(\x0b\x32\x12.CategoricalTagDef\"\xc2\x01\n\x12\x44\x61taSamplesRequest\x12\x13\n\x0bstart_index\x18\x01 \x01(\x05\x12\x13\n\x0brecords_cnt\x18\x02 \x01(\x05\x12 \n\x18include_transformed_data\x18\x03 \x01(\x08\x12\x18\n\x10include_raw_data\x18\x04 \x01(\x08\x12\x19\n\x11stats_to_retrieve\x18\x05 \x03(\t\x12\x14\n\x0cresize_width\x18\x06 \x01(\x05\x12\x15\n\rresize_height\x18\x07 \x01(\x05\"m\n\x08\x44\x61taStat\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\r\n\x05shape\x18\x03 \x03(\x05\x12\r\n\x05value\x18\x04 \x03(\x02\x12\x14\n\x0cvalue_string\x18\x05 \x01(\t\x12\x11\n\tthumbnail\x18\x06 \x01(\x0c\">\n\nDataRecord\x12\x11\n\tsample_id\x18\x01 \x01(\t\x12\x1d\n\ndata_stats\x18\x02 \x03(\x0b\x32\t.DataStat\"Z\n\x13\x44\x61taSamplesResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12!\n\x0c\x64\x61ta_records\x18\x03 \x03(\x0b\x32\x0b.DataRecord\"C\n\x0fHistogramSubBar\x12\x0e\n\x06origin\x18\x01 \x01(\t\x12\x11\n\tdiscarded\x18\x02 \x01(\x08\x12\r\n\x05\x63ount\x18\x03 \x01(\x03\"h\n\x0cHistogramBin\x12\x0b\n\x03min\x18\x01 \x01(\x01\x12\x0b\n\x03max\x18\x02 \x01(\x01\x12\x0b\n\x03\x61vg\x18\x03 \x01(\x01\x12\r\n\x05\x63ount\x18\x04 \x01(\x03\x12\"\n\x08sub_bars\x18\x05 \x03(\x0b\x32\x10.HistogramSubBar\"[\n\x17\x43\x61tegoricalHistogramBar\x12\r\n\x05label\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x02 \x01(\x03\x12\"\n\x08sub_bars\x18\x03 \x03(\x0b\x32\x10.HistogramSubBar\"4\n\x10HistogramRequest\x12\x0e\n\x06\x63olumn\x18\x01 \x01(\t\x12\x10\n\x08max_bins\x18\x02 \x01(\x05\"\xb2\x01\n\x11HistogramResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x12\n\ntotal_rows\x18\x03 \x01(\x03\x12\x1b\n\x04\x62ins\x18\x04 \x03(\x0b\x32\r.HistogramBin\x12\x16\n\x0eis_categorical\x18\x05 \x01(\x08\x12\x32\n\x10\x63\x61tegorical_bars\x18\x06 \x03(\x0b\x32\x18.CategoricalHistogramBar\"W\n\x12GetMetaDataRequest\x12\x13\n\x0bstart_index\x18\x01 \x01(\x05\x12\x13\n\x0brecords_cnt\x18\x02 \x01(\x05\x12\x17\n\x0fmodal_sample_id\x18\x03 \x01(\t\"\x99\x01\n\x13GetMetaDataResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x1a\n\x12\x61ll_metadata_names\x18\x03 \x03(\t\x12!\n\x0cgrid_records\x18\x04 \x03(\x0b\x32\x0b.DataRecord\x12!\n\x0cmodal_record\x18\x05 \x01(\x0b\x32\x0b.DataRecord\"Y\n\x1aGetSignalTrajectoryRequest\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12\x12\n\nsample_ids\x18\x02 \x03(\t\x12\x12\n\nmax_points\x18\x03 \x01(\x05\"4\n\x10SignalTrajectory\x12\x11\n\tsample_id\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x03(\x02\"}\n\x1bGetSignalTrajectoryResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12\'\n\x0ctrajectories\x18\x04 \x03(\x0b\x32\x11.SignalTrajectory\"J\n\x11PointCloudRequest\x12\x11\n\tsample_id\x18\x01 \x01(\t\x12\x0e\n\x06origin\x18\x02 \x01(\t\x12\x12\n\nmax_points\x18\x03 \x01(\x05\"\xbf\x01\n\x0fPointCloudChunk\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x12\n\nnum_points\x18\x03 \x01(\x05\x12\x14\n\x0cnum_features\x18\x04 \x01(\x05\x12\x10\n\x08pc_range\x18\x05 \x03(\x02\x12\x0c\n\x04\x64\x61ta\x18\x06 \x01(\x0c\x12\x13\n\x0b\x63hunk_index\x18\x07 \x01(\x05\x12\x14\n\x0ctotal_chunks\x18\x08 \x01(\x05\x12\x15\n\rfeature_names\x18\t \x03(\t\"\xdc\x01\n\x10\x44\x61taEditsRequest\x12\x11\n\tstat_name\x18\x01 \x01(\t\x12\x13\n\x0b\x66loat_value\x18\x02 \x01(\x02\x12\x14\n\x0cstring_value\x18\x03 \x01(\t\x12\x12\n\nbool_value\x18\x04 \x01(\x08\x12\x1d\n\x04type\x18\x05 \x01(\x0e\x32\x0f.SampleEditType\x12\x13\n\x0bsamples_ids\x18\x06 \x03(\t\x12\x16\n\x0esample_origins\x18\x07 \x03(\t\x12\x16\n\x0eis_categorical\x18\x08 \x01(\x08\x12\x12\n\ncategories\x18\t \x03(\t\"5\n\x11\x44\x61taEditsResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\":\n\x12\x44\x61taSplitsResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x13\n\x0bsplit_names\x18\x02 \x03(\t\"9\n\x13\x41gentHealthResponse\x12\x11\n\tavailable\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"^\n\x16InitializeAgentRequest\x12\x0f\n\x07\x61pi_key\x18\x01 \x01(\t\x12$\n\x08provider\x18\x02 \x01(\x0e\x32\x12.AgentProviderType\x12\r\n\x05model\x18\x03 \x01(\t\";\n\x17InitializeAgentResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"(\n\x17\x43hangeAgentModelRequest\x12\r\n\x05model\x18\x01 \x01(\t\"<\n\x18\x43hangeAgentModelResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"\x17\n\x15GetAgentModelsRequest\"J\n\x16GetAgentModelsResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0e\n\x06models\x18\x02 \x03(\t\x12\x0f\n\x07message\x18\x03 \x01(\t\"6\n\x12ResetAgentResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"3\n\x18RestoreCheckpointRequest\x12\x17\n\x0f\x65xperiment_hash\x18\x01 \x01(\t\"=\n\x19RestoreCheckpointResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"R\n\x18TriggerEvaluationRequest\x12\x12\n\nsplit_name\x18\x01 \x01(\t\x12\x0c\n\x04tags\x18\x02 \x03(\t\x12\x14\n\x0cuse_full_set\x18\x03 \x01(\x08\"=\n\x19TriggerEvaluationResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"\x1c\n\x1aGetEvaluationStatusRequest\"\x81\x01\n\x1bGetEvaluationStatusResponse\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x0f\n\x07\x63urrent\x18\x02 \x01(\x05\x12\r\n\x05total\x18\x03 \x01(\x05\x12\x0f\n\x07message\x18\x04 \x01(\t\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12\x12\n\nsplit_name\x18\x06 \x01(\t\")\n\x17\x43\x61ncelEvaluationRequest\x12\x0e\n\x06reason\x18\x01 \x01(\t\"<\n\x18\x43\x61ncelEvaluationResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t*d\n\x13WeightOperationType\x12\n\n\x06ZEROFY\x10\x00\x12\x10\n\x0cREINITIALIZE\x10\x01\x12\n\n\x06\x46REEZE\x10\x02\x12\x12\n\x0eREMOVE_NEURONS\x10\t\x12\x0f\n\x0b\x41\x44\x44_NEURONS\x10\n*o\n\x0fZerofyPredicate\x12\x19\n\x15ZEROFY_PREDICATE_NONE\x10\x00\x12 \n\x1cZEROFY_PREDICATE_WITH_FROZEN\x10\x01\x12\x1f\n\x1bZEROFY_PREDICATE_WITH_OLDER\x10\x02*M\n\x0f\x41gentIntentType\x12\x12\n\x0eINTENT_UNKNOWN\x10\x00\x12\x11\n\rINTENT_FILTER\x10\x01\x12\x13\n\x0fINTENT_ANALYSIS\x10\x02*I\n\x0eSampleEditType\x12\x11\n\rEDIT_OVERRIDE\x10\x00\x12\x13\n\x0f\x45\x44IT_ACCUMULATE\x10\x01\x12\x0f\n\x0b\x45\x44IT_REMOVE\x10\x02*,\n\x11\x41gentProviderType\x12\x17\n\x13PROVIDER_OPENROUTER\x10\x00\x32\xc7\x0b\n\x11\x45xperimentService\x12P\n\x13GetLatestLoggerData\x12\x1b.GetLatestLoggerDataRequest\x1a\x1c.GetLatestLoggerDataResponse\x12\x36\n\x11\x45xperimentCommand\x12\x0f.TrainerCommand\x1a\x10.CommandResponse\x12H\n\x11ManipulateWeights\x12\x18.WeightsOperationRequest\x1a\x19.WeightsOperationResponse\x12/\n\nGetWeights\x12\x0f.WeightsRequest\x1a\x10.WeightsResponse\x12\x39\n\x0eGetActivations\x12\x12.ActivationRequest\x1a\x13.ActivationResponse\x12\x37\n\nGetSamples\x12\x13.BatchSampleRequest\x1a\x14.BatchSampleResponse\x12\x37\n\x0e\x41pplyDataQuery\x12\x11.DataQueryRequest\x1a\x12.DataQueryResponse\x12;\n\x0eGetDataSamples\x12\x13.DataSamplesRequest\x1a\x14.DataSamplesResponse\x12\x35\n\x0cGetHistogram\x12\x11.HistogramRequest\x1a\x12.HistogramResponse\x12\x38\n\x0bGetMetaData\x12\x13.GetMetaDataRequest\x1a\x14.GetMetaDataResponse\x12P\n\x13GetSignalTrajectory\x12\x1b.GetSignalTrajectoryRequest\x1a\x1c.GetSignalTrajectoryResponse\x12\x37\n\rGetPointCloud\x12\x12.PointCloudRequest\x1a\x10.PointCloudChunk0\x01\x12\x37\n\x0e\x45\x64itDataSample\x12\x11.DataEditsRequest\x1a\x12.DataEditsResponse\x12,\n\rGetDataSplits\x12\x06.Empty\x1a\x13.DataSplitsResponse\x12\x30\n\x10\x43heckAgentHealth\x12\x06.Empty\x1a\x14.AgentHealthResponse\x12\x44\n\x0fInitializeAgent\x12\x17.InitializeAgentRequest\x1a\x18.InitializeAgentResponse\x12G\n\x10\x43hangeAgentModel\x12\x18.ChangeAgentModelRequest\x1a\x19.ChangeAgentModelResponse\x12\x41\n\x0eGetAgentModels\x12\x16.GetAgentModelsRequest\x1a\x17.GetAgentModelsResponse\x12)\n\nResetAgent\x12\x06.Empty\x1a\x13.ResetAgentResponse\x12J\n\x11RestoreCheckpoint\x12\x19.RestoreCheckpointRequest\x1a\x1a.RestoreCheckpointResponse\x12J\n\x11TriggerEvaluation\x12\x19.TriggerEvaluationRequest\x1a\x1a.TriggerEvaluationResponse\x12P\n\x13GetEvaluationStatus\x12\x1b.GetEvaluationStatusRequest\x1a\x1c.GetEvaluationStatusResponse\x12G\n\x10\x43\x61ncelEvaluation\x12\x18.CancelEvaluationRequest\x1a\x19.CancelEvaluationResponseb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n)weightslab/proto/experiment_service.proto\"\x89\x01\n\x1aGetLatestLoggerDataRequest\x12\x1c\n\x14request_full_history\x18\x01 \x01(\x08\x12\x12\n\nmax_points\x18\x02 \x01(\x05\x12\x17\n\x0f\x62reak_by_slices\x18\x03 \x01(\x08\x12\x0c\n\x04tags\x18\x04 \x03(\t\x12\x12\n\ngraph_name\x18\x05 \x01(\t\"\x81\x02\n\x0fLoggerDataPoint\x12\x13\n\x0bmetric_name\x18\x01 \x01(\t\x12\x11\n\tmodel_age\x18\x02 \x01(\x05\x12\x14\n\x0cmetric_value\x18\x03 \x01(\x02\x12\x17\n\x0f\x65xperiment_hash\x18\x04 \x01(\t\x12\x11\n\ttimestamp\x18\x05 \x01(\x03\x12\x11\n\tsample_id\x18\x06 \x01(\t\x12\x1c\n\x14is_evaluation_marker\x18\x07 \x01(\x08\x12\x12\n\nsplit_name\x18\x08 \x01(\t\x12\x17\n\x0f\x65valuation_tags\x18\t \x03(\t\x12\x12\n\npoint_note\x18\n \x01(\t\x12\x12\n\naudit_mode\x18\x0b \x01(\x08\"[\n\x1bGetLatestLoggerDataResponse\x12 \n\x06points\x18\x01 \x03(\x0b\x32\x10.LoggerDataPoint\x12\x1a\n\x12weightslab_version\x18\x02 \x01(\t\"\x07\n\x05\x45mpty\"/\n\x08NeuronId\x12\x10\n\x08layer_id\x18\x01 \x01(\x05\x12\x11\n\tneuron_id\x18\x02 \x01(\x05\"\x91\x02\n\x0fWeightOperation\x12*\n\x07op_type\x18\x01 \x01(\x0e\x32\x14.WeightOperationTypeH\x00\x88\x01\x01\x12\x15\n\x08layer_id\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x1d\n\nneuron_ids\x18\x03 \x03(\x0b\x32\t.NeuronId\x12\x16\n\x0eneurons_to_add\x18\t \x01(\x05\x12 \n\x18zerofy_from_incoming_ids\x18\x0b \x03(\x05\x12\x1c\n\x14zerofy_to_neuron_ids\x18\x0c \x03(\x05\x12+\n\x11zerofy_predicates\x18\r \x03(\x0e\x32\x10.ZerofyPredicateB\n\n\x08_op_typeB\x0b\n\t_layer_id\"_\n\x17WeightsOperationRequest\x12/\n\x10weight_operation\x18\x01 \x01(\x0b\x32\x10.WeightOperationH\x00\x88\x01\x01\x42\x13\n\x11_weight_operation\"<\n\x18WeightsOperationResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"\xc1\x05\n\x0fHyperParameters\x12\x1c\n\x0f\x65xperiment_name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12!\n\x14training_steps_to_do\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x1a\n\rlearning_rate\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x17\n\nbatch_size\x18\x04 \x01(\x05H\x03\x88\x01\x01\x12 \n\x13\x66ull_eval_frequency\x18\x05 \x01(\x05H\x04\x88\x01\x01\x12 \n\x13\x63heckpont_frequency\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x18\n\x0bis_training\x18\x07 \x01(\x08H\x06\x88\x01\x01\x12\x15\n\x08nb_steps\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x19\n\x0c\x61uditor_mode\x18\t \x01(\x08H\x08\x88\x01\x01\x12\x1d\n\x10train_batch_size\x18\n \x01(\x05H\t\x88\x01\x01\x12\x1b\n\x0eval_batch_size\x18\x0b \x01(\x05H\n\x88\x01\x01\x12\x1c\n\x0ftest_batch_size\x18\x0c \x01(\x05H\x0b\x88\x01\x01\x12\x1c\n\x0f\x65valuation_mode\x18\r \x01(\x08H\x0c\x88\x01\x01\x12\x1e\n\x11\x65valuation_config\x18\x0e \x01(\tH\r\x88\x01\x01\x42\x12\n\x10_experiment_nameB\x17\n\x15_training_steps_to_doB\x10\n\x0e_learning_rateB\r\n\x0b_batch_sizeB\x16\n\x14_full_eval_frequencyB\x16\n\x14_checkpont_frequencyB\x0e\n\x0c_is_trainingB\x0b\n\t_nb_stepsB\x0f\n\r_auditor_modeB\x13\n\x11_train_batch_sizeB\x11\n\x0f_val_batch_sizeB\x12\n\x10_test_batch_sizeB\x12\n\x10_evaluation_modeB\x14\n\x12_evaluation_config\",\n\rMetricsStatus\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02\"~\n\rAnnotatStatus\x12\x0c\n\x04name\x18\x01 \x01(\t\x12.\n\x08metadata\x18\x02 \x03(\x0b\x32\x1c.AnnotatStatus.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\"\x90\x02\n\x10TrainingStatusEx\x12\x16\n\ttimestamp\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x65xperiment_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x16\n\tmodel_age\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12+\n\x0emetrics_status\x18\x04 \x01(\x0b\x32\x0e.MetricsStatusH\x03\x88\x01\x01\x12+\n\x0e\x61nnotat_status\x18\x05 \x01(\x0b\x32\x0e.AnnotatStatusH\x04\x88\x01\x01\x42\x0c\n\n_timestampB\x12\n\x10_experiment_nameB\x0c\n\n_model_ageB\x11\n\x0f_metrics_statusB\x11\n\x0f_annotat_status\"]\n\x15HyperParameterCommand\x12/\n\x10hyper_parameters\x18\x01 \x01(\x0b\x32\x10.HyperParametersH\x00\x88\x01\x01\x42\x13\n\x11_hyper_parameters\">\n\x14\x44\x65nySamplesOperation\x12\x12\n\nsample_ids\x18\x01 \x03(\t\x12\x12\n\naccumulate\x18\x02 \x01(\x08\"0\n\x17LoadCheckpointOperation\x12\x15\n\rcheckpoint_id\x18\x01 \x01(\x05\"b\n\x11PlotNoteOperation\x12\x13\n\x0bmetric_name\x18\x01 \x01(\t\x12\x17\n\x0f\x65xperiment_hash\x18\x02 \x01(\t\x12\x11\n\tmodel_age\x18\x03 \x01(\x05\x12\x0c\n\x04note\x18\x04 \x01(\t\"L\n\x17SaveCheckpointOperation\x12\x19\n\x11save_architecture\x18\x01 \x01(\x08\x12\x16\n\x0esave_optimizer\x18\x02 \x01(\x08\"\x1a\n\x18RestartInstanceOperation\"\x8d\x08\n\x0eTrainerCommand\x12\x1c\n\x14get_hyper_parameters\x18\x04 \x01(\x08\x12\x1e\n\x16get_interactive_layers\x18\x05 \x01(\x08\x12\x1d\n\x10get_data_records\x18\x06 \x01(\tH\x00\x88\x01\x01\x12%\n\x18get_single_layer_info_id\x18\x08 \x01(\x05H\x01\x88\x01\x01\x12;\n\x16hyper_parameter_change\x18\x01 \x01(\x0b\x32\x16.HyperParameterCommandH\x02\x88\x01\x01\x12:\n\x16\x64\x65ny_samples_operation\x18\x07 \x01(\x0b\x32\x15.DenySamplesOperationH\x03\x88\x01\x01\x12?\n\x1b\x64\x65ny_eval_samples_operation\x18\n \x01(\x0b\x32\x15.DenySamplesOperationH\x04\x88\x01\x01\x12@\n\x19load_checkpoint_operation\x18\t \x01(\x0b\x32\x18.LoadCheckpointOperationH\x05\x88\x01\x01\x12\x42\n\x1eremove_from_denylist_operation\x18\x0b \x01(\x0b\x32\x15.DenySamplesOperationH\x06\x88\x01\x01\x12G\n#remove_eval_from_denylist_operation\x18\x0c \x01(\x0b\x32\x15.DenySamplesOperationH\x07\x88\x01\x01\x12\x34\n\x13plot_note_operation\x18\r \x01(\x0b\x32\x12.PlotNoteOperationH\x08\x88\x01\x01\x12@\n\x19save_checkpoint_operation\x18\x0e \x01(\x0b\x32\x18.SaveCheckpointOperationH\t\x88\x01\x01\x12\x39\n\x11restart_operation\x18\x0f \x01(\x0b\x32\x19.RestartInstanceOperationH\n\x88\x01\x01\x42\x13\n\x11_get_data_recordsB\x1b\n\x19_get_single_layer_info_idB\x19\n\x17_hyper_parameter_changeB\x19\n\x17_deny_samples_operationB\x1e\n\x1c_deny_eval_samples_operationB\x1c\n\x1a_load_checkpoint_operationB!\n\x1f_remove_from_denylist_operationB&\n$_remove_eval_from_denylist_operationB\x16\n\x14_plot_note_operationB\x1c\n\x1a_save_checkpoint_operationB\x14\n\x12_restart_operation\"\x9d\x01\n\x12HyperParameterDesc\x12\r\n\x05label\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0c\n\x04type\x18\x03 \x01(\t\x12\x1c\n\x0fnumerical_value\x18\x04 \x01(\x02H\x00\x88\x01\x01\x12\x19\n\x0cstring_value\x18\x05 \x01(\tH\x01\x88\x01\x01\x42\x12\n\x10_numerical_valueB\x0f\n\r_string_value\"\xf2\x02\n\x10NeuronStatistics\x12!\n\tneuron_id\x18\x01 \x01(\x0b\x32\t.NeuronIdH\x00\x88\x01\x01\x12\x17\n\nneuron_age\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x1f\n\x12train_trigger_rate\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x1e\n\x11\x65val_trigger_rate\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x1a\n\rlearning_rate\x18\x07 \x01(\x02H\x04\x88\x01\x01\x12\x36\n\x0bincoming_lr\x18\x08 \x03(\x0b\x32!.NeuronStatistics.IncomingLrEntry\x1a\x31\n\x0fIncomingLrEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x42\x0c\n\n_neuron_idB\r\n\x0b_neuron_ageB\x15\n\x13_train_trigger_rateB\x14\n\x12_eval_trigger_rateB\x10\n\x0e_learning_rate\"\xf0\x02\n\x13LayerRepresentation\x12\x15\n\x08layer_id\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x17\n\nlayer_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x17\n\nlayer_type\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1a\n\rneurons_count\x18\x04 \x01(\x05H\x03\x88\x01\x01\x12#\n\x16incoming_neurons_count\x18\x05 \x01(\x05H\x04\x88\x01\x01\x12\x18\n\x0bkernel_size\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x13\n\x06stride\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12-\n\x12neurons_statistics\x18\n \x03(\x0b\x32\x11.NeuronStatisticsB\x0b\n\t_layer_idB\r\n\x0b_layer_nameB\r\n\x0b_layer_typeB\x10\n\x0e_neurons_countB\x19\n\x17_incoming_neurons_countB\x0e\n\x0c_kernel_sizeB\t\n\x07_stride\"H\n\x11\x41\x63tivationRequest\x12\x10\n\x08layer_id\x18\x01 \x01(\x05\x12\x11\n\tsample_id\x18\x02 \x01(\t\x12\x0e\n\x06origin\x18\x03 \x01(\t\"H\n\rActivationMap\x12\x11\n\tneuron_id\x18\x01 \x01(\x05\x12\x0e\n\x06values\x18\x02 \x03(\x02\x12\t\n\x01H\x18\x03 \x01(\x05\x12\t\n\x01W\x18\x04 \x01(\x05\"d\n\x12\x41\x63tivationResponse\x12\x12\n\nlayer_type\x18\x01 \x01(\t\x12\x15\n\rneurons_count\x18\x02 \x01(\x05\x12#\n\x0b\x61\x63tivations\x18\x03 \x03(\x0b\x32\x0e.ActivationMap\"\x93\x01\n\tTaskField\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x15\n\x0b\x66loat_value\x18\x02 \x01(\x02H\x00\x12\x13\n\tint_value\x18\x03 \x01(\x05H\x00\x12\x16\n\x0cstring_value\x18\x04 \x01(\tH\x00\x12\x15\n\x0b\x62ytes_value\x18\x05 \x01(\x0cH\x00\x12\x14\n\nbool_value\x18\x06 \x01(\x08H\x00\x42\x07\n\x05value\"\x87\x03\n\x0eRecordMetadata\x12\x11\n\tsample_id\x18\x01 \x01(\t\x12\x14\n\x0csample_label\x18\x02 \x03(\x05\x12\x19\n\x11sample_prediction\x18\x03 \x03(\x05\x12=\n\x10sample_last_loss\x18\x04 \x03(\x0b\x32#.RecordMetadata.SampleLastLossEntry\x12\x19\n\x11sample_encounters\x18\x05 \x01(\x05\x12\x18\n\x10sample_discarded\x18\x06 \x01(\x08\x12 \n\x0c\x65xtra_fields\x18\x07 \x03(\x0b\x32\n.TaskField\x12\x16\n\x0eprediction_raw\x18\t \x01(\x0c\x12\x11\n\ttask_type\x18\n \x01(\t\x12\x19\n\x11sample_label_text\x18\x0b \x03(\t\x12\x1e\n\x16sample_prediction_text\x18\x0c \x03(\t\x1a\x35\n\x13SampleLastLossEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\"\x93\x01\n\x10SampleStatistics\x12\x13\n\x06origin\x18\x06 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0csample_count\x18\x07 \x01(\x05H\x01\x88\x01\x01\x12\x11\n\ttask_type\x18\t \x01(\t\x12 \n\x07records\x18\x08 \x03(\x0b\x32\x0f.RecordMetadataB\t\n\x07_originB\x0f\n\r_sample_count\"\xe6\x01\n\x0f\x43ommandResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x33\n\x16hyper_parameters_descs\x18\x03 \x03(\x0b\x32\x13.HyperParameterDesc\x12\x33\n\x15layer_representations\x18\x04 \x03(\x0b\x32\x14.LayerRepresentation\x12\x31\n\x11sample_statistics\x18\x05 \x01(\x0b\x32\x11.SampleStatisticsH\x00\x88\x01\x01\x42\x14\n\x12_sample_statistics\"U\n\rSampleRequest\x12\x16\n\tsample_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06origin\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x0c\n\n_sample_idB\t\n\x07_origin\"\xad\x02\n\x15SampleRequestResponse\x12\x16\n\tsample_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06origin\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x12\n\x05label\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x11\n\x04\x64\x61ta\x18\x04 \x01(\x0cH\x03\x88\x01\x01\x12\x1a\n\rerror_message\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x15\n\x08raw_data\x18\x06 \x01(\x0cH\x05\x88\x01\x01\x12\x11\n\x04mask\x18\x07 \x01(\x0cH\x06\x88\x01\x01\x12\x17\n\nprediction\x18\x08 \x01(\x0cH\x07\x88\x01\x01\x42\x0c\n\n_sample_idB\t\n\x07_originB\x08\n\x06_labelB\x07\n\x05_dataB\x10\n\x0e_error_messageB\x0b\n\t_raw_dataB\x07\n\x05_maskB\r\n\x0b_prediction\"\x92\x01\n\x12\x42\x61tchSampleRequest\x12\x12\n\nsample_ids\x18\x01 \x03(\t\x12\x0e\n\x06origin\x18\x02 \x01(\t\x12\x19\n\x0cresize_width\x18\x03 \x01(\x05H\x00\x88\x01\x01\x12\x1a\n\rresize_height\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\x0f\n\r_resize_widthB\x10\n\x0e_resize_height\">\n\x13\x42\x61tchSampleResponse\x12\'\n\x07samples\x18\x01 \x03(\x0b\x32\x16.SampleRequestResponse\".\n\x0eWeightsRequest\x12\x1c\n\tneuron_id\x18\x01 \x01(\x0b\x32\t.NeuronId\"\x9d\x02\n\x0fWeightsResponse\x12\x1c\n\tneuron_id\x18\x01 \x01(\x0b\x32\t.NeuronId\x12\x17\n\nlayer_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nlayer_type\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x10\n\x08incoming\x18\x04 \x01(\x05\x12\x10\n\x08outgoing\x18\x05 \x01(\x05\x12\x18\n\x0bkernel_size\x18\x06 \x01(\x05H\x02\x88\x01\x01\x12\x0f\n\x07weights\x18\x07 \x03(\x02\x12\x0f\n\x07success\x18\x0b \x01(\x08\x12\x1a\n\rerror_message\x18\x0c \x01(\tH\x03\x88\x01\x01\x42\r\n\x0b_layer_nameB\r\n\x0b_layer_typeB\x0e\n\x0c_kernel_sizeB\x10\n\x0e_error_message\"R\n\x10\x44\x61taQueryRequest\x12\r\n\x05query\x18\x01 \x01(\t\x12\x12\n\naccumulate\x18\x02 \x01(\x08\x12\x1b\n\x13is_natural_language\x18\x03 \x01(\x08\"5\n\x11\x43\x61tegoricalTagDef\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\ncategories\x18\x02 \x03(\t\"\xa9\x02\n\x11\x44\x61taQueryResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x1d\n\x15number_of_all_samples\x18\x03 \x01(\x05\x12%\n\x1dnumber_of_samples_in_the_loop\x18\x04 \x01(\x05\x12#\n\x1bnumber_of_discarded_samples\x18\x05 \x01(\x05\x12\x13\n\x0bunique_tags\x18\x06 \x03(\t\x12+\n\x11\x61gent_intent_type\x18\x07 \x01(\x0e\x32\x10.AgentIntentType\x12\x17\n\x0f\x61nalysis_result\x18\x08 \x01(\t\x12,\n\x10\x63\x61tegorical_tags\x18\t \x03(\x0b\x32\x12.CategoricalTagDef\"\xc2\x01\n\x12\x44\x61taSamplesRequest\x12\x13\n\x0bstart_index\x18\x01 \x01(\x05\x12\x13\n\x0brecords_cnt\x18\x02 \x01(\x05\x12 \n\x18include_transformed_data\x18\x03 \x01(\x08\x12\x18\n\x10include_raw_data\x18\x04 \x01(\x08\x12\x19\n\x11stats_to_retrieve\x18\x05 \x03(\t\x12\x14\n\x0cresize_width\x18\x06 \x01(\x05\x12\x15\n\rresize_height\x18\x07 \x01(\x05\"m\n\x08\x44\x61taStat\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\r\n\x05shape\x18\x03 \x03(\x05\x12\r\n\x05value\x18\x04 \x03(\x02\x12\x14\n\x0cvalue_string\x18\x05 \x01(\t\x12\x11\n\tthumbnail\x18\x06 \x01(\x0c\">\n\nDataRecord\x12\x11\n\tsample_id\x18\x01 \x01(\t\x12\x1d\n\ndata_stats\x18\x02 \x03(\x0b\x32\t.DataStat\"Z\n\x13\x44\x61taSamplesResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12!\n\x0c\x64\x61ta_records\x18\x03 \x03(\x0b\x32\x0b.DataRecord\"C\n\x0fHistogramSubBar\x12\x0e\n\x06origin\x18\x01 \x01(\t\x12\x11\n\tdiscarded\x18\x02 \x01(\x08\x12\r\n\x05\x63ount\x18\x03 \x01(\x03\"h\n\x0cHistogramBin\x12\x0b\n\x03min\x18\x01 \x01(\x01\x12\x0b\n\x03max\x18\x02 \x01(\x01\x12\x0b\n\x03\x61vg\x18\x03 \x01(\x01\x12\r\n\x05\x63ount\x18\x04 \x01(\x03\x12\"\n\x08sub_bars\x18\x05 \x03(\x0b\x32\x10.HistogramSubBar\"[\n\x17\x43\x61tegoricalHistogramBar\x12\r\n\x05label\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x02 \x01(\x03\x12\"\n\x08sub_bars\x18\x03 \x03(\x0b\x32\x10.HistogramSubBar\"4\n\x10HistogramRequest\x12\x0e\n\x06\x63olumn\x18\x01 \x01(\t\x12\x10\n\x08max_bins\x18\x02 \x01(\x05\"\xb2\x01\n\x11HistogramResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x12\n\ntotal_rows\x18\x03 \x01(\x03\x12\x1b\n\x04\x62ins\x18\x04 \x03(\x0b\x32\r.HistogramBin\x12\x16\n\x0eis_categorical\x18\x05 \x01(\x08\x12\x32\n\x10\x63\x61tegorical_bars\x18\x06 \x03(\x0b\x32\x18.CategoricalHistogramBar\"W\n\x12GetMetaDataRequest\x12\x13\n\x0bstart_index\x18\x01 \x01(\x05\x12\x13\n\x0brecords_cnt\x18\x02 \x01(\x05\x12\x17\n\x0fmodal_sample_id\x18\x03 \x01(\t\"\x99\x01\n\x13GetMetaDataResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x1a\n\x12\x61ll_metadata_names\x18\x03 \x03(\t\x12!\n\x0cgrid_records\x18\x04 \x03(\x0b\x32\x0b.DataRecord\x12!\n\x0cmodal_record\x18\x05 \x01(\x0b\x32\x0b.DataRecord\"Y\n\x1aGetSignalTrajectoryRequest\x12\x13\n\x0bsignal_name\x18\x01 \x01(\t\x12\x12\n\nsample_ids\x18\x02 \x03(\t\x12\x12\n\nmax_points\x18\x03 \x01(\x05\"4\n\x10SignalTrajectory\x12\x11\n\tsample_id\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x03(\x02\"}\n\x1bGetSignalTrajectoryResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x13\n\x0bsignal_name\x18\x03 \x01(\t\x12\'\n\x0ctrajectories\x18\x04 \x03(\x0b\x32\x11.SignalTrajectory\"J\n\x11PointCloudRequest\x12\x11\n\tsample_id\x18\x01 \x01(\t\x12\x0e\n\x06origin\x18\x02 \x01(\t\x12\x12\n\nmax_points\x18\x03 \x01(\x05\"\xbf\x01\n\x0fPointCloudChunk\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x12\n\nnum_points\x18\x03 \x01(\x05\x12\x14\n\x0cnum_features\x18\x04 \x01(\x05\x12\x10\n\x08pc_range\x18\x05 \x03(\x02\x12\x0c\n\x04\x64\x61ta\x18\x06 \x01(\x0c\x12\x13\n\x0b\x63hunk_index\x18\x07 \x01(\x05\x12\x14\n\x0ctotal_chunks\x18\x08 \x01(\x05\x12\x15\n\rfeature_names\x18\t \x03(\t\"\xdc\x01\n\x10\x44\x61taEditsRequest\x12\x11\n\tstat_name\x18\x01 \x01(\t\x12\x13\n\x0b\x66loat_value\x18\x02 \x01(\x02\x12\x14\n\x0cstring_value\x18\x03 \x01(\t\x12\x12\n\nbool_value\x18\x04 \x01(\x08\x12\x1d\n\x04type\x18\x05 \x01(\x0e\x32\x0f.SampleEditType\x12\x13\n\x0bsamples_ids\x18\x06 \x03(\t\x12\x16\n\x0esample_origins\x18\x07 \x03(\t\x12\x16\n\x0eis_categorical\x18\x08 \x01(\x08\x12\x12\n\ncategories\x18\t \x03(\t\"5\n\x11\x44\x61taEditsResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\":\n\x12\x44\x61taSplitsResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x13\n\x0bsplit_names\x18\x02 \x03(\t\"9\n\x13\x41gentHealthResponse\x12\x11\n\tavailable\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"^\n\x16InitializeAgentRequest\x12\x0f\n\x07\x61pi_key\x18\x01 \x01(\t\x12$\n\x08provider\x18\x02 \x01(\x0e\x32\x12.AgentProviderType\x12\r\n\x05model\x18\x03 \x01(\t\";\n\x17InitializeAgentResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"(\n\x17\x43hangeAgentModelRequest\x12\r\n\x05model\x18\x01 \x01(\t\"<\n\x18\x43hangeAgentModelResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"\x17\n\x15GetAgentModelsRequest\"J\n\x16GetAgentModelsResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0e\n\x06models\x18\x02 \x03(\t\x12\x0f\n\x07message\x18\x03 \x01(\t\"6\n\x12ResetAgentResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"3\n\x18RestoreCheckpointRequest\x12\x17\n\x0f\x65xperiment_hash\x18\x01 \x01(\t\"=\n\x19RestoreCheckpointResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"R\n\x18TriggerEvaluationRequest\x12\x12\n\nsplit_name\x18\x01 \x01(\t\x12\x0c\n\x04tags\x18\x02 \x03(\t\x12\x14\n\x0cuse_full_set\x18\x03 \x01(\x08\"=\n\x19TriggerEvaluationResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"\x1c\n\x1aGetEvaluationStatusRequest\"\x81\x01\n\x1bGetEvaluationStatusResponse\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x0f\n\x07\x63urrent\x18\x02 \x01(\x05\x12\r\n\x05total\x18\x03 \x01(\x05\x12\x0f\n\x07message\x18\x04 \x01(\t\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12\x12\n\nsplit_name\x18\x06 \x01(\t\")\n\x17\x43\x61ncelEvaluationRequest\x12\x0e\n\x06reason\x18\x01 \x01(\t\"<\n\x18\x43\x61ncelEvaluationResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t*d\n\x13WeightOperationType\x12\n\n\x06ZEROFY\x10\x00\x12\x10\n\x0cREINITIALIZE\x10\x01\x12\n\n\x06\x46REEZE\x10\x02\x12\x12\n\x0eREMOVE_NEURONS\x10\t\x12\x0f\n\x0b\x41\x44\x44_NEURONS\x10\n*o\n\x0fZerofyPredicate\x12\x19\n\x15ZEROFY_PREDICATE_NONE\x10\x00\x12 \n\x1cZEROFY_PREDICATE_WITH_FROZEN\x10\x01\x12\x1f\n\x1bZEROFY_PREDICATE_WITH_OLDER\x10\x02*M\n\x0f\x41gentIntentType\x12\x12\n\x0eINTENT_UNKNOWN\x10\x00\x12\x11\n\rINTENT_FILTER\x10\x01\x12\x13\n\x0fINTENT_ANALYSIS\x10\x02*I\n\x0eSampleEditType\x12\x11\n\rEDIT_OVERRIDE\x10\x00\x12\x13\n\x0f\x45\x44IT_ACCUMULATE\x10\x01\x12\x0f\n\x0b\x45\x44IT_REMOVE\x10\x02*,\n\x11\x41gentProviderType\x12\x17\n\x13PROVIDER_OPENROUTER\x10\x00\x32\xc7\x0b\n\x11\x45xperimentService\x12P\n\x13GetLatestLoggerData\x12\x1b.GetLatestLoggerDataRequest\x1a\x1c.GetLatestLoggerDataResponse\x12\x36\n\x11\x45xperimentCommand\x12\x0f.TrainerCommand\x1a\x10.CommandResponse\x12H\n\x11ManipulateWeights\x12\x18.WeightsOperationRequest\x1a\x19.WeightsOperationResponse\x12/\n\nGetWeights\x12\x0f.WeightsRequest\x1a\x10.WeightsResponse\x12\x39\n\x0eGetActivations\x12\x12.ActivationRequest\x1a\x13.ActivationResponse\x12\x37\n\nGetSamples\x12\x13.BatchSampleRequest\x1a\x14.BatchSampleResponse\x12\x37\n\x0e\x41pplyDataQuery\x12\x11.DataQueryRequest\x1a\x12.DataQueryResponse\x12;\n\x0eGetDataSamples\x12\x13.DataSamplesRequest\x1a\x14.DataSamplesResponse\x12\x35\n\x0cGetHistogram\x12\x11.HistogramRequest\x1a\x12.HistogramResponse\x12\x38\n\x0bGetMetaData\x12\x13.GetMetaDataRequest\x1a\x14.GetMetaDataResponse\x12P\n\x13GetSignalTrajectory\x12\x1b.GetSignalTrajectoryRequest\x1a\x1c.GetSignalTrajectoryResponse\x12\x37\n\rGetPointCloud\x12\x12.PointCloudRequest\x1a\x10.PointCloudChunk0\x01\x12\x37\n\x0e\x45\x64itDataSample\x12\x11.DataEditsRequest\x1a\x12.DataEditsResponse\x12,\n\rGetDataSplits\x12\x06.Empty\x1a\x13.DataSplitsResponse\x12\x30\n\x10\x43heckAgentHealth\x12\x06.Empty\x1a\x14.AgentHealthResponse\x12\x44\n\x0fInitializeAgent\x12\x17.InitializeAgentRequest\x1a\x18.InitializeAgentResponse\x12G\n\x10\x43hangeAgentModel\x12\x18.ChangeAgentModelRequest\x1a\x19.ChangeAgentModelResponse\x12\x41\n\x0eGetAgentModels\x12\x16.GetAgentModelsRequest\x1a\x17.GetAgentModelsResponse\x12)\n\nResetAgent\x12\x06.Empty\x1a\x13.ResetAgentResponse\x12J\n\x11RestoreCheckpoint\x12\x19.RestoreCheckpointRequest\x1a\x1a.RestoreCheckpointResponse\x12J\n\x11TriggerEvaluation\x12\x19.TriggerEvaluationRequest\x1a\x1a.TriggerEvaluationResponse\x12P\n\x13GetEvaluationStatus\x12\x1b.GetEvaluationStatusRequest\x1a\x1c.GetEvaluationStatusResponse\x12G\n\x10\x43\x61ncelEvaluation\x12\x18.CancelEvaluationRequest\x1a\x19.CancelEvaluationResponseb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -37,16 +37,16 @@ _globals['_NEURONSTATISTICS_INCOMINGLRENTRY']._serialized_options = b'8\001' _globals['_RECORDMETADATA_SAMPLELASTLOSSENTRY']._loaded_options = None _globals['_RECORDMETADATA_SAMPLELASTLOSSENTRY']._serialized_options = b'8\001' - _globals['_WEIGHTOPERATIONTYPE']._serialized_start=10143 - _globals['_WEIGHTOPERATIONTYPE']._serialized_end=10243 - _globals['_ZEROFYPREDICATE']._serialized_start=10245 - _globals['_ZEROFYPREDICATE']._serialized_end=10356 - _globals['_AGENTINTENTTYPE']._serialized_start=10358 - _globals['_AGENTINTENTTYPE']._serialized_end=10435 - _globals['_SAMPLEEDITTYPE']._serialized_start=10437 - _globals['_SAMPLEEDITTYPE']._serialized_end=10510 - _globals['_AGENTPROVIDERTYPE']._serialized_start=10512 - _globals['_AGENTPROVIDERTYPE']._serialized_end=10556 + _globals['_WEIGHTOPERATIONTYPE']._serialized_start=10202 + _globals['_WEIGHTOPERATIONTYPE']._serialized_end=10302 + _globals['_ZEROFYPREDICATE']._serialized_start=10304 + _globals['_ZEROFYPREDICATE']._serialized_end=10415 + _globals['_AGENTINTENTTYPE']._serialized_start=10417 + _globals['_AGENTINTENTTYPE']._serialized_end=10494 + _globals['_SAMPLEEDITTYPE']._serialized_start=10496 + _globals['_SAMPLEEDITTYPE']._serialized_end=10569 + _globals['_AGENTPROVIDERTYPE']._serialized_start=10571 + _globals['_AGENTPROVIDERTYPE']._serialized_end=10615 _globals['_GETLATESTLOGGERDATAREQUEST']._serialized_start=46 _globals['_GETLATESTLOGGERDATAREQUEST']._serialized_end=183 _globals['_LOGGERDATAPOINT']._serialized_start=186 @@ -104,101 +104,101 @@ _globals['_TASKFIELD']._serialized_start=4798 _globals['_TASKFIELD']._serialized_end=4945 _globals['_RECORDMETADATA']._serialized_start=4948 - _globals['_RECORDMETADATA']._serialized_end=5280 - _globals['_RECORDMETADATA_SAMPLELASTLOSSENTRY']._serialized_start=5227 - _globals['_RECORDMETADATA_SAMPLELASTLOSSENTRY']._serialized_end=5280 - _globals['_SAMPLESTATISTICS']._serialized_start=5283 - _globals['_SAMPLESTATISTICS']._serialized_end=5430 - _globals['_COMMANDRESPONSE']._serialized_start=5433 - _globals['_COMMANDRESPONSE']._serialized_end=5663 - _globals['_SAMPLEREQUEST']._serialized_start=5665 - _globals['_SAMPLEREQUEST']._serialized_end=5750 - _globals['_SAMPLEREQUESTRESPONSE']._serialized_start=5753 - _globals['_SAMPLEREQUESTRESPONSE']._serialized_end=6054 - _globals['_BATCHSAMPLEREQUEST']._serialized_start=6057 - _globals['_BATCHSAMPLEREQUEST']._serialized_end=6203 - _globals['_BATCHSAMPLERESPONSE']._serialized_start=6205 - _globals['_BATCHSAMPLERESPONSE']._serialized_end=6267 - _globals['_WEIGHTSREQUEST']._serialized_start=6269 - _globals['_WEIGHTSREQUEST']._serialized_end=6315 - _globals['_WEIGHTSRESPONSE']._serialized_start=6318 - _globals['_WEIGHTSRESPONSE']._serialized_end=6603 - _globals['_DATAQUERYREQUEST']._serialized_start=6605 - _globals['_DATAQUERYREQUEST']._serialized_end=6687 - _globals['_CATEGORICALTAGDEF']._serialized_start=6689 - _globals['_CATEGORICALTAGDEF']._serialized_end=6742 - _globals['_DATAQUERYRESPONSE']._serialized_start=6745 - _globals['_DATAQUERYRESPONSE']._serialized_end=7042 - _globals['_DATASAMPLESREQUEST']._serialized_start=7045 - _globals['_DATASAMPLESREQUEST']._serialized_end=7239 - _globals['_DATASTAT']._serialized_start=7241 - _globals['_DATASTAT']._serialized_end=7350 - _globals['_DATARECORD']._serialized_start=7352 - _globals['_DATARECORD']._serialized_end=7414 - _globals['_DATASAMPLESRESPONSE']._serialized_start=7416 - _globals['_DATASAMPLESRESPONSE']._serialized_end=7506 - _globals['_HISTOGRAMSUBBAR']._serialized_start=7508 - _globals['_HISTOGRAMSUBBAR']._serialized_end=7575 - _globals['_HISTOGRAMBIN']._serialized_start=7577 - _globals['_HISTOGRAMBIN']._serialized_end=7681 - _globals['_CATEGORICALHISTOGRAMBAR']._serialized_start=7683 - _globals['_CATEGORICALHISTOGRAMBAR']._serialized_end=7774 - _globals['_HISTOGRAMREQUEST']._serialized_start=7776 - _globals['_HISTOGRAMREQUEST']._serialized_end=7828 - _globals['_HISTOGRAMRESPONSE']._serialized_start=7831 - _globals['_HISTOGRAMRESPONSE']._serialized_end=8009 - _globals['_GETMETADATAREQUEST']._serialized_start=8011 - _globals['_GETMETADATAREQUEST']._serialized_end=8098 - _globals['_GETMETADATARESPONSE']._serialized_start=8101 - _globals['_GETMETADATARESPONSE']._serialized_end=8254 - _globals['_GETSIGNALTRAJECTORYREQUEST']._serialized_start=8256 - _globals['_GETSIGNALTRAJECTORYREQUEST']._serialized_end=8345 - _globals['_SIGNALTRAJECTORY']._serialized_start=8347 - _globals['_SIGNALTRAJECTORY']._serialized_end=8399 - _globals['_GETSIGNALTRAJECTORYRESPONSE']._serialized_start=8401 - _globals['_GETSIGNALTRAJECTORYRESPONSE']._serialized_end=8526 - _globals['_POINTCLOUDREQUEST']._serialized_start=8528 - _globals['_POINTCLOUDREQUEST']._serialized_end=8602 - _globals['_POINTCLOUDCHUNK']._serialized_start=8605 - _globals['_POINTCLOUDCHUNK']._serialized_end=8796 - _globals['_DATAEDITSREQUEST']._serialized_start=8799 - _globals['_DATAEDITSREQUEST']._serialized_end=9019 - _globals['_DATAEDITSRESPONSE']._serialized_start=9021 - _globals['_DATAEDITSRESPONSE']._serialized_end=9074 - _globals['_DATASPLITSRESPONSE']._serialized_start=9076 - _globals['_DATASPLITSRESPONSE']._serialized_end=9134 - _globals['_AGENTHEALTHRESPONSE']._serialized_start=9136 - _globals['_AGENTHEALTHRESPONSE']._serialized_end=9193 - _globals['_INITIALIZEAGENTREQUEST']._serialized_start=9195 - _globals['_INITIALIZEAGENTREQUEST']._serialized_end=9289 - _globals['_INITIALIZEAGENTRESPONSE']._serialized_start=9291 - _globals['_INITIALIZEAGENTRESPONSE']._serialized_end=9350 - _globals['_CHANGEAGENTMODELREQUEST']._serialized_start=9352 - _globals['_CHANGEAGENTMODELREQUEST']._serialized_end=9392 - _globals['_CHANGEAGENTMODELRESPONSE']._serialized_start=9394 - _globals['_CHANGEAGENTMODELRESPONSE']._serialized_end=9454 - _globals['_GETAGENTMODELSREQUEST']._serialized_start=9456 - _globals['_GETAGENTMODELSREQUEST']._serialized_end=9479 - _globals['_GETAGENTMODELSRESPONSE']._serialized_start=9481 - _globals['_GETAGENTMODELSRESPONSE']._serialized_end=9555 - _globals['_RESETAGENTRESPONSE']._serialized_start=9557 - _globals['_RESETAGENTRESPONSE']._serialized_end=9611 - _globals['_RESTORECHECKPOINTREQUEST']._serialized_start=9613 - _globals['_RESTORECHECKPOINTREQUEST']._serialized_end=9664 - _globals['_RESTORECHECKPOINTRESPONSE']._serialized_start=9666 - _globals['_RESTORECHECKPOINTRESPONSE']._serialized_end=9727 - _globals['_TRIGGEREVALUATIONREQUEST']._serialized_start=9729 - _globals['_TRIGGEREVALUATIONREQUEST']._serialized_end=9811 - _globals['_TRIGGEREVALUATIONRESPONSE']._serialized_start=9813 - _globals['_TRIGGEREVALUATIONRESPONSE']._serialized_end=9874 - _globals['_GETEVALUATIONSTATUSREQUEST']._serialized_start=9876 - _globals['_GETEVALUATIONSTATUSREQUEST']._serialized_end=9904 - _globals['_GETEVALUATIONSTATUSRESPONSE']._serialized_start=9907 - _globals['_GETEVALUATIONSTATUSRESPONSE']._serialized_end=10036 - _globals['_CANCELEVALUATIONREQUEST']._serialized_start=10038 - _globals['_CANCELEVALUATIONREQUEST']._serialized_end=10079 - _globals['_CANCELEVALUATIONRESPONSE']._serialized_start=10081 - _globals['_CANCELEVALUATIONRESPONSE']._serialized_end=10141 - _globals['_EXPERIMENTSERVICE']._serialized_start=10559 - _globals['_EXPERIMENTSERVICE']._serialized_end=12038 + _globals['_RECORDMETADATA']._serialized_end=5339 + _globals['_RECORDMETADATA_SAMPLELASTLOSSENTRY']._serialized_start=5286 + _globals['_RECORDMETADATA_SAMPLELASTLOSSENTRY']._serialized_end=5339 + _globals['_SAMPLESTATISTICS']._serialized_start=5342 + _globals['_SAMPLESTATISTICS']._serialized_end=5489 + _globals['_COMMANDRESPONSE']._serialized_start=5492 + _globals['_COMMANDRESPONSE']._serialized_end=5722 + _globals['_SAMPLEREQUEST']._serialized_start=5724 + _globals['_SAMPLEREQUEST']._serialized_end=5809 + _globals['_SAMPLEREQUESTRESPONSE']._serialized_start=5812 + _globals['_SAMPLEREQUESTRESPONSE']._serialized_end=6113 + _globals['_BATCHSAMPLEREQUEST']._serialized_start=6116 + _globals['_BATCHSAMPLEREQUEST']._serialized_end=6262 + _globals['_BATCHSAMPLERESPONSE']._serialized_start=6264 + _globals['_BATCHSAMPLERESPONSE']._serialized_end=6326 + _globals['_WEIGHTSREQUEST']._serialized_start=6328 + _globals['_WEIGHTSREQUEST']._serialized_end=6374 + _globals['_WEIGHTSRESPONSE']._serialized_start=6377 + _globals['_WEIGHTSRESPONSE']._serialized_end=6662 + _globals['_DATAQUERYREQUEST']._serialized_start=6664 + _globals['_DATAQUERYREQUEST']._serialized_end=6746 + _globals['_CATEGORICALTAGDEF']._serialized_start=6748 + _globals['_CATEGORICALTAGDEF']._serialized_end=6801 + _globals['_DATAQUERYRESPONSE']._serialized_start=6804 + _globals['_DATAQUERYRESPONSE']._serialized_end=7101 + _globals['_DATASAMPLESREQUEST']._serialized_start=7104 + _globals['_DATASAMPLESREQUEST']._serialized_end=7298 + _globals['_DATASTAT']._serialized_start=7300 + _globals['_DATASTAT']._serialized_end=7409 + _globals['_DATARECORD']._serialized_start=7411 + _globals['_DATARECORD']._serialized_end=7473 + _globals['_DATASAMPLESRESPONSE']._serialized_start=7475 + _globals['_DATASAMPLESRESPONSE']._serialized_end=7565 + _globals['_HISTOGRAMSUBBAR']._serialized_start=7567 + _globals['_HISTOGRAMSUBBAR']._serialized_end=7634 + _globals['_HISTOGRAMBIN']._serialized_start=7636 + _globals['_HISTOGRAMBIN']._serialized_end=7740 + _globals['_CATEGORICALHISTOGRAMBAR']._serialized_start=7742 + _globals['_CATEGORICALHISTOGRAMBAR']._serialized_end=7833 + _globals['_HISTOGRAMREQUEST']._serialized_start=7835 + _globals['_HISTOGRAMREQUEST']._serialized_end=7887 + _globals['_HISTOGRAMRESPONSE']._serialized_start=7890 + _globals['_HISTOGRAMRESPONSE']._serialized_end=8068 + _globals['_GETMETADATAREQUEST']._serialized_start=8070 + _globals['_GETMETADATAREQUEST']._serialized_end=8157 + _globals['_GETMETADATARESPONSE']._serialized_start=8160 + _globals['_GETMETADATARESPONSE']._serialized_end=8313 + _globals['_GETSIGNALTRAJECTORYREQUEST']._serialized_start=8315 + _globals['_GETSIGNALTRAJECTORYREQUEST']._serialized_end=8404 + _globals['_SIGNALTRAJECTORY']._serialized_start=8406 + _globals['_SIGNALTRAJECTORY']._serialized_end=8458 + _globals['_GETSIGNALTRAJECTORYRESPONSE']._serialized_start=8460 + _globals['_GETSIGNALTRAJECTORYRESPONSE']._serialized_end=8585 + _globals['_POINTCLOUDREQUEST']._serialized_start=8587 + _globals['_POINTCLOUDREQUEST']._serialized_end=8661 + _globals['_POINTCLOUDCHUNK']._serialized_start=8664 + _globals['_POINTCLOUDCHUNK']._serialized_end=8855 + _globals['_DATAEDITSREQUEST']._serialized_start=8858 + _globals['_DATAEDITSREQUEST']._serialized_end=9078 + _globals['_DATAEDITSRESPONSE']._serialized_start=9080 + _globals['_DATAEDITSRESPONSE']._serialized_end=9133 + _globals['_DATASPLITSRESPONSE']._serialized_start=9135 + _globals['_DATASPLITSRESPONSE']._serialized_end=9193 + _globals['_AGENTHEALTHRESPONSE']._serialized_start=9195 + _globals['_AGENTHEALTHRESPONSE']._serialized_end=9252 + _globals['_INITIALIZEAGENTREQUEST']._serialized_start=9254 + _globals['_INITIALIZEAGENTREQUEST']._serialized_end=9348 + _globals['_INITIALIZEAGENTRESPONSE']._serialized_start=9350 + _globals['_INITIALIZEAGENTRESPONSE']._serialized_end=9409 + _globals['_CHANGEAGENTMODELREQUEST']._serialized_start=9411 + _globals['_CHANGEAGENTMODELREQUEST']._serialized_end=9451 + _globals['_CHANGEAGENTMODELRESPONSE']._serialized_start=9453 + _globals['_CHANGEAGENTMODELRESPONSE']._serialized_end=9513 + _globals['_GETAGENTMODELSREQUEST']._serialized_start=9515 + _globals['_GETAGENTMODELSREQUEST']._serialized_end=9538 + _globals['_GETAGENTMODELSRESPONSE']._serialized_start=9540 + _globals['_GETAGENTMODELSRESPONSE']._serialized_end=9614 + _globals['_RESETAGENTRESPONSE']._serialized_start=9616 + _globals['_RESETAGENTRESPONSE']._serialized_end=9670 + _globals['_RESTORECHECKPOINTREQUEST']._serialized_start=9672 + _globals['_RESTORECHECKPOINTREQUEST']._serialized_end=9723 + _globals['_RESTORECHECKPOINTRESPONSE']._serialized_start=9725 + _globals['_RESTORECHECKPOINTRESPONSE']._serialized_end=9786 + _globals['_TRIGGEREVALUATIONREQUEST']._serialized_start=9788 + _globals['_TRIGGEREVALUATIONREQUEST']._serialized_end=9870 + _globals['_TRIGGEREVALUATIONRESPONSE']._serialized_start=9872 + _globals['_TRIGGEREVALUATIONRESPONSE']._serialized_end=9933 + _globals['_GETEVALUATIONSTATUSREQUEST']._serialized_start=9935 + _globals['_GETEVALUATIONSTATUSREQUEST']._serialized_end=9963 + _globals['_GETEVALUATIONSTATUSRESPONSE']._serialized_start=9966 + _globals['_GETEVALUATIONSTATUSRESPONSE']._serialized_end=10095 + _globals['_CANCELEVALUATIONREQUEST']._serialized_start=10097 + _globals['_CANCELEVALUATIONREQUEST']._serialized_end=10138 + _globals['_CANCELEVALUATIONRESPONSE']._serialized_start=10140 + _globals['_CANCELEVALUATIONRESPONSE']._serialized_end=10200 + _globals['_EXPERIMENTSERVICE']._serialized_start=10618 + _globals['_EXPERIMENTSERVICE']._serialized_end=12097 # @@protoc_insertion_point(module_scope) diff --git a/weightslab/proto/experiment_service_pb2_grpc.py b/weightslab/proto/experiment_service_pb2_grpc.py index 02ddfd62..5e560123 100644 --- a/weightslab/proto/experiment_service_pb2_grpc.py +++ b/weightslab/proto/experiment_service_pb2_grpc.py @@ -5,7 +5,7 @@ from weightslab.proto import experiment_service_pb2 as weightslab_dot_proto_dot_experiment__service__pb2 -GRPC_GENERATED_VERSION = '1.76.0' +GRPC_GENERATED_VERSION = '1.68.1' GRPC_VERSION = grpc.__version__ _version_not_supported = False @@ -18,7 +18,7 @@ if _version_not_supported: raise RuntimeError( f'The grpc package installed is at version {GRPC_VERSION},' - + ' but the generated code in weightslab/proto/experiment_service_pb2_grpc.py depends on' + + f' but the generated code in weightslab/proto/experiment_service_pb2_grpc.py depends on' + f' grpcio>={GRPC_GENERATED_VERSION}.' + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' diff --git a/weightslab/src.py b/weightslab/src.py index d76f0bca..e82dc9ba 100644 --- a/weightslab/src.py +++ b/weightslab/src.py @@ -2221,9 +2221,23 @@ def save_signals( # Normalize to np arrays def to_numpy(t): + # Text predictions/labels (e.g. an LLM's generated reply, or a + # reference/target string): keep as a native str rather than + # wrapping in a 0-d numpy array, so it survives the + # DataFrameManager/H5 round-trip as a plain string and the + # `isinstance(x, str)` checks in trainer_tools.py/data_service.py + # (which build the actual RecordMetadata/DataStat the UI renders) + # see a real str, not an ndarray. Forcing it through the + # classification-label uint16 cast below would raise ValueError on + # non-numeric text -- see the dict-label JSON-string fallback in + # data_service.py for the precedent this generalizes. + if isinstance(t, str): + return t arr = t.detach().cpu().numpy() if isinstance(t, th.Tensor) else np.asarray(t) if np.issubdtype(arr.dtype, np.floating): return arr.astype(np.float32) + if np.issubdtype(arr.dtype, np.str_) or np.issubdtype(arr.dtype, np.object_): + return arr return arr.astype(np.uint16) def normalize(x): diff --git a/weightslab/trainer/services/data_service.py b/weightslab/trainer/services/data_service.py index 3f479397..3c31126b 100755 --- a/weightslab/trainer/services/data_service.py +++ b/weightslab/trainer/services/data_service.py @@ -120,6 +120,29 @@ def peek_is_tabular_sample(dataset, sample_id) -> bool: return False +def looks_like_file_path_label(label) -> bool: + """True when a string label looks like a file path (e.g. a segmentation + mask path such as "mask.png") rather than free text (e.g. an LLM's + reference/reply text). + + Used by ``DataService._process_sample_row``'s task-type detection to + decide whether a string label should be treated as "empty" (triggering a + ``load_label`` reload) -- a file path with no loadable content on the row + should trigger that reload, but free text must NOT, since there is + nothing to "load" for it and doing so would silently discard the text. + + A file path ends in a short alphanumeric extension with no whitespace; + ordinary free text (multiple sentences, or a mid-sentence period) almost + always has a space right after any non-trailing '.', so requiring the + trailing segment to be short/alphanumeric/whitespace-free keeps this from + misfiring on text labels/predictions. + """ + if not isinstance(label, str) or '.' not in label or label.endswith('.'): + return False + ext = label.rsplit('.', 1)[-1] + return 1 <= len(ext) <= 6 and ext.isalnum() + + def normalize_metadata_copy_source_name(source_name: str, experiment_hash: str = None) -> str: """Normalize a source metadata name for deterministic copied-column naming.""" name = str(source_name or "").strip() @@ -1291,7 +1314,7 @@ def _process_sample_row(self, args): is_label_empty = True elif isinstance(label, list) and not label: is_label_empty = True - elif isinstance(label, str) and isinstance(label, str) and '.' in label and not label.endswith('.') and label.rsplit('.', 1)[-1] != '': + elif looks_like_file_path_label(label): is_label_empty = True elif isinstance(label, float): import math @@ -1610,6 +1633,22 @@ def _json_default(o): thumbnail=b"" ) ) + elif isinstance(label, str): + # Text label (e.g. a generative model's reference/target + # text) -- same 'target' stat name as the numeric/dict + # cases above so the frontend's existing pred/target + # column wiring picks it up unchanged; emitted directly + # as a string, never through the numeric float(label) + # path below (which would raise on non-numeric text). + data_stats.append( + create_data_stat( + name='target', + stat_type='string', + shape=[1], + value_string=label, + thumbnail=b"" + ) + ) else: # Check if label is NaN (handle both scalars and arrays) if self._is_nan_value(label): @@ -1764,6 +1803,22 @@ def _json_default(o): if pred is None: pass # No prediction to process + elif isinstance(pred, str): + # Text prediction (e.g. a generative model's reply) -- + # same 'pred' stat name as the numeric case below so the + # frontend's existing pred/target column wiring picks it + # up unchanged; emitted directly as a string, never + # through the numeric float(pred) path (which would + # raise on non-numeric text and get silently dropped). + data_stats.append( + create_data_stat( + name='pred', + stat_type='string', + shape=[1], + value_string=pred, + thumbnail=b"" + ) + ) else: # Handle scalar predictions (int, float, or unwrapped from H5) try: diff --git a/weightslab/trainer/trainer_tools.py b/weightslab/trainer/trainer_tools.py index b2b1fa68..9fbd07fb 100644 --- a/weightslab/trainer/trainer_tools.py +++ b/weightslab/trainer/trainer_tools.py @@ -222,6 +222,22 @@ def mask_to_png_bytes(mask, num_classes=21): return buf.getvalue() +def _numeric_or_text_list(value) -> Tuple[List[int], List[str]]: + """Split a label/prediction value into (int_list, text_list) -- exactly + one of the two is non-empty. Strings (a generated reply, a reference + target string) go to text_list; everything else takes the existing + numeric-coercion path unchanged (single scalar, or a list/ndarray reduced + to its single item, matching the prior int(...) behavior exactly).""" + if isinstance(value, str): + return [], [value] + if isinstance(value, (list, np.ndarray)): + arr = np.asarray(value) + if arr.dtype.kind in ("U", "S", "O") and arr.size and isinstance(arr.reshape(-1)[0], str): + return [], [str(v) for v in arr.reshape(-1).tolist()] + return [int(arr.item())], [] + return [int(value)], [] + + def _class_ids(x, num_classes=None, ignore_index=255): if x is None: return [] @@ -336,6 +352,8 @@ def _safe_dataset_length(ds): ) task_type = sample_stats.task_type + target_list_text = [] + pred_list_text = [] if task_type == "segmentation": label = row.get("target") if isinstance(label, str): @@ -346,10 +364,18 @@ def _safe_dataset_length(ds): else: target = row.get("label", row.get("target", -1)) pred = row.get("prediction_raw", -1) - target_list = [int(target)] if not isinstance(target, (list, np.ndarray)) else [int(np.array(target).item())] - pred_list = [int(pred)] if not isinstance(pred, (list, np.ndarray)) else [int(np.array(pred).item())] + # Text label/prediction (e.g. a generative model's reference text + # and its generated reply): int32 sample_label/sample_prediction + # can't carry these -- route to the additive text fields instead + # of crashing on int(target)/int(pred). Numeric tasks (the vast + # majority: classification/tabular/etc.) are unaffected since + # target/pred there are never plain strings. + target_list, target_list_text = _numeric_or_text_list(target) + pred_list, pred_list_text = _numeric_or_text_list(pred) record.sample_label.extend(target_list) record.sample_prediction.extend(pred_list) + record.sample_label_text.extend(target_list_text) + record.sample_prediction_text.extend(pred_list_text) sample_stats.records.append(record) return sample_stats From 0295d4c4a2e78a9008da29bcabc1cfb675723686 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 30 Jul 2026 10:52:43 +0000 Subject: [PATCH 2/4] Fix GetSamples image-preview crash on text-only (generative) datasets process_sample() (used by the GetSamples/BatchSampleRequest endpoint for image thumbnails) unconditionally ran torch.tensor(tensor) on whatever a dataset's __getitem__/_getitem_raw returned as its first element. For an image dataset that's the image tensor; for a generative/RLHF prompt dataset (see wl-llm-rlhf) it's the prompt STRING, and torch.tensor() on a string raises ("new(): invalid data type 'str'") -- caught internally, so it didn't crash the server, but logged an ERROR for every sample of a text dataset and returned nothing useful. There's genuinely no image to preview for a text-only sample (its content shows via the pred/target DataStat string fields added earlier on this branch, not this thumbnail path), so this is an expected "nothing to render here" case, not a failure -- return the same empty result the exception handler already returned, without the error log. Confirmed against a live wl-llm-rlhf training run: a manual GetSamples call for in-flight sample_ids logged this exact error before the fix. --- tests/trainer/test_trainer_tools.py | 28 ++++++++++++++++++++++++++++ weightslab/trainer/trainer_tools.py | 10 ++++++++++ 2 files changed, 38 insertions(+) diff --git a/tests/trainer/test_trainer_tools.py b/tests/trainer/test_trainer_tools.py index 6f9eb85f..b28b74b8 100644 --- a/tests/trainer/test_trainer_tools.py +++ b/tests/trainer/test_trainer_tools.py @@ -218,6 +218,34 @@ def test_get_input_tensor_for_sample(self): tensor = _get_input_tensor_for_sample(_IndexDataset(), sample_id=0, device="cpu") self.assertEqual(tuple(tensor.shape), (1, 3, 8, 8)) + def test_process_sample_text_only_dataset_returns_empty_without_error(self): + """A generative/RLHF prompt dataset's items are text, not images -- + process_sample (used by the GetSamples image-preview endpoint) must + return an empty/placeholder result instead of crashing on + torch.tensor(a_string) (confirmed empirically: raises 'new(): invalid + data type str').""" + + class _TextDataset: + task_type = "generation" + + def _getitem_raw(self, id): + return "flip a coin", id, "Certainly! Let's flip a fair coin..." + + sid, transformed, raw, cls_label, mask_bytes, pred_bytes = process_sample( + sid=0, + dataset=_TextDataset(), + do_resize=False, + resize_dims=(8, 8), + experiment=_Experiment(), + ) + + self.assertEqual(sid, 0) + self.assertIsNone(transformed) + self.assertIsNone(raw) + self.assertEqual(cls_label, -1) + self.assertEqual(mask_bytes, b"") + self.assertEqual(pred_bytes, b"") + def test_process_sample_classification_and_force_kill(self): exp = _Experiment() ds = _RawDataset() diff --git a/weightslab/trainer/trainer_tools.py b/weightslab/trainer/trainer_tools.py index 9fbd07fb..136dd34c 100644 --- a/weightslab/trainer/trainer_tools.py +++ b/weightslab/trainer/trainer_tools.py @@ -441,6 +441,16 @@ def process_sample(sid, dataset, do_resize, resize_dims, experiment): if isinstance(tensor, torch.Tensor): img = tensor.detach().cpu() + elif isinstance(tensor, str): + # Text-only datasets (e.g. a generative/RLHF prompt dataset) have + # no image to preview here -- their sample content is text, shown + # via the DataStat pred/target string fields instead (see + # data_service.py), not this image-thumbnail path. This is an + # expected "nothing to show" case, not a failure: return early + # rather than falling through to torch.tensor(tensor), which + # raises on a string and would log a misleading error for every + # sample of a text dataset. + return sid, None, None, -1, b"", b"" else: img = torch.tensor(tensor) From 39c6b2aa1da323b9f5c0c7504a5a88b0de06dff2 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 30 Jul 2026 11:30:53 +0000 Subject: [PATCH 3/4] Fix sample_id filter silently matching zero rows (e.g. "sample_id == 11448") sample_id is always stored as a string column (save_signals builds batch_ids_np via str(i) for i in batch_ids), but a user naturally types an unquoted integer in the UI's quick filter/query box. df.query("sample_id == 11448") does NOT raise -- pandas happily evaluates the string "11448" == int 11448 as False for every row -- so it "succeeds" with a silently empty result instead of ever reaching the existing _mask_from_coerced_query fallback, which only triggers on an exception. The UI reported "0 of N samples" for an id that demonstrably exists. Retry once against the coerced view when a query succeeds but returns zero rows on a non-empty dataframe. Scoped to numeric-looking object columns only (via the existing _mask_from_coerced_query helper), so genuine text columns (e.g. the prediction/target strings from this branch's earlier commit) and genuinely-empty-on-purpose queries are unaffected. --- .../test_data_service_sample_id_query.py | 75 +++++++++++++++++++ weightslab/trainer/services/data_service.py | 14 ++++ 2 files changed, 89 insertions(+) create mode 100644 tests/trainer/services/test_data_service_sample_id_query.py diff --git a/tests/trainer/services/test_data_service_sample_id_query.py b/tests/trainer/services/test_data_service_sample_id_query.py new file mode 100644 index 00000000..bf68449f --- /dev/null +++ b/tests/trainer/services/test_data_service_sample_id_query.py @@ -0,0 +1,75 @@ +"""Regression test: filtering by a numeric-looking sample_id (e.g. the UI's +"sample_id == 11448" quick filter) must actually match, even though +sample_id is always stored as a STRING column (see save_signals's +`batch_ids_np = [str(i) for i in batch_ids]`). + +`df.query("sample_id == 11448")` does NOT raise -- pandas happily compares +the string column to the int literal and evaluates to False for every row, +so the existing df.eval/`_mask_from_coerced_query` fallback (which only +triggers on an exception) never kicks in, and the UI reports "0 of N +samples" for an id that genuinely exists. +""" + +import unittest + +import pandas as pd + +from weightslab.trainer.services.data_service import DataService + + +class _StubDataService: + """Minimal stand-in -- _apply_agent_operation's df.query branch only + calls the (static) _mask_from_coerced_query helper, no other self state. + Bound explicitly since a bare object has no relationship to DataService + for `self._mask_from_coerced_query` to resolve through.""" + _mask_from_coerced_query = staticmethod(DataService._mask_from_coerced_query) + + +class TestSampleIdNumericQuery(unittest.TestCase): + def setUp(self): + self.service = _StubDataService() + + def _apply(self, df, expr): + return DataService._apply_agent_operation( + self.service, df, "df.query", {"expr": expr}) + + def test_numeric_literal_matches_a_string_sample_id_column(self): + df = pd.DataFrame({ + "sample_id": ["11448", "22", "34938"], + "reward": [1.0, 2.0, 3.0], + }) + msg = self._apply(df, "sample_id == 11448") + self.assertIn("Applied query", msg) + self.assertEqual(list(df["sample_id"]), ["11448"]) + + def test_still_works_for_genuinely_numeric_columns(self): + df = pd.DataFrame({ + "sample_id": ["1", "2", "3"], + "reward": [1.0, 2.0, 3.0], + }) + self._apply(df, "reward > 1.5") + self.assertEqual(list(df["sample_id"]), ["2", "3"]) + + def test_genuinely_empty_result_stays_empty(self): + df = pd.DataFrame({ + "sample_id": ["1", "2", "3"], + "reward": [1.0, 2.0, 3.0], + }) + self._apply(df, "reward > 1000") + self.assertEqual(len(df), 0) + + def test_text_prediction_column_is_not_coerced_away(self): + # A string-typed 'prediction' column with genuine free text must not + # be affected by the numeric-coercion fallback -- confirms the fix is + # scoped to numeric-looking columns only, not text predictions/labels. + df = pd.DataFrame({ + "sample_id": ["1", "2"], + "prediction": ["Certainly! Let's flip a coin.", "I don't know."], + }) + msg = self._apply(df, "prediction == \"I don't know.\"") + self.assertIn("Applied query", msg) + self.assertEqual(list(df["sample_id"]), ["2"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/weightslab/trainer/services/data_service.py b/weightslab/trainer/services/data_service.py index 3c31126b..89034d74 100755 --- a/weightslab/trainer/services/data_service.py +++ b/weightslab/trainer/services/data_service.py @@ -2933,6 +2933,20 @@ def _apply_agent_operation(self, df, func: str, params: dict) -> str: expr = params.get("expr", "") try: kept = df.query(expr) + if len(kept) == 0 and len(df) > 0: + # A comparison against a numeric-LOOKING but string-typed + # column (sample_id is always stored as str -- see + # save_signals -- and a user naturally types + # "sample_id == 11448" with no quotes) doesn't raise here: + # pandas happily evaluates str "11448" == int 11448 as + # False for every row, so df.query "succeeds" with a + # silently empty result instead of hitting the + # _mask_from_coerced_query fallback below (which only + # triggers on an exception). Retry once against the + # coerced view before accepting "0 rows" at face value. + coerced_mask = self._mask_from_coerced_query(df, expr) + if coerced_mask is not None and coerced_mask.any(): + kept = df[coerced_mask] df.drop(index=df.index.difference(kept.index), inplace=True) return f"Applied query: {expr}" except Exception as e: From b8e3c088ff198d21b04ef1507bd507c0072af5e3 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Thu, 30 Jul 2026 14:26:47 +0200 Subject: [PATCH 4/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- weightslab/trainer/services/data_service.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/weightslab/trainer/services/data_service.py b/weightslab/trainer/services/data_service.py index 89034d74..4c7ebc36 100755 --- a/weightslab/trainer/services/data_service.py +++ b/weightslab/trainer/services/data_service.py @@ -137,10 +137,17 @@ def looks_like_file_path_label(label) -> bool: trailing segment to be short/alphanumeric/whitespace-free keeps this from misfiring on text labels/predictions. """ - if not isinstance(label, str) or '.' not in label or label.endswith('.'): + if not isinstance(label, str): + return False + if any(ch.isspace() for ch in label): + return False + # Avoid treating numeric literals like "3.14" as file paths. + if re.fullmatch(r"[+-]?\d+(\.\d+)?([eE][+-]?\d+)?", label.strip()): + return False + if '.' not in label or label.endswith('.'): return False ext = label.rsplit('.', 1)[-1] - return 1 <= len(ext) <= 6 and ext.isalnum() + return 1 <= len(ext) <= 6 and ext.isalnum() and any(c.isalpha() for c in ext) def normalize_metadata_copy_source_name(source_name: str, experiment_hash: str = None) -> str: