lollms-client 0.33.0__py3-none-any.whl → 1.1.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.

Files changed (74) hide show
  1. lollms_client/__init__.py +1 -1
  2. lollms_client/llm_bindings/azure_openai/__init__.py +6 -10
  3. lollms_client/llm_bindings/claude/__init__.py +4 -7
  4. lollms_client/llm_bindings/gemini/__init__.py +3 -7
  5. lollms_client/llm_bindings/grok/__init__.py +3 -7
  6. lollms_client/llm_bindings/groq/__init__.py +4 -6
  7. lollms_client/llm_bindings/hugging_face_inference_api/__init__.py +4 -6
  8. lollms_client/llm_bindings/litellm/__init__.py +15 -6
  9. lollms_client/llm_bindings/llamacpp/__init__.py +27 -9
  10. lollms_client/llm_bindings/lollms/__init__.py +24 -14
  11. lollms_client/llm_bindings/lollms_webui/__init__.py +6 -12
  12. lollms_client/llm_bindings/mistral/__init__.py +3 -5
  13. lollms_client/llm_bindings/ollama/__init__.py +6 -11
  14. lollms_client/llm_bindings/open_router/__init__.py +4 -6
  15. lollms_client/llm_bindings/openai/__init__.py +7 -14
  16. lollms_client/llm_bindings/openllm/__init__.py +12 -12
  17. lollms_client/llm_bindings/pythonllamacpp/__init__.py +1 -1
  18. lollms_client/llm_bindings/tensor_rt/__init__.py +8 -13
  19. lollms_client/llm_bindings/transformers/__init__.py +14 -6
  20. lollms_client/llm_bindings/vllm/__init__.py +16 -12
  21. lollms_client/lollms_core.py +303 -490
  22. lollms_client/lollms_discussion.py +431 -78
  23. lollms_client/lollms_llm_binding.py +192 -381
  24. lollms_client/lollms_mcp_binding.py +33 -2
  25. lollms_client/lollms_tti_binding.py +107 -2
  26. lollms_client/mcp_bindings/local_mcp/__init__.py +3 -2
  27. lollms_client/mcp_bindings/remote_mcp/__init__.py +6 -5
  28. lollms_client/mcp_bindings/standard_mcp/__init__.py +3 -5
  29. lollms_client/stt_bindings/lollms/__init__.py +6 -8
  30. lollms_client/stt_bindings/whisper/__init__.py +2 -4
  31. lollms_client/stt_bindings/whispercpp/__init__.py +15 -16
  32. lollms_client/tti_bindings/dalle/__init__.py +50 -29
  33. lollms_client/tti_bindings/diffusers/__init__.py +227 -439
  34. lollms_client/tti_bindings/gemini/__init__.py +320 -0
  35. lollms_client/tti_bindings/lollms/__init__.py +8 -9
  36. lollms_client-1.1.0.dist-info/METADATA +1214 -0
  37. lollms_client-1.1.0.dist-info/RECORD +69 -0
  38. {lollms_client-0.33.0.dist-info → lollms_client-1.1.0.dist-info}/top_level.txt +0 -2
  39. examples/article_summary/article_summary.py +0 -58
  40. examples/console_discussion/console_app.py +0 -266
  41. examples/console_discussion.py +0 -448
  42. examples/deep_analyze/deep_analyse.py +0 -30
  43. examples/deep_analyze/deep_analyze_multiple_files.py +0 -32
  44. examples/function_calling_with_local_custom_mcp.py +0 -250
  45. examples/generate_a_benchmark_for_safe_store.py +0 -89
  46. examples/generate_and_speak/generate_and_speak.py +0 -251
  47. examples/generate_game_sfx/generate_game_fx.py +0 -240
  48. examples/generate_text_with_multihop_rag_example.py +0 -210
  49. examples/gradio_chat_app.py +0 -228
  50. examples/gradio_lollms_chat.py +0 -259
  51. examples/internet_search_with_rag.py +0 -226
  52. examples/lollms_chat/calculator.py +0 -59
  53. examples/lollms_chat/derivative.py +0 -48
  54. examples/lollms_chat/test_openai_compatible_with_lollms_chat.py +0 -12
  55. examples/lollms_discussions_test.py +0 -155
  56. examples/mcp_examples/external_mcp.py +0 -267
  57. examples/mcp_examples/local_mcp.py +0 -171
  58. examples/mcp_examples/openai_mcp.py +0 -203
  59. examples/mcp_examples/run_remote_mcp_example_v2.py +0 -290
  60. examples/mcp_examples/run_standard_mcp_example.py +0 -204
  61. examples/simple_text_gen_test.py +0 -173
  62. examples/simple_text_gen_with_image_test.py +0 -178
  63. examples/test_local_models/local_chat.py +0 -9
  64. examples/text_2_audio.py +0 -77
  65. examples/text_2_image.py +0 -144
  66. examples/text_2_image_diffusers.py +0 -274
  67. examples/text_and_image_2_audio.py +0 -59
  68. examples/text_gen.py +0 -30
  69. examples/text_gen_system_prompt.py +0 -29
  70. lollms_client-0.33.0.dist-info/METADATA +0 -854
  71. lollms_client-0.33.0.dist-info/RECORD +0 -101
  72. test/test_lollms_discussion.py +0 -368
  73. {lollms_client-0.33.0.dist-info → lollms_client-1.1.0.dist-info}/WHEEL +0 -0
  74. {lollms_client-0.33.0.dist-info → lollms_client-1.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,320 @@
1
+ # lollms_client/tti_bindings/gemini/__init__.py
2
+ import sys
3
+ from typing import Optional, List, Dict, Any, Union
4
+ import os
5
+
6
+ from lollms_client.lollms_tti_binding import LollmsTTIBinding
7
+ from ascii_colors import trace_exception, ASCIIColors
8
+ import math
9
+
10
+ # --- SDK & Dependency Management ---
11
+ try:
12
+ import pipmaster as pm
13
+ # Ensure both potential SDKs and Pillow are available
14
+ pm.ensure_packages(['google-cloud-aiplatform', 'google-generativeai', 'Pillow'])
15
+ except ImportError:
16
+ pass # pipmaster is optional
17
+
18
+ # Attempt to import Vertex AI (google-cloud-aiplatform)
19
+ try:
20
+ import vertexai
21
+ from vertexai.preview.vision_models import ImageGenerationModel
22
+ from google.api_core import exceptions as google_exceptions
23
+ VERTEX_AI_AVAILABLE = True
24
+ except ImportError:
25
+ VERTEX_AI_AVAILABLE = False
26
+
27
+ # Attempt to import Gemini API (google-generativeai)
28
+ try:
29
+ from google import genai
30
+ from google.genai import types as genai_types
31
+ GEMINI_API_AVAILABLE = True
32
+ except ImportError:
33
+ GEMINI_API_AVAILABLE = False
34
+
35
+ # Defines the binding name for the manager
36
+ BindingName = "GeminiTTIBinding_Impl"
37
+
38
+ # Known Imagen models for each service
39
+ IMAGEN_VERTEX_MODELS = ["imagegeneration@006", "imagegeneration@005", "imagegeneration@002"]
40
+ IMAGEN_GEMINI_API_MODELS = ["imagen-3", "gemini-1.5-flash-preview-0514"] # Short names are often aliases
41
+ GEMINI_API_KEY_ENV_VAR = "GEMINI_API_KEY"
42
+
43
+ class GeminiTTIBinding_Impl(LollmsTTIBinding):
44
+ """
45
+ Concrete implementation of LollmsTTIBinding for Google's Imagen models.
46
+ Supports both Vertex AI (project_id) and Gemini API (api_key) authentication.
47
+ """
48
+ def __init__(self, **kwargs):
49
+ """
50
+ Initialize the Gemini (Vertex AI / API) TTI binding.
51
+
52
+ Args:
53
+ **kwargs: Configuration parameters.
54
+ - auth_method (str): "vertex_ai" or "api_key". (Required)
55
+ - project_id (str): Google Cloud project ID (for vertex_ai).
56
+ - location (str): Google Cloud region (for vertex_ai).
57
+ - service_key (str): Gemini API Key (for api_key).
58
+ - model_name (str): The Imagen model to use.
59
+ - default_seed (int): Default seed for generation (-1 for random).
60
+ - default_guidance_scale (float): Default guidance scale (CFG).
61
+ """
62
+ super().__init__(binding_name="gemini")
63
+
64
+ # Core settings
65
+ self.auth_method = kwargs.get("auth_method", "vertex_ai") # Default to vertex_ai for backward compatibility
66
+
67
+ # Vertex AI specific settings
68
+ self.project_id = kwargs.get("project_id")
69
+ self.location = kwargs.get("location", "us-central1")
70
+
71
+ # Gemini API specific settings
72
+ self.gemini_api_key = kwargs.get("service_key")
73
+
74
+ # Common settings
75
+ self.model_name = kwargs.get("model_name")
76
+ self.default_seed = int(kwargs.get("default_seed", -1))
77
+ self.default_guidance_scale = float(kwargs.get("default_guidance_scale", 7.5))
78
+ self.client_id = kwargs.get("client_id", "gemini_client_user")
79
+
80
+ # The actual client/model instance
81
+ self.client: Optional[Any] = None
82
+
83
+ # --- Validation and Initialization ---
84
+ if self.auth_method == "vertex_ai":
85
+ if not VERTEX_AI_AVAILABLE:
86
+ raise ImportError("Vertex AI authentication selected, but 'google-cloud-aiplatform' is not installed.")
87
+ if not self.project_id:
88
+ raise ValueError("For 'vertex_ai' auth, a Google Cloud 'project_id' is required.")
89
+ if not self.model_name:
90
+ self.model_name = IMAGEN_VERTEX_MODELS[0]
91
+ elif self.auth_method == "api_key":
92
+ if not GEMINI_API_AVAILABLE:
93
+ raise ImportError("API Key authentication selected, but 'google-generativeai' is not installed.")
94
+
95
+ # Resolve API key from kwargs or environment variable
96
+ if not self.gemini_api_key:
97
+ ASCIIColors.info(f"API key not provided directly, checking environment variable '{GEMINI_API_KEY_ENV_VAR}'...")
98
+ self.gemini_api_key = os.environ.get(GEMINI_API_KEY_ENV_VAR)
99
+
100
+ if not self.gemini_api_key:
101
+ raise ValueError(f"For 'api_key' auth, a Gemini API Key is required. Provide it as 'service_key' or set the '{GEMINI_API_KEY_ENV_VAR}' environment variable.")
102
+
103
+ if not self.model_name:
104
+ self.model_name = IMAGEN_GEMINI_API_MODELS[0]
105
+ else:
106
+ raise ValueError(f"Invalid auth_method: '{self.auth_method}'. Must be 'vertex_ai' or 'api_key'.")
107
+
108
+ self._initialize_client()
109
+
110
+ def _initialize_client(self):
111
+ """Initializes the appropriate client based on the selected auth_method."""
112
+ ASCIIColors.info(f"Initializing Google client with auth method: '{self.auth_method}'...")
113
+ try:
114
+ if self.auth_method == "vertex_ai":
115
+ vertexai.init(project=self.project_id, location=self.location)
116
+ self.client = ImageGenerationModel.from_pretrained(self.model_name)
117
+ ASCIIColors.green(f"Vertex AI initialized successfully. Project: '{self.project_id}', Model: '{self.model_name}'")
118
+ elif self.auth_method == "api_key":
119
+ genai.configure(api_key=self.gemini_api_key)
120
+ # For the genai SDK, the "client" is the configured module itself,
121
+ # and we specify the model per-call. Let's store the genai module.
122
+ self.client = genai
123
+ ASCIIColors.green(f"Gemini API configured successfully. Model to be used: '{self.model_name}'")
124
+ except google_exceptions.PermissionDenied as e:
125
+ trace_exception(e)
126
+ raise Exception(
127
+ "Authentication failed. For Vertex AI, run 'gcloud auth application-default login'. For API Key, check if the key is valid and has permissions."
128
+ ) from e
129
+ except Exception as e:
130
+ trace_exception(e)
131
+ raise Exception(f"Failed to initialize Google client: {e}") from e
132
+
133
+ def _validate_dimensions_vertex(self, width: int, height: int) -> None:
134
+ """Validates image dimensions against Vertex AI Imagen constraints."""
135
+ if not (256 <= width <= 1536 and width % 8 == 0):
136
+ raise ValueError(f"Invalid width for Vertex AI: {width}. Must be 256-1536 and a multiple of 8.")
137
+ if not (256 <= height <= 1536 and height % 8 == 0):
138
+ raise ValueError(f"Invalid height for Vertex AI: {height}. Must be 256-1536 and a multiple of 8.")
139
+
140
+ def _get_aspect_ratio_for_api(self, width: int, height: int) -> str:
141
+ """Finds the closest supported aspect ratio string for the Gemini API."""
142
+ ratios = {"1:1": 1.0, "16:9": 16/9, "9:16": 9/16, "4:3": 4/3, "3:4": 3/4}
143
+ target_ratio = width / height
144
+ closest_ratio_name = min(ratios, key=lambda r: abs(ratios[r] - target_ratio))
145
+ ASCIIColors.info(f"Converted {width}x{height} to closest aspect ratio: '{closest_ratio_name}' for Gemini API.")
146
+ return closest_ratio_name
147
+
148
+ def generate_image(self,
149
+ prompt: str,
150
+ negative_prompt: Optional[str] = "",
151
+ width: int = 1024,
152
+ height: int = 1024,
153
+ **kwargs) -> bytes:
154
+ """
155
+ Generates image data using the configured Google Imagen model.
156
+ """
157
+ if not self.client:
158
+ raise RuntimeError("Google client is not initialized. Cannot generate image.")
159
+
160
+ # Use overrides from kwargs, otherwise instance defaults
161
+ seed = kwargs.get("seed", self.default_seed)
162
+ guidance_scale = kwargs.get("guidance_scale", self.default_guidance_scale)
163
+ gen_seed = seed if seed != -1 else None
164
+
165
+ final_prompt = prompt
166
+ if negative_prompt:
167
+ final_prompt = f"{prompt}. Do not include: {negative_prompt}."
168
+
169
+ ASCIIColors.info(f"Generating image with prompt: '{final_prompt[:100]}...'")
170
+
171
+ try:
172
+ if self.auth_method == "vertex_ai":
173
+ self._validate_dimensions_vertex(width, height)
174
+ gen_params = {
175
+ "prompt": final_prompt,
176
+ "number_of_images": 1,
177
+ "width": width,
178
+ "height": height,
179
+ "guidance_scale": guidance_scale,
180
+ }
181
+ if gen_seed is not None:
182
+ gen_params["seed"] = gen_seed
183
+
184
+ ASCIIColors.debug(f"Vertex AI generation parameters: {gen_params}")
185
+ response = self.client.generate_images(**gen_params)
186
+
187
+ if not response.images:
188
+ raise Exception("Image generation resulted in no images (Vertex AI). Check safety filters.")
189
+
190
+ return response.images[0]._image_bytes
191
+
192
+ elif self.auth_method == "api_key":
193
+ aspect_ratio = self._get_aspect_ratio_for_api(width, height)
194
+ gen_params = {
195
+ "model": self.model_name,
196
+ "prompt": final_prompt,
197
+ "number_of_images": 1,
198
+ "aspect_ratio": aspect_ratio
199
+ # Note: seed and guidance_scale are not standard in this simpler API call
200
+ }
201
+ ASCIIColors.debug(f"Gemini API generation parameters: {gen_params}")
202
+ response = self.client.generate_image(**gen_params)
203
+
204
+ if not response.images:
205
+ raise Exception("Image generation resulted in no images (Gemini API). Check safety filters.")
206
+
207
+ return response.images[0].image_bytes
208
+
209
+ except (google_exceptions.InvalidArgument, AttributeError) as e:
210
+ trace_exception(e)
211
+ raise ValueError(f"Invalid argument sent to Google API: {e}") from e
212
+ except google_exceptions.GoogleAPICallError as e:
213
+ trace_exception(e)
214
+ raise Exception(f"A Google API call error occurred: {e}") from e
215
+ except Exception as e:
216
+ trace_exception(e)
217
+ raise Exception(f"Imagen image generation failed: {e}") from e
218
+
219
+ def list_services(self, **kwargs) -> List[Dict[str, str]]:
220
+ """Lists available Imagen models for the current auth method."""
221
+ models = IMAGEN_VERTEX_MODELS if self.auth_method == "vertex_ai" else IMAGEN_GEMINI_API_MODELS
222
+ service_name = "Vertex AI" if self.auth_method == "vertex_ai" else "Gemini API"
223
+ return [
224
+ {
225
+ "name": name,
226
+ "caption": f"Google Imagen ({name}) via {service_name}",
227
+ "help": "High-quality text-to-image model from Google."
228
+ } for name in models
229
+ ]
230
+
231
+ def get_settings(self, **kwargs) -> List[Dict[str, Any]]:
232
+ """Retrieves the current configurable settings for the binding."""
233
+ settings = [
234
+ {"name": "auth_method", "type": "str", "value": self.auth_method, "description": "Authentication method to use.", "options": ["vertex_ai", "api_key"], "category": "Authentication"},
235
+ ]
236
+ if self.auth_method == "vertex_ai":
237
+ settings.extend([
238
+ {"name": "project_id", "type": "str", "value": self.project_id, "description": "Your Google Cloud project ID.", "category": "Authentication"},
239
+ {"name": "location", "type": "str", "value": self.location, "description": "Google Cloud region (e.g., 'us-central1').", "category": "Authentication"},
240
+ {"name": "model_name", "type": "str", "value": self.model_name, "description": "Default Imagen model for generation.", "options": IMAGEN_VERTEX_MODELS, "category": "Model Configuration"},
241
+ ])
242
+ elif self.auth_method == "api_key":
243
+ settings.extend([
244
+ {"name": "api_key_status", "type": "str", "value": "Set" if self.gemini_api_key else "Not Set", "description": f"Gemini API Key status (set at initialization via service_key or '{GEMINI_API_KEY_ENV_VAR}').", "category": "Authentication", "read_only": True},
245
+ {"name": "model_name", "type": "str", "value": self.model_name, "description": "Default Imagen model for generation.", "options": IMAGEN_GEMINI_API_MODELS, "category": "Model Configuration"},
246
+ ])
247
+
248
+ settings.extend([
249
+ {"name": "default_seed", "type": "int", "value": self.default_seed, "description": "Default seed (-1 for random).", "category": "Image Generation Defaults"},
250
+ {"name": "default_guidance_scale", "type": "float", "value": self.default_guidance_scale, "description": "Default guidance scale (CFG). (Vertex AI only)", "category": "Image Generation Defaults"},
251
+ ])
252
+ return settings
253
+
254
+ def set_settings(self, settings: Union[Dict[str, Any], List[Dict[str, Any]]], **kwargs) -> bool:
255
+ """Applies new settings. Re-initializes the client if core settings change."""
256
+ applied_some_settings = False
257
+ settings_dict = {item["name"]: item["value"] for item in settings} if isinstance(settings, list) else settings
258
+
259
+ needs_reinit = False
260
+
261
+ # Phase 1: Check for auth_method or core credential changes
262
+ if "auth_method" in settings_dict and self.auth_method != settings_dict["auth_method"]:
263
+ self.auth_method = settings_dict["auth_method"]
264
+ ASCIIColors.info(f"Authentication method changed to: {self.auth_method}")
265
+ # Reset model to a valid default for the new method
266
+ if self.auth_method == "vertex_ai":
267
+ self.model_name = IMAGEN_VERTEX_MODELS[0]
268
+ else:
269
+ self.model_name = IMAGEN_GEMINI_API_MODELS[0]
270
+ ASCIIColors.info(f"Model name reset to default for new auth method: {self.model_name}")
271
+ needs_reinit = True
272
+ applied_some_settings = True
273
+
274
+ if self.auth_method == "vertex_ai":
275
+ if "project_id" in settings_dict and self.project_id != settings_dict["project_id"]:
276
+ self.project_id = settings_dict["project_id"]
277
+ needs_reinit = True; applied_some_settings = True
278
+ if "location" in settings_dict and self.location != settings_dict["location"]:
279
+ self.location = settings_dict["location"]
280
+ needs_reinit = True; applied_some_settings = True
281
+ # API key is not settable after init, so we don't check for it here.
282
+
283
+ # Phase 2: Apply other settings
284
+ current_models = IMAGEN_VERTEX_MODELS if self.auth_method == "vertex_ai" else IMAGEN_GEMINI_API_MODELS
285
+ if "model_name" in settings_dict:
286
+ new_model = settings_dict["model_name"]
287
+ if new_model not in current_models:
288
+ ASCIIColors.warning(f"Invalid model '{new_model}' for auth method '{self.auth_method}'. Keeping '{self.model_name}'.")
289
+ elif self.model_name != new_model:
290
+ self.model_name = new_model
291
+ needs_reinit = True; applied_some_settings = True
292
+
293
+ if "default_seed" in settings_dict and self.default_seed != int(settings_dict["default_seed"]):
294
+ self.default_seed = int(settings_dict["default_seed"])
295
+ applied_some_settings = True
296
+ if "default_guidance_scale" in settings_dict and self.default_guidance_scale != float(settings_dict["default_guidance_scale"]):
297
+ self.default_guidance_scale = float(settings_dict["default_guidance_scale"])
298
+ applied_some_settings = True
299
+
300
+ # Phase 3: Re-initialize if needed
301
+ if needs_reinit:
302
+ try:
303
+ self._initialize_client()
304
+ except Exception as e:
305
+ ASCIIColors.error(f"Failed to re-initialize client with new settings: {e}")
306
+ return False
307
+
308
+ return applied_some_settings
309
+
310
+ def listModels(self) -> list:
311
+ """Lists available Imagen models in a standardized format."""
312
+ models = IMAGEN_VERTEX_MODELS if self.auth_method == "vertex_ai" else IMAGEN_GEMINI_API_MODELS
313
+ return [
314
+ {
315
+ 'model_name': name,
316
+ 'display_name': f"Imagen ({name})",
317
+ 'description': f"Google's Imagen model, version {name}",
318
+ 'owned_by': 'Google'
319
+ } for name in models
320
+ ]
@@ -9,15 +9,12 @@ from ascii_colors import trace_exception, ASCIIColors
9
9
  import json # Added for potential error parsing
10
10
 
11
11
  # Defines the binding name for the manager
12
- BindingName = "LollmsTTIBinding_Impl"
13
-
14
- class LollmsTTIBinding_Impl(LollmsTTIBinding):
12
+ BindingName = "LollmsWebuiTTIBinding_Impl"
13
+ class LollmsWebuiTTIBinding_Impl(LollmsTTIBinding):
15
14
  """Concrete implementation of the LollmsTTIBinding for the standard LOLLMS server."""
16
15
 
17
16
  def __init__(self,
18
- host_address: Optional[str] = "http://localhost:9600", # Default LOLLMS host
19
- service_key: Optional[str] = None,
20
- verify_ssl_certificate: bool = True):
17
+ **kwargs):
21
18
  """
22
19
  Initialize the LOLLMS TTI binding.
23
20
 
@@ -27,12 +24,14 @@ class LollmsTTIBinding_Impl(LollmsTTIBinding):
27
24
  verify_ssl_certificate (bool): Whether to verify SSL certificates.
28
25
  """
29
26
  super().__init__(binding_name="lollms")
30
- self.host_address=host_address
31
- self.verify_ssl_certificate = verify_ssl_certificate
27
+
28
+ # Extract parameters from kwargs, providing defaults
29
+ self.host_address = kwargs.get("host_address", "http://localhost:9600") # Default LOLLMS host
30
+ self.verify_ssl_certificate = kwargs.get("verify_ssl_certificate", True)
32
31
 
33
32
  # The 'service_key' here will act as the 'client_id' for TTI requests if provided.
34
33
  # This assumes the client library user provides their LOLLMS client_id here.
35
- self.client_id = service_key
34
+ self.client_id = kwargs.get("service_key", None) # Use service_key or None
36
35
 
37
36
  def _get_client_id(self, **kwargs) -> str:
38
37
  """Helper to get client_id, prioritizing kwargs then instance default."""