xplia 1.0.1__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.
Files changed (870) hide show
  1. venv/Lib/site-packages/_distutils_hack/__init__.py +222 -0
  2. venv/Lib/site-packages/_distutils_hack/override.py +1 -0
  3. venv/Lib/site-packages/pip/__init__.py +13 -0
  4. venv/Lib/site-packages/pip/__main__.py +24 -0
  5. venv/Lib/site-packages/pip/__pip-runner__.py +50 -0
  6. venv/Lib/site-packages/pip/_internal/__init__.py +19 -0
  7. venv/Lib/site-packages/pip/_internal/build_env.py +311 -0
  8. venv/Lib/site-packages/pip/_internal/cache.py +292 -0
  9. venv/Lib/site-packages/pip/_internal/cli/__init__.py +4 -0
  10. venv/Lib/site-packages/pip/_internal/cli/autocompletion.py +171 -0
  11. venv/Lib/site-packages/pip/_internal/cli/base_command.py +236 -0
  12. venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py +1074 -0
  13. venv/Lib/site-packages/pip/_internal/cli/command_context.py +27 -0
  14. venv/Lib/site-packages/pip/_internal/cli/main.py +79 -0
  15. venv/Lib/site-packages/pip/_internal/cli/main_parser.py +134 -0
  16. venv/Lib/site-packages/pip/_internal/cli/parser.py +294 -0
  17. venv/Lib/site-packages/pip/_internal/cli/progress_bars.py +68 -0
  18. venv/Lib/site-packages/pip/_internal/cli/req_command.py +508 -0
  19. venv/Lib/site-packages/pip/_internal/cli/spinners.py +159 -0
  20. venv/Lib/site-packages/pip/_internal/cli/status_codes.py +6 -0
  21. venv/Lib/site-packages/pip/_internal/commands/__init__.py +132 -0
  22. venv/Lib/site-packages/pip/_internal/commands/cache.py +222 -0
  23. venv/Lib/site-packages/pip/_internal/commands/check.py +54 -0
  24. venv/Lib/site-packages/pip/_internal/commands/completion.py +121 -0
  25. venv/Lib/site-packages/pip/_internal/commands/configuration.py +282 -0
  26. venv/Lib/site-packages/pip/_internal/commands/debug.py +199 -0
  27. venv/Lib/site-packages/pip/_internal/commands/download.py +147 -0
  28. venv/Lib/site-packages/pip/_internal/commands/freeze.py +108 -0
  29. venv/Lib/site-packages/pip/_internal/commands/hash.py +59 -0
  30. venv/Lib/site-packages/pip/_internal/commands/help.py +41 -0
  31. venv/Lib/site-packages/pip/_internal/commands/index.py +139 -0
  32. venv/Lib/site-packages/pip/_internal/commands/inspect.py +92 -0
  33. venv/Lib/site-packages/pip/_internal/commands/install.py +778 -0
  34. venv/Lib/site-packages/pip/_internal/commands/list.py +368 -0
  35. venv/Lib/site-packages/pip/_internal/commands/search.py +174 -0
  36. venv/Lib/site-packages/pip/_internal/commands/show.py +189 -0
  37. venv/Lib/site-packages/pip/_internal/commands/uninstall.py +113 -0
  38. venv/Lib/site-packages/pip/_internal/commands/wheel.py +183 -0
  39. venv/Lib/site-packages/pip/_internal/configuration.py +381 -0
  40. venv/Lib/site-packages/pip/_internal/distributions/__init__.py +21 -0
  41. venv/Lib/site-packages/pip/_internal/distributions/base.py +39 -0
  42. venv/Lib/site-packages/pip/_internal/distributions/installed.py +23 -0
  43. venv/Lib/site-packages/pip/_internal/distributions/sdist.py +150 -0
  44. venv/Lib/site-packages/pip/_internal/distributions/wheel.py +34 -0
  45. venv/Lib/site-packages/pip/_internal/exceptions.py +733 -0
  46. venv/Lib/site-packages/pip/_internal/index/__init__.py +2 -0
  47. venv/Lib/site-packages/pip/_internal/index/collector.py +505 -0
  48. venv/Lib/site-packages/pip/_internal/index/package_finder.py +1029 -0
  49. venv/Lib/site-packages/pip/_internal/index/sources.py +223 -0
  50. venv/Lib/site-packages/pip/_internal/locations/__init__.py +467 -0
  51. venv/Lib/site-packages/pip/_internal/locations/_distutils.py +173 -0
  52. venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py +213 -0
  53. venv/Lib/site-packages/pip/_internal/locations/base.py +81 -0
  54. venv/Lib/site-packages/pip/_internal/main.py +12 -0
  55. venv/Lib/site-packages/pip/_internal/metadata/__init__.py +127 -0
  56. venv/Lib/site-packages/pip/_internal/metadata/_json.py +84 -0
  57. venv/Lib/site-packages/pip/_internal/metadata/base.py +688 -0
  58. venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py +4 -0
  59. venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py +55 -0
  60. venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py +224 -0
  61. venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py +188 -0
  62. venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py +270 -0
  63. venv/Lib/site-packages/pip/_internal/models/__init__.py +2 -0
  64. venv/Lib/site-packages/pip/_internal/models/candidate.py +34 -0
  65. venv/Lib/site-packages/pip/_internal/models/direct_url.py +237 -0
  66. venv/Lib/site-packages/pip/_internal/models/format_control.py +80 -0
  67. venv/Lib/site-packages/pip/_internal/models/index.py +28 -0
  68. venv/Lib/site-packages/pip/_internal/models/installation_report.py +53 -0
  69. venv/Lib/site-packages/pip/_internal/models/link.py +581 -0
  70. venv/Lib/site-packages/pip/_internal/models/scheme.py +31 -0
  71. venv/Lib/site-packages/pip/_internal/models/search_scope.py +132 -0
  72. venv/Lib/site-packages/pip/_internal/models/selection_prefs.py +51 -0
  73. venv/Lib/site-packages/pip/_internal/models/target_python.py +110 -0
  74. venv/Lib/site-packages/pip/_internal/models/wheel.py +92 -0
  75. venv/Lib/site-packages/pip/_internal/network/__init__.py +2 -0
  76. venv/Lib/site-packages/pip/_internal/network/auth.py +561 -0
  77. venv/Lib/site-packages/pip/_internal/network/cache.py +69 -0
  78. venv/Lib/site-packages/pip/_internal/network/download.py +186 -0
  79. venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py +210 -0
  80. venv/Lib/site-packages/pip/_internal/network/session.py +519 -0
  81. venv/Lib/site-packages/pip/_internal/network/utils.py +96 -0
  82. venv/Lib/site-packages/pip/_internal/network/xmlrpc.py +60 -0
  83. venv/Lib/site-packages/pip/_internal/operations/__init__.py +0 -0
  84. venv/Lib/site-packages/pip/_internal/operations/build/__init__.py +0 -0
  85. venv/Lib/site-packages/pip/_internal/operations/build/build_tracker.py +124 -0
  86. venv/Lib/site-packages/pip/_internal/operations/build/metadata.py +39 -0
  87. venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py +41 -0
  88. venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py +74 -0
  89. venv/Lib/site-packages/pip/_internal/operations/build/wheel.py +37 -0
  90. venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py +46 -0
  91. venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py +102 -0
  92. venv/Lib/site-packages/pip/_internal/operations/check.py +187 -0
  93. venv/Lib/site-packages/pip/_internal/operations/freeze.py +255 -0
  94. venv/Lib/site-packages/pip/_internal/operations/install/__init__.py +2 -0
  95. venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py +46 -0
  96. venv/Lib/site-packages/pip/_internal/operations/install/wheel.py +740 -0
  97. venv/Lib/site-packages/pip/_internal/operations/prepare.py +743 -0
  98. venv/Lib/site-packages/pip/_internal/pyproject.py +179 -0
  99. venv/Lib/site-packages/pip/_internal/req/__init__.py +92 -0
  100. venv/Lib/site-packages/pip/_internal/req/constructors.py +506 -0
  101. venv/Lib/site-packages/pip/_internal/req/req_file.py +552 -0
  102. venv/Lib/site-packages/pip/_internal/req/req_install.py +874 -0
  103. venv/Lib/site-packages/pip/_internal/req/req_set.py +119 -0
  104. venv/Lib/site-packages/pip/_internal/req/req_uninstall.py +650 -0
  105. venv/Lib/site-packages/pip/_internal/resolution/__init__.py +0 -0
  106. venv/Lib/site-packages/pip/_internal/resolution/base.py +20 -0
  107. venv/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py +0 -0
  108. venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py +600 -0
  109. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py +0 -0
  110. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py +141 -0
  111. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py +555 -0
  112. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py +730 -0
  113. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py +155 -0
  114. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py +255 -0
  115. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py +80 -0
  116. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py +165 -0
  117. venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py +299 -0
  118. venv/Lib/site-packages/pip/_internal/self_outdated_check.py +242 -0
  119. venv/Lib/site-packages/pip/_internal/utils/__init__.py +0 -0
  120. venv/Lib/site-packages/pip/_internal/utils/_jaraco_text.py +109 -0
  121. venv/Lib/site-packages/pip/_internal/utils/_log.py +38 -0
  122. venv/Lib/site-packages/pip/_internal/utils/appdirs.py +52 -0
  123. venv/Lib/site-packages/pip/_internal/utils/compat.py +63 -0
  124. venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py +165 -0
  125. venv/Lib/site-packages/pip/_internal/utils/datetime.py +11 -0
  126. venv/Lib/site-packages/pip/_internal/utils/deprecation.py +120 -0
  127. venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py +87 -0
  128. venv/Lib/site-packages/pip/_internal/utils/egg_link.py +72 -0
  129. venv/Lib/site-packages/pip/_internal/utils/encoding.py +36 -0
  130. venv/Lib/site-packages/pip/_internal/utils/entrypoints.py +84 -0
  131. venv/Lib/site-packages/pip/_internal/utils/filesystem.py +153 -0
  132. venv/Lib/site-packages/pip/_internal/utils/filetypes.py +27 -0
  133. venv/Lib/site-packages/pip/_internal/utils/glibc.py +88 -0
  134. venv/Lib/site-packages/pip/_internal/utils/hashes.py +151 -0
  135. venv/Lib/site-packages/pip/_internal/utils/inject_securetransport.py +35 -0
  136. venv/Lib/site-packages/pip/_internal/utils/logging.py +348 -0
  137. venv/Lib/site-packages/pip/_internal/utils/misc.py +735 -0
  138. venv/Lib/site-packages/pip/_internal/utils/models.py +39 -0
  139. venv/Lib/site-packages/pip/_internal/utils/packaging.py +57 -0
  140. venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py +146 -0
  141. venv/Lib/site-packages/pip/_internal/utils/subprocess.py +260 -0
  142. venv/Lib/site-packages/pip/_internal/utils/temp_dir.py +246 -0
  143. venv/Lib/site-packages/pip/_internal/utils/unpacking.py +257 -0
  144. venv/Lib/site-packages/pip/_internal/utils/urls.py +62 -0
  145. venv/Lib/site-packages/pip/_internal/utils/virtualenv.py +104 -0
  146. venv/Lib/site-packages/pip/_internal/utils/wheel.py +136 -0
  147. venv/Lib/site-packages/pip/_internal/vcs/__init__.py +15 -0
  148. venv/Lib/site-packages/pip/_internal/vcs/bazaar.py +112 -0
  149. venv/Lib/site-packages/pip/_internal/vcs/git.py +526 -0
  150. venv/Lib/site-packages/pip/_internal/vcs/mercurial.py +163 -0
  151. venv/Lib/site-packages/pip/_internal/vcs/subversion.py +324 -0
  152. venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py +705 -0
  153. venv/Lib/site-packages/pip/_internal/wheel_builder.py +355 -0
  154. venv/Lib/site-packages/pip/_vendor/__init__.py +120 -0
  155. venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py +18 -0
  156. venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py +61 -0
  157. venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py +137 -0
  158. venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py +65 -0
  159. venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py +9 -0
  160. venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py +188 -0
  161. venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py +39 -0
  162. venv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py +32 -0
  163. venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py +439 -0
  164. venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py +111 -0
  165. venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py +139 -0
  166. venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py +190 -0
  167. venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py +33 -0
  168. venv/Lib/site-packages/pip/_vendor/certifi/__init__.py +4 -0
  169. venv/Lib/site-packages/pip/_vendor/certifi/__main__.py +12 -0
  170. venv/Lib/site-packages/pip/_vendor/certifi/core.py +108 -0
  171. venv/Lib/site-packages/pip/_vendor/chardet/__init__.py +115 -0
  172. venv/Lib/site-packages/pip/_vendor/chardet/big5freq.py +386 -0
  173. venv/Lib/site-packages/pip/_vendor/chardet/big5prober.py +47 -0
  174. venv/Lib/site-packages/pip/_vendor/chardet/chardistribution.py +261 -0
  175. venv/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py +106 -0
  176. venv/Lib/site-packages/pip/_vendor/chardet/charsetprober.py +147 -0
  177. venv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py +0 -0
  178. venv/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py +112 -0
  179. venv/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py +90 -0
  180. venv/Lib/site-packages/pip/_vendor/chardet/codingstatemachinedict.py +19 -0
  181. venv/Lib/site-packages/pip/_vendor/chardet/cp949prober.py +49 -0
  182. venv/Lib/site-packages/pip/_vendor/chardet/enums.py +85 -0
  183. venv/Lib/site-packages/pip/_vendor/chardet/escprober.py +102 -0
  184. venv/Lib/site-packages/pip/_vendor/chardet/escsm.py +261 -0
  185. venv/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py +102 -0
  186. venv/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py +196 -0
  187. venv/Lib/site-packages/pip/_vendor/chardet/euckrprober.py +47 -0
  188. venv/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py +388 -0
  189. venv/Lib/site-packages/pip/_vendor/chardet/euctwprober.py +47 -0
  190. venv/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py +284 -0
  191. venv/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py +47 -0
  192. venv/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py +316 -0
  193. venv/Lib/site-packages/pip/_vendor/chardet/jisfreq.py +325 -0
  194. venv/Lib/site-packages/pip/_vendor/chardet/johabfreq.py +2382 -0
  195. venv/Lib/site-packages/pip/_vendor/chardet/johabprober.py +47 -0
  196. venv/Lib/site-packages/pip/_vendor/chardet/jpcntx.py +238 -0
  197. venv/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py +4649 -0
  198. venv/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py +4397 -0
  199. venv/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py +4380 -0
  200. venv/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py +4649 -0
  201. venv/Lib/site-packages/pip/_vendor/chardet/langrussianmodel.py +5725 -0
  202. venv/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py +4380 -0
  203. venv/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py +4380 -0
  204. venv/Lib/site-packages/pip/_vendor/chardet/latin1prober.py +147 -0
  205. venv/Lib/site-packages/pip/_vendor/chardet/macromanprober.py +162 -0
  206. venv/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py +95 -0
  207. venv/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py +57 -0
  208. venv/Lib/site-packages/pip/_vendor/chardet/mbcssm.py +661 -0
  209. venv/Lib/site-packages/pip/_vendor/chardet/metadata/__init__.py +0 -0
  210. venv/Lib/site-packages/pip/_vendor/chardet/metadata/languages.py +352 -0
  211. venv/Lib/site-packages/pip/_vendor/chardet/resultdict.py +16 -0
  212. venv/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py +162 -0
  213. venv/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py +88 -0
  214. venv/Lib/site-packages/pip/_vendor/chardet/sjisprober.py +105 -0
  215. venv/Lib/site-packages/pip/_vendor/chardet/universaldetector.py +362 -0
  216. venv/Lib/site-packages/pip/_vendor/chardet/utf1632prober.py +225 -0
  217. venv/Lib/site-packages/pip/_vendor/chardet/utf8prober.py +82 -0
  218. venv/Lib/site-packages/pip/_vendor/chardet/version.py +9 -0
  219. venv/Lib/site-packages/pip/_vendor/colorama/__init__.py +7 -0
  220. venv/Lib/site-packages/pip/_vendor/colorama/ansi.py +102 -0
  221. venv/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py +277 -0
  222. venv/Lib/site-packages/pip/_vendor/colorama/initialise.py +121 -0
  223. venv/Lib/site-packages/pip/_vendor/colorama/tests/__init__.py +1 -0
  224. venv/Lib/site-packages/pip/_vendor/colorama/tests/ansi_test.py +76 -0
  225. venv/Lib/site-packages/pip/_vendor/colorama/tests/ansitowin32_test.py +294 -0
  226. venv/Lib/site-packages/pip/_vendor/colorama/tests/initialise_test.py +189 -0
  227. venv/Lib/site-packages/pip/_vendor/colorama/tests/isatty_test.py +57 -0
  228. venv/Lib/site-packages/pip/_vendor/colorama/tests/utils.py +49 -0
  229. venv/Lib/site-packages/pip/_vendor/colorama/tests/winterm_test.py +131 -0
  230. venv/Lib/site-packages/pip/_vendor/colorama/win32.py +180 -0
  231. venv/Lib/site-packages/pip/_vendor/colorama/winterm.py +195 -0
  232. venv/Lib/site-packages/pip/_vendor/distlib/__init__.py +23 -0
  233. venv/Lib/site-packages/pip/_vendor/distlib/compat.py +1116 -0
  234. venv/Lib/site-packages/pip/_vendor/distlib/database.py +1350 -0
  235. venv/Lib/site-packages/pip/_vendor/distlib/index.py +508 -0
  236. venv/Lib/site-packages/pip/_vendor/distlib/locators.py +1300 -0
  237. venv/Lib/site-packages/pip/_vendor/distlib/manifest.py +393 -0
  238. venv/Lib/site-packages/pip/_vendor/distlib/markers.py +152 -0
  239. venv/Lib/site-packages/pip/_vendor/distlib/metadata.py +1076 -0
  240. venv/Lib/site-packages/pip/_vendor/distlib/resources.py +358 -0
  241. venv/Lib/site-packages/pip/_vendor/distlib/scripts.py +437 -0
  242. venv/Lib/site-packages/pip/_vendor/distlib/util.py +1932 -0
  243. venv/Lib/site-packages/pip/_vendor/distlib/version.py +739 -0
  244. venv/Lib/site-packages/pip/_vendor/distlib/wheel.py +1082 -0
  245. venv/Lib/site-packages/pip/_vendor/distro/__init__.py +54 -0
  246. venv/Lib/site-packages/pip/_vendor/distro/__main__.py +4 -0
  247. venv/Lib/site-packages/pip/_vendor/distro/distro.py +1399 -0
  248. venv/Lib/site-packages/pip/_vendor/idna/__init__.py +44 -0
  249. venv/Lib/site-packages/pip/_vendor/idna/codec.py +112 -0
  250. venv/Lib/site-packages/pip/_vendor/idna/compat.py +13 -0
  251. venv/Lib/site-packages/pip/_vendor/idna/core.py +400 -0
  252. venv/Lib/site-packages/pip/_vendor/idna/idnadata.py +2151 -0
  253. venv/Lib/site-packages/pip/_vendor/idna/intranges.py +54 -0
  254. venv/Lib/site-packages/pip/_vendor/idna/package_data.py +2 -0
  255. venv/Lib/site-packages/pip/_vendor/idna/uts46data.py +8600 -0
  256. venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py +57 -0
  257. venv/Lib/site-packages/pip/_vendor/msgpack/exceptions.py +48 -0
  258. venv/Lib/site-packages/pip/_vendor/msgpack/ext.py +193 -0
  259. venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py +1010 -0
  260. venv/Lib/site-packages/pip/_vendor/packaging/__about__.py +26 -0
  261. venv/Lib/site-packages/pip/_vendor/packaging/__init__.py +25 -0
  262. venv/Lib/site-packages/pip/_vendor/packaging/_manylinux.py +301 -0
  263. venv/Lib/site-packages/pip/_vendor/packaging/_musllinux.py +136 -0
  264. venv/Lib/site-packages/pip/_vendor/packaging/_structures.py +61 -0
  265. venv/Lib/site-packages/pip/_vendor/packaging/markers.py +304 -0
  266. venv/Lib/site-packages/pip/_vendor/packaging/requirements.py +146 -0
  267. venv/Lib/site-packages/pip/_vendor/packaging/specifiers.py +802 -0
  268. venv/Lib/site-packages/pip/_vendor/packaging/tags.py +487 -0
  269. venv/Lib/site-packages/pip/_vendor/packaging/utils.py +136 -0
  270. venv/Lib/site-packages/pip/_vendor/packaging/version.py +504 -0
  271. venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py +3361 -0
  272. venv/Lib/site-packages/pip/_vendor/platformdirs/__init__.py +566 -0
  273. venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py +53 -0
  274. venv/Lib/site-packages/pip/_vendor/platformdirs/android.py +210 -0
  275. venv/Lib/site-packages/pip/_vendor/platformdirs/api.py +223 -0
  276. venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py +91 -0
  277. venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py +223 -0
  278. venv/Lib/site-packages/pip/_vendor/platformdirs/version.py +4 -0
  279. venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py +255 -0
  280. venv/Lib/site-packages/pip/_vendor/pygments/__init__.py +82 -0
  281. venv/Lib/site-packages/pip/_vendor/pygments/__main__.py +17 -0
  282. venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py +668 -0
  283. venv/Lib/site-packages/pip/_vendor/pygments/console.py +70 -0
  284. venv/Lib/site-packages/pip/_vendor/pygments/filter.py +71 -0
  285. venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py +940 -0
  286. venv/Lib/site-packages/pip/_vendor/pygments/formatter.py +124 -0
  287. venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py +158 -0
  288. venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py +23 -0
  289. venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py +108 -0
  290. venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py +170 -0
  291. venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py +989 -0
  292. venv/Lib/site-packages/pip/_vendor/pygments/formatters/img.py +645 -0
  293. venv/Lib/site-packages/pip/_vendor/pygments/formatters/irc.py +154 -0
  294. venv/Lib/site-packages/pip/_vendor/pygments/formatters/latex.py +521 -0
  295. venv/Lib/site-packages/pip/_vendor/pygments/formatters/other.py +161 -0
  296. venv/Lib/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py +83 -0
  297. venv/Lib/site-packages/pip/_vendor/pygments/formatters/rtf.py +146 -0
  298. venv/Lib/site-packages/pip/_vendor/pygments/formatters/svg.py +188 -0
  299. venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal.py +127 -0
  300. venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal256.py +338 -0
  301. venv/Lib/site-packages/pip/_vendor/pygments/lexer.py +943 -0
  302. venv/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py +362 -0
  303. venv/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py +559 -0
  304. venv/Lib/site-packages/pip/_vendor/pygments/lexers/python.py +1198 -0
  305. venv/Lib/site-packages/pip/_vendor/pygments/modeline.py +43 -0
  306. venv/Lib/site-packages/pip/_vendor/pygments/plugin.py +88 -0
  307. venv/Lib/site-packages/pip/_vendor/pygments/regexopt.py +91 -0
  308. venv/Lib/site-packages/pip/_vendor/pygments/scanner.py +104 -0
  309. venv/Lib/site-packages/pip/_vendor/pygments/sphinxext.py +217 -0
  310. venv/Lib/site-packages/pip/_vendor/pygments/style.py +197 -0
  311. venv/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py +103 -0
  312. venv/Lib/site-packages/pip/_vendor/pygments/token.py +213 -0
  313. venv/Lib/site-packages/pip/_vendor/pygments/unistring.py +153 -0
  314. venv/Lib/site-packages/pip/_vendor/pygments/util.py +330 -0
  315. venv/Lib/site-packages/pip/_vendor/pyparsing/__init__.py +322 -0
  316. venv/Lib/site-packages/pip/_vendor/pyparsing/actions.py +217 -0
  317. venv/Lib/site-packages/pip/_vendor/pyparsing/common.py +432 -0
  318. venv/Lib/site-packages/pip/_vendor/pyparsing/core.py +6115 -0
  319. venv/Lib/site-packages/pip/_vendor/pyparsing/diagram/__init__.py +656 -0
  320. venv/Lib/site-packages/pip/_vendor/pyparsing/exceptions.py +299 -0
  321. venv/Lib/site-packages/pip/_vendor/pyparsing/helpers.py +1100 -0
  322. venv/Lib/site-packages/pip/_vendor/pyparsing/results.py +796 -0
  323. venv/Lib/site-packages/pip/_vendor/pyparsing/testing.py +331 -0
  324. venv/Lib/site-packages/pip/_vendor/pyparsing/unicode.py +361 -0
  325. venv/Lib/site-packages/pip/_vendor/pyparsing/util.py +284 -0
  326. venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__init__.py +23 -0
  327. venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_compat.py +8 -0
  328. venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_impl.py +330 -0
  329. venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py +18 -0
  330. venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py +353 -0
  331. venv/Lib/site-packages/pip/_vendor/requests/__init__.py +182 -0
  332. venv/Lib/site-packages/pip/_vendor/requests/__version__.py +14 -0
  333. venv/Lib/site-packages/pip/_vendor/requests/_internal_utils.py +50 -0
  334. venv/Lib/site-packages/pip/_vendor/requests/adapters.py +538 -0
  335. venv/Lib/site-packages/pip/_vendor/requests/api.py +157 -0
  336. venv/Lib/site-packages/pip/_vendor/requests/auth.py +315 -0
  337. venv/Lib/site-packages/pip/_vendor/requests/certs.py +24 -0
  338. venv/Lib/site-packages/pip/_vendor/requests/compat.py +67 -0
  339. venv/Lib/site-packages/pip/_vendor/requests/cookies.py +561 -0
  340. venv/Lib/site-packages/pip/_vendor/requests/exceptions.py +141 -0
  341. venv/Lib/site-packages/pip/_vendor/requests/help.py +131 -0
  342. venv/Lib/site-packages/pip/_vendor/requests/hooks.py +33 -0
  343. venv/Lib/site-packages/pip/_vendor/requests/models.py +1034 -0
  344. venv/Lib/site-packages/pip/_vendor/requests/packages.py +16 -0
  345. venv/Lib/site-packages/pip/_vendor/requests/sessions.py +833 -0
  346. venv/Lib/site-packages/pip/_vendor/requests/status_codes.py +128 -0
  347. venv/Lib/site-packages/pip/_vendor/requests/structures.py +99 -0
  348. venv/Lib/site-packages/pip/_vendor/requests/utils.py +1094 -0
  349. venv/Lib/site-packages/pip/_vendor/resolvelib/__init__.py +26 -0
  350. venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__init__.py +0 -0
  351. venv/Lib/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py +6 -0
  352. venv/Lib/site-packages/pip/_vendor/resolvelib/providers.py +133 -0
  353. venv/Lib/site-packages/pip/_vendor/resolvelib/reporters.py +43 -0
  354. venv/Lib/site-packages/pip/_vendor/resolvelib/resolvers.py +547 -0
  355. venv/Lib/site-packages/pip/_vendor/resolvelib/structs.py +170 -0
  356. venv/Lib/site-packages/pip/_vendor/rich/__init__.py +177 -0
  357. venv/Lib/site-packages/pip/_vendor/rich/__main__.py +274 -0
  358. venv/Lib/site-packages/pip/_vendor/rich/_cell_widths.py +451 -0
  359. venv/Lib/site-packages/pip/_vendor/rich/_emoji_codes.py +3610 -0
  360. venv/Lib/site-packages/pip/_vendor/rich/_emoji_replace.py +32 -0
  361. venv/Lib/site-packages/pip/_vendor/rich/_export_format.py +76 -0
  362. venv/Lib/site-packages/pip/_vendor/rich/_extension.py +10 -0
  363. venv/Lib/site-packages/pip/_vendor/rich/_fileno.py +24 -0
  364. venv/Lib/site-packages/pip/_vendor/rich/_inspect.py +270 -0
  365. venv/Lib/site-packages/pip/_vendor/rich/_log_render.py +94 -0
  366. venv/Lib/site-packages/pip/_vendor/rich/_loop.py +43 -0
  367. venv/Lib/site-packages/pip/_vendor/rich/_null_file.py +69 -0
  368. venv/Lib/site-packages/pip/_vendor/rich/_palettes.py +309 -0
  369. venv/Lib/site-packages/pip/_vendor/rich/_pick.py +17 -0
  370. venv/Lib/site-packages/pip/_vendor/rich/_ratio.py +160 -0
  371. venv/Lib/site-packages/pip/_vendor/rich/_spinners.py +482 -0
  372. venv/Lib/site-packages/pip/_vendor/rich/_stack.py +16 -0
  373. venv/Lib/site-packages/pip/_vendor/rich/_timer.py +19 -0
  374. venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py +662 -0
  375. venv/Lib/site-packages/pip/_vendor/rich/_windows.py +72 -0
  376. venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py +56 -0
  377. venv/Lib/site-packages/pip/_vendor/rich/_wrap.py +56 -0
  378. venv/Lib/site-packages/pip/_vendor/rich/abc.py +33 -0
  379. venv/Lib/site-packages/pip/_vendor/rich/align.py +311 -0
  380. venv/Lib/site-packages/pip/_vendor/rich/ansi.py +240 -0
  381. venv/Lib/site-packages/pip/_vendor/rich/bar.py +94 -0
  382. venv/Lib/site-packages/pip/_vendor/rich/box.py +517 -0
  383. venv/Lib/site-packages/pip/_vendor/rich/cells.py +154 -0
  384. venv/Lib/site-packages/pip/_vendor/rich/color.py +622 -0
  385. venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py +38 -0
  386. venv/Lib/site-packages/pip/_vendor/rich/columns.py +187 -0
  387. venv/Lib/site-packages/pip/_vendor/rich/console.py +2633 -0
  388. venv/Lib/site-packages/pip/_vendor/rich/constrain.py +37 -0
  389. venv/Lib/site-packages/pip/_vendor/rich/containers.py +167 -0
  390. venv/Lib/site-packages/pip/_vendor/rich/control.py +225 -0
  391. venv/Lib/site-packages/pip/_vendor/rich/default_styles.py +190 -0
  392. venv/Lib/site-packages/pip/_vendor/rich/diagnose.py +37 -0
  393. venv/Lib/site-packages/pip/_vendor/rich/emoji.py +96 -0
  394. venv/Lib/site-packages/pip/_vendor/rich/errors.py +34 -0
  395. venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py +57 -0
  396. venv/Lib/site-packages/pip/_vendor/rich/filesize.py +89 -0
  397. venv/Lib/site-packages/pip/_vendor/rich/highlighter.py +232 -0
  398. venv/Lib/site-packages/pip/_vendor/rich/json.py +140 -0
  399. venv/Lib/site-packages/pip/_vendor/rich/jupyter.py +101 -0
  400. venv/Lib/site-packages/pip/_vendor/rich/layout.py +443 -0
  401. venv/Lib/site-packages/pip/_vendor/rich/live.py +375 -0
  402. venv/Lib/site-packages/pip/_vendor/rich/live_render.py +113 -0
  403. venv/Lib/site-packages/pip/_vendor/rich/logging.py +289 -0
  404. venv/Lib/site-packages/pip/_vendor/rich/markup.py +246 -0
  405. venv/Lib/site-packages/pip/_vendor/rich/measure.py +151 -0
  406. venv/Lib/site-packages/pip/_vendor/rich/padding.py +141 -0
  407. venv/Lib/site-packages/pip/_vendor/rich/pager.py +34 -0
  408. venv/Lib/site-packages/pip/_vendor/rich/palette.py +100 -0
  409. venv/Lib/site-packages/pip/_vendor/rich/panel.py +308 -0
  410. venv/Lib/site-packages/pip/_vendor/rich/pretty.py +994 -0
  411. venv/Lib/site-packages/pip/_vendor/rich/progress.py +1702 -0
  412. venv/Lib/site-packages/pip/_vendor/rich/progress_bar.py +224 -0
  413. venv/Lib/site-packages/pip/_vendor/rich/prompt.py +376 -0
  414. venv/Lib/site-packages/pip/_vendor/rich/protocol.py +42 -0
  415. venv/Lib/site-packages/pip/_vendor/rich/region.py +10 -0
  416. venv/Lib/site-packages/pip/_vendor/rich/repr.py +149 -0
  417. venv/Lib/site-packages/pip/_vendor/rich/rule.py +130 -0
  418. venv/Lib/site-packages/pip/_vendor/rich/scope.py +86 -0
  419. venv/Lib/site-packages/pip/_vendor/rich/screen.py +54 -0
  420. venv/Lib/site-packages/pip/_vendor/rich/segment.py +739 -0
  421. venv/Lib/site-packages/pip/_vendor/rich/spinner.py +137 -0
  422. venv/Lib/site-packages/pip/_vendor/rich/status.py +132 -0
  423. venv/Lib/site-packages/pip/_vendor/rich/style.py +796 -0
  424. venv/Lib/site-packages/pip/_vendor/rich/styled.py +42 -0
  425. venv/Lib/site-packages/pip/_vendor/rich/syntax.py +948 -0
  426. venv/Lib/site-packages/pip/_vendor/rich/table.py +1002 -0
  427. venv/Lib/site-packages/pip/_vendor/rich/terminal_theme.py +153 -0
  428. venv/Lib/site-packages/pip/_vendor/rich/text.py +1307 -0
  429. venv/Lib/site-packages/pip/_vendor/rich/theme.py +115 -0
  430. venv/Lib/site-packages/pip/_vendor/rich/themes.py +5 -0
  431. venv/Lib/site-packages/pip/_vendor/rich/traceback.py +756 -0
  432. venv/Lib/site-packages/pip/_vendor/rich/tree.py +251 -0
  433. venv/Lib/site-packages/pip/_vendor/six.py +998 -0
  434. venv/Lib/site-packages/pip/_vendor/tenacity/__init__.py +608 -0
  435. venv/Lib/site-packages/pip/_vendor/tenacity/_asyncio.py +94 -0
  436. venv/Lib/site-packages/pip/_vendor/tenacity/_utils.py +76 -0
  437. venv/Lib/site-packages/pip/_vendor/tenacity/after.py +51 -0
  438. venv/Lib/site-packages/pip/_vendor/tenacity/before.py +46 -0
  439. venv/Lib/site-packages/pip/_vendor/tenacity/before_sleep.py +71 -0
  440. venv/Lib/site-packages/pip/_vendor/tenacity/nap.py +43 -0
  441. venv/Lib/site-packages/pip/_vendor/tenacity/retry.py +272 -0
  442. venv/Lib/site-packages/pip/_vendor/tenacity/stop.py +103 -0
  443. venv/Lib/site-packages/pip/_vendor/tenacity/tornadoweb.py +59 -0
  444. venv/Lib/site-packages/pip/_vendor/tenacity/wait.py +228 -0
  445. venv/Lib/site-packages/pip/_vendor/tomli/__init__.py +11 -0
  446. venv/Lib/site-packages/pip/_vendor/tomli/_parser.py +691 -0
  447. venv/Lib/site-packages/pip/_vendor/tomli/_re.py +107 -0
  448. venv/Lib/site-packages/pip/_vendor/tomli/_types.py +10 -0
  449. venv/Lib/site-packages/pip/_vendor/typing_extensions.py +3072 -0
  450. venv/Lib/site-packages/pip/_vendor/urllib3/__init__.py +102 -0
  451. venv/Lib/site-packages/pip/_vendor/urllib3/_collections.py +337 -0
  452. venv/Lib/site-packages/pip/_vendor/urllib3/_version.py +2 -0
  453. venv/Lib/site-packages/pip/_vendor/urllib3/connection.py +572 -0
  454. venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py +1132 -0
  455. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py +0 -0
  456. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py +36 -0
  457. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py +0 -0
  458. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py +519 -0
  459. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py +397 -0
  460. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py +314 -0
  461. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py +130 -0
  462. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py +518 -0
  463. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py +921 -0
  464. venv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py +216 -0
  465. venv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py +323 -0
  466. venv/Lib/site-packages/pip/_vendor/urllib3/fields.py +274 -0
  467. venv/Lib/site-packages/pip/_vendor/urllib3/filepost.py +98 -0
  468. venv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py +0 -0
  469. venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py +0 -0
  470. venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py +51 -0
  471. venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py +155 -0
  472. venv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py +1076 -0
  473. venv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py +537 -0
  474. venv/Lib/site-packages/pip/_vendor/urllib3/request.py +170 -0
  475. venv/Lib/site-packages/pip/_vendor/urllib3/response.py +879 -0
  476. venv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py +49 -0
  477. venv/Lib/site-packages/pip/_vendor/urllib3/util/connection.py +149 -0
  478. venv/Lib/site-packages/pip/_vendor/urllib3/util/proxy.py +57 -0
  479. venv/Lib/site-packages/pip/_vendor/urllib3/util/queue.py +22 -0
  480. venv/Lib/site-packages/pip/_vendor/urllib3/util/request.py +137 -0
  481. venv/Lib/site-packages/pip/_vendor/urllib3/util/response.py +107 -0
  482. venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py +620 -0
  483. venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py +495 -0
  484. venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py +159 -0
  485. venv/Lib/site-packages/pip/_vendor/urllib3/util/ssltransport.py +221 -0
  486. venv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py +271 -0
  487. venv/Lib/site-packages/pip/_vendor/urllib3/util/url.py +435 -0
  488. venv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py +152 -0
  489. venv/Lib/site-packages/pip/_vendor/webencodings/__init__.py +342 -0
  490. venv/Lib/site-packages/pip/_vendor/webencodings/labels.py +231 -0
  491. venv/Lib/site-packages/pip/_vendor/webencodings/mklabels.py +59 -0
  492. venv/Lib/site-packages/pip/_vendor/webencodings/tests.py +153 -0
  493. venv/Lib/site-packages/pip/_vendor/webencodings/x_user_defined.py +325 -0
  494. venv/Lib/site-packages/pip/py.typed +4 -0
  495. venv/Lib/site-packages/pkg_resources/__init__.py +3296 -0
  496. venv/Lib/site-packages/pkg_resources/_vendor/__init__.py +0 -0
  497. venv/Lib/site-packages/pkg_resources/_vendor/appdirs.py +608 -0
  498. venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__init__.py +36 -0
  499. venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_adapters.py +170 -0
  500. venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_common.py +104 -0
  501. venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_compat.py +98 -0
  502. venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_itertools.py +35 -0
  503. venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_legacy.py +121 -0
  504. venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/abc.py +137 -0
  505. venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/readers.py +122 -0
  506. venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/simple.py +116 -0
  507. venv/Lib/site-packages/pkg_resources/_vendor/jaraco/__init__.py +0 -0
  508. venv/Lib/site-packages/pkg_resources/_vendor/jaraco/context.py +213 -0
  509. venv/Lib/site-packages/pkg_resources/_vendor/jaraco/functools.py +525 -0
  510. venv/Lib/site-packages/pkg_resources/_vendor/jaraco/text/__init__.py +599 -0
  511. venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/__init__.py +4 -0
  512. venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/more.py +4316 -0
  513. venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/recipes.py +698 -0
  514. venv/Lib/site-packages/pkg_resources/_vendor/packaging/__about__.py +26 -0
  515. venv/Lib/site-packages/pkg_resources/_vendor/packaging/__init__.py +25 -0
  516. venv/Lib/site-packages/pkg_resources/_vendor/packaging/_manylinux.py +301 -0
  517. venv/Lib/site-packages/pkg_resources/_vendor/packaging/_musllinux.py +136 -0
  518. venv/Lib/site-packages/pkg_resources/_vendor/packaging/_structures.py +61 -0
  519. venv/Lib/site-packages/pkg_resources/_vendor/packaging/markers.py +304 -0
  520. venv/Lib/site-packages/pkg_resources/_vendor/packaging/requirements.py +146 -0
  521. venv/Lib/site-packages/pkg_resources/_vendor/packaging/specifiers.py +802 -0
  522. venv/Lib/site-packages/pkg_resources/_vendor/packaging/tags.py +487 -0
  523. venv/Lib/site-packages/pkg_resources/_vendor/packaging/utils.py +136 -0
  524. venv/Lib/site-packages/pkg_resources/_vendor/packaging/version.py +504 -0
  525. venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/__init__.py +331 -0
  526. venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/actions.py +207 -0
  527. venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/common.py +424 -0
  528. venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/core.py +5814 -0
  529. venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/diagram/__init__.py +642 -0
  530. venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/exceptions.py +267 -0
  531. venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/helpers.py +1088 -0
  532. venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/results.py +760 -0
  533. venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/testing.py +331 -0
  534. venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/unicode.py +352 -0
  535. venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/util.py +235 -0
  536. venv/Lib/site-packages/pkg_resources/_vendor/zipp.py +329 -0
  537. venv/Lib/site-packages/pkg_resources/extern/__init__.py +76 -0
  538. venv/Lib/site-packages/setuptools/__init__.py +247 -0
  539. venv/Lib/site-packages/setuptools/_deprecation_warning.py +7 -0
  540. venv/Lib/site-packages/setuptools/_distutils/__init__.py +24 -0
  541. venv/Lib/site-packages/setuptools/_distutils/_collections.py +56 -0
  542. venv/Lib/site-packages/setuptools/_distutils/_functools.py +20 -0
  543. venv/Lib/site-packages/setuptools/_distutils/_macos_compat.py +12 -0
  544. venv/Lib/site-packages/setuptools/_distutils/_msvccompiler.py +572 -0
  545. venv/Lib/site-packages/setuptools/_distutils/archive_util.py +280 -0
  546. venv/Lib/site-packages/setuptools/_distutils/bcppcompiler.py +408 -0
  547. venv/Lib/site-packages/setuptools/_distutils/ccompiler.py +1220 -0
  548. venv/Lib/site-packages/setuptools/_distutils/cmd.py +436 -0
  549. venv/Lib/site-packages/setuptools/_distutils/command/__init__.py +25 -0
  550. venv/Lib/site-packages/setuptools/_distutils/command/_framework_compat.py +55 -0
  551. venv/Lib/site-packages/setuptools/_distutils/command/bdist.py +157 -0
  552. venv/Lib/site-packages/setuptools/_distutils/command/bdist_dumb.py +144 -0
  553. venv/Lib/site-packages/setuptools/_distutils/command/bdist_rpm.py +615 -0
  554. venv/Lib/site-packages/setuptools/_distutils/command/build.py +153 -0
  555. venv/Lib/site-packages/setuptools/_distutils/command/build_clib.py +208 -0
  556. venv/Lib/site-packages/setuptools/_distutils/command/build_ext.py +787 -0
  557. venv/Lib/site-packages/setuptools/_distutils/command/build_py.py +407 -0
  558. venv/Lib/site-packages/setuptools/_distutils/command/build_scripts.py +173 -0
  559. venv/Lib/site-packages/setuptools/_distutils/command/check.py +151 -0
  560. venv/Lib/site-packages/setuptools/_distutils/command/clean.py +76 -0
  561. venv/Lib/site-packages/setuptools/_distutils/command/config.py +377 -0
  562. venv/Lib/site-packages/setuptools/_distutils/command/install.py +814 -0
  563. venv/Lib/site-packages/setuptools/_distutils/command/install_data.py +84 -0
  564. venv/Lib/site-packages/setuptools/_distutils/command/install_egg_info.py +91 -0
  565. venv/Lib/site-packages/setuptools/_distutils/command/install_headers.py +45 -0
  566. venv/Lib/site-packages/setuptools/_distutils/command/install_lib.py +238 -0
  567. venv/Lib/site-packages/setuptools/_distutils/command/install_scripts.py +61 -0
  568. venv/Lib/site-packages/setuptools/_distutils/command/py37compat.py +31 -0
  569. venv/Lib/site-packages/setuptools/_distutils/command/register.py +319 -0
  570. venv/Lib/site-packages/setuptools/_distutils/command/sdist.py +531 -0
  571. venv/Lib/site-packages/setuptools/_distutils/command/upload.py +205 -0
  572. venv/Lib/site-packages/setuptools/_distutils/config.py +139 -0
  573. venv/Lib/site-packages/setuptools/_distutils/core.py +291 -0
  574. venv/Lib/site-packages/setuptools/_distutils/cygwinccompiler.py +364 -0
  575. venv/Lib/site-packages/setuptools/_distutils/debug.py +5 -0
  576. venv/Lib/site-packages/setuptools/_distutils/dep_util.py +96 -0
  577. venv/Lib/site-packages/setuptools/_distutils/dir_util.py +243 -0
  578. venv/Lib/site-packages/setuptools/_distutils/dist.py +1286 -0
  579. venv/Lib/site-packages/setuptools/_distutils/errors.py +127 -0
  580. venv/Lib/site-packages/setuptools/_distutils/extension.py +248 -0
  581. venv/Lib/site-packages/setuptools/_distutils/fancy_getopt.py +470 -0
  582. venv/Lib/site-packages/setuptools/_distutils/file_util.py +249 -0
  583. venv/Lib/site-packages/setuptools/_distutils/filelist.py +371 -0
  584. venv/Lib/site-packages/setuptools/_distutils/log.py +80 -0
  585. venv/Lib/site-packages/setuptools/_distutils/msvc9compiler.py +832 -0
  586. venv/Lib/site-packages/setuptools/_distutils/msvccompiler.py +695 -0
  587. venv/Lib/site-packages/setuptools/_distutils/py38compat.py +8 -0
  588. venv/Lib/site-packages/setuptools/_distutils/py39compat.py +22 -0
  589. venv/Lib/site-packages/setuptools/_distutils/spawn.py +109 -0
  590. venv/Lib/site-packages/setuptools/_distutils/sysconfig.py +558 -0
  591. venv/Lib/site-packages/setuptools/_distutils/text_file.py +287 -0
  592. venv/Lib/site-packages/setuptools/_distutils/unixccompiler.py +401 -0
  593. venv/Lib/site-packages/setuptools/_distutils/util.py +513 -0
  594. venv/Lib/site-packages/setuptools/_distutils/version.py +358 -0
  595. venv/Lib/site-packages/setuptools/_distutils/versionpredicate.py +175 -0
  596. venv/Lib/site-packages/setuptools/_entry_points.py +86 -0
  597. venv/Lib/site-packages/setuptools/_imp.py +82 -0
  598. venv/Lib/site-packages/setuptools/_importlib.py +47 -0
  599. venv/Lib/site-packages/setuptools/_itertools.py +23 -0
  600. venv/Lib/site-packages/setuptools/_path.py +29 -0
  601. venv/Lib/site-packages/setuptools/_reqs.py +19 -0
  602. venv/Lib/site-packages/setuptools/_vendor/__init__.py +0 -0
  603. venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__init__.py +1047 -0
  604. venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_adapters.py +68 -0
  605. venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_collections.py +30 -0
  606. venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_compat.py +71 -0
  607. venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_functools.py +104 -0
  608. venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_itertools.py +73 -0
  609. venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_meta.py +48 -0
  610. venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_text.py +99 -0
  611. venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__init__.py +36 -0
  612. venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_adapters.py +170 -0
  613. venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_common.py +104 -0
  614. venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_compat.py +98 -0
  615. venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_itertools.py +35 -0
  616. venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_legacy.py +121 -0
  617. venv/Lib/site-packages/setuptools/_vendor/importlib_resources/abc.py +137 -0
  618. venv/Lib/site-packages/setuptools/_vendor/importlib_resources/readers.py +122 -0
  619. venv/Lib/site-packages/setuptools/_vendor/importlib_resources/simple.py +116 -0
  620. venv/Lib/site-packages/setuptools/_vendor/jaraco/__init__.py +0 -0
  621. venv/Lib/site-packages/setuptools/_vendor/jaraco/context.py +213 -0
  622. venv/Lib/site-packages/setuptools/_vendor/jaraco/functools.py +525 -0
  623. venv/Lib/site-packages/setuptools/_vendor/jaraco/text/__init__.py +599 -0
  624. venv/Lib/site-packages/setuptools/_vendor/more_itertools/__init__.py +4 -0
  625. venv/Lib/site-packages/setuptools/_vendor/more_itertools/more.py +3824 -0
  626. venv/Lib/site-packages/setuptools/_vendor/more_itertools/recipes.py +620 -0
  627. venv/Lib/site-packages/setuptools/_vendor/ordered_set.py +488 -0
  628. venv/Lib/site-packages/setuptools/_vendor/packaging/__about__.py +26 -0
  629. venv/Lib/site-packages/setuptools/_vendor/packaging/__init__.py +25 -0
  630. venv/Lib/site-packages/setuptools/_vendor/packaging/_manylinux.py +301 -0
  631. venv/Lib/site-packages/setuptools/_vendor/packaging/_musllinux.py +136 -0
  632. venv/Lib/site-packages/setuptools/_vendor/packaging/_structures.py +61 -0
  633. venv/Lib/site-packages/setuptools/_vendor/packaging/markers.py +304 -0
  634. venv/Lib/site-packages/setuptools/_vendor/packaging/requirements.py +146 -0
  635. venv/Lib/site-packages/setuptools/_vendor/packaging/specifiers.py +802 -0
  636. venv/Lib/site-packages/setuptools/_vendor/packaging/tags.py +487 -0
  637. venv/Lib/site-packages/setuptools/_vendor/packaging/utils.py +136 -0
  638. venv/Lib/site-packages/setuptools/_vendor/packaging/version.py +504 -0
  639. venv/Lib/site-packages/setuptools/_vendor/pyparsing/__init__.py +331 -0
  640. venv/Lib/site-packages/setuptools/_vendor/pyparsing/actions.py +207 -0
  641. venv/Lib/site-packages/setuptools/_vendor/pyparsing/common.py +424 -0
  642. venv/Lib/site-packages/setuptools/_vendor/pyparsing/core.py +5814 -0
  643. venv/Lib/site-packages/setuptools/_vendor/pyparsing/diagram/__init__.py +642 -0
  644. venv/Lib/site-packages/setuptools/_vendor/pyparsing/exceptions.py +267 -0
  645. venv/Lib/site-packages/setuptools/_vendor/pyparsing/helpers.py +1088 -0
  646. venv/Lib/site-packages/setuptools/_vendor/pyparsing/results.py +760 -0
  647. venv/Lib/site-packages/setuptools/_vendor/pyparsing/testing.py +331 -0
  648. venv/Lib/site-packages/setuptools/_vendor/pyparsing/unicode.py +352 -0
  649. venv/Lib/site-packages/setuptools/_vendor/pyparsing/util.py +235 -0
  650. venv/Lib/site-packages/setuptools/_vendor/tomli/__init__.py +11 -0
  651. venv/Lib/site-packages/setuptools/_vendor/tomli/_parser.py +691 -0
  652. venv/Lib/site-packages/setuptools/_vendor/tomli/_re.py +107 -0
  653. venv/Lib/site-packages/setuptools/_vendor/tomli/_types.py +10 -0
  654. venv/Lib/site-packages/setuptools/_vendor/typing_extensions.py +2296 -0
  655. venv/Lib/site-packages/setuptools/_vendor/zipp.py +329 -0
  656. venv/Lib/site-packages/setuptools/archive_util.py +213 -0
  657. venv/Lib/site-packages/setuptools/build_meta.py +511 -0
  658. venv/Lib/site-packages/setuptools/command/__init__.py +12 -0
  659. venv/Lib/site-packages/setuptools/command/alias.py +78 -0
  660. venv/Lib/site-packages/setuptools/command/bdist_egg.py +457 -0
  661. venv/Lib/site-packages/setuptools/command/bdist_rpm.py +40 -0
  662. venv/Lib/site-packages/setuptools/command/build.py +146 -0
  663. venv/Lib/site-packages/setuptools/command/build_clib.py +101 -0
  664. venv/Lib/site-packages/setuptools/command/build_ext.py +383 -0
  665. venv/Lib/site-packages/setuptools/command/build_py.py +368 -0
  666. venv/Lib/site-packages/setuptools/command/develop.py +193 -0
  667. venv/Lib/site-packages/setuptools/command/dist_info.py +142 -0
  668. venv/Lib/site-packages/setuptools/command/easy_install.py +2312 -0
  669. venv/Lib/site-packages/setuptools/command/editable_wheel.py +844 -0
  670. venv/Lib/site-packages/setuptools/command/egg_info.py +763 -0
  671. venv/Lib/site-packages/setuptools/command/install.py +139 -0
  672. venv/Lib/site-packages/setuptools/command/install_egg_info.py +63 -0
  673. venv/Lib/site-packages/setuptools/command/install_lib.py +122 -0
  674. venv/Lib/site-packages/setuptools/command/install_scripts.py +70 -0
  675. venv/Lib/site-packages/setuptools/command/py36compat.py +134 -0
  676. venv/Lib/site-packages/setuptools/command/register.py +18 -0
  677. venv/Lib/site-packages/setuptools/command/rotate.py +64 -0
  678. venv/Lib/site-packages/setuptools/command/saveopts.py +22 -0
  679. venv/Lib/site-packages/setuptools/command/sdist.py +210 -0
  680. venv/Lib/site-packages/setuptools/command/setopt.py +149 -0
  681. venv/Lib/site-packages/setuptools/command/test.py +251 -0
  682. venv/Lib/site-packages/setuptools/command/upload.py +17 -0
  683. venv/Lib/site-packages/setuptools/command/upload_docs.py +213 -0
  684. venv/Lib/site-packages/setuptools/config/__init__.py +35 -0
  685. venv/Lib/site-packages/setuptools/config/_apply_pyprojecttoml.py +377 -0
  686. venv/Lib/site-packages/setuptools/config/_validate_pyproject/__init__.py +34 -0
  687. venv/Lib/site-packages/setuptools/config/_validate_pyproject/error_reporting.py +318 -0
  688. venv/Lib/site-packages/setuptools/config/_validate_pyproject/extra_validations.py +36 -0
  689. venv/Lib/site-packages/setuptools/config/_validate_pyproject/fastjsonschema_exceptions.py +51 -0
  690. venv/Lib/site-packages/setuptools/config/_validate_pyproject/fastjsonschema_validations.py +1035 -0
  691. venv/Lib/site-packages/setuptools/config/_validate_pyproject/formats.py +259 -0
  692. venv/Lib/site-packages/setuptools/config/expand.py +462 -0
  693. venv/Lib/site-packages/setuptools/config/pyprojecttoml.py +493 -0
  694. venv/Lib/site-packages/setuptools/config/setupcfg.py +762 -0
  695. venv/Lib/site-packages/setuptools/dep_util.py +25 -0
  696. venv/Lib/site-packages/setuptools/depends.py +176 -0
  697. venv/Lib/site-packages/setuptools/discovery.py +600 -0
  698. venv/Lib/site-packages/setuptools/dist.py +1222 -0
  699. venv/Lib/site-packages/setuptools/errors.py +58 -0
  700. venv/Lib/site-packages/setuptools/extension.py +148 -0
  701. venv/Lib/site-packages/setuptools/extern/__init__.py +76 -0
  702. venv/Lib/site-packages/setuptools/glob.py +167 -0
  703. venv/Lib/site-packages/setuptools/installer.py +104 -0
  704. venv/Lib/site-packages/setuptools/launch.py +36 -0
  705. venv/Lib/site-packages/setuptools/logging.py +36 -0
  706. venv/Lib/site-packages/setuptools/monkey.py +165 -0
  707. venv/Lib/site-packages/setuptools/msvc.py +1703 -0
  708. venv/Lib/site-packages/setuptools/namespaces.py +107 -0
  709. venv/Lib/site-packages/setuptools/package_index.py +1126 -0
  710. venv/Lib/site-packages/setuptools/py34compat.py +13 -0
  711. venv/Lib/site-packages/setuptools/sandbox.py +530 -0
  712. venv/Lib/site-packages/setuptools/unicode_utils.py +42 -0
  713. venv/Lib/site-packages/setuptools/version.py +6 -0
  714. venv/Lib/site-packages/setuptools/wheel.py +222 -0
  715. venv/Lib/site-packages/setuptools/windows_support.py +29 -0
  716. xplia/__init__.py +72 -0
  717. xplia/api/__init__.py +432 -0
  718. xplia/api/fastapi_app.py +453 -0
  719. xplia/cli.py +321 -0
  720. xplia/compliance/__init__.py +39 -0
  721. xplia/compliance/ai_act.py +538 -0
  722. xplia/compliance/compliance_checker.py +511 -0
  723. xplia/compliance/compliance_report.py +236 -0
  724. xplia/compliance/expert_review/__init__.py +18 -0
  725. xplia/compliance/expert_review/evaluation_criteria.py +209 -0
  726. xplia/compliance/expert_review/integration.py +270 -0
  727. xplia/compliance/expert_review/trust_expert_evaluator.py +379 -0
  728. xplia/compliance/explanation_rights.py +45 -0
  729. xplia/compliance/formatters/__init__.py +35 -0
  730. xplia/compliance/formatters/csv_formatter.py +179 -0
  731. xplia/compliance/formatters/html_formatter.py +689 -0
  732. xplia/compliance/formatters/html_trust_formatter.py +147 -0
  733. xplia/compliance/formatters/json_formatter.py +107 -0
  734. xplia/compliance/formatters/pdf_formatter.py +641 -0
  735. xplia/compliance/formatters/pdf_trust_formatter.py +309 -0
  736. xplia/compliance/formatters/trust_formatter_mixin.py +267 -0
  737. xplia/compliance/formatters/xml_formatter.py +173 -0
  738. xplia/compliance/gdpr.py +803 -0
  739. xplia/compliance/hipaa.py +134 -0
  740. xplia/compliance/report_base.py +205 -0
  741. xplia/compliance/report_generator.py +820 -0
  742. xplia/compliance/translations.py +299 -0
  743. xplia/core/__init__.py +98 -0
  744. xplia/core/base.py +391 -0
  745. xplia/core/config.py +297 -0
  746. xplia/core/factory.py +416 -0
  747. xplia/core/model_adapters/__init__.py +47 -0
  748. xplia/core/model_adapters/base.py +160 -0
  749. xplia/core/model_adapters/pytorch_adapter.py +339 -0
  750. xplia/core/model_adapters/sklearn_adapter.py +215 -0
  751. xplia/core/model_adapters/tensorflow_adapter.py +280 -0
  752. xplia/core/model_adapters/xgboost_adapter.py +295 -0
  753. xplia/core/optimizations.py +322 -0
  754. xplia/core/performance/__init__.py +57 -0
  755. xplia/core/performance/cache_manager.py +502 -0
  756. xplia/core/performance/memory_optimizer.py +465 -0
  757. xplia/core/performance/parallel_executor.py +327 -0
  758. xplia/core/registry.py +1234 -0
  759. xplia/explainers/__init__.py +70 -0
  760. xplia/explainers/__init__updated.py +62 -0
  761. xplia/explainers/adaptive/__init__.py +24 -0
  762. xplia/explainers/adaptive/explainer_selector.py +405 -0
  763. xplia/explainers/adaptive/explanation_quality.py +395 -0
  764. xplia/explainers/adaptive/fusion_strategies.py +297 -0
  765. xplia/explainers/adaptive/meta_explainer.py +320 -0
  766. xplia/explainers/adversarial/__init__.py +21 -0
  767. xplia/explainers/adversarial/adversarial_xai.py +678 -0
  768. xplia/explainers/anchor_explainer.py +1769 -0
  769. xplia/explainers/attention_explainer.py +996 -0
  770. xplia/explainers/bayesian/__init__.py +8 -0
  771. xplia/explainers/bayesian/bayesian_explainer.py +127 -0
  772. xplia/explainers/bias/__init__.py +17 -0
  773. xplia/explainers/bias/advanced_bias_detection.py +934 -0
  774. xplia/explainers/calibration/__init__.py +26 -0
  775. xplia/explainers/calibration/audience_adapter.py +376 -0
  776. xplia/explainers/calibration/audience_profiles.py +372 -0
  777. xplia/explainers/calibration/calibration_metrics.py +299 -0
  778. xplia/explainers/calibration/explanation_calibrator.py +460 -0
  779. xplia/explainers/causal/__init__.py +19 -0
  780. xplia/explainers/causal/causal_inference.py +669 -0
  781. xplia/explainers/certified/__init__.py +21 -0
  782. xplia/explainers/certified/certified_explanations.py +619 -0
  783. xplia/explainers/continual/__init__.py +8 -0
  784. xplia/explainers/continual/continual_explainer.py +102 -0
  785. xplia/explainers/counterfactual_explainer.py +804 -0
  786. xplia/explainers/counterfactuals/__init__.py +17 -0
  787. xplia/explainers/counterfactuals/advanced_counterfactuals.py +259 -0
  788. xplia/explainers/expert_evaluator.py +538 -0
  789. xplia/explainers/feature_importance_explainer.py +376 -0
  790. xplia/explainers/federated/__init__.py +17 -0
  791. xplia/explainers/federated/federated_xai.py +664 -0
  792. xplia/explainers/generative/__init__.py +15 -0
  793. xplia/explainers/generative/generative_explainer.py +243 -0
  794. xplia/explainers/gradient_explainer.py +3590 -0
  795. xplia/explainers/graph/__init__.py +26 -0
  796. xplia/explainers/graph/gnn_explainer.py +638 -0
  797. xplia/explainers/graph/molecular_explainer.py +438 -0
  798. xplia/explainers/lime_explainer.py +1580 -0
  799. xplia/explainers/llm/__init__.py +23 -0
  800. xplia/explainers/llm/llm_explainability.py +737 -0
  801. xplia/explainers/metalearning/__init__.py +15 -0
  802. xplia/explainers/metalearning/metalearning_explainer.py +276 -0
  803. xplia/explainers/moe/__init__.py +8 -0
  804. xplia/explainers/moe/moe_explainer.py +108 -0
  805. xplia/explainers/multimodal/__init__.py +30 -0
  806. xplia/explainers/multimodal/base.py +262 -0
  807. xplia/explainers/multimodal/diffusion_explainer.py +608 -0
  808. xplia/explainers/multimodal/foundation_model_explainer.py +323 -0
  809. xplia/explainers/multimodal/registry.py +139 -0
  810. xplia/explainers/multimodal/text_image_explainer.py +381 -0
  811. xplia/explainers/multimodal/vision_language_explainer.py +608 -0
  812. xplia/explainers/nas/__init__.py +5 -0
  813. xplia/explainers/nas/nas_explainer.py +65 -0
  814. xplia/explainers/neuralodes/__init__.py +5 -0
  815. xplia/explainers/neuralodes/neuralode_explainer.py +64 -0
  816. xplia/explainers/neurosymbolic/__init__.py +8 -0
  817. xplia/explainers/neurosymbolic/neurosymbolic_explainer.py +97 -0
  818. xplia/explainers/partial_dependence_explainer.py +509 -0
  819. xplia/explainers/privacy/__init__.py +21 -0
  820. xplia/explainers/privacy/differential_privacy_xai.py +624 -0
  821. xplia/explainers/quantum/__init__.py +5 -0
  822. xplia/explainers/quantum/quantum_explainer.py +79 -0
  823. xplia/explainers/recommender/__init__.py +8 -0
  824. xplia/explainers/recommender/recsys_explainer.py +124 -0
  825. xplia/explainers/reinforcement/__init__.py +15 -0
  826. xplia/explainers/reinforcement/rl_explainer.py +173 -0
  827. xplia/explainers/shap_explainer.py +2238 -0
  828. xplia/explainers/streaming/__init__.py +19 -0
  829. xplia/explainers/streaming/streaming_xai.py +703 -0
  830. xplia/explainers/timeseries/__init__.py +15 -0
  831. xplia/explainers/timeseries/timeseries_explainer.py +252 -0
  832. xplia/explainers/trust/__init__.py +24 -0
  833. xplia/explainers/trust/confidence_report.py +368 -0
  834. xplia/explainers/trust/fairwashing.py +489 -0
  835. xplia/explainers/trust/uncertainty.py +453 -0
  836. xplia/explainers/unified_explainer.py +566 -0
  837. xplia/explainers/unified_explainer_utils.py +309 -0
  838. xplia/integrations/__init__.py +3 -0
  839. xplia/integrations/mlflow_integration.py +331 -0
  840. xplia/integrations/wandb_integration.py +375 -0
  841. xplia/plugins/__init__.py +36 -0
  842. xplia/plugins/example_visualizer.py +11 -0
  843. xplia/utils/__init__.py +18 -0
  844. xplia/utils/performance.py +119 -0
  845. xplia/utils/validation.py +109 -0
  846. xplia/visualizations/__init__.py +31 -0
  847. xplia/visualizations/base.py +256 -0
  848. xplia/visualizations/boxplot_chart.py +224 -0
  849. xplia/visualizations/charts_impl.py +65 -0
  850. xplia/visualizations/gauge_chart.py +211 -0
  851. xplia/visualizations/gradient_viz.py +117 -0
  852. xplia/visualizations/heatmap_chart.py +173 -0
  853. xplia/visualizations/histogram_chart.py +176 -0
  854. xplia/visualizations/line_chart.py +100 -0
  855. xplia/visualizations/pie_chart.py +134 -0
  856. xplia/visualizations/radar_chart.py +154 -0
  857. xplia/visualizations/registry.py +76 -0
  858. xplia/visualizations/sankey_chart.py +190 -0
  859. xplia/visualizations/scatter_chart.py +252 -0
  860. xplia/visualizations/table_chart.py +263 -0
  861. xplia/visualizations/treemap_chart.py +216 -0
  862. xplia/visualizations.py +535 -0
  863. xplia/visualizers/__init__.py +87 -0
  864. xplia/visualizers/base_visualizer.py +294 -0
  865. xplia-1.0.1.dist-info/METADATA +685 -0
  866. xplia-1.0.1.dist-info/RECORD +870 -0
  867. xplia-1.0.1.dist-info/WHEEL +5 -0
  868. xplia-1.0.1.dist-info/entry_points.txt +2 -0
  869. xplia-1.0.1.dist-info/licenses/LICENSE +21 -0
  870. xplia-1.0.1.dist-info/top_level.txt +2 -0
