llm-optimizer 0.1.0__tar.gz
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.
- llm_optimizer-0.1.0/PKG-INFO +44 -0
- llm_optimizer-0.1.0/README.md +11 -0
- llm_optimizer-0.1.0/licence +21 -0
- llm_optimizer-0.1.0/llm_optimizer/__init__.py +0 -0
- llm_optimizer-0.1.0/llm_optimizer/main.py +212 -0
- llm_optimizer-0.1.0/llm_optimizer.egg-info/PKG-INFO +44 -0
- llm_optimizer-0.1.0/llm_optimizer.egg-info/SOURCES.txt +12 -0
- llm_optimizer-0.1.0/llm_optimizer.egg-info/dependency_links.txt +1 -0
- llm_optimizer-0.1.0/llm_optimizer.egg-info/entry_points.txt +2 -0
- llm_optimizer-0.1.0/llm_optimizer.egg-info/requires.txt +8 -0
- llm_optimizer-0.1.0/llm_optimizer.egg-info/top_level.txt +1 -0
- llm_optimizer-0.1.0/pyproject.toml +3 -0
- llm_optimizer-0.1.0/setup.cfg +4 -0
- llm_optimizer-0.1.0/setup.py +34 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: llm_optimizer
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Optimize LLM outputs and track emissions
|
|
5
|
+
Home-page: https://github.com/viji123450/llm_optimizer
|
|
6
|
+
Author: Vijayalakshmi
|
|
7
|
+
Author-email: viji814881@email.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: licence
|
|
14
|
+
Requires-Dist: torch
|
|
15
|
+
Requires-Dist: transformers
|
|
16
|
+
Requires-Dist: codecarbon
|
|
17
|
+
Requires-Dist: evaluate
|
|
18
|
+
Requires-Dist: numpy
|
|
19
|
+
Requires-Dist: rouge_score
|
|
20
|
+
Requires-Dist: nltk
|
|
21
|
+
Requires-Dist: absl-py
|
|
22
|
+
Dynamic: author
|
|
23
|
+
Dynamic: author-email
|
|
24
|
+
Dynamic: classifier
|
|
25
|
+
Dynamic: description
|
|
26
|
+
Dynamic: description-content-type
|
|
27
|
+
Dynamic: home-page
|
|
28
|
+
Dynamic: license
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
Dynamic: requires-dist
|
|
31
|
+
Dynamic: requires-python
|
|
32
|
+
Dynamic: summary
|
|
33
|
+
|
|
34
|
+
# LLM Optimizer
|
|
35
|
+
|
|
36
|
+
*Optimize and track emissions while running Large Language Models*
|
|
37
|
+
|
|
38
|
+
## 🚀 Features
|
|
39
|
+
|
|
40
|
+
- Load and run text generation with Hugging Face Transformers.
|
|
41
|
+
- Track energy consumption and carbon emissions using CodeCarbon.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
## 📦 Installation
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# LLM Optimizer
|
|
2
|
+
|
|
3
|
+
*Optimize and track emissions while running Large Language Models*
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
- Load and run text generation with Hugging Face Transformers.
|
|
8
|
+
- Track energy consumption and carbon emissions using CodeCarbon.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## 📦 Installation
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Vijayalakshmi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
File without changes
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
|
3
|
+
from codecarbon import EmissionsTracker
|
|
4
|
+
import time
|
|
5
|
+
import numpy as np
|
|
6
|
+
import evaluate
|
|
7
|
+
import gc
|
|
8
|
+
import os
|
|
9
|
+
|
|
10
|
+
def load_and_generate():
|
|
11
|
+
|
|
12
|
+
# Load model and tokenizer
|
|
13
|
+
model_name = "EleutherAI/gpt-neo-1.3B"
|
|
14
|
+
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
|
15
|
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
16
|
+
model = AutoModelForCausalLM.from_pretrained(model_name).to(device).eval()
|
|
17
|
+
|
|
18
|
+
# Metrics setup
|
|
19
|
+
perplexity_metric = evaluate.load("perplexity", module_type="metric")
|
|
20
|
+
bleu_metric = evaluate.load("bleu")
|
|
21
|
+
rouge_metric = evaluate.load("rouge")
|
|
22
|
+
|
|
23
|
+
# Self-freezing support
|
|
24
|
+
frozen_layers = {}
|
|
25
|
+
frozen_layer_names = []
|
|
26
|
+
|
|
27
|
+
def freeze_hook(module, input, output, layer_name):
|
|
28
|
+
frozen_output = torch.where(torch.abs(output) < 1e-4, torch.zeros_like(output), output)
|
|
29
|
+
frozen_layers[layer_name] = frozen_output.detach()
|
|
30
|
+
return frozen_output
|
|
31
|
+
|
|
32
|
+
def apply_freeze_hooks(model):
|
|
33
|
+
for name, module in model.named_modules():
|
|
34
|
+
if 'mlp' in name and hasattr(module, 'forward'):
|
|
35
|
+
module.register_forward_hook(lambda mod, inp, out, n=name: freeze_hook(mod, inp, out, n))
|
|
36
|
+
frozen_layer_names.append(name)
|
|
37
|
+
print(f"Total layers registered for self-freezing: {len(frozen_layer_names)}")
|
|
38
|
+
|
|
39
|
+
def self_prune(model, threshold=1e-3):
|
|
40
|
+
with torch.no_grad():
|
|
41
|
+
for name, param in model.named_parameters():
|
|
42
|
+
if 'weight' in name and len(param.shape) > 1:
|
|
43
|
+
mask = param.abs() > threshold
|
|
44
|
+
param.mul_(mask.float())
|
|
45
|
+
|
|
46
|
+
def free_gpu_memory():
|
|
47
|
+
torch.cuda.empty_cache()
|
|
48
|
+
gc.collect()
|
|
49
|
+
if torch.cuda.is_available():
|
|
50
|
+
torch.cuda.ipc_collect()
|
|
51
|
+
torch.cuda.empty_cache()
|
|
52
|
+
|
|
53
|
+
free_gpu_memory()
|
|
54
|
+
|
|
55
|
+
prompt_cache = {}
|
|
56
|
+
def cached_infer(prompt):
|
|
57
|
+
if prompt in prompt_cache:
|
|
58
|
+
return prompt_cache[prompt]
|
|
59
|
+
inputs = tokenizer(prompt, return_tensors="pt").to(device)
|
|
60
|
+
with torch.no_grad():
|
|
61
|
+
outputs = model.generate(**inputs, max_length=50)
|
|
62
|
+
result = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
|
63
|
+
prompt_cache[prompt] = result
|
|
64
|
+
return result
|
|
65
|
+
|
|
66
|
+
def evaluate_model(prompt, reference):
|
|
67
|
+
generated = cached_infer(prompt)
|
|
68
|
+
ppl = perplexity_metric.compute(predictions=[generated], model_id=model_name)["perplexities"][0]
|
|
69
|
+
bleu = bleu_metric.compute(predictions=[generated], references=[reference])["bleu"]
|
|
70
|
+
rouge = rouge_metric.compute(predictions=[generated], references=[reference])["rougeL"]
|
|
71
|
+
return ppl, bleu, rouge, generated
|
|
72
|
+
|
|
73
|
+
# Sample prompts
|
|
74
|
+
prompts = [
|
|
75
|
+
"The theory of relativity was developed by",
|
|
76
|
+
"Climate change is primarily caused by",
|
|
77
|
+
"Photosynthesis in plants requires",
|
|
78
|
+
"Artificial intelligence can be used in"
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
references = [
|
|
82
|
+
"The theory of relativity was developed by Albert Einstein in the early 20th century.",
|
|
83
|
+
"Climate change is primarily caused by the emission of greenhouse gases from human activities.",
|
|
84
|
+
"Photosynthesis in plants requires sunlight, carbon dioxide, and water.",
|
|
85
|
+
"Artificial intelligence can be used in healthcare, education, and autonomous vehicles."
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
prompt = prompts[0]
|
|
89
|
+
reference = references[0]
|
|
90
|
+
|
|
91
|
+
# === BASELINE ===
|
|
92
|
+
tracker_baseline = EmissionsTracker(project_name="gptneo-baseline")
|
|
93
|
+
tracker_baseline.start()
|
|
94
|
+
start_base = time.time()
|
|
95
|
+
output_baseline = evaluate_model(prompt, reference)
|
|
96
|
+
end_base = time.time()
|
|
97
|
+
baseline_emissions = tracker_baseline.stop()
|
|
98
|
+
baseline_time = end_base - start_base
|
|
99
|
+
|
|
100
|
+
# === PRUNING ===
|
|
101
|
+
self_prune(model, threshold=1e-3)
|
|
102
|
+
tracker_prune = EmissionsTracker(project_name="gptneo-pruning")
|
|
103
|
+
tracker_prune.start()
|
|
104
|
+
start_prune = time.time()
|
|
105
|
+
output_pruned = evaluate_model(prompt, reference)
|
|
106
|
+
end_prune = time.time()
|
|
107
|
+
prune_emissions = tracker_prune.stop()
|
|
108
|
+
prune_time = end_prune - start_prune
|
|
109
|
+
|
|
110
|
+
# === FREEZING ===
|
|
111
|
+
hook_start = time.time()
|
|
112
|
+
apply_freeze_hooks(model)
|
|
113
|
+
hook_end = time.time()
|
|
114
|
+
hook_setup_time = hook_end - hook_start
|
|
115
|
+
|
|
116
|
+
tracker_freeze = EmissionsTracker(project_name="gptneo-freezing")
|
|
117
|
+
tracker_freeze.start()
|
|
118
|
+
start_freeze = time.time()
|
|
119
|
+
output_freeze = evaluate_model(prompt, reference)
|
|
120
|
+
end_freeze = time.time()
|
|
121
|
+
freeze_emissions = tracker_freeze.stop()
|
|
122
|
+
freeze_time = end_freeze - start_freeze
|
|
123
|
+
|
|
124
|
+
# === OPTIMIZED ===
|
|
125
|
+
tracker_optimized = EmissionsTracker(project_name="gptneo-optimized")
|
|
126
|
+
tracker_optimized.start()
|
|
127
|
+
start_opt = time.time()
|
|
128
|
+
output_optimized = evaluate_model(prompt, reference)
|
|
129
|
+
end_opt = time.time()
|
|
130
|
+
optimized_emissions = tracker_optimized.stop()
|
|
131
|
+
optimized_time = end_opt - start_opt
|
|
132
|
+
|
|
133
|
+
# === CACHING ===
|
|
134
|
+
tracker_cache = EmissionsTracker(project_name="gptneo-caching")
|
|
135
|
+
tracker_cache.start()
|
|
136
|
+
start_cache = time.time()
|
|
137
|
+
output_cache = evaluate_model(prompt, reference)
|
|
138
|
+
end_cache = time.time()
|
|
139
|
+
cache_emissions = tracker_cache.stop()
|
|
140
|
+
cache_time = end_cache - start_cache
|
|
141
|
+
|
|
142
|
+
# === PRINT RESULTS ===
|
|
143
|
+
print("=== BASELINE ===")
|
|
144
|
+
print("Generated Text:", output_baseline[-1])
|
|
145
|
+
print(f"Perplexity: {output_baseline[0]:.2f}, BLEU: {output_baseline[1]:.2f}, ROUGE-L: {output_baseline[2]:.2f}")
|
|
146
|
+
print(f"Inference Time: {baseline_time:.2f}s, CO2 Emissions: {baseline_emissions:.6f} kg")
|
|
147
|
+
|
|
148
|
+
print("\n=== AFTER PRUNING + FREEZING ===")
|
|
149
|
+
print("Generated Text:", output_optimized[-1])
|
|
150
|
+
print(f"Perplexity: {output_optimized[0]:.2f}, BLEU: {output_optimized[1]:.2f}, ROUGE-L: {output_optimized[2]:.2f}")
|
|
151
|
+
print(f"Inference Time: {optimized_time:.2f}s, CO2 Emissions: {optimized_emissions:.6f} kg")
|
|
152
|
+
|
|
153
|
+
delta_emission = baseline_emissions - optimized_emissions
|
|
154
|
+
print("\n=== SUMMARY ===")
|
|
155
|
+
print(f"CO2 Reduction: {delta_emission:.6f} kg")
|
|
156
|
+
|
|
157
|
+
# === ABLATION STUDY ===
|
|
158
|
+
print("\n=== ABLATION: AFTER PRUNING ONLY ===")
|
|
159
|
+
print("Generated Text:", output_pruned[-1])
|
|
160
|
+
print(f"Perplexity: {output_pruned[0]:.2f}, BLEU: {output_pruned[1]:.2f}, ROUGE-L: {output_pruned[2]:.2f}")
|
|
161
|
+
print(f"Inference Time: {prune_time:.2f}s, CO2 Emissions: {prune_emissions:.6f} kg")
|
|
162
|
+
print(f"CO2 Reduction from Baseline: {baseline_emissions - prune_emissions:.6f} kg")
|
|
163
|
+
|
|
164
|
+
print("\n=== ABLATION: AFTER FREEZING ONLY ===")
|
|
165
|
+
print("Generated Text:", output_freeze[-1])
|
|
166
|
+
print(f"Perplexity: {output_freeze[0]:.2f}, BLEU: {output_freeze[1]:.2f}, ROUGE-L: {output_freeze[2]:.2f}")
|
|
167
|
+
print(f"Inference Time: {freeze_time:.2f}s, CO2 Emissions: {freeze_emissions:.6f} kg")
|
|
168
|
+
print(f"CO2 Reduction from Pruning: {prune_emissions - freeze_emissions:.6f} kg")
|
|
169
|
+
|
|
170
|
+
# === INDIVIDUAL EFFECTS ===
|
|
171
|
+
print("\n=== INDIVIDUAL EFFECTS ===")
|
|
172
|
+
print(f"[PRUNING] Inference Time: {prune_time:.2f}s, CO2: {prune_emissions:.6f} kg")
|
|
173
|
+
print(f"[FREEZING] Hook Setup Time: {hook_setup_time:.4f}s")
|
|
174
|
+
print(f"[FREEZING] Inference Time: {freeze_time:.2f}s, CO2: {freeze_emissions:.6f} kg")
|
|
175
|
+
print(f"[CACHING] Cached Inference Time: {cache_time:.4f}s, CO2: {cache_emissions:.6f} kg")
|
|
176
|
+
|
|
177
|
+
# === RUNTIME BREAKDOWN ===
|
|
178
|
+
hook_setup_ms = hook_setup_time * 1000
|
|
179
|
+
prune_saving_ms = (baseline_time - prune_time) * 1000
|
|
180
|
+
freeze_saving_ms = (baseline_time - freeze_time) * 1000
|
|
181
|
+
cache_saving_ms = (baseline_time - cache_time) * 1000
|
|
182
|
+
|
|
183
|
+
prune_speedup_pct = 100 * (baseline_time - prune_time) / baseline_time
|
|
184
|
+
freeze_speedup_pct = 100 * (baseline_time - freeze_time) / baseline_time
|
|
185
|
+
cache_speedup_pct = 100 * (baseline_time - cache_time) / baseline_time
|
|
186
|
+
|
|
187
|
+
print("\n=== RUNTIME BREAKDOWN (in ms) ===")
|
|
188
|
+
print(f"Hook Setup Overhead: {hook_setup_ms:.2f} ms (One-time cost)")
|
|
189
|
+
print(f"Inference Time Saved by Pruning: {prune_saving_ms:.2f} ms ({prune_speedup_pct:.2f}%)")
|
|
190
|
+
print(f"Inference Time Saved by Freezing: {freeze_saving_ms:.2f} ms ({freeze_speedup_pct:.2f}%)")
|
|
191
|
+
print(f"Inference Time Saved by Caching: {cache_saving_ms:.2f} ms ({cache_speedup_pct:.2f}%)")
|
|
192
|
+
|
|
193
|
+
print(f"[FREEZING ONLY] Net Inference Gain (Baseline - Freezing): {baseline_time - freeze_time:.4f}s")
|
|
194
|
+
print(f"[FREEZING ONLY] Hook Setup Time: {hook_setup_time:.4f}s")
|
|
195
|
+
|
|
196
|
+
print("\n=== QUALITATIVE COMPARISON ===")
|
|
197
|
+
print("Prompt 1:", prompts[0])
|
|
198
|
+
print("[Baseline Output]:", output_baseline[-1])
|
|
199
|
+
print("[Optimized Output]:", output_optimized[-1])
|
|
200
|
+
|
|
201
|
+
print("\n=== FULL QUALITATIVE COMPARISON (All 4 Prompts) ===")
|
|
202
|
+
for i in range(4):
|
|
203
|
+
prompt = prompts[i]
|
|
204
|
+
reference = references[i]
|
|
205
|
+
_, _, _, baseline_output = evaluate_model(prompt, reference)
|
|
206
|
+
_, _, _, optimized_output = evaluate_model(prompt, reference)
|
|
207
|
+
print(f"\nPrompt {i+1}: {prompt}")
|
|
208
|
+
print("[Baseline Output]:", baseline_output)
|
|
209
|
+
print("[Optimized Output]:", optimized_output)
|
|
210
|
+
|
|
211
|
+
if __name__ == "__main__":
|
|
212
|
+
load_and_generate()
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: llm_optimizer
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Optimize LLM outputs and track emissions
|
|
5
|
+
Home-page: https://github.com/viji123450/llm_optimizer
|
|
6
|
+
Author: Vijayalakshmi
|
|
7
|
+
Author-email: viji814881@email.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: licence
|
|
14
|
+
Requires-Dist: torch
|
|
15
|
+
Requires-Dist: transformers
|
|
16
|
+
Requires-Dist: codecarbon
|
|
17
|
+
Requires-Dist: evaluate
|
|
18
|
+
Requires-Dist: numpy
|
|
19
|
+
Requires-Dist: rouge_score
|
|
20
|
+
Requires-Dist: nltk
|
|
21
|
+
Requires-Dist: absl-py
|
|
22
|
+
Dynamic: author
|
|
23
|
+
Dynamic: author-email
|
|
24
|
+
Dynamic: classifier
|
|
25
|
+
Dynamic: description
|
|
26
|
+
Dynamic: description-content-type
|
|
27
|
+
Dynamic: home-page
|
|
28
|
+
Dynamic: license
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
Dynamic: requires-dist
|
|
31
|
+
Dynamic: requires-python
|
|
32
|
+
Dynamic: summary
|
|
33
|
+
|
|
34
|
+
# LLM Optimizer
|
|
35
|
+
|
|
36
|
+
*Optimize and track emissions while running Large Language Models*
|
|
37
|
+
|
|
38
|
+
## 🚀 Features
|
|
39
|
+
|
|
40
|
+
- Load and run text generation with Hugging Face Transformers.
|
|
41
|
+
- Track energy consumption and carbon emissions using CodeCarbon.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
## 📦 Installation
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
licence
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.py
|
|
5
|
+
llm_optimizer/__init__.py
|
|
6
|
+
llm_optimizer/main.py
|
|
7
|
+
llm_optimizer.egg-info/PKG-INFO
|
|
8
|
+
llm_optimizer.egg-info/SOURCES.txt
|
|
9
|
+
llm_optimizer.egg-info/dependency_links.txt
|
|
10
|
+
llm_optimizer.egg-info/entry_points.txt
|
|
11
|
+
llm_optimizer.egg-info/requires.txt
|
|
12
|
+
llm_optimizer.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
llm_optimizer
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name='llm_optimizer',
|
|
5
|
+
version='0.1.0',
|
|
6
|
+
description='Optimize LLM outputs and track emissions',
|
|
7
|
+
long_description=open("README.md").read(),
|
|
8
|
+
long_description_content_type="text/markdown",
|
|
9
|
+
author='Vijayalakshmi',
|
|
10
|
+
author_email='viji814881@email.com',
|
|
11
|
+
url='https://github.com/viji123450/llm_optimizer', # <-- OPTIONAL: link to your repo
|
|
12
|
+
license='MIT', # <-- or any license you prefer
|
|
13
|
+
packages=find_packages(),
|
|
14
|
+
install_requires=[
|
|
15
|
+
'torch',
|
|
16
|
+
'transformers',
|
|
17
|
+
'codecarbon',
|
|
18
|
+
'evaluate',
|
|
19
|
+
'numpy',
|
|
20
|
+
'rouge_score',
|
|
21
|
+
'nltk',
|
|
22
|
+
'absl-py'
|
|
23
|
+
],
|
|
24
|
+
entry_points={
|
|
25
|
+
'console_scripts': [
|
|
26
|
+
'llm-optimize=llm_optimizer.main:load_and_generate',
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
classifiers=[
|
|
30
|
+
'Programming Language :: Python :: 3',
|
|
31
|
+
'Operating System :: OS Independent',
|
|
32
|
+
],
|
|
33
|
+
python_requires='>=3.8',
|
|
34
|
+
)
|