edsl 0.1.15__py3-none-any.whl → 0.1.40__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 (407) hide show
  1. edsl/Base.py +348 -38
  2. edsl/BaseDiff.py +260 -0
  3. edsl/TemplateLoader.py +24 -0
  4. edsl/__init__.py +45 -10
  5. edsl/__version__.py +1 -1
  6. edsl/agents/Agent.py +842 -144
  7. edsl/agents/AgentList.py +521 -25
  8. edsl/agents/Invigilator.py +250 -374
  9. edsl/agents/InvigilatorBase.py +257 -0
  10. edsl/agents/PromptConstructor.py +272 -0
  11. edsl/agents/QuestionInstructionPromptBuilder.py +128 -0
  12. edsl/agents/QuestionTemplateReplacementsBuilder.py +137 -0
  13. edsl/agents/descriptors.py +43 -13
  14. edsl/agents/prompt_helpers.py +129 -0
  15. edsl/agents/question_option_processor.py +172 -0
  16. edsl/auto/AutoStudy.py +130 -0
  17. edsl/auto/StageBase.py +243 -0
  18. edsl/auto/StageGenerateSurvey.py +178 -0
  19. edsl/auto/StageLabelQuestions.py +125 -0
  20. edsl/auto/StagePersona.py +61 -0
  21. edsl/auto/StagePersonaDimensionValueRanges.py +88 -0
  22. edsl/auto/StagePersonaDimensionValues.py +74 -0
  23. edsl/auto/StagePersonaDimensions.py +69 -0
  24. edsl/auto/StageQuestions.py +74 -0
  25. edsl/auto/SurveyCreatorPipeline.py +21 -0
  26. edsl/auto/utilities.py +218 -0
  27. edsl/base/Base.py +279 -0
  28. edsl/config.py +115 -113
  29. edsl/conversation/Conversation.py +290 -0
  30. edsl/conversation/car_buying.py +59 -0
  31. edsl/conversation/chips.py +95 -0
  32. edsl/conversation/mug_negotiation.py +81 -0
  33. edsl/conversation/next_speaker_utilities.py +93 -0
  34. edsl/coop/CoopFunctionsMixin.py +15 -0
  35. edsl/coop/ExpectedParrotKeyHandler.py +125 -0
  36. edsl/coop/PriceFetcher.py +54 -0
  37. edsl/coop/__init__.py +1 -0
  38. edsl/coop/coop.py +1029 -134
  39. edsl/coop/utils.py +131 -0
  40. edsl/data/Cache.py +560 -89
  41. edsl/data/CacheEntry.py +230 -0
  42. edsl/data/CacheHandler.py +168 -0
  43. edsl/data/RemoteCacheSync.py +186 -0
  44. edsl/data/SQLiteDict.py +292 -0
  45. edsl/data/__init__.py +5 -3
  46. edsl/data/orm.py +6 -33
  47. edsl/data_transfer_models.py +74 -27
  48. edsl/enums.py +165 -8
  49. edsl/exceptions/BaseException.py +21 -0
  50. edsl/exceptions/__init__.py +52 -46
  51. edsl/exceptions/agents.py +33 -15
  52. edsl/exceptions/cache.py +5 -0
  53. edsl/exceptions/coop.py +8 -0
  54. edsl/exceptions/general.py +34 -0
  55. edsl/exceptions/inference_services.py +5 -0
  56. edsl/exceptions/jobs.py +15 -0
  57. edsl/exceptions/language_models.py +46 -1
  58. edsl/exceptions/questions.py +80 -5
  59. edsl/exceptions/results.py +16 -5
  60. edsl/exceptions/scenarios.py +29 -0
  61. edsl/exceptions/surveys.py +13 -10
  62. edsl/inference_services/AnthropicService.py +106 -0
  63. edsl/inference_services/AvailableModelCacheHandler.py +184 -0
  64. edsl/inference_services/AvailableModelFetcher.py +215 -0
  65. edsl/inference_services/AwsBedrock.py +118 -0
  66. edsl/inference_services/AzureAI.py +215 -0
  67. edsl/inference_services/DeepInfraService.py +18 -0
  68. edsl/inference_services/GoogleService.py +143 -0
  69. edsl/inference_services/GroqService.py +20 -0
  70. edsl/inference_services/InferenceServiceABC.py +80 -0
  71. edsl/inference_services/InferenceServicesCollection.py +138 -0
  72. edsl/inference_services/MistralAIService.py +120 -0
  73. edsl/inference_services/OllamaService.py +18 -0
  74. edsl/inference_services/OpenAIService.py +236 -0
  75. edsl/inference_services/PerplexityService.py +160 -0
  76. edsl/inference_services/ServiceAvailability.py +135 -0
  77. edsl/inference_services/TestService.py +90 -0
  78. edsl/inference_services/TogetherAIService.py +172 -0
  79. edsl/inference_services/data_structures.py +134 -0
  80. edsl/inference_services/models_available_cache.py +118 -0
  81. edsl/inference_services/rate_limits_cache.py +25 -0
  82. edsl/inference_services/registry.py +41 -0
  83. edsl/inference_services/write_available.py +10 -0
  84. edsl/jobs/AnswerQuestionFunctionConstructor.py +223 -0
  85. edsl/jobs/Answers.py +21 -20
  86. edsl/jobs/FetchInvigilator.py +47 -0
  87. edsl/jobs/InterviewTaskManager.py +98 -0
  88. edsl/jobs/InterviewsConstructor.py +50 -0
  89. edsl/jobs/Jobs.py +684 -206
  90. edsl/jobs/JobsChecks.py +172 -0
  91. edsl/jobs/JobsComponentConstructor.py +189 -0
  92. edsl/jobs/JobsPrompts.py +270 -0
  93. edsl/jobs/JobsRemoteInferenceHandler.py +311 -0
  94. edsl/jobs/JobsRemoteInferenceLogger.py +239 -0
  95. edsl/jobs/RequestTokenEstimator.py +30 -0
  96. edsl/jobs/async_interview_runner.py +138 -0
  97. edsl/jobs/buckets/BucketCollection.py +104 -0
  98. edsl/jobs/buckets/ModelBuckets.py +65 -0
  99. edsl/jobs/buckets/TokenBucket.py +283 -0
  100. edsl/jobs/buckets/TokenBucketAPI.py +211 -0
  101. edsl/jobs/buckets/TokenBucketClient.py +191 -0
  102. edsl/jobs/check_survey_scenario_compatibility.py +85 -0
  103. edsl/jobs/data_structures.py +120 -0
  104. edsl/jobs/decorators.py +35 -0
  105. edsl/jobs/interviews/Interview.py +392 -0
  106. edsl/jobs/interviews/InterviewExceptionCollection.py +99 -0
  107. edsl/jobs/interviews/InterviewExceptionEntry.py +186 -0
  108. edsl/jobs/interviews/InterviewStatistic.py +63 -0
  109. edsl/jobs/interviews/InterviewStatisticsCollection.py +25 -0
  110. edsl/jobs/interviews/InterviewStatusDictionary.py +78 -0
  111. edsl/jobs/interviews/InterviewStatusLog.py +92 -0
  112. edsl/jobs/interviews/ReportErrors.py +66 -0
  113. edsl/jobs/interviews/interview_status_enum.py +9 -0
  114. edsl/jobs/jobs_status_enums.py +9 -0
  115. edsl/jobs/loggers/HTMLTableJobLogger.py +304 -0
  116. edsl/jobs/results_exceptions_handler.py +98 -0
  117. edsl/jobs/runners/JobsRunnerAsyncio.py +151 -110
  118. edsl/jobs/runners/JobsRunnerStatus.py +298 -0
  119. edsl/jobs/tasks/QuestionTaskCreator.py +244 -0
  120. edsl/jobs/tasks/TaskCreators.py +64 -0
  121. edsl/jobs/tasks/TaskHistory.py +470 -0
  122. edsl/jobs/tasks/TaskStatusLog.py +23 -0
  123. edsl/jobs/tasks/task_status_enum.py +161 -0
  124. edsl/jobs/tokens/InterviewTokenUsage.py +27 -0
  125. edsl/jobs/tokens/TokenUsage.py +34 -0
  126. edsl/language_models/ComputeCost.py +63 -0
  127. edsl/language_models/LanguageModel.py +507 -386
  128. edsl/language_models/ModelList.py +164 -0
  129. edsl/language_models/PriceManager.py +127 -0
  130. edsl/language_models/RawResponseHandler.py +106 -0
  131. edsl/language_models/RegisterLanguageModelsMeta.py +184 -0
  132. edsl/language_models/__init__.py +1 -8
  133. edsl/language_models/fake_openai_call.py +15 -0
  134. edsl/language_models/fake_openai_service.py +61 -0
  135. edsl/language_models/key_management/KeyLookup.py +63 -0
  136. edsl/language_models/key_management/KeyLookupBuilder.py +273 -0
  137. edsl/language_models/key_management/KeyLookupCollection.py +38 -0
  138. edsl/language_models/key_management/__init__.py +0 -0
  139. edsl/language_models/key_management/models.py +131 -0
  140. edsl/language_models/model.py +256 -0
  141. edsl/language_models/repair.py +109 -41
  142. edsl/language_models/utilities.py +65 -0
  143. edsl/notebooks/Notebook.py +263 -0
  144. edsl/notebooks/NotebookToLaTeX.py +142 -0
  145. edsl/notebooks/__init__.py +1 -0
  146. edsl/prompts/Prompt.py +222 -93
  147. edsl/prompts/__init__.py +1 -1
  148. edsl/questions/ExceptionExplainer.py +77 -0
  149. edsl/questions/HTMLQuestion.py +103 -0
  150. edsl/questions/QuestionBase.py +518 -0
  151. edsl/questions/QuestionBasePromptsMixin.py +221 -0
  152. edsl/questions/QuestionBudget.py +164 -67
  153. edsl/questions/QuestionCheckBox.py +281 -62
  154. edsl/questions/QuestionDict.py +343 -0
  155. edsl/questions/QuestionExtract.py +136 -50
  156. edsl/questions/QuestionFreeText.py +79 -55
  157. edsl/questions/QuestionFunctional.py +138 -41
  158. edsl/questions/QuestionList.py +184 -57
  159. edsl/questions/QuestionMatrix.py +265 -0
  160. edsl/questions/QuestionMultipleChoice.py +293 -69
  161. edsl/questions/QuestionNumerical.py +109 -56
  162. edsl/questions/QuestionRank.py +244 -49
  163. edsl/questions/Quick.py +41 -0
  164. edsl/questions/SimpleAskMixin.py +74 -0
  165. edsl/questions/__init__.py +9 -6
  166. edsl/questions/{AnswerValidatorMixin.py → answer_validator_mixin.py} +153 -38
  167. edsl/questions/compose_questions.py +13 -7
  168. edsl/questions/data_structures.py +20 -0
  169. edsl/questions/decorators.py +21 -0
  170. edsl/questions/derived/QuestionLikertFive.py +28 -26
  171. edsl/questions/derived/QuestionLinearScale.py +41 -28
  172. edsl/questions/derived/QuestionTopK.py +34 -26
  173. edsl/questions/derived/QuestionYesNo.py +40 -27
  174. edsl/questions/descriptors.py +228 -74
  175. edsl/questions/loop_processor.py +149 -0
  176. edsl/questions/prompt_templates/question_budget.jinja +13 -0
  177. edsl/questions/prompt_templates/question_checkbox.jinja +32 -0
  178. edsl/questions/prompt_templates/question_extract.jinja +11 -0
  179. edsl/questions/prompt_templates/question_free_text.jinja +3 -0
  180. edsl/questions/prompt_templates/question_linear_scale.jinja +11 -0
  181. edsl/questions/prompt_templates/question_list.jinja +17 -0
  182. edsl/questions/prompt_templates/question_multiple_choice.jinja +33 -0
  183. edsl/questions/prompt_templates/question_numerical.jinja +37 -0
  184. edsl/questions/question_base_gen_mixin.py +168 -0
  185. edsl/questions/question_registry.py +130 -46
  186. edsl/questions/register_questions_meta.py +71 -0
  187. edsl/questions/response_validator_abc.py +188 -0
  188. edsl/questions/response_validator_factory.py +34 -0
  189. edsl/questions/settings.py +5 -2
  190. edsl/questions/templates/__init__.py +0 -0
  191. edsl/questions/templates/budget/__init__.py +0 -0
  192. edsl/questions/templates/budget/answering_instructions.jinja +7 -0
  193. edsl/questions/templates/budget/question_presentation.jinja +7 -0
  194. edsl/questions/templates/checkbox/__init__.py +0 -0
  195. edsl/questions/templates/checkbox/answering_instructions.jinja +10 -0
  196. edsl/questions/templates/checkbox/question_presentation.jinja +22 -0
  197. edsl/questions/templates/dict/__init__.py +0 -0
  198. edsl/questions/templates/dict/answering_instructions.jinja +21 -0
  199. edsl/questions/templates/dict/question_presentation.jinja +1 -0
  200. edsl/questions/templates/extract/__init__.py +0 -0
  201. edsl/questions/templates/extract/answering_instructions.jinja +7 -0
  202. edsl/questions/templates/extract/question_presentation.jinja +1 -0
  203. edsl/questions/templates/free_text/__init__.py +0 -0
  204. edsl/questions/templates/free_text/answering_instructions.jinja +0 -0
  205. edsl/questions/templates/free_text/question_presentation.jinja +1 -0
  206. edsl/questions/templates/likert_five/__init__.py +0 -0
  207. edsl/questions/templates/likert_five/answering_instructions.jinja +10 -0
  208. edsl/questions/templates/likert_five/question_presentation.jinja +12 -0
  209. edsl/questions/templates/linear_scale/__init__.py +0 -0
  210. edsl/questions/templates/linear_scale/answering_instructions.jinja +5 -0
  211. edsl/questions/templates/linear_scale/question_presentation.jinja +5 -0
  212. edsl/questions/templates/list/__init__.py +0 -0
  213. edsl/questions/templates/list/answering_instructions.jinja +4 -0
  214. edsl/questions/templates/list/question_presentation.jinja +5 -0
  215. edsl/questions/templates/matrix/__init__.py +1 -0
  216. edsl/questions/templates/matrix/answering_instructions.jinja +5 -0
  217. edsl/questions/templates/matrix/question_presentation.jinja +20 -0
  218. edsl/questions/templates/multiple_choice/__init__.py +0 -0
  219. edsl/questions/templates/multiple_choice/answering_instructions.jinja +9 -0
  220. edsl/questions/templates/multiple_choice/html.jinja +0 -0
  221. edsl/questions/templates/multiple_choice/question_presentation.jinja +12 -0
  222. edsl/questions/templates/numerical/__init__.py +0 -0
  223. edsl/questions/templates/numerical/answering_instructions.jinja +7 -0
  224. edsl/questions/templates/numerical/question_presentation.jinja +7 -0
  225. edsl/questions/templates/rank/__init__.py +0 -0
  226. edsl/questions/templates/rank/answering_instructions.jinja +11 -0
  227. edsl/questions/templates/rank/question_presentation.jinja +15 -0
  228. edsl/questions/templates/top_k/__init__.py +0 -0
  229. edsl/questions/templates/top_k/answering_instructions.jinja +8 -0
  230. edsl/questions/templates/top_k/question_presentation.jinja +22 -0
  231. edsl/questions/templates/yes_no/__init__.py +0 -0
  232. edsl/questions/templates/yes_no/answering_instructions.jinja +6 -0
  233. edsl/questions/templates/yes_no/question_presentation.jinja +12 -0
  234. edsl/results/CSSParameterizer.py +108 -0
  235. edsl/results/Dataset.py +550 -19
  236. edsl/results/DatasetExportMixin.py +594 -0
  237. edsl/results/DatasetTree.py +295 -0
  238. edsl/results/MarkdownToDocx.py +122 -0
  239. edsl/results/MarkdownToPDF.py +111 -0
  240. edsl/results/Result.py +477 -173
  241. edsl/results/Results.py +987 -269
  242. edsl/results/ResultsExportMixin.py +28 -125
  243. edsl/results/ResultsGGMixin.py +83 -15
  244. edsl/results/TableDisplay.py +125 -0
  245. edsl/results/TextEditor.py +50 -0
  246. edsl/results/__init__.py +1 -1
  247. edsl/results/file_exports.py +252 -0
  248. edsl/results/results_fetch_mixin.py +33 -0
  249. edsl/results/results_selector.py +145 -0
  250. edsl/results/results_tools_mixin.py +98 -0
  251. edsl/results/smart_objects.py +96 -0
  252. edsl/results/table_data_class.py +12 -0
  253. edsl/results/table_display.css +78 -0
  254. edsl/results/table_renderers.py +118 -0
  255. edsl/results/tree_explore.py +115 -0
  256. edsl/scenarios/ConstructDownloadLink.py +109 -0
  257. edsl/scenarios/DocumentChunker.py +102 -0
  258. edsl/scenarios/DocxScenario.py +16 -0
  259. edsl/scenarios/FileStore.py +543 -0
  260. edsl/scenarios/PdfExtractor.py +40 -0
  261. edsl/scenarios/Scenario.py +431 -62
  262. edsl/scenarios/ScenarioHtmlMixin.py +65 -0
  263. edsl/scenarios/ScenarioList.py +1415 -45
  264. edsl/scenarios/ScenarioListExportMixin.py +45 -0
  265. edsl/scenarios/ScenarioListPdfMixin.py +239 -0
  266. edsl/scenarios/__init__.py +2 -0
  267. edsl/scenarios/directory_scanner.py +96 -0
  268. edsl/scenarios/file_methods.py +85 -0
  269. edsl/scenarios/handlers/__init__.py +13 -0
  270. edsl/scenarios/handlers/csv.py +49 -0
  271. edsl/scenarios/handlers/docx.py +76 -0
  272. edsl/scenarios/handlers/html.py +37 -0
  273. edsl/scenarios/handlers/json.py +111 -0
  274. edsl/scenarios/handlers/latex.py +5 -0
  275. edsl/scenarios/handlers/md.py +51 -0
  276. edsl/scenarios/handlers/pdf.py +68 -0
  277. edsl/scenarios/handlers/png.py +39 -0
  278. edsl/scenarios/handlers/pptx.py +105 -0
  279. edsl/scenarios/handlers/py.py +294 -0
  280. edsl/scenarios/handlers/sql.py +313 -0
  281. edsl/scenarios/handlers/sqlite.py +149 -0
  282. edsl/scenarios/handlers/txt.py +33 -0
  283. edsl/scenarios/scenario_join.py +131 -0
  284. edsl/scenarios/scenario_selector.py +156 -0
  285. edsl/shared.py +1 -0
  286. edsl/study/ObjectEntry.py +173 -0
  287. edsl/study/ProofOfWork.py +113 -0
  288. edsl/study/SnapShot.py +80 -0
  289. edsl/study/Study.py +521 -0
  290. edsl/study/__init__.py +4 -0
  291. edsl/surveys/ConstructDAG.py +92 -0
  292. edsl/surveys/DAG.py +92 -11
  293. edsl/surveys/EditSurvey.py +221 -0
  294. edsl/surveys/InstructionHandler.py +100 -0
  295. edsl/surveys/Memory.py +9 -4
  296. edsl/surveys/MemoryManagement.py +72 -0
  297. edsl/surveys/MemoryPlan.py +156 -35
  298. edsl/surveys/Rule.py +221 -74
  299. edsl/surveys/RuleCollection.py +241 -61
  300. edsl/surveys/RuleManager.py +172 -0
  301. edsl/surveys/Simulator.py +75 -0
  302. edsl/surveys/Survey.py +1079 -339
  303. edsl/surveys/SurveyCSS.py +273 -0
  304. edsl/surveys/SurveyExportMixin.py +235 -40
  305. edsl/surveys/SurveyFlowVisualization.py +181 -0
  306. edsl/surveys/SurveyQualtricsImport.py +284 -0
  307. edsl/surveys/SurveyToApp.py +141 -0
  308. edsl/surveys/__init__.py +4 -2
  309. edsl/surveys/base.py +19 -3
  310. edsl/surveys/descriptors.py +17 -6
  311. edsl/surveys/instructions/ChangeInstruction.py +48 -0
  312. edsl/surveys/instructions/Instruction.py +56 -0
  313. edsl/surveys/instructions/InstructionCollection.py +82 -0
  314. edsl/surveys/instructions/__init__.py +0 -0
  315. edsl/templates/error_reporting/base.html +24 -0
  316. edsl/templates/error_reporting/exceptions_by_model.html +35 -0
  317. edsl/templates/error_reporting/exceptions_by_question_name.html +17 -0
  318. edsl/templates/error_reporting/exceptions_by_type.html +17 -0
  319. edsl/templates/error_reporting/interview_details.html +116 -0
  320. edsl/templates/error_reporting/interviews.html +19 -0
  321. edsl/templates/error_reporting/overview.html +5 -0
  322. edsl/templates/error_reporting/performance_plot.html +2 -0
  323. edsl/templates/error_reporting/report.css +74 -0
  324. edsl/templates/error_reporting/report.html +118 -0
  325. edsl/templates/error_reporting/report.js +25 -0
  326. edsl/tools/__init__.py +1 -0
  327. edsl/tools/clusters.py +192 -0
  328. edsl/tools/embeddings.py +27 -0
  329. edsl/tools/embeddings_plotting.py +118 -0
  330. edsl/tools/plotting.py +112 -0
  331. edsl/tools/summarize.py +18 -0
  332. edsl/utilities/PrettyList.py +56 -0
  333. edsl/utilities/SystemInfo.py +5 -0
  334. edsl/utilities/__init__.py +21 -20
  335. edsl/utilities/ast_utilities.py +3 -0
  336. edsl/utilities/data/Registry.py +2 -0
  337. edsl/utilities/decorators.py +41 -0
  338. edsl/utilities/gcp_bucket/__init__.py +0 -0
  339. edsl/utilities/gcp_bucket/cloud_storage.py +96 -0
  340. edsl/utilities/interface.py +310 -60
  341. edsl/utilities/is_notebook.py +18 -0
  342. edsl/utilities/is_valid_variable_name.py +11 -0
  343. edsl/utilities/naming_utilities.py +263 -0
  344. edsl/utilities/remove_edsl_version.py +24 -0
  345. edsl/utilities/repair_functions.py +28 -0
  346. edsl/utilities/restricted_python.py +70 -0
  347. edsl/utilities/utilities.py +203 -13
  348. edsl-0.1.40.dist-info/METADATA +111 -0
  349. edsl-0.1.40.dist-info/RECORD +362 -0
  350. {edsl-0.1.15.dist-info → edsl-0.1.40.dist-info}/WHEEL +1 -1
  351. edsl/agents/AgentListExportMixin.py +0 -24
  352. edsl/coop/old.py +0 -31
  353. edsl/data/Database.py +0 -141
  354. edsl/data/crud.py +0 -121
  355. edsl/jobs/Interview.py +0 -435
  356. edsl/jobs/JobsRunner.py +0 -63
  357. edsl/jobs/JobsRunnerStatusMixin.py +0 -115
  358. edsl/jobs/base.py +0 -47
  359. edsl/jobs/buckets.py +0 -178
  360. edsl/jobs/runners/JobsRunnerDryRun.py +0 -19
  361. edsl/jobs/runners/JobsRunnerStreaming.py +0 -54
  362. edsl/jobs/task_management.py +0 -215
  363. edsl/jobs/token_tracking.py +0 -78
  364. edsl/language_models/DeepInfra.py +0 -69
  365. edsl/language_models/OpenAI.py +0 -98
  366. edsl/language_models/model_interfaces/GeminiPro.py +0 -66
  367. edsl/language_models/model_interfaces/LanguageModelOpenAIFour.py +0 -8
  368. edsl/language_models/model_interfaces/LanguageModelOpenAIThreeFiveTurbo.py +0 -8
  369. edsl/language_models/model_interfaces/LlamaTwo13B.py +0 -21
  370. edsl/language_models/model_interfaces/LlamaTwo70B.py +0 -21
  371. edsl/language_models/model_interfaces/Mixtral8x7B.py +0 -24
  372. edsl/language_models/registry.py +0 -81
  373. edsl/language_models/schemas.py +0 -15
  374. edsl/language_models/unused/ReplicateBase.py +0 -83
  375. edsl/prompts/QuestionInstructionsBase.py +0 -6
  376. edsl/prompts/library/agent_instructions.py +0 -29
  377. edsl/prompts/library/agent_persona.py +0 -17
  378. edsl/prompts/library/question_budget.py +0 -26
  379. edsl/prompts/library/question_checkbox.py +0 -32
  380. edsl/prompts/library/question_extract.py +0 -19
  381. edsl/prompts/library/question_freetext.py +0 -14
  382. edsl/prompts/library/question_linear_scale.py +0 -20
  383. edsl/prompts/library/question_list.py +0 -22
  384. edsl/prompts/library/question_multiple_choice.py +0 -44
  385. edsl/prompts/library/question_numerical.py +0 -31
  386. edsl/prompts/library/question_rank.py +0 -21
  387. edsl/prompts/prompt_config.py +0 -33
  388. edsl/prompts/registry.py +0 -185
  389. edsl/questions/Question.py +0 -240
  390. edsl/report/InputOutputDataTypes.py +0 -134
  391. edsl/report/RegressionMixin.py +0 -28
  392. edsl/report/ReportOutputs.py +0 -1228
  393. edsl/report/ResultsFetchMixin.py +0 -106
  394. edsl/report/ResultsOutputMixin.py +0 -14
  395. edsl/report/demo.ipynb +0 -645
  396. edsl/results/ResultsDBMixin.py +0 -184
  397. edsl/surveys/SurveyFlowVisualizationMixin.py +0 -92
  398. edsl/trackers/Tracker.py +0 -91
  399. edsl/trackers/TrackerAPI.py +0 -196
  400. edsl/trackers/TrackerTasks.py +0 -70
  401. edsl/utilities/pastebin.py +0 -141
  402. edsl-0.1.15.dist-info/METADATA +0 -69
  403. edsl-0.1.15.dist-info/RECORD +0 -142
  404. /edsl/{language_models/model_interfaces → inference_services}/__init__.py +0 -0
  405. /edsl/{report/__init__.py → jobs/runners/JobsRunnerStatusData.py} +0 -0
  406. /edsl/{trackers/__init__.py → language_models/ServiceDataSources.py} +0 -0
  407. {edsl-0.1.15.dist-info → edsl-0.1.40.dist-info}/LICENSE +0 -0
