adaptive-harmony 0.1.23__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.
Files changed (67) hide show
  1. adaptive_harmony/__init__.py +162 -0
  2. adaptive_harmony/common/__init__.py +40 -0
  3. adaptive_harmony/common/callbacks.py +219 -0
  4. adaptive_harmony/common/checkpointing.py +163 -0
  5. adaptive_harmony/common/dpo.py +92 -0
  6. adaptive_harmony/common/env_grpo.py +361 -0
  7. adaptive_harmony/common/grpo.py +260 -0
  8. adaptive_harmony/common/gspo.py +70 -0
  9. adaptive_harmony/common/ppo.py +303 -0
  10. adaptive_harmony/common/rm.py +79 -0
  11. adaptive_harmony/common/sft.py +121 -0
  12. adaptive_harmony/core/__init__.py +0 -0
  13. adaptive_harmony/core/dataset.py +72 -0
  14. adaptive_harmony/core/display.py +93 -0
  15. adaptive_harmony/core/image_utils.py +110 -0
  16. adaptive_harmony/core/reasoning.py +12 -0
  17. adaptive_harmony/core/reward_client/__init__.py +19 -0
  18. adaptive_harmony/core/reward_client/client.py +160 -0
  19. adaptive_harmony/core/reward_client/reward_types.py +49 -0
  20. adaptive_harmony/core/reward_client/websocket_utils.py +18 -0
  21. adaptive_harmony/core/rich_counter.py +351 -0
  22. adaptive_harmony/core/rl_utils.py +38 -0
  23. adaptive_harmony/core/schedulers.py +38 -0
  24. adaptive_harmony/core/structured_output.py +385 -0
  25. adaptive_harmony/core/utils.py +365 -0
  26. adaptive_harmony/environment/__init__.py +8 -0
  27. adaptive_harmony/environment/environment.py +121 -0
  28. adaptive_harmony/evaluation/__init__.py +1 -0
  29. adaptive_harmony/evaluation/evaluation_artifact.py +67 -0
  30. adaptive_harmony/graders/__init__.py +20 -0
  31. adaptive_harmony/graders/answer_relevancy_judge/__init__.py +3 -0
  32. adaptive_harmony/graders/answer_relevancy_judge/answer_relevancy_judge.py +102 -0
  33. adaptive_harmony/graders/answer_relevancy_judge/prompts.py +58 -0
  34. adaptive_harmony/graders/base_grader.py +265 -0
  35. adaptive_harmony/graders/binary_judge/__init__.py +8 -0
  36. adaptive_harmony/graders/binary_judge/binary_judge.py +202 -0
  37. adaptive_harmony/graders/binary_judge/prompts.py +125 -0
  38. adaptive_harmony/graders/combined_grader.py +118 -0
  39. adaptive_harmony/graders/context_relevancy_judge/__init__.py +3 -0
  40. adaptive_harmony/graders/context_relevancy_judge/context_relevancy_judge.py +128 -0
  41. adaptive_harmony/graders/context_relevancy_judge/prompts.py +84 -0
  42. adaptive_harmony/graders/exceptions.py +9 -0
  43. adaptive_harmony/graders/faithfulness_judge/__init__.py +3 -0
  44. adaptive_harmony/graders/faithfulness_judge/faithfulness_judge.py +159 -0
  45. adaptive_harmony/graders/faithfulness_judge/prompts.py +22 -0
  46. adaptive_harmony/graders/range_judge/__init__.py +7 -0
  47. adaptive_harmony/graders/range_judge/prompts.py +232 -0
  48. adaptive_harmony/graders/range_judge/range_judge.py +188 -0
  49. adaptive_harmony/graders/range_judge/types.py +12 -0
  50. adaptive_harmony/graders/reward_server_grader.py +36 -0
  51. adaptive_harmony/graders/templated_prompt_judge.py +237 -0
  52. adaptive_harmony/graders/utils.py +79 -0
  53. adaptive_harmony/logging_table.py +1 -0
  54. adaptive_harmony/metric_logger.py +452 -0
  55. adaptive_harmony/parameters/__init__.py +2 -0
  56. adaptive_harmony/py.typed +0 -0
  57. adaptive_harmony/runtime/__init__.py +2 -0
  58. adaptive_harmony/runtime/context.py +2 -0
  59. adaptive_harmony/runtime/data.py +2 -0
  60. adaptive_harmony/runtime/decorators.py +2 -0
  61. adaptive_harmony/runtime/model_artifact_save.py +2 -0
  62. adaptive_harmony/runtime/runner.py +27 -0
  63. adaptive_harmony/runtime/simple_notifier.py +2 -0
  64. adaptive_harmony-0.1.23.dist-info/METADATA +37 -0
  65. adaptive_harmony-0.1.23.dist-info/RECORD +67 -0
  66. adaptive_harmony-0.1.23.dist-info/WHEEL +5 -0
  67. adaptive_harmony-0.1.23.dist-info/top_level.txt +1 -0