@@ -0,0 +1,1580 @@
1
+ """
2
+ LIME Explainer pour XPLIA
3
+ ========================
4
+
5
+ Ce module implémente l'intégration des explications LIME (Local Interpretable Model-agnostic Explanations)
6
+ dans le framework XPLIA. Cette technique permet d'expliquer les prédictions individuelles
7
+ en approximant localement le comportement du modèle avec un modèle interprétable.
8
+ """
9
+
10
+ import logging
11
+ from typing import Any, Dict, List, Optional, Tuple, Union
12
+
13
+ import numpy as np
14
+ import pandas as pd
15
+
16
+ from ..core.base import (AudienceLevel, ExplainerBase, ExplainabilityMethod,
17
+ ExplanationResult, FeatureImportance, ModelMetadata)
18
+ from ..core.registry import register_explainer
19
+
20
+
21
+ @register_explainer
22
+ class LimeExplainer(ExplainerBase):
23
+ """
24
+ Explainer basé sur LIME (Local Interpretable Model-agnostic Explanations).
25
+
26
+ Cette classe fournit des explications de modèles basées sur l'approximation locale
27
+ du comportement du modèle par un modèle interprétable (généralement linéaire).
28
+
29
+ Caractéristiques principales:
30
+ - Support de différents types de données (tabular, text, image)
31
+ - Approximation locale par modèles interprétables
32
+ - Visualisations adaptées au niveau d'audience (technique, business, public)
33
+ - Optimisations de performance pour les grands jeux de données
34
+ """
35
+
36
+ def __init__(self, model, **kwargs):
37
+ """
38
+ Initialise l'explainer LIME.
39
+
40
+ Args:
41
+ model: Modèle à expliquer
42
+ **kwargs: Paramètres additionnels
43
+ data_type: Type de données ('tabular', 'text', 'image')
44
+ feature_names: Noms des caractéristiques
45
+ class_names: Noms des classes
46
+ categorical_features: Indices des caractéristiques catégorielles
47
+ categorical_names: Noms des valeurs des caractéristiques catégorielles
48
+ kernel_width: Largeur du noyau pour la fonction de similarité
49
+ verbose: Niveau de verbosité
50
+ """
51
+ super().__init__(model, **kwargs)
52
+ self._method = ExplainabilityMethod.LIME
53
+ self._supported_model_types = [
54
+ 'RandomForestClassifier', 'RandomForestRegressor',
55
+ 'GradientBoostingClassifier', 'GradientBoostingRegressor',
56
+ 'XGBClassifier', 'XGBRegressor',
57
+ 'LGBMClassifier', 'LGBMRegressor',
58
+ 'CatBoostClassifier', 'CatBoostRegressor',
59
+ 'LogisticRegression', 'LinearRegression',
60
+ 'SVC', 'SVR',
61
+ 'Sequential', 'Model', # Keras
62
+ 'Module' # PyTorch
63
+ ]
64
+
65
+ # Paramètres LIME
66
+ self._data_type = kwargs.get('data_type', 'tabular')
67
+ self._feature_names = kwargs.get('feature_names', None)
68
+ self._class_names = kwargs.get('class_names', None)
69
+ self._categorical_features = kwargs.get('categorical_features', [])
70
+ self._categorical_names = kwargs.get('categorical_names', {})
71
+ self._kernel_width = kwargs.get('kernel_width', None)
72
+ self._verbose = kwargs.get('verbose', False)
73
+
74
+ # Initialisation de l'explainer LIME
75
+ self._lime_explainer = None
76
+ self._initialize_explainer()
77
+
78
+ # Métadonnées du modèle
79
+ self._metadata = None
80
+
81
+ # Logger
82
+ self._logger = logging.getLogger(__name__)
83
+
84
+ def _initialize_explainer(self):
85
+ """
86
+ Initialise l'explainer LIME approprié en fonction du type de données.
87
+ """
88
+ try:
89
+ import lime
90
+ import lime.lime_tabular
91
+ import lime.lime_text
92
+ import lime.lime_image
93
+ except ImportError:
94
+ raise ImportError("Le package LIME est requis. Installez-le avec 'pip install lime'.")
95
+
96
+ # Tracer l'action
97
+ self.add_audit_record("initialize_explainer", {
98
+ "data_type": self._data_type,
99
+ "kernel_width": self._kernel_width,
100
+ "verbose": self._verbose
101
+ })
102
+
103
+ try:
104
+ if self._data_type == 'tabular':
105
+ self._lime_explainer = lime.lime_tabular.LimeTabularExplainer(
106
+ training_data=np.array([]), # Sera remplacé lors de l'explication
107
+ feature_names=self._feature_names,
108
+ class_names=self._class_names,
109
+ categorical_features=self._categorical_features,
110
+ categorical_names=self._categorical_names,
111
+ kernel_width=self._kernel_width,
112
+ verbose=self._verbose,
113
+ mode='classification' if self._is_classifier() else 'regression'
114
+ )
115
+ self._logger.info("Explainer LIME tabular initialisé")
116
+ elif self._data_type == 'text':
117
+ self._lime_explainer = lime.lime_text.LimeTextExplainer(
118
+ class_names=self._class_names,
119
+ kernel_width=self._kernel_width,
120
+ verbose=self._verbose
121
+ )
122
+ self._logger.info("Explainer LIME text initialisé")
123
+ elif self._data_type == 'image':
124
+ self._lime_explainer = lime.lime_image.LimeImageExplainer(
125
+ kernel_width=self._kernel_width,
126
+ verbose=self._verbose
127
+ )
128
+ self._logger.info("Explainer LIME image initialisé")
129
+ else:
130
+ raise ValueError(f"Type de données non supporté: {self._data_type}. "
131
+ f"Utilisez 'tabular', 'text' ou 'image'.")
132
+ except Exception as e:
133
+ self._logger.error(f"Erreur lors de l'initialisation de l'explainer LIME: {str(e)}")
134
+ raise RuntimeError(f"Échec de l'initialisation de l'explainer LIME: {str(e)}")
135
+
136
+ def _is_classifier(self) -> bool:
137
+ """
138
+ Détermine si le modèle est un classifieur ou un régresseur.
139
+
140
+ Returns:
141
+ bool: True si le modèle est un classifieur, False sinon
142
+ """
143
+ # Vérifier les attributs spécifiques aux classifieurs
144
+ if hasattr(self._model, 'predict_proba'):
145
+ return True
146
+ if hasattr(self._model, 'classes_'):
147
+ return True
148
+
149
+ # Pour les modèles deep learning, vérifier la forme de sortie
150
+ model_module = self._model.__class__.__module__
151
+ if 'keras' in model_module or 'tensorflow' in model_module or 'torch' in model_module:
152
+ try:
153
+ # Créer des données synthétiques pour une inférence
154
+ input_shape = self._infer_model_input_shape()
155
+ if input_shape:
156
+ sample = np.random.normal(0, 0.1, size=(1, *input_shape))
157
+ preds = self._model_predict_wrapper(sample)
158
+
159
+ # Si la sortie a plusieurs dimensions et la dernière dimension > 1, c'est probablement une classification
160
+ if preds.ndim > 1 and preds.shape[-1] > 1:
161
+ return True
162
+ except:
163
+ pass
164
+
165
+ # Par défaut, supposer que c'est un régresseur
166
+ return False
167
+
168
+ def _model_predict_wrapper(self, instances):
169
+ """
170
+ Wrapper pour standardiser les prédictions de différents frameworks ML.
171
+
172
+ Cette méthode détecte automatiquement le framework du modèle et adapte l'interface
173
+ de prédiction en conséquence, assurant une sortie unifiée quel que soit le framework.
174
+
175
+ Args:
176
+ instances: Données d'entrée à prédire (ndarray, DataFrame, csr_matrix, etc.)
177
+
178
+ Returns:
179
+ ndarray: Les prédictions standardisées (probs pour classification, valeurs pour régression)
180
+ """
181
+ try:
182
+ # Détecter le framework du modèle
183
+ model_type = self._extract_model_type()
184
+
185
+ # Standardiser le format d'entrée si nécessaire
186
+ if hasattr(instances, 'values'):
187
+ # Convertir DataFrame en ndarray
188
+ instances = instances.values
189
+
190
+ # Adapter l'appel de prédiction selon le framework
191
+ if model_type == 'sklearn':
192
+ # sklearn a predict_proba pour classification, predict pour régression
193
+ if self._is_classifier() and hasattr(self._model, 'predict_proba'):
194
+ return self._model.predict_proba(instances)
195
+ else:
196
+ return self._model.predict(instances).reshape(-1, 1)
197
+
198
+ elif model_type in ['xgboost', 'lightgbm', 'catboost']:
199
+ # Ces frameworks ont souvent predict ou predict_proba
200
+ if hasattr(self._model, 'predict_proba'):
201
+ return self._model.predict_proba(instances)
202
+ else:
203
+ preds = self._model.predict(instances)
204
+ # S'assurer que les sorties sont 2D pour la cohérence
205
+ if preds.ndim == 1:
206
+ return preds.reshape(-1, 1)
207
+ return preds
208
+
209
+ elif model_type == 'tensorflow':
210
+ # TensorFlow/Keras models
211
+ import numpy as np
212
+ import tensorflow as tf
213
+
214
+ # Convertir en tenseur TF si nécessaire
215
+ if not isinstance(instances, tf.Tensor):
216
+ instances = tf.convert_to_tensor(instances, dtype=tf.float32)
217
+
218
+ # Prédire avec le modèle TF
219
+ preds = self._model(instances).numpy() if hasattr(self._model, '__call__') else \
220
+ self._model.predict(instances)
221
+
222
+ # Standardiser le format de sortie
223
+ return np.atleast_2d(preds)
224
+
225
+ elif model_type == 'pytorch':
226
+ # PyTorch models
227
+ import numpy as np
228
+ import torch
229
+
230
+ # Désactiver le calcul de gradient pour les prédictions
231
+ with torch.no_grad():
232
+ # Convertir en tenseur PyTorch si nécessaire
233
+ if not isinstance(instances, torch.Tensor):
234
+ instances = torch.tensor(instances, dtype=torch.float32)
235
+
236
+ # Mettre sur le device approprié (GPU/CPU)
237
+ if torch.cuda.is_available() and getattr(self, '_config', {}).get('use_gpu', False):
238
+ instances = instances.cuda()
239
+ if hasattr(self._model, 'cuda'):
240
+ model = self._model.cuda()
241
+ else:
242
+ model = self._model
243
+ else:
244
+ model = self._model
245
+
246
+ # Prédire et convertir en numpy
247
+ preds = model(instances) if hasattr(model, '__call__') else \
248
+ model.predict(instances)
249
+ preds = preds.cpu().numpy()
250
+
251
+ # Standardiser le format de sortie
252
+ return np.atleast_2d(preds)
253
+ else:
254
+ # Fallback générique pour les autres frameworks
255
+ preds = self._model.predict(instances)
256
+ # S'assurer que les sorties sont 2D pour la cohérence
257
+ if hasattr(preds, 'ndim') and preds.ndim == 1:
258
+ return preds.reshape(-1, 1)
259
+ return preds
260
+
261
+ except Exception as e:
262
+ self._logger.error(f"Erreur lors de la prédiction avec {self._model.__class__.__name__}: {str(e)}")
263
+ import traceback
264
+ self._logger.debug(traceback.format_exc())
265
+ raise RuntimeError(f"Échec de la prédiction: {str(e)}")
266
+
267
+ def _infer_model_input_shape(self):
268
+ """
269
+ Tente de déduire la forme des entrées du modèle.
270
+
271
+ Returns:
272
+ tuple ou None: Forme déduite ou None si impossible
273
+ """
274
+ model_module = self._model.__class__.__module__
275
+
276
+ if 'tensorflow' in model_module or 'keras' in model_module:
277
+ try:
278
+ # Pour les modèles Keras
279
+ return self._model.input_shape[1:]
280
+ except (AttributeError, IndexError):
281
+ pass
282
+
283
+ # Pour les modèles sklearn, xgboost, etc.
284
+ try:
285
+ if hasattr(self._model, 'n_features_in_'):
286
+ return (self._model.n_features_in_,)
287
+ except AttributeError:
288
+ pass
289
+
290
+ # Impossible de déduire
291
+ return None
292
+
293
+ def _model_predict_wrapper(self, x):
294
+ """
295
+ Wrapper pour la fonction de prédiction du modèle, adapté pour LIME.
296
+
297
+ Args:
298
+ x: Données d'entrée
299
+
300
+ Returns:
301
+ numpy.ndarray: Prédictions du modèle
302
+ """
303
+ try:
304
+ model_module = self._model.__class__.__module__
305
+
306
+ if 'sklearn' in model_module or 'xgboost' in model_module or 'lightgbm' in model_module:
307
+ if hasattr(self._model, 'predict_proba'):
308
+ return self._model.predict_proba(x)
309
+ else:
310
+ return self._model.predict(x)
311
+ elif 'tensorflow' in model_module or 'keras' in model_module:
312
+ # Conversion en format attendu par le modèle
313
+ if isinstance(x, pd.DataFrame):
314
+ x = x.values
315
+
316
+ # Appel au modèle
317
+ result = self._model.predict(x)
318
+ return result
319
+ elif 'torch' in model_module:
320
+ # Conversion en format attendu par le modèle
321
+ if isinstance(x, pd.DataFrame):
322
+ x = x.values
323
+
324
+ import torch
325
+ # Convertir en tensor PyTorch
326
+ if not isinstance(x, torch.Tensor):
327
+ x = torch.tensor(x, dtype=torch.float32)
328
+
329
+ # Mettre le modèle en mode évaluation
330
+ self._model.eval()
331
+
332
+ # Appel au modèle avec torch.no_grad
333
+ with torch.no_grad():
334
+ result = self._model(x)
335
+
336
+ # Conversion du résultat en numpy
337
+ if hasattr(result, 'detach'):
338
+ result = result.detach().numpy()
339
+ else:
340
+ result = result.numpy()
341
+ return result
342
+ else:
343
+ # Cas générique
344
+ if hasattr(self._model, 'predict'):
345
+ return self._model.predict(x)
346
+ else:
347
+ return self._model(x)
348
+ except Exception as e:
349
+ self._logger.error(f"Erreur dans le wrapper de prédiction: {str(e)}")
350
+ raise RuntimeError(f"Échec de la prédiction du modèle: {str(e)}")
351
+
352
+ def explain(self, X, y=None, **kwargs) -> ExplanationResult:
353
+ """
354
+ Génère des explications LIME pour un ensemble de données.
355
+
356
+ Args:
357
+ X: Données d'entrée à expliquer (DataFrame, numpy array, ou liste)
358
+ y: Valeurs cibles réelles (optionnel)
359
+ **kwargs: Paramètres additionnels
360
+ - num_features: Nombre de caractéristiques à inclure dans l'explication
361
+ - num_samples: Nombre d'échantillons à générer pour l'approximation locale
362
+ - max_instances: Nombre maximum d'instances à expliquer (pour performance)
363
+ - audience_level: Niveau d'audience (TECHNICAL, BUSINESS, PUBLIC)
364
+ - labels: Indices des classes à expliquer (pour les classifieurs multi-classes)
365
+
366
+ Returns:
367
+ ExplanationResult: Résultat standardisé de l'explication
368
+ """
369
+ if self._lime_explainer is None:
370
+ # Réinitialiser l'explainer avec les données actuelles
371
+ self._initialize_explainer_with_data(X, **kwargs)
372
+
373
+ # Paramètres
374
+ num_features = kwargs.get('num_features', 10)
375
+ num_samples = kwargs.get('num_samples', 5000)
376
+ max_instances = kwargs.get('max_instances', 100) # Limite pour performance
377
+ audience_level = kwargs.get('audience_level', AudienceLevel.TECHNICAL)
378
+ labels = kwargs.get('labels', None)
379
+
380
+ # Conversion des données en format approprié
381
+ if isinstance(X, pd.DataFrame):
382
+ feature_names = X.columns.tolist()
383
+ X_values = X.values
384
+ else:
385
+ X_values = np.array(X)
386
+ feature_names = kwargs.get('feature_names', self._feature_names) or \
387
+ [f"feature_{i}" for i in range(X_values.shape[1])]
388
+
389
+ # Limiter le nombre d'instances pour performance si nécessaire
390
+ if X_values.shape[0] > max_instances:
391
+ self._logger.warning(f"Échantillonnage de {max_instances} instances sur {X_values.shape[0]} pour performance.")
392
+ indices = np.random.choice(X_values.shape[0], max_instances, replace=False)
393
+ X_sample = X_values[indices]
394
+ else:
395
+ X_sample = X_values
396
+
397
+ # Tracer l'action
398
+ self.add_audit_record("explain", {
399
+ "n_samples": X_sample.shape[0],
400
+ "n_features": X_sample.shape[1],
401
+ "audience_level": audience_level.value if isinstance(audience_level, AudienceLevel) else audience_level,
402
+ "num_features": num_features,
403
+ "num_samples": num_samples
404
+ })
405
+
406
+ try:
407
+ # Calculer les explications LIME pour chaque instance
408
+ explanations = []
409
+ for i, instance in enumerate(X_sample):
410
+ if i > 0 and i % 10 == 0:
411
+ self._logger.info(f"Explication de l'instance {i}/{len(X_sample)}")
412
+
413
+ # Générer l'explication pour cette instance
414
+ if self._data_type == 'tabular':
415
+ exp = self._lime_explainer.explain_instance(
416
+ instance,
417
+ self._model_predict_wrapper,
418
+ num_features=num_features,
419
+ num_samples=num_samples,
420
+ labels=labels
421
+ )
422
+ elif self._data_type == 'text':
423
+ exp = self._lime_explainer.explain_instance(
424
+ instance,
425
+ self._model_predict_wrapper,
426
+ num_features=num_features,
427
+ labels=labels
428
+ )
429
+ elif self._data_type == 'image':
430
+ exp = self._lime_explainer.explain_instance(
431
+ instance,
432
+ self._model_predict_wrapper,
433
+ num_features=num_features,
434
+ labels=labels
435
+ )
436
+
437
+ explanations.append(exp)
438
+
439
+ # Agréger les importances de caractéristiques
440
+ feature_importances = self._aggregate_feature_importances(explanations, feature_names)
441
+
442
+ # Extraire les métadonnées du modèle
443
+ if not self._metadata:
444
+ self._extract_metadata()
445
+
446
+ # Créer le résultat d'explication
447
+ result = ExplanationResult(
448
+ method=ExplainabilityMethod.LIME,
449
+ model_metadata=self._metadata,
450
+ feature_importances=feature_importances,
451
+ raw_explanation={
452
+ "lime_explanations": explanations,
453
+ "feature_names": feature_names,
454
+ "data": X_sample
455
+ },
456
+ audience_level=audience_level
457
+ )
458
+
459
+ return result
460
+
461
+ except Exception as e:
462
+ self._logger.error(f"Erreur lors du calcul des explications LIME: {str(e)}")
463
+ raise RuntimeError(f"Échec de l'explication LIME: {str(e)}")
464
+
465
+ def _initialize_explainer_with_data(self, X, **kwargs):
466
+ """
467
+ Réinitialise l'explainer LIME avec les données actuelles.
468
+
469
+ Args:
470
+ X: Données d'entrée pour initialiser l'explainer
471
+ **kwargs: Paramètres additionnels
472
+ """
473
+ try:
474
+ import lime
475
+ import lime.lime_tabular
476
+ import lime.lime_text
477
+ import lime.lime_image
478
+ except ImportError:
479
+ raise ImportError("Le package LIME est requis. Installez-le avec 'pip install lime'.")
480
+
481
+ # Conversion des données en format approprié
482
+ if isinstance(X, pd.DataFrame):
483
+ feature_names = X.columns.tolist()
484
+ X_values = X.values
485
+ else:
486
+ X_values = np.array(X)
487
+ feature_names = kwargs.get('feature_names', self._feature_names) or \
488
+ [f"feature_{i}" for i in range(X_values.shape[1])]
489
+
490
+ # Mettre à jour les attributs
491
+ self._feature_names = feature_names
492
+
493
+ # Réinitialiser l'explainer avec les données
494
+ if self._data_type == 'tabular':
495
+ self._lime_explainer = lime.lime_tabular.LimeTabularExplainer(
496
+ training_data=X_values,
497
+ feature_names=feature_names,
498
+ class_names=self._class_names,
499
+ categorical_features=self._categorical_features,
500
+ categorical_names=self._categorical_names,
501
+ kernel_width=self._kernel_width,
502
+ verbose=self._verbose,
503
+ mode='classification' if self._is_classifier() else 'regression'
504
+ )
505
+ self._logger.info("Explainer LIME tabular réinitialisé avec les données")
506
+ else:
507
+ # Pour les types text et image, pas besoin de réinitialiser avec les données
508
+ pass
509
+
510
+ def _aggregate_feature_importances(self, explanations, feature_names):
511
+ """
512
+ Agrège les importances de caractéristiques à partir des explications LIME.
513
+
514
+ Args:
515
+ explanations: Liste des explications LIME
516
+ feature_names: Noms des caractéristiques
517
+
518
+ Returns:
519
+ List[FeatureImportance]: Liste des importances de caractéristiques agrégées
520
+ """
521
+ # Initialiser un dictionnaire pour stocker les importances agrégées
522
+ aggregated_importances = {name: [] for name in feature_names}
523
+
524
+ # Collecter toutes les importances
525
+ for exp in explanations:
526
+ # Pour les explainers tabulaires
527
+ if hasattr(exp, 'as_list'):
528
+ # Prendre la première classe si aucune n'est spécifiée
529
+ label = 1 if self._is_classifier() and exp.available_labels() else exp.available_labels()[0]
530
+ for feature, importance in exp.as_list(label=label):
531
+ # Extraire le nom de la caractéristique (peut contenir des conditions pour les valeurs catégorielles)
532
+ feature_name = feature.split(' ')[0]
533
+ if feature_name in aggregated_importances:
534
+ aggregated_importances[feature_name].append(abs(importance))
535
+ # Pour les explainers texte et image (structure différente)
536
+ elif hasattr(exp, 'local_exp'):
537
+ # Prendre la première classe
538
+ label = list(exp.local_exp.keys())[0]
539
+ for idx, importance in exp.local_exp[label]:
540
+ if idx < len(feature_names):
541
+ aggregated_importances[feature_names[idx]].append(abs(importance))
542
+
543
+ # Calculer les moyennes et créer les objets FeatureImportance
544
+ feature_importances = []
545
+ for name, importances in aggregated_importances.items():
546
+ if importances: # S'assurer qu'il y a des valeurs
547
+ avg_importance = np.mean(importances)
548
+ std_dev = np.std(importances) if len(importances) > 1 else 0.0
549
+ feature_importances.append(FeatureImportance(
550
+ feature_name=name,
551
+ importance=float(avg_importance),
552
+ std_dev=float(std_dev)
553
+ ))
554
+
555
+ # Trier par importance décroissante
556
+ feature_importances.sort(key=lambda x: x.importance, reverse=True)
557
+
558
+ return feature_importances
559
+
560
+ def explain_instance(self, instance, **kwargs) -> ExplanationResult:
561
+ """
562
+ Explique une instance spécifique avec LIME avec fonctionnalités avancées.
563
+
564
+ Cette implémentation avancée inclut:
565
+ - Support GPU optimisé pour les calculs complexes
566
+ - Système de cache intelligent pour les explications récurrentes
567
+ - Métriques de qualité et de fidélité des explications
568
+ - Génération de narratives explicatives multi-audience et multilingues
569
+ - Validation de conformité réglementaire intégrée
570
+
571
+ Args:
572
+ instance: Instance à expliquer (array, liste, dict ou pandas.Series)
573
+ **kwargs: Paramètres additionnels
574
+ - num_features: Nombre de caractéristiques à inclure dans l'explication
575
+ - num_samples: Nombre d'échantillons à générer pour l'approximation locale
576
+ - audience_level: Niveau d'audience (TECHNICAL, BUSINESS, PUBLIC)
577
+ - label: Indice de la classe à expliquer (pour les classifieurs multi-classes)
578
+ - use_cache: Activer/désactiver l'utilisation du cache (défaut: True)
579
+ - use_gpu: Utiliser GPU si disponible (défaut: configuration globale)
580
+ - compute_metrics: Calculer les métriques de qualité d'explication (défaut: True)
581
+ - include_prediction: Inclure la prédiction du modèle dans le résultat (défaut: True)
582
+ - generate_narrative: Générer des narratives textuelles explicatives (défaut: True)
583
+ - narrative_language: Langue des narratives ('fr', 'en') (défaut: 'fr')
584
+ - check_compliance: Vérifier la conformité réglementaire de l'explication (défaut: True)
585
+ - compliance_regulations: Liste des réglementations à vérifier (défaut: ['gdpr', 'ai_act'])
586
+
587
+ Returns:
588
+ ExplanationResult: Résultat standardisé de l'explication avec métriques avancées, narratives et conformité
589
+ """
590
+ import hashlib
591
+ import pickle
592
+ import time
593
+ import sys
594
+ from dataclasses import dataclass, field
595
+ from contextlib import nullcontext
596
+ from datetime import datetime
597
+
598
+ # Import des modules internes pour mesurer la performance
599
+ try:
600
+ from ..core.profiling import Timer, MemoryTracker
601
+ except ImportError:
602
+ # Fallback simple si les modules ne sont pas disponibles
603
+ class Timer:
604
+ def __init__(self, name="Timer"):
605
+ self.name = name
606
+ self.start_time = None
607
+ def __enter__(self):
608
+ self.start_time = time.time()
609
+ return self
610
+ def __exit__(self, *args):
611
+ self.elapsed = time.time() - self.start_time
612
+
613
+ class MemoryTracker:
614
+ def __init__(self, name="MemoryTracker"):
615
+ self.name = name
616
+ self.start_mem = None
617
+ def __enter__(self):
618
+ self.start_mem = sys.getsizeof({})
619
+ return self
620
+ def __exit__(self, *args):
621
+ self.usage = 0 # Placeholder
622
+
623
+ # Import du vérificateur de conformité s'il est disponible
624
+ try:
625
+ from ..compliance.compliance_checker import ComplianceChecker
626
+ has_compliance_checker = True
627
+ except ImportError:
628
+ has_compliance_checker = False
629
+
630
+ # Configuration et paramètres avancés
631
+ @dataclass
632
+ class ExplainConfig:
633
+ # Paramètres basiques de LIME
634
+ num_features: int = 10
635
+ num_samples: int = 5000
636
+ audience_level: AudienceLevel = AudienceLevel.TECHNICAL
637
+ label: Optional[int] = None
638
+ feature_names: List[str] = field(default_factory=list)
639
+
640
+ # Paramètres avancés
641
+ use_cache: bool = True
642
+ use_gpu: bool = True # Utiliser GPU si disponible
643
+ compute_metrics: bool = True # Calculer les métriques de qualité
644
+ include_prediction: bool = True # Inclure la prédiction dans le résultat
645
+ generate_narrative: bool = True # Générer des narratives explicatives
646
+ narrative_language: str = 'fr' # Langue des narratives
647
+ check_compliance: bool = True # Vérifier la conformité réglementaire
648
+ compliance_regulations: List[str] = field(default_factory=lambda: ['gdpr', 'ai_act'])
649
+
650
+ # Créer et remplir la configuration
651
+ config = ExplainConfig(
652
+ num_features=kwargs.get('num_features', 10),
653
+ num_samples=kwargs.get('num_samples', 5000),
654
+ audience_level=kwargs.get('audience_level', AudienceLevel.TECHNICAL),
655
+ label=kwargs.get('label', None),
656
+ use_cache=kwargs.get('use_cache', True),
657
+ use_gpu=kwargs.get('use_gpu', getattr(self, '_config', {}).get('use_gpu', True)),
658
+ compute_metrics=kwargs.get('compute_metrics', True),
659
+ include_prediction=kwargs.get('include_prediction', True),
660
+ generate_narrative=kwargs.get('generate_narrative', True),
661
+ narrative_language=kwargs.get('narrative_language', 'fr'),
662
+ check_compliance=kwargs.get('check_compliance', True),
663
+ compliance_regulations=kwargs.get('compliance_regulations', ['gdpr', 'ai_act'])
664
+ )
665
+
666
+ # Initialiser trackers de performance
667
+ timer = Timer("LimeExplanation")
668
+ memory_tracker = MemoryTracker("LimeMemory")
669
+
670
+ with timer, memory_tracker:
671
+ # Convertir l'instance en format approprié
672
+ if isinstance(instance, dict):
673
+ # Convertir dict en array
674
+ feature_names = list(instance.keys())
675
+ instance_array = np.array([instance[f] for f in feature_names]).reshape(1, -1)
676
+ elif isinstance(instance, pd.Series):
677
+ feature_names = instance.index.tolist()
678
+ instance_array = instance.values.reshape(1, -1)
679
+ elif isinstance(instance, (list, np.ndarray)):
680
+ instance_array = np.array(instance).reshape(1, -1)
681
+ feature_names = kwargs.get('feature_names', self._feature_names) or \
682
+ [f"feature_{i}" for i in range(instance_array.shape[1])]
683
+ else:
684
+ raise ValueError("Format d'instance non supporté. Utilisez un dict, pandas.Series, liste ou numpy.ndarray.")
685
+
686
+ config.feature_names = feature_names
687
+
688
+ # Vérification du cache si activé
689
+ if config.use_cache and hasattr(self, '_explanation_cache'):
690
+ # Générer une clé de cache unique basée sur l'instance et les paramètres
691
+ cache_key_data = {
692
+ 'instance': instance_array.tobytes(),
693
+ 'num_features': config.num_features,
694
+ 'num_samples': config.num_samples,
695
+ 'label': config.label
696
+ }
697
+ cache_key = hashlib.md5(pickle.dumps(cache_key_data)).hexdigest()
698
+
699
+ # Vérifier si l'explication est dans le cache
700
+ if hasattr(self, '_explanation_cache') and cache_key in self._explanation_cache:
701
+ self._logger.info(f"Utilisation du cache pour l'explication (clé: {cache_key[:8]}...)")
702
+ return self._explanation_cache[cache_key]
703
+ else:
704
+ cache_key = None
705
+
706
+ # Si l'explainer n'est pas initialisé avec des données, le faire maintenant
707
+ if self._lime_explainer is None or (self._data_type == 'tabular' and
708
+ not hasattr(self._lime_explainer, 'feature_names')):
709
+ # Créer un petit ensemble de données synthétiques pour l'initialisation
710
+ synthetic_data = np.random.normal(0, 1, size=(100, instance_array.shape[1]))
711
+ self._initialize_explainer_with_data(synthetic_data, feature_names=feature_names)
712
+
713
+ # Tracer l'action
714
+ audit_data = {
715
+ "n_features": len(feature_names),
716
+ "audience_level": config.audience_level.value if isinstance(config.audience_level, AudienceLevel) else config.audience_level,
717
+ "num_features": config.num_features,
718
+ "num_samples": config.num_samples,
719
+ "use_gpu": config.use_gpu,
720
+ "use_cache": config.use_cache,
721
+ "timestamp": datetime.now().isoformat()
722
+ }
723
+ self.add_audit_record("explain_instance", audit_data)
724
+
725
+ # Context manager pour GPU si activé
726
+ gpu_context = self._maybe_use_gpu_context() if config.use_gpu else nullcontext()
727
+
728
+ # Prédiction si demandée
729
+ model_prediction = None
730
+ if config.include_prediction:
731
+ with gpu_context:
732
+ try:
733
+ model_prediction = self._model_predict_wrapper(instance_array)
734
+ except Exception as e:
735
+ self._logger.warning(f"Erreur lors de la prédiction du modèle: {str(e)}")
736
+
737
+ try:
738
+ # Génération de l'explication LIME avec optimisation GPU si configurée
739
+ with gpu_context:
740
+ # Générer l'explication pour cette instance
741
+ if self._data_type == 'tabular':
742
+ exp = self._lime_explainer.explain_instance(
743
+ instance_array[0],
744
+ self._model_predict_wrapper,
745
+ num_features=config.num_features,
746
+ num_samples=config.num_samples,
747
+ labels=[config.label] if config.label is not None else None
748
+ )
749
+ elif self._data_type == 'text':
750
+ exp = self._lime_explainer.explain_instance(
751
+ instance_array[0] if isinstance(instance_array[0], str) else str(instance_array[0]),
752
+ self._model_predict_wrapper,
753
+ num_features=config.num_features,
754
+ labels=[config.label] if config.label is not None else None
755
+ )
756
+ elif self._data_type == 'image':
757
+ exp = self._lime_explainer.explain_instance(
758
+ instance_array[0],
759
+ self._model_predict_wrapper,
760
+ num_features=config.num_features,
761
+ labels=[config.label] if config.label is not None else None
762
+ )
763
+
764
+ # Extraire les importances de caractéristiques
765
+ feature_importances = []
766
+
767
+ # Pour les explainers tabulaires
768
+ if hasattr(exp, 'as_list'):
769
+ # Déterminer la classe à expliquer
770
+ if config.label is None:
771
+ # Prendre la classe avec la probabilité maximale
772
+ predictions = self._model_predict_wrapper(instance_array)
773
+ if predictions.ndim > 1 and predictions.shape[1] > 1:
774
+ config.label = np.argmax(predictions[0])
775
+ else:
776
+ # Cas binaire, prendre la classe positive
777
+ config.label = 1 if self._is_classifier() else 0
778
+
779
+ # Extraire les importances
780
+ for feature, importance in exp.as_list(label=config.label):
781
+ # Extraire le nom de la caractéristique (peut contenir des conditions pour les valeurs catégorielles)
782
+ feature_name = feature.split(' ')[0]
783
+ feature_importances.append(FeatureImportance(
784
+ feature_name=feature_name,
785
+ importance=float(importance)
786
+ ))
787
+ # Pour les explainers texte et image (structure différente)
788
+ elif hasattr(exp, 'local_exp'):
789
+ # Déterminer la classe à expliquer
790
+ if config.label is None:
791
+ # Prendre la première classe disponible
792
+ config.label = list(exp.local_exp.keys())[0]
793
+
794
+ # Extraire les importances
795
+ for idx, importance in exp.local_exp[config.label]:
796
+ if idx < len(feature_names):
797
+ feature_importances.append(FeatureImportance(
798
+ feature_name=feature_names[idx],
799
+ importance=float(importance)
800
+ ))
801
+
802
+ # Trier par importance absolue décroissante
803
+ feature_importances.sort(key=lambda x: abs(x.importance), reverse=True)
804
+
805
+ # Métriques de qualité si demandé
806
+ explanation_metrics = {}
807
+ if config.compute_metrics:
808
+ explanation_metrics = self._compute_explanation_quality(feature_importances, exp, instance_array, config)
809
+
810
+ # Narratives si demandé
811
+ narratives = {}
812
+ if config.generate_narrative:
813
+ narratives = self._generate_explanation_narrative(
814
+ exp, instance_array, feature_names,
815
+ audience_level=config.audience_level,
816
+ language=config.narrative_language
817
+ )
818
+
819
+ # Extraire les métadonnées du modèle si nécessaire
820
+ if not self._metadata:
821
+ self._extract_metadata()
822
+
823
+ # Vérification de conformité si demandée
824
+ compliance_result = None
825
+ if config.check_compliance and has_compliance_checker:
826
+ try:
827
+ compliance_checker = ComplianceChecker()
828
+ # Créer un résultat d'explication temporaire pour la vérification
829
+ temp_result = ExplanationResult(
830
+ method=ExplainabilityMethod.LIME,
831
+ model_metadata=self._metadata,
832
+ feature_importances=feature_importances
833
+ )
834
+ compliance_result = compliance_checker.check_compliance(
835
+ temp_result,
836
+ regulations=config.compliance_regulations
837
+ )
838
+ except Exception as e:
839
+ self._logger.warning(f"Erreur lors de la vérification de conformité: {str(e)}")
840
+
841
+ # Enrichir les métadonnées avec les informations de performance
842
+ performance_metadata = {
843
+ "computation_time_ms": timer.elapsed * 1000 if hasattr(timer, "elapsed") else None,
844
+ "memory_usage_bytes": memory_tracker.usage if hasattr(memory_tracker, "usage") else None,
845
+ "computation_mode": "gpu" if config.use_gpu else "cpu",
846
+ "lime_sample_count": config.num_samples,
847
+ "timestamp": datetime.now().isoformat(),
848
+ }
849
+
850
+ # Créer le résultat d'explication enrichi
851
+ result = ExplanationResult(
852
+ method=ExplainabilityMethod.LIME,
853
+ model_metadata=self._metadata,
854
+ feature_importances=feature_importances,
855
+ raw_explanation={
856
+ "lime_explanation": exp,
857
+ "feature_names": feature_names,
858
+ "data": instance_array,
859
+ "label": config.label,
860
+ "prediction": model_prediction.tolist() if model_prediction is not None else None
861
+ },
862
+ audience_level=config.audience_level,
863
+ metrics=explanation_metrics,
864
+ narratives=narratives,
865
+ compliance=compliance_result.to_dict() if compliance_result else None,
866
+ metadata=performance_metadata
867
+ )
868
+
869
+ # Mettre en cache si activé
870
+ if config.use_cache and cache_key:
871
+ if not hasattr(self, '_explanation_cache'):
872
+ self._explanation_cache = {}
873
+ self._explanation_cache[cache_key] = result
874
+ # Limiter la taille du cache
875
+ if len(self._explanation_cache) > 100:
876
+ oldest_key = next(iter(self._explanation_cache))
877
+ del self._explanation_cache[oldest_key]
878
+
879
+ return result
880
+ except Exception as e:
881
+ self._logger.error(f"Erreur lors du calcul de l'explication LIME pour l'instance: {str(e)}")
882
+ import traceback
883
+ self._logger.debug(traceback.format_exc())
884
+ raise RuntimeError(f"Échec de l'explication LIME pour l'instance: {str(e)}")
885
+
886
+ def _maybe_use_gpu_context(self):
887
+ """
888
+ Contexte de gestion des ressources GPU pour l'explication.
889
+
890
+ Permet d'optimiser automatiquement l'utilisation des ressources GPU
891
+ lors du calcul des valeurs LIME, particulièrement pour les grands jeux de données
892
+ et les modèles complexes.
893
+
894
+ Returns:
895
+ Un gestionnaire de contexte qui configure l'environnement GPU optimalement
896
+ """
897
+ if not getattr(self, '_config', {}).get('use_gpu', False):
898
+ # Si GPU non activé, retourner un contexte vide (no-op)
899
+ from contextlib import nullcontext
900
+ return nullcontext()
901
+
902
+ # Contexte GPU adapté au framework détecté
903
+ model_type = self._extract_model_type()
904
+
905
+ class _GPUContext:
906
+ def __init__(self, explainer):
907
+ self._explainer = explainer
908
+ self._prev_state = None
909
+ self._tf_context = None
910
+ self._torch_context = None
911
+
912
+ def __enter__(self):
913
+ try:
914
+ if 'tensorflow' in model_type:
915
+ import tensorflow as tf
916
+ # Activer GPU pour TensorFlow
917
+ self._explainer._set_gpu_memory_growth()
918
+ # Enregistrer les devices disponibles pour les restaurer ensuite
919
+ self._prev_state = tf.config.get_visible_devices()
920
+ # N'autoriser que GPU si disponible
921
+ gpus = tf.config.list_physical_devices('GPU')
922
+ if gpus:
923
+ tf.config.set_visible_devices(gpus, 'GPU')
924
+ self._explainer._logger.info(f"GPU activé pour TensorFlow: {len(gpus)} périphériques")
925
+ else:
926
+ self._explainer._logger.warning("GPU demandé mais non disponible pour TensorFlow")
927
+
928
+ elif 'pytorch' in model_type or 'torch' in model_type:
929
+ import torch
930
+ # Activer CUDA pour PyTorch si disponible
931
+ if torch.cuda.is_available():
932
+ # Préparer le device et définir le contexte par défaut
933
+ self._prev_state = torch.cuda.current_device()
934
+ torch.cuda.set_device(0) # Premier GPU par défaut
935
+ self._explainer._logger.info(f"GPU activé pour PyTorch: {torch.cuda.get_device_name(0)}")
936
+ else:
937
+ self._explainer._logger.warning("GPU demandé mais CUDA non disponible pour PyTorch")
938
+
939
+ # Configuration spécifique pour LIME
940
+ # LIME n'a pas d'API publique pour configurer le GPU, mais certaines
941
+ # opérations comme les calculs de similarité peuvent bénéficier du GPU
942
+ # si le framework sous-jacent est configuré correctement
943
+ except Exception as e:
944
+ self._explainer._logger.error(f"Erreur lors de l'activation GPU: {str(e)}")
945
+
946
+ return self
947
+
948
+ def __exit__(self, exc_type, exc_val, exc_tb):
949
+ try:
950
+ # Restaurer l'état précédent
951
+ if 'tensorflow' in model_type and self._prev_state is not None:
952
+ import tensorflow as tf
953
+ tf.config.set_visible_devices(self._prev_state)
954
+ elif ('pytorch' in model_type or 'torch' in model_type) and self._prev_state is not None:
955
+ import torch
956
+ if torch.cuda.is_available():
957
+ torch.cuda.set_device(self._prev_state)
958
+ # Libérer la mémoire GPU
959
+ torch.cuda.empty_cache()
960
+ except Exception as e:
961
+ self._explainer._logger.error(f"Erreur lors de la restauration du contexte GPU: {str(e)}")
962
+
963
+ # Retourner une instance du gestionnaire de contexte
964
+ return _GPUContext(self)
965
+
966
+ def _set_gpu_memory_growth(self):
967
+ """
968
+ Configure la croissance mémoire GPU dynamique pour TensorFlow.
969
+
970
+ Cette méthode contextuelle permet une utilisation optimale de la mémoire GPU
971
+ en configurant une allocation dynamique, évitant ainsi les erreurs OOM et
972
+ permettant une meilleure répartition des ressources entre plusieurs processus.
973
+ """
974
+ try:
975
+ import tensorflow as tf
976
+ gpus = tf.config.list_physical_devices('GPU')
977
+ if gpus:
978
+ # Configurer la croissance mémoire dynamique sur tous les GPU
979
+ for gpu in gpus:
980
+ tf.config.experimental.set_memory_growth(gpu, True)
981
+ self._logger.info(f"Allocation mémoire GPU dynamique activée pour {len(gpus)} GPU(s)")
982
+ except ImportError:
983
+ self._logger.info("TensorFlow non installé, croissance mémoire GPU non configurée")
984
+ except Exception as e:
985
+ self._logger.warning(f"Erreur lors de la configuration de la mémoire GPU: {str(e)}")
986
+
987
+ def _extract_model_type(self):
988
+ """
989
+ Détermine le type/framework du modèle pour adapter les optimisations.
990
+
991
+ Returns:
992
+ str: Type de modèle détecté ('tensorflow', 'pytorch', etc.)
993
+ """
994
+ model_module = self._model.__class__.__module__
995
+
996
+ if 'sklearn' in model_module:
997
+ return 'sklearn'
998
+ elif 'xgboost' in model_module:
999
+ return 'xgboost'
1000
+ elif 'lightgbm' in model_module:
1001
+ return 'lightgbm'
1002
+ elif 'catboost' in model_module:
1003
+ return 'catboost'
1004
+ elif 'tensorflow' in model_module or 'keras' in model_module:
1005
+ return 'tensorflow'
1006
+ elif 'torch' in model_module:
1007
+ return 'pytorch'
1008
+ else:
1009
+ return 'unknown'
1010
+
1011
+ def _extract_metadata(self) -> None:
1012
+ """
1013
+ Extrait les métadonnées du modèle pour l'explication.
1014
+ """
1015
+ model_module = self._model.__class__.__module__
1016
+ framework = None
1017
+
1018
+ # Déterminer le framework
1019
+ if 'sklearn' in model_module:
1020
+ framework = 'sklearn'
1021
+ elif 'xgboost' in model_module:
1022
+ framework = 'xgboost'
1023
+ elif 'lightgbm' in model_module:
1024
+ framework = 'lightgbm'
1025
+ elif 'catboost' in model_module:
1026
+ framework = 'catboost'
1027
+ elif 'tensorflow' in model_module or 'keras' in model_module:
1028
+ framework = 'tensorflow'
1029
+ elif 'torch' in model_module:
1030
+ framework = 'pytorch'
1031
+ else:
1032
+ framework = 'unknown'
1033
+
1034
+ # Déterminer le type de modèle (classification ou régression)
1035
+ is_classifier = self._is_classifier()
1036
+
1037
+ # Créer les métadonnées
1038
+ self._metadata = ModelMetadata(
1039
+ model_type="classification" if is_classifier else "regression",
1040
+ framework=framework,
1041
+ input_shape=self._infer_model_input_shape(),
1042
+ output_shape=None, # À compléter si nécessaire
1043
+ feature_names=self._feature_names,
1044
+ target_names=self._class_names,
1045
+ model_params={},
1046
+ model_version="1.0.0"
1047
+ )
1048
+
1049
+ def _compute_explanation_quality(self, feature_importances, lime_explanation, instance, config):
1050
+ """
1051
+ Calcule les métriques de qualité pour l'explication LIME.
1052
+
1053
+ Args:
1054
+ feature_importances: Liste des importances des caractéristiques calculées
1055
+ lime_explanation: Objet d'explication LIME brut
1056
+ instance: Instance à expliquer
1057
+ config: Configuration de l'explication
1058
+
1059
+ Returns:
1060
+ dict: Métriques de qualité de l'explication
1061
+ """
1062
+ metrics = {}
1063
+
1064
+ try:
1065
+ # 1. Fidélité locale - mesure à quel point l'explication
1066
+ # prédit correctement le comportement du modèle dans le voisinage
1067
+ if hasattr(lime_explanation, 'score') and lime_explanation.score is not None:
1068
+ metrics['local_fidelity'] = float(lime_explanation.score)
1069
+ elif hasattr(lime_explanation, 'local_pred') and hasattr(lime_explanation, 'score'):
1070
+ metrics['local_fidelity'] = float(lime_explanation.score)
1071
+ else:
1072
+ # Calculer la fidélité manuellement si LIME ne la fournit pas
1073
+ if hasattr(lime_explanation, 'intercept') and hasattr(lime_explanation, 'local_exp'):
1074
+ try:
1075
+ # Récupérer les données du modèle linéaire simplifié de LIME
1076
+ label = config.label if config.label is not None else 0
1077
+ coefs = dict(lime_explanation.local_exp[label])
1078
+ intercept = lime_explanation.intercept[label] if isinstance(lime_explanation.intercept, dict) else lime_explanation.intercept
1079
+
1080
+ # Obtenir les vraies prédictions du modèle
1081
+ true_pred = self._model_predict_wrapper(instance)[0]
1082
+
1083
+ # Calculer l'écart entre le modèle LIME et le vrai modèle
1084
+ if self._is_classifier():
1085
+ # Classification: utiliser l'erreur moyenne absolue sur les probabilités
1086
+ metrics['local_fidelity'] = 1 - np.mean(np.abs(lime_explanation.predict_proba - true_pred))
1087
+ else:
1088
+ # Régression: utiliser l'erreur absolue normalisée
1089
+ pred_abs_error = np.abs(lime_explanation.predict(instance.reshape(1, -1))[0] - true_pred[0])
1090
+ metrics['local_fidelity'] = 1 - min(pred_abs_error / (np.abs(true_pred[0]) + 1e-10), 1.0)
1091
+ except Exception as e:
1092
+ self._logger.warning(f"Erreur lors du calcul de la fidélité locale: {str(e)}")
1093
+ metrics['local_fidelity'] = None
1094
+
1095
+ # 2. Impact de prédiction - somme des valeurs absolues des importances
1096
+ total_abs_importance = sum(abs(fi.importance) for fi in feature_importances)
1097
+ metrics['prediction_impact'] = float(total_abs_importance)
1098
+
1099
+ # 3. Indice de Gini pour mesurer la concentration des importances
1100
+ # Valeur proche de 1 = explication concentrée sur peu de features
1101
+ # Valeur proche de 0 = explication distribuée uniformément
1102
+ if feature_importances:
1103
+ metrics['feature_concentration'] = self._gini_index(
1104
+ [abs(fi.importance) for fi in feature_importances]
1105
+ )
1106
+ else:
1107
+ metrics['feature_concentration'] = 0.0
1108
+
1109
+ # 4. Stabilité de l'explication (si explicitement demandée)
1110
+ # Cette métrique est coûteuse car elle nécessite de multiples explications
1111
+ if config.compute_stability and hasattr(instance, 'shape'):
1112
+ try:
1113
+ # Créer des perturbations légères de l'instance
1114
+ stability_samples = 5
1115
+ eps = 1e-2
1116
+ perturbed_instances = []
1117
+
1118
+ # Générer des instances avec du bruit gaussien
1119
+ rng = np.random.RandomState(42)
1120
+ for _ in range(stability_samples):
1121
+ # Ajouter un bruit gaussien faible aux instances
1122
+ perturbed = instance.copy()
1123
+ noise = eps * rng.randn(*perturbed.shape)
1124
+ perturbed += noise
1125
+ perturbed_instances.append(perturbed)
1126
+
1127
+ # Générer des explications pour les instances perturbées
1128
+ # Sans utiliser explain_instance pour éviter la récursion
1129
+ feature_imp_lists = []
1130
+ lime_explainer = self._get_lime_explainer()
1131
+
1132
+ for p_instance in perturbed_instances:
1133
+ p_exp = lime_explainer.explain_instance(
1134
+ p_instance[0],
1135
+ self._model.predict_proba if hasattr(self._model, 'predict_proba') else self._model.predict,
1136
+ num_features=len(feature_importances),
1137
+ num_samples=config.num_samples
1138
+ )
1139
+ # Extraire les importances pour la même classe
1140
+ if hasattr(p_exp, 'as_list'):
1141
+ imp_list = dict([(f.split(' ')[0], imp) for f, imp in p_exp.as_list(label=config.label)])
1142
+ elif hasattr(p_exp, 'local_exp'):
1143
+ imp_list = dict(p_exp.local_exp[config.label])
1144
+ else:
1145
+ imp_list = {}
1146
+ feature_imp_lists.append(imp_list)
1147
+
1148
+ # Calculer la similarité entre les explications (corrélation moyenne des importances)
1149
+ feature_names = [fi.feature_name for fi in feature_importances]
1150
+ stability_scores = []
1151
+
1152
+ for i in range(stability_samples):
1153
+ for j in range(i+1, stability_samples):
1154
+ imp_list_i = feature_imp_lists[i]
1155
+ imp_list_j = feature_imp_lists[j]
1156
+
1157
+ # Récupérer les importances pour les mêmes features
1158
+ common_features = set(imp_list_i.keys()).intersection(imp_list_j.keys())
1159
+ if common_features:
1160
+ vec_i = [imp_list_i.get(f, 0) for f in common_features]
1161
+ vec_j = [imp_list_j.get(f, 0) for f in common_features]
1162
+
1163
+ # Calculer la corrélation comme mesure de similarité
1164
+ from scipy.stats import spearmanr
1165
+ corr, _ = spearmanr(vec_i, vec_j)
1166
+ stability_scores.append(corr if not np.isnan(corr) else 0)
1167
+
1168
+ if stability_scores:
1169
+ # La stabilité est la corrélation moyenne entre les explications
1170
+ metrics['stability'] = float(np.mean(stability_scores))
1171
+ else:
1172
+ metrics['stability'] = None
1173
+ except Exception as e:
1174
+ self._logger.warning(f"Erreur lors du calcul de la stabilité de l'explication: {str(e)}")
1175
+ metrics['stability'] = None
1176
+
1177
+ # 5. Complexité de l'explication (nombre de features avec importance significative)
1178
+ importance_threshold = 0.01
1179
+ significant_features = sum(1 for fi in feature_importances if abs(fi.importance) > importance_threshold)
1180
+ metrics['complexity'] = significant_features
1181
+
1182
+ # 6. Déterminer les métriques spécifiques au type d'explication (tabular, text, image)
1183
+ if hasattr(lime_explanation, 'domain_mapper'):
1184
+ if hasattr(lime_explanation.domain_mapper, 'type'):
1185
+ metrics['explanation_type'] = lime_explanation.domain_mapper.type
1186
+ elif 'text' in str(lime_explanation.domain_mapper.__class__).lower():
1187
+ metrics['explanation_type'] = 'text'
1188
+ elif 'image' in str(lime_explanation.domain_mapper.__class__).lower():
1189
+ metrics['explanation_type'] = 'image'
1190
+ else:
1191
+ metrics['explanation_type'] = 'tabular'
1192
+ except Exception as e:
1193
+ self._logger.warning(f"Erreur lors du calcul des métriques de qualité: {str(e)}")
1194
+ import traceback
1195
+ self._logger.debug(traceback.format_exc())
1196
+
1197
+ return metrics
1198
+
1199
+ def _gini_index(self, values):
1200
+ """
1201
+ Calcule l'indice de Gini pour mesurer la concentration/dispersion des importances.
1202
+
1203
+ L'indice de Gini est compris entre 0 (distribution égale) et 1 (concentration extrême).
1204
+
1205
+ Args:
1206
+ values: Liste des valeurs d'importance (absolues)
1207
+
1208
+ Returns:
1209
+ float: Indice de Gini entre 0 et 1
1210
+ """
1211
+ # Filtrer les valeurs nulles ou négatives
1212
+ values = [v for v in values if v > 0]
1213
+ n = len(values)
1214
+
1215
+ if n <= 1:
1216
+ return 0.0
1217
+
1218
+ # Trier les valeurs
1219
+ values = sorted(values)
1220
+
1221
+ # Normaliser les valeurs (somme = 1)
1222
+ total = sum(values)
1223
+ if total == 0:
1224
+ return 0.0
1225
+
1226
+ values = [v / total for v in values]
1227
+
1228
+ # Calculer l'indice de Gini
1229
+ cumsum = 0
1230
+ gini = 0
1231
+
1232
+ for i, v in enumerate(values):
1233
+ rank = i + 1
1234
+ cumsum += v
1235
+ gini += v * ((n + 1 - rank) / n)
1236
+
1237
+ # Normaliser entre 0 et 1
1238
+ gini = 1 - 2 * gini
1239
+
1240
+ return max(0.0, min(1.0, gini)) # Assurer que Gini est entre 0 et 1
1241
+
1242
+ def _generate_explanation_narrative(self, lime_explanation, instance, feature_names, audience_level="technical", language="en"):
1243
+ """
1244
+ Génère une explication narrative des résultats LIME adaptée au niveau d'audience.
1245
+
1246
+ Args:
1247
+ lime_explanation: L'objet d'explication LIME
1248
+ instance: L'instance expliquée
1249
+ feature_names: Noms des caractéristiques
1250
+ audience_level: Niveau d'audience cible ("technical", "business", "public")
1251
+ language: Langue de l'explication ("en", "fr")
1252
+
1253
+ Returns:
1254
+ dict: Narratives explicatives par niveau d'audience
1255
+ """
1256
+ # Vérifier que l'objet d'explication est valide
1257
+ if lime_explanation is None:
1258
+ return {}
1259
+
1260
+ # Initialiser le dictionnaire de narratives
1261
+ narratives = {}
1262
+
1263
+ try:
1264
+ # Déterminer si nous sommes dans un cas de classification ou régression
1265
+ is_classifier = self._is_classifier()
1266
+
1267
+ # Récupérer les top N caractéristiques les plus importantes (en valeur absolue)
1268
+ top_n = 5
1269
+ important_features = []
1270
+
1271
+ if hasattr(lime_explanation, 'as_list'):
1272
+ label = getattr(lime_explanation, 'label', 0)
1273
+ features = lime_explanation.as_list(label=label)
1274
+ # Trier par importance absolue
1275
+ features.sort(key=lambda x: abs(x[1]), reverse=True)
1276
+ important_features = features[:top_n]
1277
+ elif hasattr(lime_explanation, 'local_exp'):
1278
+ # Pour les explainers texte/image
1279
+ label = list(lime_explanation.local_exp.keys())[0]
1280
+ features = [(feature_names[idx] if idx < len(feature_names) else f"feature_{idx}", imp)
1281
+ for idx, imp in lime_explanation.local_exp[label]]
1282
+ features.sort(key=lambda x: abs(x[1]), reverse=True)
1283
+ important_features = features[:top_n]
1284
+
1285
+ # Séparer les caractéristiques positives et négatives
1286
+ positive_features = [(name, importance) for name, importance in important_features if importance > 0]
1287
+ negative_features = [(name, importance) for name, importance in important_features if importance < 0]
1288
+
1289
+ # Générer la prédiction du modèle pour cette instance si disponible
1290
+ prediction = None
1291
+ pred_value = None
1292
+ confidence = None
1293
+
1294
+ try:
1295
+ # Obtenir la prédiction brute
1296
+ raw_prediction = self._model_predict_wrapper(instance)[0]
1297
+
1298
+ if is_classifier:
1299
+ if raw_prediction.ndim > 0 and len(raw_prediction) > 1:
1300
+ # Cas multi-classe
1301
+ pred_class = np.argmax(raw_prediction)
1302
+ confidence = float(raw_prediction[pred_class])
1303
+
1304
+ # Récupérer le nom de la classe si disponible
1305
+ if self._class_names and pred_class < len(self._class_names):
1306
+ prediction = self._class_names[pred_class]
1307
+ else:
1308
+ prediction = f"Classe {pred_class}"
1309
+ else:
1310
+ # Cas binaire
1311
+ pred_value = float(raw_prediction[0]) if raw_prediction.ndim > 0 else float(raw_prediction)
1312
+ threshold = 0.5
1313
+ pred_class = 1 if pred_value >= threshold else 0
1314
+
1315
+ if self._class_names and len(self._class_names) > 1:
1316
+ prediction = self._class_names[pred_class]
1317
+ else:
1318
+ prediction = "Positif" if pred_class == 1 else "Négatif"
1319
+
1320
+ confidence = pred_value if pred_class == 1 else 1 - pred_value
1321
+ else:
1322
+ # Cas régression
1323
+ pred_value = float(raw_prediction[0]) if raw_prediction.ndim > 0 else float(raw_prediction)
1324
+ prediction = f"{pred_value:.4f}"
1325
+ except Exception as e:
1326
+ self._logger.warning(f"Erreur lors de l'extraction de la prédiction: {str(e)}")
1327
+
1328
+ # Générer les narratives pour chaque niveau d'audience et selon la langue
1329
+
1330
+ # ===== NIVEAU TECHNIQUE =====
1331
+ if audience_level in ["technical", "all"]:
1332
+ technical_narrative = self._generate_technical_narrative(important_features, prediction, confidence,
1333
+ is_classifier, language)
1334
+ narratives["technical"] = technical_narrative
1335
+
1336
+ # ===== NIVEAU BUSINESS =====
1337
+ if audience_level in ["business", "all"]:
1338
+ business_narrative = self._generate_business_narrative(positive_features, negative_features,
1339
+ prediction, confidence, is_classifier, language)
1340
+ narratives["business"] = business_narrative
1341
+
1342
+ # ===== NIVEAU PUBLIC =====
1343
+ if audience_level in ["public", "all"]:
1344
+ public_narrative = self._generate_public_narrative(positive_features, negative_features,
1345
+ prediction, is_classifier, language)
1346
+ narratives["public"] = public_narrative
1347
+
1348
+ except Exception as e:
1349
+ self._logger.warning(f"Erreur lors de la génération de narrative: {str(e)}")
1350
+ import traceback
1351
+ self._logger.debug(traceback.format_exc())
1352
+
1353
+ # Fournir une narrative par défaut en cas d'erreur
1354
+ if language == "fr":
1355
+ narratives = {"technical": "Impossible de générer une explication narrative technique."}
1356
+ else:
1357
+ narratives = {"technical": "Unable to generate a technical narrative explanation."}
1358
+
1359
+ return narratives
1360
+
1361
+ def _generate_technical_narrative(self, important_features, prediction, confidence, is_classifier, language="en"):
1362
+ """
1363
+ Génère une narrative technique détaillée basée sur les résultats LIME.
1364
+
1365
+ Args:
1366
+ important_features: Liste des caractéristiques importantes et leurs valeurs
1367
+ prediction: Prédiction du modèle (classe ou valeur)
1368
+ confidence: Confiance de la prédiction (pour la classification)
1369
+ is_classifier: Indique si c'est un classificateur ou régresseur
1370
+ language: Langue de l'explication ("en", "fr")
1371
+
1372
+ Returns:
1373
+ str: Narrative technique
1374
+ """
1375
+ if language == "fr":
1376
+ # Version française
1377
+ if is_classifier:
1378
+ intro = f"Le modèle prédit la classe {prediction}"
1379
+ if confidence is not None:
1380
+ intro += f" avec une confiance de {confidence:.2%}."
1381
+ else:
1382
+ intro += "."
1383
+ else:
1384
+ intro = f"Le modèle prédit la valeur {prediction}."
1385
+
1386
+ # Détails des caractéristiques
1387
+ details = "D'après l'analyse LIME, les facteurs explicatifs les plus importants sont:\n"
1388
+
1389
+ for i, (name, importance) in enumerate(important_features):
1390
+ details += f"- {name}: impact de {importance:.4f} "
1391
+ if importance > 0:
1392
+ details += "(augmente la prédiction)"
1393
+ else:
1394
+ details += "(diminue la prédiction)"
1395
+ details += "\n"
1396
+
1397
+ # Ajouter des détails techniques
1398
+ conclusion = "\nL'algorithme LIME a généré un modèle local linéaire interprétable "
1399
+ conclusion += "qui approxime le comportement du modèle complexe dans le voisinage de cette instance. "
1400
+ conclusion += "Les coefficients représentent l'importance relative de chaque caractéristique dans la prédiction."
1401
+
1402
+ else:
1403
+ # Version anglaise (défaut)
1404
+ if is_classifier:
1405
+ intro = f"The model predicts class {prediction}"
1406
+ if confidence is not None:
1407
+ intro += f" with a confidence of {confidence:.2%}."
1408
+ else:
1409
+ intro += "."
1410
+ else:
1411
+ intro = f"The model predicts the value {prediction}."
1412
+
1413
+ # Feature details
1414
+ details = "According to LIME analysis, the most significant explanatory factors are:\n"
1415
+
1416
+ for i, (name, importance) in enumerate(important_features):
1417
+ details += f"- {name}: impact of {importance:.4f} "
1418
+ if importance > 0:
1419
+ details += "(increases the prediction)"
1420
+ else:
1421
+ details += "(decreases the prediction)"
1422
+ details += "\n"
1423
+
1424
+ # Add technical details
1425
+ conclusion = "\nThe LIME algorithm generated an interpretable linear local model "
1426
+ conclusion += "that approximates the behavior of the complex model in the vicinity of this instance. "
1427
+ conclusion += "The coefficients represent the relative importance of each feature in the prediction."
1428
+
1429
+ return intro + "\n\n" + details + conclusion
1430
+
1431
+ def _generate_business_narrative(self, positive_features, negative_features, prediction, confidence, is_classifier, language="en"):
1432
+ """
1433
+ Génère une narrative orientée business basée sur les résultats LIME.
1434
+
1435
+ Args:
1436
+ positive_features: Caractéristiques avec impact positif
1437
+ negative_features: Caractéristiques avec impact négatif
1438
+ prediction: Prédiction du modèle (classe ou valeur)
1439
+ confidence: Confiance de la prédiction
1440
+ is_classifier: Indique si c'est un classificateur ou régresseur
1441
+ language: Langue de l'explication ("en", "fr")
1442
+
1443
+ Returns:
1444
+ str: Narrative business
1445
+ """
1446
+ if language == "fr":
1447
+ # Version française
1448
+ if is_classifier:
1449
+ summary = f"Résultat: {prediction}"
1450
+ if confidence is not None:
1451
+ summary += f" (confiance: {confidence:.1%})\n\n"
1452
+ else:
1453
+ summary += "\n\n"
1454
+
1455
+ if confidence is not None and confidence < 0.7:
1456
+ summary += "Attention: La confiance du modèle dans cette prédiction est relativement faible.\n\n"
1457
+ else:
1458
+ summary = f"Résultat: La valeur prédite est {prediction}\n\n"
1459
+
1460
+ # Facteurs influents
1461
+ factors = "Principaux facteurs influents:\n"
1462
+
1463
+ if positive_features:
1464
+ factors += "\nFacteurs favorables:\n"
1465
+ for name, importance in positive_features:
1466
+ factors += f"- {name} (impact: +{abs(importance):.2f})\n"
1467
+
1468
+ if negative_features:
1469
+ factors += "\nFacteurs défavorables:\n"
1470
+ for name, importance in negative_features:
1471
+ factors += f"- {name} (impact: -{abs(importance):.2f})\n"
1472
+
1473
+ # Recommandations
1474
+ recommendations = "\nRecommandations:\n"
1475
+ if positive_features and not is_classifier:
1476
+ recommendations += "- Pour augmenter la prédiction, concentrez-vous sur l'amélioration des facteurs favorables.\n"
1477
+ elif negative_features and not is_classifier:
1478
+ recommendations += "- Pour diminuer la prédiction, réduisez l'impact des facteurs défavorables.\n"
1479
+ recommendations += "- Cette explication est basée sur LIME, une technique d'analyse locale du modèle."
1480
+
1481
+ else:
1482
+ # Version anglaise (défaut)
1483
+ if is_classifier:
1484
+ summary = f"Result: {prediction}"
1485
+ if confidence is not None:
1486
+ summary += f" (confidence: {confidence:.1%})\n\n"
1487
+ else:
1488
+ summary += "\n\n"
1489
+
1490
+ if confidence is not None and confidence < 0.7:
1491
+ summary += "Note: The model's confidence in this prediction is relatively low.\n\n"
1492
+ else:
1493
+ summary = f"Result: The predicted value is {prediction}\n\n"
1494
+
1495
+ # Influential factors
1496
+ factors = "Main influential factors:\n"
1497
+
1498
+ if positive_features:
1499
+ factors += "\nPositive factors:\n"
1500
+ for name, importance in positive_features:
1501
+ factors += f"- {name} (impact: +{abs(importance):.2f})\n"
1502
+
1503
+ if negative_features:
1504
+ factors += "\nNegative factors:\n"
1505
+ for name, importance in negative_features:
1506
+ factors += f"- {name} (impact: -{abs(importance):.2f})\n"
1507
+
1508
+ # Recommendations
1509
+ recommendations = "\nRecommendations:\n"
1510
+ if positive_features and not is_classifier:
1511
+ recommendations += "- To increase the prediction, focus on improving the positive factors.\n"
1512
+ elif negative_features and not is_classifier:
1513
+ recommendations += "- To decrease the prediction, reduce the impact of negative factors.\n"
1514
+ recommendations += "- This explanation is based on LIME, a local model analysis technique."
1515
+
1516
+ return summary + factors + recommendations
1517
+
1518
+ def _generate_public_narrative(self, positive_features, negative_features, prediction, is_classifier, language="en"):
1519
+ """
1520
+ Génère une narrative simplifiée pour le grand public.
1521
+
1522
+ Args:
1523
+ positive_features: Caractéristiques avec impact positif
1524
+ negative_features: Caractéristiques avec impact négatif
1525
+ prediction: Prédiction du modèle (classe ou valeur)
1526
+ is_classifier: Indique si c'est un classificateur ou régresseur
1527
+ language: Langue de l'explication ("en", "fr")
1528
+
1529
+ Returns:
1530
+ str: Narrative publique
1531
+ """
1532
+ # Limiter à 3 features maximum pour chaque catégorie
1533
+ pos_limited = positive_features[:3]
1534
+ neg_limited = negative_features[:3]
1535
+
1536
+ if language == "fr":
1537
+ # Version française
1538
+ if is_classifier:
1539
+ result = f"Le système a déterminé que le résultat est: {prediction}\n\n"
1540
+ else:
1541
+ result = f"Le système a estimé la valeur suivante: {prediction}\n\n"
1542
+
1543
+ explanation = "Voici pourquoi:\n"
1544
+
1545
+ if pos_limited:
1546
+ explanation += "\nPrincipalement à cause de:\n"
1547
+ for i, (name, _) in enumerate(pos_limited):
1548
+ explanation += f"- {name}\n"
1549
+
1550
+ if neg_limited:
1551
+ explanation += "\nMalgré:\n"
1552
+ for i, (name, _) in enumerate(neg_limited):
1553
+ explanation += f"- {name}\n"
1554
+
1555
+ if not pos_limited and not neg_limited:
1556
+ explanation += "\nLe système n'a pas pu identifier de facteurs clairement déterminants pour cette prédiction."
1557
+
1558
+ else:
1559
+ # Version anglaise (défaut)
1560
+ if is_classifier:
1561
+ result = f"The system has determined that the result is: {prediction}\n\n"
1562
+ else:
1563
+ result = f"The system has estimated the following value: {prediction}\n\n"
1564
+
1565
+ explanation = "Here's why:\n"
1566
+
1567
+ if pos_limited:
1568
+ explanation += "\nMainly because of:\n"
1569
+ for i, (name, _) in enumerate(pos_limited):
1570
+ explanation += f"- {name}\n"
1571
+
1572
+ if neg_limited:
1573
+ explanation += "\nDespite:\n"
1574
+ for i, (name, _) in enumerate(neg_limited):
1575
+ explanation += f"- {name}\n"
1576
+
1577
+ if not pos_limited and not neg_limited:
1578
+ explanation += "\nThe system could not identify clearly determining factors for this prediction."
1579
+
1580
+ return result + explanation