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

@@ -0,0 +1,81 @@
1
+ import json
2
+ from typing import Optional
3
+
4
+ from rasa.shared.core.constants import DEFAULT_SLOT_NAMES
5
+ from rasa.shared.core.events import (
6
+ ActionExecuted,
7
+ BotUttered,
8
+ FlowCompleted,
9
+ FlowStarted,
10
+ SlotSet,
11
+ UserUttered,
12
+ )
13
+ from rasa.shared.core.trackers import DialogueStateTracker
14
+
15
+
16
+ def tracker_as_llm_context(tracker: Optional[DialogueStateTracker]) -> str:
17
+ """Convert a tracker to a string that can be used as context for the LLM."""
18
+ if not tracker or not tracker.events:
19
+ return "No conversation history available."
20
+
21
+ context_parts = []
22
+ current_turn = []
23
+
24
+ for event in tracker.events:
25
+ if isinstance(event, UserUttered):
26
+ if current_turn:
27
+ context_parts.append(" | ".join(current_turn))
28
+ current_turn = []
29
+ current_turn.append(f"User: {event.text}")
30
+ if event.intent:
31
+ current_turn.append(f"Intent: {event.intent.get('name')}")
32
+ if event.entities:
33
+ current_turn.append(
34
+ f"Entities: {[e.get('entity') for e in event.entities]}"
35
+ )
36
+ if event.commands:
37
+ current_turn.append(
38
+ f"Commands: {[cmd.get('name') for cmd in event.commands]}"
39
+ )
40
+
41
+ elif isinstance(event, BotUttered):
42
+ if event.text:
43
+ current_turn.append(f"Bot: {event.text}")
44
+
45
+ elif isinstance(event, ActionExecuted):
46
+ current_turn.append(f"Action: {event.action_name}")
47
+ if event.confidence:
48
+ current_turn.append(f"Confidence: {event.confidence:.2f}")
49
+
50
+ elif isinstance(event, SlotSet) and event.key not in DEFAULT_SLOT_NAMES:
51
+ current_turn.append(f"Slot Set: {event.key}={event.value}")
52
+
53
+ elif isinstance(event, FlowStarted):
54
+ current_turn.append(f"# Flow Started: {event.flow_id}")
55
+
56
+ elif isinstance(event, FlowCompleted):
57
+ current_turn.append(f"# Flow Completed: {event.flow_id}")
58
+
59
+ if current_turn:
60
+ context_parts.append(" | ".join(current_turn))
61
+
62
+ # Add final state information
63
+ context_parts.append("\nCurrent State:")
64
+ context_parts.append(f"Latest Message: {tracker.latest_message.text or '-'}")
65
+
66
+ # Add active flows from stack
67
+ if tracker.active_flow:
68
+ context_parts.append(f"Active Flow: {tracker.active_flow}")
69
+ if tracker.stack:
70
+ context_parts.append(f"Flow Stack: {json.dumps(tracker.stack.as_dict())}")
71
+
72
+ # Add slot values that are not None
73
+ non_empty_slots = {
74
+ k: str(v.value)
75
+ for k, v in tracker.slots.items()
76
+ if v is not None and k not in DEFAULT_SLOT_NAMES
77
+ }
78
+ if non_empty_slots:
79
+ context_parts.append(f"Slots: {json.dumps(non_empty_slots)}")
80
+
81
+ return "\n".join(context_parts)
@@ -0,0 +1,245 @@
1
+ You are an expert Rasa chatbot development assistant. Your role is to help users build, debug, customize, and improve
2
+ their Rasa chatbots through conversational guidance and practical code solutions.
3
+
4
+ ## Your Capabilities
5
+
6
+ You can help users with:
7
+ - **Debugging & Explanation**: Analyze conversations and logs to explain bot behavior
8
+ - **Customization & Branding**: Modify responses, styling, and bot personality
9
+ - **Skill Development**: Create new intents, entities, actions, and conversation flows
10
+ - **Knowledge Integration**: Connect external documents and knowledge bases
11
+ - **Code Generation**: Provide specific YAML configs, Python actions, and file modifications
12
+ - **Flow Design**: Design complex multi-turn conversations and business logic
13
+ - **Error Resolution**: Diagnose and fix training issues, deployment problems, and runtime errors
14
+
15
+ ## Context Available to You
16
+
17
+ You have access to:
18
+ {% if current_conversation %}
19
+ **Current Bot Conversation:**
20
+ ```
21
+ {{ current_conversation }}
22
+ ```
23
+ {% endif %}
24
+
25
+ {% if bot_logs %}
26
+ **Bot Logs:**
27
+ ```
28
+ {{ bot_logs }}
29
+ ```
30
+ {% endif %}
31
+
32
+ {% if chat_bot_files %}
33
+ **Bot Configuration Files:**
34
+ {% for file_name, file_content in chat_bot_files.items() %}
35
+ **{{ file_name }}:**
36
+ ```
37
+ {{ file_content }}
38
+ ```
39
+ {% endfor %}
40
+ {% endif %}
41
+
42
+ {% if documentation_results %}
43
+ **Relevant Documentation:**
44
+ ```
45
+ {{documentation_results}}
46
+ ```
47
+ {% endif %}
48
+
49
+ ## Response Guidelines
50
+
51
+ ### When Explaining Bot Behavior ("Why did the assistant say that?")
52
+ 1. **Identify the trigger**: Point to the specific intent, entity, or context that caused the response
53
+ 2. **Trace the flow**: Show the path through flows that led to this response
54
+ 3. **Provide code references**: Show exact lines in domain.yml, flows.yml, or actions.py
55
+ 4. **Suggest improvements**: Offer specific ways to modify the behavior if needed
56
+
57
+ Example response format:
58
+ ```
59
+ The assistant said that because:
60
+
61
+ 1. **Intent triggered**: `ask_balance` (confidence: 0.95)
62
+ 2. **Flow matched**: Line 23 in flows.yml - "balance inquiry flow"
63
+ 3. **Response used**: `utter_ask_for_account_details` from domain.yml line 45
64
+
65
+ The response is defined in your domain.yml:
66
+ ```yaml
67
+ responses:
68
+ utter_ask_for_account_details:
69
+ - text: "I'll help you check your balance. Could you please provide your account number?"
70
+ ```
71
+
72
+ To customize this, you can modify the text in domain.yml or create a custom action.
73
+ ```
74
+
75
+ ### When Helping with Customization ("Make it branded")
76
+ 1. **Identify customization points**: Show specific files and sections to modify
77
+ 2. **Provide exact code**: Give complete, ready-to-use YAML or Python code
78
+ 3. **Explain the impact**: Describe how changes affect user experience
79
+ 4. **Suggest best practices**: Recommend consistent branding approaches
80
+
81
+ ### When Generating New Skills
82
+ 1. **Gather requirements**: Ask clarifying questions about the skill's purpose
83
+ 2. **Design the flow**: Outline the conversation structure
84
+ 3. **Provide complete implementation**: Include intents, entities, flows, responses, and actions
85
+ 4. **Test scenarios**: Suggest test cases to validate the skill
86
+ 5. **Handle edge cases**: Include error handling and fallback responses
87
+
88
+ ### When Integrating Knowledge
89
+ 1. **Assess integration options**: Vector databases, retrieval actions, custom connectors
90
+ 2. **Provide implementation steps**: Complete setup instructions with code
91
+ 3. **Show preview changes**: Demonstrate how responses will change
92
+ 4. **Optimize for performance**: Suggest caching and efficiency improvements
93
+
94
+ ### Code Quality Standards
95
+ - **Always provide complete, runnable code**
96
+ - **Follow Rasa best practices** (proper intent naming, entity extraction, etc.)
97
+ - **Include error handling** in custom actions
98
+ - **Add inline comments** for complex logic
99
+ - **Validate YAML syntax** before suggesting changes
100
+ - **Consider conversation context** and maintain flow continuity
101
+ - **Do not use stories, rules or forms** These are deprecated Rasa concepts.
102
+ - **Do not refer to Rasa Studio**, the bot you are building is build with Rasa Pro.
103
+
104
+ ### Using Documentation Context
105
+ When documentation context is provided:
106
+ 1. **Reference relevant sections**: Quote or paraphrase documentation that directly answers the user's question
107
+ 2. **Provide source links**: Always include links to the full documentation page when available
108
+ 3. **Combine with bot context**: Merge documentation guidance with the user's specific bot configuration
109
+ 4. **Clarify concepts**: Use documentation to explain Rasa concepts the user might not understand
110
+ 5. **Stay current**: Prioritize documentation context over general knowledge when there are conflicts
111
+
112
+ ### When You Need More Information
113
+ Ask specific questions like:
114
+ - "Could you share the exact error message you're seeing?"
115
+ - "What should happen when the user says [specific phrase]?"
116
+ - "Do you want this to work for all users or specific user types?"
117
+ - "Should this integrate with any external systems?"
118
+
119
+ ### File Modification Format
120
+ When suggesting file changes, use this format:
121
+
122
+ **File: domain.yml**
123
+ ```yaml
124
+ # Add this to your responses section:
125
+ responses:
126
+ utter_welcome_branded:
127
+ - text: "Welcome to [Your Company Name]! I'm here to help with your banking needs."
128
+ - text: "Hi there! I'm [Bot Name], your personal banking assistant."
129
+ ```
130
+
131
+ **File: actions.py**
132
+ ```python
133
+ # Add this new action:
134
+ class ActionCustomBalance(Action):
135
+ def name(self) -> Text:
136
+ return "action_get_balance"
137
+
138
+ def run(self, dispatcher, tracker, domain):
139
+ # Your implementation here
140
+ return []
141
+ ```
142
+
143
+ ### Error Handling
144
+ When users encounter errors:
145
+ 1. **Reproduce the issue**: Show understanding of the problem
146
+ 2. **Identify root cause**: Point to specific configuration issues
147
+ 3. **Provide step-by-step fix**: Clear instructions with code examples
148
+ 4. **Prevent future issues**: Suggest validation steps and best practices
149
+
150
+ ### Conversation Flow
151
+ - **Stay in character** as a helpful Rasa expert
152
+ - **Be conversational** but precise
153
+ - **Anticipate next steps** and offer proactive suggestions
154
+ - **Reference specific files and line numbers** when possible
155
+ - **Offer multiple solutions** when appropriate (simple vs. advanced)
156
+
157
+ ## Response Format
158
+
159
+ You must return your response as a JSON array of content blocks. Each content block should follow this structure:
160
+
161
+ ### Text Blocks
162
+ Use for explanations, instructions, and general content. Supports markdown formatting:
163
+ ```json
164
+ {
165
+ "type": "text",
166
+ "text": "Great question! The assistant said that because it triggered the `ask_balance` intent. Here's what happened:\n\n1. **Intent Recognition**: Your message matched the `ask_balance` intent\n2. **Flow Flow**: This triggered the flow defined in your `flows.yml`\n3. **Response**: The bot used `utter_ask_for_account_details` from your domain"
167
+ }
168
+ ```
169
+
170
+ ### Code Blocks
171
+ Use for generic code examples and snippets:
172
+ ```json
173
+ {
174
+ "type": "code",
175
+ "text": "responses:\n utter_greet:\n - text: \"Hello! How can I help you today?\"\n - text: \"Hi there! I'm here to assist you.\"",
176
+ "language": "yaml"
177
+ }
178
+ ```
179
+
180
+ ### File Blocks
181
+ **Use whenever possible** to provide specific changes that apply to the user's bot:
182
+ ```json
183
+ {
184
+ "type": "file",
185
+ "file": "domain.yml",
186
+ "content": "responses:\n utter_welcome_branded:\n - text: \"Welcome to [Your Company Name]! I'm here to help.\"\n - text: \"Hi! I'm [Bot Name], your personal assistant.\""
187
+ }
188
+ ```
189
+
190
+ ### Link Blocks
191
+ Use to reference Rasa documentation:
192
+ ```json
193
+ {
194
+ "type": "link",
195
+ "text": "https://rasa.com/docs/rasa/domain"
196
+ }
197
+ ```
198
+
199
+ ### Response Guidelines:
200
+ - **Always return a JSON array** of content blocks
201
+ - **Prefer file blocks** over code blocks when providing bot-specific changes
202
+ - **Use multiple content blocks** as needed to fully answer the question
203
+ - **Include relevant documentation links** from https://rasa.com/docs
204
+ - **Format text blocks with markdown** for better readability
205
+
206
+ ### Example Multi-Block Response:
207
+ ```json
208
+ [
209
+ {
210
+ "type": "text",
211
+ "text": "I can help you create a new skill for handling KYC verification. According to the Rasa documentation, flows provide a structured way to define conversation patterns. This will require several components:"
212
+ },
213
+ {
214
+ "type": "file",
215
+ "file": "domain.yml",
216
+ "content": "intents:\n - request_kyc\n - provide_document\n\nentities:\n - document_type\n\nresponses:\n utter_request_documents:\n - text: \"To verify your identity, please provide a government-issued ID.\""
217
+ },
218
+ {
219
+ "type": "file",
220
+ "file": "flows.yml",
221
+ "content": "flows:\n kyc_verification:\n description: Handle KYC document verification\n start_conditions:\n - intent: request_kyc\n steps:\n - action: utter_request_documents\n - intent: provide_document\n - action: action_process_kyc_document"
222
+ },
223
+ {
224
+ "type": "file",
225
+ "file": "data/nlu.yml",
226
+ "content": "- intent: request_kyc\n examples: |\n - I need to verify my identity\n - How do I complete KYC\n - What documents do you need"
227
+ },
228
+ {
229
+ "type": "text",
230
+ "text": "For more detailed information about flows and custom actions, check out these documentation pages:"
231
+ },
232
+ {
233
+ "type": "link",
234
+ "text": "https://rasa.com/docs/rasa/flows"
235
+ },
236
+ {
237
+ "type": "link",
238
+ "text": "https://rasa.com/docs/rasa/custom-actions"
239
+ }
240
+ ]
241
+ ```
242
+
243
+ Remember: Your goal is to make Rasa development accessible and efficient. Always
244
+ provide actionable, specific guidance that users can immediately implement in the
245
+ structured content block format. Keep your response short and concise.
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+ import collections
2
3
  import importlib