@@ -1,142 +1,45 @@
1
- import base64
2
- import csv
3
- import io
4
- from IPython.display import HTML, display
5
- import pandas as pd
6
- from edsl.utilities import (
7
- print_list_of_dicts_with_rich,
8
- print_list_of_dicts_as_html_table,
9
- print_dict_with_rich,
10
- )
1
+ """Mixin class for exporting results."""
11
2
 
3
+ from functools import wraps
4
+ from typing import Literal, Optional, Union
12
5
 
13
- class ResultsExportMixin:
14
- def convert_decorator(func):
15
- def wrapper(self, *args, **kwargs):
16
- if self.__class__.__name__ == "Results":
17
- return func(self.select(), *args, **kwargs)
18
- elif self.__class__.__name__ == "Dataset":
19
- return func(self, *args, **kwargs)
20
- else:
21
- raise Exception(
22
- f"Class {self.__class__.__name__} not recognized as a Results or Dataset object."
23
- )
6
+ from edsl.results.DatasetExportMixin import DatasetExportMixin
24
7
 
25
- return wrapper
26
8
 
27
- @convert_decorator
28
- def _make_tabular(self, remove_prefix) -> tuple[list, list]:
29
- "Helper function that turns the results into a tabular format."
30
- d = {}
31
- full_header = sorted(list(self.relevant_columns()))
32
- for entry in self.data:
33
- key, list_of_values = list(entry.items())[0]
34
- d[key] = list_of_values
35
- if remove_prefix:
36
- header = [h.split(".")[-1] for h in full_header]
37
- else:
38
- header = full_header
39
- num_observations = len(list(self[0].values())[0])
40
- rows = []
41
- # rows.append(header)
42
- for i in range(num_observations):
43
- row = [d[h][i] for h in full_header]
44
- rows.append(row)
45
- return header, rows
46
-
47
- def print_long(self):
48
- """ """
49
- for result in self:
50
- if hasattr(result, "combined_dict"):
51
- d = result.combined_dict
52
- else:
53
- d = result
54
- print_dict_with_rich(d)
55
-
56
- @convert_decorator
57
- def print(
58
- self,
59
- pretty_labels=None,
60
- filename=None,
61
- html=False,
62
- interactive=False,
63
- split_at_dot=True,
64
- ):
65
- if pretty_labels is None:
66
- pretty_labels = {}
9
+ def to_dataset(func):
10
+ """Convert the Results object to a Dataset object before calling the function."""
67
11
 
