glchat-plugin 0.2.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.
- glchat_plugin/__init__.py +1 -0
- glchat_plugin/config/__init__.py +1 -0
- glchat_plugin/config/app_config.py +22 -0
- glchat_plugin/config/constant.py +26 -0
- glchat_plugin/pipeline/__init__.py +1 -0
- glchat_plugin/pipeline/base_pipeline_preset_config.py +36 -0
- glchat_plugin/pipeline/pipeline_handler.py +602 -0
- glchat_plugin/pipeline/pipeline_plugin.py +126 -0
- glchat_plugin/service/__init__.py +1 -0
- glchat_plugin/service/base_user_service.py +82 -0
- glchat_plugin/storage/__init__.py +1 -0
- glchat_plugin/storage/base_anonymizer_storage.py +58 -0
- glchat_plugin/storage/base_chat_history_storage.py +356 -0
- glchat_plugin/tools/__init__.py +21 -0
- glchat_plugin/tools/decorators.py +115 -0
- glchat_plugin-0.2.0.dist-info/METADATA +62 -0
- glchat_plugin-0.2.0.dist-info/RECORD +19 -0
- glchat_plugin-0.2.0.dist-info/WHEEL +5 -0
- glchat_plugin-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
"""Pipeline handler for pipeline builder plugins.
|
|
2
|
+
|
|
3
|
+
This handler manages pipeline builder plugins and provides necessary services.
|
|
4
|
+
|
|
5
|
+
Authors:
|
|
6
|
+
Samuel Lusandi (samuel.lusandi@gdplabs.id)
|
|
7
|
+
Hermes Vincentius Gani (hermes.v.gani@gdplabs.id)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import traceback
|
|
11
|
+
from typing import Any, Type
|
|
12
|
+
|
|
13
|
+
from bosa_core import Plugin
|
|
14
|
+
from bosa_core.plugin.handler import PluginHandler
|
|
15
|
+
from gllm_core.utils import LoggerManager
|
|
16
|
+
from gllm_inference.catalog import LMRequestProcessorCatalog, PromptBuilderCatalog
|
|
17
|
+
from gllm_pipeline.pipeline.pipeline import Pipeline
|
|
18
|
+
from pydantic import BaseModel, ConfigDict
|
|
19
|
+
|
|
20
|
+
from glchat_plugin.config.app_config import AppConfig
|
|
21
|
+
from glchat_plugin.storage.base_chat_history_storage import BaseChatHistoryStorage
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ChatbotConfig(BaseModel):
|
|
25
|
+
"""Chatbot configuration class containing pipeline configs and metadata.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
pipeline_type (str): Type of pipeline to use.
|
|
29
|
+
pipeline_config (dict[str, Any]): Pipeline configuration dictionary.
|
|
30
|
+
prompt_builder_catalogs (dict[str, PromptBuilderCatalog] | None): Mapping of prompt builder catalogs.
|
|
31
|
+
lmrp_catalogs (dict[str, LMRequestProcessorCatalog] | None): Mapping of LM request processor catalogs.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
pipeline_type: str
|
|
35
|
+
pipeline_config: dict[str, Any]
|
|
36
|
+
prompt_builder_catalogs: dict[str, PromptBuilderCatalog] | None
|
|
37
|
+
lmrp_catalogs: dict[str, LMRequestProcessorCatalog] | None
|
|
38
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class PipelinePresetConfig(BaseModel):
|
|
42
|
+
"""Pipeline preset configuration class.
|
|
43
|
+
|
|
44
|
+
Attributes:
|
|
45
|
+
preset_id (str): Unique identifier for the pipeline preset.
|
|
46
|
+
supported_models (list[dict[str, Any]]): List of models (including config) supported by this preset.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
preset_id: str
|
|
50
|
+
supported_models: list[dict[str, Any]]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class ChatbotPresetMapping(BaseModel):
|
|
54
|
+
"""Chatbot preset mapping.
|
|
55
|
+
|
|
56
|
+
Attributes:
|
|
57
|
+
pipeline_type (str): Type of pipeline.
|
|
58
|
+
chatbot_preset_map (dict[str, PipelinePresetConfig]):
|
|
59
|
+
Mapping of chatbot IDs to their pipeline preset configurations.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
pipeline_type: str
|
|
63
|
+
chatbot_preset_map: dict[str, PipelinePresetConfig]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
logger = LoggerManager().get_logger(__name__)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class PipelineHandler(PluginHandler):
|
|
70
|
+
"""Handler for pipeline builder plugins.
|
|
71
|
+
|
|
72
|
+
This handler manages pipeline builder plugins and provides caching for built pipelines.
|
|
73
|
+
|
|
74
|
+
Attributes:
|
|
75
|
+
app_config (AppConfig): Application configuration.
|
|
76
|
+
_activated_configs (dict[str, ChatbotPresetMapping]): Collection of chatbot preset mapping by pipeline types.
|
|
77
|
+
_chatbot_configs (dict[str, ChatbotConfig]): Mapping of chatbot IDs to their configurations.
|
|
78
|
+
_builders (dict[str, Plugin]): Mapping of chatbot IDs to their pipeline builder plugins.
|
|
79
|
+
_plugins (dict[str, Plugin]): Mapping of pipeline types to their plugins.
|
|
80
|
+
_pipeline_cache (dict[tuple[str, str], Pipeline]):
|
|
81
|
+
Cache mapping (chatbot_id, model_id) to Pipeline instances.
|
|
82
|
+
_chatbot_pipeline_keys (dict[str, set[tuple[str, str]]]): Mapping of chatbot IDs to their pipeline keys.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
app_config: AppConfig
|
|
86
|
+
_activated_configs: dict[str, ChatbotPresetMapping] = {}
|
|
87
|
+
_chatbot_configs: dict[str, ChatbotConfig] = {}
|
|
88
|
+
_builders: dict[str, Plugin] = {}
|
|
89
|
+
_plugins: dict[str, Plugin] = {}
|
|
90
|
+
_pipeline_cache: dict[tuple[str, str], Pipeline] = {}
|
|
91
|
+
_chatbot_pipeline_keys: dict[str, set[tuple[str, str]]] = {}
|
|
92
|
+
|
|
93
|
+
def __init__(self, app_config: AppConfig, chat_history_storage: BaseChatHistoryStorage):
|
|
94
|
+
"""Initialize the pipeline handler.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
app_config (AppConfig): Application configuration.
|
|
98
|
+
chat_history_storage (BaseChatHistoryStorage): Chat history storage.
|
|
99
|
+
"""
|
|
100
|
+
self.app_config = app_config
|
|
101
|
+
self.chat_history_storage = chat_history_storage
|
|
102
|
+
self._prepare_pipelines()
|
|
103
|
+
|
|
104
|
+
@classmethod
|
|
105
|
+
def create_injections(cls, instance: "PipelineHandler") -> dict[Type[Any], Any]:
|
|
106
|
+
"""Create injection mappings for pipeline builder plugins.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
instance (PipelineHandler): The handler instance providing injections.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
dict[Type[Any], Any]: Dictionary mapping service types to their instances.
|
|
113
|
+
"""
|
|
114
|
+
return {
|
|
115
|
+
AppConfig: instance.app_config,
|
|
116
|
+
BaseChatHistoryStorage: instance.chat_history_storage,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@classmethod
|
|
120
|
+
def initialize_plugin(cls, instance: "PipelineHandler", plugin: Plugin) -> None:
|
|
121
|
+
"""Initialize plugin-specific resources.
|
|
122
|
+
|
|
123
|
+
This method is called after plugin creation and service injection.
|
|
124
|
+
For each pipeline builder plugin, we build pipelines for all supported models and cache them.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
instance (PipelineHandler): The handler instance.
|
|
128
|
+
plugin (Plugin): The pipeline builder plugin instance.
|
|
129
|
+
"""
|
|
130
|
+
pass
|
|
131
|
+
|
|
132
|
+
@classmethod
|
|
133
|
+
async def ainitialize_plugin(cls, instance: "PipelineHandler", plugin: Plugin) -> None:
|
|
134
|
+
"""Initialize plugin-specific resources.
|
|
135
|
+
|
|
136
|
+
This method is called after plugin creation and service injection.
|
|
137
|
+
For each pipeline builder plugin, we build pipelines for all supported models and cache them.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
instance (PipelineHandler): The handler instance.
|
|
141
|
+
plugin (Plugin): The pipeline builder plugin instance.
|
|
142
|
+
"""
|
|
143
|
+
pipeline_type = plugin.name
|
|
144
|
+
instance._plugins[pipeline_type] = plugin
|
|
145
|
+
|
|
146
|
+
if pipeline_type not in instance._activated_configs:
|
|
147
|
+
return
|
|
148
|
+
|
|
149
|
+
active_config = instance._activated_configs[pipeline_type]
|
|
150
|
+
for chatbot_id, preset in active_config.chatbot_preset_map.items():
|
|
151
|
+
try:
|
|
152
|
+
if pipeline_type != instance._chatbot_configs[chatbot_id].pipeline_type:
|
|
153
|
+
continue
|
|
154
|
+
|
|
155
|
+
await cls._build_plugin(instance, chatbot_id, preset.supported_models, plugin)
|
|
156
|
+
except Exception as e:
|
|
157
|
+
logger.warning(f"Failed when ainit pliugin {traceback.format_exc()}")
|
|
158
|
+
logger.warning(f"Error initializing plugin for chatbot `{chatbot_id}`: {e}")
|
|
159
|
+
|
|
160
|
+
@classmethod
|
|
161
|
+
async def acleanup_plugins(cls, instance: "PipelineHandler") -> None:
|
|
162
|
+
"""Cleanup all plugins.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
instance (PipelineHandler): The handler instance.
|
|
166
|
+
"""
|
|
167
|
+
for plugin in instance._plugins.values():
|
|
168
|
+
try:
|
|
169
|
+
await plugin.cleanup()
|
|
170
|
+
except Exception as e:
|
|
171
|
+
logger.warning(f"Error cleaning up plugin `{plugin.name}`: {e}")
|
|
172
|
+
|
|
173
|
+
@classmethod
|
|
174
|
+
async def _build_plugin(
|
|
175
|
+
cls, instance: "PipelineHandler", chatbot_id: str, supported_models: list[dict[str, Any]], plugin: Plugin
|
|
176
|
+
) -> None:
|
|
177
|
+
"""Build a plugin for the given chatbot.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
instance (PipelineHandler): The handler instance.
|
|
181
|
+
chatbot_id (str): The chatbot ID.
|
|
182
|
+
supported_models (list[dict[str, Any]]): List of models (including config).
|
|
183
|
+
plugin (Plugin): The pipeline builder plugin instance.
|
|
184
|
+
"""
|
|
185
|
+
plugin.prompt_builder_catalogs = instance._chatbot_configs[chatbot_id].prompt_builder_catalogs
|
|
186
|
+
plugin.lmrp_catalogs = instance._chatbot_configs[chatbot_id].lmrp_catalogs
|
|
187
|
+
instance._builders[chatbot_id] = plugin
|
|
188
|
+
|
|
189
|
+
for model in supported_models:
|
|
190
|
+
try:
|
|
191
|
+
model_id = model.get("model_id", model.get("name"))
|
|
192
|
+
if not model_id:
|
|
193
|
+
continue
|
|
194
|
+
|
|
195
|
+
pipeline_config = instance._chatbot_configs[chatbot_id].pipeline_config.copy()
|
|
196
|
+
# use original model name
|
|
197
|
+
pipeline_config["model_name"] = model.get("name", model_id)
|
|
198
|
+
pipeline_config["model_kwargs"] = model.get("model_kwargs", {})
|
|
199
|
+
pipeline_config["model_env_kwargs"] = model.get("model_env_kwargs", {})
|
|
200
|
+
credentials = pipeline_config["model_env_kwargs"].get("credentials")
|
|
201
|
+
if credentials:
|
|
202
|
+
pipeline_config["api_key"] = credentials
|
|
203
|
+
|
|
204
|
+
pipeline = await plugin.build(pipeline_config)
|
|
205
|
+
pipeline_key = (chatbot_id, str(model_id))
|
|
206
|
+
instance._chatbot_pipeline_keys.setdefault(chatbot_id, set()).add(pipeline_key)
|
|
207
|
+
instance._pipeline_cache[pipeline_key] = pipeline
|
|
208
|
+
except Exception as e:
|
|
209
|
+
logger.warning(f"Failed when ainit pliugin {traceback.format_exc()}")
|
|
210
|
+
logger.warning(f"Error building pipeline for chatbot `{chatbot_id}` model `{model_id}`: {e}")
|
|
211
|
+
|
|
212
|
+
def get_pipeline_builder(self, chatbot_id: str) -> Plugin:
|
|
213
|
+
"""Get a pipeline builder instance for the given chatbot.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
chatbot_id (str): The chatbot ID.
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
Plugin: The pipeline builder instance.
|
|
220
|
+
|
|
221
|
+
Raises:
|
|
222
|
+
ValueError: If the chatbot ID is invalid or the model name is not supported.
|
|
223
|
+
"""
|
|
224
|
+
if chatbot_id not in self._builders:
|
|
225
|
+
logger.warning(f"Pipeline builder not found for chatbot `{chatbot_id}`, attempting to rebuild...")
|
|
226
|
+
# Try to rebuild the plugin if it's not found
|
|
227
|
+
self._try_rebuild_plugin(chatbot_id)
|
|
228
|
+
|
|
229
|
+
if chatbot_id not in self._builders:
|
|
230
|
+
raise ValueError(f"Pipeline builder for chatbot `{chatbot_id}` not found and could not be rebuilt")
|
|
231
|
+
|
|
232
|
+
return self._builders[chatbot_id]
|
|
233
|
+
|
|
234
|
+
def _try_rebuild_plugin(self, chatbot_id: str) -> None:
|
|
235
|
+
"""Try to rebuild a plugin for the given chatbot.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
chatbot_id (str): The chatbot ID.
|
|
239
|
+
"""
|
|
240
|
+
try:
|
|
241
|
+
# Check if we have the chatbot configuration
|
|
242
|
+
if chatbot_id not in self._chatbot_configs:
|
|
243
|
+
logger.warning(f"Chatbot configuration not found for `{chatbot_id}`")
|
|
244
|
+
return
|
|
245
|
+
|
|
246
|
+
chatbot_config = self._chatbot_configs[chatbot_id]
|
|
247
|
+
pipeline_type = chatbot_config.pipeline_type
|
|
248
|
+
|
|
249
|
+
# Check if we have the plugin for this pipeline type
|
|
250
|
+
if pipeline_type not in self._plugins:
|
|
251
|
+
logger.warning(f"Plugin not found for pipeline type `{pipeline_type}`")
|
|
252
|
+
return
|
|
253
|
+
|
|
254
|
+
plugin = self._plugins[pipeline_type]
|
|
255
|
+
|
|
256
|
+
# Get supported models from the configuration
|
|
257
|
+
supported_models = list(chatbot_config.pipeline_config.get("supported_models", {}).values())
|
|
258
|
+
|
|
259
|
+
if not supported_models:
|
|
260
|
+
logger.warning(f"No supported models found for chatbot `{chatbot_id}`")
|
|
261
|
+
return
|
|
262
|
+
|
|
263
|
+
# Rebuild the plugin synchronously (this is a simplified version)
|
|
264
|
+
# Set the catalogs
|
|
265
|
+
plugin.prompt_builder_catalogs = chatbot_config.prompt_builder_catalogs
|
|
266
|
+
plugin.lmrp_catalogs = chatbot_config.lmrp_catalogs
|
|
267
|
+
self._builders[chatbot_id] = plugin
|
|
268
|
+
|
|
269
|
+
logger.info(f"Successfully rebuilt pipeline builder for chatbot `{chatbot_id}`")
|
|
270
|
+
|
|
271
|
+
except Exception as e:
|
|
272
|
+
logger.warning(f"Error rebuilding plugin for chatbot `{chatbot_id}`: {e}")
|
|
273
|
+
|
|
274
|
+
async def _async_rebuild_pipeline(self, chatbot_id: str, model_id: str) -> None:
|
|
275
|
+
"""Asynchronously rebuild a pipeline for the given chatbot and model.
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
chatbot_id (str): The chatbot ID.
|
|
279
|
+
model_id (str): The model ID.
|
|
280
|
+
"""
|
|
281
|
+
try:
|
|
282
|
+
# First, ensure we have the pipeline builder
|
|
283
|
+
if chatbot_id not in self._builders:
|
|
284
|
+
await self._async_rebuild_plugin(chatbot_id)
|
|
285
|
+
|
|
286
|
+
if chatbot_id not in self._builders:
|
|
287
|
+
logger.warning(f"Could not rebuild pipeline builder for chatbot `{chatbot_id}`")
|
|
288
|
+
return
|
|
289
|
+
|
|
290
|
+
# Check if we have the chatbot configuration
|
|
291
|
+
if chatbot_id not in self._chatbot_configs:
|
|
292
|
+
logger.warning(f"Chatbot configuration not found for `{chatbot_id}`")
|
|
293
|
+
return
|
|
294
|
+
|
|
295
|
+
chatbot_config = self._chatbot_configs[chatbot_id]
|
|
296
|
+
plugin = self._builders[chatbot_id]
|
|
297
|
+
|
|
298
|
+
# Find the model configuration
|
|
299
|
+
supported_models = list(chatbot_config.pipeline_config.get("supported_models", {}).values())
|
|
300
|
+
model_config = None
|
|
301
|
+
|
|
302
|
+
for model in supported_models:
|
|
303
|
+
if model.get("model_id", model.get("name")) == model_id:
|
|
304
|
+
model_config = model
|
|
305
|
+
break
|
|
306
|
+
if not model_config:
|
|
307
|
+
logger.warning(
|
|
308
|
+
f"Model `{model_id}` not found in supported models "
|
|
309
|
+
f"for chatbot `{chatbot_id}` async rebuild pipeline"
|
|
310
|
+
)
|
|
311
|
+
return
|
|
312
|
+
|
|
313
|
+
# Use the existing _build_plugin method to rebuild the pipeline
|
|
314
|
+
await __class__._build_plugin(self, chatbot_id, [model_config], plugin)
|
|
315
|
+
|
|
316
|
+
logger.info(f"Successfully rebuilt pipeline for chatbot `{chatbot_id}` model `{model_id}`")
|
|
317
|
+
|
|
318
|
+
except Exception as e:
|
|
319
|
+
logger.warning(f"Error rebuilding pipeline for chatbot `{chatbot_id}` model `{model_id}`: {e}")
|
|
320
|
+
|
|
321
|
+
async def aget_pipeline(self, chatbot_id: str, model_id: str) -> Pipeline:
|
|
322
|
+
"""Get a pipeline instance for the given chatbot and model ID (async version).
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
chatbot_id (str): The chatbot ID.
|
|
326
|
+
model_id (str): The model ID to use for inference.
|
|
327
|
+
|
|
328
|
+
Returns:
|
|
329
|
+
Pipeline: The pipeline instance.
|
|
330
|
+
|
|
331
|
+
Raises:
|
|
332
|
+
ValueError: If the chatbot ID is invalid.
|
|
333
|
+
"""
|
|
334
|
+
pipeline_key = (chatbot_id, str(model_id))
|
|
335
|
+
|
|
336
|
+
if pipeline_key not in self._pipeline_cache:
|
|
337
|
+
logger.warning(
|
|
338
|
+
f"Pipeline not found for chatbot `{chatbot_id}` model `{model_id}`, attempting to rebuild..."
|
|
339
|
+
)
|
|
340
|
+
# Try to rebuild the pipeline if it's not found
|
|
341
|
+
await self._async_rebuild_pipeline(chatbot_id, str(model_id))
|
|
342
|
+
|
|
343
|
+
if pipeline_key not in self._pipeline_cache:
|
|
344
|
+
raise ValueError(
|
|
345
|
+
f"Pipeline for chatbot `{chatbot_id}` model `{model_id}` not found and could not be rebuilt"
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
return self._pipeline_cache[pipeline_key]
|
|
349
|
+
|
|
350
|
+
def get_pipeline_config(self, chatbot_id: str) -> dict[str, Any]:
|
|
351
|
+
"""Get the pipeline configuration by chatbot ID.
|
|
352
|
+
|
|
353
|
+
Args:
|
|
354
|
+
chatbot_id (str): The chatbot ID.
|
|
355
|
+
|
|
356
|
+
Returns:
|
|
357
|
+
dict[str, Any]: The pipeline configuration.
|
|
358
|
+
|
|
359
|
+
Raises:
|
|
360
|
+
ValueError: If the chatbot or pipeline is not found.
|
|
361
|
+
"""
|
|
362
|
+
self._validate_pipeline(chatbot_id)
|
|
363
|
+
return self._chatbot_configs[chatbot_id].pipeline_config
|
|
364
|
+
|
|
365
|
+
def get_pipeline_type(self, chatbot_id: str) -> str:
|
|
366
|
+
"""Get the pipeline type for the given chatbot.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
chatbot_id (str): The chatbot ID.
|
|
370
|
+
"""
|
|
371
|
+
return self._chatbot_configs[chatbot_id].pipeline_type
|
|
372
|
+
|
|
373
|
+
def get_use_docproc(self, chatbot_id: str) -> bool:
|
|
374
|
+
"""Get whether DocProc should be used for this chatbot.
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
chatbot_id (str): The chatbot ID.
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
bool: Whether DocProc should be used.
|
|
381
|
+
|
|
382
|
+
Raises:
|
|
383
|
+
ValueError: If the chatbot or pipeline is not found.
|
|
384
|
+
"""
|
|
385
|
+
self._validate_pipeline(chatbot_id)
|
|
386
|
+
config = self._chatbot_configs[chatbot_id].pipeline_config
|
|
387
|
+
return config["use_docproc"]
|
|
388
|
+
|
|
389
|
+
def get_max_file_size(self, chatbot_id: str) -> int | None:
|
|
390
|
+
"""Get maximum file size for the given chatbot.
|
|
391
|
+
|
|
392
|
+
Args:
|
|
393
|
+
chatbot_id (str): The chatbot ID.
|
|
394
|
+
|
|
395
|
+
Returns:
|
|
396
|
+
int | None: The maximum file size if provided.
|
|
397
|
+
|
|
398
|
+
Raises:
|
|
399
|
+
ValueError: If the chatbot or pipeline is not found.
|
|
400
|
+
"""
|
|
401
|
+
self._validate_pipeline(chatbot_id)
|
|
402
|
+
config = self._chatbot_configs[chatbot_id].pipeline_config
|
|
403
|
+
return config.get("max_file_size")
|
|
404
|
+
|
|
405
|
+
async def create_chatbot(self, app_config: AppConfig, chatbot_id: str) -> None:
|
|
406
|
+
"""Create a new chatbot.
|
|
407
|
+
|
|
408
|
+
Args:
|
|
409
|
+
app_config (AppConfig): The application configuration.
|
|
410
|
+
chatbot_id (str): The ID of the chatbot.
|
|
411
|
+
"""
|
|
412
|
+
chatbot_info = app_config.chatbots.get(chatbot_id)
|
|
413
|
+
|
|
414
|
+
if not chatbot_info or not chatbot_info.pipeline:
|
|
415
|
+
logger.warning(f"Pipeline config not found for chatbot `{chatbot_id}`")
|
|
416
|
+
return
|
|
417
|
+
|
|
418
|
+
pipeline_info = chatbot_info.pipeline
|
|
419
|
+
pipeline_type = pipeline_info["type"]
|
|
420
|
+
plugin = self._plugins.get(pipeline_type)
|
|
421
|
+
if not plugin:
|
|
422
|
+
logger.warning(f"Pipeline plugin not found for chatbot `{chatbot_id}`")
|
|
423
|
+
return
|
|
424
|
+
|
|
425
|
+
logger.info(f"Storing pipeline config for chatbot `{chatbot_id}`")
|
|
426
|
+
self._chatbot_configs[chatbot_id] = ChatbotConfig(
|
|
427
|
+
pipeline_type=pipeline_type,
|
|
428
|
+
pipeline_config=pipeline_info["config"],
|
|
429
|
+
prompt_builder_catalogs=pipeline_info["prompt_builder_catalogs"],
|
|
430
|
+
lmrp_catalogs=pipeline_info["lmrp_catalogs"],
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
supported_models = list(pipeline_info["config"].get("supported_models", {}).values())
|
|
434
|
+
await __class__._build_plugin(self, chatbot_id, supported_models, plugin)
|
|
435
|
+
|
|
436
|
+
async def delete_chatbot(self, chatbot_id: str) -> None:
|
|
437
|
+
"""Delete a chatbot.
|
|
438
|
+
|
|
439
|
+
Args:
|
|
440
|
+
chatbot_id (str): The ID of the chatbot.
|
|
441
|
+
"""
|
|
442
|
+
for pipeline_key in self._chatbot_pipeline_keys.get(chatbot_id, set()):
|
|
443
|
+
self._pipeline_cache.pop(pipeline_key, None)
|
|
444
|
+
|
|
445
|
+
self._chatbot_pipeline_keys.pop(chatbot_id, None)
|
|
446
|
+
self._chatbot_configs.pop(chatbot_id, None)
|
|
447
|
+
self._builders.pop(chatbot_id, None)
|
|
448
|
+
|
|
449
|
+
async def update_chatbots(self, app_config: AppConfig, chatbot_ids: list[str]) -> None:
|
|
450
|
+
"""Update the chatbots.
|
|
451
|
+
|
|
452
|
+
Args:
|
|
453
|
+
app_config (AppConfig): The application configuration.
|
|
454
|
+
chatbot_ids (list[str]): The updated chatbot IDs.
|
|
455
|
+
"""
|
|
456
|
+
for chatbot_id in chatbot_ids:
|
|
457
|
+
try:
|
|
458
|
+
chatbot_info = app_config.chatbots.get(chatbot_id)
|
|
459
|
+
if not chatbot_info or not chatbot_info.pipeline:
|
|
460
|
+
logger.warning(f"Pipeline config not found for chatbot `{chatbot_id}`")
|
|
461
|
+
continue
|
|
462
|
+
|
|
463
|
+
pipeline_info = chatbot_info.pipeline
|
|
464
|
+
pipeline_type = pipeline_info["type"]
|
|
465
|
+
|
|
466
|
+
supported_models = list(pipeline_info["config"].get("supported_models", {}).values())
|
|
467
|
+
|
|
468
|
+
logger.info(f"Storing pipeline config for chatbot `{chatbot_id}`")
|
|
469
|
+
self._chatbot_configs.pop(chatbot_id, None)
|
|
470
|
+
self._chatbot_configs[chatbot_id] = ChatbotConfig(
|
|
471
|
+
pipeline_type=pipeline_type,
|
|
472
|
+
pipeline_config=pipeline_info["config"],
|
|
473
|
+
prompt_builder_catalogs=pipeline_info["prompt_builder_catalogs"],
|
|
474
|
+
lmrp_catalogs=pipeline_info["lmrp_catalogs"],
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
new_pipeline_keys = set()
|
|
478
|
+
for model in supported_models:
|
|
479
|
+
model_id = model.get("model_id", model.get("name"))
|
|
480
|
+
new_pipeline_key = (chatbot_id, str(model_id))
|
|
481
|
+
new_pipeline_keys.add(new_pipeline_key)
|
|
482
|
+
|
|
483
|
+
for pipeline_key in self._chatbot_pipeline_keys.get(chatbot_id, set()):
|
|
484
|
+
if pipeline_key not in new_pipeline_keys:
|
|
485
|
+
self._pipeline_cache.pop(pipeline_key, None)
|
|
486
|
+
|
|
487
|
+
self._chatbot_pipeline_keys[chatbot_id] = set()
|
|
488
|
+
|
|
489
|
+
plugin = self._plugins.get(pipeline_type)
|
|
490
|
+
if not plugin:
|
|
491
|
+
logger.warning(f"Pipeline plugin not found for chatbot `{chatbot_id}`")
|
|
492
|
+
continue
|
|
493
|
+
|
|
494
|
+
self._builders.pop(chatbot_id, None)
|
|
495
|
+
self._builders[chatbot_id] = plugin
|
|
496
|
+
|
|
497
|
+
await __class__._build_plugin(self, chatbot_id, supported_models, plugin)
|
|
498
|
+
except Exception as e:
|
|
499
|
+
logger.warning(f"Error updating chatbot `{chatbot_id}`: {e}")
|
|
500
|
+
|
|
501
|
+
def _prepare_pipelines(self) -> None:
|
|
502
|
+
"""Build pipeline configurations from the chatbots configuration."""
|
|
503
|
+
pipeline_types: set[str] = set()
|
|
504
|
+
chatbot_preset_map: dict[str, PipelinePresetConfig] = {}
|
|
505
|
+
for chatbot_id, chatbot_info in self.app_config.chatbots.items():
|
|
506
|
+
if not chatbot_info.pipeline:
|
|
507
|
+
logger.warning(f"Pipeline config not found for chatbot `{chatbot_id}`")
|
|
508
|
+
continue
|
|
509
|
+
|
|
510
|
+
pipeline_info = chatbot_info.pipeline
|
|
511
|
+
pipeline_type = pipeline_info["type"]
|
|
512
|
+
|
|
513
|
+
chatbot_preset_map[chatbot_id] = PipelinePresetConfig(
|
|
514
|
+
preset_id=pipeline_info["config"]["pipeline_preset_id"],
|
|
515
|
+
supported_models=list(pipeline_info["config"].get("supported_models", {}).values()),
|
|
516
|
+
)
|
|
517
|
+
|
|
518
|
+
logger.info(f"Storing pipeline config for chatbot `{chatbot_id}`")
|
|
519
|
+
self._chatbot_configs[chatbot_id] = ChatbotConfig(
|
|
520
|
+
pipeline_type=pipeline_type,
|
|
521
|
+
pipeline_config=pipeline_info["config"],
|
|
522
|
+
prompt_builder_catalogs=pipeline_info["prompt_builder_catalogs"],
|
|
523
|
+
lmrp_catalogs=pipeline_info["lmrp_catalogs"],
|
|
524
|
+
)
|
|
525
|
+
pipeline_types.add(pipeline_type)
|
|
526
|
+
|
|
527
|
+
for pipeline_type in pipeline_types:
|
|
528
|
+
self._activated_configs[pipeline_type] = ChatbotPresetMapping(
|
|
529
|
+
pipeline_type=pipeline_type,
|
|
530
|
+
chatbot_preset_map=chatbot_preset_map,
|
|
531
|
+
)
|
|
532
|
+
|
|
533
|
+
def _validate_pipeline(self, chatbot_id: str) -> None:
|
|
534
|
+
"""Validate the pipeline configuration exists.
|
|
535
|
+
|
|
536
|
+
Args:
|
|
537
|
+
chatbot_id (str): The chatbot ID.
|
|
538
|
+
|
|
539
|
+
Raises:
|
|
540
|
+
ValueError: If the chatbot or pipeline configuration is not found.
|
|
541
|
+
"""
|
|
542
|
+
if chatbot_id not in self._chatbot_configs:
|
|
543
|
+
raise ValueError(f"Pipeline configuration for chatbot `{chatbot_id}` not found")
|
|
544
|
+
|
|
545
|
+
async def aget_pipeline_builder(self, chatbot_id: str) -> Plugin:
|
|
546
|
+
"""Get a pipeline builder instance for the given chatbot (async version).
|
|
547
|
+
|
|
548
|
+
Args:
|
|
549
|
+
chatbot_id (str): The chatbot ID.
|
|
550
|
+
|
|
551
|
+
Returns:
|
|
552
|
+
Plugin: The pipeline builder instance.
|
|
553
|
+
|
|
554
|
+
Raises:
|
|
555
|
+
ValueError: If the chatbot ID is invalid or the model name is not supported.
|
|
556
|
+
"""
|
|
557
|
+
if chatbot_id not in self._builders:
|
|
558
|
+
logger.warning(f"Pipeline builder not found for chatbot `{chatbot_id}`, attempting to rebuild...")
|
|
559
|
+
# Try to rebuild the plugin if it's not found
|
|
560
|
+
await self._async_rebuild_plugin(chatbot_id)
|
|
561
|
+
|
|
562
|
+
if chatbot_id not in self._builders:
|
|
563
|
+
raise ValueError(f"Pipeline builder for chatbot `{chatbot_id}` not found and could not be rebuilt")
|
|
564
|
+
|
|
565
|
+
return self._builders[chatbot_id]
|
|
566
|
+
|
|
567
|
+
async def _async_rebuild_plugin(self, chatbot_id: str) -> None:
|
|
568
|
+
"""Asynchronously rebuild a plugin for the given chatbot.
|
|
569
|
+
|
|
570
|
+
Args:
|
|
571
|
+
chatbot_id (str): The chatbot ID.
|
|
572
|
+
"""
|
|
573
|
+
try:
|
|
574
|
+
# Check if we have the chatbot configuration
|
|
575
|
+
if chatbot_id not in self._chatbot_configs:
|
|
576
|
+
logger.warning(f"Chatbot configuration not found for `{chatbot_id}`")
|
|
577
|
+
return
|
|
578
|
+
|
|
579
|
+
chatbot_config = self._chatbot_configs[chatbot_id]
|
|
580
|
+
pipeline_type = chatbot_config.pipeline_type
|
|
581
|
+
|
|
582
|
+
# Check if we have the plugin for this pipeline type
|
|
583
|
+
if pipeline_type not in self._plugins:
|
|
584
|
+
logger.warning(f"Plugin not found for pipeline type `{pipeline_type}`")
|
|
585
|
+
return
|
|
586
|
+
|
|
587
|
+
plugin = self._plugins[pipeline_type]
|
|
588
|
+
|
|
589
|
+
# Get supported models from the configuration
|
|
590
|
+
supported_models = list(chatbot_config.pipeline_config.get("supported_models", {}).values())
|
|
591
|
+
|
|
592
|
+
if not supported_models:
|
|
593
|
+
logger.warning(f"No supported models found for chatbot `{chatbot_id}`")
|
|
594
|
+
return
|
|
595
|
+
|
|
596
|
+
# Use the existing _build_plugin method to rebuild the plugin
|
|
597
|
+
await __class__._build_plugin(self, chatbot_id, supported_models, plugin)
|
|
598
|
+
|
|
599
|
+
logger.info(f"Successfully rebuilt pipeline builder for chatbot `{chatbot_id}`")
|
|
600
|
+
|
|
601
|
+
except Exception as e:
|
|
602
|
+
logger.warning(f"Error rebuilding plugin for chatbot `{chatbot_id}`: {e}")
|