3
4
  import json
4
5
  import logging
@@ -18,6 +19,7 @@ from sanic import Sanic, response
18
19
  from structlog.testing import capture_logs
19
20
 
20
21
  import rasa.core.utils
22
+ from rasa.builder.llm_context import tracker_as_llm_context
21
23
  from rasa.cli.utils import validate_files
22
24
  from rasa.constants import PACKAGE_NAME
23
25
  from rasa.core import agent, channels
@@ -47,15 +49,15 @@ structlogger = structlog.get_logger()
47
49
 
48
50
  DEFAULT_SKILL_GENERATION_SYSTEM_PROMPT = importlib.resources.read_text(
49
51
  "rasa.builder",
50
- "skill_to_bot_prompt.jinja",
52
+ "skill_to_bot_prompt.jinja2",
51
53
  )
52
54
 
53
- VECTOR_STORE_ID = "vs_685123376e288191a005b6b144d3026f"
54
-
55
+ DEFAULT_LLM_HELPER_SYSTEM_PROMPT = importlib.resources.read_text(
56
+ "rasa.builder",
57
+ "llm_helper_prompt.jinja2",
58
+ )
55
59
 
56
- class PromptRequest(BaseModel):
57
- prompt: str
58
- client_id: Optional[str] = None
60
+ VECTOR_STORE_ID = "vs_685123376e288191a005b6b144d3026f"
59
61
 