@@ -0,0 +1,452 @@
1
+ import html
2
+ import json
3
+ import os
4
+ import tempfile
5
+ from abc import ABC, abstractmethod
6
+ from collections import defaultdict
7
+ from json.decoder import JSONDecodeError
8
+ from pathlib import Path
9
+ from typing import Any, Mapping
10
+
11
+ from loguru import logger as loguru
12
+ from rich.pretty import pprint
13
+
14
+ from adaptive_harmony.logging_table import Table
15
+
16
+
17
+ class Logger(ABC):
18
+ @abstractmethod
19
+ def __call__(self, metrics: Mapping[str, str | int | float | Table]): ...
20
+
21
+ @abstractmethod
22
+ def log_config(self, config: dict[str, Any]): ...
23
+
24
+ @staticmethod
25
+ @abstractmethod
26
+ def is_available() -> bool: ...
27
+
28
+ @property
29
+ def training_monitoring_link(self) -> str | None:
30
+ return None
31
+
32
+ def close(self):
33
+ pass
34
+
35
+
36
+ class MLFlowLogger(Logger):
37
+ def __init__(
38
+ self,
39
+ project_name: str,
40
+ run_name: str,
41
+ tracking_uri: str,
42
+ monitoring_link: str | None = None,
43
+ experiment_tags: dict[str, str] | None = None,
44
+ run_tags: dict[str, str] | None = None,
45
+ min_table_logging_step_interval: int = 5,
46
+ ):
47
+ try:
48
+ import mlflow
49
+ except ImportError:
50
+ raise ImportError(
51
+ "MLFlow is not available."
52
+ "To install adaptive-harmony with MLFlow support, install `adaptive-harmony[mlflow]`"
53
+ )
54
+
55
+ self._mlflow = mlflow
56
+ mlflow.set_tracking_uri(tracking_uri)
57
+ _ = mlflow.set_experiment(project_name)
58
+ if experiment_tags:
59
+ _ = mlflow.set_experiment_tags(experiment_tags)
60
+ self.run = mlflow.start_run(run_name=run_name, log_system_metrics=None, tags=run_tags)
61
+ self.monitoring_link = monitoring_link
62
+ self.step = 0
63
+ self.last_logged_tables_step = 0
64
+ self.min_table_logging_step_interval = min_table_logging_step_interval
65
+ self._log_tables_as_artifacts: bool = False
66
+
67
+ @staticmethod
68
+ def is_available() -> bool:
69
+ try:
70
+ import mlflow # noqa: F401
71
+
72
+ return True
73
+ except ImportError:
74
+ return False
75
+
76
+ def __call__(self, metrics: Mapping[str, str | int | float | Table]):
77
+ metric_logs: dict[str, float] = {}
78
+ str_logs: dict[str, str] = {}
79
+ tables: dict[str, Table] = {}
80
+ for entry, data in metrics.items():
81
+ if isinstance(data, int) or isinstance(data, float):
82
+ metric_logs.update({entry: float(data)})
83
+ elif isinstance(data, Table):
84
+ tables.update({entry: data})
85
+ elif isinstance(data, str):
86
+ str_logs.update({entry: data})
87
+ else:
88
+ print(f"MLFlow logger does not support type: {type(data)}")
89
+ self._mlflow.log_metrics(metric_logs, step=self.step, synchronous=True)
90
+ self._mlflow.log_params(str_logs)
91
+
92
+ if self.step == 0 or (self.step - self.last_logged_tables_step > self.min_table_logging_step_interval):
93
+ for table_entry, table in tables.items():
94
+ headers, rows = table.export()
95
+ # Transpose rows to columns for MLflow
96
+ if rows:
97
+ columns = list(zip(*rows))
98
+ table_dict = {header: list(column) for header, column in zip(headers, columns)}
99
+ table_file_name = f"{table_entry}/step_{self.step}.json"
100
+ if not self._log_tables_as_artifacts:
101
+ try:
102
+ self._mlflow.log_table(data=table_dict, artifact_file=table_file_name)
103
+ except JSONDecodeError:
104
+ loguru.warning(
105
+ f"Reached limit of # tables that can be logged to a single run at step {self.step}"
106
+ "logging tables as artifacts from now on"
107
+ )
108
+ self._log_tables_as_artifacts = True
109
+ else:
110
+ with tempfile.TemporaryDirectory() as tmp_dir:
111
+ path = Path(tmp_dir, table_file_name.replace("/", "_"))
112
+ path.parent.mkdir(parents=True, exist_ok=True)
113
+ path.write_text(json.dumps(table_dict))
114
+ self._mlflow.log_artifact(local_path=str(path))
115
+ self.last_logged_tables_step = self.step
116
+
117
+ self.step += 1
118
+
119
+ def log_config(self, config: dict[str, Any]):
120
+ for key, value in config.items():
121
+ try:
122
+ # MLflow handles params differently - convert to string for complex types
123
+ if isinstance(value, (dict, list)):
124
+ self._mlflow.log_param(key, json.dumps(value))
125
+ else:
126
+ self._mlflow.log_param(key, value)
127
+ except Exception as e:
128
+ print(
129
+ f"Warning: Argument '{key}' with value '{str(value)[:100]}...' "
130
+ f"(type: {type(value).__name__}) could not be logged to mlflow. Error: {e}"
131
+ )
132
+
133
+ @property
134
+ def training_monitoring_link(self) -> str:
135
+ return self.monitoring_link or self._mlflow.get_tracking_uri()
136
+
137
+ def close(self):
138
+ self._mlflow.end_run()
139
+
140
+
141
+ class WandbLogger(Logger):
142
+ def __init__(
143
+ self,
144
+ project_name: str,
145
+ run_name: str,
146
+ entity: str | None = None,
147
+ ):
148
+ try:
149
+ import wandb
150
+ except ImportError:
151
+ raise ImportError(
152
+ "WandB is not available."
153
+ "To install adaptive-harmony with WandB support, install `adaptive-harmony[wandb]`"
154
+ )
155
+
156
+ self._wandb = wandb
157
+ self.run = wandb.init(project=project_name, name=run_name, entity=entity)
158
+ self.step = 0
159
+
160
+ @staticmethod
161
+ def is_available() -> bool:
162
+ try:
163
+ import wandb # noqa: F401
164
+
165
+ return True
166
+ except ImportError:
167
+ return False
168
+
169
+ def __call__(self, metrics: Mapping[str, str | int | float | Table]):
170
+ logs = {k: self._process_metric(v) for k, v in metrics.items()}
171
+ str_logs = {k: str(v) for k, v in logs.items() if isinstance(v, str)}
172
+ metric_logs = {k: v for k, v in logs.items() if not isinstance(v, str)}
173
+ self._wandb.log(metric_logs, step=self.step, commit=True)
174
+ self.run.config.update(str_logs)
175
+ self.step += 1
176
+
177
+ def log_config(self, config: dict[str, Any]):
178
+ for key, value in config.items():
179
+ try:
180
+ self.run.config[key] = value
181
+ except Exception as e:
182
+ print(
183
+ f"Warning: Argument '{key}' with value '{str(value)[:100]}...' "
184
+ f"(type: {type(value).__name__}) could not be logged to wandb. Error: {e}"
185
+ )
186
+
187
+ def _process_metric(self, metric: str | int | float | Table):
188
+ if isinstance(metric, Table):
189
+ headers, rows = metric.export()
190
+ return self._wandb.Table(columns=headers, data=rows)
191
+ else:
192
+ return metric
193
+
194
+ @property
195
+ def training_monitoring_link(self) -> str:
196
+ return self.run.get_url() # type: ignore
197
+
198
+ def close(self):
199
+ self._wandb.finish()
200
+
201
+
202
+ class TBMetricsLogger(Logger):
203
+ def __init__(self, run_name: str, logging_dir: str, monitoring_link: str | None = None):
204
+ try:
205
+ from tensorboardX import SummaryWriter
206
+ except ImportError:
207
+ loguru.error(
208
+ "Tensorboard is not available."
209
+ "To install adaptive-harmony with TB support, install `adaptive-harmony[tensorboard]"
210
+ )
211
+ raise
212
+
213
+ self.monitoring_link = monitoring_link
214
+ self.logging_dir = os.path.join(logging_dir, run_name)
215
+ self.writer = SummaryWriter(str(self.logging_dir), flush_secs=15)
216
+ self.step = 0
217
+
218
+ @staticmethod
219
+ def is_available() -> bool:
220
+ try:
221
+ from tensorboardX import SummaryWriter # noqa: F401
222
+
223
+ return True
224
+ except ImportError:
225
+ return False
226
+
227
+ def __call__(self, logs: Mapping[str, str | int | float | Table]):
228
+ modified_tables = False
229
+ for entry, data in logs.items():
230
+ if isinstance(data, int) or isinstance(data, float):
231
+ self.writer.add_scalar(entry, float(data), self.step)
232
+ elif isinstance(data, Table):
233
+ modified_tables = True
234
+ table_path = os.path.join(self.logging_dir, "html_tables", f"{entry}_{self.step}.html")
235
+ os.makedirs(os.path.dirname(table_path), exist_ok=True)
236
+ with open(table_path, "w") as f:
237
+ f.write(data.to_html_table())
238
+ elif isinstance(data, str):
239
+ self.writer.add_text(entry, data)
240
+ else:
241
+ print(f"TensorBoard logger does not support type: {type(data)}")
242
+
243
+ if modified_tables:
244
+ self.create_index_page(os.path.join(self.logging_dir, "html_tables"), sample_files=None)
245
+
246
+ self.step += 1
247
+ self.writer.flush()
248
+
249
+ def log_config(self, config: dict[str, Any]):
250
+ print("Warming: TensorBoard logger does not support logging config parameters.")
251
+
252
+ def close(self):
253
+ self.writer.close()
254
+
255
+ @property
256
+ def training_monitoring_link(self) -> str:
257
+ return self.monitoring_link or self.logging_dir
258
+
259
+ def create_index_page(self, root_dir: str, sample_files: list[str] | None = None):
260
+ """
261
+ Traverses subdirectories to find all .html files OR uses a sample list
262
+ to create a grouped index.html file with relative links to them.
263
+
264
+ Args:
265
+ root_dir (str): The starting directory to search from.
266
+ Defaults to the current directory.
267
+ sample_files (list, optional): A list of dummy file paths to use
268
+ for a layout preview. If None, the
269
+ script will search the file system.
270
+ """
271
+ if sample_files:
272
+ print("Using sample data to generate layout preview.")
273
+ html_files = sample_files
274
+ else:
275
+ print("Searching for HTML files...")
276
+ html_files = []
277
+ # os.walk is perfect for recursively exploring a directory tree
278
+ for dirpath, _, filenames in os.walk(root_dir):
279
+ for filename in filenames:
280
+ # We are looking for HTML files, but we want to ignore any
281
+ # index files we might have created previously.
282
+ if filename.endswith(".html") and filename != "index.html":
283
+ # Get the full path to the file
284
+ full_path = os.path.join(dirpath, filename)
285
+ # Get the path relative to the root_dir, which is what
286
+ # we need for the hyperlink.
287
+ relative_path = os.path.relpath(full_path, root_dir)
288
+ # On Windows, paths use backslashes. For HTML links, we need
289
+ # forward slashes.
290
+ html_files.append(relative_path.replace("\\", "/"))
291
+
292
+ # Sort the list alphabetically for a clean, predictable order
293
+ html_files.sort()
294
+
295
+ # --- Group files by their parent directory ---
296
+ grouped_files = defaultdict(list)
297
+ for file_path in html_files:
298
+ parent_dir = os.path.dirname(file_path)
299
+ if not parent_dir:
300
+ parent_dir = "Top-Level Reports" # Group for files in root
301
+ grouped_files[parent_dir].append(file_path)
302
+
303
+ # --- Start Generating the HTML for the index page ---
304
+
305
+ # A simple, clean stylesheet for the index page
306
+ css_style = """
307
+ <style>
308
+ body {
309
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
310
+ line-height: 1.6;
311
+ color: #333;
312
+ max-width: 800px;
313
+ margin: 40px auto;
314
+ padding: 0 20px;
315
+ }
316
+ h1 {
317
+ color: #111;
318
+ border-bottom: 2px solid #f0f0f0;
319
+ padding-bottom: 10px;
320
+ }
321
+ .group-container {
322
+ margin-bottom: 30px;
323
+ }
324
+ h2 {
325
+ font-size: 1.2rem;
326
+ color: #444;
327
+ margin-bottom: 10px;
328
+ padding-bottom: 5px;
329
+ border-bottom: 1px solid #e0e0e0;
330
+ }
331
+ ul {
332
+ list-style-type: none;
333
+ padding: 0;
334
+ }
335
+ li {
336
+ margin-bottom: 10px;
337
+ background-color: #f9f9f9;
338
+ border-radius: 5px;
339
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
340
+ transition: box-shadow 0.2s ease-in-out;
341
+ }
342
+ li:hover {
343
+ box-shadow: 0 3px 8px rgba(0,0,0,0.1);
344
+ }
345
+ a {
346
+ text-decoration: none;
347
+ color: #0056b3;
348
+ display: block;
349
+ padding: 12px 15px;
350
+ font-weight: 500;
351
+ }
352
+ a:hover {
353
+ background-color: #f0f5fa;
354
+ border-radius: 5px;
355
+ }
356
+ .file-count {
357
+ font-size: 1rem;
358
+ color: #666;
359
+ margin-top: -10px;
360
+ }
361
+ </style>
362
+ """
363
+
364
+ html_content = f"""
365
+ <!DOCTYPE html>
366
+ <html lang="en">
367
+ <head>
368
+ <meta charset="UTF-8">
369
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
370
+ <title>Index of Reports</title>
371
+ {css_style}
372
+ </head>
373
+ <body>
374
+ <h1>Index of Generated Reports</h1>
375
+ <p class="file-count">Found {len(html_files)} report(s).</p>
376
+ """
377
+
378
+ if not html_files:
379
+ html_content += "<p>No HTML reports were found in the subdirectories.</p>"
380
+ else:
381
+ # Iterate over the grouped dictionary
382
+ for parent_dir, files in grouped_files.items():
383
+ html_content += " <div class='group-container'>\n"
384
+ html_content += f" <h2>{html.escape(parent_dir)}</h2>\n"
385
+ html_content += " <ul>\n"
386
+ for file_path in files:
387
+ # We use html.escape to ensure that any special characters in the
388
+ # filename don't break the HTML.
389
+ safe_path = html.escape(file_path)
390
+ # Display the filename only, not the full path, as the group provides context
391
+ display_name = html.escape(os.path.basename(file_path))
392
+ html_content += f" <li><a href='{safe_path}'>{display_name}</a></li>\n"
393
+ html_content += " </ul>\n"
394
+ html_content += " </div>\n"
395
+
396
+ html_content += """
397
+ </body>
398
+ </html>
399
+ """
400
+
401
+ # Write the generated HTML to the index.html file
402
+ index_file_path = os.path.join(root_dir, "index.html")
403
+ try:
404
+ with open(index_file_path, "w", encoding="utf-8") as f:
405
+ f.write(html_content)
406
+ print(f"Successfully created index.html with {len(html_files)} links.")
407
+ except OSError as e:
408
+ print(f"Error writing to file {index_file_path}: {e}")
409
+
410
+
411
+ class StdoutLogger(Logger):
412
+ def __init__(self): ...
413
+
414
+ @staticmethod
415
+ def is_available() -> bool:
416
+ return True
417
+
418
+ def __call__(self, logs: Mapping[str, str | int | float | Table]):
419
+ pprint(logs)
420
+
421
+ def log_config(self, config: dict[str, Any]):
422
+ print("\n" + "=" * 50)
423
+ pprint(config)
424
+ print("=" * 50 + "\n")
425
+
426
+ def close(self):
427
+ pass
428
+
429
+
430
+ def get_prod_logger() -> Logger:
431
+ job_id = os.environ.get("HARMONY_JOB_ID") or "unknown-job"
432
+ use_case_id = os.environ.get("HARMONY_USE_CASE_ID") or "unknown-use-case"
433
+ use_case_name = os.environ.get("HARMONY_USE_CASE") or "unknown-use-case"
434
+ recipe_name = os.environ.get("HARMONY_RECIPE_NAME") or "unknown-recipe"
435
+ run_name = os.environ.get("HARMONY_JOB_NAME") or "unknown-run"
436
+ if os.environ.get("WANDB_API_KEY") and WandbLogger.is_available():
437
+ return WandbLogger(project_name=use_case_name, run_name=f"{recipe_name}/{run_name}")
438
+ elif (uri := os.environ.get("MLFLOW_TRACKING_URI")) and MLFlowLogger.is_available():
439
+ monitoring_link = os.environ["MLFLOW_MONITORING_LINK"]
440
+ return MLFlowLogger(
441
+ project_name=use_case_name,
442
+ run_name=f"{recipe_name}/{run_name}",
443
+ tracking_uri=uri,
444
+ monitoring_link=monitoring_link,
445
+ experiment_tags={"adaptive.use_case_id": use_case_id},
446
+ run_tags={"adaptive.job_id": job_id},
447
+ )
448
+ elif (log_dir := os.environ.get("TENSORBOARD_LOGGING_DIR")) and TBMetricsLogger.is_available():
449
+ monitoring_link = os.path.join(os.environ["TENSORBOARD_MONITORING_LINK"], job_id)
450
+ return TBMetricsLogger(run_name=job_id, logging_dir=log_dir, monitoring_link=monitoring_link)
451
+ else:
452
+ return StdoutLogger()
@@ -0,0 +1,2 @@
1
+ # Re-export everything from harmony_client.parameters
2
+ from harmony_client.parameters import * # noqa: F403, F401
File without changes
@@ -0,0 +1,2 @@
1
+ # Re-export everything from harmony_client.runtime
2
+ from harmony_client.runtime import * # noqa: F403, F401
@@ -0,0 +1,2 @@
1
+ # Re-export from harmony_client.runtime.context
2
+ from harmony_client.runtime.context import * # noqa: F403, F401
@@ -0,0 +1,2 @@
1
+ # Re-export from harmony_client.runtime.data
2
+ from harmony_client.runtime.data import * # noqa: F403, F401
@@ -0,0 +1,2 @@
1
+ # Re-export from harmony_client.runtime.decorators
2
+ from harmony_client.runtime.decorators import * # noqa: F403, F401
@@ -0,0 +1,2 @@
1
+ # Re-export from harmony_client.runtime.model_artifact_save
2
+ from harmony_client.runtime.model_artifact_save import * # noqa: F403, F401
@@ -0,0 +1,27 @@
1
+ # Re-export from harmony_client.runtime.runner
2
+ from harmony_client.runtime.context import RecipeConfig as RecipeConfig # noqa: F401
3
+ from harmony_client.runtime.context import RecipeContext as RecipeContext
4
+ from harmony_client.runtime.runner import ( # noqa: F401
5
+ RunnerArgs as RunnerArgs,
6
+ )
7
+ from harmony_client.runtime.runner import (
8
+ _download_and_extract_recipe as _download_and_extract_recipe,
9
+ )
10
+ from harmony_client.runtime.runner import (
11
+ _get_params as _get_params,
12
+ )
13
+ from harmony_client.runtime.runner import (
14
+ _install_recipe_dependencies as _install_recipe_dependencies,
15
+ )
16
+ from harmony_client.runtime.runner import (
17
+ _load_and_run_recipe as _load_and_run_recipe,
18
+ )
19
+ from harmony_client.runtime.runner import (
20
+ _parse_script_metadata as _parse_script_metadata,
21
+ )
22
+ from harmony_client.runtime.runner import (
23
+ main as main,
24
+ )
25
+
26
+ if __name__ == "__main__":
27
+ main()
@@ -0,0 +1,2 @@
1
+ # Re-export from harmony_client.runtime.simple_notifier
2
+ from harmony_client.runtime.simple_notifier import * # noqa: F403, F401
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.4
2
+ Name: adaptive-harmony
3
+ Version: 0.1.23
4
+ Summary: Adaptive Harmony training recipes and utilities for LLM fine-tuning
5
+ Classifier: Programming Language :: Python :: 3.12
6
+ Classifier: Programming Language :: Python :: 3.13
7
+ Classifier: Programming Language :: Python :: Implementation :: CPython
8
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
9
+ Requires-Python: >=3.12
10
+ Requires-Dist: harmony-client
11
+ Requires-Dist: rich>=13.7.0
12
+ Requires-Dist: datasets>=2.14.0
13
+ Requires-Dist: hf-xet>=1.1.2
14
+ Requires-Dist: loguru>=0.7.2
15
+ Requires-Dist: pydantic-settings>=2.9.1
16
+ Requires-Dist: pydantic>=2.10.5
17
+ Requires-Dist: pybars3>=0.9.7
18
+ Requires-Dist: pysbd>=0.3.4
19
+ Requires-Dist: websockets>=15.0.1
20
+ Requires-Dist: setproctitle>=1.3.3
21
+ Requires-Dist: pydantic-xml>=2.16.0
22
+ Requires-Dist: openai>=1.42.0
23
+ Requires-Dist: pillow>=11.3.0
24
+ Requires-Dist: boto3>=1.40
25
+ Requires-Dist: tomli>=2
26
+ Provides-Extra: tensorboard
27
+ Requires-Dist: tensorboardX>=2.6.2.2; extra == "tensorboard"
28
+ Provides-Extra: mlflow
29
+ Requires-Dist: mlflow>=3.4.0; extra == "mlflow"
30
+ Provides-Extra: wandb
31
+ Requires-Dist: wandb>=0.19.11; extra == "wandb"
32
+ Provides-Extra: all-monitoring
33
+ Requires-Dist: tensorboardX>=2.6.2.2; extra == "all-monitoring"
34
+ Requires-Dist: mlflow>=3.4.0; extra == "all-monitoring"
35
+ Requires-Dist: wandb>=0.19.11; extra == "all-monitoring"
36
+ Provides-Extra: mlflow-skinny
37
+ Requires-Dist: mlflow-skinny>=3.4.0; extra == "mlflow-skinny"
@@ -0,0 +1,67 @@
1
+ adaptive_harmony/__init__.py,sha256=_KoDEWVU-mCtXWp7ZXXlWcTWSVVkE6_r8xlJDXyOxRw,4849
2
+ adaptive_harmony/logging_table.py,sha256=kN5jS-PO0Y1B6KFicv3BnSyXz5OfThV4L1pCY3_kUmk,56
3
+ adaptive_harmony/metric_logger.py,sha256=6KAp7UhhygiHgWj5l9Bhwc7Sg9cIhxSzAilpxp_7iZM,16619
4
+ adaptive_harmony/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ adaptive_harmony/common/__init__.py,sha256=qebnYmwNBurtouGDbK27mtwt9zLm3P0tHR_M9LnFZT4,967
6
+ adaptive_harmony/common/callbacks.py,sha256=Q5qxVOAdnQRUZxy_ZcBAVxXTmSNA3o7L-cfEZ3JPnWs,8636
7
+ adaptive_harmony/common/checkpointing.py,sha256=rNfzwTEvWzNbUMjkl4CUD3zfsYdsWU_ksR3Lqn-Ghck,6569
8
+ adaptive_harmony/common/dpo.py,sha256=ioionFEnxzagfBVnIvLBh6rb6-d8WeWtVHgp-VDBKf8,3463
9
+ adaptive_harmony/common/env_grpo.py,sha256=bQEBJ7TojBxnCIRopu_pkjzfTl1zAXRcW8olRDMDtIE,15149
10
+ adaptive_harmony/common/grpo.py,sha256=LlG0NxpTtFga06YguTNDnEOVfBjRYHJoRyz4fbAFCRc,10384
11
+ adaptive_harmony/common/gspo.py,sha256=O4z-BrKLusGeM8P6LWz77h8i0HrUhLR7_wxrAluxdxQ,2407
12
+ adaptive_harmony/common/ppo.py,sha256=owJlajLDnOxq4LpjjIn-dLXJVmKlsQh3wMG0zfnbUxU,12393
13
+ adaptive_harmony/common/rm.py,sha256=0HgJXUL722DWhqBOFk_do3k9NUk6g09bEW0qDZxGYfQ,3504
14
+ adaptive_harmony/common/sft.py,sha256=A_g72b6Et7wCSApdc8TFcCn5JoRWQgYwG1WsKm-aiaY,4883
15
+ adaptive_harmony/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ adaptive_harmony/core/dataset.py,sha256=MnECz5f0ff3D8MYOvG4Q9RXAJmuoCSk5vi7ysgo4TBM,2474
17
+ adaptive_harmony/core/display.py,sha256=Wid2sRv4MPUqDlpEcAhncBmkixT32JhkLCN9oAxw658,3073
18
+ adaptive_harmony/core/image_utils.py,sha256=NJeK3IOB-hbTuc5XR5-eSqAzomwmDOwoZChsdcjyUV0,3775
19
+ adaptive_harmony/core/reasoning.py,sha256=36HW5jBkAtWibx90CAVes_E8MlbzSAI0v0K4ITSzk-Q,445
20
+ adaptive_harmony/core/rich_counter.py,sha256=z0uIq1pLES8F7wcdyQALxD3NU-vTOmlLPyeeyVotZRg,12334
21
+ adaptive_harmony/core/rl_utils.py,sha256=gEY37o-h3jIF7lW9E9SGnFoIcBasBn3byO6-0SUK4PI,1023
22
+ adaptive_harmony/core/schedulers.py,sha256=tqjxaIsjlXAkGWfTCnvnKhTCblrIJStHaUxfAGK3qwU,1361
23
+ adaptive_harmony/core/structured_output.py,sha256=xvtQEor9Cjce5T4lYFLsN1NkZPqbomw15Jq7Cl3-MFM,14940
24
+ adaptive_harmony/core/utils.py,sha256=1q2ouNOti5IH43vGIYrx5Jm7qPokQIOVbUKJw9aV5ss,13412
25
+ adaptive_harmony/core/reward_client/__init__.py,sha256=q513qDHyTPmZZCYpedXbevHnykimn1hDqo6zzyTc65c,459
26
+ adaptive_harmony/core/reward_client/client.py,sha256=4UcgWPuaptGNJz2isp895u1szA1chwLKn6WlpefnPn8,5946
27
+ adaptive_harmony/core/reward_client/reward_types.py,sha256=1K0yfOzNAHT1GQfa8vpuWkt5o0Afe7iZ4lkzvdxWelY,817
28
+ adaptive_harmony/core/reward_client/websocket_utils.py,sha256=3oedoZDhKLnwp98g1QanepWHCXv92G3k_IJC3_MPH0E,499
29
+ adaptive_harmony/environment/__init__.py,sha256=6WpEGBGfQ4Cnr2rRncZ-S6nKDBllWimhwnN7DEqgDHQ,185
30
+ adaptive_harmony/environment/environment.py,sha256=yDAcR2VzlU-2-OdWbqVi1IPtMCqNDwiDFjKstK1axpo,3907
31
+ adaptive_harmony/evaluation/__init__.py,sha256=wsMYryTeiITYV0PHW86Alkz2z6WDdrKM6EkYON4VdLw,74
32
+ adaptive_harmony/evaluation/evaluation_artifact.py,sha256=9rx0mDg5BENIWH6Zzq9br8CsKyJrkc_Ls8jXz0bPY0w,1958
33
+ adaptive_harmony/graders/__init__.py,sha256=id10TznTfd5G0xmVNkjCbe-bWKuykHxOFCCqWrcVbXQ,580
34
+ adaptive_harmony/graders/base_grader.py,sha256=TYOeFxXgoUoOK1HaiKgjnRAucyjdlX42e2kDs0jNi2Q,9988
35
+ adaptive_harmony/graders/combined_grader.py,sha256=wmJDxBVS3U3kNPBC1nROlthfm3ZhfzWVAESzizGo9Bs,4597
36
+ adaptive_harmony/graders/exceptions.py,sha256=YBUQpx1_3RkN_GcxvKLCtODhqPUqCdOiwmdxJ01vG9s,330
37
+ adaptive_harmony/graders/reward_server_grader.py,sha256=93qkUIDdCvyvoe6OniJS500UuFtI74i1_e9fqCm_zWc,1360
38
+ adaptive_harmony/graders/templated_prompt_judge.py,sha256=0TNg9agPABXn0aIrnpMyjQFW2Dr5303L53xirIfaatk,10076
39
+ adaptive_harmony/graders/utils.py,sha256=iZHILLwQn72DXyyuFlb-6XUUEzG0t78VbaDs0yXfsWI,2533
40
+ adaptive_harmony/graders/answer_relevancy_judge/__init__.py,sha256=942BWEsIpWdkNfjzp-Ma1ZXtpmop1MF0E7b1u0CcJKY,95
41
+ adaptive_harmony/graders/answer_relevancy_judge/answer_relevancy_judge.py,sha256=KdYi6urGrVxgYBUExMGt5wit6Pf5f-K5Vfys5QgfM6w,4495
42
+ adaptive_harmony/graders/answer_relevancy_judge/prompts.py,sha256=ncIbN2UVpc9lnVimkiL3w7QrjseXoeBRk6mJvEAbL0k,1894
43
+ adaptive_harmony/graders/binary_judge/__init__.py,sha256=HmdU6eJyv4-EQPXqEtXG1kQ8Sco6X4D2iUzoOFZwRDY,188
44
+ adaptive_harmony/graders/binary_judge/binary_judge.py,sha256=Y5DiqiGSo4A68rBYrjqY70Wxyny5v5HwWHjfzPWnyVw,8307
45
+ adaptive_harmony/graders/binary_judge/prompts.py,sha256=3VQ5DebmMUBxqO9hAvLAsqfaTQw5aYqvExZozlGszZs,6415
46
+ adaptive_harmony/graders/context_relevancy_judge/__init__.py,sha256=wrxO_2-cVZvFXOtMm2O1_1hdv__eqNrJ0bvxRrE9Pvc,98
47
+ adaptive_harmony/graders/context_relevancy_judge/context_relevancy_judge.py,sha256=IATqNn_Uw6cp5jxdBl-fXMemg5webQcC-893e4wvggw,5294
48
+ adaptive_harmony/graders/context_relevancy_judge/prompts.py,sha256=eb8tmrNuHT4I7qunf5pCfr3BVis2pWfgS-BBKo3XJQs,3647
49
+ adaptive_harmony/graders/faithfulness_judge/__init__.py,sha256=8Dx5_aujk3TPR9p3iBIS8Xj1S9G2wxiQ8x44WIACUYc,85
50
+ adaptive_harmony/graders/faithfulness_judge/faithfulness_judge.py,sha256=5qOcjfPeT_7-dUGZ4MO5GeYuy32U90Yg2GXVs-YZ7BE,6044
51
+ adaptive_harmony/graders/faithfulness_judge/prompts.py,sha256=_3otDjyjUaKfebeE0yYZXU99zImi-uJ_E7D1sHEhZmg,984
52
+ adaptive_harmony/graders/range_judge/__init__.py,sha256=h2LObCYzY0h8QumTBcfjNuBW31WfZ7rkojmrL0m4rbU,200
53
+ adaptive_harmony/graders/range_judge/prompts.py,sha256=V2iVWUDGP54-I_pHR2yPyR9SuVYMa-yaOtCRag5Dq9s,9331
54
+ adaptive_harmony/graders/range_judge/range_judge.py,sha256=Av8qMqcWm8J3c8Tli_yPqMJGTlQos9dlwAbi32HcBOo,8199
55
+ adaptive_harmony/graders/range_judge/types.py,sha256=UlS_HhYiD5mNXEGK7M8jugFlk-WtvVNqMQh3IYqBUno,398
56
+ adaptive_harmony/parameters/__init__.py,sha256=MBCDZ2YzqM8J2oU3BIH2t1mnr85xHrvlLQyU-lcEHdg,114
57
+ adaptive_harmony/runtime/__init__.py,sha256=AQ9pixPP4KrHaElpDTtghaDN4VVrfh5meQJithPtnWo,108
58
+ adaptive_harmony/runtime/context.py,sha256=G-aijdP0WLHfNU8zfPFm9czGiowU79yHRjvdqAC4mlc,113
59
+ adaptive_harmony/runtime/data.py,sha256=oP1WKOLueVHuLodnz_ZHge8JCWR_YInZI7ug2LXKvQk,107
60
+ adaptive_harmony/runtime/decorators.py,sha256=zDNnG_fNz-zgHnb-d5WCPNLMMKFRtL_ncz4wEGVSp-o,119
61
+ adaptive_harmony/runtime/model_artifact_save.py,sha256=1Ui-Q1hP_eDAhKBFOXpEVix5Q3TY9_d11viXs0xsk3o,137
62
+ adaptive_harmony/runtime/runner.py,sha256=70lNz2pe2dGEgqH8Igwp8ppGLDLxHVwNmxcyV4Y6HMM,898
63
+ adaptive_harmony/runtime/simple_notifier.py,sha256=iVXtZwfcOvkZlWQgFC0qjE1P-yA6Y7Wx0SxQ9FoJ-0s,129
64
+ adaptive_harmony-0.1.23.dist-info/METADATA,sha256=vSt6Q78VZyskfevyOZyIACXAKoSSfFEIm1FeTwgeipE,1429
65
+ adaptive_harmony-0.1.23.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
66
+ adaptive_harmony-0.1.23.dist-info/top_level.txt,sha256=ZEmoKxkFM4M7H2mgH15wQ4Tf0Eb13FBmghRvC2seacU,17
67
+ adaptive_harmony-0.1.23.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ adaptive_harmony