rasa-pro 3.9.18__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 (662) hide show
  1. README.md +415 -0
  2. rasa/__init__.py +10 -0
  3. rasa/__main__.py +156 -0
  4. rasa/anonymization/__init__.py +2 -0
  5. rasa/anonymization/anonymisation_rule_yaml_reader.py +91 -0
  6. rasa/anonymization/anonymization_pipeline.py +286 -0
  7. rasa/anonymization/anonymization_rule_executor.py +260 -0
  8. rasa/anonymization/anonymization_rule_orchestrator.py +120 -0
  9. rasa/anonymization/schemas/config.yml +47 -0
  10. rasa/anonymization/utils.py +118 -0
  11. rasa/api.py +146 -0
  12. rasa/cli/__init__.py +5 -0
  13. rasa/cli/arguments/__init__.py +0 -0
  14. rasa/cli/arguments/data.py +81 -0
  15. rasa/cli/arguments/default_arguments.py +165 -0
  16. rasa/cli/arguments/evaluate.py +65 -0
  17. rasa/cli/arguments/export.py +51 -0
  18. rasa/cli/arguments/interactive.py +74 -0
  19. rasa/cli/arguments/run.py +204 -0
  20. rasa/cli/arguments/shell.py +13 -0
  21. rasa/cli/arguments/test.py +211 -0
  22. rasa/cli/arguments/train.py +263 -0
  23. rasa/cli/arguments/visualize.py +34 -0
  24. rasa/cli/arguments/x.py +30 -0
  25. rasa/cli/data.py +292 -0
  26. rasa/cli/e2e_test.py +586 -0
  27. rasa/cli/evaluate.py +222 -0
  28. rasa/cli/export.py +250 -0
  29. rasa/cli/inspect.py +63 -0
  30. rasa/cli/interactive.py +164 -0
  31. rasa/cli/license.py +65 -0
  32. rasa/cli/markers.py +78 -0
  33. rasa/cli/project_templates/__init__.py +0 -0
  34. rasa/cli/project_templates/calm/actions/__init__.py +0 -0
  35. rasa/cli/project_templates/calm/actions/action_template.py +27 -0
  36. rasa/cli/project_templates/calm/actions/add_contact.py +30 -0
  37. rasa/cli/project_templates/calm/actions/db.py +57 -0
  38. rasa/cli/project_templates/calm/actions/list_contacts.py +22 -0
  39. rasa/cli/project_templates/calm/actions/remove_contact.py +35 -0
  40. rasa/cli/project_templates/calm/config.yml +12 -0
  41. rasa/cli/project_templates/calm/credentials.yml +33 -0
  42. rasa/cli/project_templates/calm/data/flows/add_contact.yml +31 -0
  43. rasa/cli/project_templates/calm/data/flows/list_contacts.yml +14 -0
  44. rasa/cli/project_templates/calm/data/flows/remove_contact.yml +29 -0
  45. rasa/cli/project_templates/calm/db/contacts.json +10 -0
  46. rasa/cli/project_templates/calm/domain/add_contact.yml +39 -0
  47. rasa/cli/project_templates/calm/domain/list_contacts.yml +17 -0
  48. rasa/cli/project_templates/calm/domain/remove_contact.yml +38 -0
  49. rasa/cli/project_templates/calm/domain/shared.yml +10 -0
  50. rasa/cli/project_templates/calm/e2e_tests/cancelations/user_cancels_during_a_correction.yml +16 -0
  51. rasa/cli/project_templates/calm/e2e_tests/cancelations/user_changes_mind_on_a_whim.yml +7 -0
  52. rasa/cli/project_templates/calm/e2e_tests/corrections/user_corrects_contact_handle.yml +20 -0
  53. rasa/cli/project_templates/calm/e2e_tests/corrections/user_corrects_contact_name.yml +19 -0
  54. rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_adds_contact_to_their_list.yml +15 -0
  55. rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_lists_contacts.yml +5 -0
  56. rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_removes_contact.yml +11 -0
  57. rasa/cli/project_templates/calm/e2e_tests/happy_paths/user_removes_contact_from_list.yml +12 -0
  58. rasa/cli/project_templates/calm/endpoints.yml +45 -0
  59. rasa/cli/project_templates/default/actions/__init__.py +0 -0
  60. rasa/cli/project_templates/default/actions/actions.py +27 -0
  61. rasa/cli/project_templates/default/config.yml +44 -0
  62. rasa/cli/project_templates/default/credentials.yml +33 -0
  63. rasa/cli/project_templates/default/data/nlu.yml +91 -0
  64. rasa/cli/project_templates/default/data/rules.yml +13 -0
  65. rasa/cli/project_templates/default/data/stories.yml +30 -0
  66. rasa/cli/project_templates/default/domain.yml +34 -0
  67. rasa/cli/project_templates/default/endpoints.yml +42 -0
  68. rasa/cli/project_templates/default/tests/test_stories.yml +91 -0
  69. rasa/cli/project_templates/tutorial/actions.py +22 -0
  70. rasa/cli/project_templates/tutorial/config.yml +11 -0
  71. rasa/cli/project_templates/tutorial/credentials.yml +33 -0
  72. rasa/cli/project_templates/tutorial/data/flows.yml +8 -0
  73. rasa/cli/project_templates/tutorial/data/patterns.yml +6 -0
  74. rasa/cli/project_templates/tutorial/domain.yml +21 -0
  75. rasa/cli/project_templates/tutorial/endpoints.yml +45 -0
  76. rasa/cli/run.py +135 -0
  77. rasa/cli/scaffold.py +269 -0
  78. rasa/cli/shell.py +141 -0
  79. rasa/cli/studio/__init__.py +0 -0
  80. rasa/cli/studio/download.py +62 -0
  81. rasa/cli/studio/studio.py +266 -0
  82. rasa/cli/studio/train.py +59 -0
  83. rasa/cli/studio/upload.py +77 -0
  84. rasa/cli/telemetry.py +102 -0
  85. rasa/cli/test.py +280 -0
  86. rasa/cli/train.py +260 -0
  87. rasa/cli/utils.py +464 -0
  88. rasa/cli/visualize.py +40 -0
  89. rasa/cli/x.py +206 -0
  90. rasa/constants.py +37 -0
  91. rasa/core/__init__.py +17 -0
  92. rasa/core/actions/__init__.py +0 -0
  93. rasa/core/actions/action.py +1225 -0
  94. rasa/core/actions/action_clean_stack.py +59 -0
  95. rasa/core/actions/action_exceptions.py +24 -0
  96. rasa/core/actions/action_run_slot_rejections.py +207 -0
  97. rasa/core/actions/action_trigger_chitchat.py +31 -0
  98. rasa/core/actions/action_trigger_flow.py +109 -0
  99. rasa/core/actions/action_trigger_search.py +31 -0
  100. rasa/core/actions/constants.py +5 -0
  101. rasa/core/actions/custom_action_executor.py +188 -0
  102. rasa/core/actions/forms.py +741 -0
  103. rasa/core/actions/grpc_custom_action_executor.py +251 -0
  104. rasa/core/actions/http_custom_action_executor.py +140 -0
  105. rasa/core/actions/loops.py +114 -0
  106. rasa/core/actions/two_stage_fallback.py +186 -0
  107. rasa/core/agent.py +555 -0
  108. rasa/core/auth_retry_tracker_store.py +122 -0
  109. rasa/core/brokers/__init__.py +0 -0
  110. rasa/core/brokers/broker.py +126 -0
  111. rasa/core/brokers/file.py +58 -0
  112. rasa/core/brokers/kafka.py +322 -0
  113. rasa/core/brokers/pika.py +386 -0
  114. rasa/core/brokers/sql.py +86 -0
  115. rasa/core/channels/__init__.py +55 -0
  116. rasa/core/channels/audiocodes.py +463 -0
  117. rasa/core/channels/botframework.py +338 -0
  118. rasa/core/channels/callback.py +84 -0
  119. rasa/core/channels/channel.py +419 -0
  120. rasa/core/channels/console.py +241 -0
  121. rasa/core/channels/development_inspector.py +93 -0
  122. rasa/core/channels/facebook.py +419 -0
  123. rasa/core/channels/hangouts.py +329 -0
  124. rasa/core/channels/inspector/.eslintrc.cjs +25 -0
  125. rasa/core/channels/inspector/.gitignore +23 -0
  126. rasa/core/channels/inspector/README.md +54 -0
  127. rasa/core/channels/inspector/assets/favicon.ico +0 -0
  128. rasa/core/channels/inspector/assets/rasa-chat.js +2 -0
  129. rasa/core/channels/inspector/custom.d.ts +3 -0
  130. rasa/core/channels/inspector/dist/assets/arc-b6e548fe.js +1 -0
  131. rasa/core/channels/inspector/dist/assets/array-9f3ba611.js +1 -0
  132. rasa/core/channels/inspector/dist/assets/c4Diagram-d0fbc5ce-fa03ac9e.js +10 -0
  133. rasa/core/channels/inspector/dist/assets/classDiagram-936ed81e-ee67392a.js +2 -0
  134. rasa/core/channels/inspector/dist/assets/classDiagram-v2-c3cb15f1-9b283fae.js +2 -0
  135. rasa/core/channels/inspector/dist/assets/createText-62fc7601-8b6fcc2a.js +7 -0
  136. rasa/core/channels/inspector/dist/assets/edges-f2ad444c-22e77f4f.js +4 -0
  137. rasa/core/channels/inspector/dist/assets/erDiagram-9d236eb7-60ffc87f.js +51 -0
  138. rasa/core/channels/inspector/dist/assets/flowDb-1972c806-9dd802e4.js +6 -0
  139. rasa/core/channels/inspector/dist/assets/flowDiagram-7ea5b25a-5fa1912f.js +4 -0
  140. rasa/core/channels/inspector/dist/assets/flowDiagram-v2-855bc5b3-1844e5a5.js +1 -0
  141. rasa/core/channels/inspector/dist/assets/flowchart-elk-definition-abe16c3d-622a1fd2.js +139 -0
  142. rasa/core/channels/inspector/dist/assets/ganttDiagram-9b5ea136-e285a63a.js +266 -0
  143. rasa/core/channels/inspector/dist/assets/gitGraphDiagram-99d0ae7c-f237bdca.js +70 -0
  144. rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-128cfa44.ttf +0 -0
  145. rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-21dbcb97.woff +0 -0
  146. rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-222b5e26.svg +329 -0
  147. rasa/core/channels/inspector/dist/assets/ibm-plex-mono-v4-latin-regular-9ad89b2a.woff2 +0 -0
  148. rasa/core/channels/inspector/dist/assets/index-2c4b9a3b-4b03d70e.js +1 -0
  149. rasa/core/channels/inspector/dist/assets/index-3ee28881.css +1 -0
  150. rasa/core/channels/inspector/dist/assets/index-a5d3e69d.js +1040 -0
  151. rasa/core/channels/inspector/dist/assets/infoDiagram-736b4530-72a0fa5f.js +7 -0
  152. rasa/core/channels/inspector/dist/assets/init-77b53fdd.js +1 -0
  153. rasa/core/channels/inspector/dist/assets/journeyDiagram-df861f2b-82218c41.js +139 -0
  154. rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-60c05ee4.woff +0 -0
  155. rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-8335d9b8.svg +438 -0
  156. rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-9cc39c75.ttf +0 -0
  157. rasa/core/channels/inspector/dist/assets/lato-v14-latin-700-ead13ccf.woff2 +0 -0
  158. rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-16705655.woff2 +0 -0
  159. rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-5aeb07f9.woff +0 -0
  160. rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-9c459044.ttf +0 -0
  161. rasa/core/channels/inspector/dist/assets/lato-v14-latin-regular-9e2898a4.svg +435 -0
  162. rasa/core/channels/inspector/dist/assets/layout-78cff630.js +1 -0
  163. rasa/core/channels/inspector/dist/assets/line-5038b469.js +1 -0
  164. rasa/core/channels/inspector/dist/assets/linear-c4fc4098.js +1 -0
  165. rasa/core/channels/inspector/dist/assets/mindmap-definition-beec6740-c33c8ea6.js +109 -0
  166. rasa/core/channels/inspector/dist/assets/ordinal-ba9b4969.js +1 -0
  167. rasa/core/channels/inspector/dist/assets/path-53f90ab3.js +1 -0
  168. rasa/core/channels/inspector/dist/assets/pieDiagram-dbbf0591-a8d03059.js +35 -0
  169. rasa/core/channels/inspector/dist/assets/quadrantDiagram-4d7f4fd6-6a0e56b2.js +7 -0
  170. rasa/core/channels/inspector/dist/assets/requirementDiagram-6fc4c22a-2dc7c7bd.js +52 -0
  171. rasa/core/channels/inspector/dist/assets/sankeyDiagram-8f13d901-2360fe39.js +8 -0
  172. rasa/core/channels/inspector/dist/assets/sequenceDiagram-b655622a-41b9f9ad.js +122 -0
  173. rasa/core/channels/inspector/dist/assets/stateDiagram-59f0c015-0aad326f.js +1 -0
  174. rasa/core/channels/inspector/dist/assets/stateDiagram-v2-2b26beab-9847d984.js +1 -0
  175. rasa/core/channels/inspector/dist/assets/styles-080da4f6-564d890e.js +110 -0
  176. rasa/core/channels/inspector/dist/assets/styles-3dcbcfbf-38957613.js +159 -0
  177. rasa/core/channels/inspector/dist/assets/styles-9c745c82-f0fc6921.js +207 -0
  178. rasa/core/channels/inspector/dist/assets/svgDrawCommon-4835440b-ef3c5a77.js +1 -0
  179. rasa/core/channels/inspector/dist/assets/timeline-definition-5b62e21b-bf3e91c1.js +61 -0
  180. rasa/core/channels/inspector/dist/assets/xychartDiagram-2b33534f-4d4026c0.js +7 -0
  181. rasa/core/channels/inspector/dist/index.html +41 -0
  182. rasa/core/channels/inspector/index.html +39 -0
  183. rasa/core/channels/inspector/jest.config.ts +13 -0
  184. rasa/core/channels/inspector/package.json +48 -0
  185. rasa/core/channels/inspector/setupTests.ts +2 -0
  186. rasa/core/channels/inspector/src/App.tsx +170 -0
  187. rasa/core/channels/inspector/src/components/DiagramFlow.tsx +107 -0
  188. rasa/core/channels/inspector/src/components/DialogueInformation.tsx +187 -0
  189. rasa/core/channels/inspector/src/components/DialogueStack.tsx +151 -0
  190. rasa/core/channels/inspector/src/components/ExpandIcon.tsx +16 -0
  191. rasa/core/channels/inspector/src/components/FullscreenButton.tsx +45 -0
  192. rasa/core/channels/inspector/src/components/LoadingSpinner.tsx +19 -0
  193. rasa/core/channels/inspector/src/components/NoActiveFlow.tsx +21 -0
  194. rasa/core/channels/inspector/src/components/RasaLogo.tsx +32 -0
  195. rasa/core/channels/inspector/src/components/SaraDiagrams.tsx +39 -0
  196. rasa/core/channels/inspector/src/components/Slots.tsx +91 -0
  197. rasa/core/channels/inspector/src/components/Welcome.tsx +54 -0
  198. rasa/core/channels/inspector/src/helpers/formatters.test.ts +382 -0
  199. rasa/core/channels/inspector/src/helpers/formatters.ts +240 -0
  200. rasa/core/channels/inspector/src/helpers/utils.ts +42 -0
  201. rasa/core/channels/inspector/src/main.tsx +13 -0
  202. rasa/core/channels/inspector/src/theme/Button/Button.ts +29 -0
  203. rasa/core/channels/inspector/src/theme/Heading/Heading.ts +31 -0
  204. rasa/core/channels/inspector/src/theme/Input/Input.ts +27 -0
  205. rasa/core/channels/inspector/src/theme/Link/Link.ts +10 -0
  206. rasa/core/channels/inspector/src/theme/Modal/Modal.ts +47 -0
  207. rasa/core/channels/inspector/src/theme/Table/Table.tsx +38 -0
  208. rasa/core/channels/inspector/src/theme/Tooltip/Tooltip.ts +12 -0
  209. rasa/core/channels/inspector/src/theme/base/breakpoints.ts +8 -0
  210. rasa/core/channels/inspector/src/theme/base/colors.ts +88 -0
  211. rasa/core/channels/inspector/src/theme/base/fonts/fontFaces.css +29 -0
  212. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.eot +0 -0
  213. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.svg +329 -0
  214. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.ttf +0 -0
  215. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.woff +0 -0
  216. rasa/core/channels/inspector/src/theme/base/fonts/ibm-plex-mono-v4-latin/ibm-plex-mono-v4-latin-regular.woff2 +0 -0
  217. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.eot +0 -0
  218. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.svg +438 -0
  219. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.ttf +0 -0
  220. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.woff +0 -0
  221. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-700.woff2 +0 -0
  222. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.eot +0 -0
  223. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.svg +435 -0
  224. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.ttf +0 -0
  225. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.woff +0 -0
  226. rasa/core/channels/inspector/src/theme/base/fonts/lato-v14-latin/lato-v14-latin-regular.woff2 +0 -0
  227. rasa/core/channels/inspector/src/theme/base/radii.ts +9 -0
  228. rasa/core/channels/inspector/src/theme/base/shadows.ts +7 -0
  229. rasa/core/channels/inspector/src/theme/base/sizes.ts +7 -0
  230. rasa/core/channels/inspector/src/theme/base/space.ts +15 -0
  231. rasa/core/channels/inspector/src/theme/base/styles.ts +13 -0
  232. rasa/core/channels/inspector/src/theme/base/typography.ts +24 -0
  233. rasa/core/channels/inspector/src/theme/base/zIndices.ts +19 -0
  234. rasa/core/channels/inspector/src/theme/index.ts +101 -0
  235. rasa/core/channels/inspector/src/types.ts +64 -0
  236. rasa/core/channels/inspector/src/vite-env.d.ts +1 -0
  237. rasa/core/channels/inspector/tests/__mocks__/fileMock.ts +1 -0
  238. rasa/core/channels/inspector/tests/__mocks__/matchMedia.ts +16 -0
  239. rasa/core/channels/inspector/tests/__mocks__/styleMock.ts +1 -0
  240. rasa/core/channels/inspector/tests/renderWithProviders.tsx +14 -0
  241. rasa/core/channels/inspector/tsconfig.json +26 -0
  242. rasa/core/channels/inspector/tsconfig.node.json +10 -0
  243. rasa/core/channels/inspector/vite.config.ts +8 -0
  244. rasa/core/channels/inspector/yarn.lock +6156 -0
  245. rasa/core/channels/mattermost.py +229 -0
  246. rasa/core/channels/rasa_chat.py +126 -0
  247. rasa/core/channels/rest.py +225 -0
  248. rasa/core/channels/rocketchat.py +174 -0
  249. rasa/core/channels/slack.py +620 -0
  250. rasa/core/channels/socketio.py +274 -0
  251. rasa/core/channels/telegram.py +298 -0
  252. rasa/core/channels/twilio.py +169 -0
  253. rasa/core/channels/twilio_voice.py +367 -0
  254. rasa/core/channels/vier_cvg.py +374 -0
  255. rasa/core/channels/webexteams.py +134 -0
  256. rasa/core/concurrent_lock_store.py +210 -0
  257. rasa/core/constants.py +107 -0
  258. rasa/core/evaluation/__init__.py +0 -0
  259. rasa/core/evaluation/marker.py +267 -0
  260. rasa/core/evaluation/marker_base.py +923 -0
  261. rasa/core/evaluation/marker_stats.py +293 -0
  262. rasa/core/evaluation/marker_tracker_loader.py +103 -0
  263. rasa/core/exceptions.py +29 -0
  264. rasa/core/exporter.py +284 -0
  265. rasa/core/featurizers/__init__.py +0 -0
  266. rasa/core/featurizers/precomputation.py +410 -0
  267. rasa/core/featurizers/single_state_featurizer.py +421 -0
  268. rasa/core/featurizers/tracker_featurizers.py +1262 -0
  269. rasa/core/http_interpreter.py +89 -0
  270. rasa/core/information_retrieval/__init__.py +7 -0
  271. rasa/core/information_retrieval/faiss.py +121 -0
  272. rasa/core/information_retrieval/information_retrieval.py +129 -0
  273. rasa/core/information_retrieval/milvus.py +52 -0
  274. rasa/core/information_retrieval/qdrant.py +95 -0
  275. rasa/core/jobs.py +63 -0
  276. rasa/core/lock.py +139 -0
  277. rasa/core/lock_store.py +343 -0
  278. rasa/core/migrate.py +403 -0
  279. rasa/core/nlg/__init__.py +3 -0
  280. rasa/core/nlg/callback.py +146 -0
  281. rasa/core/nlg/contextual_response_rephraser.py +270 -0
  282. rasa/core/nlg/generator.py +230 -0
  283. rasa/core/nlg/interpolator.py +143 -0
  284. rasa/core/nlg/response.py +155 -0
  285. rasa/core/nlg/summarize.py +69 -0
  286. rasa/core/policies/__init__.py +0 -0
  287. rasa/core/policies/ensemble.py +329 -0
  288. rasa/core/policies/enterprise_search_policy.py +781 -0
  289. rasa/core/policies/enterprise_search_prompt_template.jinja2 +25 -0
  290. rasa/core/policies/enterprise_search_prompt_with_citation_template.jinja2 +60 -0
  291. rasa/core/policies/flow_policy.py +205 -0
  292. rasa/core/policies/flows/__init__.py +0 -0
  293. rasa/core/policies/flows/flow_exceptions.py +44 -0
  294. rasa/core/policies/flows/flow_executor.py +705 -0
  295. rasa/core/policies/flows/flow_step_result.py +43 -0
  296. rasa/core/policies/intentless_policy.py +922 -0
  297. rasa/core/policies/intentless_prompt_template.jinja2 +22 -0
  298. rasa/core/policies/memoization.py +538 -0
  299. rasa/core/policies/policy.py +725 -0
  300. rasa/core/policies/rule_policy.py +1273 -0
  301. rasa/core/policies/ted_policy.py +2169 -0
  302. rasa/core/policies/unexpected_intent_policy.py +1022 -0
  303. rasa/core/processor.py +1422 -0
  304. rasa/core/run.py +331 -0
  305. rasa/core/secrets_manager/__init__.py +0 -0
  306. rasa/core/secrets_manager/constants.py +32 -0
  307. rasa/core/secrets_manager/endpoints.py +391 -0
  308. rasa/core/secrets_manager/factory.py +233 -0
  309. rasa/core/secrets_manager/secret_manager.py +262 -0
  310. rasa/core/secrets_manager/vault.py +574 -0
  311. rasa/core/test.py +1335 -0
  312. rasa/core/tracker_store.py +1699 -0
  313. rasa/core/train.py +105 -0
  314. rasa/core/training/__init__.py +89 -0
  315. rasa/core/training/converters/__init__.py +0 -0
  316. rasa/core/training/converters/responses_prefix_converter.py +119 -0
  317. rasa/core/training/interactive.py +1745 -0
  318. rasa/core/training/story_conflict.py +381 -0
  319. rasa/core/training/training.py +93 -0
  320. rasa/core/utils.py +339 -0
  321. rasa/core/visualize.py +70 -0
  322. rasa/dialogue_understanding/__init__.py +0 -0
  323. rasa/dialogue_understanding/coexistence/__init__.py +0 -0
  324. rasa/dialogue_understanding/coexistence/constants.py +4 -0
  325. rasa/dialogue_understanding/coexistence/intent_based_router.py +196 -0
  326. rasa/dialogue_understanding/coexistence/llm_based_router.py +260 -0
  327. rasa/dialogue_understanding/coexistence/router_template.jinja2 +12 -0
  328. rasa/dialogue_understanding/commands/__init__.py +49 -0
  329. rasa/dialogue_understanding/commands/can_not_handle_command.py +70 -0
  330. rasa/dialogue_understanding/commands/cancel_flow_command.py +125 -0
  331. rasa/dialogue_understanding/commands/change_flow_command.py +44 -0
  332. rasa/dialogue_understanding/commands/chit_chat_answer_command.py +57 -0
  333. rasa/dialogue_understanding/commands/clarify_command.py +86 -0
  334. rasa/dialogue_understanding/commands/command.py +85 -0
  335. rasa/dialogue_understanding/commands/correct_slots_command.py +297 -0
  336. rasa/dialogue_understanding/commands/error_command.py +79 -0
  337. rasa/dialogue_understanding/commands/free_form_answer_command.py +9 -0
  338. rasa/dialogue_understanding/commands/handle_code_change_command.py +73 -0
  339. rasa/dialogue_understanding/commands/human_handoff_command.py +66 -0
  340. rasa/dialogue_understanding/commands/knowledge_answer_command.py +57 -0
  341. rasa/dialogue_understanding/commands/noop_command.py +54 -0
  342. rasa/dialogue_understanding/commands/set_slot_command.py +160 -0
  343. rasa/dialogue_understanding/commands/skip_question_command.py +75 -0
  344. rasa/dialogue_understanding/commands/start_flow_command.py +107 -0
  345. rasa/dialogue_understanding/generator/__init__.py +21 -0
  346. rasa/dialogue_understanding/generator/command_generator.py +343 -0
  347. rasa/dialogue_understanding/generator/constants.py +18 -0
  348. rasa/dialogue_understanding/generator/flow_document_template.jinja2 +4 -0
  349. rasa/dialogue_understanding/generator/flow_retrieval.py +412 -0
  350. rasa/dialogue_understanding/generator/llm_based_command_generator.py +467 -0
  351. rasa/dialogue_understanding/generator/llm_command_generator.py +67 -0
  352. rasa/dialogue_understanding/generator/multi_step/__init__.py +0 -0
  353. rasa/dialogue_understanding/generator/multi_step/fill_slots_prompt.jinja2 +62 -0
  354. rasa/dialogue_understanding/generator/multi_step/handle_flows_prompt.jinja2 +38 -0
  355. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +827 -0
  356. rasa/dialogue_understanding/generator/nlu_command_adapter.py +218 -0
  357. rasa/dialogue_understanding/generator/single_step/__init__.py +0 -0
  358. rasa/dialogue_understanding/generator/single_step/command_prompt_template.jinja2 +57 -0
  359. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +345 -0
  360. rasa/dialogue_understanding/patterns/__init__.py +0 -0
  361. rasa/dialogue_understanding/patterns/cancel.py +111 -0
  362. rasa/dialogue_understanding/patterns/cannot_handle.py +43 -0
  363. rasa/dialogue_understanding/patterns/chitchat.py +37 -0
  364. rasa/dialogue_understanding/patterns/clarify.py +97 -0
  365. rasa/dialogue_understanding/patterns/code_change.py +41 -0
  366. rasa/dialogue_understanding/patterns/collect_information.py +90 -0
  367. rasa/dialogue_understanding/patterns/completed.py +40 -0
  368. rasa/dialogue_understanding/patterns/continue_interrupted.py +42 -0
  369. rasa/dialogue_understanding/patterns/correction.py +278 -0
  370. rasa/dialogue_understanding/patterns/default_flows_for_patterns.yml +248 -0
  371. rasa/dialogue_understanding/patterns/human_handoff.py +37 -0
  372. rasa/dialogue_understanding/patterns/internal_error.py +47 -0
  373. rasa/dialogue_understanding/patterns/search.py +37 -0
  374. rasa/dialogue_understanding/patterns/skip_question.py +38 -0
  375. rasa/dialogue_understanding/processor/__init__.py +0 -0
  376. rasa/dialogue_understanding/processor/command_processor.py +687 -0
  377. rasa/dialogue_understanding/processor/command_processor_component.py +39 -0
  378. rasa/dialogue_understanding/stack/__init__.py +0 -0
  379. rasa/dialogue_understanding/stack/dialogue_stack.py +178 -0
  380. rasa/dialogue_understanding/stack/frames/__init__.py +19 -0
  381. rasa/dialogue_understanding/stack/frames/chit_chat_frame.py +27 -0
  382. rasa/dialogue_understanding/stack/frames/dialogue_stack_frame.py +137 -0
  383. rasa/dialogue_understanding/stack/frames/flow_stack_frame.py +157 -0
  384. rasa/dialogue_understanding/stack/frames/pattern_frame.py +10 -0
  385. rasa/dialogue_understanding/stack/frames/search_frame.py +27 -0
  386. rasa/dialogue_understanding/stack/utils.py +211 -0
  387. rasa/e2e_test/__init__.py +0 -0
  388. rasa/e2e_test/constants.py +11 -0
  389. rasa/e2e_test/e2e_test_case.py +366 -0
  390. rasa/e2e_test/e2e_test_result.py +34 -0
  391. rasa/e2e_test/e2e_test_runner.py +768 -0
  392. rasa/e2e_test/e2e_test_schema.yml +85 -0
  393. rasa/engine/__init__.py +0 -0
  394. rasa/engine/caching.py +463 -0
  395. rasa/engine/constants.py +17 -0
  396. rasa/engine/exceptions.py +14 -0
  397. rasa/engine/graph.py +637 -0
  398. rasa/engine/loader.py +36 -0
  399. rasa/engine/recipes/__init__.py +0 -0
  400. rasa/engine/recipes/config_files/default_config.yml +44 -0
  401. rasa/engine/recipes/default_components.py +99 -0
  402. rasa/engine/recipes/default_recipe.py +1251 -0
  403. rasa/engine/recipes/graph_recipe.py +79 -0
  404. rasa/engine/recipes/recipe.py +93 -0
  405. rasa/engine/runner/__init__.py +0 -0
  406. rasa/engine/runner/dask.py +250 -0
  407. rasa/engine/runner/interface.py +49 -0
  408. rasa/engine/storage/__init__.py +0 -0
  409. rasa/engine/storage/local_model_storage.py +246 -0
  410. rasa/engine/storage/resource.py +110 -0
  411. rasa/engine/storage/storage.py +203 -0
  412. rasa/engine/training/__init__.py +0 -0
  413. rasa/engine/training/components.py +176 -0
  414. rasa/engine/training/fingerprinting.py +64 -0
  415. rasa/engine/training/graph_trainer.py +256 -0
  416. rasa/engine/training/hooks.py +164 -0
  417. rasa/engine/validation.py +873 -0
  418. rasa/env.py +5 -0
  419. rasa/exceptions.py +69 -0
  420. rasa/graph_components/__init__.py +0 -0
  421. rasa/graph_components/converters/__init__.py +0 -0
  422. rasa/graph_components/converters/nlu_message_converter.py +48 -0
  423. rasa/graph_components/providers/__init__.py +0 -0
  424. rasa/graph_components/providers/domain_for_core_training_provider.py +87 -0
  425. rasa/graph_components/providers/domain_provider.py +71 -0
  426. rasa/graph_components/providers/flows_provider.py +74 -0
  427. rasa/graph_components/providers/forms_provider.py +44 -0
  428. rasa/graph_components/providers/nlu_training_data_provider.py +56 -0
  429. rasa/graph_components/providers/responses_provider.py +44 -0
  430. rasa/graph_components/providers/rule_only_provider.py +49 -0
  431. rasa/graph_components/providers/story_graph_provider.py +43 -0
  432. rasa/graph_components/providers/training_tracker_provider.py +55 -0
  433. rasa/graph_components/validators/__init__.py +0 -0
  434. rasa/graph_components/validators/default_recipe_validator.py +550 -0
  435. rasa/graph_components/validators/finetuning_validator.py +302 -0
  436. rasa/hooks.py +112 -0
  437. rasa/jupyter.py +63 -0
  438. rasa/markers/__init__.py +0 -0
  439. rasa/markers/marker.py +269 -0
  440. rasa/markers/marker_base.py +828 -0
  441. rasa/markers/upload.py +74 -0
  442. rasa/markers/validate.py +21 -0
  443. rasa/model.py +118 -0
  444. rasa/model_testing.py +457 -0
  445. rasa/model_training.py +536 -0
  446. rasa/nlu/__init__.py +7 -0
  447. rasa/nlu/classifiers/__init__.py +3 -0
  448. rasa/nlu/classifiers/classifier.py +5 -0
  449. rasa/nlu/classifiers/diet_classifier.py +1881 -0
  450. rasa/nlu/classifiers/fallback_classifier.py +192 -0
  451. rasa/nlu/classifiers/keyword_intent_classifier.py +188 -0
  452. rasa/nlu/classifiers/llm_intent_classifier.py +519 -0
  453. rasa/nlu/classifiers/logistic_regression_classifier.py +253 -0
  454. rasa/nlu/classifiers/mitie_intent_classifier.py +156 -0
  455. rasa/nlu/classifiers/regex_message_handler.py +56 -0
  456. rasa/nlu/classifiers/sklearn_intent_classifier.py +330 -0
  457. rasa/nlu/constants.py +77 -0
  458. rasa/nlu/convert.py +40 -0
  459. rasa/nlu/emulators/__init__.py +0 -0
  460. rasa/nlu/emulators/dialogflow.py +55 -0
  461. rasa/nlu/emulators/emulator.py +49 -0
  462. rasa/nlu/emulators/luis.py +86 -0
  463. rasa/nlu/emulators/no_emulator.py +10 -0
  464. rasa/nlu/emulators/wit.py +56 -0
  465. rasa/nlu/extractors/__init__.py +0 -0
  466. rasa/nlu/extractors/crf_entity_extractor.py +715 -0
  467. rasa/nlu/extractors/duckling_entity_extractor.py +206 -0
  468. rasa/nlu/extractors/entity_synonyms.py +178 -0
  469. rasa/nlu/extractors/extractor.py +470 -0
  470. rasa/nlu/extractors/mitie_entity_extractor.py +293 -0
  471. rasa/nlu/extractors/regex_entity_extractor.py +220 -0
  472. rasa/nlu/extractors/spacy_entity_extractor.py +95 -0
  473. rasa/nlu/featurizers/__init__.py +0 -0
  474. rasa/nlu/featurizers/dense_featurizer/__init__.py +0 -0
  475. rasa/nlu/featurizers/dense_featurizer/convert_featurizer.py +445 -0
  476. rasa/nlu/featurizers/dense_featurizer/dense_featurizer.py +57 -0
  477. rasa/nlu/featurizers/dense_featurizer/lm_featurizer.py +768 -0
  478. rasa/nlu/featurizers/dense_featurizer/mitie_featurizer.py +170 -0
  479. rasa/nlu/featurizers/dense_featurizer/spacy_featurizer.py +132 -0
  480. rasa/nlu/featurizers/featurizer.py +89 -0
  481. rasa/nlu/featurizers/sparse_featurizer/__init__.py +0 -0
  482. rasa/nlu/featurizers/sparse_featurizer/count_vectors_featurizer.py +867 -0
  483. rasa/nlu/featurizers/sparse_featurizer/lexical_syntactic_featurizer.py +571 -0
  484. rasa/nlu/featurizers/sparse_featurizer/regex_featurizer.py +271 -0
  485. rasa/nlu/featurizers/sparse_featurizer/sparse_featurizer.py +9 -0
  486. rasa/nlu/model.py +24 -0
  487. rasa/nlu/persistor.py +282 -0
  488. rasa/nlu/run.py +27 -0
  489. rasa/nlu/selectors/__init__.py +0 -0
  490. rasa/nlu/selectors/response_selector.py +987 -0
  491. rasa/nlu/test.py +1940 -0
  492. rasa/nlu/tokenizers/__init__.py +0 -0
  493. rasa/nlu/tokenizers/jieba_tokenizer.py +148 -0
  494. rasa/nlu/tokenizers/mitie_tokenizer.py +75 -0
  495. rasa/nlu/tokenizers/spacy_tokenizer.py +72 -0
  496. rasa/nlu/tokenizers/tokenizer.py +239 -0
  497. rasa/nlu/tokenizers/whitespace_tokenizer.py +106 -0
  498. rasa/nlu/utils/__init__.py +35 -0
  499. rasa/nlu/utils/bilou_utils.py +462 -0
  500. rasa/nlu/utils/hugging_face/__init__.py +0 -0
  501. rasa/nlu/utils/hugging_face/registry.py +108 -0
  502. rasa/nlu/utils/hugging_face/transformers_pre_post_processors.py +311 -0
  503. rasa/nlu/utils/mitie_utils.py +113 -0
  504. rasa/nlu/utils/pattern_utils.py +168 -0
  505. rasa/nlu/utils/spacy_utils.py +310 -0
  506. rasa/plugin.py +90 -0
  507. rasa/server.py +1551 -0
  508. rasa/shared/__init__.py +0 -0
  509. rasa/shared/constants.py +192 -0
  510. rasa/shared/core/__init__.py +0 -0
  511. rasa/shared/core/command_payload_reader.py +109 -0
  512. rasa/shared/core/constants.py +167 -0
  513. rasa/shared/core/conversation.py +46 -0
  514. rasa/shared/core/domain.py +2107 -0
  515. rasa/shared/core/events.py +2504 -0
  516. rasa/shared/core/flows/__init__.py +7 -0
  517. rasa/shared/core/flows/flow.py +362 -0
  518. rasa/shared/core/flows/flow_step.py +146 -0
  519. rasa/shared/core/flows/flow_step_links.py +319 -0
  520. rasa/shared/core/flows/flow_step_sequence.py +70 -0
  521. rasa/shared/core/flows/flows_list.py +223 -0
  522. rasa/shared/core/flows/flows_yaml_schema.json +217 -0
  523. rasa/shared/core/flows/nlu_trigger.py +117 -0
  524. rasa/shared/core/flows/steps/__init__.py +24 -0
  525. rasa/shared/core/flows/steps/action.py +56 -0
  526. rasa/shared/core/flows/steps/call.py +64 -0
  527. rasa/shared/core/flows/steps/collect.py +112 -0
  528. rasa/shared/core/flows/steps/constants.py +5 -0
  529. rasa/shared/core/flows/steps/continuation.py +36 -0
  530. rasa/shared/core/flows/steps/end.py +22 -0
  531. rasa/shared/core/flows/steps/internal.py +44 -0
  532. rasa/shared/core/flows/steps/link.py +51 -0
  533. rasa/shared/core/flows/steps/no_operation.py +48 -0
  534. rasa/shared/core/flows/steps/set_slots.py +50 -0
  535. rasa/shared/core/flows/steps/start.py +30 -0
  536. rasa/shared/core/flows/validation.py +527 -0
  537. rasa/shared/core/flows/yaml_flows_io.py +278 -0
  538. rasa/shared/core/generator.py +908 -0
  539. rasa/shared/core/slot_mappings.py +526 -0
  540. rasa/shared/core/slots.py +649 -0
  541. rasa/shared/core/trackers.py +1177 -0
  542. rasa/shared/core/training_data/__init__.py +0 -0
  543. rasa/shared/core/training_data/loading.py +89 -0
  544. rasa/shared/core/training_data/story_reader/__init__.py +0 -0
  545. rasa/shared/core/training_data/story_reader/story_reader.py +129 -0
  546. rasa/shared/core/training_data/story_reader/story_step_builder.py +168 -0
  547. rasa/shared/core/training_data/story_reader/yaml_story_reader.py +888 -0
  548. rasa/shared/core/training_data/story_writer/__init__.py +0 -0
  549. rasa/shared/core/training_data/story_writer/story_writer.py +76 -0
  550. rasa/shared/core/training_data/story_writer/yaml_story_writer.py +444 -0
  551. rasa/shared/core/training_data/structures.py +838 -0
  552. rasa/shared/core/training_data/visualization.html +146 -0
  553. rasa/shared/core/training_data/visualization.py +603 -0
  554. rasa/shared/data.py +249 -0
  555. rasa/shared/engine/__init__.py +0 -0
  556. rasa/shared/engine/caching.py +26 -0
  557. rasa/shared/exceptions.py +163 -0
  558. rasa/shared/importers/__init__.py +0 -0
  559. rasa/shared/importers/importer.py +704 -0
  560. rasa/shared/importers/multi_project.py +203 -0
  561. rasa/shared/importers/rasa.py +99 -0
  562. rasa/shared/importers/utils.py +34 -0
  563. rasa/shared/nlu/__init__.py +0 -0
  564. rasa/shared/nlu/constants.py +47 -0
  565. rasa/shared/nlu/interpreter.py +10 -0
  566. rasa/shared/nlu/training_data/__init__.py +0 -0
  567. rasa/shared/nlu/training_data/entities_parser.py +208 -0
  568. rasa/shared/nlu/training_data/features.py +492 -0
  569. rasa/shared/nlu/training_data/formats/__init__.py +10 -0
  570. rasa/shared/nlu/training_data/formats/dialogflow.py +163 -0
  571. rasa/shared/nlu/training_data/formats/luis.py +87 -0
  572. rasa/shared/nlu/training_data/formats/rasa.py +135 -0
  573. rasa/shared/nlu/training_data/formats/rasa_yaml.py +603 -0
  574. rasa/shared/nlu/training_data/formats/readerwriter.py +244 -0
  575. rasa/shared/nlu/training_data/formats/wit.py +52 -0
  576. rasa/shared/nlu/training_data/loading.py +137 -0
  577. rasa/shared/nlu/training_data/lookup_tables_parser.py +30 -0
  578. rasa/shared/nlu/training_data/message.py +490 -0
  579. rasa/shared/nlu/training_data/schemas/__init__.py +0 -0
  580. rasa/shared/nlu/training_data/schemas/data_schema.py +85 -0
  581. rasa/shared/nlu/training_data/schemas/nlu.yml +53 -0
  582. rasa/shared/nlu/training_data/schemas/responses.yml +70 -0
  583. rasa/shared/nlu/training_data/synonyms_parser.py +42 -0
  584. rasa/shared/nlu/training_data/training_data.py +730 -0
  585. rasa/shared/nlu/training_data/util.py +223 -0
  586. rasa/shared/providers/__init__.py +0 -0
  587. rasa/shared/providers/openai/__init__.py +0 -0
  588. rasa/shared/providers/openai/clients.py +43 -0
  589. rasa/shared/providers/openai/session_handler.py +110 -0
  590. rasa/shared/utils/__init__.py +0 -0
  591. rasa/shared/utils/cli.py +72 -0
  592. rasa/shared/utils/common.py +308 -0
  593. rasa/shared/utils/constants.py +4 -0
  594. rasa/shared/utils/io.py +415 -0
  595. rasa/shared/utils/llm.py +404 -0
  596. rasa/shared/utils/pykwalify_extensions.py +27 -0
  597. rasa/shared/utils/schemas/__init__.py +0 -0
  598. rasa/shared/utils/schemas/config.yml +2 -0
  599. rasa/shared/utils/schemas/domain.yml +145 -0
  600. rasa/shared/utils/schemas/events.py +212 -0
  601. rasa/shared/utils/schemas/model_config.yml +46 -0
  602. rasa/shared/utils/schemas/stories.yml +173 -0
  603. rasa/shared/utils/yaml.py +786 -0
  604. rasa/studio/__init__.py +0 -0
  605. rasa/studio/auth.py +268 -0
  606. rasa/studio/config.py +127 -0
  607. rasa/studio/constants.py +18 -0
  608. rasa/studio/data_handler.py +359 -0
  609. rasa/studio/download.py +483 -0
  610. rasa/studio/results_logger.py +137 -0
  611. rasa/studio/train.py +135 -0
  612. rasa/studio/upload.py +433 -0
  613. rasa/telemetry.py +1737 -0
  614. rasa/tracing/__init__.py +0 -0
  615. rasa/tracing/config.py +353 -0
  616. rasa/tracing/constants.py +62 -0
  617. rasa/tracing/instrumentation/__init__.py +0 -0
  618. rasa/tracing/instrumentation/attribute_extractors.py +672 -0
  619. rasa/tracing/instrumentation/instrumentation.py +1185 -0
  620. rasa/tracing/instrumentation/intentless_policy_instrumentation.py +144 -0
  621. rasa/tracing/instrumentation/metrics.py +294 -0
  622. rasa/tracing/metric_instrument_provider.py +205 -0
  623. rasa/utils/__init__.py +0 -0
  624. rasa/utils/beta.py +83 -0
  625. rasa/utils/cli.py +28 -0
  626. rasa/utils/common.py +635 -0
  627. rasa/utils/converter.py +53 -0
  628. rasa/utils/endpoints.py +302 -0
  629. rasa/utils/io.py +260 -0
  630. rasa/utils/licensing.py +534 -0
  631. rasa/utils/log_utils.py +174 -0
  632. rasa/utils/mapper.py +210 -0
  633. rasa/utils/ml_utils.py +145 -0
  634. rasa/utils/plotting.py +362 -0
  635. rasa/utils/singleton.py +23 -0
  636. rasa/utils/tensorflow/__init__.py +0 -0
  637. rasa/utils/tensorflow/callback.py +112 -0
  638. rasa/utils/tensorflow/constants.py +116 -0
  639. rasa/utils/tensorflow/crf.py +492 -0
  640. rasa/utils/tensorflow/data_generator.py +440 -0
  641. rasa/utils/tensorflow/environment.py +161 -0
  642. rasa/utils/tensorflow/exceptions.py +5 -0
  643. rasa/utils/tensorflow/feature_array.py +366 -0
  644. rasa/utils/tensorflow/layers.py +1565 -0
  645. rasa/utils/tensorflow/layers_utils.py +113 -0
  646. rasa/utils/tensorflow/metrics.py +281 -0
  647. rasa/utils/tensorflow/model_data.py +798 -0
  648. rasa/utils/tensorflow/model_data_utils.py +499 -0
  649. rasa/utils/tensorflow/models.py +935 -0
  650. rasa/utils/tensorflow/rasa_layers.py +1094 -0
  651. rasa/utils/tensorflow/transformer.py +640 -0
  652. rasa/utils/tensorflow/types.py +6 -0
  653. rasa/utils/train_utils.py +572 -0
  654. rasa/utils/url_tools.py +53 -0
  655. rasa/utils/yaml.py +54 -0
  656. rasa/validator.py +1337 -0
  657. rasa/version.py +3 -0
  658. rasa_pro-3.9.18.dist-info/METADATA +563 -0
  659. rasa_pro-3.9.18.dist-info/NOTICE +5 -0
  660. rasa_pro-3.9.18.dist-info/RECORD +662 -0
  661. rasa_pro-3.9.18.dist-info/WHEEL +4 -0
  662. rasa_pro-3.9.18.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,1185 @@