68
- new_data = []
69
- for entry in self:
70
- key, list_of_values = list(entry.items())[0]
71
- new_data.append({pretty_labels.get(key, key): list_of_values})
12
+ @wraps(func)
13
+ def wrapper(self, *args, **kwargs):
14
+ """Return the function with the Results object converted to a Dataset object."""
15
+ if self.__class__.__name__ == "Results":
16
+ return func(self.select(), *args, **kwargs)
17
+ elif self.__class__.__name__ == "AgentList":
18
+ return func(self.to_dataset(), *args, **kwargs)
72
19
  else:
73
- if not html:
74
- print_list_of_dicts_with_rich(
75
- new_data, filename=filename, split_at_dot=split_at_dot
76
- )
77
- else:
78
- print_list_of_dicts_as_html_table(
79
- new_data, filename=None, interactive=interactive
80
- )
20
+ return func(self, *args, **kwargs)
81
21
 
82
- @convert_decorator
83
- def to_csv(self, filename: str = None, remove_prefix=False, download_link=False):
84
- """
85
- >>> r = create_example_results()
86
- >>> r.select('how_feeling').to_csv()
87
- 'result.how_feeling\\r\\nBad\\r\\nBad\\r\\nGreat\\r\\nGreat\\r\\n'
88
- """
89
- header, rows = self._make_tabular(remove_prefix)
22
+ wrapper._is_wrapped = True
23
+ return wrapper
90
24
 
