rasa-pro 3.14.0a15__py3-none-any.whl → 3.14.0a16__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/builder/config.py +1 -0
- rasa/builder/copilot/constants.py +3 -0
- rasa/builder/copilot/copilot.py +127 -31
- rasa/builder/copilot/models.py +34 -0
- rasa/builder/copilot/prompts/copilot_system_prompt.jinja2 +28 -84
- rasa/builder/copilot/prompts/latest_user_message_context_prompt.jinja2 +61 -0
- rasa/builder/copilot/telemetry.py +16 -6
- rasa/builder/document_retrieval/models.py +3 -3
- rasa/builder/main.py +14 -5
- rasa/builder/project_generator.py +1 -3
- rasa/builder/service.py +8 -9
- rasa/builder/template_cache.py +183 -9
- rasa/cli/project_templates/telco/data/general/human_handoff.yml +1 -1
- rasa/cli/project_templates/telco/domain/general/human_handoff.yml +3 -6
- rasa/cli/project_templates/telco/tests/e2e_test_cases/billing/understand_bill.yml +67 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/bot_challenge.yml +8 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/feedback.yml +46 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/goodbye.yml +9 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/hello.yml +8 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/human_handoff.yml +35 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/general/patterns.yml +23 -0
- rasa/cli/project_templates/telco/tests/e2e_test_cases/network/solve_internet_issue.yml +57 -0
- rasa/core/channels/development_inspector.py +1 -21
- rasa/core/channels/hangouts.py +2 -2
- rasa/core/channels/inspector/dist/assets/{arc-c24d8d79.js → arc-460861ce.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{blockDiagram-38ab4fdb-1b6b9f26.js → blockDiagram-38ab4fdb-16c993e0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{c4Diagram-3d4e48cf-da91d0f9.js → c4Diagram-3d4e48cf-488337d7.js} +1 -1
- rasa/core/channels/inspector/dist/assets/channel-b560a3d4.js +1 -0
- rasa/core/channels/inspector/dist/assets/{classDiagram-70f12bd4-6067f302.js → classDiagram-70f12bd4-b08e53a8.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{classDiagram-v2-f2320105-705d024a.js → classDiagram-v2-f2320105-b73f5a83.js} +1 -1
- rasa/core/channels/inspector/dist/assets/clone-67015557.js +1 -0
- rasa/core/channels/inspector/dist/assets/{createText-2e5e7dd3-3751dffe.js → createText-2e5e7dd3-0210a219.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{edges-e0da2a9e-7b25b4af.js → edges-e0da2a9e-28df7099.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{erDiagram-9861fffd-eb7deea8.js → erDiagram-9861fffd-9fbf4a58.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDb-956e92f1-67235ff6.js → flowDb-956e92f1-fa691f62.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{flowDiagram-66a62f08-34c3a16a.js → flowDiagram-66a62f08-ca907b67.js} +1 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-4a070961.js +1 -0
- rasa/core/channels/inspector/dist/assets/{flowchart-elk-definition-4a651766-f1a93631.js → flowchart-elk-definition-4a651766-c10945f2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{ganttDiagram-c361ad54-a68cbad1.js → ganttDiagram-c361ad54-9d49a75a.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{gitGraphDiagram-72cf32ee-0b1e4a1d.js → gitGraphDiagram-72cf32ee-9aa698ac.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{graph-f3c1d212.js → graph-3ab38d50.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-3862675e-34cbca30.js → index-3862675e-6edac98f.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{index-051c5a6e.js → index-61128091.js} +41 -40
- rasa/core/channels/inspector/dist/assets/{infoDiagram-f8f76790-e69960a1.js → infoDiagram-f8f76790-21baff85.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{journeyDiagram-49397b02-8dd3296a.js → journeyDiagram-49397b02-4a6c7e98.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{layout-e93126bc.js → layout-4beae36e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{line-15eb1e26.js → line-633b638e.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{linear-fec95d33.js → linear-22d77d65.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{mindmap-definition-fc14e90a-2557813e.js → mindmap-definition-fc14e90a-f219ef43.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{pieDiagram-8a3498a8-40d756b1.js → pieDiagram-8a3498a8-c7e1cafb.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{quadrantDiagram-120e2f19-a48cbdcd.js → quadrantDiagram-120e2f19-045e49b4.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{requirementDiagram-deff3bca-dc778150.js → requirementDiagram-deff3bca-22485cb9.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sankeyDiagram-04a897e0-10026b94.js → sankeyDiagram-04a897e0-281c3da2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{sequenceDiagram-704730f1-3b2ed10a.js → sequenceDiagram-704730f1-a3dd10e0.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-587899a1-c5f3b3fb.js → stateDiagram-587899a1-61bd6eb2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{stateDiagram-v2-d93cdb3a-e503656b.js → stateDiagram-v2-d93cdb3a-deead491.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-6aaf32cf-a683ce56.js → styles-6aaf32cf-1b10e104.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-9a916d00-02bcdcee.js → styles-9a916d00-b1e18e58.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{styles-c10674c1-8e90dbb9.js → styles-c10674c1-956c3492.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{svgDrawCommon-08f97a94-7c23fc1e.js → svgDrawCommon-08f97a94-e13f753d.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{timeline-definition-85554ec2-c42faec8.js → timeline-definition-85554ec2-e568acd2.js} +1 -1
- rasa/core/channels/inspector/dist/assets/{xychartDiagram-e933f94c-5e3bb0ea.js → xychartDiagram-e933f94c-8b7e27fc.js} +1 -1
- rasa/core/channels/inspector/dist/index.html +1 -1
- rasa/core/channels/inspector/src/App.tsx +0 -7
- rasa/core/channels/inspector/src/components/DialogueInformation.tsx +9 -1
- rasa/core/channels/inspector/src/components/LatencyDisplay.tsx +63 -35
- rasa/core/channels/inspector/src/types.ts +32 -7
- rasa/core/channels/studio_chat.py +14 -40
- rasa/core/constants.py +6 -0
- rasa/core/iam_credentials_providers/__init__.py +0 -0
- rasa/core/iam_credentials_providers/aws_iam_credentials_providers.py +66 -0
- rasa/core/iam_credentials_providers/credentials_provider_protocol.py +89 -0
- rasa/core/processor.py +32 -0
- rasa/core/redis_connection_factory.py +411 -0
- rasa/core/tracker_stores/redis_tracker_store.py +32 -14
- rasa/core/tracker_stores/sql_tracker_store.py +57 -1
- rasa/model_manager/socket_bridge.py +1 -2
- rasa/shared/core/constants.py +1 -0
- rasa/shared/core/events.py +2 -0
- rasa/version.py +1 -1
- {rasa_pro-3.14.0a15.dist-info → rasa_pro-3.14.0a16.dist-info}/METADATA +11 -12
- {rasa_pro-3.14.0a15.dist-info → rasa_pro-3.14.0a16.dist-info}/RECORD +90 -77
- rasa/core/channels/inspector/dist/assets/channel-d2444dfd.js +0 -1
- rasa/core/channels/inspector/dist/assets/clone-281a0990.js +0 -1
- rasa/core/channels/inspector/dist/assets/flowDiagram-v2-96b9c2cf-aa4cca3b.js +0 -1
- /rasa/cli/project_templates/telco/domain/billing/{domain_undertand_bill.yml → understand_bill.yml} +0 -0
- /rasa/cli/project_templates/telco/domain/network/{domain_reboot_router.yml → reboot_router.yml} +0 -0
- /rasa/cli/project_templates/telco/domain/network/{domain_reset_router.yml → reset_router.yml} +0 -0
- /rasa/cli/project_templates/telco/domain/network/{domain_run_speed_test.yml → run_speed_test.yml} +0 -0
- /rasa/cli/project_templates/telco/domain/network/{domain_solve_internet_issue.yml → solve_internet_issue.yml} +0 -0
- {rasa_pro-3.14.0a15.dist-info → rasa_pro-3.14.0a16.dist-info}/NOTICE +0 -0
- {rasa_pro-3.14.0a15.dist-info → rasa_pro-3.14.0a16.dist-info}/WHEEL +0 -0
- {rasa_pro-3.14.0a15.dist-info → rasa_pro-3.14.0a16.dist-info}/entry_points.txt +0 -0
rasa/builder/config.py
CHANGED
|
@@ -39,6 +39,7 @@ VALIDATION_MAX_HISTORY = None # Could be configured if needed
|
|
|
39
39
|
COPILOT_CONTROLLED_RESPONSE_MAX_TOKENS = 20
|
|
40
40
|
COPILOT_HANDLER_ROLLING_BUFFER_SIZE = 20
|
|
41
41
|
COPILOT_ASSISTANT_TRACKER_MAX_TURNS = 10
|
|
42
|
+
COPILOT_DOCUMENTATION_SEARCH_QUERY_HISTORY_MESSAGES = 5
|
|
42
43
|
|
|
43
44
|
# Guardrail Configuration
|
|
44
45
|
LAKERA_BASE_URL = os.getenv("LAKERA_BASE_URL", "https://api.lakera.ai/v2").rstrip("/")
|
|
@@ -3,6 +3,9 @@ from typing import Literal
|
|
|
3
3
|
# A dot-path for importlib to the copilot prompt
|
|
4
4
|
COPILOT_PROMPTS_DIR = "builder.copilot.prompts"
|
|
5
5
|
COPILOT_PROMPTS_FILE = "copilot_system_prompt.jinja2"
|
|
6
|
+
COPILOT_LAST_USER_MESSAGE_CONTEXT_PROMPT_FILE = (
|
|
7
|
+
"latest_user_message_context_prompt.jinja2"
|
|
8
|
+
)
|
|
6
9
|
|
|
7
10
|
# A dot-path for importlib to the rasa internal messages templates
|
|
8
11
|
COPILOT_MESSAGE_TEMPLATES_DIR = "builder.copilot.templated_messages"
|
rasa/builder/copilot/copilot.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import copy
|
|
2
3
|
import importlib
|
|
3
4
|
import json
|
|
4
5
|
from contextlib import asynccontextmanager
|
|
@@ -10,7 +11,9 @@ from jinja2 import Template
|
|
|
10
11
|
from typing_extensions import AsyncGenerator
|
|
11
12
|
|
|
12
13
|
from rasa.builder import config
|
|
14
|
+
from rasa.builder.config import COPILOT_DOCUMENTATION_SEARCH_QUERY_HISTORY_MESSAGES
|
|
13
15
|
from rasa.builder.copilot.constants import (
|
|
16
|
+
COPILOT_LAST_USER_MESSAGE_CONTEXT_PROMPT_FILE,
|
|
14
17
|
COPILOT_PROMPTS_DIR,
|
|
15
18
|
COPILOT_PROMPTS_FILE,
|
|
16
19
|
ROLE_COPILOT,
|
|
@@ -20,8 +23,11 @@ from rasa.builder.copilot.constants import (
|
|
|
20
23
|
)
|
|
21
24
|
from rasa.builder.copilot.exceptions import CopilotStreamError
|
|
22
25
|
from rasa.builder.copilot.models import (
|
|
26
|
+
CopilotChatMessage,
|
|
23
27
|
CopilotContext,
|
|
28
|
+
CopilotGenerationContext,
|
|
24
29
|
ResponseCategory,
|
|
30
|
+
TextContent,
|
|
25
31
|
UsageStatistics,
|
|
26
32
|
)
|
|
27
33
|
from rasa.builder.document_retrieval.inkeep_document_retrieval import (
|
|
@@ -48,6 +54,12 @@ class Copilot:
|
|
|
48
54
|
COPILOT_PROMPTS_FILE,
|
|
49
55
|
)
|
|
50
56
|
)
|
|
57
|
+
self._last_user_message_context_prompt_template = Template(
|
|
58
|
+
importlib.resources.read_text(
|
|
59
|
+
f"{PACKAGE_NAME}.{COPILOT_PROMPTS_DIR}",
|
|
60
|
+
COPILOT_LAST_USER_MESSAGE_CONTEXT_PROMPT_FILE,
|
|
61
|
+
)
|
|
62
|
+
)
|
|
51
63
|
|
|
52
64
|
# The final stream chunk includes usage statistics.
|
|
53
65
|
self.usage_statistics = UsageStatistics()
|
|
@@ -102,7 +114,7 @@ class Copilot:
|
|
|
102
114
|
async def generate_response(
|
|
103
115
|
self,
|
|
104
116
|
context: CopilotContext,
|
|
105
|
-
) -> tuple[AsyncGenerator[str, None],
|
|
117
|
+
) -> tuple[AsyncGenerator[str, None], CopilotGenerationContext]:
|
|
106
118
|
"""Generate a response from the copilot.
|
|
107
119
|
|
|
108
120
|
This method performs document retrieval and response generation as a single
|
|
@@ -114,22 +126,27 @@ class Copilot:
|
|
|
114
126
|
context: The context of the copilot.
|
|
115
127
|
|
|
116
128
|
Returns:
|
|
117
|
-
A tuple containing the async response stream
|
|
118
|
-
|
|
129
|
+
A tuple containing the async response stream and a
|
|
130
|
+
CopilotGenerationContext object with relevant documents, and all the
|
|
131
|
+
messages used to generate the response.
|
|
119
132
|
|
|
120
133
|
Raises:
|
|
121
134
|
CopilotStreamError: If the stream fails.
|
|
122
135
|
Exception: If an unexpected error occurs.
|
|
123
136
|
"""
|
|
124
137
|
relevant_documents = await self.search_rasa_documentation(context)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
138
|
+
messages = await self._build_messages(context, relevant_documents)
|
|
139
|
+
|
|
140
|
+
support_evidence = CopilotGenerationContext(
|
|
141
|
+
relevant_documents=relevant_documents,
|
|
142
|
+
system_message=messages[0],
|
|
143
|
+
chat_history=messages[1:-1],
|
|
144
|
+
last_user_message=messages[-1],
|
|
145
|
+
)
|
|
128
146
|
|
|
129
147
|
return (
|
|
130
148
|
self._stream_response(messages),
|
|
131
|
-
|
|
132
|
-
system_message.get("content", ""),
|
|
149
|
+
support_evidence,
|
|
133
150
|
)
|
|
134
151
|
|
|
135
152
|
async def _stream_response(
|
|
@@ -174,60 +191,139 @@ class Copilot:
|
|
|
174
191
|
)
|
|
175
192
|
raise
|
|
176
193
|
|
|
177
|
-
async def
|
|
194
|
+
async def _build_messages(
|
|
178
195
|
self,
|
|
179
196
|
context: CopilotContext,
|
|
180
197
|
relevant_documents: List[Document],
|
|
181
|
-
) -> Dict[str, Any]:
|
|
182
|
-
"""
|
|
183
|
-
# Format relevant documentation
|
|
184
|
-
documents = [doc.model_dump() for doc in relevant_documents]
|
|
185
|
-
|
|
186
|
-
# Format conversation history
|
|
187
|
-
conversation = self._format_conversation_history(context.tracker_context)
|
|
198
|
+
) -> List[Dict[str, Any]]:
|
|
199
|
+
"""Build the complete message list for the OpenAI API.
|
|
188
200
|
|
|
189
|
-
|
|
190
|
-
|
|
201
|
+
Args:
|
|
202
|
+
context: The context of the copilot.
|
|
203
|
+
relevant_documents: The relevant documents to use in the context.
|
|
191
204
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
205
|
+
Returns:
|
|
206
|
+
A list of messages in OpenAI format.
|
|
207
|
+
"""
|
|
208
|
+
# Split chat history into past messages and latest message
|
|
209
|
+
past_messages = [
|
|
210
|
+
message
|
|
211
|
+
for message in context.copilot_chat_history[:-1]
|
|
212
|
+
if message.response_category != ResponseCategory.GUARDRAILS_POLICY_VIOLATION
|
|
213
|
+
]
|
|
214
|
+
latest_message = context.copilot_chat_history[-1]
|
|
215
|
+
|
|
216
|
+
# Create the system message
|
|
217
|
+
system_message = await self._create_system_message()
|
|
218
|
+
# Create the chat history messages (excludes the last message)
|
|
219
|
+
chat_history = self._create_chat_history_messages(past_messages)
|
|
220
|
+
# Create the last message and add the context to it
|
|
221
|
+
latest_message_with_context = self._create_last_user_message_with_context(
|
|
222
|
+
latest_message, context, relevant_documents
|
|
199
223
|
)
|
|
224
|
+
return [system_message, *chat_history, latest_message_with_context]
|
|
225
|
+
|
|
226
|
+
async def _create_system_message(self) -> Dict[str, Any]:
|
|
227
|
+
"""Render the correct Jinja template based on desired output_type."""
|
|
228
|
+
rendered_prompt = self._system_message_prompt_template.render()
|
|
200
229
|
return {"role": ROLE_SYSTEM, "content": rendered_prompt}
|
|
201
230
|
|
|
202
231
|
def _create_chat_history_messages(
|
|
203
232
|
self,
|
|
204
|
-
|
|
233
|
+
past_messages: List["CopilotChatMessage"],
|
|
205
234
|
) -> List[Dict[str, Any]]:
|
|
206
235
|
"""Create the chat history messages for the copilot.
|
|
207
236
|
|
|
208
237
|
Filter out messages with response_category of GUARDRAILS_POLICY_VIOLATION.
|
|
209
238
|
This will filter out all the user messages that were flagged by guardrails, but
|
|
210
239
|
also the copilot messages that were produced by guardrails.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
past_messages: List of past messages (excluding the latest message).
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
List of messages in OpenAI format.
|
|
211
246
|
"""
|
|
212
|
-
# Filter out messages with response_category of GUARDRAILS_POLICY_VIOLATION.
|
|
213
|
-
# This will filter out all the user messages flagged by guardrails, but also the
|
|
214
|
-
# copilot messages that were produced.
|
|
215
247
|
return [
|
|
216
248
|
message.to_openai_format()
|
|
217
|
-
for message in
|
|
249
|
+
for message in past_messages
|
|
218
250
|
if message.response_category != ResponseCategory.GUARDRAILS_POLICY_VIOLATION
|
|
219
251
|
]
|
|
220
252
|
|
|
253
|
+
def _create_last_user_message_with_context(
|
|
254
|
+
self,
|
|
255
|
+
latest_message: "CopilotChatMessage",
|
|
256
|
+
context: CopilotContext,
|
|
257
|
+
relevant_documents: List[Document],
|
|
258
|
+
) -> Dict[str, Any]:
|
|
259
|
+
"""Create the last user message with context.
|
|
260
|
+
|
|
261
|
+
The last user message is the last message in the copilot chat history.
|
|
262
|
+
We add the context prompt with the current conversation, state, assistant logs,
|
|
263
|
+
assistant files, and relevant documents as a text content block to the beginning
|
|
264
|
+
of the message.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
context: The context of the copilot.
|
|
268
|
+
relevant_documents: The relevant documents to use in the context.
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
The last user message with context in the OpenAI format.
|
|
272
|
+
"""
|
|
273
|
+
last_user_message = copy.deepcopy(latest_message)
|
|
274
|
+
context_prompt = self._render_last_user_message_context_prompt(
|
|
275
|
+
context, relevant_documents
|
|
276
|
+
)
|
|
277
|
+
last_user_message.content.insert(
|
|
278
|
+
0, TextContent(type="text", text=context_prompt)
|
|
279
|
+
)
|
|
280
|
+
return {
|
|
281
|
+
"role": ROLE_USER,
|
|
282
|
+
"content": [
|
|
283
|
+
{"type": "text", "text": content.text}
|
|
284
|
+
for content in last_user_message.content
|
|
285
|
+
if isinstance(content, TextContent)
|
|
286
|
+
],
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
def _render_last_user_message_context_prompt(
|
|
290
|
+
self,
|
|
291
|
+
context: CopilotContext,
|
|
292
|
+
relevant_documents: List[Document],
|
|
293
|
+
) -> str:
|
|
294
|
+
# Format relevant documentation
|
|
295
|
+
documents = [doc.model_dump() for doc in relevant_documents]
|
|
296
|
+
# Format conversation history
|
|
297
|
+
conversation = self._format_conversation_history(context.tracker_context)
|
|
298
|
+
# Format current state
|
|
299
|
+
current_state = self._format_current_state(context.tracker_context)
|
|
300
|
+
|
|
301
|
+
rendered_prompt = self._last_user_message_context_prompt_template.render(
|
|
302
|
+
current_conversation=conversation,
|
|
303
|
+
current_state=current_state,
|
|
304
|
+
assistant_logs=context.assistant_logs,
|
|
305
|
+
assistant_files=context.assistant_files,
|
|
306
|
+
documentation_results=documents,
|
|
307
|
+
)
|
|
308
|
+
return rendered_prompt
|
|
309
|
+
|
|
221
310
|
@staticmethod
|
|
222
311
|
def _create_documentation_search_query(context: CopilotContext) -> str:
|
|
223
312
|
"""Format chat messages between user and copilot for documentation search."""
|
|
313
|
+
|
|
224
314
|
result = ""
|
|
225
315
|
role_to_prefix = {
|
|
226
316
|
ROLE_USER: "User",
|
|
227
317
|
ROLE_COPILOT: "Assistant",
|
|
228
318
|
ROLE_COPILOT_INTERNAL: "Copilot Internal Request",
|
|
229
319
|
}
|
|
230
|
-
|
|
320
|
+
|
|
321
|
+
# Only use the last N messages for documentation search
|
|
322
|
+
messages_to_include = context.copilot_chat_history[
|
|
323
|
+
-COPILOT_DOCUMENTATION_SEARCH_QUERY_HISTORY_MESSAGES:
|
|
324
|
+
]
|
|
325
|
+
|
|
326
|
+
for message in messages_to_include:
|
|
231
327
|
prefix = role_to_prefix[message.role]
|
|
232
328
|
text = message.get_text_content().strip()
|
|
233
329
|
if text:
|
rasa/builder/copilot/models.py
CHANGED
|
@@ -13,6 +13,7 @@ from rasa.builder.copilot.constants import (
|
|
|
13
13
|
ROLE_COPILOT_INTERNAL,
|
|
14
14
|
ROLE_USER,
|
|
15
15
|
)
|
|
16
|
+
from rasa.builder.document_retrieval.models import Document
|
|
16
17
|
from rasa.builder.models import ServerSentEvent
|
|
17
18
|
from rasa.builder.shared.tracker_context import TrackerContext
|
|
18
19
|
|
|
@@ -464,3 +465,36 @@ class SigningContext(BaseModel):
|
|
|
464
465
|
"""Signing is enabled if a non-empty secret is present."""
|
|
465
466
|
secret = (self.secret or "").strip()
|
|
466
467
|
return bool(secret)
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
class CopilotGenerationContext(BaseModel):
|
|
471
|
+
"""Container for copilot generation context and supporting evidence.
|
|
472
|
+
|
|
473
|
+
This class organizes the context and supporting evidence information used by the
|
|
474
|
+
copilot's generate_response method, providing a cleaner interface than returning
|
|
475
|
+
a tuple for the non-streaming data.
|
|
476
|
+
"""
|
|
477
|
+
|
|
478
|
+
relevant_documents: List["Document"] = Field(
|
|
479
|
+
...,
|
|
480
|
+
description=(
|
|
481
|
+
"The relevant documents used as supporting evidence for the respons."
|
|
482
|
+
),
|
|
483
|
+
)
|
|
484
|
+
system_message: Dict[str, Any] = Field(
|
|
485
|
+
..., description="The system message with instructions."
|
|
486
|
+
)
|
|
487
|
+
chat_history: List[Dict[str, Any]] = Field(
|
|
488
|
+
...,
|
|
489
|
+
description=(
|
|
490
|
+
"The chat history messages (excluding the last message) used as a context."
|
|
491
|
+
),
|
|
492
|
+
)
|
|
493
|
+
last_user_message: Optional[Dict[str, Any]] = Field(
|
|
494
|
+
None, description="The last user message with context that was processed."
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
class Config:
|
|
498
|
+
"""Config for CopilotGenerationContext."""
|
|
499
|
+
|
|
500
|
+
arbitrary_types_allowed = True
|
|
@@ -313,28 +313,29 @@ Ask specific questions like:
|
|
|
313
313
|
- Minimum density: every paragraph that includes Rasa-specific facts must contain at least one citation.
|
|
314
314
|
- Prefer citing each Rasa-specific sentence. Group multiple sources when helpful.
|
|
315
315
|
|
|
316
|
-
2. Source of truth and verification
|
|
317
|
-
-
|
|
318
|
-
-
|
|
316
|
+
2. **Source of truth and verification**
|
|
317
|
+
- **Never cite from previous conversation turns or responses**. Citing from previous turns creates invalid references that will be rejected.
|
|
318
|
+
- Always verify that every citation index you use **exists in the current documentation results** and the URL matches before citing.
|
|
319
319
|
- If multiple docs conflict, prefer the most specific and recent; if unsure, cite both and note the discrepancy in one concise sentence, then ask the user which applies.
|
|
320
320
|
|
|
321
|
-
|
|
321
|
+
3. **Inline-link every citation**
|
|
322
322
|
- Use inline links immediately after the sentence or paragraph they support.
|
|
323
323
|
- **Format**: "[N](URL)" where N is the number index from the documentation context, and URL is the link provided in the documentation context.
|
|
324
324
|
- **Multiple citations format**: If needed, group citations like academic references: "[N](first source URL) [M](second source URL) [P](third source URL)", where N, M, and P are integers from the documentation context.
|
|
325
325
|
- Re-use the same N if the identical URL is cited again.
|
|
326
|
+
- Never assign different numbers to the same URL.
|
|
326
327
|
|
|
327
|
-
|
|
328
|
+
4. **Blend sources with the user's situation**
|
|
328
329
|
- Combine the documentation-based facts with details from the assistant files, code, and current state.
|
|
329
330
|
- Explain unfamiliar Rasa terms when they appear.
|
|
330
331
|
|
|
331
|
-
|
|
332
|
+
5. **Prefer docs over memories**
|
|
332
333
|
- If your prior knowledge conflicts with provided documents, follow the provided documents. If still ambiguous, briefly state the uncertainty and ask one clarifying question.
|
|
333
334
|
|
|
334
|
-
|
|
335
|
+
6. **No reference sections**
|
|
335
336
|
- Never add a bibliography-style list (e.g. "References" or "Citations") at the end.
|
|
336
337
|
|
|
337
|
-
|
|
338
|
+
7. **Incomplete answers == invalid answers**
|
|
338
339
|
- Omitting required inline citations or using the wrong format means the response is incomplete.
|
|
339
340
|
|
|
340
341
|
### Hierarchy of Documentation Usage
|
|
@@ -346,26 +347,33 @@ Ask specific questions like:
|
|
|
346
347
|
| 3 | **Version migration guides** | Only when user asks about Rasa version differences or deprecated features. |
|
|
347
348
|
| 4 (lowest) | **Changelogs** | Only when comparing versions, or tracking newly introduced or removed features. |
|
|
348
349
|
|
|
349
|
-
### Examples
|
|
350
|
-
|
|
350
|
+
### Citation Format Examples
|
|
351
|
+
|
|
352
|
+
**Single inline citation format:**
|
|
351
353
|
"""
|
|
352
|
-
Lorem ipsum dolor sit amet
|
|
353
|
-
imperdiet, nec sagittis purus volutpat [1](https://docs.example.com/lorem/intro).
|
|
354
|
+
Lorem ipsum dolor sit amet [1](https://docs.example.com/lorem/intro).
|
|
354
355
|
"""
|
|
355
356
|
|
|
356
|
-
Multiple inline citations format
|
|
357
|
+
**Multiple inline citations format:**
|
|
357
358
|
"""
|
|
358
|
-
Mauris convallis eleifend sollicitudin.
|
|
359
|
-
orci pretium elit, in facilisis risus urna sed orci [3](https://docs.example.com/lorem/pretium) [5](https://docs.example.com/lorem/convallis).
|
|
359
|
+
Mauris convallis eleifend sollicitudin [3](https://docs.example.com/lorem/pretium) [5](https://docs.example.com/lorem/convallis).
|
|
360
360
|
"""
|
|
361
361
|
|
|
362
|
-
Proper citation frequency
|
|
362
|
+
**Proper citation frequency:**
|
|
363
363
|
"""
|
|
364
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit
|
|
364
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit [1](https://docs.example.com/lorem/intro).
|
|
365
|
+
Ut enim ad minim veniam, quis nostrud exercitation [2](https://docs.example.com/lorem/features).
|
|
366
|
+
|
|
367
|
+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur [3](https://docs.example.com/lorem/configuration).
|
|
368
|
+
Excepteur sint occaecat cupidatat non proident [1](https://docs.example.com/lorem/intro).
|
|
365
369
|
|
|
366
|
-
|
|
370
|
+
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium [2](https://docs.example.com/lorem/features) [4](https://docs.example.com/lorem/advanced).
|
|
371
|
+
"""
|
|
367
372
|
|
|
368
|
-
|
|
373
|
+
**Incorrect usage of the different N for the same URL (DO NOT DO THIS):**
|
|
374
|
+
"""
|
|
375
|
+
Sentence A [1](https://docs.example.com/lorem/intro).
|
|
376
|
+
Sentence B [2](https://docs.example.com/lorem/intro). <- same URL, different N
|
|
369
377
|
"""
|
|
370
378
|
|
|
371
379
|
***
|
|
@@ -704,68 +712,4 @@ the required `if` / `then` pattern. [1](https://rasa.com/docs/reference/primitiv
|
|
|
704
712
|
```
|
|
705
713
|
|
|
706
714
|
To prevent this in the future, always validate your flow YAML files with `rasa data validate` [2](https://rasa.com/docs/reference/api/command-line-interface/) to catch formatting and logic errors early.
|
|
707
|
-
"""
|
|
708
|
-
|
|
709
|
-
---
|
|
710
|
-
|
|
711
|
-
# Context Available to You
|
|
712
|
-
You have access to:
|
|
713
|
-
|
|
714
|
-
{% if current_conversation %}
|
|
715
|
-
## Current Conversation and Conversation State between the user and the assistant
|
|
716
|
-
|
|
717
|
-
**Conversation History:**
|
|
718
|
-
```json
|
|
719
|
-
{{ current_conversation }}
|
|
720
|
-
```
|
|
721
|
-
|
|
722
|
-
**Assistant's State:**
|
|
723
|
-
```json
|
|
724
|
-
{{ current_state }}
|
|
725
|
-
```
|
|
726
|
-
{% endif %}
|
|
727
|
-
|
|
728
|
-
{% if assistant_logs %}
|
|
729
|
-
***
|
|
730
|
-
|
|
731
|
-
## Assistant Logs
|
|
732
|
-
```
|
|
733
|
-
{{ assistant_logs }}
|
|
734
|
-
```
|
|
735
|
-
{% endif %}
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
## Assistant Files (Configuration, Domain, Flows)
|
|
739
|
-
{% if assistant_files %}
|
|
740
|
-
{% for file_name, file_content in assistant_files.items() %}
|
|
741
|
-
**{{ file_name }}:**
|
|
742
|
-
```
|
|
743
|
-
{{ file_content }}
|
|
744
|
-
```
|
|
745
|
-
{% endfor %}
|
|
746
|
-
{% else %}
|
|
747
|
-
Assistant files not available.
|
|
748
|
-
{% endif %}
|
|
749
|
-
|
|
750
|
-
***
|
|
751
|
-
|
|
752
|
-
## Relevant Documentation
|
|
753
|
-
{% if documentation_results %}
|
|
754
|
-
The following documentation sources are available for reference. Use the source index
|
|
755
|
-
numbers (1, 2, 3, etc.) for inline citations:
|
|
756
|
-
```
|
|
757
|
-
{{documentation_results}}
|
|
758
|
-
```
|
|
759
|
-
{% else %}
|
|
760
|
-
No relevant documentation source found.
|
|
761
|
-
{% endif %}
|
|
762
|
-
|
|
763
|
-
---
|
|
764
|
-
|
|
765
|
-
# Remember!
|
|
766
|
-
- Focus on accessibility and efficiency. Give guidance users can act on right away.
|
|
767
|
-
- Keep answers concise, cut any fluff.
|
|
768
|
-
- Never impersonate or role-play as the assistant being built. You are the **Rasa assistant development expert**.
|
|
769
|
-
- Cite documentation inline frequently - every factual statement about Rasa features, concepts, or capabilities MUST be cited.
|
|
770
|
-
- NEVER add a separate list of URLs or sources - only use inline citations.
|
|
771
|
-
- NEVER start your response with a ``` or """ or any other quoting characters.
|
|
715
|
+
"""
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Context Available to You
|
|
2
|
+
Treat everything **below** as **current-turn context** to apply under those rules. You
|
|
3
|
+
have access to:
|
|
4
|
+
|
|
5
|
+
{% if current_conversation %}
|
|
6
|
+
## Current Conversation and Conversation State between the user and the assistant
|
|
7
|
+
|
|
8
|
+
**Conversation History:**
|
|
9
|
+
```json
|
|
10
|
+
{{ current_conversation }}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**Assistant's State:**
|
|
14
|
+
```json
|
|
15
|
+
{{ current_state }}
|
|
16
|
+
```
|
|
17
|
+
{% endif %}
|
|
18
|
+
|
|
19
|
+
{% if assistant_logs %}
|
|
20
|
+
***
|
|
21
|
+
|
|
22
|
+
## Assistant Logs
|
|
23
|
+
```
|
|
24
|
+
{{ assistant_logs }}
|
|
25
|
+
```
|
|
26
|
+
{% endif %}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## Assistant Files (Configuration, Domain, Flows)
|
|
30
|
+
{% if assistant_files %}
|
|
31
|
+
{% for file_name, file_content in assistant_files.items() %}
|
|
32
|
+
**{{ file_name }}:**
|
|
33
|
+
```
|
|
34
|
+
{{ file_content }}
|
|
35
|
+
```
|
|
36
|
+
{% endfor %}
|
|
37
|
+
{% else %}
|
|
38
|
+
Assistant files are not available.
|
|
39
|
+
{% endif %}
|
|
40
|
+
|
|
41
|
+
***
|
|
42
|
+
|
|
43
|
+
## Relevant Documentation
|
|
44
|
+
{% if documentation_results %}
|
|
45
|
+
The following documentation sources are available for reference. Use the source index
|
|
46
|
+
numbers (1, 2, 3, etc.) for inline citations:
|
|
47
|
+
```
|
|
48
|
+
{{documentation_results}}
|
|
49
|
+
```
|
|
50
|
+
{% else %}
|
|
51
|
+
No relevant documentation source found.
|
|
52
|
+
{% endif %}
|
|
53
|
+
|
|
54
|
+
# Remember!
|
|
55
|
+
- Focus on accessibility and efficiency. Give guidance users can act on right away.
|
|
56
|
+
- Keep answers concise, cut any fluff.
|
|
57
|
+
- Never impersonate or role-play as the assistant being built. You are the **Rasa assistant development expert**.
|
|
58
|
+
- Cite documentation inline frequently - every factual statement about Rasa features, concepts, or capabilities MUST be cited.
|
|
59
|
+
- Only cite from current turn documentation - never from previous conversation turns
|
|
60
|
+
- NEVER add a separate list of URLs or sources - only use inline citations.
|
|
61
|
+
- NEVER start your response with a ``` or """ or any other quoting characters.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import datetime as dt
|
|
2
2
|
import os
|
|
3
3
|
import uuid
|
|
4
|
-
from typing import Iterable, Optional, Sequence
|
|
4
|
+
from typing import Any, Iterable, Optional, Sequence
|
|
5
5
|
|
|
6
6
|
import structlog
|
|
7
7
|
|
|
@@ -97,7 +97,9 @@ class CopilotTelemetry:
|
|
|
97
97
|
input_tokens: Optional[int] = None,
|
|
98
98
|
output_tokens: Optional[int] = None,
|
|
99
99
|
total_tokens: Optional[int] = None,
|
|
100
|
-
|
|
100
|
+
system_message: Optional[dict[str, Any]] = None,
|
|
101
|
+
chat_history: Optional[list[dict[str, Any]]] = None,
|
|
102
|
+
last_user_message: Optional[dict[str, Any]] = None,
|
|
101
103
|
) -> None:
|
|
102
104
|
"""Track a copilot message in the conversation.
|
|
103
105
|
|
|
@@ -127,7 +129,9 @@ class CopilotTelemetry:
|
|
|
127
129
|
"input_tokens": input_tokens,
|
|
128
130
|
"output_tokens": output_tokens,
|
|
129
131
|
"total_tokens": total_tokens,
|
|
130
|
-
"
|
|
132
|
+
"system_message": system_message,
|
|
133
|
+
"chat_history": chat_history,
|
|
134
|
+
"last_user_message": last_user_message,
|
|
131
135
|
"timestamp": dt.datetime.utcnow().isoformat(),
|
|
132
136
|
},
|
|
133
137
|
)
|
|
@@ -171,7 +175,9 @@ class CopilotTelemetry:
|
|
|
171
175
|
prompt_tokens: int,
|
|
172
176
|
completion_tokens: int,
|
|
173
177
|
total_tokens: int,
|
|
174
|
-
|
|
178
|
+
system_message: dict[str, Any],
|
|
179
|
+
chat_history: list[dict[str, Any]],
|
|
180
|
+
last_user_message: dict[str, Any],
|
|
175
181
|
) -> None:
|
|
176
182
|
"""Log a copilot message from the response handler.
|
|
177
183
|
|
|
@@ -183,7 +189,9 @@ class CopilotTelemetry:
|
|
|
183
189
|
prompt_tokens: Number of input tokens used.
|
|
184
190
|
completion_tokens: Number of output tokens generated.
|
|
185
191
|
total_tokens: Total number of tokens used (input + output).
|
|
186
|
-
|
|
192
|
+
system_message: The system message used.
|
|
193
|
+
chat_history: The chat history messages used.
|
|
194
|
+
last_user_message: The last user message used.
|
|
187
195
|
"""
|
|
188
196
|
structlogger.debug("builder.telemetry.log_copilot_from_handler")
|
|
189
197
|
text = self._full_text(handler)
|
|
@@ -196,5 +204,7 @@ class CopilotTelemetry:
|
|
|
196
204
|
input_tokens=prompt_tokens,
|
|
197
205
|
output_tokens=completion_tokens,
|
|
198
206
|
total_tokens=total_tokens,
|
|
199
|
-
|
|
207
|
+
system_message=system_message,
|
|
208
|
+
chat_history=chat_history,
|
|
209
|
+
last_user_message=last_user_message,
|
|
200
210
|
)
|
|
@@ -10,9 +10,9 @@ class Document(BaseModel):
|
|
|
10
10
|
"""Model for document retrieval results."""
|
|
11
11
|
|
|
12
12
|
content: str = Field(...)
|
|
13
|
-
url: Optional[str] = Field(None)
|
|
14
|
-
title: Optional[str] = Field(None)
|
|
15
|
-
metadata: Optional[Dict[str, Any]] = Field(None)
|
|
13
|
+
url: Optional[str] = Field(default=None)
|
|
14
|
+
title: Optional[str] = Field(default=None)
|
|
15
|
+
metadata: Optional[Dict[str, Any]] = Field(default=None)
|
|
16
16
|
|
|
17
17
|
@classmethod
|
|
18
18
|
def from_inkeep_rag_response(cls, rag_item: Dict[str, Any]) -> "Document":
|
rasa/builder/main.py
CHANGED
|
@@ -22,9 +22,11 @@ from rasa.builder.logging_utils import (
|
|
|
22
22
|
log_request_start,
|
|
23
23
|
)
|
|
24
24
|
from rasa.builder.service import bp, setup_project_generator
|
|
25
|
+
from rasa.builder.template_cache import (
|
|
26
|
+
background_download_template_caches,
|
|
27
|
+
)
|
|
25
28
|
from rasa.builder.training_service import try_load_existing_agent, update_agent
|
|
26
29
|
from rasa.core.channels.studio_chat import StudioChatInput
|
|
27
|
-
from rasa.model_manager.warm_rasa_process import warmup
|
|
28
30
|
from rasa.server import configure_cors
|
|
29
31
|
from rasa.utils.common import configure_logging_and_warnings
|
|
30
32
|
from rasa.utils.log_utils import configure_structlog
|
|
@@ -148,6 +150,16 @@ def create_app(project_folder: str) -> Sanic:
|
|
|
148
150
|
except Exception as e:
|
|
149
151
|
structlogger.warning("Failed to load agent on server startup", error=str(e))
|
|
150
152
|
|
|
153
|
+
if config.HELLO_RASA_PROJECT_ID and app.ctx.project_generator.is_empty():
|
|
154
|
+
app.register_listener(background_download_template_caches, "after_server_start")
|
|
155
|
+
else:
|
|
156
|
+
structlogger.debug(
|
|
157
|
+
"builder.main.background_cache_download.disabled",
|
|
158
|
+
event_info=(
|
|
159
|
+
"No hello rasa project id set; skipping background cache download"
|
|
160
|
+
),
|
|
161
|
+
)
|
|
162
|
+
|
|
151
163
|
return app
|
|
152
164
|
|
|
153
165
|
|
|
@@ -188,12 +200,9 @@ def main(project_folder: Optional[str] = None) -> None:
|
|
|
188
200
|
rasa.telemetry.initialize_telemetry()
|
|
189
201
|
rasa.telemetry.initialize_error_reporting(private_mode=False)
|
|
190
202
|
|
|
203
|
+
# TODO: don't do this when running locally
|
|
191
204
|
_apply_llm_overrides_from_builder_env()
|
|
192
205
|
|
|
193
|
-
if config.HELLO_RASA_PROJECT_ID:
|
|
194
|
-
# ensures long import times for modules are ahead of time
|
|
195
|
-
warmup()
|
|
196
|
-
|
|
197
206
|
# working directory needs to be the project folder, e.g.
|
|
198
207
|
# for relative paths (./docs) in a projects config to work
|
|
199
208
|
if not project_folder:
|
|
@@ -60,7 +60,7 @@ class ProjectGenerator:
|
|
|
60
60
|
create_initial_project(self.project_folder.as_posix(), template)
|
|
61
61
|
# If a local cache for this template exists, copy it into the project.
|
|
62
62
|
# We no longer download here to avoid blocking project creation.
|
|
63
|
-
|
|
63
|
+
copy_cache_for_template_if_available(template, self.project_folder)
|
|
64
64
|
# needs to happen after caching, as we download/copy .rasa and that would
|
|
65
65
|
# overwrite the project info file in .rasa
|
|
66
66
|
ensure_first_used(self.project_folder)
|
|
@@ -339,8 +339,6 @@ class ProjectGenerator:
|
|
|
339
339
|
for filename in os.listdir(self.project_folder):
|
|
340
340
|
file_path = os.path.join(self.project_folder, filename)
|
|
341
341
|
try:
|
|
342
|
-
if filename == "lost+found":
|
|
343
|
-
continue
|
|
344
342
|
if os.path.isfile(file_path) or os.path.islink(file_path):
|
|
345
343
|
os.unlink(file_path)
|
|
346
344
|
elif os.path.isdir(file_path):
|