1
+ import contextlib
2
+ import functools
3
+ import importlib
4
+ import inspect
5
+ import json
6
+ import logging
7
+ import time
8
+ from typing import (
9
+ Any,
10
+ AsyncIterator,
11
+ Awaitable,
12
+ Callable,
13
+ Dict,
14
+ List,
15
+ Optional,
16
+ Text,
17
+ Type,
18
+ TypeVar,
19
+ )
20
+
21
+ from multidict import MultiDict
22
+ from opentelemetry.context import Context
23
+ from opentelemetry.sdk.trace import TracerProvider
24
+ from opentelemetry.trace import SpanKind, Tracer
25
+ from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
26
+
27
+ from rasa.core.actions.action import Action, RemoteAction, CustomActionExecutor
28
+ from rasa.core.actions.custom_action_executor import RetryCustomActionExecutor
29
+ from rasa.core.actions.grpc_custom_action_executor import GRPCCustomActionExecutor
30
+ from rasa.core.agent import Agent
31
+ from rasa.core.channels import OutputChannel
32
+ from rasa.core.information_retrieval.information_retrieval import (
33
+ InformationRetrieval,
34
+ SearchResultList,
35
+ )
36
+ from rasa.core.lock_store import LockStore
37
+ from rasa.core.nlg import NaturalLanguageGenerator
38
+ from rasa.core.policies.flows.flow_step_result import FlowActionPrediction
39
+ from rasa.core.policies.policy import Policy, PolicyPrediction
40
+ from rasa.core.processor import MessageProcessor
41
+ from rasa.core.tracker_store import TrackerStore
42
+ from rasa.dialogue_understanding.commands import Command
43
+ from rasa.dialogue_understanding.generator import (
44
+ LLMCommandGenerator,
45
+ MultiStepLLMCommandGenerator,
46
+ SingleStepLLMCommandGenerator,
47
+ )
48
+ from rasa.dialogue_understanding.generator.nlu_command_adapter import NLUCommandAdapter
49
+ from rasa.engine.graph import GraphNode
50
+ from rasa.engine.training.graph_trainer import GraphTrainer
51
+ from rasa.shared.core.domain import Domain
52
+ from rasa.shared.core.flows import FlowsList
53
+ from rasa.shared.core.trackers import DialogueStateTracker
54
+ from rasa.shared.nlu.constants import SET_SLOT_COMMAND
55
+ from rasa.shared.nlu.training_data.message import Message
56
+ from rasa.tracing.constants import REQUEST_BODY_SIZE_IN_BYTES_ATTRIBUTE_NAME
57
+ from rasa.tracing.instrumentation import attribute_extractors
58
+ from rasa.tracing.instrumentation.intentless_policy_instrumentation import (
59
+ _instrument_extract_ai_responses,
60
+ _instrument_generate_answer,
61
+ _instrument_select_few_shot_conversations,
62
+ _instrument_select_response_examples,
63
+ )
64
+ from rasa.tracing.instrumentation.metrics import (
65
+ record_llm_command_generator_metrics,
66
+ record_single_step_llm_command_generator_metrics,
67
+ record_multi_step_llm_command_generator_metrics,
68
+ record_callable_duration_metrics,
69
+ record_request_size_in_bytes,
70
+ )
71
+ from rasa.utils.endpoints import concat_url, EndpointConfig
72
+
73
+ # The `TypeVar` representing the return type for a function to be wrapped.
74
+ S = TypeVar("S")
75
+ # The `TypeVar` representing the type of the argument passed to the function to be
76
+ # wrapped.
77
+ T = TypeVar("T")
78
+
79
+ logger = logging.getLogger(__name__)
80
+ INSTRUMENTED_BOOLEAN_ATTRIBUTE_NAME = "class_has_been_instrumented"
81
+ INSTRUMENTED_MODULE_BOOLEAN_ATTRIBUTE_NAME = "module_has_been_instrumented"
82
+ COMMAND_PROCESSOR_MODULE_NAME = (
83
+ "rasa.dialogue_understanding.processor.command_processor"
84
+ )
85
+ FLOW_EXECUTOR_MODULE_NAME = "rasa.core.policies.flows.flow_executor"
86
+
87
+
88
+ def _check_extractor_argument_list(
89
+ fn: Callable[[T, Any, Any], S],
90
+ attr_extractor: Optional[Callable[[T, Any, Any], Dict[str, Any]]],
91
+ ) -> bool:
92
+ if attr_extractor is None:
93
+ return False
94
+
95
+ fn_args = inspect.signature(fn)
96
+ attr_args = inspect.signature(attr_extractor)
97
+
98
+ are_arglists_congruent = fn_args.parameters.keys() == attr_args.parameters.keys()
99
+
100
+ if not are_arglists_congruent:
101
+ logger.warning(
102
+ f"Argument lists for {fn.__name__} and {attr_extractor.__name__}"
103
+ f" do not match up. {fn.__name__} will be traced without attributes."
104
+ )
105
+
106
+ return are_arglists_congruent
107
+
108
+
109
+ def extract_tracing_context_from_headers(
110
+ headers: Dict[str, Any],
111
+ ) -> Optional[Context]:
112
+ """Extracts the tracing context from the headers."""
113
+ tracing_carrier = MultiDict(
114
+ [
115
+ (key, value)
116
+ for key, value in headers.items()
117
+ if key.lower() not in ("content-length", "content-encoding")
118
+ ]
119
+ )
120
+ context = (
121
+ TraceContextTextMapPropagator().extract(headers) if tracing_carrier else None
122
+ )
123
+
124
+ return context
125
+
126
+
127
+ def traceable(
128
+ fn: Callable[[T, Any, Any], S],
129
+ tracer: Tracer,
130
+ attr_extractor: Optional[Callable[[T, Any, Any], Dict[str, Any]]],
131
+ metrics_recorder: Optional[Callable],
132
+ ) -> Callable[[T, Any, Any], S]:
133
+ """Wrap a non-`async` function by tracing functionality.
134
+
135
+ :param fn: The function to be wrapped.
136
+ :param tracer: The `Tracer` that shall be used for tracing this function.
137
+ :param attr_extractor: A function that is applied to the function's instance and
138
+ the function's arguments.
139
+ :param metrics_recorder: A function that records metric measurements.
140
+ :return: The wrapped function.
141
+ """
142
+ should_extract_args = _check_extractor_argument_list(fn, attr_extractor)
143
+
144
+ @functools.wraps(fn)
145
+ def wrapper(self: T, *args: Any, **kwargs: Any) -> S:
146
+ attrs = (
147
+ attr_extractor(self, *args, **kwargs)
148
+ if attr_extractor and should_extract_args
149
+ else {}
150
+ )
151
+
152
+ module_name = attrs.pop("module_name", "")
153
+ if module_name in ["command_processor", FLOW_EXECUTOR_MODULE_NAME]:
154
+ span_name = f"{module_name}.{fn.__name__}"
155
+ else:
156
+ span_name = f"{self.__class__.__name__}.{fn.__name__}"
157
+ with tracer.start_as_current_span(span_name, attributes=attrs):
158
+ start_time = time.perf_counter_ns()
159
+
160
+ result = fn(self, *args, **kwargs)
161
+
162
+ end_time = time.perf_counter_ns()
163
+ record_callable_duration_metrics(self, start_time, end_time)
164
+
165
+ if metrics_recorder:
166
+ metrics_recorder(attrs)
167
+
168
+ return result
169
+
170
+ return wrapper
171
+
172
+
173
+ def traceable_async(
174
+ fn: Callable[[T, Any, Any], Awaitable[S]],
175
+ tracer: Tracer,
176
+ attr_extractor: Optional[Callable[[T, Any, Any], Dict[str, Any]]],
177
+ header_extractor: Optional[Callable[[T, Any, Any], Dict[str, Any]]],
178
+ metrics_recorder: Optional[Callable],
179
+ ) -> Callable[[T, Any, Any], Awaitable[S]]:
180
+ """Wrap an `async` function by tracing functionality.
181
+
182
+ :param fn: The function to be wrapped.
183
+ :param tracer: The `Tracer` that shall be used for tracing this function.
184
+ :param attr_extractor: A function that is applied to the function's instance and
185
+ the function's arguments.
186
+ :param header_extractor: A function that is applied to the function's arguments
187
+ :param metrics_recorder: A function that records metric measurements.
188
+ :return: The wrapped function.
189
+ """
190
+ should_extract_args = _check_extractor_argument_list(fn, attr_extractor)
191
+
192
+ @functools.wraps(fn)
193
+ async def async_wrapper(self: T, *args: Any, **kwargs: Any) -> S:
194
+ attrs = (
195
+ attr_extractor(self, *args, **kwargs)
196
+ if attr_extractor and should_extract_args
197
+ else {}
198
+ )
199
+ headers = header_extractor(*args, **kwargs) if header_extractor else {}
200
+ context = extract_tracing_context_from_headers(headers)
201
+
202
+ if issubclass(self.__class__, GraphNode) and fn.__name__ == "__call__":
203
+ span_name = f"{self.__class__.__name__}." + attrs.get(
204
+ "component_class", "GraphNode"
205
+ )
206
+ else:
207
+ span_name = f"{self.__class__.__name__}.{fn.__name__}"
208
+
209
+ with tracer.start_as_current_span(
210
+ span_name,
211
+ attributes=attrs,
212
+ context=context,
213
+ ) as span:
214
+ TraceContextTextMapPropagator().inject(headers)
215
+
216
+ ctx = span.get_span_context()
217
+ logger.debug(
218
+ f"The trace id for the current span '{span_name}' is '{ctx.trace_id}'."
219
+ )
220
+
221
+ start_time = time.perf_counter_ns()
222
+
223
+ result = await fn(self, *args, **kwargs)
224
+
225
+ end_time = time.perf_counter_ns()
226
+ record_callable_duration_metrics(self, start_time, end_time, **attrs)
227
+
228
+ if metrics_recorder:
229
+ metrics_recorder(attrs)
230
+
231
+ return result
232
+
233
+ return async_wrapper
234
+
235
+
236
+ def traceable_async_generator(
237
+ fn: Callable[[T, Any, Any], AsyncIterator[S]],
238
+ tracer: Tracer,
239
+ attr_extractor: Optional[Callable[[T, Any, Any], Dict[str, Any]]],
240
+ ) -> Callable[[T, Any, Any], AsyncIterator[AsyncIterator[S]]]:
241
+ """Wrap an `async` function that `yield`s by tracing functionality.
242
+
243
+ :param fn: The function to be wrapped.
244
+ :param tracer: The `Tracer` that shall be used for tracing this function.
245
+ :param attr_extractor: A function that is applied to the function's instance and
246
+ the function's arguments.
247
+ :return: The wrapped function.
248
+ """
249
+ should_extract_args = _check_extractor_argument_list(fn, attr_extractor)
250
+
251
+ @functools.wraps(fn)
252
+ async def async_wrapper(
253
+ self: T, *args: Any, **kwargs: Any
254
+ ) -> AsyncIterator[AsyncIterator[S]]:
255
+ attrs = (
256
+ attr_extractor(self, *args, **kwargs)
257
+ if attr_extractor and should_extract_args
258
+ else {}
259
+ )
260
+ with tracer.start_as_current_span(
261
+ f"{self.__class__.__name__}.{fn.__name__}", attributes=attrs
262
+ ):
263
+ yield fn(self, *args, **kwargs)
264
+
265
+ return async_wrapper
266
+
267
+
268
+ # This `TypeVar` restricts the agent_class to be instrumented to subclasses of `Agent`.
269
+ AgentType = TypeVar("AgentType", bound=Agent)
270
+ # This `TypeVar` restricts the processor_class to be instrumented to subclasses of
271
+ # `MessageProcessor`.
272
+ ProcessorType = TypeVar("ProcessorType", bound=MessageProcessor)
273
+ TrackerStoreType = TypeVar("TrackerStoreType", bound=TrackerStore)
274
+ GraphNodeType = TypeVar("GraphNodeType", bound=GraphNode)
275
+ # This `TypeVar` restricts the lock_store_class to be instrumented to subclasses of
276
+ # `LockStore`.
277
+ LockStoreType = TypeVar("LockStoreType", bound=LockStore)
278
+ GraphTrainerType = TypeVar("GraphTrainerType", bound=GraphTrainer)
279
+ LLMCommandGeneratorType = TypeVar("LLMCommandGeneratorType", bound=LLMCommandGenerator)
280
+ SingleStepLLMCommandGeneratorType = TypeVar(
281
+ "SingleStepLLMCommandGeneratorType", bound=SingleStepLLMCommandGenerator
282
+ )
283
+ MultiStepLLMCommandGeneratorType = TypeVar(
284
+ "MultiStepLLMCommandGeneratorType", bound=MultiStepLLMCommandGenerator
285
+ )
286
+ CommandType = TypeVar("CommandType", bound=Command)
287
+ PolicyType = TypeVar("PolicyType", bound=Policy)
288
+ InformationRetrievalType = TypeVar(
289
+ "InformationRetrievalType", bound=InformationRetrieval
290
+ )
291
+ NLUCommandAdapterType = TypeVar("NLUCommandAdapterType", bound=NLUCommandAdapter)
292
+ EndpointConfigType = TypeVar("EndpointConfigType", bound=EndpointConfig)
293
+
294
+
295
+ def instrument(
296
+ tracer_provider: TracerProvider,
297
+ agent_class: Optional[Type[AgentType]] = None,
298
+ processor_class: Optional[Type[ProcessorType]] = None,
299
+ tracker_store_class: Optional[Type[TrackerStoreType]] = None,
300
+ graph_node_class: Optional[Type[GraphNodeType]] = None,
301
+ lock_store_class: Optional[Type[LockStoreType]] = None,
302
+ graph_trainer_class: Optional[Type[GraphTrainerType]] = None,
303
+ llm_command_generator_class: Optional[Type[LLMCommandGeneratorType]] = None,
304
+ command_subclasses: Optional[List[Type[CommandType]]] = None,
305
+ contextual_response_rephraser_class: Optional[Any] = None,
306
+ policy_subclasses: Optional[List[Type[PolicyType]]] = None,
307
+ vector_store_subclasses: Optional[List[Type[InformationRetrievalType]]] = None,
308
+ nlu_command_adapter_class: Optional[Type[NLUCommandAdapterType]] = None,
309
+ endpoint_config_class: Optional[Type[EndpointConfigType]] = None,
310
+ grpc_custom_action_executor_class: Optional[Type[GRPCCustomActionExecutor]] = None,
311
+ single_step_llm_command_generator_class: Optional[
312
+ Type[SingleStepLLMCommandGeneratorType]
313
+ ] = None,
314
+ multi_step_llm_command_generator_class: Optional[
315
+ Type[MultiStepLLMCommandGeneratorType]
316
+ ] = None,
317
+ custom_action_executor_subclasses: Optional[
318
+ List[Type[CustomActionExecutor]]
319
+ ] = None,
320
+ ) -> None:
321
+ """Substitute methods to be traced by their traced counterparts.
322
+
323
+ Because of type bounds on `AgentType` and `ProcessorType`,
324
+ we ensure that only subtypes of `Agent`
325
+ and `MessageProcessor` can be instrumented, respectively.
326
+
327
+ :param tracer_provider: The `TracerProvider` to be used for configuring tracing
328
+ on the substituted methods.
329
+ :param agent_class: The `Agent` to be instrumented. If `None` is given, no `Agent`
330
+ will be instrumented.
331
+ :param processor_class: The `MessageProcessor` to be instrumented. If `None` is
332
+ given, no `MessageProcessor` will be instrumented.
333
+ :param tracker_store_class: The `TrackerStore` to be instrumented. If `None` is
334
+ given, no `TrackerStore` will be instrumented.
335
+ :param graph_node_class: The `GraphNode` to be instrumented. If `None` is
336
+ given, no `GraphNode` will be instrumented.
337
+ :param lock_store_class: The `LockStore` to be instrumented. If `None` is
338
+ given, no `LockStore` will be instrumented.
339
+ :param graph_trainer_class: The `GraphTrainer` to be instrumented. If `None` is
340
+ given, no `GraphTrainer` will be instrumented.
341
+ :param llm_command_generator_class: The `LLMCommandGenerator` to be instrumented.
342
+ If `None` is given, no `LLMCommandGenerator` will be instrumented.
343
+ :param command_subclasses: The subclasses of `Command` to be instrumented. If `None`
344
+ is given, no subclass of `Command` will be instrumented.
345
+ :param contextual_response_rephraser_class: The `ContextualResponseRephraser` to
346
+ be instrumented. If `None` is given, no `ContextualResponseRephraser` will be
347
+ instrumented.
348
+ :param policy_subclasses: The subclasses of `Policy` to be instrumented. If `None`
349
+ is given, no subclass of `Policy` will be instrumented.
350
+ :param vector_store_subclasses: The subclasses of `InformationRetrieval` to be
351
+ instrumented. If `None` is given, no subclass of `InformationRetrieval` will be
352
+ instrumented.
353
+ :param nlu_command_adapter_class: The `NLUCommandAdapter` to be instrumented. If
354
+ `None` is given, no `NLUCommandAdapter` will be instrumented.
355
+ :param endpoint_config_class: The `EndpointConfig` to be instrumented. If
356
+ `None` is given, no `EndpointConfig` will be instrumented.
357
+ :param grpc_custom_action_executor_class: The `GRPCCustomActionExecution` to be
358
+ instrumented. If `None` is given, no `GRPCCustomActionExecution`
359
+ will be instrumented.
360
+ :param single_step_llm_command_generator_class: The `SingleStepLLMCommandGenerator`
361
+ to be instrumented. If `None` is given, no `SingleStepLLMCommandGenerator` will
362
+ be instrumented.
363
+ :param multi_step_llm_command_generator_class: The `MultiStepLLMCommandGenerator`
364
+ to be instrumented. If `None` is given, no `MultiStepLLMCommandGenerator` will
365
+ be instrumented.
366
+ :param custom_action_executor_subclasses: The subclasses of `CustomActionExecutor`
367
+ to be instrumented. If `None` is given, no subclass of `CustomActionExecutor`
368
+ will be instrumented.
369
+ """
370
+ if agent_class is not None and not class_is_instrumented(agent_class):
371
+ _instrument_method(
372
+ tracer_provider.get_tracer(agent_class.__module__),
373
+ agent_class,
374
+ "handle_message",
375
+ attribute_extractors.extract_attrs_for_agent,
376
+ attribute_extractors.extract_headers,
377
+ )
378
+ mark_class_as_instrumented(agent_class)
379
+
380
+ if processor_class is not None and not class_is_instrumented(processor_class):
381
+ _instrument_processor(tracer_provider, processor_class)
382
+ mark_class_as_instrumented(processor_class)
383
+
384
+ if tracker_store_class is not None and not class_is_instrumented(
385
+ tracker_store_class
386
+ ):
387
+ _instrument_method(
388
+ tracer_provider.get_tracer(tracker_store_class.__module__),
389
+ tracker_store_class,
390
+ "_stream_new_events",
391
+ attribute_extractors.extract_attrs_for_tracker_store,
392
+ )
393
+ mark_class_as_instrumented(tracker_store_class)
394
+
395
+ if graph_node_class is not None and not class_is_instrumented(graph_node_class):
396
+ _instrument_method(
397
+ tracer_provider.get_tracer(graph_node_class.__module__),
398
+ graph_node_class,
399
+ "__call__",
400
+ attribute_extractors.extract_attrs_for_graph_node,
401
+ )
402
+ mark_class_as_instrumented(graph_node_class)
403
+
404
+ if lock_store_class is not None and not class_is_instrumented(lock_store_class):
405
+ # Not so straightforward: to wrap a function that is decorated as a
406
+ # `@asynccontextmanager`, we need to first unwrap the original function, then
407
+ # wrap that with the tracing functionality, and re-decorate as an
408
+ # `@asynccontextmanager`.
409
+ lock_method = inspect.unwrap(lock_store_class.lock)
410
+ traced_lock_method = traceable_async_generator(
411
+ lock_method,
412
+ tracer_provider.get_tracer(lock_store_class.__module__),
413
+ attribute_extractors.extract_attrs_for_lock_store,
414
+ )
415
+ lock_store_class.lock = contextlib.asynccontextmanager(traced_lock_method) # type: ignore[assignment]
416
+
417
+ logger.debug(f"Instrumented '{lock_store_class.__name__}.lock'.")
418
+
419
+ mark_class_as_instrumented(lock_store_class)
420
+
421
+ if graph_trainer_class is not None and not class_is_instrumented(
422
+ graph_trainer_class
423
+ ):
424
+ _instrument_method(
425
+ tracer_provider.get_tracer(graph_trainer_class.__module__),
426
+ graph_trainer_class,
427
+ "train",
428
+ attribute_extractors.extract_attrs_for_graph_trainer,
429
+ )
430
+ mark_class_as_instrumented(graph_trainer_class)
431
+
432
+ if llm_command_generator_class is not None and not class_is_instrumented(
433
+ llm_command_generator_class
434
+ ):
435
+ _instrument_method(
436
+ tracer_provider.get_tracer(llm_command_generator_class.__module__),
437
+ llm_command_generator_class,
438
+ "invoke_llm",
439
+ attribute_extractors.extract_attrs_for_llm_based_command_generator,
440
+ metrics_recorder=record_llm_command_generator_metrics,
441
+ )
442
+ _instrument_method(
443
+ tracer_provider.get_tracer(llm_command_generator_class.__module__),
444
+ llm_command_generator_class,
445
+ "_check_commands_against_startable_flows",
446
+ attribute_extractors.extract_attrs_for_check_commands_against_startable_flows,
447
+ )
448
+ mark_class_as_instrumented(llm_command_generator_class)
449
+
450
+ if (
451
+ single_step_llm_command_generator_class is not None
452
+ and not class_is_instrumented(single_step_llm_command_generator_class)
453
+ ):
454
+ _instrument_method(
455
+ tracer_provider.get_tracer(
456
+ single_step_llm_command_generator_class.__module__
457
+ ),
458
+ single_step_llm_command_generator_class,
459
+ "invoke_llm",
460
+ attribute_extractors.extract_attrs_for_llm_based_command_generator,
461
+ metrics_recorder=record_single_step_llm_command_generator_metrics,
462
+ )
463
+ _instrument_method(
464
+ tracer_provider.get_tracer(
465
+ single_step_llm_command_generator_class.__module__
466
+ ),
467
+ single_step_llm_command_generator_class,
468
+ "_check_commands_against_startable_flows",
469
+ attribute_extractors.extract_attrs_for_check_commands_against_startable_flows,
470
+ )
471
+ mark_class_as_instrumented(single_step_llm_command_generator_class)
472
+
473
+ if multi_step_llm_command_generator_class is not None and not class_is_instrumented(
474
+ multi_step_llm_command_generator_class
475
+ ):
476
+ _instrument_method(
477
+ tracer_provider.get_tracer(
478
+ multi_step_llm_command_generator_class.__module__
479
+ ),
480
+ multi_step_llm_command_generator_class,
481
+ "invoke_llm",
482
+ attribute_extractors.extract_attrs_for_llm_based_command_generator,
483
+ metrics_recorder=record_multi_step_llm_command_generator_metrics,
484
+ )
485
+ _instrument_multi_step_llm_command_generator_parse_commands(
486
+ tracer_provider.get_tracer(
487
+ multi_step_llm_command_generator_class.__module__
488
+ ),
489
+ multi_step_llm_command_generator_class,
490
+ )
491
+ mark_class_as_instrumented(multi_step_llm_command_generator_class)
492
+
493
+ if command_subclasses:
494
+ for command_subclass in command_subclasses:
495
+ if command_subclass is not None and not class_is_instrumented(
496
+ command_subclass
497
+ ):
498
+ _instrument_method(
499
+ tracer_provider.get_tracer(command_subclass.__module__),
500
+ command_subclass,
501
+ "run_command_on_tracker",
502
+ attribute_extractors.extract_attrs_for_command,
503
+ )
504
+ mark_class_as_instrumented(command_subclass)
505
+
506
+ if contextual_response_rephraser_class is not None and not class_is_instrumented(
507
+ contextual_response_rephraser_class
508
+ ):
509
+ _instrument_method(
510
+ tracer_provider.get_tracer(contextual_response_rephraser_class.__module__),
511
+ contextual_response_rephraser_class,
512
+ "_generate_llm_response",
513
+ attribute_extractors.extract_attrs_for_contextual_response_rephraser,
514
+ )
515
+ _instrument_method(
516
+ tracer_provider.get_tracer(contextual_response_rephraser_class.__module__),
517
+ contextual_response_rephraser_class,
518
+ "_create_history",
519
+ attribute_extractors.extract_attrs_for_create_history,
520
+ )
521
+ _instrument_method(
522
+ tracer_provider.get_tracer(contextual_response_rephraser_class.__module__),
523
+ contextual_response_rephraser_class,
524
+ "generate",
525
+ attribute_extractors.extract_attrs_for_generate,
526
+ )
527
+ mark_class_as_instrumented(contextual_response_rephraser_class)
528
+
529
+ if not module_is_instrumented(COMMAND_PROCESSOR_MODULE_NAME):
530
+ _instrument_command_processor_module(tracer_provider)
531
+
532
+ if not module_is_instrumented(FLOW_EXECUTOR_MODULE_NAME):
533
+ _instrument_flow_executor_module(tracer_provider)
534
+
535
+ if policy_subclasses:
536
+ for policy_subclass in policy_subclasses:
537
+ if policy_subclass is not None and not class_is_instrumented(
538
+ policy_subclass
539
+ ):
540
+ _instrument_method(
541
+ tracer_provider.get_tracer(policy_subclass.__module__),
542
+ policy_subclass,
543
+ "_prediction",
544
+ attribute_extractors.extract_attrs_for_policy_prediction,
545
+ )
546
+
547
+ _instrument_intentless_policy(
548
+ tracer_provider,
549
+ policy_subclass,
550
+ )
551
+
552
+ _instrument_enterprise_search_policy(
553
+ tracer_provider,
554
+ policy_subclass,
555
+ )
556
+
557
+ mark_class_as_instrumented(policy_subclass)
558
+
559
+ if vector_store_subclasses:
560
+ for vector_store_subclass in vector_store_subclasses:
561
+ if vector_store_subclass is not None and not class_is_instrumented(
562
+ vector_store_subclass
563
+ ):
564
+ _instrument_information_retrieval_search(
565
+ tracer_provider.get_tracer(vector_store_subclass.__module__),
566
+ vector_store_subclass,
567
+ )
568
+ mark_class_as_instrumented(vector_store_subclass)
569
+
570
+ if nlu_command_adapter_class is not None and not class_is_instrumented(
571
+ nlu_command_adapter_class
572
+ ):
573
+ _instrument_nlu_command_adapter_predict_commands(
574
+ tracer_provider.get_tracer(nlu_command_adapter_class.__module__),
575
+ nlu_command_adapter_class,
576
+ )
577
+ mark_class_as_instrumented(nlu_command_adapter_class)
578
+
579
+ if endpoint_config_class is not None and not class_is_instrumented(
580
+ endpoint_config_class
581
+ ):
582
+ _instrument_endpoint_config(
583
+ tracer_provider.get_tracer(endpoint_config_class.__module__),
584
+ endpoint_config_class,
585
+ )
586
+
587
+ if grpc_custom_action_executor_class is not None and not class_is_instrumented(
588
+ grpc_custom_action_executor_class
589
+ ):
590
+ _instrument_grpc_custom_action_executor(
591
+ tracer_provider.get_tracer(grpc_custom_action_executor_class.__module__),
592
+ grpc_custom_action_executor_class,
593
+ )
594
+
595
+ if custom_action_executor_subclasses:
596
+ for custom_action_executor_subclass in custom_action_executor_subclasses:
597
+ if (
598
+ custom_action_executor_subclass is not None
599
+ and not class_is_instrumented(custom_action_executor_subclass)
600
+ ):
601
+ _instrument_method(
602
+ tracer_provider.get_tracer(
603
+ custom_action_executor_subclass.__module__
604
+ ),
605
+ custom_action_executor_subclass,
606
+ "run",
607
+ attribute_extractors.extract_attrs_for_custom_action_executor_run,
608
+ )
609
+
610
+ if issubclass(
611
+ custom_action_executor_subclass, GRPCCustomActionExecutor
612
+ ):
613
+ _instrument_method(
614
+ tracer=tracer_provider.get_tracer(
615
+ custom_action_executor_subclass.__module__
616
+ ),
617
+ instrumented_class=custom_action_executor_subclass,
618
+ method_name="_request",
619
+ attr_extractor=attribute_extractors.extract_attrs_for_grpc_custom_action_executor_request,
620
+ )
621
+
622
+ mark_class_as_instrumented(custom_action_executor_subclass)
623
+
624
+
625
+ def _instrument_nlu_command_adapter_predict_commands(
626
+ tracer: Tracer, nlu_command_adapter_class: Type[NLUCommandAdapterType]
627
+ ) -> None:
628
+ def tracing_nlu_command_adapter_predict_commands_wrapper(fn: Callable) -> Callable:
629
+ @functools.wraps(fn)
630
+ async def wrapper(
631
+ self: NLUCommandAdapter,
632
+ message: Message,
633
+ flows: FlowsList,
634
+ tracker: Optional[DialogueStateTracker] = None,
635
+ **kwargs: Any,
636
+ ) -> List[Command]:
637
+ with tracer.start_as_current_span(
638
+ f"{self.__class__.__name__}.{fn.__name__}"
639
+ ) as span:
640
+ commands = await fn(self, message, flows, tracker, **kwargs)
641
+
642
+ span.set_attributes(
643
+ {
644
+ "commands": json.dumps(
645
+ [command.as_dict() for command in commands]
646
+ ),
647
+ "intent": json.dumps(message.get("intent", {}).get("name")),
648
+ }
649
+ )
650
+ return commands
651
+
652
+ return wrapper
653
+
654
+ nlu_command_adapter_class.predict_commands = ( # type: ignore[assignment]
655
+ tracing_nlu_command_adapter_predict_commands_wrapper(
656
+ nlu_command_adapter_class.predict_commands
657
+ )
658
+ )
659
+
660
+ logger.debug(
661
+ f"Instrumented '{nlu_command_adapter_class.__name__}.predict_commands'."
662
+ )
663
+
664
+
665
+ def _instrument_multi_step_llm_command_generator_parse_commands(
666
+ tracer: Tracer,
667
+ multi_step_llm_command_generator_class: Type[MultiStepLLMCommandGeneratorType],
668
+ ) -> None:
669
+ def tracing_multi_step_llm_command_generator_parse_commands_wrapper(
670
+ fn: Callable,
671
+ ) -> Callable:
672
+ @functools.wraps(fn)
673
+ def wrapper(
674
+ cls: MultiStepLLMCommandGenerator,
675
+ actions: Optional[str],
676
+ tracker: DialogueStateTracker,
677
+ flows: FlowsList,
678
+ is_start_or_end_prompt: bool = False,
679
+ ) -> List[Command]:
680
+ with tracer.start_as_current_span(
681
+ f"{cls.__class__.__name__}.{fn.__name__}"
682
+ ) as span:
683
+ commands = fn(actions, tracker, flows, is_start_or_end_prompt)
684
+
685
+ commands_list = []
686
+ for command in commands:
687
+ command_as_dict = command.as_dict()
688
+ command_type = command.command()
689
+
690
+ if command_type == SET_SLOT_COMMAND:
691
+ slot_value = command_as_dict.pop("value", None)
692
+ command_as_dict["is_slot_value_missing_or_none"] = (
693
+ slot_value is None
694
+ )
695
+
696
+ commands_list.append(command_as_dict)
697
+
698
+ span.set_attributes({"commands": json.dumps(commands_list)})
699
+ return commands
700
+
701
+ return wrapper
702
+
703
+ multi_step_llm_command_generator_class.parse_commands = ( # type: ignore[assignment]
704
+ tracing_multi_step_llm_command_generator_parse_commands_wrapper(
705
+ multi_step_llm_command_generator_class.parse_commands
706
+ )
707
+ )
708
+
709
+
710
+ def _instrument_information_retrieval_search(
711
+ tracer: Tracer, vector_store_class: Type[InformationRetrievalType]
712
+ ) -> None:
713
+ def tracing_information_retrieval_search_wrapper(fn: Callable) -> Callable:
714
+ @functools.wraps(fn)
715
+ async def wrapper(
716
+ self: InformationRetrieval,
717
+ query: Text,
718
+ tracker_state: Dict[str, Any],
719
+ threshold: float = 0.0,
720
+ ) -> SearchResultList:
721
+ with tracer.start_as_current_span(
722
+ f"{self.__class__.__name__}.{fn.__name__}"
723
+ ) as span:
724
+ documents = await fn(self, query, tracker_state, threshold)
725
+ span.set_attributes(
726
+ {
727
+ "query": query,
728
+ "document_metadata": json.dumps(
729
+ [document.metadata for document in documents.results]
730
+ ),
731
+ }
732
+ )
733
+ return documents
734
+
735
+ return wrapper
736
+
737
+ vector_store_class.search = tracing_information_retrieval_search_wrapper( # type: ignore[assignment]
738
+ vector_store_class.search
739
+ )
740
+
741
+ logger.debug(f"Instrumented '{vector_store_class.__name__}.search' method.")
742
+
743
+
744
+ def _instrument_enterprise_search_policy(
745
+ tracer_provider: TracerProvider, policy_class: Type[PolicyType]
746
+ ) -> None:
747
+ if policy_class.__module__ != "rasa.core.policies.enterprise_search_policy":
748
+ return None
749
+
750
+ tracer = tracer_provider.get_tracer(policy_class.__module__)
751
+
752
+ _instrument_method(
753
+ tracer,
754
+ policy_class,
755
+ "_generate_llm_answer",
756
+ attribute_extractors.extract_attrs_for_enterprise_search_generate_llm_answer,
757
+ )
758
+
759
+
760
+ def _instrument_intentless_policy(
761
+ tracer_provider: TracerProvider, policy_class: Type[PolicyType]
762
+ ) -> None:
763
+ if policy_class.__module__ != "rasa.core.policies.intentless_policy":
764
+ return None
765
+
766
+ tracer = tracer_provider.get_tracer(policy_class.__module__)
767
+
768
+ _instrument_method(
769
+ tracer,
770
+ policy_class,
771
+ "_prediction_result",
772
+ attribute_extractors.extract_attrs_for_intentless_policy_prediction_result,
773
+ )
774
+ _instrument_method(
775
+ tracer,
776
+ policy_class,
777
+ "find_closest_response",
778
+ attribute_extractors.extract_attrs_for_intentless_policy_find_closest_response,
779
+ )
780
+ _instrument_select_response_examples(tracer, policy_class)
781
+ _instrument_select_few_shot_conversations(tracer, policy_class)
782
+ _instrument_extract_ai_responses(tracer, policy_class)
783
+ _instrument_generate_answer(tracer, policy_class)
784
+ _instrument_method(
785
+ tracer,
786
+ policy_class,
787
+ "_generate_llm_answer",
788
+ attribute_extractors.extract_attrs_for_intentless_policy_generate_llm_answer,
789
+ )
790
+
791
+
792
+ def _instrument_processor(
793
+ tracer_provider: TracerProvider, processor_class: Type[ProcessorType]
794
+ ) -> None:
795
+ tracer = tracer_provider.get_tracer(processor_class.__module__)
796
+ _instrument_method(
797
+ tracer,
798
+ processor_class,
799
+ "handle_message",
800
+ None,
801
+ attribute_extractors.extract_headers,
802
+ )
803
+ _instrument_method(
804
+ tracer,
805
+ processor_class,
806
+ "log_message",
807
+ None,
808
+ attribute_extractors.extract_headers,
809
+ )
810
+ _instrument_run_action(tracer, processor_class)
811
+ _instrument_method(
812
+ tracer,
813
+ processor_class,
814
+ "save_tracker",
815
+ attribute_extractors.extract_number_of_events,
816
+ )
817
+ _instrument_method(tracer, processor_class, "_run_prediction_loop", None)
818
+ _instrument_method(
819
+ tracer,
820
+ processor_class,
821
+ "_predict_next_with_tracker",
822
+ attribute_extractors.extract_intent_name_and_slots,
823
+ )
824
+ _instrument_get_tracker(tracer, processor_class)
825
+
826
+
827
+ # Wrapping `get_tracker` works a bit differently since in this case, we actually need
828
+ # to extract the attributes from the return value.
829
+ def _instrument_get_tracker(
830
+ tracer: Tracer, processor_class: Type[ProcessorType]
831
+ ) -> None:
832
+ def tracing_get_tracker_wrapper(fn: Callable) -> Callable:
833
+ @functools.wraps(fn)
834
+ async def wrapper(
835
+ self: Type[ProcessorType], conversation_id: Text
836
+ ) -> DialogueStateTracker:
837
+ with tracer.start_as_current_span(
838
+ f"{self.__class__.__name__}.{fn.__name__}"
839
+ ) as span:
840
+ tracker: DialogueStateTracker = await fn(self, conversation_id)
841
+ span.set_attributes({"number_of_events": len(tracker.events)})
842
+ return tracker
843
+
844
+ return wrapper
845
+
846
+ processor_class.get_tracker = tracing_get_tracker_wrapper( # type: ignore[assignment]
847
+ processor_class.get_tracker
848
+ )
849
+
850
+ logger.debug(f"Instrumented '{processor_class.__name__}.get_tracker'.")
851
+
852
+
853
+ def _instrument_command_processor_module(tracer_provider: TracerProvider) -> None:
854
+ _instrument_function(
855
+ tracer_provider.get_tracer(COMMAND_PROCESSOR_MODULE_NAME),
856
+ COMMAND_PROCESSOR_MODULE_NAME,
857
+ "execute_commands",
858
+ attribute_extractors.extract_attrs_for_execute_commands,
859
+ )
860
+ _instrument_function(
861
+ tracer_provider.get_tracer(COMMAND_PROCESSOR_MODULE_NAME),
862
+ COMMAND_PROCESSOR_MODULE_NAME,
863
+ "validate_state_of_commands",
864
+ attribute_extractors.extract_attrs_for_validate_state_of_commands,
865
+ )
866
+ _instrument_function(
867
+ tracer_provider.get_tracer(COMMAND_PROCESSOR_MODULE_NAME),
868
+ COMMAND_PROCESSOR_MODULE_NAME,
869
+ "clean_up_commands",
870
+ attribute_extractors.extract_attrs_for_clean_up_commands,
871
+ )
872
+ _instrument_function(
873
+ tracer_provider.get_tracer(COMMAND_PROCESSOR_MODULE_NAME),
874
+ COMMAND_PROCESSOR_MODULE_NAME,
875
+ "remove_duplicated_set_slots",
876
+ attribute_extractors.extract_attrs_for_remove_duplicated_set_slots,
877
+ )
878
+ mark_module_as_instrumented(COMMAND_PROCESSOR_MODULE_NAME)
879
+
880
+
881
+ def _instrument_flow_executor_module(tracer_provider: TracerProvider) -> None:
882
+ _instrument_function(
883
+ tracer_provider.get_tracer(FLOW_EXECUTOR_MODULE_NAME),
884
+ FLOW_EXECUTOR_MODULE_NAME,
885
+ "advance_flows",
886
+ attribute_extractors.extract_attrs_for_advance_flows,
887
+ )
888
+ _instrument_advance_flows_until_next_action(
889
+ tracer_provider.get_tracer(FLOW_EXECUTOR_MODULE_NAME),
890
+ FLOW_EXECUTOR_MODULE_NAME,
891
+ "advance_flows_until_next_action",
892
+ )
893
+ _instrument_function(
894
+ tracer_provider.get_tracer(FLOW_EXECUTOR_MODULE_NAME),
895
+ FLOW_EXECUTOR_MODULE_NAME,
896
+ "run_step",
897
+ attribute_extractors.extract_attrs_for_run_step,
898
+ )
899
+ mark_module_as_instrumented(FLOW_EXECUTOR_MODULE_NAME)
900
+
901
+
902
+ def _instrument_advance_flows_until_next_action(
903
+ tracer: Tracer,
904
+ module_name: str,
905
+ function_name: str,
906
+ ) -> None:
907
+ def tracing_advance_flows_until_next_action_wrapper(fn: Callable) -> Callable:
908
+ @functools.wraps(fn)
909
+ def wrapper(
910
+ tracker: DialogueStateTracker,
911
+ available_actions: List[str],
912
+ flows: FlowsList,
913
+ ) -> FlowActionPrediction:
914
+ with tracer.start_as_current_span(f"{module_name}.{fn.__name__}") as span:
915
+ prediction: FlowActionPrediction = fn(tracker, available_actions, flows)
916
+
917
+ span.set_attributes(
918
+ {
919
+ "action_name": prediction.action_name
920
+ if prediction.action_name
921
+ else "None",
922
+ "score": prediction.score,
923
+ "metadata": json.dumps(prediction.metadata)
924
+ if prediction.metadata
925
+ else "{}",
926
+ "events": json.dumps(
927
+ [event.__class__.__name__ for event in prediction.events]
928
+ if prediction.events
929
+ else [],
930
+ ),
931
+ }
932
+ )
933
+
934
+ return prediction
935
+
936
+ return wrapper
937
+
938
+ module = importlib.import_module(module_name)
939
+ function_to_trace = getattr(module, function_name)
940
+
941
+ traced_function = tracing_advance_flows_until_next_action_wrapper(function_to_trace)
942
+
943
+ setattr(module, function_name, traced_function)
944
+
945
+ logger.debug(
946
+ f"Instrumented function '{function_name}' in the module '{module_name}'. "
947
+ )
948
+
949
+
950
+ def _instrument_method(
951
+ tracer: Tracer,
952
+ instrumented_class: Type,
953
+ method_name: Text,
954
+ attr_extractor: Optional[Callable],
955
+ header_extractor: Optional[Callable] = None,
956
+ metrics_recorder: Optional[Callable] = None,
957
+ ) -> None:
958
+ method_to_trace = getattr(instrumented_class, method_name)
959
+ traced_method = _wrap_with_tracing_decorator(
960
+ method_to_trace, tracer, attr_extractor, header_extractor, metrics_recorder
961
+ )
962
+ setattr(instrumented_class, method_name, traced_method)
963
+
964
+ logger.debug(f"Instrumented '{instrumented_class.__name__}.{method_name}'.")
965
+
966
+
967
+ def _instrument_function(
968
+ tracer: Tracer,
969
+ module_name: Text,
970
+ function_name: Text,
971
+ attr_extractor: Optional[Callable],
972
+ header_extractor: Optional[Callable] = None,
973
+ ) -> None:
974
+ module = importlib.import_module(module_name)
975
+ function_to_trace = getattr(module, function_name)
976
+ traced_function = _wrap_with_tracing_decorator(
977
+ function_to_trace, tracer, attr_extractor, header_extractor
978
+ )
979
+
980
+ setattr(module, function_name, traced_function)
981
+
982
+ logger.debug(
983
+ f"Instrumented function '{function_name}' in the module '{module_name}'. "
984
+ )
985
+
986
+
987
+ def _wrap_with_tracing_decorator(
988
+ callable_to_trace: Callable,
989
+ tracer: Tracer,
990
+ attr_extractor: Optional[Callable],
991
+ header_extractor: Optional[Callable] = None,
992
+ metrics_recorder: Optional[Callable] = None,
993
+ ) -> Callable:
994
+ if inspect.iscoroutinefunction(callable_to_trace):
995
+ traced_callable = traceable_async(
996
+ callable_to_trace,
997
+ tracer,
998
+ attr_extractor,
999
+ header_extractor,
1000
+ metrics_recorder,
1001
+ )
1002
+ else:
1003
+ traced_callable = traceable(
1004
+ callable_to_trace, tracer, attr_extractor, metrics_recorder
1005
+ )
1006
+
1007
+ return traced_callable
1008
+
1009
+
1010
+ def _instrument_run_action(
1011
+ tracer: Tracer, processor_class: Type[ProcessorType]
1012
+ ) -> None:
1013
+ def tracing_run_action_wrapper(fn: Callable) -> Callable:
1014
+ @functools.wraps(fn)
1015
+ async def wrapper(
1016
+ self: Type[ProcessorType],
1017
+ action: Action,
1018
+ tracker: DialogueStateTracker,
1019
+ output_channel: OutputChannel,
1020
+ nlg: NaturalLanguageGenerator,
1021
+ prediction: PolicyPrediction,
1022
+ ) -> bool:
1023
+ attrs = {
1024
+ "action_name": action.name(),
1025
+ "sender_id": tracker.sender_id,
1026
+ "message_id": tracker.latest_message.message_id or "default", # type: ignore[union-attr]
1027
+ }
1028
+ if isinstance(action, RemoteAction):
1029
+ if isinstance(action.executor, RetryCustomActionExecutor):
1030
+ attrs["executor_class_name"] = type(
1031
+ action.executor._custom_action_executor
1032
+ ).__name__
1033
+ else:
1034
+ attrs["executor_class_name"] = type(action.executor).__name__
1035
+ with tracer.start_as_current_span(
1036
+ f"{self.__class__.__name__}.{fn.__name__}",
1037
+ kind=SpanKind.CLIENT,
1038
+ attributes=attrs,
1039
+ ):
1040
+ return await fn(self, action, tracker, output_channel, nlg, prediction)
1041
+
1042
+ return wrapper
1043
+
1044
+ processor_class._run_action = tracing_run_action_wrapper( # type: ignore[assignment]
1045
+ processor_class._run_action
1046
+ )
1047
+
1048
+ logger.debug(f"Instrumented '{processor_class.__name__}._run_action'.")
1049
+
1050
+
1051
+ def _instrument_endpoint_config(
1052
+ tracer: Tracer, endpoint_config_class: Type[EndpointConfigType]
1053
+ ) -> None:
1054
+ """Instrument the `request` method of the `EndpointConfig` class.
1055
+
1056
+ Args:
1057
+ tracer: The `Tracer` that shall be used for tracing.
1058
+ endpoint_config_class: The `EndpointConfig` to be instrumented.
1059
+ """
1060
+
1061
+ def tracing_endpoint_config_wrapper(fn: Callable) -> Callable:
1062
+ @functools.wraps(fn)
1063
+ async def wrapper(
1064
+ self: Type[EndpointConfigType],
1065
+ method: Text = "post",
1066
+ subpath: Optional[Text] = None,
1067
+ content_type: Optional[Text] = "application/json",
1068
+ compress: bool = False,
1069
+ **kwargs: Any,
1070
+ ) -> bool:
1071
+ request_body = kwargs.get("json")
1072
+ attrs: Dict[str, Any] = {"url": concat_url(self.url, subpath)}
1073
+
1074
+ if not request_body:
1075
+ attrs.update({REQUEST_BODY_SIZE_IN_BYTES_ATTRIBUTE_NAME: 0})
1076
+ else:
1077
+ attrs.update(
1078
+ {
1079
+ REQUEST_BODY_SIZE_IN_BYTES_ATTRIBUTE_NAME: len(
1080
+ json.dumps(request_body).encode("utf-8")
1081
+ )
1082
+ }
1083
+ )
1084
+ with tracer.start_as_current_span(
1085
+ f"{self.__class__.__name__}.{fn.__name__}",
1086
+ attributes=attrs,
1087
+ ):
1088
+ TraceContextTextMapPropagator().inject(self.headers)
1089
+
1090
+ start_time = time.perf_counter_ns()
1091
+ result = await fn(
1092
+ self, method, subpath, content_type, compress, **kwargs
1093
+ )
1094
+ end_time = time.perf_counter_ns()
1095
+
1096
+ record_callable_duration_metrics(self, start_time, end_time)
1097
+ record_request_size_in_bytes(attrs)
1098
+
1099
+ return result
1100
+
1101
+ return wrapper
1102
+
1103
+ endpoint_config_class.request = tracing_endpoint_config_wrapper( # type: ignore[assignment]
1104
+ endpoint_config_class.request
1105
+ )
1106
+
1107
+ logger.debug(f"Instrumented '{endpoint_config_class.__name__}.request'.")
1108
+
1109
+
1110
+ def _instrument_grpc_custom_action_executor(
1111
+ tracer: Tracer, grpc_custom_action_executor_class: Type[GRPCCustomActionExecutor]
1112
+ ) -> None:
1113
+ """Instrument the `run` method of the `GRPCCustomActionExecutor` class.
1114
+
1115
+ Args:
1116
+ tracer: The `Tracer` that shall be used for tracing.
1117
+ grpc_custom_action_executor_class: The `GRPCCustomActionExecutor` to
1118
+ be instrumented.
1119
+ """
1120
+
1121
+ def tracing_grpc_custom_action_executor_wrapper(fn: Callable) -> Callable:
1122
+ @functools.wraps(fn)
1123
+ async def wrapper(
1124
+ self: Type[GRPCCustomActionExecutor],
1125
+ tracker: Type[DialogueStateTracker],
1126
+ domain: Type[Domain],
1127
+ include_domain: bool = False,
1128
+ ) -> bool:
1129
+ TraceContextTextMapPropagator().inject(self.action_endpoint.headers)
1130
+ result = await fn(self, tracker, domain, include_domain)
1131
+ return result
1132
+
1133
+ return wrapper
1134
+
1135
+ grpc_custom_action_executor_class.run = tracing_grpc_custom_action_executor_wrapper( # type: ignore[assignment]
1136
+ grpc_custom_action_executor_class.run
1137
+ )
1138
+
1139
+ logger.debug(f"Instrumented '{grpc_custom_action_executor_class.__name__}.run.")
1140
+
1141
+
1142
+ def _mangled_instrumented_boolean_attribute_name(instrumented_class: Type) -> Text:
1143
+ # see https://peps.python.org/pep-0008/#method-names-and-instance-variables
1144
+ # and https://stackoverflow.com/a/50401073
1145
+ return f"_{instrumented_class.__name__}__{INSTRUMENTED_BOOLEAN_ATTRIBUTE_NAME}"
1146
+
1147
+
1148
+ def class_is_instrumented(instrumented_class: Type) -> bool:
1149
+ """Check if a class has already been instrumented."""
1150
+ return getattr(
1151
+ instrumented_class,
1152
+ _mangled_instrumented_boolean_attribute_name(instrumented_class),
1153
+ False,
1154
+ )
1155
+
1156
+
1157
+ def mark_class_as_instrumented(instrumented_class: Type) -> None:
1158
+ """Mark a class as instrumented if it isn't already marked."""
1159
+ if not class_is_instrumented(instrumented_class):
1160
+ setattr(
1161
+ instrumented_class,
1162
+ _mangled_instrumented_boolean_attribute_name(instrumented_class),
1163
+ True,
1164
+ )
1165
+
1166
+
1167
+ def _instrumented_module_boolean_attribute_name(module_name: Text) -> Text:
1168
+ return f"{module_name}_{INSTRUMENTED_MODULE_BOOLEAN_ATTRIBUTE_NAME}"
1169
+
1170
+
1171
+ def module_is_instrumented(module_name: Text) -> bool:
1172
+ """Check if a module has already been instrumented."""
1173
+ module = importlib.import_module(module_name)
1174
+ return getattr(
1175
+ module,
1176
+ _instrumented_module_boolean_attribute_name(module_name),
1177
+ False,
1178
+ )
1179
+
1180
+
1181
+ def mark_module_as_instrumented(module_name: Text) -> None:
1182
+ """Mark a module as instrumented if it isn't already marked."""
1183
+ module = importlib.import_module(module_name)
1184
+ if not module_is_instrumented(module_name):
1185
+ setattr(module, _instrumented_module_boolean_attribute_name(module_name), True)