weco 0.2.14__py3-none-any.whl → 0.2.16__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.
weco/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import os
2
2
 
3
3
  # DO NOT EDIT
4
- __pkg_version__ = "0.2.14"
4
+ __pkg_version__ = "0.2.16"
5
5
  __api_version__ = "v1"
6
6
 
7
7
  __base_url__ = f"https://api.weco.ai/{__api_version__}"
weco/api.py CHANGED
@@ -28,33 +28,28 @@ def start_optimization_session(
28
28
  ) -> Dict[str, Any]:
29
29
  """Start the optimization session."""
30
30
  with console.status("[bold green]Starting Optimization..."):
31
- try:
32
- # __base_url__ already contains /v1
33
- response = requests.post(
34
- f"{__base_url__}/sessions", # Path is relative to base_url
35
- json={
36
- "source_code": source_code,
37
- "additional_instructions": additional_instructions,
38
- "objective": {"evaluation_command": evaluation_command, "metric_name": metric_name, "maximize": maximize},
39
- "optimizer": {
40
- "steps": steps,
41
- "code_generator": code_generator_config,
42
- "evaluator": evaluator_config,
43
- "search_policy": search_policy_config,
44
- },
45
- "metadata": {"client_name": "cli", "client_version": __pkg_version__, **api_keys},
31
+ response = requests.post(
32
+ f"{__base_url__}/sessions", # Path is relative to base_url
33
+ json={
34
+ "source_code": source_code,
35
+ "additional_instructions": additional_instructions,
36
+ "objective": {"evaluation_command": evaluation_command, "metric_name": metric_name, "maximize": maximize},
37
+ "optimizer": {
38
+ "steps": steps,
39
+ "code_generator": code_generator_config,
40
+ "evaluator": evaluator_config,
41
+ "search_policy": search_policy_config,
46
42
  },
47
- headers=auth_headers, # Add headers
48
- timeout=timeout,
49
- )
50
- response.raise_for_status()
51
- return response.json()
52
- except requests.exceptions.HTTPError as e:
53
- handle_api_error(e=e, console=console)
43
+ "metadata": {"client_name": "cli", "client_version": __pkg_version__, **api_keys},
44
+ },
45
+ headers=auth_headers, # Add headers
46
+ timeout=timeout,
47
+ )
48
+ response.raise_for_status()
49
+ return response.json()
54
50
 
55
51
 
56
52
  def evaluate_feedback_then_suggest_next_solution(
57
- console: rich.console.Console,
58
53
  session_id: str,
59
54
  execution_output: str,
60
55
  additional_instructions: str = None,
@@ -63,41 +58,29 @@ def evaluate_feedback_then_suggest_next_solution(
63
58
  timeout: int = 800,
64
59
  ) -> Dict[str, Any]:
65
60
  """Evaluate the feedback and suggest the next solution."""
66
- try:
67
- # __base_url__ already contains /v1
68
- response = requests.post(
69
- f"{__base_url__}/sessions/{session_id}/suggest", # Path is relative to base_url
70
- json={
71
- "execution_output": execution_output,
72
- "additional_instructions": additional_instructions,
73
- "metadata": {**api_keys},
74
- },
75
- headers=auth_headers, # Add headers
76
- timeout=timeout,
77
- )
78
- response.raise_for_status()
79
- return response.json()
80
- except requests.exceptions.HTTPError as e:
81
- handle_api_error(e=e, console=console)
61
+ response = requests.post(
62
+ f"{__base_url__}/sessions/{session_id}/suggest", # Path is relative to base_url
63
+ json={
64
+ "execution_output": execution_output,
65
+ "additional_instructions": additional_instructions,
66
+ "metadata": {**api_keys},
67
+ },
68
+ headers=auth_headers, # Add headers
69
+ timeout=timeout,
70
+ )
71
+ response.raise_for_status()
72
+ return response.json()
82
73
 
83
74
 
84
75
  def get_optimization_session_status(
85
- console: rich.console.Console,
86
- session_id: str,
87
- include_history: bool = False,
88
- auth_headers: dict = {},
89
- timeout: int = 800, # Add auth_headers
76
+ session_id: str, include_history: bool = False, auth_headers: dict = {}, timeout: int = 800
90
77
  ) -> Dict[str, Any]:
91
78
  """Get the current status of the optimization session."""
92
- try:
93
- # __base_url__ already contains /v1
94
- response = requests.get(
95
- f"{__base_url__}/sessions/{session_id}", # Path is relative to base_url
96
- params={"include_history": include_history},
97
- headers=auth_headers, # Add headers
98
- timeout=timeout,
99
- )
100
- response.raise_for_status()
101
- return response.json()
102
- except requests.exceptions.HTTPError as e:
103
- handle_api_error(e=e, console=console)
79
+ response = requests.get(
80
+ f"{__base_url__}/sessions/{session_id}", # Path is relative to base_url
81
+ params={"include_history": include_history},
82
+ headers=auth_headers,
83
+ timeout=timeout,
84
+ )
85
+ response.raise_for_status()
86
+ return response.json()
weco/cli.py CHANGED
@@ -256,23 +256,20 @@ def main() -> None:
256
256
  maximize = args.maximize == "true"
257
257
  steps = args.steps
258
258
  code_generator_config = {"model": args.model}
259
- evaluator_config = {
260
- "model": args.model,
261
- "include_analysis": False, # NOTE: False for now
262
- }
259
+ evaluator_config = {"model": args.model, "include_analysis": True}
263
260
  search_policy_config = {
264
261
  "num_drafts": max(1, math.ceil(0.15 * steps)),
265
262
  "debug_prob": 0.5,
266
263
  "max_debug_depth": max(1, math.ceil(0.1 * steps)),
267
264
  }
265
+ # API request timeout
266
+ timeout = 800
268
267
  # Read additional instructions
269
268
  additional_instructions = read_additional_instructions(additional_instructions=args.additional_instructions)
270
269
  # Read source code path
271
270
  source_fp = pathlib.Path(args.source)
272
271
  # Read source code content
273
272
  source_code = read_from_path(fp=source_fp, is_json=False)
274
- # API request timeout
275
- timeout = 800
276
273
 
277
274
  # --- Panel Initialization ---
278
275
  summary_panel = SummaryPanel(
@@ -310,9 +307,8 @@ def main() -> None:
310
307
  runs_dir = pathlib.Path(args.log_dir) / session_id
311
308
  runs_dir.mkdir(parents=True, exist_ok=True)
312
309
 
313
- # Save the original code (.runs/<session-id>/original.<extension>)
314
- runs_copy_source_fp = runs_dir / f"original{source_fp.suffix}" # Use correct suffix
315
- write_to_path(fp=runs_copy_source_fp, content=source_code)
310
+ # Write the initial code string to the logs
311
+ write_to_path(fp=runs_dir / f"step_0{source_fp.suffix}", content=session_response["code"])
316
312
 
317
313
  # Write the initial code string to the source file path (if not preserving)
318
314
  if not args.preserve_source:
@@ -380,7 +376,8 @@ def main() -> None:
380
376
  transition_delay=0.1,
381
377
  )
382
378
 
383
- for step in range(1, steps):
379
+ # Starting from step 1 to steps (inclusive) because the baseline solution is step 0, so we want to optimize for steps worth of steps
380
+ for step in range(1, steps + 1):
384
381
  # Re-read instructions from the original source (file path or string) BEFORE each suggest call
385
382
  current_additional_instructions = read_additional_instructions(
386
383
  additional_instructions=args.additional_instructions
@@ -388,7 +385,6 @@ def main() -> None:
388
385
 
389
386
  # Send feedback and get next suggestion
390
387
  eval_and_next_solution_response = evaluate_feedback_then_suggest_next_solution(
391
- console=console,
392
388
  session_id=session_id,
393
389
  execution_output=term_out,
394
390
  additional_instructions=current_additional_instructions, # Pass current instructions
@@ -408,11 +404,7 @@ def main() -> None:
408
404
  # Get the optimization session status for
409
405
  # the best solution, its score, and the history to plot the tree
410
406
  status_response = get_optimization_session_status(
411
- console=console,
412
- session_id=session_id,
413
- include_history=True,
414
- timeout=timeout,
415
- auth_headers=auth_headers,
407
+ session_id=session_id, include_history=True, timeout=timeout, auth_headers=auth_headers
416
408
  )
417
409
 
418
410
  # Update the step of the progress bar
@@ -493,7 +485,6 @@ def main() -> None:
493
485
 
494
486
  # Ensure we pass evaluation results for the last step's generated solution
495
487
  eval_and_next_solution_response = evaluate_feedback_then_suggest_next_solution(
496
- console=console,
497
488
  session_id=session_id,
498
489
  execution_output=term_out,
499
490
  additional_instructions=current_additional_instructions,
@@ -510,7 +501,7 @@ def main() -> None:
510
501
  # Get the optimization session status for
511
502
  # the best solution, its score, and the history to plot the tree
512
503
  status_response = get_optimization_session_status(
513
- console=console, session_id=session_id, include_history=True, timeout=timeout, auth_headers=auth_headers
504
+ session_id=session_id, include_history=True, timeout=timeout, auth_headers=auth_headers
514
505
  )
515
506
  # Build the metric tree
516
507
  tree_panel.build_metric_tree(nodes=status_response["history"])
@@ -553,9 +544,7 @@ def main() -> None:
553
544
  best_solution_score = None
554
545
 
555
546
  if best_solution_code is None or best_solution_score is None:
556
- best_solution_content = (
557
- f"# Weco could not find a better solution\n\n{read_from_path(fp=runs_copy_source_fp, is_json=False)}"
558
- )
547
+ best_solution_content = f"# Weco could not find a better solution\n\n{read_from_path(fp=runs_dir / f'step_0{source_fp.suffix}', is_json=False)}"
559
548
  else:
560
549
  # Format score for the comment
561
550
  best_score_str = (
@@ -577,7 +566,11 @@ def main() -> None:
577
566
  console.print(end_optimization_layout)
578
567
 
579
568
  except Exception as e:
580
- console.print(Panel(f"[bold red]Error: {str(e)}", title="[bold red]Error", border_style="red"))
569
+ try:
570
+ error_message = e.response.json()["detail"]
571
+ except Exception:
572
+ error_message = str(e)
573
+ console.print(Panel(f"[bold red]Error: {error_message}", title="[bold red]Error", border_style="red"))
581
574
  # Print traceback for debugging
582
- console.print_exception(show_locals=True)
575
+ # console.print_exception(show_locals=False)
583
576
  sys.exit(1)
weco/panels.py CHANGED
@@ -121,6 +121,7 @@ class Node:
121
121
  self.metric = metric
122
122
  self.is_buggy = is_buggy
123
123
  self.evaluated = True
124
+ self.name = ""
124
125
 
125
126
 
126
127
  class MetricTree:
@@ -181,16 +182,17 @@ class MetricTreePanel:
181
182
  nodes.sort(key=lambda x: x["step"])
182
183
 
183
184
  # Finally build the new tree
184
- for node in nodes:
185
- self.metric_tree.add_node(
186
- Node(
187
- id=node["solution_id"],
188
- parent_id=node["parent_id"],
189
- code=node["code"],
190
- metric=node["metric_value"],
191
- is_buggy=node["is_buggy"],
192
- )
185
+ for i, node in enumerate(nodes):
186
+ node = Node(
187
+ id=node["solution_id"],
188
+ parent_id=node["parent_id"],
189
+ code=node["code"],
190
+ metric=node["metric_value"],
191
+ is_buggy=node["is_buggy"],
193
192
  )
193
+ if i == 0:
194
+ node.name = "baseline"
195
+ self.metric_tree.add_node(node)
194
196
 
195
197
  def set_unevaluated_node(self, node_id: str):
196
198
  """Set the unevaluated node."""
@@ -232,12 +234,15 @@ class MetricTreePanel:
232
234
  style = None
233
235
  text = f"{node.metric:.3f}"
234
236
 
237
+ # add the node name info
238
+ text = f"{node.name} {text}".strip()
239
+
235
240
  s = f"[{f'{style} ' if style is not None else ''}{color}]● {text}"
236
241
  subtree = tree.add(s)
237
242
  for child in node.children:
238
243
  append_rec(child, subtree)
239
244
 
240
- tree = Tree("🌳")
245
+ tree = Tree("", hide_root=True)
241
246
  for n in self.metric_tree.get_draft_nodes():
242
247
  append_rec(n, tree)
243
248
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: weco
3
- Version: 0.2.14
3
+ Version: 0.2.16
4
4
  Summary: Documentation for `weco`, a CLI for using Weco AI's code optimizer.
5
5
  Author-email: Weco AI Team <contact@weco.ai>
6
6
  License: MIT
@@ -20,7 +20,7 @@ Requires-Dist: build; extra == "dev"
20
20
  Requires-Dist: setuptools_scm; extra == "dev"
21
21
  Dynamic: license-file
22
22
 
23
- # Weco: The Evaluation-Driven AI Code Optimizer
23
+ # Weco: The AI Research Engineer
24
24
 
25
25
  [![Python](https://img.shields.io/badge/Python-3.12.0-blue)](https://www.python.org)
26
26
  [![PyPI version](https://badge.fury.io/py/weco.svg)](https://badge.fury.io/py/weco)
@@ -30,11 +30,11 @@ Weco systematically optimizes your code, guided directly by your evaluation metr
30
30
 
31
31
  Example applications include:
32
32
 
33
- - **GPU Kernel Optimization**: Reimplement PyTorch functions using CUDA, Triton or Metal, optimizing for `latency`, `throughput`, or `memory_bandwidth`.
33
+ - **GPU Kernel Optimization**: Reimplement PyTorch functions using CUDA or Triton optimizing for `latency`, `throughput`, or `memory_bandwidth`.
34
34
  - **Model Development**: Tune feature transformations or architectures, optimizing for `validation_accuracy`, `AUC`, or `Sharpe Ratio`.
35
35
  - **Prompt Engineering**: Refine prompts for LLMs, optimizing for `win_rate`, `relevance`, or `format_adherence`
36
36
 
37
- https://github.com/user-attachments/assets/cb724ef1-bff6-4757-b457-d3b2201ede81
37
+ ![image](assets/example-optimization.gif)
38
38
 
39
39
  ---
40
40
 
@@ -42,7 +42,7 @@ https://github.com/user-attachments/assets/cb724ef1-bff6-4757-b457-d3b2201ede81
42
42
 
43
43
  The `weco` CLI leverages a tree search approach guided by Large Language Models (LLMs) to iteratively explore and refine your code. It automatically applies changes, runs your evaluation script, parses the results, and proposes further improvements based on the specified goal.
44
44
 
45
- [image](https://github.com/user-attachments/assets/a6ed63fa-9c40-498e-aa98-a873e5786509)
45
+ ![image](https://github.com/user-attachments/assets/a6ed63fa-9c40-498e-aa98-a873e5786509)
46
46
 
47
47
  ---
48
48
 
@@ -101,7 +101,7 @@ This command starts the optimization process.
101
101
 
102
102
  This basic example shows how to optimize a simple PyTorch function for speedup.
103
103
 
104
- For more advanced examples, including **[Metal/MLX](/examples/metal/README.md), [Triton](/examples/triton/README.md), [CUDA kernel optimization](/examples/cuda/README.md)**, and **[ML model optimization](/examples/spaceship-titanic/README.md)**, please see the `README.md` files within the corresponding subdirectories under the [`examples/`](./examples/) folder.
104
+ For more advanced examples, including [Triton](/examples/triton/README.md), [CUDA kernel optimization](/examples/cuda/README.md)**, and **[ML model optimization](/examples/spaceship-titanic/README.md)**, please see the `README.md` files within the corresponding subdirectories under the [`examples/`](./examples/) folder.
105
105
 
106
106
  ```bash
107
107
  # Navigate to the example directory
@@ -0,0 +1,12 @@
1
+ weco/__init__.py,sha256=HyOG-766A8if3MM5YvAM6CMJobEib3oM54UAJMk9GFA,426
2
+ weco/api.py,sha256=0OU1hEhN7sbIZ1zj8TeeB0tMaxXk6n6qw82FmcdK0ec,3111
3
+ weco/auth.py,sha256=IPfiLthcNRkPyM8pWHTyDLvikw83sigacpY1PmeA03Y,2343
4
+ weco/cli.py,sha256=DPObmIes3tRAVswBGYOx5G_8zIjeIJFufOGnFt__XwE,28869
5
+ weco/panels.py,sha256=8DoTQC-epGpGjn-xDBcqelC5BKaX7JXnrJ97LInEbRU,13561
6
+ weco/utils.py,sha256=hhIebUPnetFMfNSFfcsKVw1TSpeu_Zw3rBPPnxDie0U,3911
7
+ weco-0.2.16.dist-info/licenses/LICENSE,sha256=p_GQqJBvuZgkLNboYKyH-5dhpTDlKs2wq2TVM55WrWE,1065
8
+ weco-0.2.16.dist-info/METADATA,sha256=CFe6w8pRnMh-zDuyebtqIOFfIuf6JEJFqgVdUPSTO6s,10749
9
+ weco-0.2.16.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
10
+ weco-0.2.16.dist-info/entry_points.txt,sha256=ixJ2uClALbCpBvnIR6BXMNck8SHAab8eVkM9pIUowcs,39
11
+ weco-0.2.16.dist-info/top_level.txt,sha256=F0N7v6e2zBSlsorFv-arAq2yDxQbzX3KVO8GxYhPUeE,5
12
+ weco-0.2.16.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.0)
2
+ Generator: setuptools (80.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,12 +0,0 @@
1
- weco/__init__.py,sha256=q4zeQ8CJq8NJyRcBMmST6zCzmK_HjNSFChrNBzJ9oks,426
2
- weco/api.py,sha256=z2DCe0kQJaaBHo-Vml52GRc9nwQBnrKATXoY3UfPojw,3842
3
- weco/auth.py,sha256=IPfiLthcNRkPyM8pWHTyDLvikw83sigacpY1PmeA03Y,2343
4
- weco/cli.py,sha256=7pGJiyoBO7n6Xocwusx9iVqsaPj8OuPaJ1A2ks83Ekw,28961
5
- weco/panels.py,sha256=gB4rZbCvqzewUCBcILvyyU4fnOQLwFgHCGmtn-ZlgSo,13385
6
- weco/utils.py,sha256=hhIebUPnetFMfNSFfcsKVw1TSpeu_Zw3rBPPnxDie0U,3911
7
- weco-0.2.14.dist-info/licenses/LICENSE,sha256=p_GQqJBvuZgkLNboYKyH-5dhpTDlKs2wq2TVM55WrWE,1065
8
- weco-0.2.14.dist-info/METADATA,sha256=855avaVBC-wUyFDWIvITw0t4o_v4s90Us-t_3lQnPGw,10851
9
- weco-0.2.14.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
10
- weco-0.2.14.dist-info/entry_points.txt,sha256=ixJ2uClALbCpBvnIR6BXMNck8SHAab8eVkM9pIUowcs,39
11
- weco-0.2.14.dist-info/top_level.txt,sha256=F0N7v6e2zBSlsorFv-arAq2yDxQbzX3KVO8GxYhPUeE,5
12
- weco-0.2.14.dist-info/RECORD,,