60
62
 
61
63
  default_credentials_yaml = """
@@ -65,6 +67,23 @@ studio_chat:
65
67
  session_persistence: true
66
68
  """
67
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
+
68
87
 
69
88
  def default_credentials() -> Dict[str, Any]:
70
89
  return read_yaml(default_credentials_yaml)
@@ -255,7 +274,9 @@ class PromptToBotService:
255
274
  )
256
275
  except Exception as e:
257
276
  structlogger.error(
258
- "prompt_to_bot.update_bot_data.validation_error", error=str(e)
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),
259
280
  )
260
281
  await response.send(
261
282
  sse_event(
@@ -273,7 +294,9 @@ class PromptToBotService:
273
294
  await response.send(sse_event("train_success", {"status": "train_success"}))
274
295
  except Exception as e:
275
296
  structlogger.error(
276
- "prompt_to_bot.update_bot_data.train_error", error=str(e)
297
+ "prompt_to_bot.update_bot_data.train_error",
298
+ error=str(e),
299
+ event_info="Failed to train the agent. Error: " + str(e),
277
300
  )
278
301
  await response.send(
279
302
  sse_event("train_error", {"status": "train_error", "error": str(e)})
@@ -298,19 +321,15 @@ class PromptToBotService:
298
321
  }
299
322
 
300
323
  async def generate_rasa_project_with_retries(
301
- self, base_prompt: str, config: Dict[str, Any], max_retry_count: int = 5
324
+ self, skill_description: str, config: Dict[str, Any], max_retry_count: int = 5
302
325
  ) -> Dict[str, Any]:
303
326
  """Generate Rasa project data with retry logic."""
304
- initial_messages = self.prompt_messages(base_prompt)
327
+ initial_messages = self.prompt_messages(skill_description)
305
328
 
306
329
  async def _generate(messages: List[Dict[str, Any]], tries_left: int):
307
330
  rasa_project_data = await self.generate_rasa_project(messages)
308
331
  self.update_stored_bot_data(rasa_project_data, config)
309
332
 
310
- # write the data to a file
311
- with open(f"rasa_project_{tries_left}.json", "w") as f:
312
- json.dump(rasa_project_data, f)
313
-
314
333
  structlogger.info(
315
334
  "prompt_to_bot.generate_rasa_project_with_retries.generated_project",
316
335
  tries_left=tries_left,
@@ -365,9 +384,9 @@ class PromptToBotService:
365
384
 
366
385
  return await _generate(initial_messages, max_retry_count)
367
386
 
368
- def prompt_messages(self, prompt: str) -> List[Dict[str, Any]]:
387
+ def prompt_messages(self, skill_description: str) -> List[Dict[str, Any]]:
369
388
  system_prompt = Template(DEFAULT_SKILL_GENERATION_SYSTEM_PROMPT).render(
370
- prompt=prompt
389
+ skill_description=skill_description
371
390
  )
372
391
 
373
392
  return [
@@ -450,107 +469,73 @@ class PromptToBotService:
450
469
  ] = await self.app.ctx.agent.tracker_store.retrieve(
451
470
  self.input_channel.latest_tracker_session_id
452
471
  )
453
- if tracker is None:
454
- test_conversation = []
455
- else:
456
- test_conversation = tracker.current_state()
472
+ return tracker_as_llm_context(tracker)
457
473
  else:
458
- test_conversation = []
474
+ return tracker_as_llm_context(None)
459
475
 
460
- chat_bot_files = self.bot_files
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
+ )
461
501
 
462
- return {
463
- "test_conversation": test_conversation,
464
- "chat_bot_files": chat_bot_files,
465
- }
502
+ return [
503
+ {"role": "system", "content": system_prompt},
504
+ ]
466
505
 
467
506
  async def llm_builder(self, request):
468
- chat_bot_context = await self.generate_chat_bot_context()
507
+ current_conversation = await self.generate_chat_bot_context()
508
+ bot_logs = "\n".join(recent_logs)
509
+ chat_bot_files = self.bot_files
469
510
  user_chat_history = request.json.get("messages", [])
470
- last_user_message = (
471
- user_chat_history[-1].get("content") if user_chat_history else ""
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,
472
529
  )
473
530
 
474
- prompt = dedent(f"""
475
- You are a helpful assistant that helps users building chatbots using Rasa.
476
- Do not mention Rasa Studio - only ever refer to Rasa Pro.
477
- You are given the user question as well as context about the user's project.
478
- You need to generate a response using content blocks.
479
-
480
- The content blocks should be in the following format:
481
- {{
482
- "type": "text",
483
- "text": "Great question, you can take a look at the following resource:"
484
- }}
485
- The type can be one of the following: text, link, file, code.
486
- When using a block of type `text`, the `text` attribute can contain markdown.
487
- Use markdown to format the text when needed.
488
- The text is the text of the content block.
489
-
490
- Code blocks:
491
- {{
492
- "type": "code",
493
- "text": "- action: utter_greet\n next: END\n",
494
- "language": "yaml"
495
- }}
496
- Use code blocks to provide generic code examples. Whenever possible,
497
- use file blocks to provide the user with changes that apply to their bot.
498
-
499
- Link blocks:
500
- {{
501
- "type": "link",
502
- "text": "http://rasa.com/docs/rasa/core/flows"
503
- }}
504
-
505
- File blocks:
506
- {{
507
- "type": "file",
508
- "file": "flows.yml",
509
- "content": "- action: utter_greet\n next: END\n",
510
- }}
511
- Whenever possible, use file blocks to provide the user with changes
512
- that apply to their bot.
513
-
514
- You can use multiple content blocks to answer the user's question. Return
515
- as many content blocks as needed.
516
-
517
- Create links to https://rasa.com/docs for the user to take a look at.
518
-
519
- Chat bot context:
520
- {json.dumps(chat_bot_context)}
521
- """)
522
-
523
- past_messages = []
524
531
  for message in user_chat_history:
525
- past_messages.append(
532
+ messages.append(
526
533
  {
527
534
  "role": "user" if message.get("type") == "user" else "assistant",
528
535
  "content": json.dumps(message.get("content")),
529
536
  }
530
537
  )
531
538
 
532
- client = openai.AsyncOpenAI()
533
-
534
- results = await client.vector_stores.search(
535
- vector_store_id=VECTOR_STORE_ID,
536
- query=last_user_message,
537
- )
538
-
539
- formatted_results = self.format_results(results.data)
540
-
541
- messages = [
542
- {"role": "system", "content": prompt},
543
- *past_messages,
544
- {
545
- "role": "user",
546
- "content": (
547
- f"Documentation Context: {formatted_results}\n\n"
548
- "Respond with a json array of content blocks. Keep the "
549
- "response short and concise."
550
- ),
551
- },
552
- ]
553
-
554
539
  llm_helper_schema = read_json_file(
555
540
  importlib_resources.files(PACKAGE_NAME).joinpath(
556
541
  "builder/llm-helper-schema.json"
@@ -622,7 +607,10 @@ class PromptToBotService:
622
607
  )
623
608
 
624
609
  if not agent_instance.is_ready():
625
- raise Exception("Failed to load model.")
610
+ raise Exception(
611
+ "Generation of the chatbot failed with an error (model failed "
612
+ "to load). Please try again."
613
+ )
626
614
 
627
615
  structlogger.info(
628
616
  "prompt_to_bot.train_and_load_agent.agent_ready",
@@ -642,7 +630,13 @@ def main():
642
630
  warn_only_once=True,
643
631
  filter_repeated_logs=True,
644
632
  )
645
- configure_structlog(log_level, include_time=True)
633
+ configure_structlog(
634
+ log_level,
635
+ include_time=True,
636
+ additional_processors=[
637
+ collecting_logs_processor,
638
+ ],
639
+ )
646
640
 
647
641
  service = PromptToBotService()
648
642
  register_custom_sanic_error_handler(service.app)
@@ -127,11 +127,11 @@ CALM BOT JSON:
127
127
  - Use `steps` to outline the conversation flow
128
128
  - Implement `collect` steps for gathering information
129
129
  - `collect` steps should reference an existing slot
130
- - For a collect step referencing a slot `A`, there should be a corresponding `utter_ask_A`
130
+ - For a collect step referencing a slot `A`, there should be a corresponding `utter_ask_A`
131
131
  utterance that is used in the collect step to ask for the information to be stored in `A`
132
132
  - Use `action` steps for custom actions
133
133
  - Implement conditional logic with `if`, `then`, and `else` where appropriate
134
- - Use `next` to define the flow between steps. If the flow should end after a step, add next: END.
134
+ - Use `next` to define the flow between steps. If the flow should end after a step, add next: END.
135
135
  - The content after `then` or `else` can be: the id of another step defined in the flow, a list of steps, or an END
136
136
  - End the flow with an appropriate action or message
137
137
 
@@ -155,4 +155,5 @@ CALM BOT JSON:
155
155
 
156
156
  Now, please generate Rasa CALM flow and domain JSON configuration for the following skill description:
157
157
 
158
- ${skillDescription}
158
+ USER_SKILL_DESCRIPTION:
159
+ {{skill_description}}
@@ -206,9 +206,6 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
206
206
 
207
207
  async def on_tracker_updated(self, tracker: "DialogueStateTracker") -> None:
208
208
  """Triggers a tracker update notification after a change to the tracker."""
209
- # we need the latest session id to use it for the llm helper to get the
210
- # most recent conversation the user had with the bot.
211
- self.latest_tracker_session_id = tracker.sender_id
212
209
  await self.publish_tracker_update(tracker.sender_id, tracker_as_dump(tracker))
213
210
 
214
211
  async def publish_tracker_update(self, sender_id: str, tracker_dump: Dict) -> None:
@@ -216,6 +213,11 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
216
213
  if not self.sio:
217
214
  structlogger.error("studio_chat.on_tracker_updated.sio_not_initialized")
218
215
  return
216
+
217
+ # we need the latest session id to use it for the llm helper to get the
218
+ # most recent conversation the user had with the bot.
219
+ self.latest_tracker_session_id = sender_id
220
+
219
221
  await self.sio.emit("tracker", tracker_dump, room=sender_id)
220
222
 
221
223
  async def on_message_proxy(
@@ -227,7 +229,14 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
227
229
 
228
230
  Triggers a tracker update notification after processing the message.
229
231
  """
230
- await on_new_message(message)
232
+ try:
233
+ await on_new_message(message)
234
+ except Exception as e:
235
+ structlogger.exception(
236
+ "studio_chat.on_new_message.error",
237
+ error=str(e),
238
+ sender_id=message.sender_id,
239
+ )
231
240
 
232
241
  if not self.agent:
233
242
  structlogger.error("studio_chat.on_message_proxy.agent_not_initialized")
@@ -437,8 +446,15 @@ class StudioChatInput(SocketIOInput, VoiceInputChannel):
437
446
  ws.put_message(data)
438
447
  return
439
448
 
440
- # Handle text messages
441
- await self.handle_user_message(sid, data, on_new_message)
449
+ try:
450
+ # Handle text messages
451
+ await self.handle_user_message(sid, data, on_new_message)
452
+ except Exception as e:
453
+ structlogger.exception(
454
+ "studio_chat.sio.handle_message.error",
455
+ error=str(e),
456
+ sid=sid,
457
+ )
442
458
 
443
459
  @self.sio.on("update_tracker", namespace=self.namespace)
444
460
  async def on_update_tracker(sid: Text, data: Dict) -> None:
@@ -734,7 +734,14 @@ def _run_action_step(
734
734
  # do not log about non-existing validation actions of collect steps
735
735
  utter_action_name = render_template_variables("{{context.utter}}", context)
736
736
  if utter_action_name not in available_actions:
737
- structlogger.warning("flow.step.run.action.unknown", action=action_name)
737
+ structlogger.warning(
738
+ "flow.step.run.action.unknown",
739
+ action=action_name,
740
+ event_info=(
741
+ f"The action '{action_name}' is not defined in the domain but "
742
+ f"getting triggered by the flow '{step.flow_id}'."
743
+ ),
744
+ )
738
745
  return ContinueFlowWithNextStep(events=initial_events)
739
746
 
740
747
 
rasa/utils/log_utils.py CHANGED
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import logging
4
4
  import os
5
5
  import sys
6
- from typing import Any, Optional
6
+ from typing import Any, List, Optional
7
7
 
8
8
  import structlog
9
9
  from structlog.dev import ConsoleRenderer
@@ -37,6 +37,7 @@ class HumanConsoleRenderer(ConsoleRenderer):
37
37
  def configure_structlog(
38
38
  log_level: Optional[int] = None,
39
39
  include_time: bool = False,
40
+ additional_processors: Optional[List[structlog.processors.Processor]] = None,
40
41
  ) -> None:
41
42
  """Configure logging of the server."""
42
43
  if log_level is None: # Log level NOTSET is 0 so we use `is None` here
@@ -75,6 +76,9 @@ def configure_structlog(
75
76
  if include_time:
76
77
  shared_processors.append(structlog.processors.TimeStamper(fmt="iso"))
77
78
 
79
+ if additional_processors:
80
+ shared_processors.extend(additional_processors)
81
+
78
82
  if not FORCE_JSON_LOGGING and sys.stderr.isatty():
79
83
  # Pretty printing when we run in a terminal session.
80
84
  # Automatically prints pretty tracebacks when "rich" is installed
rasa/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  # this file will automatically be changed,
2
2
  # do not add anything but the version number here!
3
- __version__ = "3.13.0a1.dev4"
3
+ __version__ = "3.13.0a1.dev6"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rasa-pro
3
- Version: 3.13.0a1.dev4
3
+ Version: 3.13.0a1.dev6
4
4
  Summary: State-of-the-art open-core Conversational AI framework for Enterprises that natively leverages generative AI for effortless assistant development.
5
5
  Keywords: nlp,machine-learning,machine-learning-library,bot,bots,botkit,rasa conversational-agents,conversational-ai,chatbot,chatbot-framework,bot-framework
6
6
  Author: Rasa Technologies GmbH
@@ -4,9 +4,11 @@ rasa/api.py,sha256=RY3SqtlOcdq4YZGgr6DOm-nUBpiA8l8uguUZOctL_7o,6320
4
4
  rasa/builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  rasa/builder/create_openai_vector_store.py,sha256=GeOV5Wa5snNr6PNOnRcLjltKrG2NyydeRgGvs81n37g,1929
6
6
  rasa/builder/llm-helper-schema.json,sha256=z5IJc_-2mZ9oQ-z-9WzTivOoqYsLXCAm8MIOTWy5rGs,1609
7
- rasa/builder/prompt_to_bot.py,sha256=ntATcck6MMHTNRQpzXQOB2tseMB21NgKi9QSzZddyiQ,22436
7
+ rasa/builder/llm_context.py,sha256=zy7htrXgS_QWJWeEj4TfseQgTI65whFJR_4GKm_iOvE,2826
8
+ rasa/builder/llm_helper_prompt.jinja2,sha256=AhfEzXYIMTmWgd2TgVmPVeCfojHA29IiuO6JhTOXXKY,9585
9
+ rasa/builder/prompt_to_bot.py,sha256=EoWzwsg1PdIgYUReRNhQSguIEOLdMf_sNWHPSpFYxLU,22257
8
10
  rasa/builder/scrape_rasa_docs.py,sha256=HukkTCIh1rMCE8D_EtXGHy0aHtFBVrVTT_6Wpex3XQM,2428
9
- rasa/builder/skill_to_bot_prompt.jinja,sha256=h_HyrqPYMjLht8LJyw6vRChNkBTPM0uq2wopo9VjGc0,5345
11
+ rasa/builder/skill_to_bot_prompt.jinja2,sha256=NPQrQpSfrxF1IAZutkRSW7_hmho36WM9b77Pyqb5oxs,5369
10
12
  rasa/cli/__init__.py,sha256=eO5vp9rFCANtbTVU-pxN3iMBKw4p9WRcgzytt9MzinY,115
11
13
  rasa/cli/arguments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
14
  rasa/cli/arguments/data.py,sha256=e3mYapaRIczM74P5genuXy1ORqIR4x20khQXUvy8JLA,3040
@@ -259,7 +261,7 @@ rasa/core/channels/rest.py,sha256=LWBYBdVzOz5Vv5tZCkB1QA7LxXJFTeC87CQLAi_ZGeI,73
259
261
  rasa/core/channels/rocketchat.py,sha256=hajaH6549CjEYFM5jSapw1DQKBPKTXbn7cVSuZzknmI,5999
260
262
  rasa/core/channels/slack.py,sha256=jVsTTUu9wUjukPoIsAhbee9o0QFUMCNlQHbR8LTcMBc,24406
261
263
  rasa/core/channels/socketio.py,sha256=ZEavmx2on9AH73cuIFSGMKn1LHJhzcQVaqrFz7SH-CE,11348
262
- rasa/core/channels/studio_chat.py,sha256=U4aDQ17asMv1m0gHYRb6PHJPkCNzG2MgvQZNIsbrDa8,19547
264
+ rasa/core/channels/studio_chat.py,sha256=b61PxuvvRNStmVsDHiz_INQ1N14KbeIY3gztt4QQi28,20007
263
265
  rasa/core/channels/telegram.py,sha256=TKVknsk3U9tYeY1a8bzlhqkltWmZfGSOvrcmwa9qozc,12499
264
266
  rasa/core/channels/twilio.py,sha256=2BTQpyx0b0yPpc0A2BHYfxLPgodrLGLs8nq6i3lVGAM,5906
265
267
  rasa/core/channels/vier_cvg.py,sha256=5O4yx0TDQIMppvlCxTOzmPB60CA-vqQXqWQ7upfrTO0,13496
@@ -332,7 +334,7 @@ rasa/core/policies/enterprise_search_prompt_with_relevancy_check_and_citation_te
332
334
  rasa/core/policies/flow_policy.py,sha256=Rvx5MIGDHi9sVxGazf-dXs6F-hFHSi3UoVjjSP8ATik,7470
333
335
  rasa/core/policies/flows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
334
336
  rasa/core/policies/flows/flow_exceptions.py,sha256=_FQuN-cerQDM1pivce9bz4zylh5UYkljvYS1gjDukHI,1527
335
- rasa/core/policies/flows/flow_executor.py,sha256=rdODUFtDRlpgFV7Wzd6UuSYpXbiqUIwaaVZkl1HueBg,28314
337
+ rasa/core/policies/flows/flow_executor.py,sha256=MDYZ_XKl8LfzmBwcyEUL3Tnap0lcqpzknSgwTyJ_kpc,28592
336
338
  rasa/core/policies/flows/flow_step_result.py,sha256=agjPrD6lahGSe2ViO5peBeoMdI9ngVGRSgtytgxmJmg,1360
337
339
  rasa/core/policies/intentless_policy.py,sha256=1A7FSkI4PQdN3t1p3GQhSImmO-m6UVCUzzEsjxz4nKc,38040
338
340
  rasa/core/policies/intentless_prompt_template.jinja2,sha256=KhIL3cruMmkxhrs5oVbqgSvK6ZiN_6TQ_jXrgtEB-ZY,677
@@ -820,7 +822,7 @@ rasa/utils/endpoints.py,sha256=jX9xSI_3KJ-NpzymyfaO-Zj-ISaWbA4ql2Kx3NulBvE,10905
820
822
  rasa/utils/io.py,sha256=LIAdQQqUPA-V_mdpgeQzPDzA4rmsdZLyVKc8j_0Z70Y,7161
821
823
  rasa/utils/json_utils.py,sha256=SKtJzzsIRCAgNEQiBvWDDm9euMRBgJ-TyvCi2tXHH1w,1689
822
824
  rasa/utils/licensing.py,sha256=_YGELCUjBF9rzVwlKoP1YfnqskszHUqyd-_qVpXr5Kw,20508
823
- rasa/utils/log_utils.py,sha256=QR0R5Ezs9xOaESluelqdikViIypXSWVxCPJmJM4Ir3E,5440
825
+ rasa/utils/log_utils.py,sha256=ihkghF8HQ-9nAH04OE433aaYXamSWuw8zBMBIRFewlY,5615
824
826
  rasa/utils/mapper.py,sha256=CZiD3fu7-W-OJgoB1R8JaOg-Hq13TK20D-zGVNgbF18,7726
825
827
  rasa/utils/ml_utils.py,sha256=y4Czr9GdRBj-a2npXU8ED2qC9bzw5olRyqQEmu5BB8k,4185
826
828
  rasa/utils/plotting.py,sha256=Dv7O58T4eu3XwwIFgptx4ay1ocjHLmeA7uReN2FIne4,12260
@@ -847,9 +849,9 @@ rasa/utils/train_utils.py,sha256=ClJx-6x3-h3Vt6mskacgkcCUJTMXjFPe3zAcy_DfmaU,212
847
849
  rasa/utils/url_tools.py,sha256=dZ1HGkVdWTJB7zYEdwoDIrEuyX9HE5WsxKKFVsXBLE0,1218
848
850
  rasa/utils/yaml.py,sha256=KjbZq5C94ZP7Jdsw8bYYF7HASI6K4-C_kdHfrnPLpSI,2000
849
851
  rasa/validator.py,sha256=IRhLfcgCpps0wSpokOvUGNaY8t8GsmeSmPOUVRKeOeE,83087
850
- rasa/version.py,sha256=jE1pYjm2152_i0qt5oD2cxd0kGGE-S9GshzD3iFuYfQ,124
851
- rasa_pro-3.13.0a1.dev4.dist-info/METADATA,sha256=df5eOzp5yQ8PeEp2nGD8xza-F0mW2ROkVGpjBS5-2Lc,10562
852
- rasa_pro-3.13.0a1.dev4.dist-info/NOTICE,sha256=7HlBoMHJY9CL2GlYSfTQ-PZsVmLmVkYmMiPlTjhuCqA,218
853
- rasa_pro-3.13.0a1.dev4.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
854
- rasa_pro-3.13.0a1.dev4.dist-info/entry_points.txt,sha256=ckJ2SfEyTPgBqj_I6vm_tqY9dZF_LAPJZA335Xp0Q9U,43
855
- rasa_pro-3.13.0a1.dev4.dist-info/RECORD,,
852
+ rasa/version.py,sha256=IZ2ybsKOBWTR0KSRoc80l0EOgaRAf-MH27mX4j-rvw0,124
853
+ rasa_pro-3.13.0a1.dev6.dist-info/METADATA,sha256=I0gXAqseW9UEzuLDgxOTpvue2duKhy497BPcQJFJGr0,10562
854
+ rasa_pro-3.13.0a1.dev6.dist-info/NOTICE,sha256=7HlBoMHJY9CL2GlYSfTQ-PZsVmLmVkYmMiPlTjhuCqA,218
855
+ rasa_pro-3.13.0a1.dev6.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
856
+ rasa_pro-3.13.0a1.dev6.dist-info/entry_points.txt,sha256=ckJ2SfEyTPgBqj_I6vm_tqY9dZF_LAPJZA335Xp0Q9U,43
857
+ rasa_pro-3.13.0a1.dev6.dist-info/RECORD,,