rasa-pro 3.10.15__py3-none-any.whl → 3.11.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 rasa-pro might be problematic. Click here for more details.
- rasa/__main__.py +31 -15
- rasa/api.py +12 -2
- rasa/cli/arguments/default_arguments.py +24 -4
- rasa/cli/arguments/run.py +15 -0
- rasa/cli/arguments/shell.py +5 -1
- rasa/cli/arguments/train.py +17 -9
- rasa/cli/evaluate.py +7 -7
- rasa/cli/inspect.py +19 -7
- rasa/cli/interactive.py +1 -0
- rasa/cli/project_templates/calm/config.yml +5 -7
- rasa/cli/project_templates/calm/endpoints.yml +15 -2
- rasa/cli/project_templates/tutorial/config.yml +8 -5
- rasa/cli/project_templates/tutorial/data/flows.yml +1 -1
- rasa/cli/project_templates/tutorial/data/patterns.yml +5 -0
- rasa/cli/project_templates/tutorial/domain.yml +14 -0
- rasa/cli/project_templates/tutorial/endpoints.yml +5 -0
- rasa/cli/run.py +7 -0
- rasa/cli/scaffold.py +4 -2
- rasa/cli/studio/upload.py +0 -15
- rasa/cli/train.py +14 -53
- rasa/cli/utils.py +14 -11
- rasa/cli/x.py +7 -7
- rasa/constants.py +3 -1
- rasa/core/actions/action.py +77 -33
- rasa/core/actions/action_hangup.py +29 -0
- rasa/core/actions/action_repeat_bot_messages.py +89 -0
- rasa/core/actions/e2e_stub_custom_action_executor.py +5 -1
- rasa/core/actions/http_custom_action_executor.py +4 -0
- rasa/core/agent.py +2 -2
- rasa/core/brokers/kafka.py +3 -1
- rasa/core/brokers/pika.py +3 -1
- rasa/core/channels/__init__.py +10 -6
- rasa/core/channels/channel.py +41 -4
- rasa/core/channels/development_inspector.py +150 -46
- rasa/core/channels/inspector/README.md +1 -1
- rasa/core/channels/inspector/dist/assets/{arc-b6e548fe.js → arc-bc141fb2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-d0fbc5ce-fa03ac9e.js → c4Diagram-d0fbc5ce-be2db283.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-936ed81e-ee67392a.js → classDiagram-936ed81e-55366915.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-c3cb15f1-9b283fae.js → classDiagram-v2-c3cb15f1-bb529518.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{createText-62fc7601-8b6fcc2a.js → createText-62fc7601-b0ec81d6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-f2ad444c-22e77f4f.js → edges-f2ad444c-6166330c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9d236eb7-60ffc87f.js → erDiagram-9d236eb7-5ccc6a8e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-1972c806-9dd802e4.js → flowDb-1972c806-fca3bfe4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-7ea5b25a-5fa1912f.js → flowDiagram-7ea5b25a-4739080f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-736177bf.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-abe16c3d-622a1fd2.js → flowchart-elk-definition-abe16c3d-7c1b0e0f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-9b5ea136-e285a63a.js → ganttDiagram-9b5ea136-772fd050.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-99d0ae7c-f237bdca.js → gitGraphDiagram-99d0ae7c-8eae1dc9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-2c4b9a3b-4b03d70e.js → index-2c4b9a3b-f55afcdf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/index-e7cef9de.js +1317 -0
- rasa/core/channels/inspector/dist/assets/{infoDiagram-736b4530-72a0fa5f.js → infoDiagram-736b4530-124d4a14.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-df861f2b-82218c41.js → journeyDiagram-df861f2b-7c4fae44.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-78cff630.js → layout-b9885fb6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-5038b469.js → line-7c59abb6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-c4fc4098.js → linear-4776f780.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-beec6740-c33c8ea6.js → mindmap-definition-beec6740-2332c46c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-dbbf0591-a8d03059.js → pieDiagram-dbbf0591-8fb39303.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-4d7f4fd6-6a0e56b2.js → quadrantDiagram-4d7f4fd6-3c7180a2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-6fc4c22a-2dc7c7bd.js → requirementDiagram-6fc4c22a-e910bcb8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-8f13d901-2360fe39.js → sankeyDiagram-8f13d901-ead16c89.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-b655622a-41b9f9ad.js → sequenceDiagram-b655622a-29a02a19.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-59f0c015-0aad326f.js → stateDiagram-59f0c015-042b3137.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-2b26beab-9847d984.js → stateDiagram-v2-2b26beab-2178c0f3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-080da4f6-564d890e.js → styles-080da4f6-23ffa4fc.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-3dcbcfbf-38957613.js → styles-3dcbcfbf-94f59763.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9c745c82-f0fc6921.js → styles-9c745c82-78a6bebc.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-4835440b-ef3c5a77.js → svgDrawCommon-4835440b-eae2a6f6.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-5b62e21b-bf3e91c1.js → timeline-definition-5b62e21b-5c968d92.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-2b33534f-4d4026c0.js → xychartDiagram-2b33534f-fd3db0d5.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +18 -15
- rasa/core/channels/inspector/index.html +17 -14
- rasa/core/channels/inspector/package.json +5 -1
- rasa/core/channels/inspector/src/App.tsx +118 -68
- rasa/core/channels/inspector/src/components/Chat.tsx +95 -0
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +11 -10
- rasa/core/channels/inspector/src/components/DialogueStack.tsx +10 -25
- rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +6 -3
- rasa/core/channels/inspector/src/helpers/audiostream.ts +165 -0
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +10 -0
- rasa/core/channels/inspector/src/helpers/formatters.ts +107 -41
- rasa/core/channels/inspector/src/helpers/utils.ts +92 -7
- rasa/core/channels/inspector/src/types.ts +21 -1
- rasa/core/channels/inspector/yarn.lock +94 -1
- rasa/core/channels/rest.py +51 -46
- rasa/core/channels/socketio.py +28 -1
- rasa/core/channels/telegram.py +1 -1
- rasa/core/channels/twilio.py +1 -1
- rasa/core/channels/{audiocodes.py → voice_ready/audiocodes.py} +122 -69
- rasa/core/channels/{voice_aware → voice_ready}/jambonz.py +26 -8
- rasa/core/channels/{voice_aware → voice_ready}/jambonz_protocol.py +57 -5
- rasa/core/channels/{twilio_voice.py → voice_ready/twilio_voice.py} +64 -28
- rasa/core/channels/voice_ready/utils.py +37 -0
- rasa/core/channels/voice_stream/asr/__init__.py +0 -0
- rasa/core/channels/voice_stream/asr/asr_engine.py +89 -0
- rasa/core/channels/voice_stream/asr/asr_event.py +18 -0
- rasa/core/channels/voice_stream/asr/azure.py +129 -0
- rasa/core/channels/voice_stream/asr/deepgram.py +90 -0
- rasa/core/channels/voice_stream/audio_bytes.py +8 -0
- rasa/core/channels/voice_stream/browser_audio.py +107 -0
- rasa/core/channels/voice_stream/call_state.py +23 -0
- rasa/core/channels/voice_stream/tts/__init__.py +0 -0
- rasa/core/channels/voice_stream/tts/azure.py +106 -0
- rasa/core/channels/voice_stream/tts/cartesia.py +118 -0
- rasa/core/channels/voice_stream/tts/tts_cache.py +27 -0
- rasa/core/channels/voice_stream/tts/tts_engine.py +58 -0
- rasa/core/channels/voice_stream/twilio_media_streams.py +173 -0
- rasa/core/channels/voice_stream/util.py +57 -0
- rasa/core/channels/voice_stream/voice_channel.py +427 -0
- rasa/core/information_retrieval/qdrant.py +1 -0
- rasa/core/nlg/contextual_response_rephraser.py +45 -17
- rasa/{nlu → core}/persistor.py +203 -68
- rasa/core/policies/enterprise_search_policy.py +119 -63
- rasa/core/policies/flows/flow_executor.py +15 -22
- rasa/core/policies/intentless_policy.py +83 -28
- rasa/core/processor.py +25 -0
- rasa/core/run.py +12 -2
- rasa/core/secrets_manager/constants.py +4 -0
- rasa/core/secrets_manager/factory.py +8 -0
- rasa/core/secrets_manager/vault.py +11 -1
- rasa/core/training/interactive.py +33 -34
- rasa/core/utils.py +47 -21
- rasa/dialogue_understanding/coexistence/llm_based_router.py +41 -14
- rasa/dialogue_understanding/commands/__init__.py +6 -0
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +60 -0
- rasa/dialogue_understanding/commands/session_end_command.py +61 -0
- rasa/dialogue_understanding/commands/user_silence_command.py +59 -0
- rasa/dialogue_understanding/commands/utils.py +5 -0
- rasa/dialogue_understanding/generator/constants.py +2 -0
- rasa/dialogue_understanding/generator/flow_retrieval.py +47 -9
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +38 -15
- rasa/dialogue_understanding/generator/llm_command_generator.py +1 -1
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +35 -13
- rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +3 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +60 -13
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +53 -0
- rasa/dialogue_understanding/patterns/repeat.py +37 -0
- rasa/dialogue_understanding/patterns/user_silence.py +37 -0
- rasa/dialogue_understanding/processor/command_processor.py +21 -1
- rasa/e2e_test/aggregate_test_stats_calculator.py +1 -11
- rasa/e2e_test/assertions.py +136 -61
- rasa/e2e_test/assertions_schema.yml +23 -0
- rasa/e2e_test/e2e_test_case.py +85 -6
- rasa/e2e_test/e2e_test_runner.py +2 -3
- rasa/engine/graph.py +0 -1
- rasa/engine/loader.py +12 -0
- rasa/engine/recipes/config_files/default_config.yml +0 -3
- rasa/engine/recipes/default_recipe.py +0 -1
- rasa/engine/recipes/graph_recipe.py +0 -1
- rasa/engine/runner/dask.py +2 -2
- rasa/engine/storage/local_model_storage.py +12 -42
- rasa/engine/storage/storage.py +1 -5
- rasa/engine/validation.py +527 -74
- rasa/model_manager/__init__.py +0 -0
- rasa/model_manager/config.py +40 -0
- rasa/model_manager/model_api.py +559 -0
- rasa/model_manager/runner_service.py +286 -0
- rasa/model_manager/socket_bridge.py +146 -0
- rasa/model_manager/studio_jwt_auth.py +86 -0
- rasa/model_manager/trainer_service.py +325 -0
- rasa/model_manager/utils.py +87 -0
- rasa/model_manager/warm_rasa_process.py +187 -0
- rasa/model_service.py +112 -0
- rasa/model_training.py +42 -23
- rasa/nlu/tokenizers/whitespace_tokenizer.py +3 -14
- rasa/server.py +4 -2
- rasa/shared/constants.py +60 -8
- rasa/shared/core/constants.py +13 -0
- rasa/shared/core/domain.py +107 -50
- rasa/shared/core/events.py +29 -0
- rasa/shared/core/flows/flow.py +5 -0
- rasa/shared/core/flows/flows_list.py +19 -6
- rasa/shared/core/flows/flows_yaml_schema.json +10 -0
- rasa/shared/core/flows/utils.py +39 -0
- rasa/shared/core/flows/validation.py +121 -0
- rasa/shared/core/flows/yaml_flows_io.py +15 -27
- rasa/shared/core/slots.py +5 -0
- rasa/shared/importers/importer.py +59 -41
- rasa/shared/importers/multi_project.py +23 -11
- rasa/shared/importers/rasa.py +12 -3
- rasa/shared/importers/remote_importer.py +196 -0
- rasa/shared/importers/utils.py +3 -1
- rasa/shared/nlu/training_data/formats/rasa_yaml.py +18 -3
- rasa/shared/nlu/training_data/training_data.py +18 -19
- rasa/shared/providers/_configs/litellm_router_client_config.py +220 -0
- rasa/shared/providers/_configs/model_group_config.py +167 -0
- rasa/shared/providers/_configs/openai_client_config.py +1 -1
- rasa/shared/providers/_configs/rasa_llm_client_config.py +73 -0
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +1 -0
- rasa/shared/providers/_configs/utils.py +16 -0
- rasa/shared/providers/_utils.py +79 -0
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +13 -29
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +54 -21
- rasa/shared/providers/embedding/default_litellm_embedding_client.py +24 -0
- rasa/shared/providers/embedding/litellm_router_embedding_client.py +135 -0
- rasa/shared/providers/llm/_base_litellm_client.py +34 -22
- rasa/shared/providers/llm/azure_openai_llm_client.py +50 -29
- rasa/shared/providers/llm/default_litellm_llm_client.py +24 -0
- rasa/shared/providers/llm/litellm_router_llm_client.py +182 -0
- rasa/shared/providers/llm/rasa_llm_client.py +112 -0
- rasa/shared/providers/llm/self_hosted_llm_client.py +5 -29
- rasa/shared/providers/mappings.py +19 -0
- rasa/shared/providers/router/__init__.py +0 -0
- rasa/shared/providers/router/_base_litellm_router_client.py +183 -0
- rasa/shared/providers/router/router_client.py +73 -0
- rasa/shared/utils/common.py +40 -24
- rasa/shared/utils/health_check/__init__.py +0 -0
- rasa/shared/utils/health_check/embeddings_health_check_mixin.py +31 -0
- rasa/shared/utils/health_check/health_check.py +258 -0
- rasa/shared/utils/health_check/llm_health_check_mixin.py +31 -0
- rasa/shared/utils/io.py +27 -6
- rasa/shared/utils/llm.py +353 -43
- rasa/shared/utils/schemas/events.py +2 -0
- rasa/shared/utils/schemas/model_config.yml +0 -10
- rasa/shared/utils/yaml.py +181 -38
- rasa/studio/data_handler.py +3 -1
- rasa/studio/upload.py +160 -74
- rasa/telemetry.py +94 -17
- rasa/tracing/config.py +3 -1
- rasa/tracing/instrumentation/attribute_extractors.py +95 -18
- rasa/tracing/instrumentation/instrumentation.py +121 -0
- rasa/utils/common.py +5 -0
- rasa/utils/endpoints.py +27 -1
- rasa/utils/io.py +8 -16
- rasa/utils/log_utils.py +9 -2
- rasa/utils/sanic_error_handler.py +32 -0
- rasa/validator.py +110 -4
- rasa/version.py +1 -1
- {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/METADATA +14 -12
- {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/RECORD +234 -183
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +0 -1
- rasa/core/channels/inspector/dist/assets/index-a5d3e69d.js +0 -1040
- rasa/core/channels/voice_aware/utils.py +0 -20
- rasa/llm_fine_tuning/notebooks/unsloth_finetuning.ipynb +0 -407
- /rasa/core/channels/{voice_aware → voice_ready}/__init__.py +0 -0
- /rasa/core/channels/{voice_native → voice_stream}/__init__.py +0 -0
- {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/NOTICE +0 -0
- {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/WHEEL +0 -0
- {rasa_pro-3.10.15.dist-info → rasa_pro-3.11.0.dist-info}/entry_points.txt +0 -0
|
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Text, Tuple, Union
|
|
|
5
5
|
|
|
6
6
|
import tiktoken
|
|
7
7
|
from numpy import ndarray
|
|
8
|
+
from rasa.dialogue_understanding.generator.constants import FLOW_RETRIEVAL_KEY
|
|
8
9
|
from rasa_sdk.grpc_py import action_webhook_pb2
|
|
9
10
|
|
|
10
11
|
from rasa.core.actions.action import DirectCustomActionExecutor
|
|
@@ -19,6 +20,7 @@ from rasa.core.processor import MessageProcessor
|
|
|
19
20
|
from rasa.core.tracker_store import TrackerStore
|
|
20
21
|
from rasa.dialogue_understanding.commands import Command
|
|
21
22
|
from rasa.dialogue_understanding.stack.dialogue_stack import DialogueStack
|
|
23
|
+
from rasa.dialogue_understanding.generator import LLMBasedCommandGenerator
|
|
22
24
|
from rasa.engine.graph import ExecutionContext, GraphModelConfiguration, GraphNode
|
|
23
25
|
from rasa.engine.training.graph_trainer import GraphTrainer
|
|
24
26
|
from rasa.shared.constants import (
|
|
@@ -27,6 +29,8 @@ from rasa.shared.constants import (
|
|
|
27
29
|
PROVIDER_CONFIG_KEY,
|
|
28
30
|
TIMEOUT_CONFIG_KEY,
|
|
29
31
|
DEPLOYMENT_CONFIG_KEY,
|
|
32
|
+
MODEL_GROUP_ID_CONFIG_KEY,
|
|
33
|
+
LLM_CONFIG_KEY,
|
|
30
34
|
)
|
|
31
35
|
from rasa.shared.core.constants import REQUESTED_SLOT
|
|
32
36
|
from rasa.shared.core.domain import Domain
|
|
@@ -50,10 +54,7 @@ if TYPE_CHECKING:
|
|
|
50
54
|
from rasa.core.policies.enterprise_search_policy import EnterpriseSearchPolicy
|
|
51
55
|
from rasa.core.policies.intentless_policy import IntentlessPolicy
|
|
52
56
|
from rasa.core.policies.policy import PolicyPrediction
|
|
53
|
-
from rasa.dialogue_understanding.generator import
|
|
54
|
-
CommandGenerator,
|
|
55
|
-
LLMBasedCommandGenerator,
|
|
56
|
-
)
|
|
57
|
+
from rasa.dialogue_understanding.generator import CommandGenerator
|
|
57
58
|
|
|
58
59
|
# This file contains all attribute extractors for tracing instrumentation.
|
|
59
60
|
# These are functions that are applied to the arguments of the wrapped function to be
|
|
@@ -300,22 +301,49 @@ def extract_attrs_for_command(
|
|
|
300
301
|
}
|
|
301
302
|
|
|
302
303
|
|
|
303
|
-
def extract_llm_config(
|
|
304
|
+
def extract_llm_config(
|
|
305
|
+
self: Any,
|
|
306
|
+
default_llm_config: Dict[str, Any],
|
|
307
|
+
default_embeddings_config: Dict[str, Any],
|
|
308
|
+
) -> Dict[str, Any]:
|
|
304
309
|
if isinstance(self, ContextualResponseRephraser):
|
|
305
|
-
|
|
310
|
+
# ContextualResponseRephraser is not a graph component, so it's
|
|
311
|
+
# not having a full config.
|
|
312
|
+
config = {"llm": self.llm_config}
|
|
306
313
|
else:
|
|
307
314
|
config = self.config
|
|
308
315
|
|
|
309
316
|
llm_property = combine_custom_and_default_config(
|
|
310
|
-
config.get(
|
|
317
|
+
config.get(LLM_CONFIG_KEY), default_llm_config
|
|
311
318
|
)
|
|
312
319
|
|
|
320
|
+
if isinstance(self, LLMBasedCommandGenerator):
|
|
321
|
+
flow_retrieval_config = config.get(FLOW_RETRIEVAL_KEY, {}) or {}
|
|
322
|
+
embeddings_property = combine_custom_and_default_config(
|
|
323
|
+
flow_retrieval_config.get(EMBEDDINGS_CONFIG_KEY),
|
|
324
|
+
default_embeddings_config,
|
|
325
|
+
)
|
|
326
|
+
else:
|
|
327
|
+
embeddings_property = combine_custom_and_default_config(
|
|
328
|
+
config.get(EMBEDDINGS_CONFIG_KEY), default_embeddings_config
|
|
329
|
+
)
|
|
330
|
+
|
|
313
331
|
attributes = {
|
|
314
332
|
"class_name": self.__class__.__name__,
|
|
333
|
+
# llm client attributes
|
|
315
334
|
"llm_model": str(llm_property.get(MODEL_CONFIG_KEY)),
|
|
316
335
|
"llm_type": str(llm_property.get(PROVIDER_CONFIG_KEY)),
|
|
317
|
-
"
|
|
336
|
+
"llm_model_group_id": str(llm_property.get(MODEL_GROUP_ID_CONFIG_KEY)),
|
|
318
337
|
"llm_temperature": str(llm_property.get("temperature")),
|
|
338
|
+
"llm_request_timeout": str(llm_property.get(TIMEOUT_CONFIG_KEY)),
|
|
339
|
+
# embedding client attributes
|
|
340
|
+
"embeddings_model": str(embeddings_property.get(MODEL_CONFIG_KEY)),
|
|
341
|
+
"embeddings_type": str(embeddings_property.get(PROVIDER_CONFIG_KEY)),
|
|
342
|
+
"embeddings_model_group_id": str(
|
|
343
|
+
embeddings_property.get(MODEL_GROUP_ID_CONFIG_KEY)
|
|
344
|
+
),
|
|
345
|
+
# TODO: Keeping this to avoid potential breaking changes
|
|
346
|
+
"embeddings": json.dumps(embeddings_property, sort_keys=True),
|
|
319
347
|
"request_timeout": str(llm_property.get(TIMEOUT_CONFIG_KEY)),
|
|
320
348
|
}
|
|
321
349
|
|
|
@@ -329,11 +357,16 @@ def extract_attrs_for_llm_based_command_generator(
|
|
|
329
357
|
self: "LLMBasedCommandGenerator",
|
|
330
358
|
prompt: str,
|
|
331
359
|
) -> Dict[str, Any]:
|
|
332
|
-
from rasa.dialogue_understanding.generator.constants import
|
|
333
|
-
|
|
360
|
+
from rasa.dialogue_understanding.generator.constants import DEFAULT_LLM_CONFIG
|
|
361
|
+
from rasa.dialogue_understanding.generator.flow_retrieval import (
|
|
362
|
+
DEFAULT_EMBEDDINGS_CONFIG,
|
|
334
363
|
)
|
|
335
364
|
|
|
336
|
-
attributes = extract_llm_config(
|
|
365
|
+
attributes = extract_llm_config(
|
|
366
|
+
self,
|
|
367
|
+
default_llm_config=DEFAULT_LLM_CONFIG,
|
|
368
|
+
default_embeddings_config=DEFAULT_EMBEDDINGS_CONFIG,
|
|
369
|
+
)
|
|
337
370
|
|
|
338
371
|
return extend_attributes_with_prompt_tokens_length(self, attributes, prompt)
|
|
339
372
|
|
|
@@ -344,7 +377,12 @@ def extract_attrs_for_contextual_response_rephraser(
|
|
|
344
377
|
) -> Dict[str, Any]:
|
|
345
378
|
from rasa.core.nlg.contextual_response_rephraser import DEFAULT_LLM_CONFIG
|
|
346
379
|
|
|
347
|
-
attributes = extract_llm_config(
|
|
380
|
+
attributes = extract_llm_config(
|
|
381
|
+
self,
|
|
382
|
+
default_llm_config=DEFAULT_LLM_CONFIG,
|
|
383
|
+
# rephraser is not using embeddings
|
|
384
|
+
default_embeddings_config={},
|
|
385
|
+
)
|
|
348
386
|
|
|
349
387
|
return extend_attributes_with_prompt_tokens_length(self, attributes, prompt)
|
|
350
388
|
|
|
@@ -355,7 +393,12 @@ def extract_attrs_for_create_history(
|
|
|
355
393
|
) -> Dict[str, Any]:
|
|
356
394
|
from rasa.core.nlg.contextual_response_rephraser import DEFAULT_LLM_CONFIG
|
|
357
395
|
|
|
358
|
-
return extract_llm_config(
|
|
396
|
+
return extract_llm_config(
|
|
397
|
+
self,
|
|
398
|
+
default_llm_config=DEFAULT_LLM_CONFIG,
|
|
399
|
+
# rephraser is not using embeddings
|
|
400
|
+
default_embeddings_config={},
|
|
401
|
+
)
|
|
359
402
|
|
|
360
403
|
|
|
361
404
|
def extract_attrs_for_generate(
|
|
@@ -371,6 +414,26 @@ def extract_attrs_for_generate(
|
|
|
371
414
|
}
|
|
372
415
|
|
|
373
416
|
|
|
417
|
+
def extract_attrs_for_performing_health_check(
|
|
418
|
+
custom_config: Optional[Dict[str, Any]],
|
|
419
|
+
default_config: Dict[str, Any],
|
|
420
|
+
log_source_method: str,
|
|
421
|
+
log_source_component: str,
|
|
422
|
+
) -> Dict[str, Any]:
|
|
423
|
+
from rasa.shared.utils.health_check.health_check import is_api_health_check_enabled
|
|
424
|
+
|
|
425
|
+
attrs = {
|
|
426
|
+
"api_health_check_enabled": is_api_health_check_enabled(),
|
|
427
|
+
"health_check_trigger_component": log_source_component,
|
|
428
|
+
"health_check_trigger_method": log_source_method,
|
|
429
|
+
}
|
|
430
|
+
if is_api_health_check_enabled():
|
|
431
|
+
attrs["config"] = json.dumps(
|
|
432
|
+
combine_custom_and_default_config(custom_config, default_config)
|
|
433
|
+
)
|
|
434
|
+
return attrs
|
|
435
|
+
|
|
436
|
+
|
|
374
437
|
def extract_attrs_for_execute_commands(
|
|
375
438
|
tracker: DialogueStateTracker,
|
|
376
439
|
all_flows: FlowsList,
|
|
@@ -580,9 +643,16 @@ def extract_attrs_for_intentless_policy_find_closest_response(
|
|
|
580
643
|
def extract_attrs_for_intentless_policy_generate_llm_answer(
|
|
581
644
|
self: "IntentlessPolicy", llm: "BaseLLM", prompt: str
|
|
582
645
|
) -> Dict[str, Any]:
|
|
583
|
-
from rasa.core.policies.intentless_policy import
|
|
646
|
+
from rasa.core.policies.intentless_policy import (
|
|
647
|
+
DEFAULT_LLM_CONFIG,
|
|
648
|
+
DEFAULT_EMBEDDINGS_CONFIG,
|
|
649
|
+
)
|
|
584
650
|
|
|
585
|
-
attributes = extract_llm_config(
|
|
651
|
+
attributes = extract_llm_config(
|
|
652
|
+
self,
|
|
653
|
+
default_llm_config=DEFAULT_LLM_CONFIG,
|
|
654
|
+
default_embeddings_config=DEFAULT_EMBEDDINGS_CONFIG,
|
|
655
|
+
)
|
|
586
656
|
|
|
587
657
|
return extend_attributes_with_prompt_tokens_length(self, attributes, prompt)
|
|
588
658
|
|
|
@@ -590,9 +660,16 @@ def extract_attrs_for_intentless_policy_generate_llm_answer(
|
|
|
590
660
|
def extract_attrs_for_enterprise_search_generate_llm_answer(
|
|
591
661
|
self: "EnterpriseSearchPolicy", llm: "BaseLLM", prompt: str
|
|
592
662
|
) -> Dict[str, Any]:
|
|
593
|
-
from rasa.core.policies.enterprise_search_policy import
|
|
663
|
+
from rasa.core.policies.enterprise_search_policy import (
|
|
664
|
+
DEFAULT_LLM_CONFIG,
|
|
665
|
+
DEFAULT_EMBEDDINGS_CONFIG,
|
|
666
|
+
)
|
|
594
667
|
|
|
595
|
-
attributes = extract_llm_config(
|
|
668
|
+
attributes = extract_llm_config(
|
|
669
|
+
self,
|
|
670
|
+
default_llm_config=DEFAULT_LLM_CONFIG,
|
|
671
|
+
default_embeddings_config=DEFAULT_EMBEDDINGS_CONFIG,
|
|
672
|
+
)
|
|
596
673
|
|
|
597
674
|
return extend_attributes_with_prompt_tokens_length(self, attributes, prompt)
|
|
598
675
|
|
|
@@ -664,7 +741,7 @@ def extract_attrs_for_custom_action_executor_run(
|
|
|
664
741
|
|
|
665
742
|
attrs: Dict[str, Any] = {
|
|
666
743
|
"class_name": self.__class__.__name__,
|
|
667
|
-
"action_name": self.action_name,
|
|
744
|
+
"action_name": self.action_name if hasattr(self, "action_name") else "None",
|
|
668
745
|
"sender_id": tracker.sender_id,
|
|
669
746
|
"url": str(url),
|
|
670
747
|
"actions_module": str(actions_module),
|
|
@@ -45,6 +45,7 @@ from rasa.dialogue_understanding.generator import (
|
|
|
45
45
|
MultiStepLLMCommandGenerator,
|
|
46
46
|
SingleStepLLMCommandGenerator,
|
|
47
47
|
)
|
|
48
|
+
from rasa.dialogue_understanding.generator.flow_retrieval import FlowRetrieval
|
|
48
49
|
from rasa.dialogue_understanding.generator.nlu_command_adapter import NLUCommandAdapter
|
|
49
50
|
from rasa.engine.graph import GraphNode
|
|
50
51
|
from rasa.engine.training.graph_trainer import GraphTrainer
|
|
@@ -283,6 +284,7 @@ SingleStepLLMCommandGeneratorType = TypeVar(
|
|
|
283
284
|
MultiStepLLMCommandGeneratorType = TypeVar(
|
|
284
285
|
"MultiStepLLMCommandGeneratorType", bound=MultiStepLLMCommandGenerator
|
|
285
286
|
)
|
|
287
|
+
FlowRetrievalType = TypeVar("FlowRetrievalType", bound=FlowRetrieval)
|
|
286
288
|
CommandType = TypeVar("CommandType", bound=Command)
|
|
287
289
|
PolicyType = TypeVar("PolicyType", bound=Policy)
|
|
288
290
|
InformationRetrievalType = TypeVar(
|
|
@@ -317,6 +319,7 @@ def instrument(
|
|
|
317
319
|
custom_action_executor_subclasses: Optional[
|
|
318
320
|
List[Type[CustomActionExecutor]]
|
|
319
321
|
] = None,
|
|
322
|
+
flow_retrieval_class: Optional[Type[FlowRetrievalType]] = None,
|
|
320
323
|
) -> None:
|
|
321
324
|
"""Substitute methods to be traced by their traced counterparts.
|
|
322
325
|
|
|
@@ -445,6 +448,12 @@ def instrument(
|
|
|
445
448
|
"_check_commands_against_startable_flows",
|
|
446
449
|
attribute_extractors.extract_attrs_for_check_commands_against_startable_flows,
|
|
447
450
|
)
|
|
451
|
+
_instrument_perform_health_check_method_for_component(
|
|
452
|
+
tracer_provider.get_tracer(llm_command_generator_class.__module__),
|
|
453
|
+
llm_command_generator_class,
|
|
454
|
+
"perform_llm_health_check",
|
|
455
|
+
attribute_extractors.extract_attrs_for_performing_health_check,
|
|
456
|
+
)
|
|
448
457
|
mark_class_as_instrumented(llm_command_generator_class)
|
|
449
458
|
|
|
450
459
|
if (
|
|
@@ -468,6 +477,14 @@ def instrument(
|
|
|
468
477
|
"_check_commands_against_startable_flows",
|
|
469
478
|
attribute_extractors.extract_attrs_for_check_commands_against_startable_flows,
|
|
470
479
|
)
|
|
480
|
+
_instrument_perform_health_check_method_for_component(
|
|
481
|
+
tracer_provider.get_tracer(
|
|
482
|
+
single_step_llm_command_generator_class.__module__
|
|
483
|
+
),
|
|
484
|
+
single_step_llm_command_generator_class,
|
|
485
|
+
"perform_llm_health_check",
|
|
486
|
+
attribute_extractors.extract_attrs_for_performing_health_check,
|
|
487
|
+
)
|
|
471
488
|
mark_class_as_instrumented(single_step_llm_command_generator_class)
|
|
472
489
|
|
|
473
490
|
if multi_step_llm_command_generator_class is not None and not class_is_instrumented(
|
|
@@ -488,8 +505,36 @@ def instrument(
|
|
|
488
505
|
),
|
|
489
506
|
multi_step_llm_command_generator_class,
|
|
490
507
|
)
|
|
508
|
+
_instrument_perform_health_check_method_for_component(
|
|
509
|
+
tracer_provider.get_tracer(
|
|
510
|
+
multi_step_llm_command_generator_class.__module__
|
|
511
|
+
),
|
|
512
|
+
multi_step_llm_command_generator_class,
|
|
513
|
+
"perform_llm_health_check",
|
|
514
|
+
attribute_extractors.extract_attrs_for_performing_health_check,
|
|
515
|
+
)
|
|
491
516
|
mark_class_as_instrumented(multi_step_llm_command_generator_class)
|
|
492
517
|
|
|
518
|
+
if (
|
|
519
|
+
any(
|
|
520
|
+
llm_based_command_generator_class is not None
|
|
521
|
+
for llm_based_command_generator_class in (
|
|
522
|
+
llm_command_generator_class,
|
|
523
|
+
single_step_llm_command_generator_class,
|
|
524
|
+
multi_step_llm_command_generator_class,
|
|
525
|
+
)
|
|
526
|
+
)
|
|
527
|
+
and flow_retrieval_class is not None
|
|
528
|
+
and not class_is_instrumented(flow_retrieval_class)
|
|
529
|
+
):
|
|
530
|
+
_instrument_perform_health_check_method_for_component(
|
|
531
|
+
tracer_provider.get_tracer(flow_retrieval_class.__module__),
|
|
532
|
+
flow_retrieval_class,
|
|
533
|
+
"perform_embeddings_health_check",
|
|
534
|
+
attribute_extractors.extract_attrs_for_performing_health_check,
|
|
535
|
+
)
|
|
536
|
+
mark_class_as_instrumented(flow_retrieval_class)
|
|
537
|
+
|
|
493
538
|
if command_subclasses:
|
|
494
539
|
for command_subclass in command_subclasses:
|
|
495
540
|
if command_subclass is not None and not class_is_instrumented(
|
|
@@ -524,6 +569,12 @@ def instrument(
|
|
|
524
569
|
"generate",
|
|
525
570
|
attribute_extractors.extract_attrs_for_generate,
|
|
526
571
|
)
|
|
572
|
+
_instrument_perform_health_check_method_for_component(
|
|
573
|
+
tracer_provider.get_tracer(contextual_response_rephraser_class.__module__),
|
|
574
|
+
contextual_response_rephraser_class,
|
|
575
|
+
"perform_llm_health_check",
|
|
576
|
+
attribute_extractors.extract_attrs_for_performing_health_check,
|
|
577
|
+
)
|
|
527
578
|
mark_class_as_instrumented(contextual_response_rephraser_class)
|
|
528
579
|
|
|
529
580
|
if not module_is_instrumented(COMMAND_PROCESSOR_MODULE_NAME):
|
|
@@ -755,6 +806,18 @@ def _instrument_enterprise_search_policy(
|
|
|
755
806
|
"_generate_llm_answer",
|
|
756
807
|
attribute_extractors.extract_attrs_for_enterprise_search_generate_llm_answer,
|
|
757
808
|
)
|
|
809
|
+
_instrument_perform_health_check_method_for_component(
|
|
810
|
+
tracer_provider.get_tracer(policy_class.__module__),
|
|
811
|
+
policy_class,
|
|
812
|
+
"perform_embeddings_health_check",
|
|
813
|
+
attribute_extractors.extract_attrs_for_performing_health_check,
|
|
814
|
+
)
|
|
815
|
+
_instrument_perform_health_check_method_for_component(
|
|
816
|
+
tracer_provider.get_tracer(policy_class.__module__),
|
|
817
|
+
policy_class,
|
|
818
|
+
"perform_llm_health_check",
|
|
819
|
+
attribute_extractors.extract_attrs_for_performing_health_check,
|
|
820
|
+
)
|
|
758
821
|
|
|
759
822
|
|
|
760
823
|
def _instrument_intentless_policy(
|
|
@@ -787,6 +850,18 @@ def _instrument_intentless_policy(
|
|
|
787
850
|
"_generate_llm_answer",
|
|
788
851
|
attribute_extractors.extract_attrs_for_intentless_policy_generate_llm_answer,
|
|
789
852
|
)
|
|
853
|
+
_instrument_perform_health_check_method_for_component(
|
|
854
|
+
tracer_provider.get_tracer(policy_class.__module__),
|
|
855
|
+
policy_class,
|
|
856
|
+
"perform_embeddings_health_check",
|
|
857
|
+
attribute_extractors.extract_attrs_for_performing_health_check,
|
|
858
|
+
)
|
|
859
|
+
_instrument_perform_health_check_method_for_component(
|
|
860
|
+
tracer_provider.get_tracer(policy_class.__module__),
|
|
861
|
+
policy_class,
|
|
862
|
+
"perform_llm_health_check",
|
|
863
|
+
attribute_extractors.extract_attrs_for_performing_health_check,
|
|
864
|
+
)
|
|
790
865
|
|
|
791
866
|
|
|
792
867
|
def _instrument_processor(
|
|
@@ -1139,6 +1214,52 @@ def _instrument_grpc_custom_action_executor(
|
|
|
1139
1214
|
logger.debug(f"Instrumented '{grpc_custom_action_executor_class.__name__}.run.")
|
|
1140
1215
|
|
|
1141
1216
|
|
|
1217
|
+
def _instrument_perform_health_check_method_for_component(
|
|
1218
|
+
tracer: Tracer,
|
|
1219
|
+
instrumented_class: Type,
|
|
1220
|
+
method_name: Text,
|
|
1221
|
+
attr_extractor: Optional[Callable] = None,
|
|
1222
|
+
return_value_attr_extractor: Optional[Callable] = None,
|
|
1223
|
+
) -> None:
|
|
1224
|
+
def tracing_perform_health_check_for_component(
|
|
1225
|
+
fn: Callable[..., S],
|
|
1226
|
+
) -> Callable[..., S]:
|
|
1227
|
+
@functools.wraps(fn)
|
|
1228
|
+
def wrapper(*args: Any, **kwargs: Any) -> S:
|
|
1229
|
+
# Check the first argument to adjust for self/cls depending on how
|
|
1230
|
+
# the static method from LLMHealthCheckMixin / EmbeddingsLLMHealthCheckMixin
|
|
1231
|
+
# is called.
|
|
1232
|
+
if args and isinstance(
|
|
1233
|
+
args[0], (instrumented_class, type(instrumented_class))
|
|
1234
|
+
):
|
|
1235
|
+
# The first argument is self/cls; align args to match the signature
|
|
1236
|
+
args = args[1:]
|
|
1237
|
+
|
|
1238
|
+
span_name = f"{instrumented_class.__name__}.{fn.__name__}"
|
|
1239
|
+
extracted_attrs = attr_extractor(*args, **kwargs) if attr_extractor else {}
|
|
1240
|
+
|
|
1241
|
+
with tracer.start_as_current_span(span_name) as span:
|
|
1242
|
+
result = fn(*args, **kwargs)
|
|
1243
|
+
|
|
1244
|
+
# Extract attributes from the return value, if an extractor is provided
|
|
1245
|
+
return_value_attributes = (
|
|
1246
|
+
return_value_attr_extractor(result, *args, **kwargs)
|
|
1247
|
+
if return_value_attr_extractor
|
|
1248
|
+
else {}
|
|
1249
|
+
)
|
|
1250
|
+
|
|
1251
|
+
span.set_attributes({**extracted_attrs, **return_value_attributes})
|
|
1252
|
+
return result
|
|
1253
|
+
|
|
1254
|
+
return wrapper
|
|
1255
|
+
|
|
1256
|
+
method_to_trace = getattr(instrumented_class, method_name)
|
|
1257
|
+
traced_method = tracing_perform_health_check_for_component(method_to_trace)
|
|
1258
|
+
setattr(instrumented_class, method_name, traced_method)
|
|
1259
|
+
|
|
1260
|
+
logger.debug(f"Instrumented '{instrumented_class.__name__}.{method_name}'.")
|
|
1261
|
+
|
|
1262
|
+
|
|
1142
1263
|
def _mangled_instrumented_boolean_attribute_name(instrumented_class: Type) -> Text:
|
|
1143
1264
|
# see https://peps.python.org/pep-0008/#method-names-and-instance-variables
|
|
1144
1265
|
# and https://stackoverflow.com/a/50401073
|
rasa/utils/common.py
CHANGED
|
@@ -90,6 +90,11 @@ EXPECTED_WARNINGS: List[Tuple[Type[Warning], str]] = [
|
|
|
90
90
|
# Ignore Keras DeprecationWarning since it requires that we
|
|
91
91
|
# upgrade tensorflow-macos to 2.13.0 version.
|
|
92
92
|
(DeprecationWarning, "invalid escape sequence*"),
|
|
93
|
+
# Ignore importlib open_text and read_text warnings for now
|
|
94
|
+
(
|
|
95
|
+
DeprecationWarning,
|
|
96
|
+
"https://importlib-resources.readthedocs.io/en/latest/using.html#migrating-from-legacy",
|
|
97
|
+
),
|
|
93
98
|
]
|
|
94
99
|
|
|
95
100
|
PYTHON_LOGGING_SCHEMA_DOCS = (
|
rasa/utils/endpoints.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import ssl
|
|
3
3
|
from types import ModuleType
|
|
4
|
-
from typing import Any, Optional, Text, Dict, Union
|
|
4
|
+
from typing import Any, List, Optional, Text, Dict, Union
|
|
5
5
|
|
|
6
6
|
import aiohttp
|
|
7
7
|
import structlog
|
|
@@ -41,6 +41,32 @@ def read_endpoint_config(
|
|
|
41
41
|
return None
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
def read_property_config_from_endpoints_file(
|
|
45
|
+
filename: str, property_name: str
|
|
46
|
+
) -> Optional[Union[Dict[str, Any], List]]:
|
|
47
|
+
"""Read a property from an endpoint configuration file."""
|
|
48
|
+
if not filename:
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
content = read_config_file(filename)
|
|
53
|
+
|
|
54
|
+
if content.get(property_name) is None:
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
return content[property_name]
|
|
58
|
+
except FileNotFoundError:
|
|
59
|
+
structlogger.error(
|
|
60
|
+
"endpoint.read.failed_no_such_file",
|
|
61
|
+
filename=os.path.abspath(filename),
|
|
62
|
+
event_info=(
|
|
63
|
+
"Failed to read endpoint configuration file - "
|
|
64
|
+
"the file was not found."
|
|
65
|
+
),
|
|
66
|
+
)
|
|
67
|
+
return None
|
|
68
|
+
|
|
69
|
+
|
|
44
70
|
def concat_url(base: Text, subpath: Optional[Text]) -> Text:
|
|
45
71
|
"""Append a subpath to a base url.
|
|
46
72
|
|
rasa/utils/io.py
CHANGED
|
@@ -18,7 +18,6 @@ from typing import (
|
|
|
18
18
|
Type,
|
|
19
19
|
Callable,
|
|
20
20
|
TYPE_CHECKING,
|
|
21
|
-
Pattern,
|
|
22
21
|
)
|
|
23
22
|
|
|
24
23
|
from ruamel import yaml
|
|
@@ -167,21 +166,14 @@ def create_validator(
|
|
|
167
166
|
return FunctionValidator
|
|
168
167
|
|
|
169
168
|
|
|
170
|
-
def
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
"\U00002702-\U000027b0"
|
|
179
|
-
"\U000024c2-\U0001f251"
|
|
180
|
-
"\u200d" # zero width joiner
|
|
181
|
-
"\u200c" # zero width non-joiner
|
|
182
|
-
"]+",
|
|
183
|
-
flags=re.UNICODE,
|
|
184
|
-
)
|
|
169
|
+
def remove_emojis(s: str) -> str:
|
|
170
|
+
import demoji
|
|
171
|
+
|
|
172
|
+
replaced = demoji.replace(s)
|
|
173
|
+
if replaced == s:
|
|
174
|
+
return s
|
|
175
|
+
# remove duplicate or trailing whitespaces if emojis were removed
|
|
176
|
+
return re.sub(r" +", " ", replaced).strip()
|
|
185
177
|
|
|
186
178
|
|
|
187
179
|
def are_directories_equal(dir1: Path, dir2: Path) -> bool:
|
rasa/utils/log_utils.py
CHANGED
|
@@ -78,6 +78,7 @@ def _anonymizer(
|
|
|
78
78
|
|
|
79
79
|
def configure_structlog(
|
|
80
80
|
log_level: Optional[int] = None,
|
|
81
|
+
include_time: bool = False,
|
|
81
82
|
) -> None:
|
|
82
83
|
"""Configure logging of the server."""
|
|
83
84
|
if log_level is None: # Log level NOTSET is 0 so we use `is None` here
|
|
@@ -114,6 +115,9 @@ def configure_structlog(
|
|
|
114
115
|
SentryProcessor(event_level=logging.FATAL),
|
|
115
116
|
]
|
|
116
117
|
|
|
118
|
+
if include_time:
|
|
119
|
+
shared_processors.append(structlog.processors.TimeStamper(fmt="iso"))
|
|
120
|
+
|
|
117
121
|
if not FORCE_JSON_LOGGING and sys.stderr.isatty():
|
|
118
122
|
# Pretty printing when we run in a terminal session.
|
|
119
123
|
# Automatically prints pretty tracebacks when "rich" is installed
|
|
@@ -143,11 +147,14 @@ def configure_structlog(
|
|
|
143
147
|
# logger.
|
|
144
148
|
cache_logger_on_first_use=True,
|
|
145
149
|
)
|
|
150
|
+
# doing logger creation inline, to prevent usage of unconfigured logger
|
|
151
|
+
structlog.get_logger().debug("structlog.configured")
|
|
146
152
|
|
|
147
153
|
|
|
148
154
|
def log_llm(logger: Any, log_module: str, log_event: str, **kwargs: Any) -> None:
|
|
149
|
-
"""Logs LLM-specific events depending on a flag passed through an
|
|
150
|
-
|
|
155
|
+
"""Logs LLM-specific events depending on a flag passed through an env var.
|
|
156
|
+
|
|
157
|
+
If the module's flag is set to INFO (e.g.
|
|
151
158
|
LOG_PROMPT_LLM_COMMAND_GENERATOR=INFO), its prompt is logged at INFO level,
|
|
152
159
|
overriding the general log level setting.
|
|
153
160
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from sanic import Sanic
|
|
2
|
+
from sanic.handlers import ErrorHandler
|
|
3
|
+
from sanic.request import Request
|
|
4
|
+
from sanic.exceptions import ServerError
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# TODO: remove custom handler when upgrading to sanic >= 24
|
|
8
|
+
# the underlying issue https://github.com/sanic-org/sanic/issues/2572
|
|
9
|
+
# has been fixed in sanic 24
|
|
10
|
+
class IgnoreWSServerErrorHandler(ErrorHandler):
|
|
11
|
+
@staticmethod
|
|
12
|
+
def log(request: Request, exception: Exception) -> None:
|
|
13
|
+
try:
|
|
14
|
+
if (
|
|
15
|
+
request.url.startswith("ws")
|
|
16
|
+
and isinstance(exception, ServerError)
|
|
17
|
+
and exception.args
|
|
18
|
+
and (
|
|
19
|
+
exception.args[0]
|
|
20
|
+
== "Invalid response type None (need HTTPResponse)"
|
|
21
|
+
)
|
|
22
|
+
):
|
|
23
|
+
# in case we are in a websocket connection, we don't want to log the
|
|
24
|
+
# the error, as this is a bug in sanic
|
|
25
|
+
return
|
|
26
|
+
except Exception:
|
|
27
|
+
pass
|
|
28
|
+
ErrorHandler.log(request, exception) # type: ignore
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def register_custom_sanic_error_handler(app: Sanic) -> None:
|
|
32
|
+
app.error_handler = IgnoreWSServerErrorHandler()
|