91
- if filename is not None:
92
- with open(filename, "w") as f:
93
- writer = csv.writer(f)
94
- writer.writerow(header)
95
- writer.writerows(rows)
96
- else:
97
- output = io.StringIO()
98
- writer = csv.writer(output)
99
- writer.writerow(header)
100
- writer.writerows(rows)
101
25
 
102
- if download_link:
103
- csv_file = output.getvalue()
104
- b64 = base64.b64encode(csv_file.encode()).decode()
105
- download_link = f'<a href="data:file/csv;base64,{b64}" download="my_data.csv">Download CSV file</a>'
106
- display(HTML(download_link))
107
- else:
108
- return output.getvalue()
26
+ def decorate_methods_from_mixin(cls, mixin_cls):
27
+ for attr_name, attr_value in mixin_cls.__dict__.items():
28
+ if callable(attr_value) and not attr_name.startswith("__"):
29
+ setattr(cls, attr_name, to_dataset(attr_value))
30
+ return cls
109
31
 
110
- @convert_decorator
111
- def to_pandas(self, remove_prefix=False):
112
- csv_string = self.to_csv(remove_prefix=remove_prefix)
113
- csv_buffer = io.StringIO(csv_string)
114
- df = pd.read_csv(csv_buffer)
115
- df_sorted = df.sort_index(axis=1) # Sort columns alphabetically
116
- return df_sorted
117
- # return df
118
32
 
