rasa-pro 3.12.10.dev1__py3-none-any.whl → 3.12.12.dev1__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 rasa-pro might be problematic. Click here for more details.
- rasa/__init__.py +0 -6
- rasa/api.py +4 -0
- rasa/cli/arguments/default_arguments.py +13 -1
- rasa/cli/arguments/train.py +2 -0
- rasa/cli/train.py +1 -0
- rasa/constants.py +2 -0
- rasa/core/actions/action.py +1 -1
- rasa/core/channels/voice_ready/audiocodes.py +71 -31
- rasa/core/persistor.py +55 -20
- rasa/core/policies/intentless_policy.py +1 -3
- rasa/dialogue_understanding/coexistence/llm_based_router.py +1 -0
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +4 -15
- rasa/dialogue_understanding/generator/llm_command_generator.py +1 -3
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +4 -44
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +1 -14
- rasa/hooks.py +0 -55
- rasa/keys +1 -0
- rasa/model_manager/config.py +3 -1
- rasa/model_manager/model_api.py +1 -2
- rasa/model_manager/runner_service.py +8 -4
- rasa/model_manager/trainer_service.py +1 -0
- rasa/model_training.py +12 -3
- rasa/nlu/extractors/crf_entity_extractor.py +66 -16
- rasa/shared/constants.py +0 -5
- rasa/shared/providers/constants.py +0 -9
- rasa/shared/providers/llm/_base_litellm_client.py +4 -14
- rasa/shared/providers/llm/litellm_router_llm_client.py +7 -17
- rasa/shared/providers/llm/llm_client.py +15 -24
- rasa/shared/providers/llm/self_hosted_llm_client.py +2 -10
- rasa/tracing/instrumentation/attribute_extractors.py +2 -2
- rasa/version.py +1 -1
- {rasa_pro-3.12.10.dev1.dist-info → rasa_pro-3.12.12.dev1.dist-info}/METADATA +2 -3
- {rasa_pro-3.12.10.dev1.dist-info → rasa_pro-3.12.12.dev1.dist-info}/RECORD +36 -36
- rasa/monkey_patches.py +0 -91
- {rasa_pro-3.12.10.dev1.dist-info → rasa_pro-3.12.12.dev1.dist-info}/NOTICE +0 -0
- {rasa_pro-3.12.10.dev1.dist-info → rasa_pro-3.12.12.dev1.dist-info}/WHEEL +0 -0
- {rasa_pro-3.12.10.dev1.dist-info → rasa_pro-3.12.12.dev1.dist-info}/entry_points.txt +0 -0
rasa/hooks.py
CHANGED
|
@@ -1,20 +1,8 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import logging
|
|
3
|
-
import os
|
|
4
3
|
from typing import TYPE_CHECKING, List, Optional, Text, Union
|
|
5
4
|
|
|
6
|
-
import litellm
|
|
7
5
|
import pluggy
|
|
8
|
-
import structlog
|
|
9
|
-
|
|
10
|
-
from rasa.shared.providers.constants import (
|
|
11
|
-
LANGFUSE_CALLBACK_NAME,
|
|
12
|
-
LANGFUSE_HOST_ENV_VAR,
|
|
13
|
-
LANGFUSE_PROJECT_ID_ENV_VAR,
|
|
14
|
-
LANGFUSE_PUBLIC_KEY_ENV_VAR,
|
|
15
|
-
LANGFUSE_SECRET_KEY_ENV_VAR,
|
|
16
|
-
RASA_LANGFUSE_INTEGRATION_ENABLED_ENV_VAR,
|
|
17
|
-
)
|
|
18
6
|
|
|
19
7
|
# IMPORTANT: do not import anything from rasa here - use scoped imports
|
|
20
8
|
# this avoids circular imports, as the hooks are used in different places
|
|
@@ -30,7 +18,6 @@ if TYPE_CHECKING:
|
|
|
30
18
|
|
|
31
19
|
hookimpl = pluggy.HookimplMarker("rasa")
|
|
32
20
|
logger = logging.getLogger(__name__)
|
|
33
|
-
structlogger = structlog.get_logger()
|
|
34
21
|
|
|
35
22
|
|
|
36
23
|
@hookimpl # type: ignore[misc]
|
|
@@ -70,8 +57,6 @@ def configure_commandline(cmdline_arguments: argparse.Namespace) -> Optional[Tex
|
|
|
70
57
|
config.configure_tracing(tracer_provider)
|
|
71
58
|
config.configure_metrics(endpoints_file)
|
|
72
59
|
|
|
73
|
-
_init_langfuse_integration()
|
|
74
|
-
|
|
75
60
|
return endpoints_file
|
|
76
61
|
|
|
77
62
|
|
|
@@ -130,43 +115,3 @@ def after_server_stop() -> None:
|
|
|
130
115
|
|
|
131
116
|
if anon_pipeline is not None:
|
|
132
117
|
anon_pipeline.stop()
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
def _is_langfuse_integration_enabled() -> bool:
|
|
136
|
-
return (
|
|
137
|
-
os.environ.get(RASA_LANGFUSE_INTEGRATION_ENABLED_ENV_VAR, "false").lower()
|
|
138
|
-
== "true"
|
|
139
|
-
)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
def _init_langfuse_integration() -> None:
|
|
143
|
-
if not _is_langfuse_integration_enabled():
|
|
144
|
-
structlogger.info(
|
|
145
|
-
"hooks._init_langfuse_integration.disabled",
|
|
146
|
-
event_info="Langfuse integration is disabled.",
|
|
147
|
-
)
|
|
148
|
-
return
|
|
149
|
-
|
|
150
|
-
if (
|
|
151
|
-
not os.environ.get(LANGFUSE_HOST_ENV_VAR)
|
|
152
|
-
or not os.environ.get(LANGFUSE_PROJECT_ID_ENV_VAR)
|
|
153
|
-
or not os.environ.get(LANGFUSE_PUBLIC_KEY_ENV_VAR)
|
|
154
|
-
or not os.environ.get(LANGFUSE_SECRET_KEY_ENV_VAR)
|
|
155
|
-
):
|
|
156
|
-
structlogger.warning(
|
|
157
|
-
"hooks._init_langfuse_integration.missing_langfuse_keys",
|
|
158
|
-
event_info=(
|
|
159
|
-
"Langfuse integration is enabled, but some environment variables "
|
|
160
|
-
"are missing. Please set LANGFUSE_HOST, LANGFUSE_PROJECT_ID, "
|
|
161
|
-
"LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY environment "
|
|
162
|
-
"variables to use Langfuse integration."
|
|
163
|
-
),
|
|
164
|
-
)
|
|
165
|
-
return
|
|
166
|
-
|
|
167
|
-
litellm.success_callback = [LANGFUSE_CALLBACK_NAME]
|
|
168
|
-
litellm.failure_callback = [LANGFUSE_CALLBACK_NAME]
|
|
169
|
-
structlogger.info(
|
|
170
|
-
"hooks.langfuse_callbacks_initialized",
|
|
171
|
-
event_info="Langfuse integration initialized.",
|
|
172
|
-
)
|
rasa/keys
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"segment": "CcvVD1I68Nkkxrv93cIqv1twIwrwG8nz", "sentry": "a283f1fde04347b099c8d729109dd450@o251570"}
|
rasa/model_manager/config.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
3
|
|
|
4
|
+
from rasa.constants import RASA_REMOTE_STORAGE_ENV_VAR_NAME
|
|
5
|
+
|
|
4
6
|
DEFAULT_SERVER_BASE_WORKING_DIRECTORY = "working-data"
|
|
5
7
|
|
|
6
8
|
SERVER_BASE_WORKING_DIRECTORY = os.environ.get(
|
|
@@ -12,7 +14,7 @@ SERVER_PORT = os.environ.get("RASA_MODEL_SERVER_PORT", 8000)
|
|
|
12
14
|
SERVER_BASE_URL = os.environ.get("RASA_MODEL_SERVER_BASE_URL", None)
|
|
13
15
|
|
|
14
16
|
# defaults to storing on the local hard drive
|
|
15
|
-
SERVER_MODEL_REMOTE_STORAGE = os.environ.get(
|
|
17
|
+
SERVER_MODEL_REMOTE_STORAGE = os.environ.get(RASA_REMOTE_STORAGE_ENV_VAR_NAME, None)
|
|
16
18
|
|
|
17
19
|
# The path to the python executable that is running this script
|
|
18
20
|
# we will use the same python to run training / bots
|
rasa/model_manager/model_api.py
CHANGED
|
@@ -532,8 +532,7 @@ def size_of_model(model_name: str) -> Optional[int]:
|
|
|
532
532
|
model_name=model_file_name,
|
|
533
533
|
)
|
|
534
534
|
return fetch_size_of_remote_model(
|
|
535
|
-
model_file_name,
|
|
536
|
-
config.SERVER_MODEL_REMOTE_STORAGE,
|
|
535
|
+
model_file_name, config.SERVER_MODEL_REMOTE_STORAGE, model_path
|
|
537
536
|
)
|
|
538
537
|
raise ModelNotFound("Model not found.")
|
|
539
538
|
|
|
@@ -166,13 +166,13 @@ def fetch_remote_model_to_dir(
|
|
|
166
166
|
) -> str:
|
|
167
167
|
"""Fetch the model from remote storage.
|
|
168
168
|
|
|
169
|
-
Returns the path to the model
|
|
169
|
+
Returns the path to the model directory.
|
|
170
170
|
"""
|
|
171
171
|
from rasa.core.persistor import get_persistor
|
|
172
172
|
|
|
173
173
|
persistor = get_persistor(storage_type)
|
|
174
174
|
|
|
175
|
-
# we
|
|
175
|
+
# we know there must be a persistor, because the config is set
|
|
176
176
|
# this is here to please the type checker for the call below
|
|
177
177
|
assert persistor is not None
|
|
178
178
|
|
|
@@ -182,7 +182,9 @@ def fetch_remote_model_to_dir(
|
|
|
182
182
|
raise ModelNotFound() from e
|
|
183
183
|
|
|
184
184
|
|
|
185
|
-
def fetch_size_of_remote_model(
|
|
185
|
+
def fetch_size_of_remote_model(
|
|
186
|
+
model_name: str, storage_type: str, model_path: str
|
|
187
|
+
) -> int:
|
|
186
188
|
"""Fetch the size of the model from remote storage."""
|
|
187
189
|
from rasa.core.persistor import get_persistor
|
|
188
190
|
|
|
@@ -192,7 +194,9 @@ def fetch_size_of_remote_model(model_name: str, storage_type: str) -> int:
|
|
|
192
194
|
# this is here to please the type checker for the call below
|
|
193
195
|
assert persistor is not None
|
|
194
196
|
|
|
195
|
-
return persistor.size_of_persisted_model(
|
|
197
|
+
return persistor.size_of_persisted_model(
|
|
198
|
+
model_name=model_name, target_path=model_path
|
|
199
|
+
)
|
|
196
200
|
|
|
197
201
|
|
|
198
202
|
def start_bot_process(
|
rasa/model_training.py
CHANGED
|
@@ -160,6 +160,7 @@ async def train(
|
|
|
160
160
|
remote_storage: Optional[StorageType] = None,
|
|
161
161
|
file_importer: Optional[TrainingDataImporter] = None,
|
|
162
162
|
keep_local_model_copy: bool = False,
|
|
163
|
+
remote_root_only: bool = False,
|
|
163
164
|
) -> TrainingResult:
|
|
164
165
|
"""Trains a Rasa model (Core and NLU).
|
|
165
166
|
|
|
@@ -187,6 +188,8 @@ async def train(
|
|
|
187
188
|
If it is not provided, a new instance will be created.
|
|
188
189
|
keep_local_model_copy: If `True` the model will be stored locally even if
|
|
189
190
|
remote storage is configured.
|
|
191
|
+
remote_root_only: If `True`, the model will be stored in the root of the
|
|
192
|
+
remote model storage.
|
|
190
193
|
|
|
191
194
|
Returns:
|
|
192
195
|
An instance of `TrainingResult`.
|
|
@@ -269,6 +272,7 @@ async def train(
|
|
|
269
272
|
dry_run=dry_run,
|
|
270
273
|
remote_storage=remote_storage,
|
|
271
274
|
keep_local_model_copy=keep_local_model_copy,
|
|
275
|
+
remote_root_only=remote_root_only,
|
|
272
276
|
**(core_additional_arguments or {}),
|
|
273
277
|
**(nlu_additional_arguments or {}),
|
|
274
278
|
)
|
|
@@ -284,6 +288,7 @@ async def _train_graph(
|
|
|
284
288
|
dry_run: bool = False,
|
|
285
289
|
remote_storage: Optional[StorageType] = None,
|
|
286
290
|
keep_local_model_copy: bool = False,
|
|
291
|
+
remote_root_only: bool = False,
|
|
287
292
|
**kwargs: Any,
|
|
288
293
|
) -> TrainingResult:
|
|
289
294
|
if model_to_finetune:
|
|
@@ -363,7 +368,9 @@ async def _train_graph(
|
|
|
363
368
|
is_finetuning=is_finetuning,
|
|
364
369
|
)
|
|
365
370
|
if remote_storage:
|
|
366
|
-
push_model_to_remote_storage(
|
|
371
|
+
push_model_to_remote_storage(
|
|
372
|
+
full_model_path, remote_storage, remote_root_only
|
|
373
|
+
)
|
|
367
374
|
if not keep_local_model_copy:
|
|
368
375
|
full_model_path.unlink()
|
|
369
376
|
structlogger.info(
|
|
@@ -581,14 +588,16 @@ async def train_nlu(
|
|
|
581
588
|
).model
|
|
582
589
|
|
|
583
590
|
|
|
584
|
-
def push_model_to_remote_storage(
|
|
591
|
+
def push_model_to_remote_storage(
|
|
592
|
+
model_path: Path, remote_storage: StorageType, remote_root_only: bool = False
|
|
593
|
+
) -> None:
|
|
585
594
|
"""Push model to remote storage."""
|
|
586
595
|
from rasa.core.persistor import get_persistor
|
|
587
596
|
|
|
588
597
|
persistor = get_persistor(remote_storage)
|
|
589
598
|
|
|
590
599
|
if persistor is not None:
|
|
591
|
-
persistor.persist(str(model_path))
|
|
600
|
+
persistor.persist(str(model_path), remote_root_only)
|
|
592
601
|
|
|
593
602
|
else:
|
|
594
603
|
raise RasaException(
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
import shutil
|
|
4
5
|
import typing
|
|
5
6
|
from collections import OrderedDict
|
|
6
7
|
from enum import Enum
|
|
8
|
+
from pathlib import Path
|
|
7
9
|
from typing import Any, Callable, Dict, List, Optional, Text, Tuple, Type
|
|
8
10
|
|
|
9
11
|
import numpy as np
|
|
@@ -43,6 +45,10 @@ if typing.TYPE_CHECKING:
|
|
|
43
45
|
|
|
44
46
|
CONFIG_FEATURES = "features"
|
|
45
47
|
|
|
48
|
+
TAGGERS_DIR = "taggers"
|
|
49
|
+
CRFSUITE_MODEL_FILE_NAME = "model.crfsuite"
|
|
50
|
+
PLAIN_CRF_MODEL_FILE_NAME = "model.txt"
|
|
51
|
+
|
|
46
52
|
|
|
47
53
|
class CRFToken:
|
|
48
54
|
def __init__(
|
|
@@ -419,19 +425,11 @@ class CRFEntityExtractor(GraphComponent, EntityExtractorMixin):
|
|
|
419
425
|
"""Loads trained component (see parent class for full docstring)."""
|
|
420
426
|
try:
|
|
421
427
|
with model_storage.read_from(resource) as model_dir:
|
|
422
|
-
dataset = rasa.shared.utils.io.read_json_file(
|
|
423
|
-
model_dir / "crf_dataset.json"
|
|
424
|
-
)
|
|
425
428
|
crf_order = rasa.shared.utils.io.read_json_file(
|
|
426
429
|
model_dir / "crf_order.json"
|
|
427
430
|
)
|
|
428
431
|
|
|
429
|
-
|
|
430
|
-
[CRFToken.create_from_dict(token_data) for token_data in sub_list]
|
|
431
|
-
for sub_list in dataset
|
|
432
|
-
]
|
|
433
|
-
|
|
434
|
-
entity_taggers = cls.train_model(dataset, config, crf_order)
|
|
432
|
+
entity_taggers = cls._load_taggers(model_dir, config)
|
|
435
433
|
|
|
436
434
|
entity_extractor = cls(config, model_storage, resource, entity_taggers)
|
|
437
435
|
entity_extractor.crf_order = crf_order
|
|
@@ -443,19 +441,71 @@ class CRFEntityExtractor(GraphComponent, EntityExtractorMixin):
|
|
|
443
441
|
)
|
|
444
442
|
return cls(config, model_storage, resource)
|
|
445
443
|
|
|
444
|
+
@classmethod
|
|
445
|
+
def _load_taggers(
|
|
446
|
+
cls, model_dir: Path, config: Dict[Text, Any]
|
|
447
|
+
) -> Dict[str, "CRF"]:
|
|
448
|
+
"""
|
|
449
|
+
Load taggers from model directory that persists trained binary
|
|
450
|
+
`model.crfsuite` files.
|
|
451
|
+
"""
|
|
452
|
+
|
|
453
|
+
import pycrfsuite
|
|
454
|
+
import sklearn_crfsuite
|
|
455
|
+
|
|
456
|
+
# Get tagger directories
|
|
457
|
+
taggers_base = model_dir / TAGGERS_DIR
|
|
458
|
+
if not taggers_base.exists():
|
|
459
|
+
return {}
|
|
460
|
+
|
|
461
|
+
taggers_dirs = [
|
|
462
|
+
directory for directory in taggers_base.iterdir() if directory.is_dir()
|
|
463
|
+
]
|
|
464
|
+
|
|
465
|
+
entity_taggers: Dict[str, "CRF"] = {}
|
|
466
|
+
|
|
467
|
+
for tagger_dir in taggers_dirs:
|
|
468
|
+
# Instantiate sklearns CRF wrapper for the pycrfsuite's Tagger
|
|
469
|
+
entity_tagger = sklearn_crfsuite.CRF(
|
|
470
|
+
algorithm="lbfgs",
|
|
471
|
+
# coefficient for L1 penalty
|
|
472
|
+
c1=config["L1_c"],
|
|
473
|
+
# coefficient for L2 penalty
|
|
474
|
+
c2=config["L2_c"],
|
|
475
|
+
# stop earlier
|
|
476
|
+
max_iterations=config["max_iterations"],
|
|
477
|
+
# include transitions that are possible, but not observed
|
|
478
|
+
all_possible_transitions=True,
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
# Load pycrfsuite tagger from the persisted binary model.crfsuite file
|
|
482
|
+
entity_tagger._tagger = pycrfsuite.Tagger()
|
|
483
|
+
entity_tagger._tagger.open(str(tagger_dir / CRFSUITE_MODEL_FILE_NAME))
|
|
484
|
+
|
|
485
|
+
entity_taggers[tagger_dir.name] = entity_tagger
|
|
486
|
+
|
|
487
|
+
return entity_taggers
|
|
488
|
+
|
|
446
489
|
def persist(self, dataset: List[List[CRFToken]]) -> None:
|
|
447
490
|
"""Persist this model into the passed directory."""
|
|
448
491
|
with self._model_storage.write_to(self._resource) as model_dir:
|
|
449
|
-
data_to_store = [
|
|
450
|
-
[token.to_dict() for token in sub_list] for sub_list in dataset
|
|
451
|
-
]
|
|
452
|
-
|
|
453
|
-
rasa.shared.utils.io.dump_obj_as_json_to_file(
|
|
454
|
-
model_dir / "crf_dataset.json", data_to_store
|
|
455
|
-
)
|
|
456
492
|
rasa.shared.utils.io.dump_obj_as_json_to_file(
|
|
457
493
|
model_dir / "crf_order.json", self.crf_order
|
|
458
494
|
)
|
|
495
|
+
if self.entity_taggers is not None:
|
|
496
|
+
for tag_name, entity_tagger in self.entity_taggers.items():
|
|
497
|
+
# Create the directories for storing the CRF model
|
|
498
|
+
tagger_dir = model_dir / TAGGERS_DIR / tag_name
|
|
499
|
+
tagger_dir.mkdir(parents=True, exist_ok=True)
|
|
500
|
+
# Create a plain text version of the CRF model
|
|
501
|
+
entity_tagger.tagger_.dump(
|
|
502
|
+
str(tagger_dir / PLAIN_CRF_MODEL_FILE_NAME)
|
|
503
|
+
)
|
|
504
|
+
# Persist binary version of the model.crfsuite
|
|
505
|
+
shutil.copy2(
|
|
506
|
+
src=entity_tagger.modelfile.name,
|
|
507
|
+
dst=tagger_dir / CRFSUITE_MODEL_FILE_NAME,
|
|
508
|
+
)
|
|
459
509
|
|
|
460
510
|
@classmethod
|
|
461
511
|
def _crf_tokens_to_features(
|
rasa/shared/constants.py
CHANGED
|
@@ -339,8 +339,3 @@ ROLE_SYSTEM = "system"
|
|
|
339
339
|
# Used for key values in ValidateSlotPatternFlowStackFrame
|
|
340
340
|
REFILL_UTTER = "refill_utter"
|
|
341
341
|
REJECTIONS = "rejections"
|
|
342
|
-
|
|
343
|
-
LANGFUSE_METADATA_USER_ID = "trace_user_id"
|
|
344
|
-
LANGFUSE_METADATA_SESSION_ID = "session_id"
|
|
345
|
-
LANGFUSE_CUSTOM_METADATA_DICT = "trace_metadata"
|
|
346
|
-
LANGFUSE_TAGS = "tags"
|
|
@@ -4,12 +4,3 @@ LITE_LLM_API_KEY_FIELD = "api_key"
|
|
|
4
4
|
LITE_LLM_API_VERSION_FIELD = "api_version"
|
|
5
5
|
LITE_LLM_MODEL_FIELD = "model"
|
|
6
6
|
LITE_LLM_AZURE_AD_TOKEN = "azure_ad_token"
|
|
7
|
-
|
|
8
|
-
# Enable or disable Langfuse integration
|
|
9
|
-
RASA_LANGFUSE_INTEGRATION_ENABLED_ENV_VAR = "RASA_LANGFUSE_INTEGRATION_ENABLED"
|
|
10
|
-
# Langfuse configuration
|
|
11
|
-
LANGFUSE_CALLBACK_NAME = "langfuse"
|
|
12
|
-
LANGFUSE_HOST_ENV_VAR = "LANGFUSE_HOST"
|
|
13
|
-
LANGFUSE_PROJECT_ID_ENV_VAR = "LANGFUSE_PROJECT_ID"
|
|
14
|
-
LANGFUSE_PUBLIC_KEY_ENV_VAR = "LANGFUSE_PUBLIC_KEY"
|
|
15
|
-
LANGFUSE_SECRET_KEY_ENV_VAR = "LANGFUSE_SECRET_KEY"
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
from abc import abstractmethod
|
|
5
|
-
from typing import Any, Dict, List,
|
|
5
|
+
from typing import Any, Dict, List, Union, cast
|
|
6
6
|
|
|
7
7
|
import structlog
|
|
8
8
|
from litellm import acompletion, completion, validate_environment
|
|
@@ -123,11 +123,7 @@ class _BaseLiteLLMClient:
|
|
|
123
123
|
raise ProviderClientValidationError(event_info)
|
|
124
124
|
|
|
125
125
|
@suppress_logs(log_level=logging.WARNING)
|
|
126
|
-
def completion(
|
|
127
|
-
self,
|
|
128
|
-
messages: Union[List[dict], List[str], str],
|
|
129
|
-
metadata: Optional[Dict[str, Any]] = None,
|
|
130
|
-
) -> LLMResponse:
|
|
126
|
+
def completion(self, messages: Union[List[dict], List[str], str]) -> LLMResponse:
|
|
131
127
|
"""Synchronously generate completions for given list of messages.
|
|
132
128
|
|
|
133
129
|
Args:
|
|
@@ -139,7 +135,6 @@ class _BaseLiteLLMClient:
|
|
|
139
135
|
- a list of messages. Each message is a string and will be formatted
|
|
140
136
|
as a user message.
|
|
141
137
|
- a single message as a string which will be formatted as user message.
|
|
142
|
-
metadata: Optional metadata to be passed to the LLM call.
|
|
143
138
|
|
|
144
139
|
Returns:
|
|
145
140
|
List of message completions.
|
|
@@ -157,9 +152,7 @@ class _BaseLiteLLMClient:
|
|
|
157
152
|
|
|
158
153
|
@suppress_logs(log_level=logging.WARNING)
|
|
159
154
|
async def acompletion(
|
|
160
|
-
self,
|
|
161
|
-
messages: Union[List[dict], List[str], str],
|
|
162
|
-
metadata: Optional[Dict[str, Any]] = None,
|
|
155
|
+
self, messages: Union[List[dict], List[str], str]
|
|
163
156
|
) -> LLMResponse:
|
|
164
157
|
"""Asynchronously generate completions for given list of messages.
|
|
165
158
|
|
|
@@ -172,7 +165,6 @@ class _BaseLiteLLMClient:
|
|
|
172
165
|
- a list of messages. Each message is a string and will be formatted
|
|
173
166
|
as a user message.
|
|
174
167
|
- a single message as a string which will be formatted as user message.
|
|
175
|
-
metadata: Optional metadata to be passed to the LLM call.
|
|
176
168
|
|
|
177
169
|
Returns:
|
|
178
170
|
List of message completions.
|
|
@@ -183,9 +175,7 @@ class _BaseLiteLLMClient:
|
|
|
183
175
|
try:
|
|
184
176
|
formatted_messages = self._get_formatted_messages(messages)
|
|
185
177
|
arguments = resolve_environment_variables(self._completion_fn_args)
|
|
186
|
-
response = await acompletion(
|
|
187
|
-
messages=formatted_messages, metadata=metadata, **arguments
|
|
188
|
-
)
|
|
178
|
+
response = await acompletion(messages=formatted_messages, **arguments)
|
|
189
179
|
return self._format_response(response)
|
|
190
180
|
except Exception as e:
|
|
191
181
|
message = ""
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from typing import Any, Dict, List,
|
|
4
|
+
from typing import Any, Dict, List, Union
|
|
5
5
|
|
|
6
6
|
import structlog
|
|
7
7
|
|
|
@@ -122,12 +122,9 @@ class LiteLLMRouterLLMClient(_BaseLiteLLMRouterClient, _BaseLiteLLMClient):
|
|
|
122
122
|
raise ProviderClientAPIException(e)
|
|
123
123
|
|
|
124
124
|
@suppress_logs(log_level=logging.WARNING)
|
|
125
|
-
def completion(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
metadata: Optional[Dict[str, Any]] = None,
|
|
129
|
-
) -> LLMResponse:
|
|
130
|
-
"""Synchronously generate completions for given list of messages.
|
|
125
|
+
def completion(self, messages: Union[List[dict], List[str], str]) -> LLMResponse:
|
|
126
|
+
"""
|
|
127
|
+
Synchronously generate completions for given list of messages.
|
|
131
128
|
|
|
132
129
|
Method overrides the base class method to call the appropriate
|
|
133
130
|
completion method based on the configuration. If the chat completions
|
|
@@ -143,11 +140,8 @@ class LiteLLMRouterLLMClient(_BaseLiteLLMRouterClient, _BaseLiteLLMClient):
|
|
|
143
140
|
- a list of messages. Each message is a string and will be formatted
|
|
144
141
|
as a user message.
|
|
145
142
|
- a single message as a string which will be formatted as user message.
|
|
146
|
-
metadata: Optional metadata to be passed to the LLM call.
|
|
147
|
-
|
|
148
143
|
Returns:
|
|
149
144
|
List of message completions.
|
|
150
|
-
|
|
151
145
|
Raises:
|
|
152
146
|
ProviderClientAPIException: If the API request fails.
|
|
153
147
|
"""
|
|
@@ -164,11 +158,10 @@ class LiteLLMRouterLLMClient(_BaseLiteLLMRouterClient, _BaseLiteLLMClient):
|
|
|
164
158
|
|
|
165
159
|
@suppress_logs(log_level=logging.WARNING)
|
|
166
160
|
async def acompletion(
|
|
167
|
-
self,
|
|
168
|
-
messages: Union[List[dict], List[str], str],
|
|
169
|
-
metadata: Optional[Dict[str, Any]] = None,
|
|
161
|
+
self, messages: Union[List[dict], List[str], str]
|
|
170
162
|
) -> LLMResponse:
|
|
171
|
-
"""
|
|
163
|
+
"""
|
|
164
|
+
Asynchronously generate completions for given list of messages.
|
|
172
165
|
|
|
173
166
|
Method overrides the base class method to call the appropriate
|
|
174
167
|
completion method based on the configuration. If the chat completions
|
|
@@ -184,11 +177,8 @@ class LiteLLMRouterLLMClient(_BaseLiteLLMRouterClient, _BaseLiteLLMClient):
|
|
|
184
177
|
- a list of messages. Each message is a string and will be formatted
|
|
185
178
|
as a user message.
|
|
186
179
|
- a single message as a string which will be formatted as user message.
|
|
187
|
-
metadata: Optional metadata to be passed to the LLM call.
|
|
188
|
-
|
|
189
180
|
Returns:
|
|
190
181
|
List of message completions.
|
|
191
|
-
|
|
192
182
|
Raises:
|
|
193
183
|
ProviderClientAPIException: If the API request fails.
|
|
194
184
|
"""
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Dict, List, Protocol, Union, runtime_checkable
|
|
4
4
|
|
|
5
5
|
from rasa.shared.providers.llm.llm_response import LLMResponse
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
@runtime_checkable
|
|
9
9
|
class LLMClient(Protocol):
|
|
10
|
-
"""
|
|
10
|
+
"""
|
|
11
|
+
Protocol for an LLM client that specifies the interface for interacting
|
|
11
12
|
with the API.
|
|
12
13
|
"""
|
|
13
14
|
|
|
14
15
|
@classmethod
|
|
15
16
|
def from_config(cls, config: dict) -> LLMClient:
|
|
16
|
-
"""
|
|
17
|
+
"""
|
|
18
|
+
Initializes the llm client with the given configuration.
|
|
17
19
|
|
|
18
20
|
This class method should be implemented to parse the given
|
|
19
21
|
configuration and create an instance of an llm client.
|
|
@@ -22,24 +24,17 @@ class LLMClient(Protocol):
|
|
|
22
24
|
|
|
23
25
|
@property
|
|
24
26
|
def config(self) -> Dict:
|
|
25
|
-
"""
|
|
27
|
+
"""
|
|
28
|
+
Returns the configuration for that the llm client is initialized with.
|
|
26
29
|
|
|
27
30
|
This property should be implemented to return a dictionary containing
|
|
28
31
|
the configuration settings for the llm client.
|
|
29
32
|
"""
|
|
30
33
|
...
|
|
31
34
|
|
|
32
|
-
def completion(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
metadata: Optional[Dict[str, Any]] = None,
|
|
36
|
-
) -> LLMResponse:
|
|
37
|
-
"""Synchronously generate completions for given list of messages.
|
|
38
|
-
def completion(
|
|
39
|
-
self,
|
|
40
|
-
messages: Union[List[dict], List[str], str],
|
|
41
|
-
metadata: Optional[Dict[str, Any]] = None,
|
|
42
|
-
) -> LLMResponse:
|
|
35
|
+
def completion(self, messages: Union[List[dict], List[str], str]) -> LLMResponse:
|
|
36
|
+
"""
|
|
37
|
+
Synchronously generate completions for given list of messages.
|
|
43
38
|
|
|
44
39
|
This method should be implemented to take a list of messages (as
|
|
45
40
|
strings) and return a list of completions (as strings).
|
|
@@ -53,19 +48,16 @@ class LLMClient(Protocol):
|
|
|
53
48
|
- a list of messages. Each message is a string and will be formatted
|
|
54
49
|
as a user message.
|
|
55
50
|
- a single message as a string which will be formatted as user message.
|
|
56
|
-
metadata: Optional metadata to be passed to the LLM call.
|
|
57
|
-
|
|
58
51
|
Returns:
|
|
59
52
|
LLMResponse
|
|
60
53
|
"""
|
|
61
54
|
...
|
|
62
55
|
|
|
63
56
|
async def acompletion(
|
|
64
|
-
self,
|
|
65
|
-
messages: Union[List[dict], List[str], str],
|
|
66
|
-
metadata: Optional[Dict[str, Any]] = None,
|
|
57
|
+
self, messages: Union[List[dict], List[str], str]
|
|
67
58
|
) -> LLMResponse:
|
|
68
|
-
"""
|
|
59
|
+
"""
|
|
60
|
+
Asynchronously generate completions for given list of messages.
|
|
69
61
|
|
|
70
62
|
This method should be implemented to take a list of messages (as
|
|
71
63
|
strings) and return a list of completions (as strings).
|
|
@@ -79,15 +71,14 @@ class LLMClient(Protocol):
|
|
|
79
71
|
- a list of messages. Each message is a string and will be formatted
|
|
80
72
|
as a user message.
|
|
81
73
|
- a single message as a string which will be formatted as user message.
|
|
82
|
-
metadata: Optional metadata to be passed to the LLM call.
|
|
83
|
-
|
|
84
74
|
Returns:
|
|
85
75
|
LLMResponse
|
|
86
76
|
"""
|
|
87
77
|
...
|
|
88
78
|
|
|
89
79
|
def validate_client_setup(self, *args, **kwargs) -> None: # type: ignore
|
|
90
|
-
"""
|
|
80
|
+
"""
|
|
81
|
+
Perform client setup validation.
|
|
91
82
|
|
|
92
83
|
This method should be implemented to validate whether the client can be
|
|
93
84
|
used with the parameters provided through configuration or environment
|
|
@@ -237,9 +237,7 @@ class SelfHostedLLMClient(_BaseLiteLLMClient):
|
|
|
237
237
|
raise ProviderClientAPIException(e)
|
|
238
238
|
|
|
239
239
|
async def acompletion(
|
|
240
|
-
self,
|
|
241
|
-
messages: Union[List[dict], List[str], str],
|
|
242
|
-
metadata: Optional[Dict[str, Any]] = None,
|
|
240
|
+
self, messages: Union[List[dict], List[str], str]
|
|
243
241
|
) -> LLMResponse:
|
|
244
242
|
"""Asynchronous completion of the model with the given messages.
|
|
245
243
|
|
|
@@ -257,7 +255,6 @@ class SelfHostedLLMClient(_BaseLiteLLMClient):
|
|
|
257
255
|
- a list of messages. Each message is a string and will be formatted
|
|
258
256
|
as a user message.
|
|
259
257
|
- a single message as a string which will be formatted as user message.
|
|
260
|
-
metadata: Optional metadata to be passed to the LLM call.
|
|
261
258
|
|
|
262
259
|
Returns:
|
|
263
260
|
The completion response.
|
|
@@ -266,11 +263,7 @@ class SelfHostedLLMClient(_BaseLiteLLMClient):
|
|
|
266
263
|
return await super().acompletion(messages)
|
|
267
264
|
return await self._atext_completion(messages)
|
|
268
265
|
|
|
269
|
-
def completion(
|
|
270
|
-
self,
|
|
271
|
-
messages: Union[List[dict], List[str], str],
|
|
272
|
-
metadata: Optional[Dict[str, Any]] = None,
|
|
273
|
-
) -> LLMResponse:
|
|
266
|
+
def completion(self, messages: Union[List[dict], List[str], str]) -> LLMResponse:
|
|
274
267
|
"""Completion of the model with the given messages.
|
|
275
268
|
|
|
276
269
|
Method overrides the base class method to call the appropriate
|
|
@@ -280,7 +273,6 @@ class SelfHostedLLMClient(_BaseLiteLLMClient):
|
|
|
280
273
|
|
|
281
274
|
Args:
|
|
282
275
|
messages: The messages to be used for completion.
|
|
283
|
-
metadata: Optional metadata to be passed to the LLM call.
|
|
284
276
|
|
|
285
277
|
Returns:
|
|
286
278
|
The completion response.
|
|
@@ -372,7 +372,6 @@ def extract_llm_config(
|
|
|
372
372
|
def extract_attrs_for_llm_based_command_generator(
|
|
373
373
|
self: "LLMBasedCommandGenerator",
|
|
374
374
|
prompt: str,
|
|
375
|
-
metadata: Optional[Dict[str, Any]] = None,
|
|
376
375
|
) -> Dict[str, Any]:
|
|
377
376
|
from rasa.dialogue_understanding.generator.flow_retrieval import (
|
|
378
377
|
DEFAULT_EMBEDDINGS_CONFIG,
|
|
@@ -388,7 +387,8 @@ def extract_attrs_for_llm_based_command_generator(
|
|
|
388
387
|
|
|
389
388
|
|
|
390
389
|
def extract_attrs_for_contextual_response_rephraser(
|
|
391
|
-
self: Any,
|
|
390
|
+
self: Any,
|
|
391
|
+
prompt: str,
|
|
392
392
|
) -> Dict[str, Any]:
|
|
393
393
|
from rasa.core.nlg.contextual_response_rephraser import DEFAULT_LLM_CONFIG
|
|
394
394
|
|
rasa/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: rasa-pro
|
|
3
|
-
Version: 3.12.
|
|
3
|
+
Version: 3.12.12.dev1
|
|
4
4
|
Summary: State-of-the-art open-core Conversational AI framework for Enterprises that natively leverages generative AI for effortless assistant development.
|
|
5
5
|
Keywords: nlp,machine-learning,machine-learning-library,bot,bots,botkit,rasa conversational-agents,conversational-ai,chatbot,chatbot-framework,bot-framework
|
|
6
6
|
Author: Rasa Technologies GmbH
|
|
@@ -63,8 +63,7 @@ Requires-Dist: keras (==2.14.0)
|
|
|
63
63
|
Requires-Dist: langchain (>=0.2.17,<0.3.0)
|
|
64
64
|
Requires-Dist: langchain-community (>=0.2.19,<0.3.0)
|
|
65
65
|
Requires-Dist: langcodes (>=3.5.0,<4.0.0)
|
|
66
|
-
Requires-Dist:
|
|
67
|
-
Requires-Dist: litellm (>=1.68.0,<1.69.0)
|
|
66
|
+
Requires-Dist: litellm (>=1.69.0,<1.70.0)
|
|
68
67
|
Requires-Dist: matplotlib (>=3.7,<3.8)
|
|
69
68
|
Requires-Dist: mattermostwrapper (>=2.2,<2.3)
|
|
70
69
|
Requires-Dist: networkx (>=3.1,<3.2)
|