weco 0.2.15__py3-none-any.whl → 0.2.17__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.15"
4
+ __pkg_version__ = "0.2.17"
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
@@ -194,11 +194,6 @@ def main() -> None:
194
194
  type=str,
195
195
  help="Description of additional instruction or path to a file containing additional instructions",
196
196
  )
197
- run_parser.add_argument(
198
- "--preserve-source",
199
- action="store_true",
200
- help="If set, do not overwrite the original source file; only save modified versions in the runs directory",
201
- )
202
197
 
203
198
  # --- Logout Command ---
204
199
  _ = subparsers.add_parser("logout", help="Log out from Weco and clear saved API key.")
@@ -256,10 +251,7 @@ def main() -> None:
256
251
  maximize = args.maximize == "true"
257
252
  steps = args.steps
258
253
  code_generator_config = {"model": args.model}
259
- evaluator_config = {
260
- "model": args.model,
261
- "include_analysis": False, # NOTE: False for now
262
- }
254
+ evaluator_config = {"model": args.model, "include_analysis": True}
263
255
  search_policy_config = {
264
256
  "num_drafts": max(1, math.ceil(0.15 * steps)),
265
257
  "debug_prob": 0.5,
@@ -313,9 +305,8 @@ def main() -> None:
313
305
  # Write the initial code string to the logs
314
306
  write_to_path(fp=runs_dir / f"step_0{source_fp.suffix}", content=session_response["code"])
315
307
 
316
- # Write the initial code string to the source file path (if not preserving)
317
- if not args.preserve_source:
318
- write_to_path(fp=source_fp, content=session_response["code"])
308
+ # Write the initial code string to the source file path
309
+ write_to_path(fp=source_fp, content=session_response["code"])
319
310
 
320
311
  # Update the panels with the initial solution
321
312
  summary_panel.set_session_id(session_id=session_id) # Add session id now that we have it
@@ -388,7 +379,6 @@ def main() -> None:
388
379
 
389
380
  # Send feedback and get next suggestion
390
381
  eval_and_next_solution_response = evaluate_feedback_then_suggest_next_solution(
391
- console=console,
392
382
  session_id=session_id,
393
383
  execution_output=term_out,
394
384
  additional_instructions=current_additional_instructions, # Pass current instructions
@@ -402,17 +392,12 @@ def main() -> None:
402
392
  )
403
393
 
404
394
  # Write the next solution to the source file
405
- if not args.preserve_source:
406
- write_to_path(fp=source_fp, content=eval_and_next_solution_response["code"])
395
+ write_to_path(fp=source_fp, content=eval_and_next_solution_response["code"])
407
396
 
408
397
  # Get the optimization session status for
409
398
  # the best solution, its score, and the history to plot the tree
410
399
  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,
400
+ session_id=session_id, include_history=True, timeout=timeout, auth_headers=auth_headers
416
401
  )
417
402
 
418
403
  # Update the step of the progress bar
@@ -493,7 +478,6 @@ def main() -> None:
493
478
 
494
479
  # Ensure we pass evaluation results for the last step's generated solution
