edsl 0.1.14__tar.gz → 0.1.40__tar.gz

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 (478) hide show
  1. edsl-0.1.40/PKG-INFO +111 -0
  2. edsl-0.1.40/README.md +54 -0
  3. edsl-0.1.40/edsl/Base.py +413 -0
  4. edsl-0.1.40/edsl/BaseDiff.py +260 -0
  5. edsl-0.1.40/edsl/TemplateLoader.py +24 -0
  6. edsl-0.1.40/edsl/__init__.py +58 -0
  7. edsl-0.1.40/edsl/__version__.py +1 -0
  8. edsl-0.1.40/edsl/agents/Agent.py +1071 -0
  9. edsl-0.1.40/edsl/agents/AgentList.py +551 -0
  10. edsl-0.1.40/edsl/agents/Invigilator.py +285 -0
  11. edsl-0.1.40/edsl/agents/InvigilatorBase.py +257 -0
  12. edsl-0.1.40/edsl/agents/PromptConstructor.py +272 -0
  13. edsl-0.1.40/edsl/agents/QuestionInstructionPromptBuilder.py +128 -0
  14. edsl-0.1.40/edsl/agents/QuestionTemplateReplacementsBuilder.py +137 -0
  15. edsl-0.1.40/edsl/agents/descriptors.py +99 -0
  16. edsl-0.1.40/edsl/agents/prompt_helpers.py +129 -0
  17. edsl-0.1.40/edsl/agents/question_option_processor.py +172 -0
  18. edsl-0.1.40/edsl/auto/AutoStudy.py +130 -0
  19. edsl-0.1.40/edsl/auto/StageBase.py +243 -0
  20. edsl-0.1.40/edsl/auto/StageGenerateSurvey.py +178 -0
  21. edsl-0.1.40/edsl/auto/StageLabelQuestions.py +125 -0
  22. edsl-0.1.40/edsl/auto/StagePersona.py +61 -0
  23. edsl-0.1.40/edsl/auto/StagePersonaDimensionValueRanges.py +88 -0
  24. edsl-0.1.40/edsl/auto/StagePersonaDimensionValues.py +74 -0
  25. edsl-0.1.40/edsl/auto/StagePersonaDimensions.py +69 -0
  26. edsl-0.1.40/edsl/auto/StageQuestions.py +74 -0
  27. edsl-0.1.40/edsl/auto/SurveyCreatorPipeline.py +21 -0
  28. edsl-0.1.40/edsl/auto/utilities.py +218 -0
  29. edsl-0.1.40/edsl/base/Base.py +279 -0
  30. edsl-0.1.40/edsl/config.py +177 -0
  31. edsl-0.1.40/edsl/conversation/Conversation.py +290 -0
  32. edsl-0.1.40/edsl/conversation/car_buying.py +59 -0
  33. edsl-0.1.40/edsl/conversation/chips.py +95 -0
  34. edsl-0.1.40/edsl/conversation/mug_negotiation.py +81 -0
  35. edsl-0.1.40/edsl/conversation/next_speaker_utilities.py +93 -0
  36. edsl-0.1.40/edsl/coop/CoopFunctionsMixin.py +15 -0
  37. edsl-0.1.40/edsl/coop/ExpectedParrotKeyHandler.py +125 -0
  38. edsl-0.1.40/edsl/coop/PriceFetcher.py +54 -0
  39. edsl-0.1.40/edsl/coop/__init__.py +2 -0
  40. edsl-0.1.40/edsl/coop/coop.py +1109 -0
  41. edsl-0.1.40/edsl/coop/utils.py +131 -0
  42. edsl-0.1.40/edsl/data/Cache.py +580 -0
  43. edsl-0.1.40/edsl/data/CacheEntry.py +230 -0
  44. edsl-0.1.40/edsl/data/CacheHandler.py +168 -0
  45. edsl-0.1.40/edsl/data/RemoteCacheSync.py +186 -0
  46. edsl-0.1.40/edsl/data/SQLiteDict.py +292 -0
  47. edsl-0.1.40/edsl/data/__init__.py +5 -0
  48. edsl-0.1.40/edsl/data/orm.py +10 -0
  49. edsl-0.1.40/edsl/data_transfer_models.py +74 -0
  50. edsl-0.1.40/edsl/enums.py +202 -0
  51. edsl-0.1.40/edsl/exceptions/BaseException.py +21 -0
  52. edsl-0.1.40/edsl/exceptions/__init__.py +54 -0
  53. edsl-0.1.40/edsl/exceptions/agents.py +54 -0
  54. edsl-0.1.40/edsl/exceptions/cache.py +5 -0
  55. edsl-0.1.40/edsl/exceptions/coop.py +10 -0
  56. edsl-0.1.40/edsl/exceptions/general.py +34 -0
  57. edsl-0.1.40/edsl/exceptions/inference_services.py +5 -0
  58. edsl-0.1.40/edsl/exceptions/jobs.py +33 -0
  59. edsl-0.1.40/edsl/exceptions/language_models.py +63 -0
  60. edsl-0.1.40/edsl/exceptions/questions.py +109 -0
  61. edsl-0.1.40/edsl/exceptions/results.py +29 -0
  62. edsl-0.1.40/edsl/exceptions/scenarios.py +29 -0
  63. edsl-0.1.40/edsl/exceptions/surveys.py +37 -0
  64. edsl-0.1.40/edsl/inference_services/AnthropicService.py +106 -0
  65. edsl-0.1.40/edsl/inference_services/AvailableModelCacheHandler.py +184 -0
  66. edsl-0.1.40/edsl/inference_services/AvailableModelFetcher.py +215 -0
  67. edsl-0.1.40/edsl/inference_services/AwsBedrock.py +118 -0
  68. edsl-0.1.40/edsl/inference_services/AzureAI.py +215 -0
  69. edsl-0.1.40/edsl/inference_services/DeepInfraService.py +18 -0
  70. edsl-0.1.40/edsl/inference_services/GoogleService.py +143 -0
  71. edsl-0.1.40/edsl/inference_services/GroqService.py +20 -0
  72. edsl-0.1.40/edsl/inference_services/InferenceServiceABC.py +80 -0
  73. edsl-0.1.40/edsl/inference_services/InferenceServicesCollection.py +138 -0
  74. edsl-0.1.40/edsl/inference_services/MistralAIService.py +120 -0
  75. edsl-0.1.40/edsl/inference_services/OllamaService.py +18 -0
  76. edsl-0.1.40/edsl/inference_services/OpenAIService.py +236 -0
  77. edsl-0.1.40/edsl/inference_services/PerplexityService.py +160 -0
  78. edsl-0.1.40/edsl/inference_services/ServiceAvailability.py +135 -0
  79. edsl-0.1.40/edsl/inference_services/TestService.py +90 -0
  80. edsl-0.1.40/edsl/inference_services/TogetherAIService.py +172 -0
  81. edsl-0.1.40/edsl/inference_services/data_structures.py +134 -0
  82. edsl-0.1.40/edsl/inference_services/models_available_cache.py +118 -0
  83. edsl-0.1.40/edsl/inference_services/rate_limits_cache.py +25 -0
  84. edsl-0.1.40/edsl/inference_services/registry.py +41 -0
  85. edsl-0.1.40/edsl/inference_services/write_available.py +10 -0
  86. edsl-0.1.40/edsl/jobs/AnswerQuestionFunctionConstructor.py +223 -0
  87. edsl-0.1.40/edsl/jobs/Answers.py +43 -0
  88. edsl-0.1.40/edsl/jobs/FetchInvigilator.py +47 -0
  89. edsl-0.1.40/edsl/jobs/InterviewTaskManager.py +98 -0
  90. edsl-0.1.40/edsl/jobs/InterviewsConstructor.py +50 -0
  91. edsl-0.1.40/edsl/jobs/Jobs.py +824 -0
  92. edsl-0.1.40/edsl/jobs/JobsChecks.py +172 -0
  93. edsl-0.1.40/edsl/jobs/JobsComponentConstructor.py +189 -0
  94. edsl-0.1.40/edsl/jobs/JobsPrompts.py +270 -0
  95. edsl-0.1.40/edsl/jobs/JobsRemoteInferenceHandler.py +311 -0
  96. edsl-0.1.40/edsl/jobs/JobsRemoteInferenceLogger.py +239 -0
  97. edsl-0.1.40/edsl/jobs/RequestTokenEstimator.py +30 -0
  98. edsl-0.1.40/edsl/jobs/async_interview_runner.py +138 -0
  99. edsl-0.1.40/edsl/jobs/buckets/BucketCollection.py +104 -0
  100. edsl-0.1.40/edsl/jobs/buckets/ModelBuckets.py +65 -0
  101. edsl-0.1.40/edsl/jobs/buckets/TokenBucket.py +283 -0
  102. edsl-0.1.40/edsl/jobs/buckets/TokenBucketAPI.py +211 -0
  103. edsl-0.1.40/edsl/jobs/buckets/TokenBucketClient.py +191 -0
  104. edsl-0.1.40/edsl/jobs/check_survey_scenario_compatibility.py +85 -0
  105. edsl-0.1.40/edsl/jobs/data_structures.py +120 -0
  106. edsl-0.1.40/edsl/jobs/decorators.py +35 -0
  107. edsl-0.1.40/edsl/jobs/interviews/Interview.py +392 -0
  108. edsl-0.1.40/edsl/jobs/interviews/InterviewExceptionCollection.py +99 -0
  109. edsl-0.1.40/edsl/jobs/interviews/InterviewExceptionEntry.py +186 -0
  110. edsl-0.1.40/edsl/jobs/interviews/InterviewStatistic.py +63 -0
  111. edsl-0.1.40/edsl/jobs/interviews/InterviewStatisticsCollection.py +25 -0
  112. edsl-0.1.40/edsl/jobs/interviews/InterviewStatusDictionary.py +78 -0
  113. edsl-0.1.40/edsl/jobs/interviews/InterviewStatusLog.py +92 -0
  114. edsl-0.1.40/edsl/jobs/interviews/ReportErrors.py +66 -0
  115. edsl-0.1.40/edsl/jobs/interviews/interview_status_enum.py +9 -0
  116. edsl-0.1.40/edsl/jobs/jobs_status_enums.py +9 -0
  117. edsl-0.1.40/edsl/jobs/loggers/HTMLTableJobLogger.py +304 -0
  118. edsl-0.1.40/edsl/jobs/results_exceptions_handler.py +98 -0
  119. edsl-0.1.40/edsl/jobs/runners/JobsRunnerAsyncio.py +163 -0
  120. edsl-0.1.40/edsl/jobs/runners/JobsRunnerStatus.py +298 -0
  121. edsl-0.1.40/edsl/jobs/tasks/QuestionTaskCreator.py +244 -0
  122. edsl-0.1.40/edsl/jobs/tasks/TaskCreators.py +64 -0
  123. edsl-0.1.40/edsl/jobs/tasks/TaskHistory.py +470 -0
  124. edsl-0.1.40/edsl/jobs/tasks/TaskStatusLog.py +23 -0
  125. edsl-0.1.40/edsl/jobs/tasks/task_status_enum.py +161 -0
  126. edsl-0.1.40/edsl/jobs/tokens/InterviewTokenUsage.py +27 -0
  127. edsl-0.1.40/edsl/jobs/tokens/TokenUsage.py +34 -0
  128. edsl-0.1.40/edsl/language_models/ComputeCost.py +63 -0
  129. edsl-0.1.40/edsl/language_models/LanguageModel.py +626 -0
  130. edsl-0.1.40/edsl/language_models/ModelList.py +164 -0
  131. edsl-0.1.40/edsl/language_models/PriceManager.py +127 -0
  132. edsl-0.1.40/edsl/language_models/RawResponseHandler.py +106 -0
  133. edsl-0.1.40/edsl/language_models/RegisterLanguageModelsMeta.py +184 -0
  134. edsl-0.1.40/edsl/language_models/__init__.py +2 -0
  135. edsl-0.1.40/edsl/language_models/fake_openai_call.py +15 -0
  136. edsl-0.1.40/edsl/language_models/fake_openai_service.py +61 -0
  137. edsl-0.1.40/edsl/language_models/key_management/KeyLookup.py +63 -0
  138. edsl-0.1.40/edsl/language_models/key_management/KeyLookupBuilder.py +273 -0
  139. edsl-0.1.40/edsl/language_models/key_management/KeyLookupCollection.py +38 -0
  140. edsl-0.1.40/edsl/language_models/key_management/models.py +131 -0
  141. edsl-0.1.40/edsl/language_models/model.py +256 -0
  142. edsl-0.1.40/edsl/language_models/repair.py +156 -0
  143. edsl-0.1.40/edsl/language_models/utilities.py +65 -0
  144. edsl-0.1.40/edsl/notebooks/Notebook.py +263 -0
  145. edsl-0.1.40/edsl/notebooks/NotebookToLaTeX.py +142 -0
  146. edsl-0.1.40/edsl/notebooks/__init__.py +1 -0
  147. edsl-0.1.40/edsl/prompts/Prompt.py +352 -0
  148. edsl-0.1.40/edsl/prompts/__init__.py +2 -0
  149. edsl-0.1.40/edsl/questions/ExceptionExplainer.py +77 -0
  150. edsl-0.1.40/edsl/questions/HTMLQuestion.py +103 -0
  151. edsl-0.1.40/edsl/questions/QuestionBase.py +518 -0
  152. edsl-0.1.40/edsl/questions/QuestionBasePromptsMixin.py +221 -0
  153. edsl-0.1.40/edsl/questions/QuestionBudget.py +227 -0
  154. edsl-0.1.40/edsl/questions/QuestionCheckBox.py +359 -0
  155. edsl-0.1.40/edsl/questions/QuestionDict.py +343 -0
  156. edsl-0.1.40/edsl/questions/QuestionExtract.py +180 -0
  157. edsl-0.1.40/edsl/questions/QuestionFreeText.py +113 -0
  158. edsl-0.1.40/edsl/questions/QuestionFunctional.py +166 -0
  159. edsl-0.1.40/edsl/questions/QuestionList.py +223 -0
  160. edsl-0.1.40/edsl/questions/QuestionMatrix.py +265 -0
  161. edsl-0.1.40/edsl/questions/QuestionMultipleChoice.py +330 -0
  162. edsl-0.1.40/edsl/questions/QuestionNumerical.py +151 -0
  163. edsl-0.1.40/edsl/questions/QuestionRank.py +314 -0
  164. edsl-0.1.40/edsl/questions/Quick.py +41 -0
  165. edsl-0.1.40/edsl/questions/SimpleAskMixin.py +74 -0
  166. {edsl-0.1.14 → edsl-0.1.40}/edsl/questions/__init__.py +9 -6
  167. edsl-0.1.14/edsl/questions/AnswerValidatorMixin.py → edsl-0.1.40/edsl/questions/answer_validator_mixin.py +153 -38
  168. {edsl-0.1.14 → edsl-0.1.40}/edsl/questions/compose_questions.py +13 -7
  169. edsl-0.1.40/edsl/questions/data_structures.py +20 -0
  170. edsl-0.1.40/edsl/questions/decorators.py +21 -0
  171. edsl-0.1.40/edsl/questions/derived/QuestionLikertFive.py +76 -0
  172. edsl-0.1.40/edsl/questions/derived/QuestionLinearScale.py +90 -0
  173. {edsl-0.1.14 → edsl-0.1.40}/edsl/questions/derived/QuestionTopK.py +34 -26
  174. edsl-0.1.40/edsl/questions/derived/QuestionYesNo.py +82 -0
  175. edsl-0.1.40/edsl/questions/derived/__init__.py +0 -0
  176. edsl-0.1.40/edsl/questions/descriptors.py +471 -0
  177. edsl-0.1.40/edsl/questions/loop_processor.py +149 -0
  178. edsl-0.1.40/edsl/questions/prompt_templates/question_budget.jinja +13 -0
  179. edsl-0.1.40/edsl/questions/prompt_templates/question_checkbox.jinja +32 -0
  180. edsl-0.1.40/edsl/questions/prompt_templates/question_extract.jinja +11 -0
  181. edsl-0.1.40/edsl/questions/prompt_templates/question_free_text.jinja +3 -0
  182. edsl-0.1.40/edsl/questions/prompt_templates/question_linear_scale.jinja +11 -0
  183. edsl-0.1.40/edsl/questions/prompt_templates/question_list.jinja +17 -0
  184. edsl-0.1.40/edsl/questions/prompt_templates/question_multiple_choice.jinja +33 -0
  185. edsl-0.1.40/edsl/questions/prompt_templates/question_numerical.jinja +37 -0
  186. edsl-0.1.40/edsl/questions/question_base_gen_mixin.py +168 -0
  187. edsl-0.1.40/edsl/questions/question_registry.py +177 -0
  188. edsl-0.1.40/edsl/questions/register_questions_meta.py +71 -0
  189. edsl-0.1.40/edsl/questions/response_validator_abc.py +188 -0
  190. edsl-0.1.40/edsl/questions/response_validator_factory.py +34 -0
  191. {edsl-0.1.14 → edsl-0.1.40}/edsl/questions/settings.py +5 -2
  192. edsl-0.1.40/edsl/questions/templates/__init__.py +0 -0
  193. edsl-0.1.40/edsl/questions/templates/budget/__init__.py +0 -0
  194. edsl-0.1.40/edsl/questions/templates/budget/answering_instructions.jinja +7 -0
  195. edsl-0.1.40/edsl/questions/templates/budget/question_presentation.jinja +7 -0
  196. edsl-0.1.40/edsl/questions/templates/checkbox/__init__.py +0 -0
  197. edsl-0.1.40/edsl/questions/templates/checkbox/answering_instructions.jinja +10 -0
  198. edsl-0.1.40/edsl/questions/templates/checkbox/question_presentation.jinja +22 -0
  199. edsl-0.1.40/edsl/questions/templates/dict/__init__.py +0 -0
  200. edsl-0.1.40/edsl/questions/templates/dict/answering_instructions.jinja +21 -0
  201. edsl-0.1.40/edsl/questions/templates/dict/question_presentation.jinja +1 -0
  202. edsl-0.1.40/edsl/questions/templates/extract/__init__.py +0 -0
  203. edsl-0.1.40/edsl/questions/templates/extract/answering_instructions.jinja +7 -0
  204. edsl-0.1.40/edsl/questions/templates/extract/question_presentation.jinja +1 -0
  205. edsl-0.1.40/edsl/questions/templates/free_text/__init__.py +0 -0
  206. edsl-0.1.40/edsl/questions/templates/free_text/answering_instructions.jinja +0 -0
  207. edsl-0.1.40/edsl/questions/templates/free_text/question_presentation.jinja +1 -0
  208. edsl-0.1.40/edsl/questions/templates/likert_five/__init__.py +0 -0
  209. edsl-0.1.40/edsl/questions/templates/likert_five/answering_instructions.jinja +10 -0
  210. edsl-0.1.40/edsl/questions/templates/likert_five/question_presentation.jinja +12 -0
  211. edsl-0.1.40/edsl/questions/templates/linear_scale/__init__.py +0 -0
  212. edsl-0.1.40/edsl/questions/templates/linear_scale/answering_instructions.jinja +5 -0
  213. edsl-0.1.40/edsl/questions/templates/linear_scale/question_presentation.jinja +5 -0
  214. edsl-0.1.40/edsl/questions/templates/list/__init__.py +0 -0
  215. edsl-0.1.40/edsl/questions/templates/list/answering_instructions.jinja +4 -0
  216. edsl-0.1.40/edsl/questions/templates/list/question_presentation.jinja +5 -0
  217. edsl-0.1.40/edsl/questions/templates/matrix/__init__.py +1 -0
  218. edsl-0.1.40/edsl/questions/templates/matrix/answering_instructions.jinja +5 -0
  219. edsl-0.1.40/edsl/questions/templates/matrix/question_presentation.jinja +20 -0
  220. edsl-0.1.40/edsl/questions/templates/multiple_choice/__init__.py +0 -0
  221. edsl-0.1.40/edsl/questions/templates/multiple_choice/answering_instructions.jinja +9 -0
  222. edsl-0.1.40/edsl/questions/templates/multiple_choice/html.jinja +0 -0
  223. edsl-0.1.40/edsl/questions/templates/multiple_choice/question_presentation.jinja +12 -0
  224. edsl-0.1.40/edsl/questions/templates/numerical/__init__.py +0 -0
  225. edsl-0.1.40/edsl/questions/templates/numerical/answering_instructions.jinja +7 -0
  226. edsl-0.1.40/edsl/questions/templates/numerical/question_presentation.jinja +7 -0
  227. edsl-0.1.40/edsl/questions/templates/rank/__init__.py +0 -0
  228. edsl-0.1.40/edsl/questions/templates/rank/answering_instructions.jinja +11 -0
  229. edsl-0.1.40/edsl/questions/templates/rank/question_presentation.jinja +15 -0
  230. edsl-0.1.40/edsl/questions/templates/top_k/__init__.py +0 -0
  231. edsl-0.1.40/edsl/questions/templates/top_k/answering_instructions.jinja +8 -0
  232. edsl-0.1.40/edsl/questions/templates/top_k/question_presentation.jinja +22 -0
  233. edsl-0.1.40/edsl/questions/templates/yes_no/__init__.py +0 -0
  234. edsl-0.1.40/edsl/questions/templates/yes_no/answering_instructions.jinja +6 -0
  235. edsl-0.1.40/edsl/questions/templates/yes_no/question_presentation.jinja +12 -0
  236. edsl-0.1.40/edsl/results/CSSParameterizer.py +108 -0
  237. edsl-0.1.40/edsl/results/Dataset.py +587 -0
  238. edsl-0.1.40/edsl/results/DatasetExportMixin.py +594 -0
  239. edsl-0.1.40/edsl/results/DatasetTree.py +295 -0
  240. edsl-0.1.40/edsl/results/MarkdownToDocx.py +122 -0
  241. edsl-0.1.40/edsl/results/MarkdownToPDF.py +111 -0
  242. edsl-0.1.40/edsl/results/Result.py +573 -0
  243. edsl-0.1.40/edsl/results/Results.py +1195 -0
  244. edsl-0.1.40/edsl/results/ResultsExportMixin.py +45 -0
  245. edsl-0.1.40/edsl/results/ResultsGGMixin.py +121 -0
  246. edsl-0.1.40/edsl/results/TableDisplay.py +125 -0
  247. edsl-0.1.40/edsl/results/TextEditor.py +50 -0
  248. {edsl-0.1.14 → edsl-0.1.40}/edsl/results/__init__.py +1 -1
  249. edsl-0.1.40/edsl/results/file_exports.py +252 -0
  250. edsl-0.1.40/edsl/results/results_fetch_mixin.py +33 -0
  251. edsl-0.1.40/edsl/results/results_selector.py +145 -0
  252. edsl-0.1.40/edsl/results/results_tools_mixin.py +98 -0
  253. edsl-0.1.40/edsl/results/smart_objects.py +96 -0
  254. edsl-0.1.40/edsl/results/table_data_class.py +12 -0
  255. edsl-0.1.40/edsl/results/table_display.css +78 -0
  256. edsl-0.1.40/edsl/results/table_renderers.py +118 -0
  257. edsl-0.1.40/edsl/results/tree_explore.py +115 -0
  258. edsl-0.1.40/edsl/scenarios/ConstructDownloadLink.py +109 -0
  259. edsl-0.1.40/edsl/scenarios/DocumentChunker.py +102 -0
  260. edsl-0.1.40/edsl/scenarios/DocxScenario.py +16 -0
  261. edsl-0.1.40/edsl/scenarios/FileStore.py +543 -0
  262. edsl-0.1.40/edsl/scenarios/PdfExtractor.py +40 -0
  263. edsl-0.1.40/edsl/scenarios/Scenario.py +498 -0
  264. edsl-0.1.40/edsl/scenarios/ScenarioHtmlMixin.py +65 -0
  265. edsl-0.1.40/edsl/scenarios/ScenarioList.py +1458 -0
  266. edsl-0.1.40/edsl/scenarios/ScenarioListExportMixin.py +45 -0
  267. edsl-0.1.40/edsl/scenarios/ScenarioListPdfMixin.py +239 -0
  268. edsl-0.1.40/edsl/scenarios/__init__.py +3 -0
  269. edsl-0.1.40/edsl/scenarios/directory_scanner.py +96 -0
  270. edsl-0.1.40/edsl/scenarios/file_methods.py +85 -0
  271. edsl-0.1.40/edsl/scenarios/handlers/__init__.py +13 -0
  272. edsl-0.1.40/edsl/scenarios/handlers/csv.py +49 -0
  273. edsl-0.1.40/edsl/scenarios/handlers/docx.py +76 -0
  274. edsl-0.1.40/edsl/scenarios/handlers/html.py +37 -0
  275. edsl-0.1.40/edsl/scenarios/handlers/json.py +111 -0
  276. edsl-0.1.40/edsl/scenarios/handlers/latex.py +5 -0
  277. edsl-0.1.40/edsl/scenarios/handlers/md.py +51 -0
  278. edsl-0.1.40/edsl/scenarios/handlers/pdf.py +68 -0
  279. edsl-0.1.40/edsl/scenarios/handlers/png.py +39 -0
  280. edsl-0.1.40/edsl/scenarios/handlers/pptx.py +105 -0
  281. edsl-0.1.40/edsl/scenarios/handlers/py.py +294 -0
  282. edsl-0.1.40/edsl/scenarios/handlers/sql.py +313 -0
  283. edsl-0.1.40/edsl/scenarios/handlers/sqlite.py +149 -0
  284. edsl-0.1.40/edsl/scenarios/handlers/txt.py +33 -0
  285. edsl-0.1.40/edsl/scenarios/scenario_join.py +131 -0
  286. edsl-0.1.40/edsl/scenarios/scenario_selector.py +156 -0
  287. edsl-0.1.40/edsl/shared.py +1 -0
  288. edsl-0.1.40/edsl/study/ObjectEntry.py +173 -0
  289. edsl-0.1.40/edsl/study/ProofOfWork.py +113 -0
  290. edsl-0.1.40/edsl/study/SnapShot.py +80 -0
  291. edsl-0.1.40/edsl/study/Study.py +521 -0
  292. edsl-0.1.40/edsl/study/__init__.py +4 -0
  293. edsl-0.1.40/edsl/surveys/ConstructDAG.py +92 -0
  294. edsl-0.1.40/edsl/surveys/DAG.py +148 -0
  295. edsl-0.1.40/edsl/surveys/EditSurvey.py +221 -0
  296. edsl-0.1.40/edsl/surveys/InstructionHandler.py +100 -0
  297. {edsl-0.1.14 → edsl-0.1.40}/edsl/surveys/Memory.py +9 -4
  298. edsl-0.1.40/edsl/surveys/MemoryManagement.py +72 -0
  299. edsl-0.1.40/edsl/surveys/MemoryPlan.py +244 -0
  300. edsl-0.1.40/edsl/surveys/Rule.py +327 -0
  301. edsl-0.1.40/edsl/surveys/RuleCollection.py +385 -0
  302. edsl-0.1.40/edsl/surveys/RuleManager.py +172 -0
  303. edsl-0.1.40/edsl/surveys/Simulator.py +75 -0
  304. edsl-0.1.40/edsl/surveys/Survey.py +1284 -0
  305. edsl-0.1.40/edsl/surveys/SurveyCSS.py +273 -0
  306. edsl-0.1.40/edsl/surveys/SurveyExportMixin.py +259 -0
  307. edsl-0.1.40/edsl/surveys/SurveyFlowVisualization.py +181 -0
  308. edsl-0.1.40/edsl/surveys/SurveyQualtricsImport.py +284 -0
  309. edsl-0.1.40/edsl/surveys/SurveyToApp.py +141 -0
  310. edsl-0.1.40/edsl/surveys/__init__.py +5 -0
  311. edsl-0.1.40/edsl/surveys/base.py +53 -0
  312. {edsl-0.1.14 → edsl-0.1.40}/edsl/surveys/descriptors.py +17 -6
  313. edsl-0.1.40/edsl/surveys/instructions/ChangeInstruction.py +48 -0
  314. edsl-0.1.40/edsl/surveys/instructions/Instruction.py +56 -0
  315. edsl-0.1.40/edsl/surveys/instructions/InstructionCollection.py +82 -0
  316. edsl-0.1.40/edsl/surveys/instructions/__init__.py +0 -0
  317. edsl-0.1.40/edsl/templates/error_reporting/base.html +24 -0
  318. edsl-0.1.40/edsl/templates/error_reporting/exceptions_by_model.html +35 -0
  319. edsl-0.1.40/edsl/templates/error_reporting/exceptions_by_question_name.html +17 -0
  320. edsl-0.1.40/edsl/templates/error_reporting/exceptions_by_type.html +17 -0
  321. edsl-0.1.40/edsl/templates/error_reporting/interview_details.html +116 -0
  322. edsl-0.1.40/edsl/templates/error_reporting/interviews.html +19 -0
  323. edsl-0.1.40/edsl/templates/error_reporting/overview.html +5 -0
  324. edsl-0.1.40/edsl/templates/error_reporting/performance_plot.html +2 -0
  325. edsl-0.1.40/edsl/templates/error_reporting/report.css +74 -0
  326. edsl-0.1.40/edsl/templates/error_reporting/report.html +118 -0
  327. edsl-0.1.40/edsl/templates/error_reporting/report.js +25 -0
  328. edsl-0.1.40/edsl/tools/__init__.py +1 -0
  329. edsl-0.1.40/edsl/tools/clusters.py +192 -0
  330. edsl-0.1.40/edsl/tools/embeddings.py +27 -0
  331. edsl-0.1.40/edsl/tools/embeddings_plotting.py +118 -0
  332. edsl-0.1.40/edsl/tools/plotting.py +112 -0
  333. edsl-0.1.40/edsl/tools/summarize.py +18 -0
  334. edsl-0.1.40/edsl/utilities/PrettyList.py +56 -0
  335. {edsl-0.1.14 → edsl-0.1.40}/edsl/utilities/SystemInfo.py +5 -0
  336. edsl-0.1.40/edsl/utilities/__init__.py +22 -0
  337. {edsl-0.1.14 → edsl-0.1.40}/edsl/utilities/ast_utilities.py +3 -0
  338. {edsl-0.1.14 → edsl-0.1.40}/edsl/utilities/data/Registry.py +2 -0
  339. edsl-0.1.40/edsl/utilities/decorators.py +77 -0
  340. edsl-0.1.40/edsl/utilities/gcp_bucket/__init__.py +0 -0
  341. edsl-0.1.40/edsl/utilities/gcp_bucket/cloud_storage.py +96 -0
  342. {edsl-0.1.14 → edsl-0.1.40}/edsl/utilities/interface.py +310 -60
  343. edsl-0.1.40/edsl/utilities/is_notebook.py +18 -0
  344. edsl-0.1.40/edsl/utilities/is_valid_variable_name.py +11 -0
  345. edsl-0.1.40/edsl/utilities/naming_utilities.py +263 -0
  346. edsl-0.1.40/edsl/utilities/remove_edsl_version.py +24 -0
  347. edsl-0.1.40/edsl/utilities/repair_functions.py +28 -0
  348. edsl-0.1.40/edsl/utilities/restricted_python.py +70 -0
  349. {edsl-0.1.14 → edsl-0.1.40}/edsl/utilities/utilities.py +203 -13
  350. edsl-0.1.40/pyproject.toml +86 -0
  351. edsl-0.1.14/PKG-INFO +0 -69
  352. edsl-0.1.14/README.md +0 -27
  353. edsl-0.1.14/edsl/Base.py +0 -103
  354. edsl-0.1.14/edsl/__init__.py +0 -22
  355. edsl-0.1.14/edsl/agents/Agent.py +0 -373
  356. edsl-0.1.14/edsl/agents/AgentList.py +0 -55
  357. edsl-0.1.14/edsl/agents/AgentListExportMixin.py +0 -24
  358. edsl-0.1.14/edsl/agents/Invigilator.py +0 -409
  359. edsl-0.1.14/edsl/agents/descriptors.py +0 -69
  360. edsl-0.1.14/edsl/config.py +0 -160
  361. edsl-0.1.14/edsl/coop/__init__.py +0 -1
  362. edsl-0.1.14/edsl/coop/coop.py +0 -214
  363. edsl-0.1.14/edsl/coop/old.py +0 -31
  364. edsl-0.1.14/edsl/data/Cache.py +0 -109
  365. edsl-0.1.14/edsl/data/Database.py +0 -141
  366. edsl-0.1.14/edsl/data/__init__.py +0 -3
  367. edsl-0.1.14/edsl/data/crud.py +0 -121
  368. edsl-0.1.14/edsl/data/orm.py +0 -37
  369. edsl-0.1.14/edsl/data_transfer_models.py +0 -27
  370. edsl-0.1.14/edsl/enums.py +0 -45
  371. edsl-0.1.14/edsl/exceptions/__init__.py +0 -48
  372. edsl-0.1.14/edsl/exceptions/agents.py +0 -36
  373. edsl-0.1.14/edsl/exceptions/coop.py +0 -2
  374. edsl-0.1.14/edsl/exceptions/jobs.py +0 -18
  375. edsl-0.1.14/edsl/exceptions/language_models.py +0 -18
  376. edsl-0.1.14/edsl/exceptions/questions.py +0 -34
  377. edsl-0.1.14/edsl/exceptions/results.py +0 -18
  378. edsl-0.1.14/edsl/exceptions/surveys.py +0 -34
  379. edsl-0.1.14/edsl/jobs/Answers.py +0 -42
  380. edsl-0.1.14/edsl/jobs/Interview.py +0 -417
  381. edsl-0.1.14/edsl/jobs/Jobs.py +0 -344
  382. edsl-0.1.14/edsl/jobs/JobsRunner.py +0 -63
  383. edsl-0.1.14/edsl/jobs/JobsRunnerStatusMixin.py +0 -115
  384. edsl-0.1.14/edsl/jobs/base.py +0 -47
  385. edsl-0.1.14/edsl/jobs/buckets.py +0 -166
  386. edsl-0.1.14/edsl/jobs/runners/JobsRunnerAsyncio.py +0 -122
  387. edsl-0.1.14/edsl/jobs/runners/JobsRunnerDryRun.py +0 -19
  388. edsl-0.1.14/edsl/jobs/runners/JobsRunnerStreaming.py +0 -54
  389. edsl-0.1.14/edsl/jobs/task_management.py +0 -218
  390. edsl-0.1.14/edsl/jobs/token_tracking.py +0 -78
  391. edsl-0.1.14/edsl/language_models/DeepInfra.py +0 -69
  392. edsl-0.1.14/edsl/language_models/LanguageModel.py +0 -505
  393. edsl-0.1.14/edsl/language_models/OpenAI.py +0 -98
  394. edsl-0.1.14/edsl/language_models/__init__.py +0 -9
  395. edsl-0.1.14/edsl/language_models/model_interfaces/GeminiPro.py +0 -66
  396. edsl-0.1.14/edsl/language_models/model_interfaces/LanguageModelOpenAIFour.py +0 -8
  397. edsl-0.1.14/edsl/language_models/model_interfaces/LanguageModelOpenAIThreeFiveTurbo.py +0 -8
  398. edsl-0.1.14/edsl/language_models/model_interfaces/LlamaTwo13B.py +0 -21
  399. edsl-0.1.14/edsl/language_models/model_interfaces/LlamaTwo70B.py +0 -21
  400. edsl-0.1.14/edsl/language_models/model_interfaces/Mixtral8x7B.py +0 -24
  401. edsl-0.1.14/edsl/language_models/registry.py +0 -81
  402. edsl-0.1.14/edsl/language_models/repair.py +0 -88
  403. edsl-0.1.14/edsl/language_models/schemas.py +0 -15
  404. edsl-0.1.14/edsl/language_models/unused/ReplicateBase.py +0 -83
  405. edsl-0.1.14/edsl/prompts/Prompt.py +0 -223
  406. edsl-0.1.14/edsl/prompts/QuestionInstructionsBase.py +0 -6
  407. edsl-0.1.14/edsl/prompts/__init__.py +0 -2
  408. edsl-0.1.14/edsl/prompts/library/agent_instructions.py +0 -29
  409. edsl-0.1.14/edsl/prompts/library/agent_persona.py +0 -17
  410. edsl-0.1.14/edsl/prompts/library/question_budget.py +0 -26
  411. edsl-0.1.14/edsl/prompts/library/question_checkbox.py +0 -32
  412. edsl-0.1.14/edsl/prompts/library/question_extract.py +0 -19
  413. edsl-0.1.14/edsl/prompts/library/question_freetext.py +0 -14
  414. edsl-0.1.14/edsl/prompts/library/question_linear_scale.py +0 -20
  415. edsl-0.1.14/edsl/prompts/library/question_list.py +0 -22
  416. edsl-0.1.14/edsl/prompts/library/question_multiple_choice.py +0 -44
  417. edsl-0.1.14/edsl/prompts/library/question_numerical.py +0 -31
  418. edsl-0.1.14/edsl/prompts/library/question_rank.py +0 -21
  419. edsl-0.1.14/edsl/prompts/prompt_config.py +0 -33
  420. edsl-0.1.14/edsl/prompts/registry.py +0 -185
  421. edsl-0.1.14/edsl/questions/Question.py +0 -240
  422. edsl-0.1.14/edsl/questions/QuestionBudget.py +0 -130
  423. edsl-0.1.14/edsl/questions/QuestionCheckBox.py +0 -140
  424. edsl-0.1.14/edsl/questions/QuestionExtract.py +0 -94
  425. edsl-0.1.14/edsl/questions/QuestionFreeText.py +0 -89
  426. edsl-0.1.14/edsl/questions/QuestionFunctional.py +0 -69
  427. edsl-0.1.14/edsl/questions/QuestionList.py +0 -96
  428. edsl-0.1.14/edsl/questions/QuestionMultipleChoice.py +0 -106
  429. edsl-0.1.14/edsl/questions/QuestionNumerical.py +0 -98
  430. edsl-0.1.14/edsl/questions/QuestionRank.py +0 -119
  431. edsl-0.1.14/edsl/questions/derived/QuestionLikertFive.py +0 -74
  432. edsl-0.1.14/edsl/questions/derived/QuestionLinearScale.py +0 -77
  433. edsl-0.1.14/edsl/questions/derived/QuestionYesNo.py +0 -69
  434. edsl-0.1.14/edsl/questions/descriptors.py +0 -317
  435. edsl-0.1.14/edsl/questions/question_registry.py +0 -93
  436. edsl-0.1.14/edsl/report/InputOutputDataTypes.py +0 -134
  437. edsl-0.1.14/edsl/report/RegressionMixin.py +0 -28
  438. edsl-0.1.14/edsl/report/ReportOutputs.py +0 -1228
  439. edsl-0.1.14/edsl/report/ResultsFetchMixin.py +0 -106
  440. edsl-0.1.14/edsl/report/ResultsOutputMixin.py +0 -14
  441. edsl-0.1.14/edsl/report/demo.ipynb +0 -645
  442. edsl-0.1.14/edsl/results/Dataset.py +0 -56
  443. edsl-0.1.14/edsl/results/Result.py +0 -269
  444. edsl-0.1.14/edsl/results/Results.py +0 -477
  445. edsl-0.1.14/edsl/results/ResultsDBMixin.py +0 -184
  446. edsl-0.1.14/edsl/results/ResultsExportMixin.py +0 -142
  447. edsl-0.1.14/edsl/results/ResultsGGMixin.py +0 -53
  448. edsl-0.1.14/edsl/scenarios/Scenario.py +0 -129
  449. edsl-0.1.14/edsl/scenarios/ScenarioList.py +0 -88
  450. edsl-0.1.14/edsl/scenarios/__init__.py +0 -1
  451. edsl-0.1.14/edsl/surveys/DAG.py +0 -67
  452. edsl-0.1.14/edsl/surveys/MemoryPlan.py +0 -123
  453. edsl-0.1.14/edsl/surveys/Rule.py +0 -180
  454. edsl-0.1.14/edsl/surveys/RuleCollection.py +0 -205
  455. edsl-0.1.14/edsl/surveys/Survey.py +0 -544
  456. edsl-0.1.14/edsl/surveys/SurveyExportMixin.py +0 -64
  457. edsl-0.1.14/edsl/surveys/SurveyFlowVisualizationMixin.py +0 -92
  458. edsl-0.1.14/edsl/surveys/__init__.py +0 -3
  459. edsl-0.1.14/edsl/surveys/base.py +0 -37
  460. edsl-0.1.14/edsl/trackers/Tracker.py +0 -91
  461. edsl-0.1.14/edsl/trackers/TrackerAPI.py +0 -196
  462. edsl-0.1.14/edsl/trackers/TrackerTasks.py +0 -70
  463. edsl-0.1.14/edsl/utilities/__init__.py +0 -21
  464. edsl-0.1.14/edsl/utilities/decorators.py +0 -36
  465. edsl-0.1.14/edsl/utilities/pastebin.py +0 -141
  466. edsl-0.1.14/pyproject.toml +0 -71
  467. {edsl-0.1.14 → edsl-0.1.40}/LICENSE +0 -0
  468. {edsl-0.1.14 → edsl-0.1.40}/edsl/agents/__init__.py +0 -0
  469. {edsl-0.1.14 → edsl-0.1.40}/edsl/exceptions/configuration.py +0 -0
  470. {edsl-0.1.14 → edsl-0.1.40}/edsl/exceptions/data.py +0 -0
  471. {edsl-0.1.14 → edsl-0.1.40}/edsl/exceptions/prompts.py +0 -0
  472. {edsl-0.1.14/edsl/language_models/model_interfaces → edsl-0.1.40/edsl/inference_services}/__init__.py +0 -0
  473. {edsl-0.1.14 → edsl-0.1.40}/edsl/jobs/__init__.py +0 -0
  474. /edsl-0.1.14/edsl/questions/derived/__init__.py → /edsl-0.1.40/edsl/jobs/runners/JobsRunnerStatusData.py +0 -0
  475. /edsl-0.1.14/edsl/report/__init__.py → /edsl-0.1.40/edsl/language_models/ServiceDataSources.py +0 -0
  476. {edsl-0.1.14/edsl/trackers → edsl-0.1.40/edsl/language_models/key_management}/__init__.py +0 -0
  477. {edsl-0.1.14 → edsl-0.1.40}/edsl/utilities/data/__init__.py +0 -0
  478. {edsl-0.1.14 → edsl-0.1.40}/edsl/utilities/data/scooter_results.json +0 -0
