rasa-pro 3.13.1a17__py3-none-any.whl → 3.13.2__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/cli/scaffold.py +3 -22
- rasa/core/actions/action.py +3 -5
- rasa/core/actions/direct_custom_actions_executor.py +8 -15
- rasa/core/channels/studio_chat.py +10 -34
- rasa/core/channels/voice_stream/asr/asr_engine.py +5 -1
- rasa/core/channels/voice_stream/asr/deepgram.py +5 -0
- rasa/core/channels/voice_stream/audiocodes.py +9 -4
- rasa/core/channels/voice_stream/jambonz.py +1 -1
- rasa/core/channels/voice_stream/voice_channel.py +7 -0
- rasa/core/policies/enterprise_search_policy.py +9 -8
- rasa/core/policies/flows/flow_executor.py +1 -8
- rasa/dialogue_understanding/commands/correct_slots_command.py +0 -10
- rasa/dialogue_understanding/generator/command_generator.py +5 -5
- rasa/dialogue_understanding/generator/flow_retrieval.py +9 -10
- rasa/dialogue_understanding/processor/command_processor.py +6 -1
- rasa/model_manager/model_api.py +3 -2
- rasa/model_manager/runner_service.py +1 -1
- rasa/model_manager/trainer_service.py +9 -12
- rasa/model_manager/utils.py +29 -1
- rasa/shared/core/domain.py +15 -62
- rasa/shared/core/flows/flow_step.py +1 -7
- rasa/shared/core/flows/yaml_flows_io.py +8 -16
- rasa/shared/core/slots.py +0 -4
- rasa/shared/importers/importer.py +0 -6
- rasa/shared/importers/utils.py +1 -77
- rasa/studio/upload.py +45 -10
- rasa/telemetry.py +1 -2
- rasa/utils/io.py +9 -27
- rasa/utils/json_utils.py +1 -6
- rasa/utils/log_utils.py +1 -5
- rasa/utils/plotting.py +1 -1
- rasa/validator.py +3 -7
- rasa/version.py +1 -1
- {rasa_pro-3.13.1a17.dist-info → rasa_pro-3.13.2.dist-info}/METADATA +8 -9
- {rasa_pro-3.13.1a17.dist-info → rasa_pro-3.13.2.dist-info}/RECORD +38 -260
- rasa/builder/README.md +0 -120
- rasa/builder/__init__.py +0 -0
- rasa/builder/config.py +0 -79
- rasa/builder/create_openai_vector_store.py +0 -228
- rasa/builder/exceptions.py +0 -55
- rasa/builder/inkeep-rag-response-schema.json +0 -64
- rasa/builder/inkeep_document_retrieval.py +0 -212
- rasa/builder/llm-helper-schema.json +0 -69
- rasa/builder/llm_context.py +0 -81
- rasa/builder/llm_helper_prompt.jinja2 +0 -245
- rasa/builder/llm_service.py +0 -317
- rasa/builder/logging_utils.py +0 -51
- rasa/builder/main.py +0 -147
- rasa/builder/models.py +0 -225
- rasa/builder/project_generator.py +0 -282
- rasa/builder/scrape_rasa_docs.py +0 -97
- rasa/builder/service.py +0 -742
- rasa/builder/skill_to_bot_prompt.jinja2 +0 -164
- rasa/builder/training_service.py +0 -132
- rasa/builder/validation_service.py +0 -93
- rasa/cli/project_templates/finance/actions/__init__.py +0 -0
- rasa/cli/project_templates/finance/actions/action_add_payee.py +0 -47
- rasa/cli/project_templates/finance/actions/action_ask_account.py +0 -50
- rasa/cli/project_templates/finance/actions/action_ask_account_from.py +0 -50
- rasa/cli/project_templates/finance/actions/action_ask_card.py +0 -47
- rasa/cli/project_templates/finance/actions/action_check_balance.py +0 -40
- rasa/cli/project_templates/finance/actions/action_check_card_existence.py +0 -35
- rasa/cli/project_templates/finance/actions/action_check_payee_existence.py +0 -40
- rasa/cli/project_templates/finance/actions/action_check_sufficient_funds.py +0 -41
- rasa/cli/project_templates/finance/actions/action_list_payees.py +0 -45
- rasa/cli/project_templates/finance/actions/action_process_immediate_payment.py +0 -18
- rasa/cli/project_templates/finance/actions/action_remove_payee.py +0 -49
- rasa/cli/project_templates/finance/actions/action_schedule_payment.py +0 -19
- rasa/cli/project_templates/finance/actions/action_session_start.py +0 -69
- rasa/cli/project_templates/finance/actions/action_update_card_status.py +0 -45
- rasa/cli/project_templates/finance/actions/action_validate_payment_date.py +0 -36
- rasa/cli/project_templates/finance/actions/database.py +0 -276
- rasa/cli/project_templates/finance/config.yml +0 -32
- rasa/cli/project_templates/finance/credentials.yml +0 -33
- rasa/cli/project_templates/finance/csvs/accounts.csv +0 -8
- rasa/cli/project_templates/finance/csvs/advisors.csv +0 -7
- rasa/cli/project_templates/finance/csvs/appointments.csv +0 -211
- rasa/cli/project_templates/finance/csvs/branches.csv +0 -10
- rasa/cli/project_templates/finance/csvs/cards.csv +0 -11
- rasa/cli/project_templates/finance/csvs/payees.csv +0 -10
- rasa/cli/project_templates/finance/csvs/transactions.csv +0 -71
- rasa/cli/project_templates/finance/csvs/users.csv +0 -4
- rasa/cli/project_templates/finance/data/flows/add_payee.yml +0 -29
- rasa/cli/project_templates/finance/data/flows/block_card.yml +0 -66
- rasa/cli/project_templates/finance/data/flows/check_balance.yml +0 -9
- rasa/cli/project_templates/finance/data/flows/list_payees.yml +0 -5
- rasa/cli/project_templates/finance/data/flows/remove_payee.yml +0 -21
- rasa/cli/project_templates/finance/data/flows/select_card.yml +0 -12
- rasa/cli/project_templates/finance/data/flows/transfer_money.yml +0 -67
- rasa/cli/project_templates/finance/data/flows/welcome.yml +0 -14
- rasa/cli/project_templates/finance/data/nlu.yml +0 -29
- rasa/cli/project_templates/finance/data/patterns/pattern_chitchat.yml +0 -7
- rasa/cli/project_templates/finance/data/patterns/pattern_completed.yml +0 -6
- rasa/cli/project_templates/finance/data/patterns/pattern_search.yml +0 -5
- rasa/cli/project_templates/finance/data/patterns/pattern_session_start.yml +0 -9
- rasa/cli/project_templates/finance/data/source/accounts.json +0 -51
- rasa/cli/project_templates/finance/data/source/advisors.json +0 -44
- rasa/cli/project_templates/finance/data/source/appointments.json +0 -1474
- rasa/cli/project_templates/finance/data/source/branches.json +0 -47
- rasa/cli/project_templates/finance/data/source/cards.json +0 -72
- rasa/cli/project_templates/finance/data/source/payees.json +0 -74
- rasa/cli/project_templates/finance/data/source/transactions.json +0 -492
- rasa/cli/project_templates/finance/data/source/users.json +0 -29
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/consequences_of_blocking_card.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/reasons_to_block_card.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/recovering_from_card_fraud.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/tips_for_card_security.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/block_card/what_to_do_if_card_is_lost.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/account_balance_security.txt +0 -7
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/common_balance_inquiries.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/methods_to_check_balance.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/understanding_balance_updates.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/check_balance/what_to_do_if_balance_is_incorrect.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/benefits_of_authorised_payees.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/common_issues_with_payees.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/general_payee_information.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/payee_management_tips.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/manage_payees/understanding_payee_types.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/common_transfer_errors.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/fees_for_transfers.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/general_transfer_information.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/security_tips_for_transfers.txt +0 -8
- rasa/cli/project_templates/finance/docs/bank_of_rasa_faq/transfer_money/transfer_processing_times.txt +0 -8
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part1.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part10.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part11.txt +0 -48
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part12.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part13.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part14.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part15.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part16.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part17.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part18.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part19.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part2.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part20.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part21.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part22.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part23.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part24.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part25.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part26.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part27.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part28.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part29.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part3.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part30.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part31.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part32.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part33.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part34.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part35.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part36.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part37.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part38.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part39.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part4.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part40.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part41.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part42.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part43.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part44.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part45.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part46.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part47.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part48.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part49.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part5.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part50.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part51.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part52.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part53.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part54.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part55.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part56.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part57.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part58.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part59.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part6.txt +0 -47
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part60.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part61.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part7.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part8.txt +0 -50
- rasa/cli/project_templates/finance/docs/huggingface_alpaca_dataset/questions_part9.txt +0 -47
- rasa/cli/project_templates/finance/domain/add_payee.yml +0 -47
- rasa/cli/project_templates/finance/domain/block_card.yml +0 -101
- rasa/cli/project_templates/finance/domain/check_balance.yml +0 -9
- rasa/cli/project_templates/finance/domain/default_actions.yml +0 -16
- rasa/cli/project_templates/finance/domain/default_flows.yml +0 -33
- rasa/cli/project_templates/finance/domain/list_payees.yml +0 -4
- rasa/cli/project_templates/finance/domain/remove_payee.yml +0 -16
- rasa/cli/project_templates/finance/domain/select_card.yml +0 -12
- rasa/cli/project_templates/finance/domain/transfer_money.yml +0 -79
- rasa/cli/project_templates/finance/endpoints.yml +0 -62
- rasa/cli/project_templates/finance/prompts/command-generator.jinja2 +0 -57
- rasa/cli/project_templates/finance/prompts/rephraser_demo_personality_prompt.jinja2 +0 -19
- rasa/cli/project_templates/finance/tests/conversation_repair/cancellations.yml +0 -12
- rasa/cli/project_templates/finance/tests/conversation_repair/cannot_handle.yml +0 -7
- rasa/cli/project_templates/finance/tests/conversation_repair/chitchat.yml +0 -7
- rasa/cli/project_templates/finance/tests/conversation_repair/clarification.yml +0 -9
- rasa/cli/project_templates/finance/tests/conversation_repair/completion.yml +0 -18
- rasa/cli/project_templates/finance/tests/conversation_repair/corrections.yml +0 -17
- rasa/cli/project_templates/finance/tests/conversation_repair/digressions.yml +0 -32
- rasa/cli/project_templates/finance/tests/conversation_repair/human_handoff.yml +0 -21
- rasa/cli/project_templates/finance/tests/conversation_repair/skipping_collect_steps.yml +0 -16
- rasa/cli/project_templates/finance/tests/demo_scripts/main.yml +0 -16
- rasa/cli/project_templates/finance/tests/happy_paths/balance_verification.yml +0 -15
- rasa/cli/project_templates/finance/tests/happy_paths/banking_questions.yml +0 -12
- rasa/cli/project_templates/finance/tests/happy_paths/card_blocking.yml +0 -52
- rasa/cli/project_templates/finance/tests/happy_paths/money_transfer.yml +0 -136
- rasa/cli/project_templates/finance/tests/happy_paths/payee_management.yml +0 -27
- rasa/cli/project_templates/finance/tests/happy_paths/user_greeted.yml +0 -5
- rasa/cli/project_templates/plain/actions/__init__.py +0 -0
- rasa/cli/project_templates/plain/config.yml +0 -17
- rasa/cli/project_templates/plain/credentials.yml +0 -33
- rasa/cli/project_templates/plain/data/patterns/pattern_session_start.yml +0 -7
- rasa/cli/project_templates/plain/domain.yml +0 -5
- rasa/cli/project_templates/plain/endpoints.yml +0 -58
- rasa/cli/project_templates/telco/actions/__init__.py +0 -0
- rasa/cli/project_templates/telco/actions/actions_billing.py +0 -197
- rasa/cli/project_templates/telco/actions/actions_get_data_from_db.py +0 -43
- rasa/cli/project_templates/telco/actions/actions_run_diagnostics.py +0 -23
- rasa/cli/project_templates/telco/actions/actions_session_start.py +0 -13
- rasa/cli/project_templates/telco/config.yml +0 -25
- rasa/cli/project_templates/telco/credentials.yml +0 -33
- rasa/cli/project_templates/telco/csvs/billing.csv +0 -10
- rasa/cli/project_templates/telco/csvs/customers.csv +0 -5
- rasa/cli/project_templates/telco/data/flows/flow_global.yml +0 -5
- rasa/cli/project_templates/telco/data/flows/flow_reboot_router.yml +0 -8
- rasa/cli/project_templates/telco/data/flows/flow_reset_router.yml +0 -7
- rasa/cli/project_templates/telco/data/flows/flow_solve_internet_issue.yml +0 -73
- rasa/cli/project_templates/telco/data/flows/flow_undertand_bill.yml +0 -45
- rasa/cli/project_templates/telco/data/patterns/pattern_completed.yml +0 -7
- rasa/cli/project_templates/telco/data/patterns/pattern_human_handoff.yml +0 -6
- rasa/cli/project_templates/telco/data/patterns/pattern_search.yml +0 -7
- rasa/cli/project_templates/telco/data/patterns/pattern_session_start.yml +0 -9
- rasa/cli/project_templates/telco/docs/reset_vs_rboot_router.txt +0 -1
- rasa/cli/project_templates/telco/docs/restart_router.txt +0 -6
- rasa/cli/project_templates/telco/docs/run_speed_test.txt +0 -6
- rasa/cli/project_templates/telco/domain/domain_global.yml +0 -29
- rasa/cli/project_templates/telco/domain/domain_patterns.yml +0 -17
- rasa/cli/project_templates/telco/domain/domain_reboot_router.yml +0 -20
- rasa/cli/project_templates/telco/domain/domain_reset_router.yml +0 -11
- rasa/cli/project_templates/telco/domain/domain_run_speed_test.yml +0 -24
- rasa/cli/project_templates/telco/domain/domain_solve_internet_issue.yml +0 -74
- rasa/cli/project_templates/telco/domain/domain_undertand_bill.yml +0 -102
- rasa/cli/project_templates/telco/endpoints.yml +0 -60
- rasa/cli/project_templates/telco/prompts/command-generator.jinja2 +0 -57
- rasa/cli/project_templates/telco/tests/e2e_results_failed.yml +0 -62
- rasa/cli/project_templates/telco/tests/e2e_results_passed.yml +0 -130
- rasa/cli/project_templates/telco/tests/e2e_test_cases/billing_test_cases.yml +0 -68
- rasa/cli/project_templates/telco/tests/e2e_test_cases/global_test_cases.yml +0 -13
- rasa/cli/project_templates/telco/tests/e2e_test_cases/internet_slow_test_case.yml +0 -47
- rasa/cli/project_templates/telco/tests/e2e_test_cases/out_of_scope_test_case.yml +0 -21
- rasa/cli/project_templates/telco/tests/e2e_test_cases/patterns_test_cases.yml +0 -15
- rasa/shared/importers/static.py +0 -63
- rasa/utils/openapi.py +0 -144
- {rasa_pro-3.13.1a17.dist-info → rasa_pro-3.13.2.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.1a17.dist-info → rasa_pro-3.13.2.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.1a17.dist-info → rasa_pro-3.13.2.dist-info}/entry_points.txt +0 -0
rasa/builder/llm_service.py
DELETED
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
"""Service for handling LLM interactions."""
|
|
2
|
-
|
|
3
|
-
import asyncio
|
|
4
|
-
import importlib
|
|
5
|
-
import json
|
|
6
|
-
from contextlib import asynccontextmanager
|
|
7
|
-
from copy import deepcopy
|
|
8
|
-
from typing import Any, AsyncGenerator, Dict, List, Optional
|
|
9
|
-
|
|
10
|
-
import importlib_resources
|
|
11
|
-
import openai
|
|
12
|
-
import structlog
|
|
13
|
-
from jinja2 import Template
|
|
14
|
-
from pydantic import ValidationError
|
|
15
|
-
|
|
16
|
-
from rasa.builder import config
|
|
17
|
-
from rasa.builder.exceptions import LLMGenerationError
|
|
18
|
-
from rasa.builder.inkeep_document_retrieval import InKeepDocumentRetrieval
|
|
19
|
-
from rasa.builder.llm_context import tracker_as_llm_context
|
|
20
|
-
from rasa.builder.models import Document, LLMBuilderContext, LLMHelperResponse
|
|
21
|
-
from rasa.constants import PACKAGE_NAME
|
|
22
|
-
from rasa.shared.constants import DOMAIN_SCHEMA_FILE, RESPONSES_SCHEMA_FILE
|
|
23
|
-
from rasa.shared.core.flows.yaml_flows_io import FLOWS_SCHEMA_FILE
|
|
24
|
-
from rasa.shared.utils.io import read_json_file
|
|
25
|
-
from rasa.shared.utils.yaml import read_schema_file
|
|
26
|
-
|
|
27
|
-
structlogger = structlog.get_logger()
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class LLMService:
|
|
31
|
-
"""Handles OpenAI LLM interactions with caching for efficiency."""
|
|
32
|
-
|
|
33
|
-
def __init__(self) -> None:
|
|
34
|
-
self._client: Optional[openai.AsyncOpenAI] = None
|
|
35
|
-
self._domain_schema: Optional[Dict[str, Any]] = None
|
|
36
|
-
self._flows_schema: Optional[Dict[str, Any]] = None
|
|
37
|
-
self._helper_schema: Optional[Dict[str, Any]] = None
|
|
38
|
-
|
|
39
|
-
@asynccontextmanager
|
|
40
|
-
async def _get_client(self) -> AsyncGenerator[openai.AsyncOpenAI, None]:
|
|
41
|
-
"""Get or create OpenAI client with proper resource management."""
|
|
42
|
-
if self._client is None:
|
|
43
|
-
self._client = openai.AsyncOpenAI(timeout=config.OPENAI_TIMEOUT)
|
|
44
|
-
|
|
45
|
-
try:
|
|
46
|
-
yield self._client
|
|
47
|
-
except Exception as e:
|
|
48
|
-
structlogger.error("llm.client_error", error=str(e))
|
|
49
|
-
raise
|
|
50
|
-
|
|
51
|
-
def _prepare_schemas(self) -> None:
|
|
52
|
-
"""Prepare and cache schemas for LLM generation."""
|
|
53
|
-
if self._domain_schema is None:
|
|
54
|
-
self._domain_schema = _prepare_domain_schema()
|
|
55
|
-
|
|
56
|
-
if self._flows_schema is None:
|
|
57
|
-
self._flows_schema = _prepare_flows_schema()
|
|
58
|
-
|
|
59
|
-
if self._helper_schema is None:
|
|
60
|
-
self._helper_schema = _load_helper_schema()
|
|
61
|
-
|
|
62
|
-
async def generate_rasa_project(
|
|
63
|
-
self, messages: List[Dict[str, Any]]
|
|
64
|
-
) -> Dict[str, Any]:
|
|
65
|
-
"""Generate Rasa project data using OpenAI."""
|
|
66
|
-
self._prepare_schemas()
|
|
67
|
-
|
|
68
|
-
try:
|
|
69
|
-
async with self._get_client() as client:
|
|
70
|
-
response = await client.chat.completions.create(
|
|
71
|
-
model=config.OPENAI_MODEL,
|
|
72
|
-
messages=messages,
|
|
73
|
-
temperature=config.OPENAI_TEMPERATURE,
|
|
74
|
-
response_format={
|
|
75
|
-
"type": "json_schema",
|
|
76
|
-
"json_schema": {
|
|
77
|
-
"name": "rasa_project",
|
|
78
|
-
"schema": {
|
|
79
|
-
"type": "object",
|
|
80
|
-
"properties": {
|
|
81
|
-
"domain": self._domain_schema,
|
|
82
|
-
"flows": self._flows_schema,
|
|
83
|
-
},
|
|
84
|
-
"required": ["domain", "flows"],
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
content = response.choices[0].message.content
|
|
91
|
-
if not content:
|
|
92
|
-
raise LLMGenerationError("Empty response from LLM")
|
|
93
|
-
|
|
94
|
-
try:
|
|
95
|
-
return json.loads(content)
|
|
96
|
-
except json.JSONDecodeError as e:
|
|
97
|
-
raise LLMGenerationError(f"Invalid JSON from LLM: {e}")
|
|
98
|
-
|
|
99
|
-
except openai.OpenAIError as e:
|
|
100
|
-
raise LLMGenerationError(f"OpenAI API error: {e}")
|
|
101
|
-
except asyncio.TimeoutError:
|
|
102
|
-
raise LLMGenerationError("LLM request timed out")
|
|
103
|
-
|
|
104
|
-
async def create_helper_messages(
|
|
105
|
-
self, llm_builder_context: LLMBuilderContext
|
|
106
|
-
) -> List[Dict[str, Any]]:
|
|
107
|
-
"""Create helper messages for LLM builder."""
|
|
108
|
-
# Format chat history for documentation search
|
|
109
|
-
chat_dump = self._format_chat_dump(llm_builder_context.chat_history)
|
|
110
|
-
|
|
111
|
-
# Search documentation
|
|
112
|
-
documentation_results = await self.search_documentation(chat_dump)
|
|
113
|
-
formatted_docs = self._format_documentation_results(documentation_results)
|
|
114
|
-
|
|
115
|
-
current_conversation = tracker_as_llm_context(llm_builder_context.tracker)
|
|
116
|
-
|
|
117
|
-
# Prepare LLM messages
|
|
118
|
-
system_messages = get_helper_messages(
|
|
119
|
-
current_conversation,
|
|
120
|
-
llm_builder_context.bot_logs,
|
|
121
|
-
llm_builder_context.chat_bot_files,
|
|
122
|
-
formatted_docs,
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
# Add user messages
|
|
126
|
-
messages = system_messages.copy()
|
|
127
|
-
for msg in llm_builder_context.chat_history:
|
|
128
|
-
messages.append(
|
|
129
|
-
{
|
|
130
|
-
"role": "user" if msg.type == "user" else "assistant",
|
|
131
|
-
"content": json.dumps(msg.content)
|
|
132
|
-
if isinstance(msg.content, list)
|
|
133
|
-
else msg.content,
|
|
134
|
-
}
|
|
135
|
-
)
|
|
136
|
-
return messages
|
|
137
|
-
|
|
138
|
-
async def generate_helper_response(
|
|
139
|
-
self, messages: List[Dict[str, Any]]
|
|
140
|
-
) -> LLMHelperResponse:
|
|
141
|
-
"""Generate helper response using OpenAI."""
|
|
142
|
-
self._prepare_schemas()
|
|
143
|
-
|
|
144
|
-
try:
|
|
145
|
-
async with self._get_client() as client:
|
|
146
|
-
response = await client.chat.completions.create(
|
|
147
|
-
model=config.OPENAI_MODEL,
|
|
148
|
-
messages=messages,
|
|
149
|
-
response_format={
|
|
150
|
-
"type": "json_schema",
|
|
151
|
-
"json_schema": {
|
|
152
|
-
"name": "llm_helper",
|
|
153
|
-
"schema": self._helper_schema,
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
content = response.choices[0].message.content
|
|
159
|
-
if not content:
|
|
160
|
-
raise LLMGenerationError("Empty response from LLM helper")
|
|
161
|
-
|
|
162
|
-
try:
|
|
163
|
-
return LLMHelperResponse.model_validate_json(json.loads(content))
|
|
164
|
-
except json.JSONDecodeError as e:
|
|
165
|
-
raise LLMGenerationError(f"Invalid JSON from LLM helper: {e}")
|
|
166
|
-
except ValidationError as e:
|
|
167
|
-
raise LLMGenerationError(f"Invalid JSON from LLM helper: {e}")
|
|
168
|
-
|
|
169
|
-
except openai.OpenAIError as e:
|
|
170
|
-
raise LLMGenerationError(f"OpenAI API error in helper: {e}")
|
|
171
|
-
except asyncio.TimeoutError:
|
|
172
|
-
raise LLMGenerationError("LLM helper request timed out")
|
|
173
|
-
|
|
174
|
-
async def search_documentation(
|
|
175
|
-
self, query: str, max_results: Optional[int] = None
|
|
176
|
-
) -> List[Document]:
|
|
177
|
-
"""Search documentation using OpenAI vector store."""
|
|
178
|
-
inkeep_document_retrieval = InKeepDocumentRetrieval()
|
|
179
|
-
documents = await inkeep_document_retrieval.retrieve_documents(query)
|
|
180
|
-
return documents
|
|
181
|
-
|
|
182
|
-
@staticmethod
|
|
183
|
-
def _format_chat_dump(messages: List[Dict[str, Any]]) -> str:
|
|
184
|
-
"""Format chat messages for documentation search."""
|
|
185
|
-
result = ""
|
|
186
|
-
for message in messages:
|
|
187
|
-
if message.type == "user":
|
|
188
|
-
content = (
|
|
189
|
-
message.content
|
|
190
|
-
if isinstance(message.content, str)
|
|
191
|
-
else str(message.content)
|
|
192
|
-
)
|
|
193
|
-
result += f"User: {content}\n"
|
|
194
|
-
else:
|
|
195
|
-
if isinstance(message.content, list):
|
|
196
|
-
for part in message.content:
|
|
197
|
-
if part.get("type") == "text":
|
|
198
|
-
result += f"Assistant: {part.get('text')}\n"
|
|
199
|
-
else:
|
|
200
|
-
result += f"Assistant: {message.content}\n"
|
|
201
|
-
return result
|
|
202
|
-
|
|
203
|
-
@staticmethod
|
|
204
|
-
def _format_documentation_results(results: List[Document]) -> str:
|
|
205
|
-
"""Format documentation search results."""
|
|
206
|
-
if not results:
|
|
207
|
-
return "<sources>No relevant documentation found.</sources>"
|
|
208
|
-
|
|
209
|
-
formatted_results = ""
|
|
210
|
-
for result in results:
|
|
211
|
-
formatted_result = f"<result url='{result.url}'>"
|
|
212
|
-
formatted_result += f"<content>{result.content}</content>"
|
|
213
|
-
formatted_results += formatted_result + "</result>"
|
|
214
|
-
|
|
215
|
-
return f"<sources>{formatted_results}</sources>"
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
# Schema preparation functions (stateless)
|
|
219
|
-
def _prepare_domain_schema() -> Dict[str, Any]:
|
|
220
|
-
"""Prepare domain schema by removing unnecessary parts."""
|
|
221
|
-
domain_schema = deepcopy(read_schema_file(DOMAIN_SCHEMA_FILE, PACKAGE_NAME, False))
|
|
222
|
-
|
|
223
|
-
if not isinstance(domain_schema, dict):
|
|
224
|
-
raise ValueError("Domain schema is not a dictionary")
|
|
225
|
-
|
|
226
|
-
# Remove parts not needed for CALM bots
|
|
227
|
-
unnecessary_keys = ["intents", "entities", "forms", "config", "session_config"]
|
|
228
|
-
|
|
229
|
-
for key in unnecessary_keys:
|
|
230
|
-
domain_schema["mapping"].pop(key, None)
|
|
231
|
-
|
|
232
|
-
# Remove problematic slot mappings
|
|
233
|
-
slot_mapping = domain_schema["mapping"]["slots"]["mapping"]["regex;([A-Za-z]+)"][
|
|
234
|
-
"mapping"
|
|
235
|
-
]
|
|
236
|
-
slot_mapping.pop("mappings", None)
|
|
237
|
-
slot_mapping.pop("validation", None)
|
|
238
|
-
|
|
239
|
-
# Add responses schema
|
|
240
|
-
domain_schema["mapping"]["responses"] = read_schema_file(
|
|
241
|
-
RESPONSES_SCHEMA_FILE, PACKAGE_NAME, False
|
|
242
|
-
)["schema;responses"]
|
|
243
|
-
|
|
244
|
-
return domain_schema
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
def _prepare_flows_schema() -> Dict[str, Any]:
|
|
248
|
-
"""Prepare flows schema by removing nlu_trigger."""
|
|
249
|
-
schema_file = str(
|
|
250
|
-
importlib_resources.files(PACKAGE_NAME).joinpath(FLOWS_SCHEMA_FILE)
|
|
251
|
-
)
|
|
252
|
-
flows_schema = deepcopy(read_json_file(schema_file))
|
|
253
|
-
flows_schema["$defs"]["flow"]["properties"].pop("nlu_trigger", None)
|
|
254
|
-
return flows_schema
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
def _load_helper_schema() -> Dict[str, Any]:
|
|
258
|
-
"""Load helper schema."""
|
|
259
|
-
return read_json_file(
|
|
260
|
-
importlib_resources.files(PACKAGE_NAME).joinpath(
|
|
261
|
-
"builder/llm-helper-schema.json"
|
|
262
|
-
)
|
|
263
|
-
)
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
# Template functions (stateless with caching)
|
|
267
|
-
_skill_template: Optional[Template] = None
|
|
268
|
-
_helper_template: Optional[Template] = None
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
def get_skill_generation_messages(
|
|
272
|
-
skill_description: str, project_data: Dict[str, str]
|
|
273
|
-
) -> List[Dict[str, Any]]:
|
|
274
|
-
"""Get messages for skill generation."""
|
|
275
|
-
global _skill_template
|
|
276
|
-
|
|
277
|
-
if _skill_template is None:
|
|
278
|
-
template_content = importlib.resources.read_text(
|
|
279
|
-
"rasa.builder",
|
|
280
|
-
"skill_to_bot_prompt.jinja2",
|
|
281
|
-
)
|
|
282
|
-
_skill_template = Template(template_content)
|
|
283
|
-
|
|
284
|
-
system_prompt = _skill_template.render(
|
|
285
|
-
skill_description=skill_description,
|
|
286
|
-
project_data=project_data,
|
|
287
|
-
)
|
|
288
|
-
return [{"role": "system", "content": system_prompt}]
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
def get_helper_messages(
|
|
292
|
-
current_conversation: str,
|
|
293
|
-
bot_logs: str,
|
|
294
|
-
chat_bot_files: Dict[str, str],
|
|
295
|
-
documentation_results: str,
|
|
296
|
-
) -> List[Dict[str, Any]]:
|
|
297
|
-
"""Get messages for helper response."""
|
|
298
|
-
global _helper_template
|
|
299
|
-
|
|
300
|
-
if _helper_template is None:
|
|
301
|
-
template_content = importlib.resources.read_text(
|
|
302
|
-
"rasa.builder",
|
|
303
|
-
"llm_helper_prompt.jinja2",
|
|
304
|
-
)
|
|
305
|
-
_helper_template = Template(template_content)
|
|
306
|
-
|
|
307
|
-
system_prompt = _helper_template.render(
|
|
308
|
-
current_conversation=current_conversation,
|
|
309
|
-
bot_logs=bot_logs,
|
|
310
|
-
chat_bot_files=chat_bot_files,
|
|
311
|
-
documentation_results=documentation_results,
|
|
312
|
-
)
|
|
313
|
-
return [{"role": "system", "content": system_prompt}]
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
# Global service instance
|
|
317
|
-
llm_service = LLMService()
|
rasa/builder/logging_utils.py
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"""Logging utilities for the prompt-to-bot service."""
|
|
2
|
-
|
|
3
|
-
import collections
|
|
4
|
-
import logging
|
|
5
|
-
import threading
|
|
6
|
-
from typing import Any, Deque, Dict
|
|
7
|
-
|
|
8
|
-
from rasa.builder import config
|
|
9
|
-
|
|
10
|
-
# Thread-safe deque for collecting recent logs
|
|
11
|
-
_recent_logs: Deque[str] = collections.deque(maxlen=config.MAX_LOG_ENTRIES)
|
|
12
|
-
_logs_lock = threading.RLock()
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def collecting_logs_processor(
|
|
16
|
-
logger: Any, log_level: str, event_dict: Dict[str, Any]
|
|
17
|
-
) -> Dict[str, Any]:
|
|
18
|
-
"""Structlog processor that collects recent log entries.
|
|
19
|
-
|
|
20
|
-
This processor is thread-safe and maintains a rolling buffer of recent logs.
|
|
21
|
-
"""
|
|
22
|
-
if log_level != logging.getLevelName(logging.DEBUG).lower():
|
|
23
|
-
event_message = event_dict.get("event_info") or event_dict.get("event", "")
|
|
24
|
-
log_entry = f"[{log_level}] {event_message}"
|
|
25
|
-
|
|
26
|
-
with _logs_lock:
|
|
27
|
-
_recent_logs.append(log_entry)
|
|
28
|
-
|
|
29
|
-
return event_dict
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def get_recent_logs() -> str:
|
|
33
|
-
"""Get recent log entries as a formatted string.
|
|
34
|
-
|
|
35
|
-
Returns:
|
|
36
|
-
Formatted string of recent log entries, one per line.
|
|
37
|
-
"""
|
|
38
|
-
with _logs_lock:
|
|
39
|
-
return "\n".join(list(_recent_logs))
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def clear_recent_logs() -> None:
|
|
43
|
-
"""Clear the recent logs buffer."""
|
|
44
|
-
with _logs_lock:
|
|
45
|
-
_recent_logs.clear()
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def get_log_count() -> int:
|
|
49
|
-
"""Get the current number of log entries."""
|
|
50
|
-
with _logs_lock:
|
|
51
|
-
return len(_recent_logs)
|
rasa/builder/main.py
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Main entry point for the prompt-to-bot service."""
|
|
3
|
-
|
|
4
|
-
import logging
|
|
5
|
-
import sys
|
|
6
|
-
from typing import Optional
|
|
7
|
-
|
|
8
|
-
import structlog
|
|
9
|
-
from sanic import HTTPResponse, Sanic
|
|
10
|
-
from sanic.request import Request
|
|
11
|
-
from sanic_openapi import openapi3_blueprint
|
|
12
|
-
|
|
13
|
-
import rasa.core.utils
|
|
14
|
-
from rasa.builder import config
|
|
15
|
-
from rasa.builder.logging_utils import collecting_logs_processor
|
|
16
|
-
from rasa.builder.service import bp, setup_project_generator
|
|
17
|
-
from rasa.core.channels.studio_chat import StudioChatInput
|
|
18
|
-
from rasa.server import configure_cors
|
|
19
|
-
from rasa.utils.common import configure_logging_and_warnings
|
|
20
|
-
from rasa.utils.log_utils import configure_structlog
|
|
21
|
-
from rasa.utils.sanic_error_handler import register_custom_sanic_error_handler
|
|
22
|
-
|
|
23
|
-
structlogger = structlog.get_logger()
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def setup_logging() -> None:
|
|
27
|
-
"""Setup logging configuration."""
|
|
28
|
-
log_level = logging.DEBUG
|
|
29
|
-
|
|
30
|
-
configure_logging_and_warnings(
|
|
31
|
-
log_level=log_level,
|
|
32
|
-
logging_config_file=None,
|
|
33
|
-
warn_only_once=True,
|
|
34
|
-
filter_repeated_logs=True,
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
configure_structlog(
|
|
38
|
-
log_level,
|
|
39
|
-
include_time=True,
|
|
40
|
-
additional_processors=[collecting_logs_processor],
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def setup_input_channel() -> StudioChatInput:
|
|
45
|
-
"""Setup the input channel for chat interactions."""
|
|
46
|
-
studio_chat_credentials = config.get_default_credentials().get(
|
|
47
|
-
StudioChatInput.name()
|
|
48
|
-
)
|
|
49
|
-
return StudioChatInput.from_credentials(credentials=studio_chat_credentials)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def setup_middleware(app: Sanic) -> None:
|
|
53
|
-
"""Setup middleware for request/response processing."""
|
|
54
|
-
|
|
55
|
-
@app.middleware("request")
|
|
56
|
-
async def log_request(request: Request) -> None:
|
|
57
|
-
structlogger.info(
|
|
58
|
-
"request.received",
|
|
59
|
-
method=request.method,
|
|
60
|
-
path=request.path,
|
|
61
|
-
remote_addr=request.remote_addr or "unknown",
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
@app.middleware("response")
|
|
65
|
-
async def log_response(request: Request, response: HTTPResponse) -> None:
|
|
66
|
-
structlogger.info(
|
|
67
|
-
"request.completed",
|
|
68
|
-
method=request.method,
|
|
69
|
-
path=request.path,
|
|
70
|
-
status=response.status,
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def create_app(project_folder: Optional[str] = None) -> Sanic:
|
|
75
|
-
"""Create and configure the Sanic app."""
|
|
76
|
-
app = Sanic("BotBuilderService")
|
|
77
|
-
|
|
78
|
-
# Basic app configuration
|
|
79
|
-
app.config.REQUEST_TIMEOUT = 60 # 1 minute timeout
|
|
80
|
-
app.ctx.agent = None
|
|
81
|
-
|
|
82
|
-
# Set up project generator and store in app context
|
|
83
|
-
app.ctx.project_generator = setup_project_generator(project_folder)
|
|
84
|
-
|
|
85
|
-
# Set up input channel and store in app context
|
|
86
|
-
app.ctx.input_channel = setup_input_channel()
|
|
87
|
-
|
|
88
|
-
# Register the blueprint
|
|
89
|
-
app.blueprint(bp)
|
|
90
|
-
|
|
91
|
-
# OpenAPI docs
|
|
92
|
-
app.blueprint(openapi3_blueprint)
|
|
93
|
-
app.config.API_TITLE = "Bot Builder API"
|
|
94
|
-
app.config.API_VERSION = rasa.__version__
|
|
95
|
-
app.config.API_DESCRIPTION = (
|
|
96
|
-
"API for building conversational AI bots from prompts and templates. "
|
|
97
|
-
"The API allows to change the assistant and retrain it with new data."
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
# Setup middleware
|
|
101
|
-
setup_middleware(app)
|
|
102
|
-
|
|
103
|
-
configure_cors(app, cors_origins=config.CORS_ORIGINS)
|
|
104
|
-
|
|
105
|
-
# Register input channel webhooks
|
|
106
|
-
from rasa.core import channels
|
|
107
|
-
|
|
108
|
-
channels.channel.register([app.ctx.input_channel], app, route="/webhooks/")
|
|
109
|
-
|
|
110
|
-
return app
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
def main(project_folder: Optional[str] = None) -> None:
|
|
114
|
-
"""Main entry point."""
|
|
115
|
-
try:
|
|
116
|
-
# Setup logging
|
|
117
|
-
setup_logging()
|
|
118
|
-
|
|
119
|
-
# Create and configure app
|
|
120
|
-
app = create_app(project_folder)
|
|
121
|
-
register_custom_sanic_error_handler(app)
|
|
122
|
-
|
|
123
|
-
# Run the service
|
|
124
|
-
structlogger.info(
|
|
125
|
-
"service.starting",
|
|
126
|
-
host=config.BUILDER_SERVER_HOST,
|
|
127
|
-
port=config.BUILDER_SERVER_PORT,
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
app.run(
|
|
131
|
-
host=config.BUILDER_SERVER_HOST,
|
|
132
|
-
port=config.BUILDER_SERVER_PORT,
|
|
133
|
-
legacy=True,
|
|
134
|
-
motd=False,
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
except KeyboardInterrupt:
|
|
138
|
-
print("\nService stopped by user")
|
|
139
|
-
sys.exit(0)
|
|
140
|
-
except Exception as e:
|
|
141
|
-
print(f"Failed to start service: {e}")
|
|
142
|
-
sys.exit(1)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if __name__ == "__main__":
|
|
146
|
-
project_folder = sys.argv[1] if len(sys.argv) > 1 else None
|
|
147
|
-
main(project_folder)
|