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 +1 -1
- weco/api.py +39 -56
- weco/cli.py +13 -26
- weco/panels.py +15 -10
- {weco-0.2.15.dist-info → weco-0.2.17.dist-info}/METADATA +16 -8
- weco-0.2.17.dist-info/RECORD +12 -0
- {weco-0.2.15.dist-info → weco-0.2.17.dist-info}/WHEEL +1 -1
- weco-0.2.15.dist-info/RECORD +0 -12
- {weco-0.2.15.dist-info → weco-0.2.17.dist-info}/entry_points.txt +0 -0
- {weco-0.2.15.dist-info → weco-0.2.17.dist-info}/licenses/LICENSE +0 -0
- {weco-0.2.15.dist-info → weco-0.2.17.dist-info}/top_level.txt +0 -0
weco/__init__.py
CHANGED
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
|
-
|
|
32
|
-
#
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
67
|
-
#
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
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
|
-
|
|
93
|
-
#
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
|
317
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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=
|
|
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
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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.
|
|
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
|
-
|
|
23
|
+
<div align="center">
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
# Weco: The AI Code Optimizer
|
|
26
|
+
|
|
27
|
+
[](https://www.python.org)
|
|
28
|
+
[](https://docs.weco.ai/)
|
|
26
29
|
[](https://badge.fury.io/py/weco)
|
|
27
30
|
[](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
|
|
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
|
-
|
|
46
|
+

|
|
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
|
+

|
|
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
|
|
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,,
|
weco-0.2.15.dist-info/RECORD
DELETED
|
@@ -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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|