119
- @convert_decorator
120
- def to_dicts(self, remove_prefix=False):
121
- df = self.to_pandas(remove_prefix=remove_prefix)
122
- df = df.convert_dtypes()
123
- list_of_dicts = df.to_dict(orient="records")
124
- # Convert any pd.NA values to None
125
- list_of_dicts = [
126
- {k: (None if pd.isna(v) else v) for k, v in record.items()}
127
- for record in list_of_dicts
128
- ]
129
- return list_of_dicts
33
+ class ResultsExportMixin(DatasetExportMixin):
34
+ """Mixin class for exporting Results objects."""
130
35
 
131
- @convert_decorator
132
- def to_list(self):
133
- if len(self) == 1:
134
- return list(self[0].values())[0]
135
- else:
136
- return tuple([list(x.values())[0] for x in self])
36
+ def __init_subclass__(cls, **kwargs):
37
+ super().__init_subclass__(**kwargs)
38
+ decorate_methods_from_mixin(cls, DatasetExportMixin)
137
39
 
138
40
 
139
41
  if __name__ == "__main__":
42
+ # pass
140
43
  import doctest
141
44
 
142
- doctest.testmod()
45
+ doctest.testmod(optionflags=doctest.ELLIPSIS)
@@ -1,17 +1,47 @@
1
+ """Mixin class for ggplot2 plotting."""
2
+
1
3
  import subprocess