495
480
  eval_and_next_solution_response = evaluate_feedback_then_suggest_next_solution(
496
- console=console,
497
481
  session_id=session_id,
498
482
  execution_output=term_out,
499
483
  additional_instructions=current_additional_instructions,
@@ -510,7 +494,7 @@ def main() -> None:
510
494
  # Get the optimization session status for
511
495
  # the best solution, its score, and the history to plot the tree
512
496
  status_response = get_optimization_session_status(
513
- console=console, session_id=session_id, include_history=True, timeout=timeout, auth_headers=auth_headers
497
+ session_id=session_id, include_history=True, timeout=timeout, auth_headers=auth_headers
514
498
  )
515
499
  # Build the metric tree
516
500
  tree_panel.build_metric_tree(nodes=status_response["history"])
@@ -569,13 +553,16 @@ def main() -> None:
569
553
  write_to_path(fp=runs_dir / f"best{source_fp.suffix}", content=best_solution_content)
570
554
 
571
555
  # write the best solution to the source file
572
- if not args.preserve_source:
573
- write_to_path(fp=source_fp, content=best_solution_content)
556
+ write_to_path(fp=source_fp, content=best_solution_content)
574
557
 
575
558
  console.print(end_optimization_layout)
576
559
 
577
560
  except Exception as e:
578
- console.print(Panel(f"[bold red]Error: {str(e)}", title="[bold red]Error", border_style="red"))
561
+ try:
562
+ error_message = e.response.json()["detail"]
563
+ except Exception:
564
+ error_message = str(e)
565
+ console.print(Panel(f"[bold red]Error: {error_message}", title="[bold red]Error", border_style="red"))
579
566
  # Print traceback for debugging
580
- console.print_exception(show_locals=True)
567
+ # console.print_exception(show_locals=False)
581
568
  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.15
3
+ Version: 0.2.17
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,21 +20,30 @@ 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
+ <div align="center">
24
24
 
25
- [![Python](https://img.shields.io/badge/Python-3.12.0-blue)](https://www.python.org)
25
+ # Weco: The AI Code Optimizer
26
+
27
+ [![Python](https://img.shields.io/badge/Python-3.8.0+-blue)](https://www.python.org)
28
+ [![docs](https://img.shields.io/website?url=https://docs.weco.ai/&label=docs)](https://docs.weco.ai/)
26
29
  [![PyPI version](https://badge.fury.io/py/weco.svg)](https://badge.fury.io/py/weco)
27
30
  [![AIDE](https://img.shields.io/badge/AI--Driven_Exploration-arXiv-orange?style=flat-square&logo=arxiv)](https://arxiv.org/abs/2502.13138)
28
31
 
32
+ <code>pip install weco</code>
33
+
34
+ </div>
35
+
36
+ ---
37
+
29
38
  Weco systematically optimizes your code, guided directly by your evaluation metrics.
30
39
 
31
40
  Example applications include:
32
41
 
33
- - **GPU Kernel Optimization**: Reimplement PyTorch functions using CUDA, Triton or Metal, optimizing for `latency`, `throughput`, or `memory_bandwidth`.
42
+ - **GPU Kernel Optimization**: Reimplement PyTorch functions using CUDA or Triton optimizing for `latency`, `throughput`, or `memory_bandwidth`.
34
43
  - **Model Development**: Tune feature transformations or architectures, optimizing for `validation_accuracy`, `AUC`, or `Sharpe Ratio`.
35
44
  - **Prompt Engineering**: Refine prompts for LLMs, optimizing for `win_rate`, `relevance`, or `format_adherence`
36
45
 
37
- https://github.com/user-attachments/assets/cb724ef1-bff6-4757-b457-d3b2201ede81
46
+ ![image](assets/example-optimization.gif)
38
47
 
39
48
  ---
40
49
 
@@ -42,7 +51,7 @@ https://github.com/user-attachments/assets/cb724ef1-bff6-4757-b457-d3b2201ede81
42
51
 
43
52
  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
53
 
45
- [image](https://github.com/user-attachments/assets/a6ed63fa-9c40-498e-aa98-a873e5786509)
54
+ ![image](https://github.com/user-attachments/assets/a6ed63fa-9c40-498e-aa98-a873e5786509)
46
55
 
47
56
  ---
48
57
 
@@ -101,7 +110,7 @@ This command starts the optimization process.
101
110
 
102
111
  This basic example shows how to optimize a simple PyTorch function for speedup.
103
112
 
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.
113
+ For more advanced examples, including [Triton](/examples/triton/README.md), [CUDA kernel optimization](/examples/cuda/README.md), [ML model optimization](/examples/spaceship-titanic/README.md), and [prompt engineering for math problems](https://github.com/WecoAI/weco-cli/tree/main/examples/prompt), please see the `README.md` files within the corresponding subdirectories under the [`examples/`](./examples/) folder.
105
114
 
106
115
  ```bash
107
116
  # Navigate to the example directory
@@ -136,7 +145,6 @@ weco run --source optimize.py \
136
145
  | `--model` | Model identifier for the LLM to use (e.g., `gpt-4o`, `claude-3.5-sonnet`). Recommended models to try include `o3-mini`, `claude-3-haiku`, and `gemini-2.5-pro-exp-03-25`. | Yes |
137
146
  | `--additional-instructions` | (Optional) Natural language description of specific instructions OR path to a file containing detailed instructions to guide the LLM. | No |
138
147
  | `--log-dir` | (Optional) Path to the directory to log intermediate steps and final optimization result. Defaults to `.runs/`. | No |
139
- | `--preserve-source` | (Optional) If set, do not overwrite the original `--source` file. Modifications and the best solution will still be saved in the `--log-dir`. | No |
140
148
 
141
149
  ---
142
150
 
@@ -0,0 +1,12 @@
1
+ weco/__init__.py,sha256=aMh5ZK_EMG8kGfy59ah_5gRVfWeEXgBhcfReKNsqNmQ,426
2
+ weco/api.py,sha256=0OU1hEhN7sbIZ1zj8TeeB0tMaxXk6n6qw82FmcdK0ec,3111
3
+ weco/auth.py,sha256=IPfiLthcNRkPyM8pWHTyDLvikw83sigacpY1PmeA03Y,2343
4
+ weco/cli.py,sha256=j8EyHVIIl2zNAjfVUoOFtJBZbDV69LrfnFA2WlDgbao,28488
5
+ weco/panels.py,sha256=8DoTQC-epGpGjn-xDBcqelC5BKaX7JXnrJ97LInEbRU,13561
6
+ weco/utils.py,sha256=hhIebUPnetFMfNSFfcsKVw1TSpeu_Zw3rBPPnxDie0U,3911
7
+ weco-0.2.17.dist-info/licenses/LICENSE,sha256=p_GQqJBvuZgkLNboYKyH-5dhpTDlKs2wq2TVM55WrWE,1065
8
+ weco-0.2.17.dist-info/METADATA,sha256=G2unWMKcPFan2r5a1kGlcizCQr1nVayJBVVLb-e-9fE,10795
9
+ weco-0.2.17.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
10
+ weco-0.2.17.dist-info/entry_points.txt,sha256=ixJ2uClALbCpBvnIR6BXMNck8SHAab8eVkM9pIUowcs,39
11
+ weco-0.2.17.dist-info/top_level.txt,sha256=F0N7v6e2zBSlsorFv-arAq2yDxQbzX3KVO8GxYhPUeE,5
12
+ weco-0.2.17.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.1)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,12 +0,0 @@
1
- weco/__init__.py,sha256=2P-Z80aRiNeL8hyXD4ExZxizUgLb_Tj_NOydwoqTZ_k,426
2
- weco/api.py,sha256=z2DCe0kQJaaBHo-Vml52GRc9nwQBnrKATXoY3UfPojw,3842
3
- weco/auth.py,sha256=IPfiLthcNRkPyM8pWHTyDLvikw83sigacpY1PmeA03Y,2343
4
- weco/cli.py,sha256=rcntl-hFQorCNSBX1yaNoL-4eBJFSkN5Vo35b6-W4UU,28993
5
- weco/panels.py,sha256=gB4rZbCvqzewUCBcILvyyU4fnOQLwFgHCGmtn-ZlgSo,13385
6
- weco/utils.py,sha256=hhIebUPnetFMfNSFfcsKVw1TSpeu_Zw3rBPPnxDie0U,3911
7
- weco-0.2.15.dist-info/licenses/LICENSE,sha256=p_GQqJBvuZgkLNboYKyH-5dhpTDlKs2wq2TVM55WrWE,1065
8
- weco-0.2.15.dist-info/METADATA,sha256=B97o-KOP1o2sUVHqSz1maZGy-iysBKBbvq16QIyVE68,10851
9
- weco-0.2.15.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
10
- weco-0.2.15.dist-info/entry_points.txt,sha256=ixJ2uClALbCpBvnIR6BXMNck8SHAab8eVkM9pIUowcs,39
11
- weco-0.2.15.dist-info/top_level.txt,sha256=F0N7v6e2zBSlsorFv-arAq2yDxQbzX3KVO8GxYhPUeE,5
12
- weco-0.2.15.dist-info/RECORD,,