SafeLLM4SE 0.1.1__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 (58) hide show
  1. safellm4se/__init__.py +13 -0
  2. safellm4se/compare.py +57 -0
  3. safellm4se/comparing/__init__.py +0 -0
  4. safellm4se/comparing/cli.py +176 -0
  5. safellm4se/comparing/comparator.py +58 -0
  6. safellm4se/comparing/metrics.py +722 -0
  7. safellm4se/comparing/models.py +67 -0
  8. safellm4se/comparing/plots.py +335 -0
  9. safellm4se/comparing/writer.py +30 -0
  10. safellm4se/py.typed +1 -0
  11. safellm4se/report.py +58 -0
  12. safellm4se/reporting/__init__.py +13 -0
  13. safellm4se/reporting/cli.py +180 -0
  14. safellm4se/reporting/metrics.py +259 -0
  15. safellm4se/reporting/models.py +22 -0
  16. safellm4se/reporting/plots.py +368 -0
  17. safellm4se/reporting/reader.py +107 -0
  18. safellm4se/reporting/reporter.py +45 -0
  19. safellm4se/reporting/writer.py +30 -0
  20. safellm4se/sample.py +63 -0
  21. safellm4se/sampling/__init__.py +6 -0
  22. safellm4se/sampling/cli.py +448 -0
  23. safellm4se/sampling/config/__init__.py +5 -0
  24. safellm4se/sampling/config/config.py +33 -0
  25. safellm4se/sampling/config/logger.py +89 -0
  26. safellm4se/sampling/evaluators.py +312 -0
  27. safellm4se/sampling/locking.py +37 -0
  28. safellm4se/sampling/models.py +40 -0
  29. safellm4se/sampling/myevaluators/__init__.py +1 -0
  30. safellm4se/sampling/myevaluators/base_evaluator.py +119 -0
  31. safellm4se/sampling/myevaluators/gemini/__init__.py +0 -0
  32. safellm4se/sampling/myevaluators/gemini/common.py +540 -0
  33. safellm4se/sampling/myevaluators/gemini/humaneval_fullbench.py +226 -0
  34. safellm4se/sampling/myevaluators/gemini/humaneval_oneprogram.py +110 -0
  35. safellm4se/sampling/myevaluators/gemini/random.py +73 -0
  36. safellm4se/sampling/myevaluators/grok_evaluator.py +143 -0
  37. safellm4se/sampling/myevaluators/groq/__init__.py +1 -0
  38. safellm4se/sampling/myevaluators/groq/common.py +605 -0
  39. safellm4se/sampling/myevaluators/groq/humaneval_fullbench.py +223 -0
  40. safellm4se/sampling/myevaluators/groq/humaneval_oneprogram.py +108 -0
  41. safellm4se/sampling/myevaluators/groq/random.py +79 -0
  42. safellm4se/sampling/myevaluators/ollama/__init__.py +0 -0
  43. safellm4se/sampling/myevaluators/ollama/common.py +489 -0
  44. safellm4se/sampling/myevaluators/ollama/humaneval_fullbench.py +186 -0
  45. safellm4se/sampling/myevaluators/ollama/humaneval_oneprogram.py +108 -0
  46. safellm4se/sampling/myevaluators/ollama/random.py +71 -0
  47. safellm4se/sampling/myevaluators/random_binary_evaluator.py +81 -0
  48. safellm4se/sampling/myevaluators/random_normal_evaluator.py +90 -0
  49. safellm4se/sampling/persistence.py +477 -0
  50. safellm4se/sampling/sampler.py +198 -0
  51. safellm4se/sampling/statistics.py +35 -0
  52. safellm4se/statistical_utils.py +446 -0
  53. safellm4se-0.1.1.dist-info/METADATA +166 -0
  54. safellm4se-0.1.1.dist-info/RECORD +58 -0
  55. safellm4se-0.1.1.dist-info/WHEEL +5 -0
  56. safellm4se-0.1.1.dist-info/entry_points.txt +4 -0
  57. safellm4se-0.1.1.dist-info/licenses/LICENSE +21 -0
  58. safellm4se-0.1.1.dist-info/top_level.txt +1 -0
