opik-optimizer 0.8.1__py3-none-any.whl → 0.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. opik_optimizer/__init__.py +15 -26
  2. opik_optimizer/base_optimizer.py +28 -44
  3. opik_optimizer/datasets/__init__.py +6 -7
  4. opik_optimizer/evolutionary_optimizer/evolutionary_optimizer.py +742 -726
  5. opik_optimizer/evolutionary_optimizer/reporting.py +246 -0
  6. opik_optimizer/few_shot_bayesian_optimizer/few_shot_bayesian_optimizer.py +297 -193
  7. opik_optimizer/few_shot_bayesian_optimizer/reporting.py +119 -0
  8. opik_optimizer/meta_prompt_optimizer/__init__.py +5 -0
  9. opik_optimizer/meta_prompt_optimizer/meta_prompt_optimizer.py +816 -0
  10. opik_optimizer/meta_prompt_optimizer/reporting.py +140 -0
  11. opik_optimizer/mipro_optimizer/__init__.py +1 -1
  12. opik_optimizer/mipro_optimizer/_mipro_optimizer_v2.py +12 -20
  13. opik_optimizer/mipro_optimizer/mipro_optimizer.py +32 -52
  14. opik_optimizer/mipro_optimizer/utils.py +1 -23
  15. opik_optimizer/optimization_config/chat_prompt.py +106 -0
  16. opik_optimizer/optimization_config/configs.py +2 -21
  17. opik_optimizer/optimization_config/mappers.py +1 -1
  18. opik_optimizer/optimization_result.py +57 -85
  19. opik_optimizer/reporting_utils.py +180 -0
  20. opik_optimizer/task_evaluator.py +41 -26
  21. opik_optimizer/utils.py +187 -3
  22. {opik_optimizer-0.8.1.dist-info → opik_optimizer-0.9.0.dist-info}/METADATA +15 -31
  23. opik_optimizer-0.9.0.dist-info/RECORD +48 -0
  24. {opik_optimizer-0.8.1.dist-info → opik_optimizer-0.9.0.dist-info}/WHEEL +1 -1
  25. opik_optimizer/few_shot_bayesian_optimizer/prompt_parameter.py +0 -91
  26. opik_optimizer/few_shot_bayesian_optimizer/prompt_templates.py +0 -80
  27. opik_optimizer/integrations/__init__.py +0 -0
  28. opik_optimizer/meta_prompt_optimizer.py +0 -1151
  29. opik_optimizer-0.8.1.dist-info/RECORD +0 -45
  30. {opik_optimizer-0.8.1.dist-info → opik_optimizer-0.9.0.dist-info}/licenses/LICENSE +0 -0
  31. {opik_optimizer-0.8.1.dist-info → opik_optimizer-0.9.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,246 @@
1
+ from contextlib import contextmanager
2
+ from io import StringIO
3
+ from typing import List
4
+
5
+ import rich
6
+ from rich.console import Console
7
+ from rich.panel import Panel
8
+ from rich.text import Text
9
+
10
+ from ..optimization_config import chat_prompt
11
+ from ..reporting_utils import (
12
+ convert_tqdm_to_rich,
13
+ display_configuration, # noqa: F401
14
+ display_header, # noqa: F401
15
+ display_messages, # noqa: F401
16
+ display_result, # noqa: F401
17
+ get_console,
18
+ suppress_opik_logs,
19
+ )
20
+
21
+ PANEL_WIDTH = 70
22
+ console = get_console()
23
+
24
+
25
+ @contextmanager
26
+ def infer_output_style(verbose: int = 1):
27
+ class Reporter:
28
+ def start_style_inference(self, output_style_prompt):
29
+ if verbose >= 1:
30
+ console.print("> Infering the output style using the prompt:")
31
+ console.print("│")
32
+
33
+ def error(self, error_message):
34
+ if verbose >= 1:
35
+ console.print(Text("│ ").append(Text(f"Failed to infer output style: {error_message}", style="red")))
36
+ console.print(Text("│ ").append(Text("Continuing with default style", style="dim")))
37
+
38
+ def display_style_inference_prompt(self, output_style_prompt):
39
+ if verbose >= 1:
40
+ panel = Panel(
41
+ Text(output_style_prompt),
42
+ title="Output style inference prompt",
43
+ title_align="left",
44
+ border_style="dim",
45
+ width=PANEL_WIDTH,
46
+ padding=(1, 2),
47
+ )
48
+
49
+ # Use a temporary buffer to render the panel
50
+ buffer = StringIO()
51
+ temp_console = get_console(file=buffer, width=console.width)
52
+ temp_console.print(panel)
53
+
54
+ # Add prefix to each line
55
+ panel_output = buffer.getvalue()
56
+ prefixed = "\n".join(f"│ {line}" for line in panel_output.splitlines())
57
+
58
+ # Print the final result
59
+ console.print(prefixed)
60
+ console.print(Text("│"))
61
+
62
+ def success(self, output_style_prompt):
63
+ if verbose >= 1:
64
+ panel = Panel(
65
+ Text(output_style_prompt),
66
+ title="Successfully inferred output style",
67
+ title_align="left",
68
+ border_style="green",
69
+ width=PANEL_WIDTH,
70
+ padding=(1, 2),
71
+ )
72
+
73
+ # Capture the panel as rendered text with ANSI styles
74
+ with console.capture() as capture:
75
+ console.print(panel)
76
+
77
+ # Retrieve the rendered string (with ANSI)
78
+ rendered_panel = capture.get()
79
+
80
+ # Prefix each line with '│ ', preserving ANSI styles
81
+ prefixed_output = "\n".join(f"│ {line}" for line in rendered_panel.splitlines())
82
+
83
+ # Print the prefixed output (will include colors)
84
+ console.print(prefixed_output, highlight=False)
85
+ console.print(Text(""))
86
+
87
+ try:
88
+ yield Reporter()
89
+ finally:
90
+ pass
91
+
92
+ @contextmanager
93
+ def initializing_population(verbose: int = 1):
94
+ class Reporter:
95
+ def start(self, population_size):
96
+ if verbose >= 1:
97
+ console.print(f"> Creating {population_size - 1} variations of the initial prompt")
98
+ console.print("│")
99
+
100
+ def start_fresh_prompts(self, num_fresh_starts):
101
+ if verbose >= 1:
102
+ console.print(f"│ Generating {num_fresh_starts} fresh prompts based on the task description.")
103
+
104
+ def success_fresh_prompts(self, num_fresh_starts):
105
+ if verbose >= 1:
106
+ console.print(Text("│ ").append(Text(f"Successfully generated {num_fresh_starts} fresh prompts based on the task description.", style="dim green")))
107
+ console.print("│")
108
+
109
+ def failed_fresh_prompts(self, num_fresh_starts, error):
110
+ if verbose >= 1:
111
+ console.print(Text("│ ").append(Text(f"Failed to generate fresh prompts from LLM: {error}", style="dim red")))
112
+ console.print("│")
113
+
114
+ def start_variations(self, num_variations):
115
+ if verbose >= 1:
116
+ console.print(f"│ Generating {num_variations} variations of the initial prompt.")
117
+
118
+ def success_variations(self, num_variations):
119
+ if verbose >= 1:
120
+ console.print(Text(f"│ Successfully generated {num_variations - 1} variations of the initial prompt).", style="dim green"))
121
+ console.print("│")
122
+
123
+ def failed_variations(self, num_variations, error):
124
+ if verbose >= 1:
125
+ console.print(Text(f"│ Failed to generate {num_variations - 1} variations of the initial prompt: {error}", style="dim red"))
126
+ console.print("│")
127
+
128
+ def end(self, population_prompts: List[chat_prompt.ChatPrompt]):
129
+ if verbose >= 1:
130
+ console.print(f"│ Successfully initialized population with {len(population_prompts)} prompts.")
131
+ console.print("")
132
+
133
+
134
+ try:
135
+ yield Reporter()
136
+ finally:
137
+ pass
138
+
139
+ @contextmanager
140
+ def baseline_performance(verbose: int = 1):
141
+ """Context manager to display messages during an evaluation phase."""
142
+ # Entry point
143
+ if verbose >= 1:
144
+ console.print(Text("> First we will establish the baseline performance."))
145
+
146
+ # Create a simple object with a method to set the score
147
+ class Reporter:
148
+ def set_score(self, s):
149
+ if verbose >= 1:
150
+ console.print(Text(f"\r Baseline score was: {s:.4f}.\n", style="green"))
151
+
152
+ # Use our log suppression context manager and yield the reporter
153
+ with suppress_opik_logs():
154
+ with convert_tqdm_to_rich(" Evaluation", verbose=verbose):
155
+ try:
156
+ yield Reporter()
157
+ finally:
158
+ pass
159
+
160
+ @contextmanager
161
+ def evaluate_initial_population(verbose: int = 1):
162
+ """Context manager to display messages during an evaluation phase."""
163
+ # Entry point
164
+ if verbose >= 1:
165
+ console.print(Text("> Let's now evaluate the initial population"))
166
+
167
+ # Create a simple object with a method to set the score
168
+ class Reporter:
169
+ def set_score(self, index, score, baseline_score):
170
+ if verbose >= 1:
171
+ if score >= baseline_score:
172
+ console.print(Text(f"\r Prompt {index+1} score was: {score}.", style="green"))
173
+ else:
174
+ console.print(Text(f"\r Prompt {index+1} score was: {score}.", style="dim"))
175
+
176
+ # Use our log suppression context manager and yield the reporter
177
+ with suppress_opik_logs():
178
+ with convert_tqdm_to_rich("│ Evaluation", verbose=verbose):
179
+ try:
180
+ yield Reporter()
181
+ finally:
182
+ if verbose >= 1:
183
+ console.print("")
184
+
185
+ @contextmanager
186
+ def start_evolutionary_algo(verbose: int = 1):
187
+ """Context manager to display messages during an evolutionary algorithm phase."""
188
+ # Entry point
189
+ if verbose >= 1:
190
+ console.print(Text("> Starting evolutionary algorithm optimization"))
191
+
192
+ # Create a simple object with a method to set the score
193
+ class Reporter:
194
+ def start_gen(self, gen, num_gens):
195
+ if verbose >= 1:
196
+ console.print(Text(f"│ Starting generation {gen} of {num_gens}"))
197
+
198
+ def restart_population(self, restart_generation_nb):
199
+ if verbose >= 1:
200
+ console.print(Text(f"│ Re-creating the population as we have not made progress in {restart_generation_nb} generations."))
201
+
202
+ def performing_crossover(self):
203
+ if verbose >= 1:
204
+ console.print(Text("│ Performing crossover - Combining multiple prompts into a new one."))
205
+
206
+ def performing_mutation(self):
207
+ if verbose >= 1:
208
+ console.print(Text("│ Performing mutation - Altering prompts to improve their performance."))
209
+
210
+ def performing_evaluation(self, num_prompts: int):
211
+ if verbose >= 1:
212
+ console.print(Text(f"│ Performing evaluation - Assessing {num_prompts} prompts' performance."))
213
+
214
+ def performed_evaluation(self, prompt_idx: int, score: float):
215
+ if verbose >= 1:
216
+ console.print(Text(f"│ Performed evaluation for prompt {prompt_idx} - Score: {score:.4f}.", style="dim"))
217
+
218
+ # Use our log suppression context manager and yield the reporter
219
+ with suppress_opik_logs():
220
+ with convert_tqdm_to_rich("│ Evaluation", verbose=verbose):
221
+ try:
222
+ yield Reporter()
223
+ finally:
224
+ if verbose >= 1:
225
+ console.print("")
226
+
227
+ def display_error(error_message, verbose: int = 1):
228
+ if verbose >= 1:
229
+ console.print(Text("│ ").append(Text(error_message, style="dim red")))
230
+
231
+ def display_success(message, verbose: int = 1):
232
+ if verbose >= 1:
233
+ console.print(Text("│ ").append(Text(message, style="dim green")))
234
+
235
+ def display_message(message, verbose: int = 1):
236
+ if verbose >= 1:
237
+ console.print(Text("│ ").append(Text(message, style="dim")))
238
+
239
+ def end_gen(generation_idx, best_gen_score, initial_primary_score, verbose: int = 1):
240
+ if verbose >= 1:
241
+ if best_gen_score >= initial_primary_score:
242
+ console.print(Text(f"│ Generation {generation_idx} completed. Found a new prompt with a score of {best_gen_score:.4f}.", style="green"))
243
+ else:
244
+ console.print(Text(f"│ Generation {generation_idx} completed. No improvement in this generation."))
245
+
246
+ console.print("│")