edsl-0.1.40/PKG-INFO ADDED
@@ -0,0 +1,111 @@
1
+ Metadata-Version: 2.1
2
+ Name: edsl
3
+ Version: 0.1.40
4
+ Summary: Create and analyze LLM-based surveys
5
+ Home-page: https://www.expectedparrot.com/
6
+ License: MIT
7
+ Keywords: LLM,social science,surveys,user research
8
+ Author: Apostolos Filippas
9
+ Author-email: apostolos@expectedparrot.com
10
+ Requires-Python: >=3.9.1,<3.13
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Requires-Dist: aiohttp (>=3.9.1,<4.0.0)
20
+ Requires-Dist: anthropic (>=0.23.1,<0.24.0)
21
+ Requires-Dist: azure-ai-inference (>=1.0.0b3,<2.0.0)
22
+ Requires-Dist: black[jupyter] (>=24.4.2,<25.0.0)
23
+ Requires-Dist: boto3 (>=1.34.161,<2.0.0)
24
+ Requires-Dist: google-generativeai (>=0.8.2,<0.9.0)
25
+ Requires-Dist: groq (>=0.9.0,<0.10.0)
26
+ Requires-Dist: jinja2 (>=3.1.2,<4.0.0)
27
+ Requires-Dist: json-repair (>=0.28.4,<0.29.0)
28
+ Requires-Dist: jupyter (>=1.0.0,<2.0.0)
29
+ Requires-Dist: markdown2 (>=2.4.11,<3.0.0)
30
+ Requires-Dist: matplotlib (>=3.8,<3.9)
31
+ Requires-Dist: mistralai (>=1.0.2,<2.0.0)
32
+ Requires-Dist: nest-asyncio (>=1.5.9,<2.0.0)
33
+ Requires-Dist: numpy (>=1.22,<2.0)
34
+ Requires-Dist: openai (>=1.4.0,<2.0.0)
35
+ Requires-Dist: openpyxl (>=3.1.5,<4.0.0)
36
+ Requires-Dist: pandas (>=2.1.4,<3.0.0)
37
+ Requires-Dist: platformdirs (>=4.3.6,<5.0.0)
38
+ Requires-Dist: pydot (>=2.0.0,<3.0.0)
39
+ Requires-Dist: pygments (>=2.17.2,<3.0.0)
40
+ Requires-Dist: pymupdf (>=1.24.4,<2.0.0)
41
+ Requires-Dist: pypdf2 (>=3.0.1,<4.0.0)
42
+ Requires-Dist: pyreadstat (>=1.2.7,<2.0.0)
43
+ Requires-Dist: python-docx (>=1.1.0,<2.0.0)
44
+ Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
45
+ Requires-Dist: python-pptx (>=1.0.2,<2.0.0)
46
+ Requires-Dist: restrictedpython (>=7.1,<8.0)
47
+ Requires-Dist: rich (>=13.7.0,<14.0.0)
48
+ Requires-Dist: setuptools (<72.0)
49
+ Requires-Dist: simpleeval (>=0.9.13,<0.10.0)
50
+ Requires-Dist: sqlalchemy (>=2.0.23,<3.0.0)
51
+ Requires-Dist: tabulate (>=0.9.0,<0.10.0)
52
+ Requires-Dist: tenacity (>=8.2.3,<9.0.0)
53
+ Requires-Dist: urllib3 (>=1.25.4,<1.27)
54
+ Project-URL: Documentation, https://docs.expectedparrot.com
55
+ Description-Content-Type: text/markdown
56
+
57
+ # Expected Parrot Domain-Specific Language
58
+ <p align="center">
59
+ <img src="https://github.com/expectedparrot/edsl/blob/main/static/logo.png?raw=true" alt="edsl.png" width="100"/>
60
+ </p>
61
+
62
+ The Expected Parrot Domain-Specific Language (EDSL) package lets you conduct computational social science and market research with AI. Use it to design surveys and experiments, simulate responses with large language models, and perform data labeling and other research tasks. Results are formatted as specified datasets and come with built-in methods for analyzing, visualizing, and sharing.
63
+
64
+ ## 🔗 Links
65
+ - [PyPI](https://pypi.org/project/edsl/)
66
+ - [Documentation](https://docs.expectedparrot.com)
67
+ - [Getting started](https://docs.expectedparrot.com/en/latest/starter_tutorial.html)
68
+ - [Discord](https://discord.com/invite/mxAYkjfy9m)
69
+ - [Twitter](https://x.com/ExpectedParrot)
70
+ - [LinkedIn](https://www.linkedin.com/company/expectedparrot/)
71
+ - [Blog](https://blog.expectedparrot.com)
72
+
73
+ ## 🌎 Hello, World!
74
+ A quick example:
75
+
76
+ ```python
77
+ # Import a question type
78
+ from edsl import QuestionMultipleChoice
79
+
80
+ # Construct a question using the question type template
81
+ q = QuestionMultipleChoice(
82
+ question_name="example_question",
83
+ question_text="How do you feel today?",
84
+ question_options=["Bad", "OK", "Good"]
85
+ )
86
+
87
+ # Run it with the default language model
88
+ results = q.run()
89
+
90
+ # Inspect the results
91
+ results.select("example_question")
92
+ ```
93
+
94
+ Output:
95
+ ```python
96
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━┓
97
+ ┃ answer.example_question ┃
98
+ ┡━━━━━━━━━━━━━━━━━━━━━━━━━┩
99
+ │ Good │
100
+ └─────────────────────────┘
101
+ ```
102
+
103
+ ## 💻 Requirements
104
+ * EDSL is compatible with Python 3.9 - 3.12.
105
+ * API keys for large language models that you want to use, stored in a `.env` file.
106
+ See instructions on [storing API keys](https://docs.expectedparrot.com/en/latest/api_keys.html) and [activating remote inference](https://docs.expectedparrot.com/en/latest/remote_inference.html).
107
+
108
+ ## 💡 Contributions, feature requests & bugs
109
+ Interested in contributing? Want us to add a new feature? Found a bug for us to squash?
110
+ Please send us an email at [info@expectedparrot.com](mailto:info@expectedparrot.com) or message us at our [Discord channel](https://discord.com/invite/mxAYkjfy9m).
111
+
edsl-0.1.40/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # Expected Parrot Domain-Specific Language
2
+ <p align="center">
3
+ <img src="https://github.com/expectedparrot/edsl/blob/main/static/logo.png?raw=true" alt="edsl.png" width="100"/>
4
+ </p>
5
+
6
+ The Expected Parrot Domain-Specific Language (EDSL) package lets you conduct computational social science and market research with AI. Use it to design surveys and experiments, simulate responses with large language models, and perform data labeling and other research tasks. Results are formatted as specified datasets and come with built-in methods for analyzing, visualizing, and sharing.
7
+
8
+ ## 🔗 Links
9
+ - [PyPI](https://pypi.org/project/edsl/)
10
+ - [Documentation](https://docs.expectedparrot.com)
11
+ - [Getting started](https://docs.expectedparrot.com/en/latest/starter_tutorial.html)
12
+ - [Discord](https://discord.com/invite/mxAYkjfy9m)
13
+ - [Twitter](https://x.com/ExpectedParrot)
14
+ - [LinkedIn](https://www.linkedin.com/company/expectedparrot/)
15
+ - [Blog](https://blog.expectedparrot.com)
16
+
17
+ ## 🌎 Hello, World!
18
+ A quick example:
19
+
20
+ ```python
21
+ # Import a question type
22
+ from edsl import QuestionMultipleChoice
23
+
24
+ # Construct a question using the question type template
25
+ q = QuestionMultipleChoice(
26
+ question_name="example_question",
27
+ question_text="How do you feel today?",
28
+ question_options=["Bad", "OK", "Good"]
29
+ )
30
+
31
+ # Run it with the default language model
32
+ results = q.run()
33
+
34
+ # Inspect the results
35
+ results.select("example_question")
36
+ ```
37
+
38
+ Output:
39
+ ```python
40
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━┓
41
+ ┃ answer.example_question ┃
42
+ ┡━━━━━━━━━━━━━━━━━━━━━━━━━┩
43
+ │ Good │
44
+ └─────────────────────────┘
45
+ ```
46
+
47
+ ## 💻 Requirements
48
+ * EDSL is compatible with Python 3.9 - 3.12.
49
+ * API keys for large language models that you want to use, stored in a `.env` file.
50
+ See instructions on [storing API keys](https://docs.expectedparrot.com/en/latest/api_keys.html) and [activating remote inference](https://docs.expectedparrot.com/en/latest/remote_inference.html).
51
+
52
+ ## 💡 Contributions, feature requests & bugs
53
+ Interested in contributing? Want us to add a new feature? Found a bug for us to squash?
54
+ Please send us an email at [info@expectedparrot.com](mailto:info@expectedparrot.com) or message us at our [Discord channel](https://discord.com/invite/mxAYkjfy9m).
@@ -0,0 +1,413 @@
1
+ """Base class for all classes in the package. It provides rich printing and persistence of objects."""
2
+
3
+ from abc import ABC, abstractmethod, ABCMeta
4
+ import gzip
5
+ import json
6
+ from typing import Any, Optional, Union
7
+ from uuid import UUID
8
+
9
+
10
+ class PersistenceMixin:
11
+ """Mixin for saving and loading objects to and from files."""
12
+
13
+ def duplicate(self, add_edsl_version=False):
14
+ """Return a duplicate of the object."""
15
+ return self.from_dict(self.to_dict(add_edsl_version=False))
16
+
17
+ def push(
18
+ self,
19
+ description: Optional[str] = None,
20
+ alias: Optional[str] = None,
21
+ visibility: Optional[str] = "unlisted",
22
+ expected_parrot_url: Optional[str] = None,
23
+ ):
24
+ """Post the object to coop."""
25
+ from edsl.coop import Coop
26
+
27
+ c = Coop(url=expected_parrot_url)
28
+ return c.create(self, description, alias, visibility)
29
+
30
+ def to_yaml(self, add_edsl_version=False, filename: str = None) -> Union[str, None]:
31
+ import yaml
32
+
33
+ output = yaml.dump(self.to_dict(add_edsl_version=add_edsl_version))
34
+ if not filename:
35
+ return output
36
+
37
+ with open(filename, "w") as f:
38
+ f.write(output)
39
+
40
+ @classmethod
41
+ def from_yaml(cls, yaml_str: Optional[str] = None, filename: Optional[str] = None):
42
+ if yaml_str is None and filename is not None:
43
+ with open(filename, "r") as f:
44
+ yaml_str = f.read()
45
+ return cls.from_yaml(yaml_str=yaml_str)
46
+ elif yaml_str and filename is None:
47
+ import yaml
48
+
49
+ d = yaml.load(yaml_str, Loader=yaml.FullLoader)
50
+ return cls.from_dict(d)
51
+ else:
52
+ raise ValueError("Either yaml_str or filename must be provided.")
53
+
54
+ def create_download_link(self):
55
+ from tempfile import NamedTemporaryFile
56
+ from edsl.scenarios.FileStore import FileStore
57
+
58
+ with NamedTemporaryFile(suffix=".json.gz") as f:
59
+ self.save(f.name)
60
+ print(f.name)
61
+ fs = FileStore(path=f.name)
62
+ return fs.create_link()
63
+
64
+ @classmethod
65
+ def pull(
66
+ cls,
67
+ uuid: Optional[Union[str, UUID]] = None,
68
+ url: Optional[str] = None,
69
+ expected_parrot_url: Optional[str] = None,
70
+ ):
71
+ """Pull the object from coop."""
72
+ from edsl.coop import Coop
73
+ from edsl.coop.utils import ObjectRegistry
74
+
75
+ object_type = ObjectRegistry.get_object_type_by_edsl_class(cls)
76
+ coop = Coop(url=expected_parrot_url)
77
+ return coop.get(uuid, url, object_type)
78
+
79
+ @classmethod
80
+ def delete(cls, uuid: Optional[Union[str, UUID]] = None, url: Optional[str] = None):
81
+ """Delete the object from coop."""
82
+ from edsl.coop import Coop
83
+
84
+ coop = Coop()
85
+ return coop.delete(uuid, url)
86
+
87
+ @classmethod
88
+ def patch(
89
+ cls,
90
+ uuid: Optional[Union[str, UUID]] = None,
91
+ url: Optional[str] = None,
92
+ description: Optional[str] = None,
93
+ alias: Optional[str] = None,
94
+ value: Optional[Any] = None,
95
+ visibility: Optional[str] = None,
96
+ ):
97
+ """
98
+ Patch an uploaded objects attributes.
99
+ - `description` changes the description of the object on Coop
100
+ - `value` changes the value of the object on Coop. **has to be an EDSL object**
101
+ - `visibility` changes the visibility of the object on Coop
102
+ """
103
+ from edsl.coop import Coop
104
+
105
+ coop = Coop()
106
+ return coop.patch(uuid, url, description, alias, value, visibility)
107
+
108
+ @classmethod
109
+ def search(cls, query):
110
+ """Search for objects on coop."""
111
+ from edsl.coop import Coop
112
+
113
+ c = Coop()
114
+ return c.search(cls, query)
115
+
116
+ def store(self, d: dict, key_name: Optional[str] = None):
117
+ if key_name is None:
118
+ index = len(d)
119
+ else:
120
+ index = key_name
121
+ d[index] = self
122
+
123
+ def save(self, filename, compress=True):
124
+ """Save the object to a file as zippped JSON.
125
+
126
+ >>> obj.save("obj.json.gz")
127
+
128
+ """
129
+ if filename.endswith("json.gz"):
130
+ import warnings
131
+
132
+ filename = filename[:-8]
133
+ if filename.endswith("json"):
134
+ filename = filename[:-5]
135
+
136
+ if compress:
137
+ full_file_name = filename + ".json.gz"
138
+ with gzip.open(full_file_name, "wb") as f:
139
+ f.write(json.dumps(self.to_dict()).encode("utf-8"))
140
+ else:
141
+ full_file_name = filename + ".json"
142
+ with open(filename + ".json", "w") as f:
143
+ f.write(json.dumps(self.to_dict()))
144
+
145
+ print("Saved to", full_file_name)
146
+
147
+ @staticmethod
148
+ def open_compressed_file(filename):
149
+ with gzip.open(filename, "rb") as f:
150
+ file_contents = f.read()
151
+ file_contents_decoded = file_contents.decode("utf-8")
152
+ d = json.loads(file_contents_decoded)
153
+ return d
154
+
155
+ @staticmethod
156
+ def open_regular_file(filename):
157
+ with open(filename, "r") as f:
158
+ d = json.loads(f.read())
159
+ return d
160
+
161
+ @classmethod
162
+ def load(cls, filename):
163
+ """Load the object from a file.
164
+
165
+ >>> obj = cls.load("obj.json.gz")
166
+
167
+ """
168
+
169
+ if filename.endswith("json.gz"):
170
+ d = cls.open_compressed_file(filename)
171
+ elif filename.endswith("json"):
172
+ d = cls.open_regular_file(filename)
173
+ else:
174
+ try:
175
+ d = cls.open_compressed_file(filename + ".json.gz")
176
+ except:
177
+ d = cls.open_regular_file(filename + ".json")
178
+ # finally:
179
+ # raise ValueError("File must be a json or json.gz file")
180
+
181
+ return cls.from_dict(d)
182
+
183
+
184
+ class RegisterSubclassesMeta(ABCMeta):
185
+ """Metaclass for registering subclasses."""
186
+
187
+ _registry = {}
188
+
189
+ def __init__(cls, name, bases, nmspc):
190
+ """Register the class in the registry upon creation."""
191
+ super(RegisterSubclassesMeta, cls).__init__(name, bases, nmspc)
192
+ if cls.__name__ != "Base":
193
+ RegisterSubclassesMeta._registry[cls.__name__] = cls
194
+
195
+ @staticmethod
196
+ def get_registry(exclude_classes: Optional[list] = None):
197
+ """Return the registry of subclasses."""
198
+ if exclude_classes is None:
199
+ exclude_classes = []
200
+ return {
201
+ k: v
202
+ for k, v in dict(RegisterSubclassesMeta._registry).items()
203
+ if k not in exclude_classes
204
+ }
205
+
206
+
207
+ class DiffMethodsMixin:
208
+ def __sub__(self, other):
209
+ """Return the difference between two objects."""
210
+ from edsl.BaseDiff import BaseDiff
211
+
212
+ return BaseDiff(self, other)
213
+
214
+
215
+ def is_iterable(obj):
216
+ try:
217
+ iter(obj)
218
+ except TypeError:
219
+ return False
220
+ return True
221
+
222
+
223
+ class RepresentationMixin:
224
+ def json(self):
225
+ return json.loads(json.dumps(self.to_dict(add_edsl_version=False)))
226
+
227
+ def to_dataset(self):
228
+ from edsl.results.Dataset import Dataset
229
+
230
+ return Dataset.from_edsl_object(self)
231
+
232
+ def view(self):
233
+ "Displays an interactive / perspective view of the object"
234
+ return self.to_dataset().view()
235
+
236
+ # def print(self, format="rich"):
237
+ # return self.to_dataset().table()
238
+
239
+ def display_dict(self):
240
+ display_dict = {}
241
+ d = self.to_dict(add_edsl_version=False)
242
+ for key, value in d.items():
243
+ if isinstance(value, dict):
244
+ for k, v in value.items():
245
+ display_dict[f"{key}:{k}"] = v
246
+ elif isinstance(value, list):
247
+ for i, v in enumerate(value):
248
+ display_dict[f"{key}:{i}"] = v
249
+ else:
250
+ display_dict[key] = value
251
+ return display_dict
252
+
253
+ def print(self, format="rich"):
254
+ from rich.table import Table
255
+ from rich.console import Console
256
+
257
+ table = Table(title=self.__class__.__name__)
258
+ table.add_column("Key", style="bold")
259
+ table.add_column("Value", style="bold")
260
+
261
+ for key, value in self.display_dict().items():
262
+ table.add_row(key, str(value))
263
+
264
+ console = Console(record=True)
265
+ console.print(table)
266
+
267
+ def help(obj):
268
+ """
269
+ Extract all public instance methods and their docstrings from a class instance.
270
+
271
+ Args:
272
+ obj: The instance to inspect
273
+
274
+ Returns:
275
+ dict: A dictionary where keys are method names and values are their docstrings
276
+ """
277
+ import inspect
278
+
279
+ if inspect.isclass(obj):
280
+ raise TypeError("Please provide a class instance, not a class")
281
+
282
+ methods = {}
283
+
284
+ # Get all members of the instance
285
+ for name, member in inspect.getmembers(obj):
286
+ # Skip private and special methods (those starting with underscore)
287
+ if name.startswith("_"):
288
+ continue
289
+
290
+ # Check if it's specifically an instance method
291
+ if inspect.ismethod(member):
292
+ # Get the docstring (or empty string if none exists)
293
+ docstring = inspect.getdoc(member) or ""
294
+ methods[name] = docstring
295
+
296
+ from edsl.results.Dataset import Dataset
297
+
298
+ d = Dataset(
299
+ [
300
+ {"method": list(methods.keys())},
301
+ {"documentation": list(methods.values())},
302
+ ]
303
+ )
304
+ return d
305
+
306
+ def _repr_html_(self):
307
+ from edsl.results.TableDisplay import TableDisplay
308
+
309
+ if hasattr(self, "_summary"):
310
+ summary_dict = self._summary()
311
+ summary_line = "".join([f" {k}: {v};" for k, v in summary_dict.items()])
312
+ class_name = self.__class__.__name__
313
+ docs = getattr(self, "__documentation__", "")
314
+ return (
315
+ "<p>"
316
+ + f"<a href='{docs}'>{class_name}</a>"
317
+ + summary_line
318
+ + "</p>"
319
+ + self.table()._repr_html_()
320
+ )
321
+ else:
322
+ class_name = self.__class__.__name__
323
+ documenation = getattr(self, "__documentation__", "")
324
+ summary_line = "<p>" + f"<a href='{documenation}'>{class_name}</a>" + "</p>"
325
+ display_dict = self.display_dict()
326
+ return (
327
+ summary_line
328
+ + TableDisplay.from_dictionary_wide(display_dict)._repr_html_()
329
+ )
330
+
331
+ def __str__(self):
332
+ return self.__repr__()
333
+
334
+
335
+ class HashingMixin:
336
+ def __hash__(self) -> int:
337
+ """Return a hash of the question."""
338
+ from edsl.utilities.utilities import dict_hash
339
+
340
+ return dict_hash(self.to_dict(add_edsl_version=False))
341
+
342
+ def __eq__(self, other):
343
+ """Return whether two objects are equal."""
344
+ return hash(self) == hash(other)
345
+
346
+
347
+ class Base(
348
+ RepresentationMixin,
349
+ PersistenceMixin,
350
+ DiffMethodsMixin,
351
+ HashingMixin,
352
+ ABC,
353
+ metaclass=RegisterSubclassesMeta,
354
+ ):
355
+ """Base class for all classes in the package."""
356
+
357
+ def keys(self):
358
+ """Return the keys of the object."""
359
+ _keys = list(self.to_dict().keys())
360
+ if "edsl_version" in _keys:
361
+ _keys.remove("edsl_version")
362
+ if "edsl_class_name" in _keys:
363
+ _keys.remove("edsl_class_name")
364
+ return _keys
365
+
366
+ def values(self):
367
+ """Return the values of the object."""
368
+ data = self.to_dict()
369
+ keys = self.keys()
370
+ return {data[key] for key in keys}
371
+
372
+ @abstractmethod
373
+ def example():
374
+ """This method should be implemented by subclasses."""
375
+ raise NotImplementedError("This method is not implemented yet.")
376
+
377
+ @abstractmethod
378
+ def to_dict():
379
+ """This method should be implemented by subclasses."""
380
+ raise NotImplementedError("This method is not implemented yet.")
381
+
382
+ def to_json(self):
383
+ return json.dumps(self.to_dict())
384
+
385
+ def store(self, d: dict, key_name: Optional[str] = None):
386
+ if key_name is None:
387
+ index = len(d)
388
+ else:
389
+ index = key_name
390
+ d[index] = self
391
+
392
+ @abstractmethod
393
+ def from_dict():
394
+ """This method should be implemented by subclasses."""
395
+ raise NotImplementedError("This method is not implemented yet.")
396
+
397
+ @abstractmethod
398
+ def code():
399
+ """This method should be implemented by subclasses."""
400
+ raise NotImplementedError("This method is not implemented yet.")
401
+
402
+ def show_methods(self, show_docstrings=True):
403
+ """Show the methods of the object."""
404
+ public_methods_with_docstrings = [
405
+ (method, getattr(self, method).__doc__)
406
+ for method in dir(self)
407
+ if callable(getattr(self, method)) and not method.startswith("_")
408
+ ]
409
+ if show_docstrings:
410
+ for method, documentation in public_methods_with_docstrings:
411
+ print(f"{method}: {documentation}")
412
+ else:
413
+ return [x[0] for x in public_methods_with_docstrings]