rasa-pro 3.13.0a1.dev6__py3-none-any.whl → 3.13.0a1.dev7__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.

Files changed (47) hide show
  1. rasa/builder/README.md +120 -0
  2. rasa/builder/config.py +69 -0
  3. rasa/builder/create_openai_vector_store.py +204 -45
  4. rasa/builder/exceptions.py +49 -0
  5. rasa/builder/llm_service.py +327 -0
  6. rasa/builder/logging_utils.py +51 -0
  7. rasa/builder/main.py +61 -0
  8. rasa/builder/models.py +174 -0
  9. rasa/builder/project_generator.py +264 -0
  10. rasa/builder/service.py +447 -0
  11. rasa/builder/skill_to_bot_prompt.jinja2 +6 -1
  12. rasa/builder/training_service.py +123 -0
  13. rasa/builder/validation_service.py +79 -0
  14. rasa/cli/project_templates/finance/config.yml +17 -0
  15. rasa/cli/project_templates/finance/credentials.yml +33 -0
  16. rasa/cli/project_templates/finance/data/flows/transfer_money.yml +5 -0
  17. rasa/cli/project_templates/finance/data/patterns/pattern_session_start.yml +7 -0
  18. rasa/cli/project_templates/finance/domain.yml +7 -0
  19. rasa/cli/project_templates/finance/endpoints.yml +58 -0
  20. rasa/cli/project_templates/plain/config.yml +17 -0
  21. rasa/cli/project_templates/plain/credentials.yml +33 -0
  22. rasa/cli/project_templates/plain/data/patterns/pattern_session_start.yml +7 -0
  23. rasa/cli/project_templates/plain/domain.yml +5 -0
  24. rasa/cli/project_templates/plain/endpoints.yml +58 -0
  25. rasa/cli/project_templates/telecom/config.yml +17 -0
  26. rasa/cli/project_templates/telecom/credentials.yml +33 -0
  27. rasa/cli/project_templates/telecom/data/flows/upgrade_contract.yml +5 -0
  28. rasa/cli/project_templates/telecom/data/patterns/pattern_session_start.yml +7 -0
  29. rasa/cli/project_templates/telecom/domain.yml +7 -0
  30. rasa/cli/project_templates/telecom/endpoints.yml +58 -0
  31. rasa/cli/scaffold.py +19 -3
  32. rasa/core/actions/action.py +5 -3
  33. rasa/model_manager/model_api.py +1 -1
  34. rasa/model_manager/runner_service.py +1 -1
  35. rasa/model_manager/trainer_service.py +1 -1
  36. rasa/model_manager/utils.py +1 -29
  37. rasa/shared/core/domain.py +62 -15
  38. rasa/shared/core/flows/yaml_flows_io.py +16 -8
  39. rasa/telemetry.py +2 -1
  40. rasa/utils/io.py +27 -9
  41. rasa/version.py +1 -1
  42. {rasa_pro-3.13.0a1.dev6.dist-info → rasa_pro-3.13.0a1.dev7.dist-info}/METADATA +1 -1
  43. {rasa_pro-3.13.0a1.dev6.dist-info → rasa_pro-3.13.0a1.dev7.dist-info}/RECORD +46 -19
  44. rasa/builder/prompt_to_bot.py +0 -650
  45. {rasa_pro-3.13.0a1.dev6.dist-info → rasa_pro-3.13.0a1.dev7.dist-info}/NOTICE +0 -0
  46. {rasa_pro-3.13.0a1.dev6.dist-info → rasa_pro-3.13.0a1.dev7.dist-info}/WHEEL +0 -0
  47. {rasa_pro-3.13.0a1.dev6.dist-info → rasa_pro-3.13.0a1.dev7.dist-info}/entry_points.txt +0 -0
