py-adtools 0.1.4__tar.gz → 0.1.8__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.
Potentially problematic release.
This version of py-adtools might be problematic. Click here for more details.
- {py_adtools-0.1.4 → py_adtools-0.1.8}/PKG-INFO +2 -1
- {py_adtools-0.1.4 → py_adtools-0.1.8}/adtools/evaluator.py +36 -11
- {py_adtools-0.1.4 → py_adtools-0.1.8}/adtools/evaluator_pool.py +9 -7
- py_adtools-0.1.8/adtools/lm/__init__.py +6 -0
- py_adtools-0.1.8/adtools/lm/lm_base.py +39 -0
- py_adtools-0.1.8/adtools/lm/openai_api.py +72 -0
- py_adtools-0.1.4/adtools/lm_base.py → py_adtools-0.1.8/adtools/lm/vllm_server.py +45 -117
- {py_adtools-0.1.4 → py_adtools-0.1.8}/py_adtools.egg-info/PKG-INFO +2 -1
- {py_adtools-0.1.4 → py_adtools-0.1.8}/py_adtools.egg-info/SOURCES.txt +4 -1
- {py_adtools-0.1.4 → py_adtools-0.1.8}/py_adtools.egg-info/requires.txt +1 -0
- {py_adtools-0.1.4 → py_adtools-0.1.8}/setup.py +3 -3
- {py_adtools-0.1.4 → py_adtools-0.1.8}/LICENSE +0 -0
- {py_adtools-0.1.4 → py_adtools-0.1.8}/README.md +0 -0
- {py_adtools-0.1.4 → py_adtools-0.1.8}/adtools/__init__.py +0 -0
- {py_adtools-0.1.4 → py_adtools-0.1.8}/adtools/py_code.py +0 -0
- {py_adtools-0.1.4 → py_adtools-0.1.8}/py_adtools.egg-info/dependency_links.txt +0 -0
- {py_adtools-0.1.4 → py_adtools-0.1.8}/py_adtools.egg-info/top_level.txt +0 -0
- {py_adtools-0.1.4 → py_adtools-0.1.8}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: py-adtools
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
4
4
|
Summary: Useful tools for parsing and evaluating Python programs for LLM-based algorithm design.
|
|
5
5
|
Home-page: https://github.com/RayZhhh/py-adtools
|
|
6
6
|
Author: Rui Zhang
|
|
@@ -13,6 +13,7 @@ Requires-Python: >=3.10
|
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
15
|
Requires-Dist: psutil
|
|
16
|
+
Requires-Dist: openai
|
|
16
17
|
Dynamic: author
|
|
17
18
|
Dynamic: author-email
|
|
18
19
|
Dynamic: classifier
|
|
@@ -8,10 +8,12 @@ Commercial use of this software or its derivatives requires prior written permis
|
|
|
8
8
|
import multiprocessing
|
|
9
9
|
import os
|
|
10
10
|
import sys
|
|
11
|
+
import time
|
|
11
12
|
from abc import ABC, abstractmethod
|
|
12
13
|
from queue import Empty
|
|
13
|
-
from typing import Any, Literal, Dict, Callable, List
|
|
14
|
+
from typing import Any, Literal, Dict, Callable, List, Tuple
|
|
14
15
|
import psutil
|
|
16
|
+
import traceback
|
|
15
17
|
|
|
16
18
|
from .py_code import PyProgram
|
|
17
19
|
|
|
@@ -21,6 +23,7 @@ class PyEvaluator(ABC):
|
|
|
21
23
|
def __init__(
|
|
22
24
|
self,
|
|
23
25
|
exec_code: bool = True,
|
|
26
|
+
find_and_kill_children_evaluation_process: bool = False,
|
|
24
27
|
debug_mode: bool = False,
|
|
25
28
|
*,
|
|
26
29
|
join_timeout_seconds: int = 10
|
|
@@ -32,11 +35,15 @@ class PyEvaluator(ABC):
|
|
|
32
35
|
which will be passed to 'self.evaluate_program()'. Set this parameter to 'False' if you are going to
|
|
33
36
|
evaluate a Python scripy. Note that if the parameter is set to 'False', the arguments 'callable_...'
|
|
34
37
|
in 'self.evaluate_program()' will no longer be affective.
|
|
38
|
+
find_and_kill_children_evaluation_process: If using 'self.secure_evaluate', kill children processes
|
|
39
|
+
when they are terminated. Note that it is suggested to set to 'False' if the evaluation process
|
|
40
|
+
does not start new processes.
|
|
35
41
|
debug_mode: Debug mode.
|
|
36
42
|
join_timeout_seconds: Timeout in seconds to wait for the process to finish. Kill the process if timeout.
|
|
37
43
|
"""
|
|
38
44
|
self.debug_mode = debug_mode
|
|
39
45
|
self.exec_code = exec_code
|
|
46
|
+
self.find_and_kill_children_evaluation_process = find_and_kill_children_evaluation_process
|
|
40
47
|
self.join_timeout_seconds = join_timeout_seconds
|
|
41
48
|
|
|
42
49
|
@abstractmethod
|
|
@@ -65,11 +72,14 @@ class PyEvaluator(ABC):
|
|
|
65
72
|
)
|
|
66
73
|
|
|
67
74
|
def _kill_process_and_its_children(self, process: multiprocessing.Process):
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
if self.find_and_kill_children_evaluation_process:
|
|
76
|
+
# Find all children processes
|
|
77
|
+
try:
|
|
78
|
+
parent = psutil.Process(process.pid)
|
|
79
|
+
children_processes = parent.children(recursive=True)
|
|
80
|
+
except psutil.NoSuchProcess:
|
|
81
|
+
children_processes = []
|
|
82
|
+
else:
|
|
73
83
|
children_processes = []
|
|
74
84
|
# Terminate parent process
|
|
75
85
|
process.terminate()
|
|
@@ -124,7 +134,7 @@ class PyEvaluator(ABC):
|
|
|
124
134
|
return res
|
|
125
135
|
except Exception as e:
|
|
126
136
|
if self.debug_mode:
|
|
127
|
-
print(
|
|
137
|
+
print(traceback.format_exc())
|
|
128
138
|
return None
|
|
129
139
|
|
|
130
140
|
def _evaluate_in_safe_process(
|
|
@@ -150,8 +160,9 @@ class PyEvaluator(ABC):
|
|
|
150
160
|
timeout_seconds: int | float = None,
|
|
151
161
|
redirect_to_devnull: bool = False,
|
|
152
162
|
multiprocessing_start_method: Literal['default', 'auto', 'fork', 'spawn'] = 'auto',
|
|
163
|
+
get_evaluate_time=False,
|
|
153
164
|
**kwargs
|
|
154
|
-
):
|
|
165
|
+
) -> Any | Tuple[Any, float]:
|
|
155
166
|
"""Evaluate program in a new process. This enables timeout restriction and output redirection.
|
|
156
167
|
Args:
|
|
157
168
|
program: the program to be evaluated.
|
|
@@ -160,7 +171,11 @@ class PyEvaluator(ABC):
|
|
|
160
171
|
multiprocessing_start_method: start a process using 'fork' or 'spawn'. If set to 'auto',
|
|
161
172
|
the process will be started using 'fork' with Linux/macOS and 'spawn' with Windows.
|
|
162
173
|
If set to 'default', there will be no changes to system default.
|
|
174
|
+
get_evaluate_time: get evaluation time for this program.
|
|
163
175
|
**kwargs: additional keyword arguments to pass to 'evaluate_program'.
|
|
176
|
+
Returns:
|
|
177
|
+
Returns the evaluation results. If the 'get_evaluate_time' is True,
|
|
178
|
+
the return value will be (Results, Time).
|
|
164
179
|
"""
|
|
165
180
|
if multiprocessing_start_method == 'auto':
|
|
166
181
|
# Force macOS and Linux use 'fork' to generate new process
|
|
@@ -179,33 +194,43 @@ class PyEvaluator(ABC):
|
|
|
179
194
|
args=(str(program), result_queue, redirect_to_devnull),
|
|
180
195
|
kwargs=kwargs,
|
|
181
196
|
)
|
|
197
|
+
evaluate_start_time = time.time()
|
|
182
198
|
process.start()
|
|
183
199
|
|
|
184
200
|
if timeout_seconds is not None:
|
|
185
201
|
try:
|
|
186
202
|
# Get the result in timeout seconds
|
|
187
203
|
result = result_queue.get(timeout=timeout_seconds)
|
|
204
|
+
# Calculate the evaluate time
|
|
205
|
+
eval_time = time.time() - evaluate_start_time
|
|
188
206
|
# After getting the result, terminate/kill the process
|
|
189
207
|
self._kill_process_and_its_children(process)
|
|
190
208
|
except Empty: # The queue is empty indicates a timeout
|
|
209
|
+
# Calculate the evaluate time
|
|
210
|
+
eval_time = time.time() - evaluate_start_time
|
|
191
211
|
if self.debug_mode:
|
|
192
212
|
print(f'DEBUG: the evaluation time exceeds {timeout_seconds}s.')
|
|
193
213
|
# Terminate/kill all processes if timeout happens
|
|
194
214
|
self._kill_process_and_its_children(process)
|
|
195
215
|
result = None
|
|
196
216
|
except Exception as e:
|
|
217
|
+
# Calculate the evaluate time
|
|
218
|
+
eval_time = time.time() - evaluate_start_time
|
|
197
219
|
if self.debug_mode:
|
|
198
|
-
print(f'DEBUG: evaluation failed with exception:\n{
|
|
220
|
+
print(f'DEBUG: evaluation failed with exception:\n{traceback.format_exc()}')
|
|
199
221
|
# Terminate/kill all processes if meet exceptions
|
|
200
222
|
self._kill_process_and_its_children(process)
|
|
201
223
|
result = None
|
|
202
224
|
else:
|
|
203
225
|
# If there is no timeout limit, wait execution to finish
|
|
204
226
|
result = result_queue.get()
|
|
227
|
+
# Calculate the evaluate time
|
|
228
|
+
eval_time = time.time() - evaluate_start_time
|
|
205
229
|
# Terminate/kill all processes after evaluation
|
|
206
230
|
self._kill_process_and_its_children(process)
|
|
207
|
-
|
|
231
|
+
|
|
232
|
+
return (result, eval_time) if get_evaluate_time else result
|
|
208
233
|
except Exception as e:
|
|
209
234
|
if self.debug_mode:
|
|
210
|
-
print(
|
|
235
|
+
print(traceback.format_exc())
|
|
211
236
|
return None
|
|
@@ -62,21 +62,23 @@ class EvaluatorExecutorPool:
|
|
|
62
62
|
program: the program to be evaluated.
|
|
63
63
|
timeout_seconds: return 'None' if the execution time exceeds 'timeout_seconds'.
|
|
64
64
|
redirect_to_devnull: redirect any output to '/dev/null'.
|
|
65
|
-
multiprocessing_start_method: start a process using 'fork' or 'spawn'.
|
|
65
|
+
multiprocessing_start_method: start a process using 'fork' or 'spawn'. If set to 'auto',
|
|
66
|
+
the process will be started using 'fork' with Linux/macOS and 'spawn' with Windows.
|
|
67
|
+
If set to 'default', there will be no changes to system default.
|
|
68
|
+
return_time: get evaluation time for this program.
|
|
66
69
|
**kwargs: additional keyword arguments to pass to 'evaluate_program'.
|
|
70
|
+
Returns:
|
|
71
|
+
Returns the evaluation results. If the 'get_evaluate_time' is True,
|
|
72
|
+
the return value will be (Results, Time).
|
|
67
73
|
"""
|
|
68
|
-
start_time = time.time()
|
|
69
74
|
future = self.pool.submit(
|
|
70
75
|
self.evaluator.secure_evaluate,
|
|
71
76
|
program,
|
|
72
77
|
timeout_seconds,
|
|
73
78
|
redirect_to_devnull,
|
|
74
79
|
multiprocessing_start_method,
|
|
80
|
+
return_time,
|
|
75
81
|
**kwargs
|
|
76
82
|
)
|
|
77
83
|
res = future.result()
|
|
78
|
-
|
|
79
|
-
if return_time:
|
|
80
|
-
return res, duration
|
|
81
|
-
else:
|
|
82
|
-
return res
|
|
84
|
+
return res
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) 2025 Rui Zhang <rzhang.cs@gmail.com>
|
|
3
|
+
|
|
4
|
+
NOTICE: This code is under MIT license. This code is intended for academic/research purposes only.
|
|
5
|
+
Commercial use of this software or its derivatives requires prior written permission.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from abc import abstractmethod
|
|
9
|
+
from typing import List
|
|
10
|
+
|
|
11
|
+
import openai.types.chat
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class LanguageModel:
|
|
15
|
+
"""Base class for language model interface."""
|
|
16
|
+
|
|
17
|
+
@abstractmethod
|
|
18
|
+
def chat_completion(
|
|
19
|
+
self,
|
|
20
|
+
message: str | List[openai.types.chat.ChatCompletionMessageParam],
|
|
21
|
+
max_tokens: int,
|
|
22
|
+
timeout_seconds: float,
|
|
23
|
+
*args,
|
|
24
|
+
**kwargs
|
|
25
|
+
):
|
|
26
|
+
"""Send a chat completion query with OpenAI format to the vLLM server. Return the response content.
|
|
27
|
+
Args:
|
|
28
|
+
message: The message in str or openai format.
|
|
29
|
+
max_tokens: The maximum number of tokens to generate.
|
|
30
|
+
timeout_seconds: The timeout seconds.
|
|
31
|
+
"""
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
def close(self):
|
|
35
|
+
"""Release resources (if necessary)."""
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
def __del__(self):
|
|
39
|
+
self.close()
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Copyright (c) 2025 Rui Zhang <rzhang.cs@gmail.com>
|
|
3
|
+
|
|
4
|
+
NOTICE: This code is under MIT license. This code is intended for academic/research purposes only.
|
|
5
|
+
Commercial use of this software or its derivatives requires prior written permission.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
from typing import List
|
|
10
|
+
|
|
11
|
+
import openai.types.chat
|
|
12
|
+
|
|
13
|
+
from .lm_base import LanguageModel
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class OpenAIAPI(LanguageModel):
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
model: str,
|
|
20
|
+
base_url: str = None,
|
|
21
|
+
api_key: str = None,
|
|
22
|
+
**openai_init_kwargs
|
|
23
|
+
):
|
|
24
|
+
super().__init__()
|
|
25
|
+
# If base_url is set to None, find 'OPENAI_BASE_URL' in environment variables
|
|
26
|
+
if base_url is None:
|
|
27
|
+
if 'OPENAI_BASE_URL' not in os.environ:
|
|
28
|
+
raise RuntimeError('If "base_url" is None, the environment variable OPENAI_BASE_URL must be set.')
|
|
29
|
+
else:
|
|
30
|
+
base_url = os.environ['OPENAI_BASE_URL']
|
|
31
|
+
|
|
32
|
+
# If api_key is set to None, find 'OPENAI_API_KEY' in environment variables
|
|
33
|
+
if api_key is None:
|
|
34
|
+
if 'OPENAI_API_KEY' not in os.environ:
|
|
35
|
+
raise RuntimeError('If "api_key" is None, OPENAI_API_KEY must be set.')
|
|
36
|
+
else:
|
|
37
|
+
api_key = os.environ['OPENAI_API_KEY']
|
|
38
|
+
|
|
39
|
+
self._model = model
|
|
40
|
+
self._client = openai.OpenAI(
|
|
41
|
+
api_key=api_key,
|
|
42
|
+
base_url=base_url,
|
|
43
|
+
**openai_init_kwargs
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def chat_completion(
|
|
47
|
+
self,
|
|
48
|
+
message: str | List[openai.types.chat.ChatCompletionMessageParam],
|
|
49
|
+
max_tokens: int,
|
|
50
|
+
timeout_seconds: float,
|
|
51
|
+
*args,
|
|
52
|
+
**kwargs
|
|
53
|
+
):
|
|
54
|
+
"""Send a chat completion query with OpenAI format to the vLLM server. Return the response content.
|
|
55
|
+
Args:
|
|
56
|
+
message: The message in str or openai format.
|
|
57
|
+
max_tokens: The maximum number of tokens to generate.
|
|
58
|
+
timeout_seconds: The timeout seconds.
|
|
59
|
+
"""
|
|
60
|
+
if isinstance(message, str):
|
|
61
|
+
message = [{'role': 'user', 'content': message.strip()}]
|
|
62
|
+
|
|
63
|
+
response = self._client.chat.completions.create(
|
|
64
|
+
model=self._model,
|
|
65
|
+
messages=message,
|
|
66
|
+
stream=False,
|
|
67
|
+
max_tokens=max_tokens,
|
|
68
|
+
timeout=timeout_seconds,
|
|
69
|
+
*args,
|
|
70
|
+
**kwargs,
|
|
71
|
+
)
|
|
72
|
+
return response.choices[0].message.content
|
|
@@ -5,103 +5,27 @@ NOTICE: This code is under MIT license. This code is intended for academic/resea
|
|
|
5
5
|
Commercial use of this software or its derivatives requires prior written permission.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
try:
|
|
9
|
+
import vllm
|
|
10
|
+
except ImportError:
|
|
11
|
+
raise ImportError('Python package "vllm" is not installed.')
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
import requests
|
|
15
|
+
except ImportError:
|
|
16
|
+
raise ImportError('Python package "requests" is not installed.')
|
|
17
|
+
|
|
9
18
|
from typing import Optional, List, Literal, Dict, Any
|
|
10
19
|
import os
|
|
11
20
|
import subprocess
|
|
12
21
|
import sys
|
|
13
22
|
from pathlib import Path
|
|
14
23
|
import psutil
|
|
15
|
-
import requests
|
|
16
24
|
import time
|
|
17
25
|
|
|
18
26
|
import openai.types.chat
|
|
19
27
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class LanguageModel:
|
|
24
|
-
"""Base class for language model interface."""
|
|
25
|
-
|
|
26
|
-
@abstractmethod
|
|
27
|
-
def chat_completion(
|
|
28
|
-
self,
|
|
29
|
-
message: str | List[openai.types.chat.ChatCompletionMessageParam],
|
|
30
|
-
max_tokens: int,
|
|
31
|
-
timeout_seconds: float,
|
|
32
|
-
*args,
|
|
33
|
-
**kwargs
|
|
34
|
-
):
|
|
35
|
-
"""Send a chat completion query with OpenAI format to the vLLM server. Return the response content.
|
|
36
|
-
Args:
|
|
37
|
-
message: The message in str or openai format.
|
|
38
|
-
max_tokens: The maximum number of tokens to generate.
|
|
39
|
-
timeout_seconds: The timeout seconds.
|
|
40
|
-
"""
|
|
41
|
-
pass
|
|
42
|
-
|
|
43
|
-
def close(self):
|
|
44
|
-
"""Release resources (if necessary)."""
|
|
45
|
-
pass
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class OpenAIAPI(LanguageModel):
|
|
49
|
-
def __init__(
|
|
50
|
-
self,
|
|
51
|
-
model: str,
|
|
52
|
-
base_url: str = None,
|
|
53
|
-
api_key: str = None,
|
|
54
|
-
**openai_init_kwargs
|
|
55
|
-
):
|
|
56
|
-
super().__init__()
|
|
57
|
-
# If base_url is set to None, find 'OPENAI_BASE_URL' in environment variables
|
|
58
|
-
if base_url is None:
|
|
59
|
-
if 'OPENAI_BASE_URL' not in os.environ:
|
|
60
|
-
raise RuntimeError('If "base_url" is None, the environment variable OPENAI_BASE_URL must be set.')
|
|
61
|
-
else:
|
|
62
|
-
base_url = os.environ['OPENAI_BASE_URL']
|
|
63
|
-
|
|
64
|
-
# If api_key is set to None, find 'OPENAI_API_KEY' in environment variables
|
|
65
|
-
if api_key is None:
|
|
66
|
-
if 'OPENAI_API_KEY' not in os.environ:
|
|
67
|
-
raise RuntimeError('If "api_key" is None, OPENAI_API_KEY must be set.')
|
|
68
|
-
else:
|
|
69
|
-
api_key = os.environ['OPENAI_API_KEY']
|
|
70
|
-
|
|
71
|
-
self._model = model
|
|
72
|
-
self._client = openai.OpenAI(
|
|
73
|
-
api_key=api_key,
|
|
74
|
-
base_url=base_url,
|
|
75
|
-
**openai_init_kwargs
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
def chat_completion(
|
|
79
|
-
self,
|
|
80
|
-
message: str | List[openai.types.chat.ChatCompletionMessageParam],
|
|
81
|
-
max_tokens: int,
|
|
82
|
-
timeout_seconds: float,
|
|
83
|
-
*args,
|
|
84
|
-
**kwargs
|
|
85
|
-
):
|
|
86
|
-
"""Send a chat completion query with OpenAI format to the vLLM server. Return the response content.
|
|
87
|
-
Args:
|
|
88
|
-
message: The message in str or openai format.
|
|
89
|
-
max_tokens: The maximum number of tokens to generate.
|
|
90
|
-
timeout_seconds: The timeout seconds.
|
|
91
|
-
"""
|
|
92
|
-
if isinstance(message, str):
|
|
93
|
-
message = [{'role': 'user', 'content': message.strip()}]
|
|
94
|
-
|
|
95
|
-
response = self._client.chat.completions.create(
|
|
96
|
-
model=self._model,
|
|
97
|
-
messages=message,
|
|
98
|
-
stream=False,
|
|
99
|
-
max_tokens=max_tokens,
|
|
100
|
-
timeout=timeout_seconds,
|
|
101
|
-
*args,
|
|
102
|
-
**kwargs,
|
|
103
|
-
)
|
|
104
|
-
return response.choices[0].message.content
|
|
28
|
+
from .lm_base import LanguageModel
|
|
105
29
|
|
|
106
30
|
|
|
107
31
|
def _print_cmd_list(cmd_list, gpus, host, port):
|
|
@@ -115,24 +39,26 @@ def _print_cmd_list(cmd_list, gpus, host, port):
|
|
|
115
39
|
print('=' * 80 + '\n', flush=True)
|
|
116
40
|
|
|
117
41
|
|
|
118
|
-
class VLLMServer:
|
|
119
|
-
def __init__(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
42
|
+
class VLLMServer(LanguageModel):
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
model_path: str,
|
|
46
|
+
port: int,
|
|
47
|
+
gpus: int | list[int],
|
|
48
|
+
tokenizer_path: Optional[str] = None,
|
|
49
|
+
max_model_len: int = 16384,
|
|
50
|
+
max_lora_rank: Optional[int] = None,
|
|
51
|
+
host: str = '0.0.0.0',
|
|
52
|
+
mem_util: float = 0.85,
|
|
53
|
+
deploy_timeout_seconds: int = 600,
|
|
54
|
+
enforce_eager: bool = False,
|
|
55
|
+
vllm_log_level: Literal['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] = 'INFO',
|
|
56
|
+
silent_mode: bool = False,
|
|
57
|
+
env_variable_dict: Optional[Dict[str, str]] = None,
|
|
58
|
+
vllm_serve_args: Optional[List[str]] = None,
|
|
59
|
+
vllm_serve_kwargs: Optional[Dict[str, str]] = None,
|
|
60
|
+
chat_template_kwargs: Optional[Dict[str, Any]] = None
|
|
61
|
+
):
|
|
136
62
|
"""Deploy an LLM on specified GPUs.
|
|
137
63
|
Args:
|
|
138
64
|
model_path: Path to the model to deploy.
|
|
@@ -234,8 +160,8 @@ class VLLMServer:
|
|
|
234
160
|
env['CUDA_VISIBLE_DEVICES'] = gpus
|
|
235
161
|
env['VLLM_LOGGING_LEVEL'] = self._vllm_log_level
|
|
236
162
|
|
|
237
|
-
# FIXME: These code are required for my machine
|
|
238
|
-
# FIXME: This may due to the bad NCCL
|
|
163
|
+
# FIXME: These code are required for my machine :(
|
|
164
|
+
# FIXME: This may due to the bad NCCL configuration :(
|
|
239
165
|
if isinstance(self._gpus, list) and len(self._gpus) > 1:
|
|
240
166
|
# set NCCL environment variable
|
|
241
167
|
env['NCCL_P2P_DISABLE'] = '1'
|
|
@@ -352,24 +278,26 @@ class VLLMServer:
|
|
|
352
278
|
print(f'[vLLM] Failed to load LoRA adapter. '
|
|
353
279
|
f'Status code: {response.status_code}, Response: {response.text}')
|
|
354
280
|
return True
|
|
355
|
-
except requests.exceptions.RequestException
|
|
281
|
+
except requests.exceptions.RequestException:
|
|
356
282
|
continue
|
|
357
283
|
|
|
358
|
-
print(f'[vLLM] Error loading LoRA adapter
|
|
284
|
+
print(f'[vLLM] Error loading LoRA adapter.')
|
|
359
285
|
return False
|
|
360
286
|
|
|
361
287
|
def close(self):
|
|
362
288
|
"""Shut down vLLM server and kill all vLLM processes."""
|
|
363
289
|
self._kill_vllm_process()
|
|
364
290
|
|
|
365
|
-
def chat_completion(
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
291
|
+
def chat_completion(
|
|
292
|
+
self,
|
|
293
|
+
message: str | List[openai.types.chat.ChatCompletionMessageParam],
|
|
294
|
+
max_tokens: Optional[int] = None,
|
|
295
|
+
timeout_seconds: Optional[int] = None,
|
|
296
|
+
lora_name: Optional[str] = None,
|
|
297
|
+
temperature: float = 0.9,
|
|
298
|
+
top_p: float = 0.9,
|
|
299
|
+
chat_template_kwargs: Optional[Dict[str, Any]] = None
|
|
300
|
+
) -> str:
|
|
373
301
|
"""Send a chat completion query with OpenAI format to the vLLM server. Return the response content.
|
|
374
302
|
Args:
|
|
375
303
|
message: The message in str or openai format.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: py-adtools
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
4
4
|
Summary: Useful tools for parsing and evaluating Python programs for LLM-based algorithm design.
|
|
5
5
|
Home-page: https://github.com/RayZhhh/py-adtools
|
|
6
6
|
Author: Rui Zhang
|
|
@@ -13,6 +13,7 @@ Requires-Python: >=3.10
|
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
15
|
Requires-Dist: psutil
|
|
16
|
+
Requires-Dist: openai
|
|
16
17
|
Dynamic: author
|
|
17
18
|
Dynamic: author-email
|
|
18
19
|
Dynamic: classifier
|
|
@@ -4,8 +4,11 @@ setup.py
|
|
|
4
4
|
adtools/__init__.py
|
|
5
5
|
adtools/evaluator.py
|
|
6
6
|
adtools/evaluator_pool.py
|
|
7
|
-
adtools/lm_base.py
|
|
8
7
|
adtools/py_code.py
|
|
8
|
+
adtools/lm/__init__.py
|
|
9
|
+
adtools/lm/lm_base.py
|
|
10
|
+
adtools/lm/openai_api.py
|
|
11
|
+
adtools/lm/vllm_server.py
|
|
9
12
|
py_adtools.egg-info/PKG-INFO
|
|
10
13
|
py_adtools.egg-info/SOURCES.txt
|
|
11
14
|
py_adtools.egg-info/dependency_links.txt
|
|
@@ -5,14 +5,14 @@ with open('README.md', 'r', encoding='utf-8') as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name='py-adtools',
|
|
8
|
-
version='0.1.
|
|
8
|
+
version='0.1.8',
|
|
9
9
|
author='Rui Zhang',
|
|
10
10
|
author_email='rzhang.cs@gmail.com',
|
|
11
11
|
description='Useful tools for parsing and evaluating Python programs for LLM-based algorithm design.',
|
|
12
12
|
long_description=long_description,
|
|
13
13
|
long_description_content_type='text/markdown',
|
|
14
14
|
url='https://github.com/RayZhhh/py-adtools',
|
|
15
|
-
packages=
|
|
15
|
+
packages=find_packages(),
|
|
16
16
|
classifiers=[
|
|
17
17
|
'Programming Language :: Python :: 3',
|
|
18
18
|
'Operating System :: OS Independent',
|
|
@@ -20,5 +20,5 @@ setup(
|
|
|
20
20
|
'Topic :: Scientific/Engineering',
|
|
21
21
|
],
|
|
22
22
|
python_requires='>=3.10',
|
|
23
|
-
install_requires=['psutil'],
|
|
23
|
+
install_requires=['psutil', 'openai'],
|
|
24
24
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|