lollms-client 1.6.7__py3-none-any.whl → 1.7.0__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.
Potentially problematic release.
This version of lollms-client might be problematic. Click here for more details.
- lollms_client/__init__.py +1 -1
- lollms_client/lollms_agentic.py +4 -2
- lollms_client/lollms_core.py +263 -138
- lollms_client/lollms_discussion.py +15 -2
- lollms_client/lollms_stt_binding.py +59 -3
- lollms_client/lollms_tti_binding.py +3 -1
- lollms_client/lollms_ttm_binding.py +3 -1
- lollms_client/lollms_tts_binding.py +2 -2
- lollms_client/lollms_ttv_binding.py +3 -1
- lollms_client/stt_bindings/whisper/__init__.py +20 -12
- lollms_client/stt_bindings/whispercpp/__init__.py +7 -1
- lollms_client/tti_bindings/diffusers/__init__.py +9 -10
- lollms_client/tti_bindings/diffusers/server/main.py +10 -59
- lollms_client/tti_bindings/gemini/__init__.py +4 -1
- lollms_client/tti_bindings/leonardo_ai/__init__.py +5 -2
- lollms_client/tti_bindings/lollms/__init__.py +4 -1
- lollms_client/tti_bindings/novita_ai/__init__.py +4 -1
- lollms_client/tti_bindings/openai/__init__.py +10 -11
- lollms_client/tti_bindings/stability_ai/__init__.py +4 -2
- lollms_client/ttm_bindings/audiocraft/__init__.py +7 -12
- lollms_client/ttm_bindings/beatoven_ai/__init__.py +7 -3
- lollms_client/ttm_bindings/lollms/__init__.py +4 -17
- lollms_client/ttm_bindings/replicate/__init__.py +7 -4
- lollms_client/ttm_bindings/stability_ai/__init__.py +7 -4
- lollms_client/ttm_bindings/topmediai/__init__.py +6 -3
- lollms_client/tts_bindings/bark/__init__.py +7 -10
- lollms_client/tts_bindings/piper_tts/__init__.py +7 -10
- lollms_client/tts_bindings/xtts/__init__.py +8 -8
- {lollms_client-1.6.7.dist-info → lollms_client-1.7.0.dist-info}/METADATA +1 -1
- {lollms_client-1.6.7.dist-info → lollms_client-1.7.0.dist-info}/RECORD +33 -33
- {lollms_client-1.6.7.dist-info → lollms_client-1.7.0.dist-info}/WHEEL +0 -0
- {lollms_client-1.6.7.dist-info → lollms_client-1.7.0.dist-info}/licenses/LICENSE +0 -0
- {lollms_client-1.6.7.dist-info → lollms_client-1.7.0.dist-info}/top_level.txt +0 -0
|
@@ -4,12 +4,13 @@ import importlib
|
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import Optional, List, Dict, Any, Union
|
|
6
6
|
from ascii_colors import trace_exception
|
|
7
|
-
|
|
7
|
+
import yaml
|
|
8
8
|
class LollmsSTTBinding(ABC):
|
|
9
9
|
"""Abstract base class for all LOLLMS Speech-to-Text bindings."""
|
|
10
10
|
|
|
11
11
|
def __init__(self,
|
|
12
|
-
binding_name:str="unknown"
|
|
12
|
+
binding_name:str="unknown",
|
|
13
|
+
config={}):
|
|
13
14
|
"""
|
|
14
15
|
Initialize the LollmsSTTBinding base class.
|
|
15
16
|
|
|
@@ -17,6 +18,7 @@ class LollmsSTTBinding(ABC):
|
|
|
17
18
|
binding_name (Optional[str]): The binding name
|
|
18
19
|
"""
|
|
19
20
|
self.binding_name = binding_name
|
|
21
|
+
self.config = config
|
|
20
22
|
|
|
21
23
|
@abstractmethod
|
|
22
24
|
def transcribe_audio(self, audio_path: Union[str, Path], model: Optional[str] = None, **kwargs) -> str:
|
|
@@ -122,4 +124,58 @@ class LollmsSTTBindingManager:
|
|
|
122
124
|
list[str]: List of binding names.
|
|
123
125
|
"""
|
|
124
126
|
return [binding_dir.name for binding_dir in self.stt_bindings_dir.iterdir()
|
|
125
|
-
if binding_dir.is_dir() and (binding_dir / "__init__.py").exists()]
|
|
127
|
+
if binding_dir.is_dir() and (binding_dir / "__init__.py").exists()]
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@staticmethod
|
|
131
|
+
def _get_fallback_description(binding_name: str) -> Dict:
|
|
132
|
+
return {
|
|
133
|
+
"binding_name": binding_name,
|
|
134
|
+
"title": binding_name.replace("_", " ").title(),
|
|
135
|
+
"author": "Unknown",
|
|
136
|
+
"version": "N/A",
|
|
137
|
+
"description": f"A binding for {binding_name}. No description.yaml file was found.",
|
|
138
|
+
"input_parameters": [
|
|
139
|
+
{
|
|
140
|
+
"name": "model_name",
|
|
141
|
+
"type": "str",
|
|
142
|
+
"description": "The model name or ID to be used.",
|
|
143
|
+
"mandatory": False,
|
|
144
|
+
"default": ""
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"generate_audio_parameters": []
|
|
148
|
+
}
|
|
149
|
+
@staticmethod
|
|
150
|
+
def get_bindings_list(stt_bindings_dir: Union[str, Path]) -> List[Dict]:
|
|
151
|
+
bindings_dir = Path(stt_bindings_dir)
|
|
152
|
+
if not bindings_dir.is_dir():
|
|
153
|
+
return []
|
|
154
|
+
|
|
155
|
+
bindings_list = []
|
|
156
|
+
for binding_folder in bindings_dir.iterdir():
|
|
157
|
+
if binding_folder.is_dir() and (binding_folder / "__init__.py").exists():
|
|
158
|
+
binding_name = binding_folder.name
|
|
159
|
+
description_file = binding_folder / "description.yaml"
|
|
160
|
+
|
|
161
|
+
binding_info = {}
|
|
162
|
+
if description_file.exists():
|
|
163
|
+
try:
|
|
164
|
+
with open(description_file, 'r', encoding='utf-8') as f:
|
|
165
|
+
binding_info = yaml.safe_load(f)
|
|
166
|
+
binding_info['binding_name'] = binding_name
|
|
167
|
+
except Exception as e:
|
|
168
|
+
print(f"Error loading description.yaml for {binding_name}: {e}")
|
|
169
|
+
binding_info = LollmsSTTBindingManager._get_fallback_description(binding_name)
|
|
170
|
+
else:
|
|
171
|
+
binding_info = LollmsSTTBindingManager._get_fallback_description(binding_name)
|
|
172
|
+
|
|
173
|
+
bindings_list.append(binding_info)
|
|
174
|
+
|
|
175
|
+
return sorted(bindings_list, key=lambda b: b.get('title', b['binding_name']))
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def get_available_bindings(stt_bindings_dir: Union[str, Path] = None) -> List[Dict]:
|
|
179
|
+
if stt_bindings_dir is None:
|
|
180
|
+
stt_bindings_dir = Path(__file__).resolve().parent / "stt_bindings"
|
|
181
|
+
return LollmsSTTBindingManager.get_bindings_list(stt_bindings_dir)
|
|
@@ -9,7 +9,8 @@ class LollmsTTIBinding(ABC):
|
|
|
9
9
|
"""Abstract base class for all LOLLMS Text-to-Image bindings."""
|
|
10
10
|
|
|
11
11
|
def __init__(self,
|
|
12
|
-
binding_name:str="unknown"
|
|
12
|
+
binding_name:str="unknown",
|
|
13
|
+
config={}):
|
|
13
14
|
"""
|
|
14
15
|
Initialize the LollmsTTIBinding base class.
|
|
15
16
|
|
|
@@ -17,6 +18,7 @@ class LollmsTTIBinding(ABC):
|
|
|
17
18
|
binding_name (Optional[str]): The binding name
|
|
18
19
|
"""
|
|
19
20
|
self.binding_name = binding_name
|
|
21
|
+
self.config = config
|
|
20
22
|
|
|
21
23
|
@abstractmethod
|
|
22
24
|
def generate_image(self,
|
|
@@ -9,7 +9,8 @@ class LollmsTTMBinding(ABC):
|
|
|
9
9
|
"""Abstract base class for all LOLLMS Text-to-Music bindings."""
|
|
10
10
|
|
|
11
11
|
def __init__(self,
|
|
12
|
-
binding_name:str="unknown"
|
|
12
|
+
binding_name:str="unknown",
|
|
13
|
+
config={}):
|
|
13
14
|
"""
|
|
14
15
|
Initialize the LollmsTTMBinding base class.
|
|
15
16
|
|
|
@@ -17,6 +18,7 @@ class LollmsTTMBinding(ABC):
|
|
|
17
18
|
binding_name (Optional[str]): The binding name
|
|
18
19
|
"""
|
|
19
20
|
self.binding_name = binding_name
|
|
21
|
+
self.config = config
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
@abstractmethod
|
|
@@ -8,9 +8,9 @@ from ascii_colors import trace_exception
|
|
|
8
8
|
class LollmsTTSBinding(ABC):
|
|
9
9
|
def __init__(self,
|
|
10
10
|
binding_name: str = "unknown",
|
|
11
|
-
|
|
11
|
+
config={}):
|
|
12
12
|
self.binding_name = binding_name
|
|
13
|
-
self.
|
|
13
|
+
self.config = config
|
|
14
14
|
|
|
15
15
|
@abstractmethod
|
|
16
16
|
def generate_audio(self,
|
|
@@ -9,7 +9,8 @@ class LollmsTTVBinding(ABC):
|
|
|
9
9
|
"""Abstract base class for all LOLLMS Text-to-Video bindings."""
|
|
10
10
|
|
|
11
11
|
def __init__(self,
|
|
12
|
-
binding_name:str="unknown"
|
|
12
|
+
binding_name:str="unknown",
|
|
13
|
+
config={}):
|
|
13
14
|
"""
|
|
14
15
|
Initialize the LollmsTTVBinding base class.
|
|
15
16
|
|
|
@@ -17,6 +18,7 @@ class LollmsTTVBinding(ABC):
|
|
|
17
18
|
binding_name (Optional[str]): The binding name
|
|
18
19
|
"""
|
|
19
20
|
self.binding_name = binding_name
|
|
21
|
+
self.config = config
|
|
20
22
|
|
|
21
23
|
@abstractmethod
|
|
22
24
|
def generate_video(self, prompt: str, **kwargs) -> bytes:
|
|
@@ -67,7 +67,7 @@ class WhisperSTTBinding(LollmsSTTBinding):
|
|
|
67
67
|
"""
|
|
68
68
|
|
|
69
69
|
# Standard Whisper model sizes
|
|
70
|
-
WHISPER_MODEL_SIZES = ["
|
|
70
|
+
WHISPER_MODEL_SIZES = ["turbo"]
|
|
71
71
|
|
|
72
72
|
def __init__(self,
|
|
73
73
|
**kwargs # To catch any other LollmsSTTBinding standard args
|
|
@@ -76,12 +76,13 @@ class WhisperSTTBinding(LollmsSTTBinding):
|
|
|
76
76
|
Initialize the Whisper STT binding.
|
|
77
77
|
|
|
78
78
|
Args:
|
|
79
|
-
model_name (str): The Whisper model size to use (e.g., "
|
|
80
|
-
Defaults to "
|
|
79
|
+
model_name (str): The Whisper model size to use (e.g., "turbo").
|
|
80
|
+
Defaults to "turno".
|
|
81
81
|
device (Optional[str]): The device to run the model on ("cpu", "cuda", "mps").
|
|
82
82
|
If None, `torch` will attempt to auto-detect. Defaults to None.
|
|
83
83
|
"""
|
|
84
84
|
super().__init__(binding_name="whisper") # Not applicable
|
|
85
|
+
self.default_model_name = kwargs.get("model_name", "turno")
|
|
85
86
|
|
|
86
87
|
if not _whisper_installed:
|
|
87
88
|
raise ImportError(f"Whisper STT binding dependencies not met. Please ensure 'openai-whisper' and 'torch' are installed. Error: {_whisper_installation_error}")
|
|
@@ -99,12 +100,15 @@ class WhisperSTTBinding(LollmsSTTBinding):
|
|
|
99
100
|
|
|
100
101
|
self.loaded_model_name = None
|
|
101
102
|
self.model = None
|
|
102
|
-
|
|
103
|
+
try:
|
|
104
|
+
self._load_whisper_model(kwargs.get("model_name", "turbo")) # Default to "turno" if not specified
|
|
105
|
+
except Exception as e:
|
|
106
|
+
pass
|
|
103
107
|
|
|
104
108
|
|
|
105
109
|
def _load_whisper_model(self, model_name_to_load: str):
|
|
106
110
|
"""Loads or reloads the Whisper model."""
|
|
107
|
-
if model_name_to_load not in
|
|
111
|
+
if model_name_to_load not in whisper.available_models():
|
|
108
112
|
ASCIIColors.warning(f"'{model_name_to_load}' is not a standard Whisper model size. Attempting to load anyway. Known sizes: {self.WHISPER_MODEL_SIZES}")
|
|
109
113
|
|
|
110
114
|
if self.model is not None and self.loaded_model_name == model_name_to_load:
|
|
@@ -149,6 +153,10 @@ class WhisperSTTBinding(LollmsSTTBinding):
|
|
|
149
153
|
RuntimeError: If the Whisper model is not loaded or transcription fails.
|
|
150
154
|
Exception: For other errors during transcription.
|
|
151
155
|
"""
|
|
156
|
+
if not self.model:
|
|
157
|
+
self._load_whisper_model(self.default_model_name)
|
|
158
|
+
|
|
159
|
+
|
|
152
160
|
audio_file = Path(audio_path)
|
|
153
161
|
if not audio_file.exists():
|
|
154
162
|
raise FileNotFoundError(f"Audio file not found at: {audio_path}")
|
|
@@ -191,8 +199,8 @@ class WhisperSTTBinding(LollmsSTTBinding):
|
|
|
191
199
|
trace_exception(e)
|
|
192
200
|
raise Exception(f"Whisper transcription error: {e}") from e
|
|
193
201
|
|
|
194
|
-
|
|
195
|
-
def list_models(
|
|
202
|
+
@staticmethod
|
|
203
|
+
def list_models(**kwargs) -> List[str]:
|
|
196
204
|
"""
|
|
197
205
|
Lists the available standard Whisper model sizes.
|
|
198
206
|
|
|
@@ -202,7 +210,7 @@ class WhisperSTTBinding(LollmsSTTBinding):
|
|
|
202
210
|
Returns:
|
|
203
211
|
List[str]: A list of available Whisper model size identifiers.
|
|
204
212
|
"""
|
|
205
|
-
return
|
|
213
|
+
return whisper.available_models() # Return a copy
|
|
206
214
|
|
|
207
215
|
def __del__(self):
|
|
208
216
|
"""Clean up: Unload the model to free resources."""
|
|
@@ -252,7 +260,7 @@ if __name__ == '__main__':
|
|
|
252
260
|
else:
|
|
253
261
|
try:
|
|
254
262
|
ASCIIColors.cyan("\n--- Initializing WhisperSTTBinding (model: 'tiny') ---")
|
|
255
|
-
# Using 'tiny' model for faster testing. Change to '
|
|
263
|
+
# Using 'tiny' model for faster testing. Change to 'turno' or 'small' for better quality.
|
|
256
264
|
stt_binding = WhisperSTTBinding(model_name="tiny")
|
|
257
265
|
|
|
258
266
|
ASCIIColors.cyan("\n--- Listing available Whisper models ---")
|
|
@@ -269,9 +277,9 @@ if __name__ == '__main__':
|
|
|
269
277
|
# print(f"Transcription (tiny, lang='en'): '{transcription_lang_hint}'")
|
|
270
278
|
|
|
271
279
|
# Test switching model dynamically (optional, will re-download/load if different)
|
|
272
|
-
# ASCIIColors.cyan(f"\n--- Transcribing '{test_audio_file.name}' by switching to '
|
|
273
|
-
# transcription_base = stt_binding.transcribe_audio(test_audio_file, model="
|
|
274
|
-
# print(f"Transcription (
|
|
280
|
+
# ASCIIColors.cyan(f"\n--- Transcribing '{test_audio_file.name}' by switching to 'turno' model ---")
|
|
281
|
+
# transcription_base = stt_binding.transcribe_audio(test_audio_file, model="turno")
|
|
282
|
+
# print(f"Transcription (turno): '{transcription_base}'")
|
|
275
283
|
|
|
276
284
|
|
|
277
285
|
except ImportError as e_imp:
|
|
@@ -31,6 +31,8 @@ class WhisperCppSTTBinding(LollmsSTTBinding):
|
|
|
31
31
|
n_threads = kwargs.get("n_threads", 4)
|
|
32
32
|
extra_whisper_args = kwargs.get("extra_whisper_args", []) # e.g. ["--no-timestamps"]
|
|
33
33
|
|
|
34
|
+
self.default_model_name = "base"
|
|
35
|
+
|
|
34
36
|
# --- Validate FFMPEG ---
|
|
35
37
|
self.ffmpeg_exe = None
|
|
36
38
|
if ffmpeg_path:
|
|
@@ -376,4 +378,8 @@ if __name__ == '__main__':
|
|
|
376
378
|
TEST_MODELS_SEARCH_DIR.rmdir()
|
|
377
379
|
except OSError: pass # Ignore if not empty or other issues
|
|
378
380
|
|
|
379
|
-
ASCIIColors.yellow("\n--- WhisperCppSTTBinding Test Finished ---")
|
|
381
|
+
ASCIIColors.yellow("\n--- WhisperCppSTTBinding Test Finished ---")
|
|
382
|
+
|
|
383
|
+
def list_models(self) -> List[Dict[str, Any]]:
|
|
384
|
+
return ["base" , "small", "medium", "large"]
|
|
385
|
+
|
|
@@ -36,16 +36,15 @@ class DiffusersBinding(LollmsTTIBinding):
|
|
|
36
36
|
"""
|
|
37
37
|
def __init__(self,
|
|
38
38
|
**kwargs):
|
|
39
|
-
|
|
40
|
-
super().__init__(binding_name=BindingName)
|
|
41
|
-
|
|
42
39
|
# Prioritize 'model_name' but accept 'model' as an alias from config files.
|
|
43
40
|
if 'model' in kwargs and 'model_name' not in kwargs:
|
|
44
41
|
kwargs['model_name'] = kwargs.pop('model')
|
|
42
|
+
super().__init__(binding_name=BindingName, config=kwargs)
|
|
43
|
+
|
|
44
|
+
|
|
45
45
|
|
|
46
|
-
self.config = kwargs
|
|
47
46
|
self.host = kwargs.get("host", "localhost")
|
|
48
|
-
self.port = kwargs.get("port",
|
|
47
|
+
self.port = kwargs.get("port", 9632)
|
|
49
48
|
self.auto_start_server = kwargs.get("auto_start_server", True)
|
|
50
49
|
self.server_process = None
|
|
51
50
|
self.base_url = f"http://{self.host}:{self.port}"
|
|
@@ -61,7 +60,7 @@ class DiffusersBinding(LollmsTTIBinding):
|
|
|
61
60
|
def is_server_running(self) -> bool:
|
|
62
61
|
"""Checks if the server is already running and responsive."""
|
|
63
62
|
try:
|
|
64
|
-
response = requests.get(f"{self.base_url}/status", timeout=
|
|
63
|
+
response = requests.get(f"{self.base_url}/status", timeout=4)
|
|
65
64
|
if response.status_code == 200 and response.json().get("status") == "running":
|
|
66
65
|
return True
|
|
67
66
|
except requests.exceptions.RequestException:
|
|
@@ -90,7 +89,7 @@ class DiffusersBinding(LollmsTTIBinding):
|
|
|
90
89
|
try:
|
|
91
90
|
# Try to acquire the lock with a timeout. If another process is starting
|
|
92
91
|
# the server, this will wait until it's finished.
|
|
93
|
-
with lock.acquire(timeout=
|
|
92
|
+
with lock.acquire(timeout=3):
|
|
94
93
|
# After acquiring the lock, we MUST re-check if the server is running.
|
|
95
94
|
# Another process might have started it and released the lock while we were waiting.
|
|
96
95
|
if not self.is_server_running():
|
|
@@ -105,7 +104,7 @@ class DiffusersBinding(LollmsTTIBinding):
|
|
|
105
104
|
# This happens if the process holding the lock takes more than 60 seconds to start the server.
|
|
106
105
|
# We don't try to start another one. We just wait for the existing one to be ready.
|
|
107
106
|
ASCIIColors.yellow("Could not acquire lock, another process is taking a long time to start the server. Waiting...")
|
|
108
|
-
self._wait_for_server(timeout=
|
|
107
|
+
self._wait_for_server(timeout=60) # Give it a longer timeout here just in case.
|
|
109
108
|
|
|
110
109
|
# A final verification to ensure we are connected.
|
|
111
110
|
if not self.is_server_running():
|
|
@@ -214,7 +213,7 @@ class DiffusersBinding(LollmsTTIBinding):
|
|
|
214
213
|
self.server_process = subprocess.Popen(command, creationflags=creationflags)
|
|
215
214
|
ASCIIColors.info("Diffusers server process launched in the background.")
|
|
216
215
|
|
|
217
|
-
def _wait_for_server(self, timeout=
|
|
216
|
+
def _wait_for_server(self, timeout=30):
|
|
218
217
|
"""Waits for the server to become responsive."""
|
|
219
218
|
ASCIIColors.info("Waiting for Diffusers server to become available...")
|
|
220
219
|
start_time = time.time()
|
|
@@ -374,4 +373,4 @@ class DiffusersBinding(LollmsTTIBinding):
|
|
|
374
373
|
def __del__(self):
|
|
375
374
|
# The client destructor does not stop the server,
|
|
376
375
|
# as it is a shared resource for all worker processes.
|
|
377
|
-
pass
|
|
376
|
+
pass
|
|
@@ -60,66 +60,14 @@ MODELS_PATH = Path("./models")
|
|
|
60
60
|
|
|
61
61
|
# --- START: Core Logic (Complete and Unabridged) ---
|
|
62
62
|
CIVITAI_MODELS = {
|
|
63
|
-
"
|
|
64
|
-
"display_name": "Realistic Vision V6.0", "url": "https://civitai.com/api/download/models/501240?type=Model&format=SafeTensor&size=pruned&fp=fp16",
|
|
65
|
-
"filename": "realisticVisionV60_v60B1.safetensors", "description": "Photorealistic SD1.5 checkpoint.", "owned_by": "civitai"
|
|
66
|
-
},
|
|
67
|
-
"absolute-reality": {
|
|
68
|
-
"display_name": "Absolute Reality", "url": "https://civitai.com/api/download/models/132760?type=Model&format=SafeTensor&size=pruned&fp=fp16",
|
|
69
|
-
"filename": "absolutereality_v181.safetensors", "description": "General realistic SD1.5.", "owned_by": "civitai"
|
|
70
|
-
},
|
|
71
|
-
"dreamshaper-8": {
|
|
63
|
+
"DreamShaper-8": {
|
|
72
64
|
"display_name": "DreamShaper 8", "url": "https://civitai.com/api/download/models/128713",
|
|
73
65
|
"filename": "dreamshaper_8.safetensors", "description": "Versatile SD1.5 style model.", "owned_by": "civitai"
|
|
74
66
|
},
|
|
75
|
-
"
|
|
67
|
+
"Juggernaut-xl": {
|
|
76
68
|
"display_name": "Juggernaut XL", "url": "https://civitai.com/api/download/models/133005",
|
|
77
69
|
"filename": "juggernautXL_version6Rundiffusion.safetensors", "description": "Artistic SDXL.", "owned_by": "civitai"
|
|
78
70
|
},
|
|
79
|
-
"lyriel-v1.6": {
|
|
80
|
-
"display_name": "Lyriel v1.6", "url": "https://civitai.com/api/download/models/72396?type=Model&format=SafeTensor&size=full&fp=fp16",
|
|
81
|
-
"filename": "lyriel_v16.safetensors", "description": "Fantasy/stylized SD1.5.", "owned_by": "civitai"
|
|
82
|
-
},
|
|
83
|
-
"ui_icons": {
|
|
84
|
-
"display_name": "UI Icons", "url": "https://civitai.com/api/download/models/367044?type=Model&format=SafeTensor&size=full&fp=fp16",
|
|
85
|
-
"filename": "uiIcons_v10.safetensors", "description": "A model for generating UI icons.", "owned_by": "civitai"
|
|
86
|
-
},
|
|
87
|
-
"meinamix": {
|
|
88
|
-
"display_name": "MeinaMix", "url": "https://civitai.com/api/download/models/948574?type=Model&format=SafeTensor&size=pruned&fp=fp16",
|
|
89
|
-
"filename": "meinamix_meinaV11.safetensors", "description": "Anime/illustration SD1.5.", "owned_by": "civitai"
|
|
90
|
-
},
|
|
91
|
-
"rpg-v5": {
|
|
92
|
-
"display_name": "RPG v5", "url": "https://civitai.com/api/download/models/124626?type=Model&format=SafeTensor&size=pruned&fp=fp16",
|
|
93
|
-
"filename": "rpg_v5.safetensors", "description": "RPG assets SD1.5.", "owned_by": "civitai"
|
|
94
|
-
},
|
|
95
|
-
"pixel-art-xl": {
|
|
96
|
-
"display_name": "Pixel Art XL", "url": "https://civitai.com/api/download/models/135931?type=Model&format=SafeTensor",
|
|
97
|
-
"filename": "pixelartxl_v11.safetensors", "description": "Pixel art SDXL.", "owned_by": "civitai"
|
|
98
|
-
},
|
|
99
|
-
"lowpoly-world": {
|
|
100
|
-
"display_name": "Lowpoly World", "url": "https://civitai.com/api/download/models/146502?type=Model&format=SafeTensor",
|
|
101
|
-
"filename": "LowpolySDXL.safetensors", "description": "Lowpoly style SD1.5.", "owned_by": "civitai"
|
|
102
|
-
},
|
|
103
|
-
"toonyou": {
|
|
104
|
-
"display_name": "ToonYou", "url": "https://civitai.com/api/download/models/125771?type=Model&format=SafeTensor&size=pruned&fp=fp16",
|
|
105
|
-
"filename": "toonyou_beta6.safetensors", "description": "Cartoon/Disney SD1.5.", "owned_by": "civitai"
|
|
106
|
-
},
|
|
107
|
-
"papercut": {
|
|
108
|
-
"display_name": "Papercut", "url": "https://civitai.com/api/download/models/133503?type=Model&format=SafeTensor",
|
|
109
|
-
"filename": "papercut.safetensors", "description": "Paper cutout SD1.5.", "owned_by": "civitai"
|
|
110
|
-
},
|
|
111
|
-
"fantassifiedIcons": {
|
|
112
|
-
"display_name": "Fantassified Icons", "url": "https://civitai.com/api/download/models/67584?type=Model&format=SafeTensor&size=pruned&fp=fp16",
|
|
113
|
-
"filename": "fantassifiedIcons_fantassifiedIconsV20.safetensors", "description": "Flat, modern Icons.", "owned_by": "civitai"
|
|
114
|
-
},
|
|
115
|
-
"game_icon_institute": {
|
|
116
|
-
"display_name": "Game icon institute", "url": "https://civitai.com/api/download/models/158776?type=Model&format=SafeTensor&size=full&fp=fp16",
|
|
117
|
-
"filename": "gameIconInstituteV10_v10.safetensors", "description": "Flat, modern game Icons.", "owned_by": "civitai"
|
|
118
|
-
},
|
|
119
|
-
"M4RV3LS_DUNGEONS": {
|
|
120
|
-
"display_name": "M4RV3LS & DUNGEONS", "url": "https://civitai.com/api/download/models/139417?type=Model&format=SafeTensor&size=pruned&fp=fp16",
|
|
121
|
-
"filename": "M4RV3LSDUNGEONSNEWV40COMICS_mD40.safetensors", "description": "comics.", "owned_by": "civitai"
|
|
122
|
-
},
|
|
123
71
|
}
|
|
124
72
|
|
|
125
73
|
HF_PUBLIC_MODELS = {
|
|
@@ -183,6 +131,7 @@ SCHEDULER_MAPPING = {
|
|
|
183
131
|
"dpm2_karras": "KDPM2DiscreteScheduler", "dpm2_a": "KDPM2AncestralDiscreteScheduler", "dpm2_a_karras": "KDPM2AncestralDiscreteScheduler",
|
|
184
132
|
"euler": "EulerDiscreteScheduler", "euler_a": "EulerAncestralDiscreteScheduler", "heun": "HeunDiscreteScheduler", "lms": "LMSDiscreteScheduler"
|
|
185
133
|
}
|
|
134
|
+
|
|
186
135
|
SCHEDULER_USES_KARRAS_SIGMAS = [
|
|
187
136
|
"dpm_multistep_karras","dpm++_2m_karras","dpm++_2s_ancestral_karras", "dpm++_sde_karras","heun_karras","lms_karras",
|
|
188
137
|
"dpm++_2m_sde_karras","dpm2_karras","dpm2_a_karras"
|
|
@@ -604,7 +553,7 @@ class ServerState:
|
|
|
604
553
|
return {
|
|
605
554
|
"model_name": "", "device": "auto", "torch_dtype_str": "auto", "use_safetensors": True,
|
|
606
555
|
"scheduler_name": "default", "safety_checker_on": True, "num_inference_steps": 25,
|
|
607
|
-
"guidance_scale": 7.0, "width":
|
|
556
|
+
"guidance_scale": 7.0, "width": 1024, "height": 1024, "seed": -1,
|
|
608
557
|
"enable_cpu_offload": False, "enable_sequential_cpu_offload": False, "enable_xformers": False,
|
|
609
558
|
"hf_variant": None, "hf_token": None, "hf_cache_path": None, "local_files_only": False,
|
|
610
559
|
"unload_inactive_model_after": 0
|
|
@@ -749,8 +698,8 @@ async def generate_image(request: T2IRequest):
|
|
|
749
698
|
# Add prompts and ensure types for specific args
|
|
750
699
|
pipeline_args["prompt"] = request.prompt
|
|
751
700
|
pipeline_args["negative_prompt"] = request.negative_prompt
|
|
752
|
-
pipeline_args["width"] = int(pipeline_args.get("width",
|
|
753
|
-
pipeline_args["height"] = int(pipeline_args.get("height",
|
|
701
|
+
pipeline_args["width"] = int(pipeline_args.get("width", 1024))
|
|
702
|
+
pipeline_args["height"] = int(pipeline_args.get("height", 1024))
|
|
754
703
|
pipeline_args["num_inference_steps"] = int(pipeline_args.get("num_inference_steps", 25))
|
|
755
704
|
pipeline_args["guidance_scale"] = float(pipeline_args.get("guidance_scale", 7.0))
|
|
756
705
|
|
|
@@ -800,6 +749,8 @@ async def generate_image(request: T2IRequest):
|
|
|
800
749
|
async def edit_image(request: EditRequestJSON):
|
|
801
750
|
manager = None
|
|
802
751
|
temp_config = None
|
|
752
|
+
ASCIIColors.info(f"Received /edit_image request with {len(request.images_b64)} image(s).")
|
|
753
|
+
ASCIIColors.info(request.params)
|
|
803
754
|
try:
|
|
804
755
|
if "model_name" in request.params and request.params["model_name"]:
|
|
805
756
|
temp_config = state.config.copy()
|
|
@@ -843,7 +794,7 @@ async def edit_image(request: EditRequestJSON):
|
|
|
843
794
|
edit_mode = pipeline_args.get("edit_mode", "fusion")
|
|
844
795
|
if edit_mode == "fusion": pipeline_args["image"] = pil_images
|
|
845
796
|
else:
|
|
846
|
-
pipeline_args.update({"image": pil_images[0]
|
|
797
|
+
pipeline_args.update({"image": pil_images[0]})
|
|
847
798
|
|
|
848
799
|
log_args = {k: v for k, v in pipeline_args.items() if k not in ['generator', 'image', 'mask_image']}
|
|
849
800
|
if pipeline_args.get("generator"): log_args['generator'] = f"<torch.Generator(seed={seed})>"
|
|
@@ -989,4 +940,4 @@ if __name__ == "__main__":
|
|
|
989
940
|
else:
|
|
990
941
|
ASCIIColors.info(f"Detected device: {state.config['device']}")
|
|
991
942
|
|
|
992
|
-
uvicorn.run(app, host=args.host, port=args.port, reload=False)
|
|
943
|
+
uvicorn.run(app, host=args.host, port=args.port, reload=False)
|
|
@@ -69,7 +69,10 @@ def _load_image_from_str(image_str: str) -> bytes:
|
|
|
69
69
|
|
|
70
70
|
class GeminiTTIBinding_Impl(LollmsTTIBinding):
|
|
71
71
|
def __init__(self, **kwargs):
|
|
72
|
-
|
|
72
|
+
# Prioritize 'model_name' but accept 'model' as an alias from config files.
|
|
73
|
+
if 'model' in kwargs and 'model_name' not in kwargs:
|
|
74
|
+
kwargs['model_name'] = kwargs.pop('model')
|
|
75
|
+
super().__init__(binding_name=BindingName, config=kwargs)
|
|
73
76
|
self.auth_method = kwargs.get("auth_method", "vertex_ai")
|
|
74
77
|
self.client: Optional[Any] = None
|
|
75
78
|
self.available_models = []
|
|
@@ -29,8 +29,11 @@ class LeonardoAITTIBinding(LollmsTTIBinding):
|
|
|
29
29
|
"""Leonardo.ai TTI binding for LoLLMS"""
|
|
30
30
|
|
|
31
31
|
def __init__(self, **kwargs):
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
# Prioritize 'model_name' but accept 'model' as an alias from config files.
|
|
33
|
+
if 'model' in kwargs and 'model_name' not in kwargs:
|
|
34
|
+
kwargs['model_name'] = kwargs.pop('model')
|
|
35
|
+
super().__init__(binding_name=BindingName, config=kwargs)
|
|
36
|
+
|
|
34
37
|
self.api_key = self.config.get("api_key") or os.environ.get("LEONARDO_API_KEY")
|
|
35
38
|
if not self.api_key:
|
|
36
39
|
raise ValueError("Leonardo.ai API key is required.")
|
|
@@ -23,7 +23,10 @@ class LollmsWebuiTTIBinding_Impl(LollmsTTIBinding):
|
|
|
23
23
|
service_key (Optional[str]): Authentication key (used for client_id verification).
|
|
24
24
|
verify_ssl_certificate (bool): Whether to verify SSL certificates.
|
|
25
25
|
"""
|
|
26
|
-
|
|
26
|
+
# Prioritize 'model_name' but accept 'model' as an alias from config files.
|
|
27
|
+
if 'model' in kwargs and 'model_name' not in kwargs:
|
|
28
|
+
kwargs['model_name'] = kwargs.pop('model')
|
|
29
|
+
super().__init__(binding_name=BindingName, config=kwargs)
|
|
27
30
|
|
|
28
31
|
# Extract parameters from kwargs, providing defaults
|
|
29
32
|
self.host_address = kwargs.get("host_address", "http://localhost:9600") # Default LOLLMS host
|
|
@@ -27,7 +27,10 @@ class NovitaAITTIBinding(LollmsTTIBinding):
|
|
|
27
27
|
"""Novita.ai TTI binding for LoLLMS"""
|
|
28
28
|
|
|
29
29
|
def __init__(self, **kwargs):
|
|
30
|
-
|
|
30
|
+
# Prioritize 'model_name' but accept 'model' as an alias from config files.
|
|
31
|
+
if 'model' in kwargs and 'model_name' not in kwargs:
|
|
32
|
+
kwargs['model_name'] = kwargs.pop('model')
|
|
33
|
+
super().__init__(binding_name=BindingName, config=kwargs)
|
|
31
34
|
self.config = kwargs
|
|
32
35
|
self.api_key = self.config.get("api_key") or os.environ.get("NOVITA_API_KEY")
|
|
33
36
|
if not self.api_key:
|
|
@@ -6,7 +6,7 @@ from io import BytesIO
|
|
|
6
6
|
from ascii_colors import trace_exception
|
|
7
7
|
from openai import OpenAI
|
|
8
8
|
from lollms_client.lollms_tti_binding import LollmsTTIBinding
|
|
9
|
-
|
|
9
|
+
import os
|
|
10
10
|
BindingName = "OpenAITTIBinding"
|
|
11
11
|
|
|
12
12
|
|
|
@@ -50,19 +50,18 @@ class OpenAITTIBinding(LollmsTTIBinding):
|
|
|
50
50
|
|
|
51
51
|
def __init__(
|
|
52
52
|
self,
|
|
53
|
-
model: str = "gpt-image-1",
|
|
54
|
-
api_key: Optional[str] = None,
|
|
55
|
-
size: str = "1024x1024",
|
|
56
|
-
n: int = 1,
|
|
57
|
-
quality: str = "standard",
|
|
58
53
|
**kwargs,
|
|
59
54
|
):
|
|
60
|
-
|
|
55
|
+
# Prioritize 'model_name' but accept 'model' as an alias from config files.
|
|
56
|
+
if 'model' in kwargs and 'model_name' not in kwargs:
|
|
57
|
+
kwargs['model_name'] = kwargs.pop('model')
|
|
58
|
+
super().__init__(binding_name=BindingName, config=kwargs)
|
|
59
|
+
self.client = OpenAI(api_key=kwargs.get("api_key" or os.environ.get("OPENAI_API_KEY")))
|
|
61
60
|
self.global_params = {
|
|
62
|
-
"model":
|
|
63
|
-
"size": size,
|
|
64
|
-
"n": n,
|
|
65
|
-
"quality": quality,
|
|
61
|
+
"model": kwargs.get("model_name") or "gpt-image-1",
|
|
62
|
+
"size": kwargs.get("size", "1024x1024"),
|
|
63
|
+
"n": kwargs.get("n", 1),
|
|
64
|
+
"quality": kwargs.get("quality", "standard"),
|
|
66
65
|
}
|
|
67
66
|
|
|
68
67
|
def _resolve_param(self, name: str, kwargs: Dict[str, Any], default: Any) -> Any:
|
|
@@ -33,8 +33,10 @@ class StabilityAITTIBinding(LollmsTTIBinding):
|
|
|
33
33
|
"""Stability AI TTI binding for LoLLMS"""
|
|
34
34
|
|
|
35
35
|
def __init__(self, **kwargs):
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
# Prioritize 'model_name' but accept 'model' as an alias from config files.
|
|
37
|
+
if 'model' in kwargs and 'model_name' not in kwargs:
|
|
38
|
+
kwargs['model_name'] = kwargs.pop('model')
|
|
39
|
+
super().__init__(binding_name=BindingName, config=kwargs)
|
|
38
40
|
self.api_key = self.config.get("api_key") or os.environ.get("STABILITY_API_KEY")
|
|
39
41
|
if not self.api_key:
|
|
40
42
|
raise ValueError("Stability AI API key is required. Please set it in the configuration or as STABILITY_API_KEY environment variable.")
|
|
@@ -75,21 +75,16 @@ DEFAULT_AUDIOCRAFT_MODELS = [
|
|
|
75
75
|
|
|
76
76
|
class AudioCraftTTMBinding(LollmsTTMBinding):
|
|
77
77
|
def __init__(self,
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
service_key: Optional[str] = None, # Not used by local binding
|
|
84
|
-
verify_ssl_certificate: bool = True,# Not used by local binding
|
|
85
|
-
**kwargs): # Catch-all for future compatibility or specific audiocraft params
|
|
86
|
-
|
|
87
|
-
super().__init__(binding_name="audiocraft")
|
|
78
|
+
**kwargs):
|
|
79
|
+
# Prioritize 'model_name' but accept 'model' as an alias from config files.
|
|
80
|
+
if 'model' in kwargs and 'model_name' not in kwargs:
|
|
81
|
+
kwargs['model_name'] = kwargs.pop('model')
|
|
82
|
+
super().__init__(binding_name=BindingName, config=kwargs)
|
|
88
83
|
|
|
89
84
|
if not _audiocraft_installed_with_correct_torch:
|
|
90
85
|
raise ImportError(f"AudioCraft TTM binding dependencies not met. Please ensure 'audiocraft', 'torch', 'torchaudio', 'scipy', 'numpy' are installed. Error: {_audiocraft_installation_error}")
|
|
91
86
|
|
|
92
|
-
self.device = device
|
|
87
|
+
self.device = kwargs.get("device") # "cuda", "mps", "cpu", or None for auto-detect
|
|
93
88
|
if self.device is None: # Auto-detect if not specified by user
|
|
94
89
|
if torch.cuda.is_available():
|
|
95
90
|
self.device = "cuda"
|
|
@@ -117,7 +112,7 @@ class AudioCraftTTMBinding(LollmsTTMBinding):
|
|
|
117
112
|
ASCIIColors.warning(f"Unsupported output_format '{self.output_format}'. Defaulting to 'wav'.")
|
|
118
113
|
self.output_format = "wav"
|
|
119
114
|
|
|
120
|
-
self._load_audiocraft_model(model_name)
|
|
115
|
+
self._load_audiocraft_model(kwargs.get("model_name") or "facebook/musicgen-small")
|
|
121
116
|
|
|
122
117
|
def _load_audiocraft_model(self, model_name_to_load: str):
|
|
123
118
|
if self.model is not None and self.loaded_model_name == model_name_to_load:
|
|
@@ -16,9 +16,13 @@ BindingName = "BeatovenAITTMBinding"
|
|
|
16
16
|
class BeatovenAITTMBinding(LollmsTTMBinding):
|
|
17
17
|
"""A Text-to-Music binding for the Beatoven.ai API."""
|
|
18
18
|
|
|
19
|
-
def __init__(self,
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
def __init__(self,
|
|
20
|
+
**kwargs):
|
|
21
|
+
# Prioritize 'model_name' but accept 'model' as an alias from config files.
|
|
22
|
+
if 'model' in kwargs and 'model_name' not in kwargs:
|
|
23
|
+
kwargs['model_name'] = kwargs.pop('model')
|
|
24
|
+
super().__init__(binding_name=BindingName, config=kwargs)
|
|
25
|
+
self.api_key = self.config.get("api_key") or os.environ.get("BEATOVEN_API_KEY")
|
|
22
26
|
if not self.api_key:
|
|
23
27
|
raise ValueError("Beatoven.ai API key is required. Please set it in config or as BEATOVEN_API_KEY env var.")
|
|
24
28
|
self.base_url = "https://api.beatoven.ai/api/v1"
|