@@ -1,650 +0,0 @@
1
- import asyncio
2
- import collections
3
- import importlib
4
- import json
5
- import logging
6
- import sys
7
- import tempfile
8
- import traceback
9
- from copy import deepcopy
10
- from textwrap import dedent
11
- from typing import Any, Callable, Dict, List, Optional
12
-
13
- import importlib_resources
14
- import openai
15
- import structlog
16
- from jinja2 import Template
17
- from pydantic import BaseModel
18
- from sanic import Sanic, response
19
- from structlog.testing import capture_logs
20
-
21
- import rasa.core.utils
22
- from rasa.builder.llm_context import tracker_as_llm_context
23
- from rasa.cli.utils import validate_files
24
- from rasa.constants import PACKAGE_NAME
25
- from rasa.core import agent, channels
26
- from rasa.core.channels.channel import InputChannel
27
- from rasa.core.channels.studio_chat import StudioChatInput
28
- from rasa.core.utils import AvailableEndpoints, read_endpoints_from_path
29
- from rasa.model_training import train
30
- from rasa.server import configure_cors
31
- from rasa.shared.constants import DOMAIN_SCHEMA_FILE, RESPONSES_SCHEMA_FILE
32
- from rasa.shared.core.domain import Domain
33
- from rasa.shared.core.flows.yaml_flows_io import FLOWS_SCHEMA_FILE, YAMLFlowsReader
34
- from rasa.shared.core.trackers import DialogueStateTracker
35
- from rasa.shared.importers.importer import TrainingDataImporter
36
- from rasa.shared.importers.static import StaticTrainingDataImporter
37
- from rasa.shared.utils.io import read_json_file
38
- from rasa.shared.utils.yaml import (
39
- dump_obj_as_yaml_to_string,
40
- read_schema_file,
41
- read_yaml,
42
- read_yaml_file,
43
- )
44
- from rasa.utils.common import configure_logging_and_warnings
45
- from rasa.utils.log_utils import configure_structlog
46
- from rasa.utils.sanic_error_handler import register_custom_sanic_error_handler
47
-
48
- structlogger = structlog.get_logger()
49
-
50
- DEFAULT_SKILL_GENERATION_SYSTEM_PROMPT = importlib.resources.read_text(
51
- "rasa.builder",
52
- "skill_to_bot_prompt.jinja2",
53
- )
54
-
55
- DEFAULT_LLM_HELPER_SYSTEM_PROMPT = importlib.resources.read_text(
56
- "rasa.builder",
57
- "llm_helper_prompt.jinja2",
58
- )
59
-
60
- VECTOR_STORE_ID = "vs_685123376e288191a005b6b144d3026f"
61
-
62
-
63
- default_credentials_yaml = """
64
- studio_chat:
65
- user_message_evt: "user_message"
66
- bot_message_evt: "bot_message"
67
- session_persistence: true
68
- """
69
-
70
- # create a dict where we collect most recent logs. only collect the last 30 log lines
71
- # use a builtin type for this
72
- recent_logs = collections.deque(maxlen=30)
73
-
74
-
75
- def collecting_logs_processor(logger, log_level, event_dict):
76
- if log_level != logging.getLevelName(logging.DEBUG).lower():
77
- event_message = event_dict.get("event_info") or event_dict.get("event", "")
78
- recent_logs.append(f"[{log_level}] {event_message}")
79
-
80
- return event_dict
81
-
82
-
83
- class PromptRequest(BaseModel):
84
- prompt: str
85
- client_id: Optional[str] = None
86
-
87
-
88
- def default_credentials() -> Dict[str, Any]:
89
- return read_yaml(default_credentials_yaml)
90
-
91
-
92
- def default_endpoints() -> Dict[str, Any]:
93
- return read_yaml_file(
94
- str(
95
- importlib_resources.files(PACKAGE_NAME).joinpath(
96
- "cli/project_templates/default/endpoints.yml"
97
- )
98
- )
99
- )
100
-
101
-
102
- def default_config(assistant_id: str) -> Dict[str, Any]:
103
- base_config = read_yaml_file(
104
- str(
105
- importlib_resources.files(PACKAGE_NAME).joinpath(
106
- "cli/project_templates/default/config.yml"
107
- )
108
- )
109
- )
110
-
111
- base_config["assistant_id"] = assistant_id
112
-
113
- return base_config
114
-
115
-
116
- async def continuously_run_task(task: Callable, name: str) -> None:
117
- """Regularly run a task."""
118
- structlogger.debug("prompt_to_bot.continuously_run_task.started", name=name)
119
-
120
- while True:
121
- try:
122
- if asyncio.iscoroutinefunction(task):
123
- await task()
124
- else:
125
- task()
126
- except asyncio.exceptions.CancelledError:
127
- structlogger.debug(
128
- "prompt_to_bot.continuously_run_task.cancelled", name=name
129
- )
130
- break
131
- except Exception as e:
132
- structlogger.error(
133
- "prompt_to_bot.continuously_run_task.error", name=name, error=str(e)
134
- )
135
- finally:
136
- await asyncio.sleep(0.1)
137
-
138
-
139
- class PromptToBotService:
140
- def __init__(self):
141
- self.app = Sanic("PromptToBotService")
142
- self.app.ctx.agent = None
143
- self.input_channel = self.setup_input_channel()
144
- self.setup_routes(self.input_channel)
145
- self.max_retries = 5
146
- self.bot_files = {}
147
-
148
- configure_cors(self.app, cors_origins=["*"])
149
-
150
- def setup_input_channel(self) -> StudioChatInput:
151
- studio_chat_credentials = default_credentials().get(StudioChatInput.name())
152
- return StudioChatInput.from_credentials(credentials=studio_chat_credentials)
153
-
154
- def setup_routes(self, input_channel: InputChannel):
155
- self.app.add_route(
156
- self.handle_prompt_to_bot, "/api/prompt-to-bot", methods=["POST"]
157
- )
158
- self.app.add_route(self.get_bot_data, "/api/bot-data", methods=["GET"])
159
-
160
- self.app.add_route(self.update_bot_data, "/api/bot-data", methods=["PUT"])
161
-
162
- self.app.add_route(self.llm_builder, "/api/llm-builder", methods=["POST"])
163
-
164
- self.app.add_route(self.health, "/", methods=["GET"])
165
-
166
- input_channels = [input_channel]
167
- channels.channel.register(input_channels, self.app, route="/webhooks/")
168
-
169
- def health(self, request):
170
- return response.json({"status": "ok"})
171
-
172
- def importer_for_data(self) -> TrainingDataImporter:
173
- return TrainingDataImporter.wrap_in_builtins(
174
- [
175
- StaticTrainingDataImporter(
176
- domain=Domain.from_dict(
177
- read_yaml(self.bot_files.get("domain.yml", ""))
178
- ),
179
- flows=YAMLFlowsReader.read_from_string(
180
- self.bot_files.get("flows.yml", "")
181
- ),
182
- config=self.config_from_bot_data(),
183
- )
184
- ]
185
- )
186
-
187
- async def validate_rasa_project(self) -> Optional[str]:
188
- """Validate the Rasa project data."""
189
- was_sys_exit_called = {"value": False}
190
-
191
- def sys_exit_mock(code: int = 0):
192
- was_sys_exit_called["value"] = True
193
-
194
- # prevent sys.exit from being called
195
- original_exit = sys.exit
196
- # TODO: avoid sys exit in the validation functions in the first place
197
- sys.exit = sys_exit_mock
198
- try:
199
- training_data_importer = self.importer_for_data()
200
-
201
- with capture_logs() as cap_logs:
202
- validate_files(
203
- fail_on_warnings=False,
204
- max_history=None,
205
- importer=training_data_importer,
206
- )
207
-
208
- if was_sys_exit_called["value"]:
209
- structlogger.error(
210
- "prompt_to_bot.validate_rasa_project.failed.sys_exit",
211
- error_logs=cap_logs,
212
- )
213
- return json.dumps(
214
- [x for x in cap_logs if x.get("log_level") != "debug"]
215
- )
216
-
217
- return None
218
- except Exception as e:
219
- structlogger.error(
220
- "prompt_to_bot.validate_rasa_project.failed.exception",
221
- error=str(e),
222
- traceback=traceback.format_exc(),
223
- )
224
- return str(e)
225
- finally:
226
- sys.exit = original_exit
227
-
228
- async def handle_prompt_to_bot(self, request):
229
- try:
230
- prompt_data = PromptRequest(**request.json)
231
- config = default_config(prompt_data.client_id)
232
- # Generate Rasa project data with retries
233
- await self.generate_rasa_project_with_retries(
234
- prompt_data.prompt,
235
- config,
236
- self.max_retries,
237
- )
238
-
239
- self.app.ctx.agent = await self.train_and_load_agent()
240
-
241
- return response.json(
242
- {
243
- "bot_data": self.bot_files,
244
- "status": "success",
245
- }
246
- )
247
-
248
- except Exception as e:
249
- structlogger.error("prompt_to_bot.error", error=str(e))
250
- return response.json({"error": str(e)}, status=500)
251
-
252
- async def get_bot_data(self, request):
253
- return response.json(self.bot_files)
254
-
255
- async def update_bot_data(self, request):
256
- response = await request.respond(content_type="text/event-stream")
257
-
258
- def sse_event(event, data):
259
- return f"event: {event}\ndata: {json.dumps(data)}\n\n"
260
-
261
- # 1. Received
262
- await response.send(sse_event("received", {"status": "received"}))
263
-
264
- bot_data = request.json
265
- for file_name, file_content in bot_data.items():
266
- self.bot_files[file_name] = file_content
267
-
268
- # 2. Validating
269
- await response.send(sse_event("validating", {"status": "validating"}))
270
- try:
271
- await self.validate_rasa_project()
272
- await response.send(
273
- sse_event("validation_success", {"status": "validation_success"})
274
- )
275
- except Exception as e:
276
- structlogger.error(
277
- "prompt_to_bot.update_bot_data.validation_error",
278
- error=str(e),
279
- event_info="Failed to validate the Rasa project. Error: " + str(e),
280
- )
281
- await response.send(
282
- sse_event(
283
- "validation_error",
284
- {"status": "validation_error", "error": str(e)},
285
- )
286
- )
287
- await response.eof()
288
- return
289
-
290
- # 3. Training
291
- await response.send(sse_event("training", {"status": "training"}))
292
- try:
293
- self.app.ctx.agent = await self.train_and_load_agent()
294
- await response.send(sse_event("train_success", {"status": "train_success"}))
295
- except Exception as e:
296
- structlogger.error(
297
- "prompt_to_bot.update_bot_data.train_error",
298
- error=str(e),
299
- event_info="Failed to train the agent. Error: " + str(e),
300
- )
301
- await response.send(
302
- sse_event("train_error", {"status": "train_error", "error": str(e)})
303
- )
304
- await response.eof()
305
- return
306
-
307
- # 4. Done
308
- await response.send(
309
- sse_event("done", {"status": "done", "bot_data": self.bot_files})
310
- )
311
- await response.eof()
312
-
313
- def config_from_bot_data(self) -> Dict[str, Any]:
314
- return read_yaml(self.bot_files.get("config.yml", ""))
315
-
316
- def update_stored_bot_data(self, bot_data: Dict[str, Any], config: Dict[str, Any]):
317
- self.bot_files = {
318
- "domain.yml": dump_obj_as_yaml_to_string(bot_data["domain"]),
319
- "flows.yml": dump_obj_as_yaml_to_string(bot_data["flows"]),
320
- "config.yml": dump_obj_as_yaml_to_string(config),
321
- }
322
-
323
- async def generate_rasa_project_with_retries(
324
- self, skill_description: str, config: Dict[str, Any], max_retry_count: int = 5
325
- ) -> Dict[str, Any]:
326
- """Generate Rasa project data with retry logic."""
327
- initial_messages = self.prompt_messages(skill_description)
328
-
329
- async def _generate(messages: List[Dict[str, Any]], tries_left: int):
330
- rasa_project_data = await self.generate_rasa_project(messages)
331
- self.update_stored_bot_data(rasa_project_data, config)
332
-
333
- structlogger.info(
334
- "prompt_to_bot.generate_rasa_project_with_retries.generated_project",
335
- tries_left=tries_left,
336
- )
337
-
338
- try:
339
- validation_error = await self.validate_rasa_project()
340
-
341
- if validation_error:
342
- structlogger.error(
343
- "prompt_to_bot.generate_rasa_project_with_retries.validation_error",
344
- validation_error=validation_error,
345
- )
346
- raise Exception(validation_error)
347
-
348
- structlogger.info(
349
- "prompt_to_bot.generate_rasa_project_with_retries.validation_success",
350
- tries_left=tries_left,
351
- )
352
-
353
- return rasa_project_data
354
- except Exception as e:
355
- structlogger.error(
356
- "prompt_to_bot.generate_rasa_project_with_retries.error",
357
- error=str(e),
358
- tries_left=tries_left,
359
- )
360
-
361
- if tries_left <= 0:
362
- raise Exception(
363
- f"Failed to generate valid Rasa project after "
364
- f"{max_retry_count} attempts"
365
- )
366
-
367
- # Use error to improve the prompt
368
- messages = messages + [
369
- {
370
- "role": "assistant",
371
- "content": json.dumps(rasa_project_data),
372
- },
373
- {
374
- "role": "user",
375
- "content": dedent(f"""
376
- Previous attempt failed with error: {e!s}
377
-
378
- Please fix the issues and generate a valid Rasa project.
379
- """),
380
- },
381
- ]
382
-
383
- return await _generate(messages, tries_left - 1)
384
-
385
- return await _generate(initial_messages, max_retry_count)
386
-
387
- def prompt_messages(self, skill_description: str) -> List[Dict[str, Any]]:
388
- system_prompt = Template(DEFAULT_SKILL_GENERATION_SYSTEM_PROMPT).render(
389
- skill_description=skill_description
390
- )
391
-
392
- return [
393
- {"role": "system", "content": system_prompt},
394
- ]
395
-
396
- async def generate_rasa_project(
397
- self, messages: List[Dict[str, Any]]
398
- ) -> Dict[str, Any]:
399
- """Generate Rasa project data using LLM."""
400
- schema_file = str(
401
- importlib_resources.files(PACKAGE_NAME).joinpath(FLOWS_SCHEMA_FILE)
402
- )
403
-
404
- # TODO: clean up the schema
405
- flows_schema = deepcopy(read_json_file(schema_file))
406
-
407
- del flows_schema["$defs"]["flow"]["properties"]["nlu_trigger"]
408
-
409
- # TODO: restrict the domain schema to only the properties that are
410
- # needed for the CALM bot
411
- domain_schema = deepcopy(
412
- read_schema_file(DOMAIN_SCHEMA_FILE, PACKAGE_NAME, False)
413
- )
414
-
415
- # not needed in calm
416
- del domain_schema["mapping"]["intents"]
417
- del domain_schema["mapping"]["entities"]
418
- del domain_schema["mapping"]["forms"]
419
-
420
- # don't think the llm needs to configure these
421
- del domain_schema["mapping"]["config"]
422
- del domain_schema["mapping"]["session_config"]
423
-
424
- # don't work, llm tends to pick from_intent or something like that
425
- del domain_schema["mapping"]["slots"]["mapping"]["regex;([A-Za-z]+)"][
426
- "mapping"
427
- ]["mappings"]
428
- # also creates issues...
429
- del domain_schema["mapping"]["slots"]["mapping"]["regex;([A-Za-z]+)"][
430
- "mapping"
431
- ]["validation"]
432
-
433
- # pull in the responses schema
434
- domain_schema["mapping"]["responses"] = read_schema_file(
435
- RESPONSES_SCHEMA_FILE, PACKAGE_NAME, False
436
- )["schema;responses"]
437
-
438
- client = openai.AsyncOpenAI()
439
- response = await client.chat.completions.create(
440
- model="gpt-4.1-2025-04-14",
441
- messages=messages,
442
- temperature=0.7,
443
- response_format={
444
- "type": "json_schema",
445
- "json_schema": {
446
- "name": "rasa_project",
447
- "schema": {
448
- "type": "object",
449
- "properties": {
450
- "domain": domain_schema,
451
- "flows": flows_schema,
452
- },
453
- "required": ["domain", "flows"],
454
- },
455
- },
456
- },
457
- )
458
-
459
- try:
460
- return json.loads(response.choices[0].message.content)
461
- except json.JSONDecodeError:
462
- raise Exception("LLM response was not valid JSON")
463
-
464
- async def generate_chat_bot_context(self) -> str:
465
- """Generate a chat bot context."""
466
- if self.app.ctx.agent and self.input_channel.latest_tracker_session_id:
467
- tracker: Optional[
468
- DialogueStateTracker
469
- ] = await self.app.ctx.agent.tracker_store.retrieve(
470
- self.input_channel.latest_tracker_session_id
471
- )
472
- return tracker_as_llm_context(tracker)
473
- else:
474
- return tracker_as_llm_context(None)
475
-
476
- def format_chat_dump(self, user_chat_history: List[Dict[str, Any]]) -> str:
477
- """Format the chat dump for the LLM."""
478
- result = ""
479
- for message in user_chat_history:
480
- if message.get("type") == "user":
481
- result += f"User: {message.get('content')}\n"
482
- else:
483
- for part in message.get("content", []):
484
- if part.get("type") == "text":
485
- result += f"Assistant: {part.get('text')}\n"
486
- return result
487
-
488
- def llm_helper_prompt_messages(
489
- self,
490
- current_conversation: str,
491
- bot_logs: str,
492
- chat_bot_files: Dict[str, str],
493
- documentation_results: str,
494
- ) -> List[Dict[str, Any]]:
495
- system_prompt = Template(DEFAULT_LLM_HELPER_SYSTEM_PROMPT).render(
496
- current_conversation=current_conversation,
497
- bot_logs=bot_logs,
498
- chat_bot_files=chat_bot_files,
499
- documentation_results=documentation_results,
500
- )
501
-
502
- return [
503
- {"role": "system", "content": system_prompt},
504
- ]
505
-
506
- async def llm_builder(self, request):
507
- current_conversation = await self.generate_chat_bot_context()
508
- bot_logs = "\n".join(recent_logs)
509
- chat_bot_files = self.bot_files
510
- user_chat_history = request.json.get("messages", [])
511
- chat_dump = self.format_chat_dump(user_chat_history)
512
-
513
- client = openai.AsyncOpenAI()
514
-
515
- results = await client.vector_stores.search(
516
- vector_store_id=VECTOR_STORE_ID,
517
- query=chat_dump,
518
- max_num_results=10,
519
- rewrite_query=True,
520
- )
521
-
522
- documentation_results = self.format_results(results.data)
523
-
524
- messages = self.llm_helper_prompt_messages(
525
- current_conversation,
526
- bot_logs,
527
- chat_bot_files,
528
- documentation_results,
529
- )
530
-
531
- for message in user_chat_history:
532
- messages.append(
533
- {
534
- "role": "user" if message.get("type") == "user" else "assistant",
535
- "content": json.dumps(message.get("content")),
536
- }
537
- )
538
-
539
- llm_helper_schema = read_json_file(
540
- importlib_resources.files(PACKAGE_NAME).joinpath(
541
- "builder/llm-helper-schema.json"
542
- )
543
- )
544
-
545
- openai_response = await client.chat.completions.create(
546
- model="gpt-4.1-2025-04-14",
547
- messages=messages,
548
- response_format={
549
- "type": "json_schema",
550
- "json_schema": {
551
- "name": "llm_helper",
552
- "schema": llm_helper_schema,
553
- },
554
- },
555
- )
556
-
557
- return response.json(json.loads(openai_response.choices[0].message.content))
558
-
559
- @staticmethod
560
- def format_results(results):
561
- formatted_results = ""
562
- for result in results:
563
- formatted_result = f"<result url='{result.attributes.get('url')}'>"
564
- for part in result.content:
565
- formatted_result += f"<content>{part.text}</content>"
566
- formatted_results += formatted_result + "</result>"
567
- return f"<sources>{formatted_results}</sources>"
568
-
569
- async def train_and_load_agent(self):
570
- file_importer = self.importer_for_data()
571
- # this is used inside the training validation. validation assumes
572
- # that the endpoints are either stored in the default location or
573
- # that they have been loaded before - so that is what we do here.
574
- with tempfile.NamedTemporaryFile() as temp_file:
575
- temp_file.write(
576
- dump_obj_as_yaml_to_string(default_endpoints()).encode("utf-8")
577
- )
578
- temp_file.flush()
579
- AvailableEndpoints.reset_instance()
580
- read_endpoints_from_path(temp_file.name)
581
-
582
- available_endpoints = AvailableEndpoints.get_instance()
583
- assert available_endpoints is not None
584
-
585
- training_result = await train(
586
- domain="",
587
- config="",
588
- training_files=None,
589
- file_importer=file_importer,
590
- )
591
-
592
- structlogger.info(
593
- "prompt_to_bot.train_and_load_agent.training_result",
594
- training_result=training_result,
595
- )
596
-
597
- agent_instance = await agent.load_agent(
598
- model_path=training_result.model,
599
- remote_storage=None,
600
- endpoints=available_endpoints,
601
- loop=self.app.loop,
602
- )
603
-
604
- structlogger.info(
605
- "prompt_to_bot.train_and_load_agent.agent_instance",
606
- agent_instance=agent_instance,
607
- )
608
-
609
- if not agent_instance.is_ready():
610
- raise Exception(
611
- "Generation of the chatbot failed with an error (model failed "
612
- "to load). Please try again."
613
- )
614
-
615
- structlogger.info(
616
- "prompt_to_bot.train_and_load_agent.agent_ready",
617
- agent_instance=agent_instance,
618
- )
619
-
620
- self.input_channel.agent = agent_instance
621
- return agent_instance
622
-
623
-
624
- def main():
625
- """Start the Prompt to Bot service."""
626
- log_level = logging.DEBUG
627
- configure_logging_and_warnings(
628
- log_level=log_level,
629
- logging_config_file=None,
630
- warn_only_once=True,
631
- filter_repeated_logs=True,
632
- )
633
- configure_structlog(
634
- log_level,
635
- include_time=True,
636
- additional_processors=[
637
- collecting_logs_processor,
638
- ],
639
- )
640
-
641
- service = PromptToBotService()
642
- register_custom_sanic_error_handler(service.app)
643
-
644
- rasa.core.utils.list_routes(service.app)
645
-
646
- service.app.run(host="0.0.0.0", port=5005, legacy=True, motd=False)
647
-
648
-
649
- if __name__ == "__main__":
650
- main()