2
- import pandas as pd
3
4
  import tempfile
4
- import matplotlib.pyplot as plt
5
- import matplotlib.image as mpimg
5
+ from typing import Optional
6
6
 
7
7
 
8
8
  class ResultsGGMixin:
9
- def ggplot2(self, ggplot_code: str, filename=None, shape="wide"):
10
- # Fetching DataFrame based on shape
9
+ """Mixin class for ggplot2 plotting."""
10
+
11
+ def ggplot2(
12
+ self,
13
+ ggplot_code: str,
14
+ filename: str = None,
15
+ shape="wide",
16
+ sql: str = None,
17
+ remove_prefix: bool = True,
18
+ debug: bool = False,
19
+ height=4,
20
+ width=6,
21
+ format="svg",
22
+ factor_orders: Optional[dict] = None,
23
+ ):
24
+ """Create a ggplot2 plot from a DataFrame.
25
+
26
+ :param ggplot_code: The ggplot2 code to execute.
27
+ :param filename: The filename to save the plot to.
28
+ :param shape: The shape of the data in the DataFrame (wide or long).
29
+ :param sql: The SQL query to execute beforehand to manipulate the data.
30
+ :param remove_prefix: Whether to remove the prefix from the column names.
31
+ :param debug: Whether to print the R code instead of executing it.
32
+ :param height: The height of the plot in inches.
33
+ :param width: The width of the plot in inches.
34
+ :param format: The format to save the plot in (png or svg).
35
+ :param factor_orders: A dictionary of factor columns and their order.
36
+ """
37
+
38
+ if sql == None:
39
+ sql = "select * from self"
40
+
11
41
  if shape == "long":
