rasa-pro 3.13.1a18__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/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.1a18.dist-info → rasa_pro-3.13.2.dist-info}/METADATA +8 -9
- {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.2.dist-info}/RECORD +37 -259
- 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.1a18.dist-info → rasa_pro-3.13.2.dist-info}/NOTICE +0 -0
- {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.2.dist-info}/WHEEL +0 -0
- {rasa_pro-3.13.1a18.dist-info → rasa_pro-3.13.2.dist-info}/entry_points.txt +0 -0
rasa/builder/service.py
DELETED
|
@@ -1,742 +0,0 @@
|
|
|
1
|
-
"""Main service for the prompt-to-bot functionality."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
from typing import Any, Optional
|
|
5
|
-
|
|
6
|
-
import structlog
|
|
7
|
-
from sanic import Blueprint, HTTPResponse, response
|
|
8
|
-
from sanic.request import Request
|
|
9
|
-
from sanic_openapi import openapi
|
|
10
|
-
|
|
11
|
-
from rasa.builder.exceptions import (
|
|
12
|
-
LLMGenerationError,
|
|
13
|
-
ProjectGenerationError,
|
|
14
|
-
TrainingError,
|
|
15
|
-
ValidationError,
|
|
16
|
-
)
|
|
17
|
-
from rasa.builder.llm_service import llm_service
|
|
18
|
-
from rasa.builder.logging_utils import get_recent_logs
|
|
19
|
-
from rasa.builder.models import (
|
|
20
|
-
ApiErrorResponse,
|
|
21
|
-
LLMBuilderContext,
|
|
22
|
-
LLMBuilderRequest,
|
|
23
|
-
LLMHelperResponse,
|
|
24
|
-
PromptRequest,
|
|
25
|
-
ServerSentEvent,
|
|
26
|
-
TemplateRequest,
|
|
27
|
-
)
|
|
28
|
-
from rasa.builder.project_generator import ProjectGenerator
|
|
29
|
-
from rasa.builder.training_service import train_and_load_agent
|
|
30
|
-
from rasa.builder.validation_service import validate_project
|
|
31
|
-
from rasa.cli.scaffold import ProjectTemplateName
|
|
32
|
-
from rasa.core.channels.studio_chat import StudioChatInput
|
|
33
|
-
from rasa.shared.core.trackers import DialogueStateTracker
|
|
34
|
-
from rasa.studio.upload import CALMUserData, extract_calm_import_parts_from_importer
|
|
35
|
-
from rasa.utils.openapi import model_to_schema
|
|
36
|
-
|
|
37
|
-
structlogger = structlog.get_logger()
|
|
38
|
-
|
|
39
|
-
# Create the blueprint
|
|
40
|
-
bp = Blueprint("bot_builder", url_prefix="/api")
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def setup_project_generator(project_folder: Optional[str] = None) -> ProjectGenerator:
|
|
44
|
-
"""Initialize and return a ProjectGenerator instance."""
|
|
45
|
-
if project_folder is None:
|
|
46
|
-
import tempfile
|
|
47
|
-
|
|
48
|
-
project_folder = tempfile.mkdtemp(prefix="rasa_builder_")
|
|
49
|
-
|
|
50
|
-
# working directory needs to be the project folder, e.g.
|
|
51
|
-
# for relative paths (./docs) in a projects config to work
|
|
52
|
-
os.chdir(project_folder)
|
|
53
|
-
|
|
54
|
-
structlogger.info(
|
|
55
|
-
"bot_builder_service.service_initialized", project_folder=project_folder
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
return ProjectGenerator(project_folder)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def get_project_generator(request: Request) -> ProjectGenerator:
|
|
62
|
-
"""Get the project generator from app context."""
|
|
63
|
-
return request.app.ctx.project_generator
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def get_input_channel(request: Request) -> StudioChatInput:
|
|
67
|
-
"""Get the input channel from app context."""
|
|
68
|
-
return request.app.ctx.input_channel
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def extract_calm_import_parts_from_project_generator(
|
|
72
|
-
project_generator: ProjectGenerator,
|
|
73
|
-
) -> CALMUserData:
|
|
74
|
-
"""Extract CALMUserData from a ProjectGenerator.
|
|
75
|
-
|
|
76
|
-
Args:
|
|
77
|
-
project_generator: The project generator to extract data from
|
|
78
|
-
|
|
79
|
-
Returns:
|
|
80
|
-
CALMUserData containing flows, domain, config, endpoints, and nlu data
|
|
81
|
-
"""
|
|
82
|
-
# Get the training data importer
|
|
83
|
-
importer = project_generator._create_importer()
|
|
84
|
-
|
|
85
|
-
# Extract endpoints (if exists)
|
|
86
|
-
endpoints_path = project_generator.project_folder / "endpoints.yml"
|
|
87
|
-
if endpoints_path.exists():
|
|
88
|
-
from rasa.shared.utils.yaml import read_yaml_file
|
|
89
|
-
|
|
90
|
-
endpoints = read_yaml_file(endpoints_path, expand_env_vars=False)
|
|
91
|
-
else:
|
|
92
|
-
endpoints = {}
|
|
93
|
-
|
|
94
|
-
# Use the shared function with the importer and project data paths
|
|
95
|
-
return extract_calm_import_parts_from_importer(
|
|
96
|
-
importer=importer,
|
|
97
|
-
config=None, # Let the shared function get config from importer
|
|
98
|
-
endpoints=endpoints,
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
# Health check endpoint
|
|
103
|
-
@bp.route("/", methods=["GET"])
|
|
104
|
-
@openapi.summary("Health check endpoint")
|
|
105
|
-
@openapi.description("Returns the health status of the Bot Builder service")
|
|
106
|
-
@openapi.tag("health")
|
|
107
|
-
@openapi.response(200, {"application/json": {"status": str, "service": str}})
|
|
108
|
-
async def health(request: Request) -> HTTPResponse:
|
|
109
|
-
"""Health check endpoint."""
|
|
110
|
-
return response.json({"status": "ok", "service": "bot-builder"})
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
@bp.route("/prompt-to-bot", methods=["POST"])
|
|
114
|
-
@openapi.summary("Generate bot from natural language prompt")
|
|
115
|
-
@openapi.description(
|
|
116
|
-
"Creates a complete conversational AI bot from a natural language prompt "
|
|
117
|
-
"using LLM generation. Returns server-sent events (SSE) for real-time "
|
|
118
|
-
"progress tracking through the entire bot creation process.\n\n"
|
|
119
|
-
"**SSE Event Flow:**\n"
|
|
120
|
-
"1. `received` - Request received by server\n"
|
|
121
|
-
"2. `generating` - Generating bot project files\n"
|
|
122
|
-
"3. `generation_success` - Bot generation completed successfully\n"
|
|
123
|
-
"4. `training` - Training the bot model\n"
|
|
124
|
-
"5. `train_success` - Model training completed\n"
|
|
125
|
-
"6. `done` - Bot creation completed\n\n"
|
|
126
|
-
"**Error Events (can occur at any time):**\n"
|
|
127
|
-
"- `generation_error` - Failed to generate bot from prompt\n"
|
|
128
|
-
"- `train_error` - Bot generated but training failed\n"
|
|
129
|
-
"- `validation_error` - Generated bot configuration is invalid\n"
|
|
130
|
-
"- `error` - Unexpected error occurred\n\n"
|
|
131
|
-
"**Usage:** Send POST request with Content-Type: application/json and "
|
|
132
|
-
"Accept: text/event-stream"
|
|
133
|
-
)
|
|
134
|
-
@openapi.tag("bot-generation")
|
|
135
|
-
@openapi.body(
|
|
136
|
-
{"application/json": model_to_schema(PromptRequest)},
|
|
137
|
-
description="Prompt request with natural language description and client ID "
|
|
138
|
-
"for tracking",
|
|
139
|
-
required=True,
|
|
140
|
-
)
|
|
141
|
-
@openapi.response(
|
|
142
|
-
200,
|
|
143
|
-
{"text/event-stream": str},
|
|
144
|
-
description="Server-sent events stream with real-time progress updates",
|
|
145
|
-
)
|
|
146
|
-
@openapi.response(
|
|
147
|
-
400,
|
|
148
|
-
{"application/json": model_to_schema(ApiErrorResponse)},
|
|
149
|
-
description="Validation error in request payload",
|
|
150
|
-
)
|
|
151
|
-
@openapi.response(
|
|
152
|
-
500,
|
|
153
|
-
{"application/json": model_to_schema(ApiErrorResponse)},
|
|
154
|
-
description="Internal server error",
|
|
155
|
-
)
|
|
156
|
-
async def handle_prompt_to_bot(request: Request) -> None:
|
|
157
|
-
"""Handle prompt-to-bot generation requests."""
|
|
158
|
-
sse_response = await request.respond(content_type="text/event-stream")
|
|
159
|
-
project_generator = get_project_generator(request)
|
|
160
|
-
input_channel = get_input_channel(request)
|
|
161
|
-
|
|
162
|
-
try:
|
|
163
|
-
# 1. Received
|
|
164
|
-
await _send_sse_event(
|
|
165
|
-
sse_response,
|
|
166
|
-
ServerSentEvent(event="received", data={"status": "received"}),
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
# Validate request
|
|
170
|
-
prompt_data = PromptRequest(**request.json)
|
|
171
|
-
|
|
172
|
-
# 2. Generating
|
|
173
|
-
await _send_sse_event(
|
|
174
|
-
sse_response,
|
|
175
|
-
ServerSentEvent(event="generating", data={"status": "generating"}),
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
try:
|
|
179
|
-
# Generate project with retries
|
|
180
|
-
bot_files = await project_generator.generate_project_with_retries(
|
|
181
|
-
prompt_data.prompt,
|
|
182
|
-
template=ProjectTemplateName.PLAIN,
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
await _send_sse_event(
|
|
186
|
-
sse_response,
|
|
187
|
-
ServerSentEvent(
|
|
188
|
-
event="generation_success",
|
|
189
|
-
data={"status": "generation_success"},
|
|
190
|
-
),
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
except (ProjectGenerationError, LLMGenerationError) as e:
|
|
194
|
-
await _send_sse_event(
|
|
195
|
-
sse_response,
|
|
196
|
-
ServerSentEvent(
|
|
197
|
-
event="generation_error",
|
|
198
|
-
data={"status": "generation_error", "error": str(e)},
|
|
199
|
-
),
|
|
200
|
-
)
|
|
201
|
-
await sse_response.eof()
|
|
202
|
-
return
|
|
203
|
-
|
|
204
|
-
# 3. Training
|
|
205
|
-
await _send_sse_event(
|
|
206
|
-
sse_response,
|
|
207
|
-
ServerSentEvent(event="training", data={"status": "training"}),
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
try:
|
|
211
|
-
# Train and load agent
|
|
212
|
-
importer = project_generator._create_importer()
|
|
213
|
-
request.app.ctx.agent = await train_and_load_agent(importer)
|
|
214
|
-
|
|
215
|
-
# Update input channel with new agent
|
|
216
|
-
input_channel.agent = request.app.ctx.agent
|
|
217
|
-
|
|
218
|
-
await _send_sse_event(
|
|
219
|
-
sse_response,
|
|
220
|
-
ServerSentEvent(
|
|
221
|
-
event="train_success", data={"status": "train_success"}
|
|
222
|
-
),
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
except TrainingError as e:
|
|
226
|
-
await _send_sse_event(
|
|
227
|
-
sse_response,
|
|
228
|
-
ServerSentEvent(
|
|
229
|
-
event="train_error",
|
|
230
|
-
data={"status": "train_error", "error": str(e)},
|
|
231
|
-
),
|
|
232
|
-
)
|
|
233
|
-
await sse_response.eof()
|
|
234
|
-
return
|
|
235
|
-
|
|
236
|
-
# 4. Done
|
|
237
|
-
await _send_sse_event(
|
|
238
|
-
sse_response,
|
|
239
|
-
ServerSentEvent(
|
|
240
|
-
event="done",
|
|
241
|
-
data={
|
|
242
|
-
"status": "done",
|
|
243
|
-
},
|
|
244
|
-
),
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
structlogger.info(
|
|
248
|
-
"bot_builder_service.prompt_to_bot.success",
|
|
249
|
-
client_id=prompt_data.client_id,
|
|
250
|
-
files_generated=list(bot_files.keys()),
|
|
251
|
-
)
|
|
252
|
-
|
|
253
|
-
except ValidationError as e:
|
|
254
|
-
structlogger.error(
|
|
255
|
-
"bot_builder_service.prompt_to_bot.validation_error", error=str(e)
|
|
256
|
-
)
|
|
257
|
-
await _send_sse_event(
|
|
258
|
-
sse_response,
|
|
259
|
-
ServerSentEvent(
|
|
260
|
-
event="validation_error",
|
|
261
|
-
data={"status": "validation_error", "error": str(e)},
|
|
262
|
-
),
|
|
263
|
-
)
|
|
264
|
-
|
|
265
|
-
except Exception as e:
|
|
266
|
-
structlogger.error(
|
|
267
|
-
"bot_builder_service.prompt_to_bot.unexpected_error", error=str(e)
|
|
268
|
-
)
|
|
269
|
-
await _send_sse_event(
|
|
270
|
-
sse_response,
|
|
271
|
-
ServerSentEvent(event="error", data={"status": "error", "error": str(e)}),
|
|
272
|
-
)
|
|
273
|
-
finally:
|
|
274
|
-
await sse_response.eof()
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
@bp.route("/template-to-bot", methods=["POST"])
|
|
278
|
-
@openapi.summary("Generate bot from predefined template")
|
|
279
|
-
@openapi.description(
|
|
280
|
-
"Creates a complete conversational AI bot from a predefined template with "
|
|
281
|
-
"immediate setup. Returns server-sent events (SSE) for real-time progress "
|
|
282
|
-
"tracking through the entire bot creation process.\n\n"
|
|
283
|
-
"**SSE Event Flow:**\n"
|
|
284
|
-
"1. `received` - Request received by server\n"
|
|
285
|
-
"2. `generating` - Initializing bot from template\n"
|
|
286
|
-
"3. `generation_success` - Template initialization completed successfully\n"
|
|
287
|
-
"4. `training` - Training the bot model\n"
|
|
288
|
-
"5. `train_success` - Model training completed\n"
|
|
289
|
-
"6. `done` - Bot creation completed\n\n"
|
|
290
|
-
"**Error Events (can occur at any time):**\n"
|
|
291
|
-
"- `generation_error` - Failed to initialize bot from template\n"
|
|
292
|
-
"- `train_error` - Template loaded but training failed\n"
|
|
293
|
-
"- `validation_error` - Template configuration is invalid\n"
|
|
294
|
-
"- `error` - Unexpected error occurred\n\n"
|
|
295
|
-
"**Usage:** Send POST request with Content-Type: application/json and "
|
|
296
|
-
"Accept: text/event-stream\n"
|
|
297
|
-
"**Templates Available:** Check available templates through the API or "
|
|
298
|
-
"documentation"
|
|
299
|
-
)
|
|
300
|
-
@openapi.tag("bot-generation")
|
|
301
|
-
@openapi.body(
|
|
302
|
-
{"application/json": model_to_schema(TemplateRequest)},
|
|
303
|
-
description="Template request with template name and client ID for " "tracking",
|
|
304
|
-
required=True,
|
|
305
|
-
)
|
|
306
|
-
@openapi.response(
|
|
307
|
-
200,
|
|
308
|
-
{"text/event-stream": model_to_schema(ServerSentEvent)},
|
|
309
|
-
description="Server-sent events stream with real-time progress updates",
|
|
310
|
-
example=ServerSentEvent(
|
|
311
|
-
event="generation_success",
|
|
312
|
-
data={"status": "generation_success"},
|
|
313
|
-
).model_dump(),
|
|
314
|
-
)
|
|
315
|
-
@openapi.response(
|
|
316
|
-
400,
|
|
317
|
-
{"application/json": model_to_schema(ApiErrorResponse)},
|
|
318
|
-
description="Validation error in request payload or invalid template name",
|
|
319
|
-
)
|
|
320
|
-
@openapi.response(
|
|
321
|
-
500,
|
|
322
|
-
{"application/json": model_to_schema(ApiErrorResponse)},
|
|
323
|
-
description="Internal server error",
|
|
324
|
-
)
|
|
325
|
-
async def handle_template_to_bot(request: Request) -> None:
|
|
326
|
-
"""Handle template-to-bot generation requests."""
|
|
327
|
-
sse_response = await request.respond(content_type="text/event-stream")
|
|
328
|
-
project_generator = get_project_generator(request)
|
|
329
|
-
input_channel = get_input_channel(request)
|
|
330
|
-
|
|
331
|
-
try:
|
|
332
|
-
# 1. Received
|
|
333
|
-
await _send_sse_event(
|
|
334
|
-
sse_response,
|
|
335
|
-
ServerSentEvent(event="received", data={"status": "received"}),
|
|
336
|
-
)
|
|
337
|
-
|
|
338
|
-
# Validate request
|
|
339
|
-
template_data = TemplateRequest(**request.json)
|
|
340
|
-
|
|
341
|
-
# 2. Generating
|
|
342
|
-
await _send_sse_event(
|
|
343
|
-
sse_response,
|
|
344
|
-
ServerSentEvent(event="generating", data={"status": "generating"}),
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
try:
|
|
348
|
-
# Generate project with retries
|
|
349
|
-
project_generator.init_from_template(
|
|
350
|
-
template_data.template_name,
|
|
351
|
-
)
|
|
352
|
-
bot_files = project_generator.get_bot_files()
|
|
353
|
-
|
|
354
|
-
await _send_sse_event(
|
|
355
|
-
sse_response,
|
|
356
|
-
ServerSentEvent(
|
|
357
|
-
event="generation_success",
|
|
358
|
-
data={"status": "generation_success"},
|
|
359
|
-
),
|
|
360
|
-
)
|
|
361
|
-
|
|
362
|
-
except ProjectGenerationError as e:
|
|
363
|
-
await _send_sse_event(
|
|
364
|
-
sse_response,
|
|
365
|
-
ServerSentEvent(
|
|
366
|
-
event="generation_error",
|
|
367
|
-
data={"status": "generation_error", "error": str(e)},
|
|
368
|
-
),
|
|
369
|
-
)
|
|
370
|
-
await sse_response.eof()
|
|
371
|
-
return
|
|
372
|
-
|
|
373
|
-
# 3. Training
|
|
374
|
-
await _send_sse_event(
|
|
375
|
-
sse_response,
|
|
376
|
-
ServerSentEvent(event="training", data={"status": "training"}),
|
|
377
|
-
)
|
|
378
|
-
|
|
379
|
-
try:
|
|
380
|
-
# Train and load agent
|
|
381
|
-
importer = project_generator._create_importer()
|
|
382
|
-
request.app.ctx.agent = await train_and_load_agent(importer)
|
|
383
|
-
|
|
384
|
-
# Update input channel with new agent
|
|
385
|
-
input_channel.agent = request.app.ctx.agent
|
|
386
|
-
|
|
387
|
-
await _send_sse_event(
|
|
388
|
-
sse_response,
|
|
389
|
-
ServerSentEvent(
|
|
390
|
-
event="train_success", data={"status": "train_success"}
|
|
391
|
-
),
|
|
392
|
-
)
|
|
393
|
-
|
|
394
|
-
except TrainingError as e:
|
|
395
|
-
await _send_sse_event(
|
|
396
|
-
sse_response,
|
|
397
|
-
ServerSentEvent(
|
|
398
|
-
event="train_error",
|
|
399
|
-
data={"status": "train_error", "error": str(e)},
|
|
400
|
-
),
|
|
401
|
-
)
|
|
402
|
-
await sse_response.eof()
|
|
403
|
-
return
|
|
404
|
-
|
|
405
|
-
# 4. Done
|
|
406
|
-
await _send_sse_event(
|
|
407
|
-
sse_response,
|
|
408
|
-
ServerSentEvent(
|
|
409
|
-
event="done",
|
|
410
|
-
data={
|
|
411
|
-
"status": "done",
|
|
412
|
-
},
|
|
413
|
-
),
|
|
414
|
-
)
|
|
415
|
-
|
|
416
|
-
structlogger.info(
|
|
417
|
-
"bot_builder_service.template_to_bot.success",
|
|
418
|
-
client_id=template_data.client_id,
|
|
419
|
-
files_generated=list(bot_files.keys()),
|
|
420
|
-
)
|
|
421
|
-
|
|
422
|
-
except ValidationError as e:
|
|
423
|
-
structlogger.error(
|
|
424
|
-
"bot_builder_service.template_to_bot.validation_error", error=str(e)
|
|
425
|
-
)
|
|
426
|
-
await _send_sse_event(
|
|
427
|
-
sse_response,
|
|
428
|
-
ServerSentEvent(
|
|
429
|
-
event="validation_error",
|
|
430
|
-
data={"status": "validation_error", "error": str(e)},
|
|
431
|
-
),
|
|
432
|
-
)
|
|
433
|
-
|
|
434
|
-
except Exception as e:
|
|
435
|
-
structlogger.error(
|
|
436
|
-
"bot_builder_service.template_to_bot.unexpected_error", error=str(e)
|
|
437
|
-
)
|
|
438
|
-
await _send_sse_event(
|
|
439
|
-
sse_response,
|
|
440
|
-
ServerSentEvent(event="error", data={"status": "error", "error": str(e)}),
|
|
441
|
-
)
|
|
442
|
-
finally:
|
|
443
|
-
await sse_response.eof()
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
@bp.route("/files", methods=["GET"])
|
|
447
|
-
@openapi.summary("Get bot files")
|
|
448
|
-
@openapi.description("Retrieves the current bot configuration files and data")
|
|
449
|
-
@openapi.tag("bot-files")
|
|
450
|
-
@openapi.response(
|
|
451
|
-
200,
|
|
452
|
-
{"application/json": {str: Optional[str]}},
|
|
453
|
-
description="Bot files retrieved successfully",
|
|
454
|
-
)
|
|
455
|
-
@openapi.response(
|
|
456
|
-
500,
|
|
457
|
-
{"application/json": model_to_schema(ApiErrorResponse)},
|
|
458
|
-
description="Internal server error",
|
|
459
|
-
)
|
|
460
|
-
async def get_bot_files(request: Request) -> HTTPResponse:
|
|
461
|
-
"""Get current bot files."""
|
|
462
|
-
project_generator = get_project_generator(request)
|
|
463
|
-
bot_files = project_generator.get_bot_files()
|
|
464
|
-
return response.json(bot_files)
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
@bp.route("/files", methods=["PUT"])
|
|
468
|
-
@openapi.summary("Update bot files")
|
|
469
|
-
@openapi.description(
|
|
470
|
-
"Updates the bot configuration files and retrains the model. "
|
|
471
|
-
"Returns server-sent events (SSE) for real-time progress tracking "
|
|
472
|
-
"through the entire update process.\n\n"
|
|
473
|
-
"**SSE Event Flow:**\n"
|
|
474
|
-
"1. `received` - Request received by server\n"
|
|
475
|
-
"2. `validating` - Validating bot configuration files\n"
|
|
476
|
-
"3. `validation_success` - File validation completed successfully\n"
|
|
477
|
-
"4. `training` - Training the bot model with updated files\n"
|
|
478
|
-
"5. `train_success` - Model training completed\n"
|
|
479
|
-
"6. `done` - Bot files update completed\n\n"
|
|
480
|
-
"**Error Events (can occur at any time):**\n"
|
|
481
|
-
"- `validation_error` - Bot configuration files are invalid\n"
|
|
482
|
-
"- `train_error` - Files updated but training failed\n"
|
|
483
|
-
"- `error` - Unexpected error occurred\n\n"
|
|
484
|
-
"**Usage:** Send PUT request with Content-Type: application/json and "
|
|
485
|
-
"Accept: text/event-stream"
|
|
486
|
-
)
|
|
487
|
-
@openapi.tag("bot-files")
|
|
488
|
-
@openapi.body(
|
|
489
|
-
{"application/json": {"file_name": str}},
|
|
490
|
-
description="A dictionary mapping file names to their updated content. "
|
|
491
|
-
"The file name should be the name of the file in the project folder. "
|
|
492
|
-
"Files that are not in the request will not be updated.",
|
|
493
|
-
required=True,
|
|
494
|
-
)
|
|
495
|
-
@openapi.response(
|
|
496
|
-
200,
|
|
497
|
-
{"text/event-stream": str},
|
|
498
|
-
description="Server-sent events stream with update progress",
|
|
499
|
-
)
|
|
500
|
-
@openapi.response(
|
|
501
|
-
400,
|
|
502
|
-
{"application/json": model_to_schema(ApiErrorResponse)},
|
|
503
|
-
description="Validation error in bot files",
|
|
504
|
-
)
|
|
505
|
-
@openapi.response(
|
|
506
|
-
500,
|
|
507
|
-
{"application/json": model_to_schema(ApiErrorResponse)},
|
|
508
|
-
description="Internal server error",
|
|
509
|
-
)
|
|
510
|
-
async def update_bot_files(request: Request) -> None:
|
|
511
|
-
"""Update bot files with server-sent events for progress tracking."""
|
|
512
|
-
sse_response = await request.respond(content_type="text/event-stream")
|
|
513
|
-
project_generator = get_project_generator(request)
|
|
514
|
-
input_channel = get_input_channel(request)
|
|
515
|
-
|
|
516
|
-
try:
|
|
517
|
-
# 1. Received
|
|
518
|
-
await _send_sse_event(
|
|
519
|
-
sse_response,
|
|
520
|
-
ServerSentEvent(event="received", data={"status": "received"}),
|
|
521
|
-
)
|
|
522
|
-
|
|
523
|
-
# Update bot files
|
|
524
|
-
bot_files = request.json
|
|
525
|
-
project_generator.update_bot_files(bot_files)
|
|
526
|
-
|
|
527
|
-
# 2. Validating
|
|
528
|
-
await _send_sse_event(
|
|
529
|
-
sse_response,
|
|
530
|
-
ServerSentEvent(event="validating", data={"status": "validating"}),
|
|
531
|
-
)
|
|
532
|
-
|
|
533
|
-
try:
|
|
534
|
-
importer = project_generator._create_importer()
|
|
535
|
-
validation_error = await validate_project(importer)
|
|
536
|
-
|
|
537
|
-
if validation_error:
|
|
538
|
-
raise ValidationError(validation_error)
|
|
539
|
-
|
|
540
|
-
await _send_sse_event(
|
|
541
|
-
sse_response,
|
|
542
|
-
ServerSentEvent(
|
|
543
|
-
event="validation_success",
|
|
544
|
-
data={"status": "validation_success"},
|
|
545
|
-
),
|
|
546
|
-
)
|
|
547
|
-
|
|
548
|
-
except ValidationError as e:
|
|
549
|
-
await _send_sse_event(
|
|
550
|
-
sse_response,
|
|
551
|
-
ServerSentEvent(
|
|
552
|
-
event="validation_error",
|
|
553
|
-
data={"status": "validation_error", "error": str(e)},
|
|
554
|
-
),
|
|
555
|
-
)
|
|
556
|
-
await sse_response.eof()
|
|
557
|
-
return
|
|
558
|
-
|
|
559
|
-
# 3. Training
|
|
560
|
-
await _send_sse_event(
|
|
561
|
-
sse_response,
|
|
562
|
-
ServerSentEvent(event="training", data={"status": "training"}),
|
|
563
|
-
)
|
|
564
|
-
|
|
565
|
-
try:
|
|
566
|
-
request.app.ctx.agent = await train_and_load_agent(importer)
|
|
567
|
-
input_channel.agent = request.app.ctx.agent
|
|
568
|
-
|
|
569
|
-
await _send_sse_event(
|
|
570
|
-
sse_response,
|
|
571
|
-
ServerSentEvent(
|
|
572
|
-
event="train_success", data={"status": "train_success"}
|
|
573
|
-
),
|
|
574
|
-
)
|
|
575
|
-
|
|
576
|
-
except TrainingError as e:
|
|
577
|
-
await _send_sse_event(
|
|
578
|
-
sse_response,
|
|
579
|
-
ServerSentEvent(
|
|
580
|
-
event="train_error",
|
|
581
|
-
data={"status": "train_error", "error": str(e)},
|
|
582
|
-
),
|
|
583
|
-
)
|
|
584
|
-
await sse_response.eof()
|
|
585
|
-
return
|
|
586
|
-
|
|
587
|
-
# 4. Done
|
|
588
|
-
await _send_sse_event(
|
|
589
|
-
sse_response,
|
|
590
|
-
ServerSentEvent(
|
|
591
|
-
event="done",
|
|
592
|
-
data={
|
|
593
|
-
"status": "done",
|
|
594
|
-
},
|
|
595
|
-
),
|
|
596
|
-
)
|
|
597
|
-
|
|
598
|
-
except Exception as e:
|
|
599
|
-
await _send_sse_event(
|
|
600
|
-
sse_response,
|
|
601
|
-
ServerSentEvent(event="error", data={"status": "error", "error": str(e)}),
|
|
602
|
-
)
|
|
603
|
-
finally:
|
|
604
|
-
await sse_response.eof()
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
@bp.route("/data", methods=["GET"])
|
|
608
|
-
@openapi.summary("Get bot data")
|
|
609
|
-
@openapi.description(
|
|
610
|
-
"Retrieves the current bot data in CALM import format with flows, domain, "
|
|
611
|
-
"config, endpoints, and NLU data"
|
|
612
|
-
)
|
|
613
|
-
@openapi.tag("bot-data")
|
|
614
|
-
@openapi.response(
|
|
615
|
-
200,
|
|
616
|
-
{"application/json": model_to_schema(CALMUserData)},
|
|
617
|
-
description="Bot data retrieved successfully",
|
|
618
|
-
)
|
|
619
|
-
@openapi.response(
|
|
620
|
-
500,
|
|
621
|
-
{"application/json": model_to_schema(ApiErrorResponse)},
|
|
622
|
-
description="Internal server error",
|
|
623
|
-
)
|
|
624
|
-
async def get_bot_data(request: Request) -> HTTPResponse:
|
|
625
|
-
"""Get current bot data in CALM import format."""
|
|
626
|
-
try:
|
|
627
|
-
project_generator = get_project_generator(request)
|
|
628
|
-
calm_parts = extract_calm_import_parts_from_project_generator(project_generator)
|
|
629
|
-
|
|
630
|
-
return response.json(calm_parts.model_dump())
|
|
631
|
-
except Exception as e:
|
|
632
|
-
structlogger.error("bot_builder_service.get_bot_data.error", error=str(e))
|
|
633
|
-
return response.json(
|
|
634
|
-
ApiErrorResponse(
|
|
635
|
-
error="Failed to retrieve bot data",
|
|
636
|
-
details={"error": str(e)},
|
|
637
|
-
).model_dump(),
|
|
638
|
-
status=500,
|
|
639
|
-
)
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
@bp.route("/llm-builder", methods=["POST"])
|
|
643
|
-
@openapi.summary("LLM assistant for bot building")
|
|
644
|
-
@openapi.description(
|
|
645
|
-
"Provides LLM-powered assistance for bot building tasks, including "
|
|
646
|
-
"debugging, suggestions, and explanations"
|
|
647
|
-
)
|
|
648
|
-
@openapi.tag("llm-assistant")
|
|
649
|
-
@openapi.body(
|
|
650
|
-
{"application/json": model_to_schema(LLMBuilderRequest)},
|
|
651
|
-
description="LLM builder request containing chat messages and context",
|
|
652
|
-
required=True,
|
|
653
|
-
)
|
|
654
|
-
@openapi.response(
|
|
655
|
-
200,
|
|
656
|
-
{"application/json": model_to_schema(LLMHelperResponse)},
|
|
657
|
-
description="LLM response with assistance and suggestions",
|
|
658
|
-
)
|
|
659
|
-
@openapi.response(
|
|
660
|
-
400,
|
|
661
|
-
{"application/json": model_to_schema(ApiErrorResponse)},
|
|
662
|
-
description="Validation error in request",
|
|
663
|
-
)
|
|
664
|
-
@openapi.response(
|
|
665
|
-
502,
|
|
666
|
-
{"application/json": model_to_schema(ApiErrorResponse)},
|
|
667
|
-
description="LLM generation failed",
|
|
668
|
-
)
|
|
669
|
-
@openapi.response(
|
|
670
|
-
500,
|
|
671
|
-
{"application/json": model_to_schema(ApiErrorResponse)},
|
|
672
|
-
description="Internal server error",
|
|
673
|
-
)
|
|
674
|
-
async def llm_builder(request: Request) -> HTTPResponse:
|
|
675
|
-
"""Handle LLM builder requests."""
|
|
676
|
-
project_generator = get_project_generator(request)
|
|
677
|
-
input_channel = get_input_channel(request)
|
|
678
|
-
|
|
679
|
-
try:
|
|
680
|
-
# Validate request
|
|
681
|
-
builder_request = LLMBuilderRequest(**request.json)
|
|
682
|
-
|
|
683
|
-
# Get current conversation context
|
|
684
|
-
current_tracker = await current_tracker_from_input_channel(
|
|
685
|
-
request.app, input_channel
|
|
686
|
-
)
|
|
687
|
-
bot_logs = get_recent_logs()
|
|
688
|
-
chat_bot_files = project_generator.get_bot_files()
|
|
689
|
-
|
|
690
|
-
# create LLM builder context
|
|
691
|
-
llm_builder_context = LLMBuilderContext(
|
|
692
|
-
tracker=current_tracker,
|
|
693
|
-
bot_logs=bot_logs,
|
|
694
|
-
chat_bot_files=chat_bot_files,
|
|
695
|
-
chat_history=builder_request.messages,
|
|
696
|
-
)
|
|
697
|
-
|
|
698
|
-
# Generate response
|
|
699
|
-
messages = await llm_service.create_helper_messages(llm_builder_context)
|
|
700
|
-
llm_response = await llm_service.generate_helper_response(messages)
|
|
701
|
-
|
|
702
|
-
return response.json(llm_response)
|
|
703
|
-
|
|
704
|
-
except LLMGenerationError as e:
|
|
705
|
-
structlogger.error(
|
|
706
|
-
"bot_builder_service.llm_builder.generation_error", error=str(e)
|
|
707
|
-
)
|
|
708
|
-
return response.json(
|
|
709
|
-
ApiErrorResponse(
|
|
710
|
-
error="LLM helper generation failed", details={"llm_error": str(e)}
|
|
711
|
-
).model_dump(),
|
|
712
|
-
status=502,
|
|
713
|
-
)
|
|
714
|
-
|
|
715
|
-
except Exception as e:
|
|
716
|
-
structlogger.error(
|
|
717
|
-
"bot_builder_service.llm_builder.unexpected_error", error=str(e)
|
|
718
|
-
)
|
|
719
|
-
return response.json(
|
|
720
|
-
ApiErrorResponse(
|
|
721
|
-
error="Unexpected error in LLM builder",
|
|
722
|
-
details=None,
|
|
723
|
-
).model_dump(),
|
|
724
|
-
status=500,
|
|
725
|
-
)
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
async def current_tracker_from_input_channel(
|
|
729
|
-
app: Any, input_channel: StudioChatInput
|
|
730
|
-
) -> Optional[DialogueStateTracker]:
|
|
731
|
-
"""Generate chat bot context from current conversation."""
|
|
732
|
-
if app.ctx.agent and input_channel.latest_tracker_session_id:
|
|
733
|
-
return await app.ctx.agent.tracker_store.retrieve(
|
|
734
|
-
input_channel.latest_tracker_session_id
|
|
735
|
-
)
|
|
736
|
-
else:
|
|
737
|
-
return None
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
async def _send_sse_event(sse_response: HTTPResponse, event: ServerSentEvent) -> None:
|
|
741
|
-
"""Send a server-sent event."""
|
|
742
|
-
await sse_response.send(event.format())
|