safellm4se/__init__.py ADDED
@@ -0,0 +1,13 @@
1
+ """Public package interface for SafeLLM4SE."""
2
+
3
+ from safellm4se.sampling.models import SamplerSettings, SamplingObservation
4
+ from safellm4se.sampling.sampler import AdaptiveSampler
5
+
6
+ __version__: str = "0.1.0"
7
+
8
+ __all__: list[str] = [
9
+ "AdaptiveSampler",
10
+ "SamplerSettings",
11
+ "SamplingObservation",
12
+ "__version__",
13
+ ]
safellm4se/compare.py ADDED
@@ -0,0 +1,57 @@
1
+ """Command-line entry point for SafeLLM4SE two-sample CSV comparisons."""
2
+
3
+ import argparse
4
+ from pathlib import Path
5
+
6
+ from loguru import logger
7
+
8
+ from safellm4se.comparing.cli import parse_args, settings_from_args
9
+ from safellm4se.comparing.comparator import generate_comparison_report
10
+ from safellm4se.comparing.models import ComparisonSettings
11
+ from safellm4se.sampling.config.logger import create_log_file_path, setup_logger
12
+
13
+
14
+ def _console_log_level_from_args(args: argparse.Namespace) -> str | None:
15
+ """Return the console log level requested by command-line arguments.
16
+
17
+ Args:
18
+ args: Parsed command-line arguments.
19
+
20
+ Returns:
21
+ A log level for console output, or None when console logging is disabled.
22
+ """
23
+ if args.log_level:
24
+ return args.log_level
25
+ if args.verbose:
26
+ return "INFO"
27
+ return None
28
+
29
+
30
+ def main() -> None:
31
+ """Run the comparison report command-line entry point.
32
+
33
+ Raises:
34
+ Exception: Re-raises uncaught exceptions from comparison generation.
35
+ """
36
+ args: argparse.Namespace = parse_args()
37
+ settings: ComparisonSettings = settings_from_args(args)
38
+ log_directory: Path = settings.output_path.parent
39
+ log_file: Path | None = setup_logger(
40
+ create_log_file_path(log_directory),
41
+ console_level=_console_log_level_from_args(args),
42
+ )
43
+ logger.info("Running SafeLLM4SE comparison report generation...")
44
+ if log_file is not None:
45
+ logger.info(f"Execution log written to {log_file}.")
46
+ try:
47
+ generate_comparison_report(settings)
48
+ final_message: str = f"Comparison report written in {settings.output_path}."
49
+ logger.info(final_message)
50
+ print(final_message)
51
+ except Exception:
52
+ logger.exception("SafeLLM4SE comparison report generation failed.")
53
+ raise
54
+
55
+
56
+ if __name__ == "__main__":
57
+ main()
File without changes
@@ -0,0 +1,176 @@
1
+ """Command-line parsing for SafeLLM4SE comparison reports."""
2
+
3
+ import argparse
4
+ from pathlib import Path
5
+
6
+ from safellm4se.sampling.config.logger import LOG_LEVELS
7
+
8
+ from safellm4se.reporting.cli import MandatoryAwareDefaultsHelpFormatter
9
+ from safellm4se.comparing.models import ComparisonSettings
10
+
11
+
12
+ def build_parser() -> argparse.ArgumentParser:
13
+ """Build the command-line parser used by comparing.py.
14
+
15
+ Returns:
16
+ A configured argument parser for two-sample comparison reports.
17
+ """
18
+ parser: argparse.ArgumentParser = argparse.ArgumentParser(
19
+ description="SafeLLM4SE two-sample CSV comparison reporting.",
20
+ formatter_class=MandatoryAwareDefaultsHelpFormatter,
21
+ )
22
+ parser.add_argument(
23
+ "--h",
24
+ action="help",
25
+ help="Show this help message and exit.",
26
+ )
27
+ parser.add_argument(
28
+ "--input",
29
+ required=True,
30
+ metavar="FILE_NAME",
31
+ help="Input CSV file generated by sample.py.",
32
+ )
33
+ parser.add_argument(
34
+ "--output",
35
+ default="comparing.csv",
36
+ metavar="FILE_NAME",
37
+ help="Output CSV comparison report file.",
38
+ )
39
+ parser.add_argument(
40
+ "--verbose",
41
+ action="store_true",
42
+ help="Show INFO and higher log messages on screen.",
43
+ )
44
+ parser.add_argument(
45
+ "--log",
46
+ dest="log_level",
47
+ choices=LOG_LEVELS,
48
+ type=str.upper,
49
+ metavar="LEVEL",
50
+ default=None,
51
+ help=(
52
+ "Show log messages on screen from the selected level. Accepted "
53
+ f"values: {', '.join(LOG_LEVELS)}."
54
+ ),
55
+ )
56
+ parser.add_argument(
57
+ "--task-id-1",
58
+ required=True,
59
+ metavar="TASK_ID",
60
+ help="First task identifier to include in the comparison report.",
61
+ )
62
+ parser.add_argument(
63
+ "--task-name-1",
64
+ metavar="NAME",
65
+ default=None,
66
+ help="Optional first task name to display in generated plots.",
67
+ )
68
+ parser.add_argument(
69
+ "--task-id-2",
70
+ required=True,
71
+ metavar="TASK_ID",
72
+ help="Second task identifier to include in the comparison report.",
73
+ )
74
+ parser.add_argument(
75
+ "--task-name-2",
76
+ metavar="NAME",
77
+ default=None,
78
+ help="Optional second task name to display in generated plots.",
79
+ )
80
+ parser.add_argument(
81
+ "--test-type",
82
+ required=True,
83
+ choices=["paired", "independent"],
84
+ help="Experimental design used to comparing both distributions.",
85
+ )
86
+ parser.add_argument(
87
+ "--confidence-level",
88
+ default=0.95,
89
+ type=float,
90
+ metavar="CONFIDENCE_LEVEL",
91
+ help="Confidence level used for confidence intervals.",
92
+ )
93
+ parser.add_argument(
94
+ "--boxplot",
95
+ metavar="FILE_NAME",
96
+ default=None,
97
+ help="Optional SVG output file for a two-sample boxplot.",
98
+ )
99
+ parser.add_argument(
100
+ "--violin",
101
+ metavar="FILE_NAME",
102
+ default=None,
103
+ help="Optional SVG output file for a two-sample violin plot.",
104
+ )
105
+ parser.add_argument(
106
+ "--ECDF",
107
+ "--ecdf",
108
+ dest="ecdf",
109
+ metavar="FILE_NAME",
110
+ default=None,
111
+ help="Optional SVG output file for a two-sample ECDF plot.",
112
+ )
113
+ parser.add_argument(
114
+ "--raincloud",
115
+ metavar="FILE_NAME",
116
+ default=None,
117
+ help="Optional SVG output file for a two-sample raincloud plot.",
118
+ )
119
+ parser.add_argument(
120
+ "--KDE",
121
+ "--kde",
122
+ dest="kde",
123
+ metavar="FILE_NAME",
124
+ default=None,
125
+ help="Optional SVG output file for a two-sample KDE plot.",
126
+ )
127
+ return parser
128
+
129
+
130
+ def parse_args() -> argparse.Namespace:
131
+ """Parse command-line arguments for a comparison report generation run.
132
+
133
+ Returns:
134
+ The parsed command-line namespace.
135
+ """
136
+ return build_parser().parse_args()
137
+
138
+
139
+ def settings_from_args(args: argparse.Namespace) -> ComparisonSettings:
140
+ """Create comparison settings from parsed command-line arguments.
141
+
142
+ Args:
143
+ args: Parsed command-line arguments.
144
+
145
+ Returns:
146
+ Runtime settings for comparison report generation.
147
+ """
148
+ return ComparisonSettings(
149
+ input_path=Path(args.input),
150
+ output_path=Path(args.output),
151
+ boxplot_path=_optional_path(args.boxplot),
152
+ violin_path=_optional_path(args.violin),
153
+ ecdf_path=_optional_path(args.ecdf),
154
+ raincloud_path=_optional_path(args.raincloud),
155
+ kde_path=_optional_path(args.kde),
156
+ task_id_1=args.task_id_1,
157
+ task_id_2=args.task_id_2,
158
+ task_name_1=args.task_name_1,
159
+ task_name_2=args.task_name_2,
160
+ test_type=args.test_type,
161
+ confidence_level=args.confidence_level,
162
+ )
163
+
164
+
165
+ def _optional_path(file_name: str | None) -> Path | None:
166
+ """Return a Path for an optional file name.
167
+
168
+ Args:
169
+ file_name: Optional command-line file name.
170
+
171
+ Returns:
172
+ A path when a file name was provided; otherwise, None.
173
+ """
174
+ if file_name is None:
175
+ return None
176
+ return Path(file_name)
@@ -0,0 +1,58 @@
1
+ """High-level comparison workflow for SafeLLM4SE sampling outputs."""
2
+
3
+ from typing import Any
4
+
5
+ from loguru import logger
6
+
7
+ from safellm4se.comparing.metrics import build_comparison_report_row
8
+ from safellm4se.comparing.models import ComparisonSettings
9
+ from safellm4se.comparing.plots import generate_requested_comparison_plots
10
+ from safellm4se.comparing.writer import write_comparison_report
11
+ from safellm4se.reporting.metrics import parse_theta_values
12
+ from safellm4se.reporting.reader import read_task_rows
13
+
14
+
15
+ def generate_comparison_report(settings: ComparisonSettings) -> dict[str, Any]:
16
+ """Generate a two-sample comparison report CSV.
17
+
18
+ Args:
19
+ settings: Runtime settings for comparison report generation.
20
+
21
+ Returns:
22
+ The generated comparison report row.
23
+
24
+ Raises:
25
+ FileNotFoundError: If the input CSV file does not exist.
26
+ OSError: If the output CSV file or plot files cannot be written.
27
+ ValueError: If the input data is invalid or inconsistent.
28
+ """
29
+ logger.info("Reading sampling measurements from {}.", settings.input_path)
30
+ rows_1: list[dict[str, str]] = read_task_rows(
31
+ settings.input_path,
32
+ settings.task_id_1,
33
+ )
34
+ rows_2: list[dict[str, str]] = read_task_rows(
35
+ settings.input_path,
36
+ settings.task_id_2,
37
+ )
38
+ logger.info(
39
+ "Generating comparison report from {} and {} filtered rows.",
40
+ len(rows_1),
41
+ len(rows_2),
42
+ )
43
+ report_row: dict[str, Any] = build_comparison_report_row(
44
+ rows_1,
45
+ rows_2,
46
+ settings.test_type,
47
+ settings.confidence_level,
48
+ )
49
+ write_comparison_report(settings.output_path, report_row)
50
+ logger.info("Comparison report written to {}.", settings.output_path)
51
+ generated_plot_paths = generate_requested_comparison_plots(
52
+ parse_theta_values(rows_1),
53
+ parse_theta_values(rows_2),
54
+ settings,
55
+ )
56
+ for generated_plot_path in generated_plot_paths:
57
+ logger.info("Comparison plot written to {}.", generated_plot_path)
58
+ return report_row