12
- df = self.sql("select * from self", shape="long")
42
+ df = self.sql(sql, shape="long")
13
43
  elif shape == "wide":
14
- df = self.sql("select * from self", shape="wide", remove_prefix=True)
44
+ df = self.sql(sql, shape="wide", remove_prefix=remove_prefix)
15
45
 
16
46
  # Convert DataFrame to CSV format
17
47
  csv_data = df.to_csv(index=False)
@@ -20,18 +50,32 @@ class ResultsGGMixin:
20
50
  csv_data_escaped = csv_data.replace("\n", "\\n").replace("'", "\\'")
21
51
  read_csv_code = f"self <- read.csv(text = '{csv_data_escaped}', sep = ',')\n"
22
52
 
53
+ if factor_orders is not None:
54
+ for factor, order in factor_orders.items():
55
+ # read_csv_code += f"""self${{{factor}}} <- factor(self${{{factor}}}, levels=c({','.join(['"{}"'.format(x) for x in order])}))"""
56
+
57
+ level_string = ", ".join([f'"{x}"' for x in order])
58
+ read_csv_code += (
59
+ f"self${factor} <- factor(self${factor}, levels=c({level_string}))"
60
+ )
61
+ read_csv_code += "\n"
62
+
23
63
  # Load ggplot2 library
24
64
  load_ggplot2 = "library(ggplot2)\n"
25
65
 
26
66
  # Check if a filename is provided for the plot, if not create a temporary one
27
67
  if not filename:
28
- filename = tempfile.mktemp(suffix=".png")
68
+ filename = tempfile.mktemp(suffix=f".{format}")
29
69
 
30
70
  # Combine all R script parts
31
71
  full_r_code = load_ggplot2 + read_csv_code + ggplot_code
32
72
 
33
73
  # Add command to save the plot to a file
34
- full_r_code += f'\nggsave("{filename}", plot = last_plot(), width = 6, height = 4, device = "png")'
74
+ full_r_code += f'\nggsave("{filename}", plot = last_plot(), width = {width}, height = {height}, device = "{format}")'
75
+
76
+ if debug:
77
+ print(full_r_code)
78
+ return
35
79
 
36
80
  result = subprocess.run(
37
81
  ["Rscript", "-"],
@@ -41,13 +85,37 @@ class ResultsGGMixin:
41
85
  stderr=subprocess.PIPE,
42
86
  )
43
87
 
88
+ if result.returncode != 0:
89
+ if result.returncode == 127: # 'command not found'
90
+ raise RuntimeError(
91
+ "Rscript is probably not installed. Please install R from https://cran.r-project.org/"
92
+ )
93
+ else:
94
+ raise RuntimeError(
95
+ f"An error occurred while running Rscript: {result.stderr}"
96
+ )
97
+
44
98
  if result.stderr:
45
99
  print("Error in R script:", result.stderr)
46
100
  else:
47
- self._display_plot(filename)
101
+ self._display_plot(filename, width, height)
48
102
 
