rasa-pro 3.13.0.dev5__py3-none-any.whl → 3.13.0.dev8__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 +0 -3
- rasa/api.py +5 -1
- rasa/cli/arguments/default_arguments.py +13 -1
- rasa/cli/arguments/train.py +2 -0
- rasa/cli/dialogue_understanding_test.py +1 -1
- rasa/cli/e2e_test.py +1 -1
- rasa/cli/evaluate.py +2 -2
- rasa/cli/export.py +3 -3
- rasa/cli/llm_fine_tuning.py +12 -11
- rasa/cli/project_templates/defaults.py +133 -0
- rasa/cli/run.py +1 -1
- rasa/cli/studio/link.py +53 -0
- rasa/cli/studio/pull.py +78 -0
- rasa/cli/studio/push.py +78 -0
- rasa/cli/studio/studio.py +12 -0
- rasa/cli/studio/upload.py +8 -0
- rasa/cli/train.py +2 -1
- rasa/cli/utils.py +1 -1
- rasa/cli/x.py +1 -1
- rasa/constants.py +4 -0
- rasa/core/__init__.py +0 -16
- rasa/core/actions/action.py +5 -1
- rasa/core/actions/action_repeat_bot_messages.py +18 -22
- rasa/core/actions/action_run_slot_rejections.py +0 -1
- rasa/core/agent.py +18 -3
- rasa/core/available_endpoints.py +146 -0
- rasa/core/brokers/kafka.py +4 -0
- rasa/core/brokers/pika.py +5 -2
- rasa/core/brokers/sql.py +1 -1
- rasa/core/channels/botframework.py +2 -2
- rasa/core/channels/channel.py +2 -2
- rasa/core/channels/hangouts.py +8 -5
- rasa/core/channels/inspector/.eslintrc.cjs +12 -6
- rasa/core/channels/inspector/.prettierrc +5 -0
- rasa/core/channels/inspector/README.md +10 -4
- rasa/core/channels/inspector/dist/assets/{arc-9f75cc3b.js → arc-c4b064fc.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-7f34db23.js → blockDiagram-38ab4fdb-215b5026.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-948bab2c.js → c4Diagram-3d4e48cf-2b54a0a3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-3730f5fd.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-53b0dd0e.js → classDiagram-70f12bd4-daacea5f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-fdf789e7.js → classDiagram-v2-f2320105-930d4dc2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-e847561e.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-87c4ece5.js → createText-2e5e7dd3-83c206ba.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-5a8b0749.js → edges-e0da2a9e-b0eb01d0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-66da90e2.js → erDiagram-9861fffd-17586500.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-10044f05.js → flowDb-956e92f1-be2a1776.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-f338f66a.js → flowDiagram-66a62f08-c2120ebd.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-efbbfe00.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-b13140aa.js → flowchart-elk-definition-4a651766-a6ab5c48.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-f2b4a55a.js → ganttDiagram-c361ad54-ef613457.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-dedc298d.js → gitGraphDiagram-72cf32ee-d59185b3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-4ede11ff.js → graph-0f155405.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-65549d37.js → index-3862675e-d5f1d1b7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3a23e736.js → index-47737d3a.js} +123 -123
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-65439671.js → infoDiagram-f8f76790-b07d141f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-56d03d98.js → journeyDiagram-49397b02-1936d429.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-dd48f7f4.js → layout-dde8d0f3.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-1569ad2c.js → line-0c2c7ee0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-48bf4935.js → linear-35dd89a4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-688504c1.js → mindmap-definition-fc14e90a-56192851.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-78b6d7e6.js → pieDiagram-8a3498a8-fc21ed78.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-048b84b3.js → quadrantDiagram-120e2f19-25e98518.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-dd67f107.js → requirementDiagram-deff3bca-546ff1f5.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-8128436e.js → sankeyDiagram-04a897e0-02d8b82d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-1a0d1461.js → sequenceDiagram-704730f1-3ca5a92e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-46d388ed.js → stateDiagram-587899a1-128ea07c.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-ea42951a.js → stateDiagram-v2-d93cdb3a-95f290af.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-7427ed0c.js → styles-6aaf32cf-4984898a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-ff5e5a16.js → styles-9a916d00-1bf266ba.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-7b3680cf.js → styles-c10674c1-60521c63.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-f860f2ad.js → svgDrawCommon-08f97a94-a25b6e12.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-2eebf0c8.js → timeline-definition-85554ec2-0fc086bf.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-5d7f4e96.js → xychartDiagram-e933f94c-44ee592e.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/package.json +3 -1
- rasa/core/channels/inspector/src/App.tsx +91 -90
- rasa/core/channels/inspector/src/components/Chat.tsx +45 -41
- rasa/core/channels/inspector/src/components/DiagramFlow.tsx +40 -40
- rasa/core/channels/inspector/src/components/DialogueInformation.tsx +57 -57
- rasa/core/channels/inspector/src/components/DialogueStack.tsx +36 -27
- rasa/core/channels/inspector/src/components/ExpandIcon.tsx +4 -4
- rasa/core/channels/inspector/src/components/FullscreenButton.tsx +7 -7
- rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +28 -12
- rasa/core/channels/inspector/src/components/NoActiveFlow.tsx +9 -9
- rasa/core/channels/inspector/src/components/RasaLogo.tsx +5 -5
- rasa/core/channels/inspector/src/components/RecruitmentPanel.tsx +55 -60
- rasa/core/channels/inspector/src/components/SaraDiagrams.tsx +5 -5
- rasa/core/channels/inspector/src/components/Slots.tsx +22 -22
- rasa/core/channels/inspector/src/components/Welcome.tsx +28 -31
- rasa/core/channels/inspector/src/helpers/audio/audiostream.ts +245 -0
- rasa/core/channels/inspector/src/helpers/audio/microphone-processor.js +12 -0
- rasa/core/channels/inspector/src/helpers/audio/playback-processor.js +36 -0
- rasa/core/channels/inspector/src/helpers/conversation.ts +7 -7
- rasa/core/channels/inspector/src/helpers/formatters.test.ts +181 -181
- rasa/core/channels/inspector/src/helpers/formatters.ts +111 -111
- rasa/core/channels/inspector/src/helpers/utils.ts +78 -61
- rasa/core/channels/inspector/src/main.tsx +8 -8
- rasa/core/channels/inspector/src/theme/Button/Button.ts +8 -8
- rasa/core/channels/inspector/src/theme/Heading/Heading.ts +7 -7
- rasa/core/channels/inspector/src/theme/Input/Input.ts +9 -9
- rasa/core/channels/inspector/src/theme/Link/Link.ts +6 -6
- rasa/core/channels/inspector/src/theme/Modal/Modal.ts +13 -13
- rasa/core/channels/inspector/src/theme/Table/Table.tsx +10 -10
- rasa/core/channels/inspector/src/theme/Tooltip/Tooltip.ts +5 -5
- rasa/core/channels/inspector/src/theme/base/breakpoints.ts +7 -7
- rasa/core/channels/inspector/src/theme/base/colors.ts +64 -64
- rasa/core/channels/inspector/src/theme/base/fonts/fontFaces.css +21 -18
- rasa/core/channels/inspector/src/theme/base/radii.ts +8 -8
- rasa/core/channels/inspector/src/theme/base/shadows.ts +5 -5
- rasa/core/channels/inspector/src/theme/base/sizes.ts +5 -5
- rasa/core/channels/inspector/src/theme/base/space.ts +12 -12
- rasa/core/channels/inspector/src/theme/base/styles.ts +5 -5
- rasa/core/channels/inspector/src/theme/base/typography.ts +12 -12
- rasa/core/channels/inspector/src/theme/base/zIndices.ts +3 -3
- rasa/core/channels/inspector/src/theme/index.ts +38 -38
- rasa/core/channels/inspector/src/types.ts +56 -50
- rasa/core/channels/inspector/yarn.lock +5 -0
- rasa/core/channels/mattermost.py +1 -1
- rasa/core/channels/rasa_chat.py +2 -4
- rasa/core/channels/rest.py +5 -4
- rasa/core/channels/studio_chat.py +3 -2
- rasa/core/channels/vier_cvg.py +1 -2
- rasa/core/channels/voice_ready/audiocodes.py +35 -25
- rasa/core/channels/voice_stream/audiocodes.py +7 -4
- rasa/core/channels/voice_stream/genesys.py +2 -2
- rasa/core/channels/voice_stream/twilio_media_streams.py +10 -5
- rasa/core/channels/voice_stream/voice_channel.py +33 -22
- rasa/core/evaluation/marker_tracker_loader.py +1 -1
- rasa/core/exporter.py +1 -1
- rasa/core/http_interpreter.py +3 -7
- rasa/core/jobs.py +2 -1
- rasa/core/nlg/contextual_response_rephraser.py +38 -11
- rasa/core/nlg/generator.py +0 -1
- rasa/core/nlg/interpolator.py +2 -3
- rasa/core/nlg/summarize.py +40 -6
- rasa/core/persistor.py +55 -20
- rasa/core/policies/enterprise_search_policy.py +290 -66
- rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2 +63 -0
- rasa/core/policies/flow_policy.py +1 -1
- rasa/core/policies/flows/flow_executor.py +96 -17
- rasa/core/policies/intentless_policy.py +24 -16
- rasa/core/processor.py +106 -53
- rasa/core/run.py +40 -13
- rasa/core/tracker_stores/__init__.py +0 -0
- rasa/core/{auth_retry_tracker_store.py → tracker_stores/auth_retry_tracker_store.py} +5 -1
- rasa/core/tracker_stores/dynamo_tracker_store.py +218 -0
- rasa/core/tracker_stores/mongo_tracker_store.py +206 -0
- rasa/core/tracker_stores/redis_tracker_store.py +219 -0
- rasa/core/tracker_stores/sql_tracker_store.py +555 -0
- rasa/core/tracker_stores/tracker_store.py +805 -0
- rasa/core/training/interactive.py +1 -1
- rasa/core/utils.py +24 -91
- rasa/dialogue_understanding/coexistence/intent_based_router.py +2 -1
- rasa/dialogue_understanding/coexistence/llm_based_router.py +8 -3
- rasa/dialogue_understanding/commands/can_not_handle_command.py +2 -0
- rasa/dialogue_understanding/commands/cancel_flow_command.py +2 -0
- rasa/dialogue_understanding/commands/chit_chat_answer_command.py +2 -0
- rasa/dialogue_understanding/commands/clarify_command.py +6 -2
- rasa/dialogue_understanding/commands/command_syntax_manager.py +1 -0
- rasa/dialogue_understanding/commands/human_handoff_command.py +2 -0
- rasa/dialogue_understanding/commands/knowledge_answer_command.py +2 -0
- rasa/dialogue_understanding/commands/repeat_bot_messages_command.py +2 -0
- rasa/dialogue_understanding/commands/set_slot_command.py +11 -1
- rasa/dialogue_understanding/commands/skip_question_command.py +2 -0
- rasa/dialogue_understanding/commands/start_flow_command.py +4 -0
- rasa/dialogue_understanding/commands/utils.py +26 -2
- rasa/dialogue_understanding/generator/__init__.py +7 -1
- rasa/dialogue_understanding/generator/command_generator.py +4 -2
- rasa/dialogue_understanding/generator/command_parser.py +2 -2
- rasa/dialogue_understanding/generator/command_parser_validator.py +63 -0
- rasa/dialogue_understanding/generator/constants.py +2 -2
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +1 -1
- rasa/dialogue_understanding/generator/prompt_templates/command_prompt_v3_gpt_4o_2024_11_20_template.jinja2 +78 -0
- rasa/dialogue_understanding/generator/single_step/compact_llm_command_generator.py +28 -463
- rasa/dialogue_understanding/generator/single_step/search_ready_llm_command_generator.py +147 -0
- rasa/dialogue_understanding/generator/single_step/single_step_based_llm_command_generator.py +477 -0
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +8 -58
- rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +37 -25
- rasa/dialogue_understanding/patterns/domain_for_patterns.py +190 -0
- rasa/dialogue_understanding/processor/command_processor.py +3 -3
- rasa/dialogue_understanding/processor/command_processor_component.py +3 -3
- rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +17 -4
- rasa/dialogue_understanding/utils.py +68 -12
- rasa/dialogue_understanding_test/du_test_case.py +1 -1
- rasa/dialogue_understanding_test/du_test_runner.py +4 -22
- rasa/dialogue_understanding_test/test_case_simulation/test_case_tracker_simulator.py +2 -6
- rasa/e2e_test/e2e_test_runner.py +1 -1
- rasa/engine/constants.py +1 -1
- rasa/engine/recipes/default_recipe.py +26 -2
- rasa/engine/validation.py +3 -2
- rasa/hooks.py +2 -30
- rasa/keys +1 -0
- rasa/llm_fine_tuning/annotation_module.py +39 -9
- rasa/llm_fine_tuning/conversations.py +3 -0
- rasa/llm_fine_tuning/llm_data_preparation_module.py +66 -49
- rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +4 -2
- rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +52 -44
- rasa/llm_fine_tuning/paraphrasing_module.py +10 -12
- rasa/llm_fine_tuning/storage.py +4 -4
- rasa/llm_fine_tuning/utils.py +63 -1
- rasa/model_manager/config.py +3 -1
- rasa/model_manager/model_api.py +89 -2
- rasa/model_manager/runner_service.py +8 -4
- rasa/model_manager/trainer_service.py +5 -4
- rasa/model_training.py +12 -3
- rasa/nlu/extractors/crf_entity_extractor.py +66 -16
- rasa/plugin.py +2 -12
- rasa/privacy/__init__.py +0 -0
- rasa/privacy/constants.py +83 -0
- rasa/privacy/event_broker_utils.py +77 -0
- rasa/privacy/privacy_config.py +281 -0
- rasa/privacy/privacy_config_schema.json +86 -0
- rasa/privacy/privacy_filter.py +340 -0
- rasa/privacy/privacy_manager.py +576 -0
- rasa/server.py +29 -4
- rasa/shared/constants.py +6 -0
- rasa/shared/core/constants.py +4 -3
- rasa/shared/core/domain.py +7 -0
- rasa/shared/core/events.py +99 -3
- rasa/shared/core/flows/flow.py +1 -2
- rasa/shared/core/flows/flows_yaml_schema.json +3 -0
- rasa/shared/core/flows/steps/collect.py +46 -2
- rasa/shared/core/slots.py +28 -0
- rasa/shared/exceptions.py +4 -0
- rasa/shared/providers/_configs/azure_openai_client_config.py +4 -0
- rasa/shared/providers/_configs/openai_client_config.py +4 -0
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +3 -0
- rasa/shared/providers/llm/_base_litellm_client.py +5 -2
- rasa/shared/utils/llm.py +161 -6
- rasa/shared/utils/yaml.py +32 -0
- rasa/studio/data_handler.py +3 -3
- rasa/studio/download/download.py +37 -60
- rasa/studio/download/flows.py +23 -31
- rasa/studio/link.py +200 -0
- rasa/studio/pull.py +94 -0
- rasa/studio/push.py +131 -0
- rasa/studio/upload.py +117 -67
- rasa/telemetry.py +84 -27
- rasa/tracing/config.py +4 -5
- rasa/tracing/constants.py +19 -1
- rasa/tracing/instrumentation/attribute_extractors.py +11 -3
- rasa/tracing/instrumentation/instrumentation.py +54 -3
- rasa/tracing/instrumentation/metrics.py +98 -15
- rasa/tracing/metric_instrument_provider.py +75 -3
- rasa/utils/common.py +1 -27
- rasa/utils/licensing.py +1 -2
- rasa/utils/log_utils.py +1 -45
- rasa/validator.py +2 -8
- rasa/version.py +1 -1
- {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/METADATA +8 -9
- {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/RECORD +254 -231
- rasa/anonymization/__init__.py +0 -2
- rasa/anonymization/anonymisation_rule_yaml_reader.py +0 -91
- rasa/anonymization/anonymization_pipeline.py +0 -286
- rasa/anonymization/anonymization_rule_executor.py +0 -266
- rasa/anonymization/anonymization_rule_orchestrator.py +0 -119
- rasa/anonymization/schemas/config.yml +0 -47
- rasa/anonymization/utils.py +0 -118
- rasa/core/channels/inspector/dist/assets/channel-dfa68278.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-edb7f119.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-65e7c670.js +0 -1
- rasa/core/channels/inspector/src/helpers/audiostream.ts +0 -191
- rasa/core/tracker_store.py +0 -1792
- {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.0.dev5.dist-info → rasa_pro-3.13.0.dev8.dist-info}/entry_points.txt +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import dataclasses
|
|
1
2
|
import importlib.resources
|
|
2
3
|
import json
|
|
3
4
|
import re
|
|
4
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Text
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Text
|
|
5
6
|
|
|
6
7
|
import dotenv
|
|
7
8
|
import structlog
|
|
@@ -9,6 +10,7 @@ from jinja2 import Template
|
|
|
9
10
|
from pydantic import ValidationError
|
|
10
11
|
|
|
11
12
|
import rasa.shared.utils.io
|
|
13
|
+
from rasa.core.available_endpoints import AvailableEndpoints
|
|
12
14
|
from rasa.core.constants import (
|
|
13
15
|
POLICY_MAX_HISTORY,
|
|
14
16
|
POLICY_PRIORITY,
|
|
@@ -23,7 +25,6 @@ from rasa.core.information_retrieval import (
|
|
|
23
25
|
)
|
|
24
26
|
from rasa.core.information_retrieval.faiss import FAISS_Store
|
|
25
27
|
from rasa.core.policies.policy import Policy, PolicyPrediction
|
|
26
|
-
from rasa.core.utils import AvailableEndpoints
|
|
27
28
|
from rasa.dialogue_understanding.generator.constants import (
|
|
28
29
|
LLM_CONFIG_KEY,
|
|
29
30
|
)
|
|
@@ -46,12 +47,17 @@ from rasa.graph_components.providers.forms_provider import Forms
|
|
|
46
47
|
from rasa.graph_components.providers.responses_provider import Responses
|
|
47
48
|
from rasa.shared.constants import (
|
|
48
49
|
EMBEDDINGS_CONFIG_KEY,
|
|
50
|
+
MAX_COMPLETION_TOKENS_CONFIG_KEY,
|
|
51
|
+
MAX_RETRIES_CONFIG_KEY,
|
|
49
52
|
MODEL_CONFIG_KEY,
|
|
50
53
|
MODEL_GROUP_ID_CONFIG_KEY,
|
|
51
54
|
MODEL_NAME_CONFIG_KEY,
|
|
52
55
|
OPENAI_PROVIDER,
|
|
53
56
|
PROMPT_CONFIG_KEY,
|
|
57
|
+
PROMPT_TEMPLATE_CONFIG_KEY,
|
|
54
58
|
PROVIDER_CONFIG_KEY,
|
|
59
|
+
RASA_PATTERN_CANNOT_HANDLE_NO_RELEVANT_ANSWER,
|
|
60
|
+
TEMPERATURE_CONFIG_KEY,
|
|
55
61
|
TIMEOUT_CONFIG_KEY,
|
|
56
62
|
)
|
|
57
63
|
from rasa.shared.core.constants import (
|
|
@@ -75,7 +81,6 @@ from rasa.shared.nlu.training_data.training_data import TrainingData
|
|
|
75
81
|
from rasa.shared.providers.embedding._langchain_embedding_client_adapter import (
|
|
76
82
|
_LangchainEmbeddingClientAdapter,
|
|
77
83
|
)
|
|
78
|
-
from rasa.shared.providers.llm.llm_client import LLMClient
|
|
79
84
|
from rasa.shared.providers.llm.llm_response import LLMResponse, measure_llm_latency
|
|
80
85
|
from rasa.shared.utils.cli import print_error_and_exit
|
|
81
86
|
from rasa.shared.utils.constants import (
|
|
@@ -110,7 +115,7 @@ if TYPE_CHECKING:
|
|
|
110
115
|
|
|
111
116
|
from rasa.utils.log_utils import log_llm
|
|
112
117
|
|
|
113
|
-
|
|
118
|
+
structlogger = structlog.get_logger()
|
|
114
119
|
|
|
115
120
|
dotenv.load_dotenv("./.env")
|
|
116
121
|
|
|
@@ -121,6 +126,7 @@ VECTOR_STORE_THRESHOLD_PROPERTY = "threshold"
|
|
|
121
126
|
TRACE_TOKENS_PROPERTY = "trace_prompt_tokens"
|
|
122
127
|
CITATION_ENABLED_PROPERTY = "citation_enabled"
|
|
123
128
|
USE_LLM_PROPERTY = "use_generative_llm"
|
|
129
|
+
CHECK_RELEVANCY_PROPERTY = "check_relevancy"
|
|
124
130
|
MAX_MESSAGES_IN_QUERY_KEY = "max_messages_in_query"
|
|
125
131
|
|
|
126
132
|
DEFAULT_VECTOR_STORE_TYPE = "faiss"
|
|
@@ -131,18 +137,22 @@ DEFAULT_VECTOR_STORE = {
|
|
|
131
137
|
VECTOR_STORE_THRESHOLD_PROPERTY: DEFAULT_VECTOR_STORE_THRESHOLD,
|
|
132
138
|
}
|
|
133
139
|
|
|
140
|
+
DEFAULT_CHECK_RELEVANCY_PROPERTY = False
|
|
141
|
+
DEFAULT_USE_LLM_PROPERTY = True
|
|
142
|
+
DEFAULT_CITATION_ENABLED_PROPERTY = False
|
|
143
|
+
|
|
134
144
|
DEFAULT_LLM_CONFIG = {
|
|
135
145
|
PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
|
|
136
146
|
MODEL_CONFIG_KEY: DEFAULT_OPENAI_CHAT_MODEL_NAME,
|
|
137
147
|
TIMEOUT_CONFIG_KEY: 10,
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
148
|
+
TEMPERATURE_CONFIG_KEY: 0.0,
|
|
149
|
+
MAX_COMPLETION_TOKENS_CONFIG_KEY: 256,
|
|
150
|
+
MAX_RETRIES_CONFIG_KEY: 1,
|
|
141
151
|
}
|
|
142
152
|
|
|
143
153
|
DEFAULT_EMBEDDINGS_CONFIG = {
|
|
144
154
|
PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
|
|
145
|
-
|
|
155
|
+
MODEL_CONFIG_KEY: DEFAULT_OPENAI_EMBEDDING_MODEL_NAME,
|
|
146
156
|
}
|
|
147
157
|
|
|
148
158
|
ENTERPRISE_SEARCH_PROMPT_FILE_NAME = "enterprise_search_policy_prompt.jinja2"
|
|
@@ -159,6 +169,18 @@ DEFAULT_ENTERPRISE_SEARCH_PROMPT_WITH_CITATION_TEMPLATE = importlib.resources.re
|
|
|
159
169
|
"rasa.core.policies", "enterprise_search_prompt_with_citation_template.jinja2"
|
|
160
170
|
)
|
|
161
171
|
|
|
172
|
+
DEFAULT_ENTERPRISE_SEARCH_PROMPT_WITH_RELEVANCY_CHECK_AND_CITATION_TEMPLATE = (
|
|
173
|
+
importlib.resources.read_text(
|
|
174
|
+
"rasa.core.policies",
|
|
175
|
+
"enterprise_search_prompt_with_relevancy_check_and_citation_template.jinja2",
|
|
176
|
+
)
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# TODO: Update this pattern once the experiments are done
|
|
180
|
+
_ENTERPRISE_SEARCH_ANSWER_NOT_RELEVANT_PATTERN = re.compile(
|
|
181
|
+
r"\[NO_RELEVANT_ANSWER_FOUND\]"
|
|
182
|
+
)
|
|
183
|
+
|
|
162
184
|
|
|
163
185
|
class VectorStoreConnectionError(RasaException):
|
|
164
186
|
"""Exception raised for errors in connecting to the vector store."""
|
|
@@ -168,6 +190,12 @@ class VectorStoreConfigurationError(RasaException):
|
|
|
168
190
|
"""Exception raised for errors in vector store configuration."""
|
|
169
191
|
|
|
170
192
|
|
|
193
|
+
@dataclasses.dataclass
|
|
194
|
+
class _RelevancyCheckResponse:
|
|
195
|
+
answer: Optional[str]
|
|
196
|
+
relevant: bool
|
|
197
|
+
|
|
198
|
+
|
|
171
199
|
@DefaultV1Recipe.register(
|
|
172
200
|
DefaultV1Recipe.ComponentType.POLICY_WITH_END_TO_END_SUPPORT, is_trainable=True
|
|
173
201
|
)
|
|
@@ -217,6 +245,11 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
217
245
|
"""Constructs a new Policy object."""
|
|
218
246
|
super().__init__(config, model_storage, resource, execution_context, featurizer)
|
|
219
247
|
|
|
248
|
+
# Check for deprecated keys and issue a warning if those are used
|
|
249
|
+
self._check_config_keys_and_warn_if_deprecated()
|
|
250
|
+
# Check for mutual exclusivity of extractive and generative search
|
|
251
|
+
self._check_and_warn_mutual_exclusivity_of_extractive_and_generative_search()
|
|
252
|
+
|
|
220
253
|
# Resolve LLM config
|
|
221
254
|
self.config[LLM_CONFIG_KEY] = resolve_model_client_config(
|
|
222
255
|
self.config.get(LLM_CONFIG_KEY), EnterpriseSearchPolicy.__name__
|
|
@@ -231,6 +264,9 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
231
264
|
self.vector_store_config = self.config.get(
|
|
232
265
|
VECTOR_STORE_PROPERTY, DEFAULT_VECTOR_STORE
|
|
233
266
|
)
|
|
267
|
+
self.vector_search_threshold = self.vector_store_config.get(
|
|
268
|
+
VECTOR_STORE_THRESHOLD_PROPERTY, DEFAULT_VECTOR_STORE_THRESHOLD
|
|
269
|
+
)
|
|
234
270
|
|
|
235
271
|
# Embeddings configuration for encoding the search query
|
|
236
272
|
self.embeddings_config = (
|
|
@@ -246,30 +282,77 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
246
282
|
# Maximum number of messages to include in the search query
|
|
247
283
|
self.max_messages_in_query = self.config.get(MAX_MESSAGES_IN_QUERY_KEY, 2)
|
|
248
284
|
|
|
249
|
-
#
|
|
285
|
+
# Boolean to enable/disable tracing of prompt tokens
|
|
250
286
|
self.trace_prompt_tokens = self.config.get(TRACE_TOKENS_PROPERTY, False)
|
|
251
287
|
|
|
252
|
-
#
|
|
253
|
-
self.use_llm = self.config.get(USE_LLM_PROPERTY,
|
|
288
|
+
# Boolean to enable/disable the use of LLM for response generation
|
|
289
|
+
self.use_llm = self.config.get(USE_LLM_PROPERTY, DEFAULT_USE_LLM_PROPERTY)
|
|
254
290
|
|
|
255
|
-
#
|
|
256
|
-
|
|
291
|
+
# Boolean to enable/disable citation generation. This flag enables citation
|
|
292
|
+
# logic, but it only takes effect if `use_llm` is True.
|
|
293
|
+
self.citation_enabled = self.config.get(
|
|
294
|
+
CITATION_ENABLED_PROPERTY, DEFAULT_CITATION_ENABLED_PROPERTY
|
|
295
|
+
)
|
|
257
296
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
297
|
+
# Boolean to enable/disable the use of relevancy check alongside answer
|
|
298
|
+
# generation. This flag enables citation logic, but it only takes effect if
|
|
299
|
+
# `use_llm` is True.
|
|
300
|
+
self.relevancy_check_enabled = self.config.get(
|
|
301
|
+
CHECK_RELEVANCY_PROPERTY, DEFAULT_CHECK_RELEVANCY_PROPERTY
|
|
263
302
|
)
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
303
|
+
|
|
304
|
+
# Resolve the prompt template. The prompt will only be used if the 'use_llm' is
|
|
305
|
+
# set to True.
|
|
306
|
+
self.prompt_template = prompt_template or self._resolve_prompt_template(
|
|
307
|
+
self.config, LOG_COMPONENT_SOURCE_METHOD_INIT
|
|
269
308
|
)
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
309
|
+
|
|
310
|
+
def _check_config_keys_and_warn_if_deprecated(self) -> None:
|
|
311
|
+
"""Checks and warns about deprecated config parameters."""
|
|
312
|
+
if (
|
|
313
|
+
PROMPT_CONFIG_KEY in self.config
|
|
314
|
+
and PROMPT_TEMPLATE_CONFIG_KEY in self.config
|
|
315
|
+
):
|
|
316
|
+
structlogger.warning(
|
|
317
|
+
"enterprise_search_policy.init"
|
|
318
|
+
".both_deprecated_and_non_deprecated_config_keys_used_at_the_same_time",
|
|
319
|
+
event_info=(
|
|
320
|
+
f"Both '{PROMPT_CONFIG_KEY}' and '{PROMPT_TEMPLATE_CONFIG_KEY}' "
|
|
321
|
+
f"are present in the config. '{PROMPT_CONFIG_KEY}' will be ignored "
|
|
322
|
+
f"in favor of {PROMPT_TEMPLATE_CONFIG_KEY}."
|
|
323
|
+
),
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
# 'prompt' config key is deprecated in favor of 'prompt_template'
|
|
327
|
+
if PROMPT_CONFIG_KEY in self.config:
|
|
328
|
+
structlogger.warning(
|
|
329
|
+
"enterprise_search_policy.init.deprecated_config_key",
|
|
330
|
+
event_info=(
|
|
331
|
+
f"The config parameter '{PROMPT_CONFIG_KEY}' is deprecated "
|
|
332
|
+
"and will be removed in Rasa 4.0.0. "
|
|
333
|
+
f"Please use the config parameter '{PROMPT_TEMPLATE_CONFIG_KEY}'"
|
|
334
|
+
f"instead. "
|
|
335
|
+
),
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
def _check_and_warn_mutual_exclusivity_of_extractive_and_generative_search(
|
|
339
|
+
self,
|
|
340
|
+
) -> None:
|
|
341
|
+
if self.config.get(
|
|
342
|
+
CHECK_RELEVANCY_PROPERTY, DEFAULT_CHECK_RELEVANCY_PROPERTY
|
|
343
|
+
) and not self.config.get(USE_LLM_PROPERTY, DEFAULT_USE_LLM_PROPERTY):
|
|
344
|
+
structlogger.warning(
|
|
345
|
+
"enterprise_search_policy.init"
|
|
346
|
+
".relevancy_check_enabled_with_disabled_generative_search",
|
|
347
|
+
event_info=(
|
|
348
|
+
f"The config parameter '{CHECK_RELEVANCY_PROPERTY}' is set to"
|
|
349
|
+
f"'True', but the generative search is disabled (config"
|
|
350
|
+
f"parameter '{USE_LLM_PROPERTY}' is set to 'False'). As a result, "
|
|
351
|
+
"the relevancy check for the generative search will be disabled. "
|
|
352
|
+
f"To use this check, set the config parameter '{USE_LLM_PROPERTY}' "
|
|
353
|
+
f"to `True`."
|
|
354
|
+
),
|
|
355
|
+
)
|
|
273
356
|
|
|
274
357
|
@classmethod
|
|
275
358
|
def _create_plain_embedder(cls, config: Dict[Text, Any]) -> "Embeddings":
|
|
@@ -363,7 +446,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
363
446
|
try:
|
|
364
447
|
embeddings = self._create_plain_embedder(self.config)
|
|
365
448
|
except (ValidationError, Exception) as e:
|
|
366
|
-
|
|
449
|
+
structlogger.error(
|
|
367
450
|
"enterprise_search_policy.train.embedder_instantiation_failed",
|
|
368
451
|
message="Unable to instantiate the embedding client.",
|
|
369
452
|
error=e,
|
|
@@ -374,7 +457,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
374
457
|
)
|
|
375
458
|
|
|
376
459
|
if store_type == DEFAULT_VECTOR_STORE_TYPE:
|
|
377
|
-
|
|
460
|
+
structlogger.info("enterprise_search_policy.train.faiss")
|
|
378
461
|
with self._model_storage.write_to(self._resource) as path:
|
|
379
462
|
self.vector_store = FAISS_Store(
|
|
380
463
|
docs_folder=self.vector_store_config.get(SOURCE_PROPERTY),
|
|
@@ -383,7 +466,9 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
383
466
|
create_index=True,
|
|
384
467
|
)
|
|
385
468
|
else:
|
|
386
|
-
|
|
469
|
+
structlogger.info(
|
|
470
|
+
"enterprise_search_policy.train.custom", store_type=store_type
|
|
471
|
+
)
|
|
387
472
|
|
|
388
473
|
# telemetry call to track training completion
|
|
389
474
|
track_enterprise_search_policy_train_completed(
|
|
@@ -399,6 +484,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
399
484
|
or self.llm_config.get(MODEL_NAME_CONFIG_KEY),
|
|
400
485
|
llm_model_group_id=self.llm_config.get(MODEL_GROUP_ID_CONFIG_KEY),
|
|
401
486
|
citation_enabled=self.citation_enabled,
|
|
487
|
+
relevancy_check_enabled=self.relevancy_check_enabled,
|
|
402
488
|
)
|
|
403
489
|
self.persist()
|
|
404
490
|
return self._resource
|
|
@@ -451,7 +537,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
451
537
|
config = endpoints.vector_store if endpoints else None
|
|
452
538
|
store_type = self.vector_store_config.get(VECTOR_STORE_TYPE_PROPERTY)
|
|
453
539
|
if config is None and store_type != DEFAULT_VECTOR_STORE_TYPE:
|
|
454
|
-
|
|
540
|
+
structlogger.error(
|
|
455
541
|
"enterprise_search_policy._connect_vector_store_or_raise.no_config"
|
|
456
542
|
)
|
|
457
543
|
raise VectorStoreConfigurationError(
|
|
@@ -461,7 +547,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
461
547
|
try:
|
|
462
548
|
self.vector_store.connect(config) # type: ignore
|
|
463
549
|
except Exception as e:
|
|
464
|
-
|
|
550
|
+
structlogger.error(
|
|
465
551
|
"enterprise_search_policy._connect_vector_store_or_raise.connect_error",
|
|
466
552
|
error=e,
|
|
467
553
|
config=config,
|
|
@@ -487,14 +573,14 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
487
573
|
transcript.append(sanitize_message_for_prompt(event.text))
|
|
488
574
|
|
|
489
575
|
search_query = " ".join(transcript[-history:][::-1])
|
|
490
|
-
|
|
576
|
+
structlogger.debug("search_query", search_query=search_query)
|
|
491
577
|
return search_query
|
|
492
578
|
|
|
493
579
|
async def predict_action_probabilities( # type: ignore[override]
|
|
494
580
|
self,
|
|
495
581
|
tracker: DialogueStateTracker,
|
|
496
582
|
domain: Domain,
|
|
497
|
-
endpoints: Optional[AvailableEndpoints],
|
|
583
|
+
endpoints: Optional[AvailableEndpoints] = None,
|
|
498
584
|
rule_only_data: Optional[Dict[Text, Any]] = None,
|
|
499
585
|
**kwargs: Any,
|
|
500
586
|
) -> PolicyPrediction:
|
|
@@ -513,23 +599,20 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
513
599
|
The prediction.
|
|
514
600
|
"""
|
|
515
601
|
logger_key = "enterprise_search_policy.predict_action_probabilities"
|
|
516
|
-
|
|
517
|
-
VECTOR_STORE_THRESHOLD_PROPERTY, DEFAULT_VECTOR_STORE_THRESHOLD
|
|
518
|
-
)
|
|
519
|
-
llm = llm_factory(self.config.get(LLM_CONFIG_KEY), DEFAULT_LLM_CONFIG)
|
|
602
|
+
|
|
520
603
|
if not self.supports_current_stack_frame(
|
|
521
604
|
tracker, False, False
|
|
522
605
|
) or self.should_abstain_in_coexistence(tracker, True):
|
|
523
606
|
return self._prediction(self._default_predictions(domain))
|
|
524
607
|
|
|
525
608
|
if not self.vector_store:
|
|
526
|
-
|
|
609
|
+
structlogger.error(f"{logger_key}.no_vector_store")
|
|
527
610
|
return self._create_prediction_internal_error(domain, tracker)
|
|
528
611
|
|
|
529
612
|
try:
|
|
530
613
|
self._connect_vector_store_or_raise(endpoints)
|
|
531
614
|
except (VectorStoreConfigurationError, VectorStoreConnectionError) as e:
|
|
532
|
-
|
|
615
|
+
structlogger.error(f"{logger_key}.connection_error", error=e)
|
|
533
616
|
return self._create_prediction_internal_error(domain, tracker)
|
|
534
617
|
|
|
535
618
|
search_query = self._prepare_search_query(
|
|
@@ -541,20 +624,19 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
541
624
|
documents = await self.vector_store.search(
|
|
542
625
|
query=search_query,
|
|
543
626
|
tracker_state=tracker_state,
|
|
544
|
-
threshold=vector_search_threshold,
|
|
627
|
+
threshold=self.vector_search_threshold,
|
|
545
628
|
)
|
|
546
629
|
except InformationRetrievalException as e:
|
|
547
|
-
|
|
630
|
+
structlogger.error(f"{logger_key}.search_error", error=e)
|
|
548
631
|
return self._create_prediction_internal_error(domain, tracker)
|
|
549
632
|
|
|
550
633
|
if not documents.results:
|
|
551
|
-
|
|
634
|
+
structlogger.info(f"{logger_key}.no_documents")
|
|
552
635
|
return self._create_prediction_cannot_handle(domain, tracker)
|
|
553
636
|
|
|
554
637
|
if self.use_llm:
|
|
555
638
|
prompt = self._render_prompt(tracker, documents.results)
|
|
556
|
-
llm_response = await self.
|
|
557
|
-
llm_response = LLMResponse.ensure_llm_response(llm_response)
|
|
639
|
+
llm_response = await self._invoke_llm(prompt)
|
|
558
640
|
|
|
559
641
|
self._add_prompt_and_llm_response_to_latest_message(
|
|
560
642
|
tracker=tracker,
|
|
@@ -564,24 +646,38 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
564
646
|
)
|
|
565
647
|
|
|
566
648
|
if llm_response is None or not llm_response.choices:
|
|
567
|
-
|
|
649
|
+
structlogger.debug(f"{logger_key}.no_llm_response")
|
|
568
650
|
response = None
|
|
569
651
|
else:
|
|
570
652
|
llm_answer = llm_response.choices[0]
|
|
571
653
|
|
|
654
|
+
if self.relevancy_check_enabled:
|
|
655
|
+
relevancy_response = self._parse_llm_relevancy_check_response(
|
|
656
|
+
llm_answer
|
|
657
|
+
)
|
|
658
|
+
if not relevancy_response.relevant:
|
|
659
|
+
structlogger.debug(f"{logger_key}.answer_not_relevant")
|
|
660
|
+
return self._create_prediction_cannot_handle(
|
|
661
|
+
domain,
|
|
662
|
+
tracker,
|
|
663
|
+
RASA_PATTERN_CANNOT_HANDLE_NO_RELEVANT_ANSWER,
|
|
664
|
+
)
|
|
665
|
+
|
|
572
666
|
if self.citation_enabled:
|
|
573
667
|
llm_answer = self.post_process_citations(llm_answer)
|
|
574
668
|
|
|
575
|
-
|
|
669
|
+
structlogger.debug(
|
|
670
|
+
f"{logger_key}.llm_answer", prompt=prompt, llm_answer=llm_answer
|
|
671
|
+
)
|
|
576
672
|
response = llm_answer
|
|
577
673
|
else:
|
|
578
674
|
response = documents.results[0].metadata.get("answer", None)
|
|
579
675
|
if not response:
|
|
580
|
-
|
|
676
|
+
structlogger.error(
|
|
581
677
|
f"{logger_key}.answer_key_missing_in_metadata",
|
|
582
678
|
search_results=documents.results,
|
|
583
679
|
)
|
|
584
|
-
|
|
680
|
+
structlogger.debug(
|
|
585
681
|
"enterprise_search_policy.predict_action_probabilities.no_llm",
|
|
586
682
|
search_results=documents,
|
|
587
683
|
)
|
|
@@ -613,6 +709,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
613
709
|
or self.llm_config.get(MODEL_NAME_CONFIG_KEY),
|
|
614
710
|
llm_model_group_id=self.llm_config.get(MODEL_GROUP_ID_CONFIG_KEY),
|
|
615
711
|
citation_enabled=self.citation_enabled,
|
|
712
|
+
relevancy_check_enabled=self.relevancy_check_enabled,
|
|
616
713
|
)
|
|
617
714
|
return self._create_prediction(
|
|
618
715
|
domain=domain, tracker=tracker, action_metadata=action_metadata
|
|
@@ -636,11 +733,12 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
636
733
|
),
|
|
637
734
|
"docs": documents,
|
|
638
735
|
"slots": self._prepare_slots_for_template(tracker),
|
|
736
|
+
"check_relevancy": self.relevancy_check_enabled,
|
|
639
737
|
"citation_enabled": self.citation_enabled,
|
|
640
738
|
}
|
|
641
739
|
prompt = Template(self.prompt_template).render(**inputs)
|
|
642
740
|
log_llm(
|
|
643
|
-
logger=
|
|
741
|
+
logger=structlogger,
|
|
644
742
|
log_module="EnterpriseSearchPolicy",
|
|
645
743
|
log_event="enterprise_search_policy._render_prompt.prompt_rendered",
|
|
646
744
|
prompt=prompt,
|
|
@@ -648,9 +746,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
648
746
|
return prompt
|
|
649
747
|
|
|
650
748
|
@measure_llm_latency
|
|
651
|
-
async def
|
|
652
|
-
self, llm: LLMClient, prompt: Text
|
|
653
|
-
) -> Optional[LLMResponse]:
|
|
749
|
+
async def _invoke_llm(self, prompt: Text) -> Optional[LLMResponse]:
|
|
654
750
|
"""Fetches an LLM completion for the provided prompt.
|
|
655
751
|
|
|
656
752
|
Args:
|
|
@@ -660,17 +756,32 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
660
756
|
Returns:
|
|
661
757
|
An LLMResponse object, or None if the call fails.
|
|
662
758
|
"""
|
|
759
|
+
llm = llm_factory(self.config.get(LLM_CONFIG_KEY), DEFAULT_LLM_CONFIG)
|
|
663
760
|
try:
|
|
664
|
-
|
|
761
|
+
response = await llm.acompletion(prompt)
|
|
762
|
+
return LLMResponse.ensure_llm_response(response)
|
|
665
763
|
except Exception as e:
|
|
666
764
|
# unfortunately, langchain does not wrap LLM exceptions which means
|
|
667
765
|
# we have to catch all exceptions here
|
|
668
|
-
|
|
766
|
+
structlogger.error(
|
|
669
767
|
"enterprise_search_policy._generate_llm_answer.llm_error",
|
|
670
768
|
error=e,
|
|
671
769
|
)
|
|
672
770
|
return None
|
|
673
771
|
|
|
772
|
+
def _parse_llm_relevancy_check_response(
|
|
773
|
+
self, llm_answer: str
|
|
774
|
+
) -> _RelevancyCheckResponse:
|
|
775
|
+
"""Checks if the LLM response is relevant by parsing it."""
|
|
776
|
+
answer_relevant = not _ENTERPRISE_SEARCH_ANSWER_NOT_RELEVANT_PATTERN.search(
|
|
777
|
+
llm_answer
|
|
778
|
+
)
|
|
779
|
+
structlogger.debug("")
|
|
780
|
+
return _RelevancyCheckResponse(
|
|
781
|
+
answer=llm_answer if answer_relevant else None,
|
|
782
|
+
relevant=answer_relevant,
|
|
783
|
+
)
|
|
784
|
+
|
|
674
785
|
def _create_prediction(
|
|
675
786
|
self,
|
|
676
787
|
domain: Domain,
|
|
@@ -705,10 +816,18 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
705
816
|
)
|
|
706
817
|
|
|
707
818
|
def _create_prediction_cannot_handle(
|
|
708
|
-
self,
|
|
819
|
+
self,
|
|
820
|
+
domain: Domain,
|
|
821
|
+
tracker: DialogueStateTracker,
|
|
822
|
+
reason: Optional[str] = None,
|
|
709
823
|
) -> PolicyPrediction:
|
|
824
|
+
cannot_handle_stack_frame = (
|
|
825
|
+
CannotHandlePatternFlowStackFrame(reason=reason)
|
|
826
|
+
if reason is not None
|
|
827
|
+
else CannotHandlePatternFlowStackFrame()
|
|
828
|
+
)
|
|
710
829
|
return self._create_prediction_for_pattern(
|
|
711
|
-
domain, tracker,
|
|
830
|
+
domain, tracker, cannot_handle_stack_frame
|
|
712
831
|
)
|
|
713
832
|
|
|
714
833
|
def _create_prediction_for_pattern(
|
|
@@ -777,7 +896,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
777
896
|
path / ENTERPRISE_SEARCH_PROMPT_FILE_NAME
|
|
778
897
|
)
|
|
779
898
|
except (FileNotFoundError, FileIOException) as e:
|
|
780
|
-
|
|
899
|
+
structlogger.warning(
|
|
781
900
|
"enterprise_search_policy.load.failed", error=e, resource=resource.name
|
|
782
901
|
)
|
|
783
902
|
|
|
@@ -787,7 +906,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
787
906
|
|
|
788
907
|
embeddings = cls._create_plain_embedder(config)
|
|
789
908
|
|
|
790
|
-
|
|
909
|
+
structlogger.info("enterprise_search_policy.load", config=config)
|
|
791
910
|
if store_type == DEFAULT_VECTOR_STORE_TYPE:
|
|
792
911
|
# if a vector store is not specified,
|
|
793
912
|
# default to using FAISS with the index stored in the model
|
|
@@ -846,15 +965,12 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
846
965
|
@classmethod
|
|
847
966
|
def fingerprint_addon(cls, config: Dict[str, Any]) -> Optional[str]:
|
|
848
967
|
"""Add a fingerprint of enterprise search policy for the graph."""
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
prompt_template = get_prompt_template(
|
|
852
|
-
config.get(PROMPT_CONFIG_KEY),
|
|
853
|
-
DEFAULT_ENTERPRISE_SEARCH_PROMPT_TEMPLATE,
|
|
854
|
-
log_source_component=EnterpriseSearchPolicy.__name__,
|
|
855
|
-
log_source_method=LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON,
|
|
968
|
+
prompt_template = cls._resolve_prompt_template(
|
|
969
|
+
config, LOG_COMPONENT_SOURCE_METHOD_FINGERPRINT_ADDON
|
|
856
970
|
)
|
|
857
971
|
|
|
972
|
+
local_knowledge_data = cls._get_local_knowledge_data(config)
|
|
973
|
+
|
|
858
974
|
llm_config = resolve_model_client_config(
|
|
859
975
|
config.get(LLM_CONFIG_KEY), EnterpriseSearchPolicy.__name__
|
|
860
976
|
)
|
|
@@ -878,7 +994,7 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
878
994
|
Returns:
|
|
879
995
|
The post-processed LLM answer.
|
|
880
996
|
"""
|
|
881
|
-
|
|
997
|
+
structlogger.debug(
|
|
882
998
|
"enterprise_search_policy.post_process_citations", llm_answer=llm_answer
|
|
883
999
|
)
|
|
884
1000
|
|
|
@@ -979,3 +1095,111 @@ class EnterpriseSearchPolicy(LLMHealthCheckMixin, EmbeddingsHealthCheckMixin, Po
|
|
|
979
1095
|
log_source_method,
|
|
980
1096
|
EnterpriseSearchPolicy.__name__,
|
|
981
1097
|
)
|
|
1098
|
+
|
|
1099
|
+
@classmethod
|
|
1100
|
+
def get_system_default_prompt_based_on_config(cls, config: Dict[str, Any]) -> str:
|
|
1101
|
+
"""
|
|
1102
|
+
Resolves the default prompt template for Enterprise Search Policy based on
|
|
1103
|
+
the component's configuration.
|
|
1104
|
+
|
|
1105
|
+
- The old prompt is selected when both citation and relevancy check are either
|
|
1106
|
+
disabled or not set in the configuration.
|
|
1107
|
+
- The citation prompt is used when citation is enabled and relevancy check is
|
|
1108
|
+
either disabled or not set in the configuration.
|
|
1109
|
+
- The relevancy check prompt is only used when relevancy check is enabled.
|
|
1110
|
+
|
|
1111
|
+
Args:
|
|
1112
|
+
config: The component's configuration.
|
|
1113
|
+
|
|
1114
|
+
Returns:
|
|
1115
|
+
The resolved jinja prompt template as a string.
|
|
1116
|
+
"""
|
|
1117
|
+
|
|
1118
|
+
# Get the feature flags
|
|
1119
|
+
citation_enabled = config.get(
|
|
1120
|
+
CITATION_ENABLED_PROPERTY, DEFAULT_CITATION_ENABLED_PROPERTY
|
|
1121
|
+
)
|
|
1122
|
+
relevancy_check_enabled = config.get(
|
|
1123
|
+
CHECK_RELEVANCY_PROPERTY, DEFAULT_CHECK_RELEVANCY_PROPERTY
|
|
1124
|
+
)
|
|
1125
|
+
|
|
1126
|
+
# Based on the enabled features (citation, relevancy check) fetch the
|
|
1127
|
+
# appropriate default prompt
|
|
1128
|
+
default_prompt = cls._select_default_prompt_template_based_on_features(
|
|
1129
|
+
relevancy_check_enabled, citation_enabled
|
|
1130
|
+
)
|
|
1131
|
+
|
|
1132
|
+
return default_prompt
|
|
1133
|
+
|
|
1134
|
+
@classmethod
|
|
1135
|
+
def _resolve_prompt_template(
|
|
1136
|
+
cls,
|
|
1137
|
+
config: dict,
|
|
1138
|
+
log_source_method: Literal["init", "fingerprint"],
|
|
1139
|
+
) -> str:
|
|
1140
|
+
"""
|
|
1141
|
+
Resolves the prompt template to use for the Enterprise Search Policy's
|
|
1142
|
+
generative search.
|
|
1143
|
+
|
|
1144
|
+
Checks if a custom template is provided via component's configuration. If not,
|
|
1145
|
+
it selects the appropriate default template based on the enabled features
|
|
1146
|
+
(citation and relevancy check).
|
|
1147
|
+
|
|
1148
|
+
Args:
|
|
1149
|
+
config: The component's configuration.
|
|
1150
|
+
log_source_method: The name of the method or function emitting the log for
|
|
1151
|
+
better traceability.
|
|
1152
|
+
Returns:
|
|
1153
|
+
The resolved jinja prompt template as a string.
|
|
1154
|
+
"""
|
|
1155
|
+
|
|
1156
|
+
# Read the template path from the configuration if available.
|
|
1157
|
+
# The deprecated 'prompt' has a lower priority compared to 'prompt_template'
|
|
1158
|
+
config_defined_prompt = (
|
|
1159
|
+
config.get(PROMPT_TEMPLATE_CONFIG_KEY)
|
|
1160
|
+
or config.get(PROMPT_CONFIG_KEY)
|
|
1161
|
+
or None
|
|
1162
|
+
)
|
|
1163
|
+
# Select the default prompt based on the features set in the config.
|
|
1164
|
+
default_prompt = cls.get_system_default_prompt_based_on_config(config)
|
|
1165
|
+
|
|
1166
|
+
return get_prompt_template(
|
|
1167
|
+
config_defined_prompt,
|
|
1168
|
+
default_prompt,
|
|
1169
|
+
log_source_component=EnterpriseSearchPolicy.__name__,
|
|
1170
|
+
log_source_method=log_source_method,
|
|
1171
|
+
)
|
|
1172
|
+
|
|
1173
|
+
@classmethod
|
|
1174
|
+
def _select_default_prompt_template_based_on_features(
|
|
1175
|
+
cls,
|
|
1176
|
+
relevancy_check_enabled: bool,
|
|
1177
|
+
citation_enabled: bool,
|
|
1178
|
+
) -> str:
|
|
1179
|
+
"""
|
|
1180
|
+
Returns the appropriate default prompt template based on the feature flags.
|
|
1181
|
+
|
|
1182
|
+
The selection follows this priority:
|
|
1183
|
+
1. If relevancy check is enabled, return the prompt that includes both relevancy
|
|
1184
|
+
and citation blocks.
|
|
1185
|
+
2. If only citation is enabled, return the prompt with citation blocks.
|
|
1186
|
+
3. Otherwise, fall back to the legacy default prompt template.
|
|
1187
|
+
|
|
1188
|
+
Args:
|
|
1189
|
+
relevancy_check_enabled: Whether the LLM-generated answer should undergo
|
|
1190
|
+
relevancy evaluation.
|
|
1191
|
+
citation_enabled: Whether citations should be included in the generated
|
|
1192
|
+
answer.
|
|
1193
|
+
|
|
1194
|
+
Returns:
|
|
1195
|
+
The default prompt template corresponding to the enabled features.
|
|
1196
|
+
"""
|
|
1197
|
+
if relevancy_check_enabled:
|
|
1198
|
+
# ES prompt that has relevancy check and citations blocks
|
|
1199
|
+
return DEFAULT_ENTERPRISE_SEARCH_PROMPT_WITH_RELEVANCY_CHECK_AND_CITATION_TEMPLATE # noqa: E501
|
|
1200
|
+
elif citation_enabled:
|
|
1201
|
+
# ES prompt with citation's block - backward compatibility
|
|
1202
|
+
return DEFAULT_ENTERPRISE_SEARCH_PROMPT_WITH_CITATION_TEMPLATE
|
|
1203
|
+
else:
|
|
1204
|
+
# Legacy ES prompt - backward compatibility
|
|
1205
|
+
return DEFAULT_ENTERPRISE_SEARCH_PROMPT_TEMPLATE
|