49
- def _display_plot(self, filename):
50
- img = mpimg.imread(filename)
51
- plt.imshow(img)
52
- plt.axis("off")
53
- plt.show()
103
+ def _display_plot(self, filename: str, width: float, height: float):
104
+ """Display the plot in the notebook."""
105
+ import matplotlib.pyplot as plt
106
+ import matplotlib.image as mpimg
107
+
108
+ if filename.endswith(".png"):
109
+ img = mpimg.imread(filename)
110
+ plt.figure(
111
+ figsize=(width, height)
112
+ ) # Set the figure size (width, height) in inches
113
+ plt.imshow(img)
114
+ plt.axis("off")
115
+ plt.show()
116
+ elif filename.endswith(".svg"):
117
+ from IPython.display import SVG, display
118
+
119
+ display(SVG(filename=filename))
120
+ else:
121
+ print("Unsupported file format. Please provide a PNG or SVG file.")
@@ -0,0 +1,125 @@
1
+ from typing import (
2
+ Protocol,
3
+ List,
4
+ Any,
5
+ Optional,
6
+ TYPE_CHECKING,
7
+ Sequence,
8
+ Union,
9
+ Literal,
10
+ )
11
+
12
+ if TYPE_CHECKING:
13
+ from edsl.results.Dataset import Dataset
14
+
15
+ from edsl.results.table_data_class import TableData
16
+
17
+ from edsl.results.table_renderers import DataTablesRenderer, PandasStyleRenderer
18
+
19
+ Row = Sequence[Union[str, int, float, bool, None]]
20
+ TableFormat = Literal[
21
+ "grid", "simple", "pipe", "orgtbl", "rst", "mediawiki", "html", "latex"
22
+ ]
23
+
24
+
25
+ class TableRenderer(Protocol):
26
+ """Table renderer protocol"""
27
+
28
+ def render_html(self, table_data: TableData) -> str:
29
+ pass
30
+
31
+
32
+ # Modified TableDisplay class
33
+ class TableDisplay:
34
+ def __init__(
35
+ self,
36
+ headers: Sequence[str],
37
+ data: Sequence[Row],
38
+ tablefmt: Optional[TableFormat] = None,
39
+ raw_data_set: "Dataset" = None,
40
+ renderer_class: Optional[TableRenderer] = None,
41
+ ):
42
+ assert len(headers) == len(data[0]) # Check if headers and data are consistent
43
+
44
+ self.headers = headers
45
+ self.data = data
46
+ self.tablefmt = tablefmt
47
+ self.raw_data_set = raw_data_set
48
+
49
+ self.renderer_class = renderer_class or PandasStyleRenderer
50
+
51
+ # Handle printing parameters from raw_data_set
52
+ if hasattr(raw_data_set, "print_parameters"):
53
+ self.printing_parameters = (
54
+ raw_data_set.print_parameters if raw_data_set.print_parameters else {}
55
+ )
56
+ else:
57
+ self.printing_parameters = {}
58
+
59
+ def _repr_html_(self) -> str:
60
+ table_data = TableData(
61
+ headers=self.headers,
62
+ data=self.data,
63
+ parameters=self.printing_parameters,
64
+ raw_data_set=self.raw_data_set,
65
+ )
66
+ return self.renderer_class(table_data).render_html()
67
+
68
+ def __repr__(self):
69
+ from tabulate import tabulate
70
+
71
+ return tabulate(self.data, headers=self.headers, tablefmt=self.tablefmt)
72
+
73
+ @classmethod
74
+ def from_dictionary(
75
+ cls,
76
+ dictionary: dict,
77
+ tablefmt: Optional[TableFormat] = None,
78
+ renderer: Optional[TableRenderer] = None,
79
+ ) -> "TableDisplay":
80
+ headers = list(dictionary.keys())
81
+ data = [list(dictionary.values())]
82
+ return cls(headers, data, tablefmt, renderer_class=renderer)
83
+
84
+ @classmethod
85
+ def from_dictionary_wide(
86
+ cls,
87
+ dictionary: dict,
88
+ tablefmt: Optional[TableFormat] = None,
89
+ renderer: Optional[TableRenderer] = None,
90
+ ) -> "TableDisplay":
91
+ headers = ["key", "value"]
92
+ data = [[k, v] for k, v in dictionary.items()]
93
+ return cls(headers, data, tablefmt, renderer_class=renderer)
94
+
95
+ @classmethod
96
+ def from_dataset(
97
+ cls,
98
+ dataset: "Dataset",
99
+ tablefmt: Optional[TableFormat] = None,
100
+ renderer: Optional[TableRenderer] = None,
101
+ ) -> "TableDisplay":
102
+ headers, data = dataset._tabular()
103
+ return cls(headers, data, tablefmt, dataset, renderer_class=renderer)
104
+
105
+ def long(self) -> "TableDisplay":
106
+ """Convert to long format"""
107
+ new_header = ["row", "key", "value"]
108
+ new_data = []
109
+ for index, row in enumerate(self.data):
110
+ new_data.extend([[index, k, v] for k, v in zip(self.headers, row)])
111
+ return TableDisplay(
112
+ new_header, new_data, self.tablefmt, renderer_class=self.renderer_class
113
+ )
114
+
115
+
116
+ # Example usage:
117
+ if __name__ == "__main__":
118
+ headers = ["Name", "Age", "City"]
119
+ data = [["John", 30, "New York"], ["Jane", 25, "London"]]
120
+
121
+ # Using default (Pandas) renderer
122
+ table1 = TableDisplay(headers, data)
123
+
124
+ # Using DataTables renderer
125
+ table2 = TableDisplay(headers, data, renderer=DataTablesRenderer())
@@ -0,0 +1,50 @@
1
+ try:
2
+ import gradio as gr
3
+ except ImportError:
4
+ print("Gradio is not installed. Please install it using `pip install gradio`")
5
+
6
+ import time
7
+
8
+
9
+ class TextEditor:
10
+ def __init__(self, initial_text=""):
11
+ self.text = initial_text
12
+ self._text_saved = False
13
+
14
+ def save_text(self, new_text):
15
+ self.text = new_text
16
+ self._text_saved = True
17
+ return "Text saved successfully!"
18
+
19
+ def edit_gui(self):
20
+ js_code = """
21
+ async (text) => {
22
+ await navigator.clipboard.writeText(text);
23
+ return "Copied to clipboard!";
24
+ }
25
+ """
26
+
27
+ with gr.Blocks() as interface:
28
+ text_area = gr.Textbox(
29
+ value=self.text, lines=10, label="Edit Text", placeholder="Type here..."
30
+ )
31
+
32
+ with gr.Row():
33
+ save_btn = gr.Button("Save")
34
+ copy_btn = gr.Button("Copy to Clipboard")
35
+
36
+ output = gr.Textbox(label="Status")
37
+
38
+ save_btn.click(fn=self.save_text, inputs=[text_area], outputs=[output])
39
+
40
+ # Add copy functionality
41
+ copy_btn.click(
42
+ fn=None, inputs=text_area, outputs=output, api_name=False, js=js_code
43
+ )
44
+
45
+ interface.launch(share=False, prevent_thread_lock=True)
46
+
47
+ while not self._text_saved:
48
+ time.sleep(0.1)
49
+
50
+ return self.text
edsl/results/__init__.py CHANGED
@@ -1,2 +1,2 @@
1
- from edsl.results.Result import Result
1
+ # from edsl.results.Result import Result
2
2
  from edsl.results.Results import Results