edsl 0.1.14__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 +46 -10
  5. edsl/__version__.py +1 -0
  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 +121 -104
  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 -204
  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.14.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 -417
  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 -166
  360. edsl/jobs/runners/JobsRunnerDryRun.py +0 -19
  361. edsl/jobs/runners/JobsRunnerStreaming.py +0 -54
  362. edsl/jobs/task_management.py +0 -218
  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.14.dist-info/METADATA +0 -69
  403. edsl-0.1.14.dist-info/RECORD +0 -141
  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.14.dist-info โ†’ edsl-0.1.40.dist-info}/LICENSE +0 -0
@@ -1,3 +1,9 @@
1
+ """Utility functions for working with strings, dictionaries, and files."""
2
+
3
+ from functools import wraps
4
+ import types
5
+ import time
6
+
1
7
  import hashlib
2
8
  import json
3
9
  import keyword
@@ -8,11 +14,138 @@ import string
8
14
  import tempfile
9
15
  import gzip
10
16
  import webbrowser
17
+ import json
18
+
11
19
  from html import escape
12
20
  from typing import Callable, Union
13
21
 
14
22
 
23
+ class CustomEncoder(json.JSONEncoder):
24
+ def default(self, obj):
25
+ try:
26
+ return json.JSONEncoder.default(self, obj)
27
+ except TypeError:
28
+ return str(obj)
29
+
30
+
31
+ def time_it(func):
32
+ @wraps(func)
33
+ def wrapper(*args, **kwargs):
34
+ start_time = time.time()
35
+ result = func(*args, **kwargs)
36
+ end_time = time.time()
37
+ execution_time = end_time - start_time
38
+ class_name = args[0].__class__.__name__ if args else func.__module__
39
+ print(
40
+ f"Function {class_name}.{func.__name__} took {execution_time:.4f} seconds to execute"
41
+ )
42
+ return result
43
+
44
+ return wrapper
45
+
46
+
47
+ def time_all_functions(module_or_class):
48
+ for name, obj in vars(module_or_class).items():
49
+ if isinstance(obj, types.FunctionType):
50
+ setattr(module_or_class, name, time_it(obj))
51
+
52
+
53
+ def dict_hash(data: dict):
54
+ return hash(
55
+ int(hashlib.md5(json.dumps(data, sort_keys=True).encode()).hexdigest(), 16)
56
+ )
57
+
58
+
59
+ def extract_json_from_string(text):
60
+ pattern = re.compile(r"\{.*?\}")
61
+ match = pattern.search(text)
62
+ if match:
63
+ json_data = match.group(0)
64
+ try:
65
+ json_object = json.loads(json_data)
66
+ return json_object
67
+ except json.JSONDecodeError:
68
+ return None
69
+ return None
70
+
71
+
72
+ def fix_partial_correct_response(text: str) -> dict:
73
+ # Find the start position of the key "answer"
74
+ answer_key_start = text.find('"answer"')
75
+
76
+ if answer_key_start == -1:
77
+ return {"error": "No 'answer' key found in the text"}
78
+
79
+ # Define regex to find the complete JSON object starting with "answer"
80
+ json_pattern = r'(\{[^\{\}]*"answer"[^\{\}]*\})'
81
+ match = re.search(json_pattern, text)
82
+
83
+ if not match:
84
+ return {"error": "No valid JSON object found"}
85
+
86
+ # Extract the matched JSON object
87
+ json_object = match.group(0)
88
+
89
+ # Find the start and stop positions of the JSON object in the original text
90
+ start_pos = text.find(json_object)
91
+ stop_pos = start_pos + len(json_object)
92
+
93
+ # Parse the JSON object to validate it
94
+ try:
95
+ parsed_json = json.loads(json_object)
96
+ except json.JSONDecodeError:
97
+ return {"error": "Failed to parse JSON object"}
98
+
99
+ # Return the result as a dictionary with positions
100
+ return {"start": start_pos, "stop": stop_pos, "extracted_json": json_object}
101
+
102
+
103
+ def clean_json(bad_json_str):
104
+ """
105
+ Clean JSON string by replacing single quotes with double quotes
106
+
107
+ """
108
+ replacements = [
109
+ ("\\", "\\\\"),
110
+ ("\n", "\\n"),
111
+ ("\r", "\\r"),
112
+ ("\t", "\\t"),
113
+ ("\b", "\\b"),
114
+ ("\f", "\\f"),
115
+ ("[/INST]", "removed_inst"),
116
+ ]
117
+
118
+ s = bad_json_str
119
+ for old, new in replacements:
120
+ s = s.replace(old, new)
121
+ return s
122
+
123
+
124
+ # def data_to_html(data, replace_new_lines=False):
125
+ # if "edsl_version" in data:
126
+ # _ = data.pop("edsl_version")
127
+ # if "edsl_class_name" in data:
128
+ # _ = data.pop("edsl_class_name")
129
+
130
+ # from pygments import highlight
131
+ # from pygments.lexers import JsonLexer
132
+ # from pygments.formatters import HtmlFormatter
133
+ # from IPython.display import HTML
134
+
135
+ # json_str = json.dumps(data, indent=4, cls=CustomEncoder)
136
+ # formatted_json = highlight(
137
+ # json_str,
138
+ # JsonLexer(),
139
+ # HtmlFormatter(style="default", full=False, noclasses=False),
140
+ # )
141
+ # if replace_new_lines:
142
+ # formatted_json = formatted_json.replace("\\n", "<br>")
143
+
144
+ # return HTML(formatted_json).data
145
+
146
+
15
147
  def is_gzipped(file_path):
148
+ """Check if a file is gzipped."""
16
149
  try:
17
150
  with gzip.open(file_path, "rb") as file:
18
151
  file.read(1) # Try reading a small amount of data
@@ -22,7 +155,7 @@ def is_gzipped(file_path):
22
155
 
23
156
 
24
157
  def hash_value(value: Union[str, int]) -> str:
25
- """Hashes a string or integer value using SHA-256."""
158
+ """Hash a string or integer value using SHA-256."""
26
159
  if isinstance(value, str):
27
160
  value_bytes = value.encode("utf-8")
28
161
  elif isinstance(value, int):
@@ -34,7 +167,7 @@ def hash_value(value: Union[str, int]) -> str:
34
167
 
35
168
 
36
169
  def repair_json(json_string: str) -> str:
37
- """Attempts to repair a JSON string that is not valid JSON."""
170
+ """Attempt to repair a JSON string that is not valid JSON."""
38
171
  json_string = json_string.replace("\n", "\\n").replace("\r", "\\r")
39
172
  json_string = json_string.replace("'", "\\'")
40
173
  json_string = json_string.replace("'", '"')
@@ -45,6 +178,7 @@ def repair_json(json_string: str) -> str:
45
178
 
46
179
 
47
180
  def dict_to_html(d):
181
+ """Convert a dictionary to an HTML table."""
48
182
  # Start the HTML table
49
183
  html_table = f'<table border="1">\n<tr><th>{escape("Key")}</th><th>{escape("Value")}</th></tr>\n'
50
184
 
@@ -60,29 +194,53 @@ def dict_to_html(d):
60
194
 
61
195
 
62
196
  def is_notebook() -> bool:
197
+ """Check if the code is running in a Jupyter notebook or Google Colab."""
63
198
  try:
64
199
  shell = get_ipython().__class__.__name__
65
200
  if shell == "ZMQInteractiveShell":
66
201
  return True # Jupyter notebook or qtconsole
202
+ elif shell == "Shell": # Google Colab's shell class
203
+ import sys
204
+
205
+ if "google.colab" in sys.modules:
206
+ return True # Running in Google Colab
207
+ return False
67
208
  elif shell == "TerminalInteractiveShell":
68
209
  return False # Terminal running IPython
69
210
  else:
70
- return False # Other type (e.g., IDLE, PyCharm, etc.)
211
+ return False # Other type
71
212
  except NameError:
72
213
  return False # Probably standard Python interpreter
73
214
 
74
215
 
216
+ def file_notice(file_name):
217
+ """Print a notice about the file being created."""
218
+ if is_notebook():
219
+ from IPython.display import HTML, display
220
+
221
+ link_text = "Download file"
222
+ display(
223
+ HTML(
224
+ f'<p>File created: {file_name}</p>.<a href="{file_name}" download>{link_text}</a>'
225
+ )
226
+ )
227
+ else:
228
+ print(f"File created: {file_name}")
229
+
230
+
75
231
  class HTMLSnippet(str):
76
- """
77
- Creates an object with html content (`value`).
232
+ """Create an object with html content (`value`).
233
+
78
234
  `view` method allows you to view the html content in a web browser.
79
235
  """
80
236
 
81
237
  def __init__(self, value):
238
+ """Initialize the HTMLSnippet object."""
82
239
  super().__init__()
83
240
  self.value = value
84
241
 
85
242
  def view(self):
243
+ """View the HTML content in a web browser."""
86
244
  html_content = self.value
87
245
 
88
246
  # create a tempfile to write the HTML content
@@ -94,12 +252,12 @@ class HTMLSnippet(str):
94
252
 
95
253
 
96
254
  def random_string() -> str:
97
- """Generate a random string of fixed length"""
255
+ """Generate a random string of fixed length."""
98
256
  return "".join(random.choice(string.ascii_letters) for i in range(10))
99
257
 
100
258
 
101
259
  def shortname_proposal(question, max_length=None):
102
- """Take a question text and generate a slug"""
260
+ """Take a question text and generate a slug."""
103
261
  question = question.lower()
104
262
  tokens = question.split()
105
263
  stopwords = set(
@@ -138,7 +296,7 @@ def shortname_proposal(question, max_length=None):
138
296
 
139
297
 
140
298
  def text_to_shortname(long_text, forbidden_names=[]):
141
- """Creates a slug for the question"""
299
+ """Create a slug for the question."""
142
300
  proposed_name = shortname_proposal(long_text)
143
301
  counter = 1
144
302
  # make sure the name is unique
@@ -149,7 +307,7 @@ def text_to_shortname(long_text, forbidden_names=[]):
149
307
 
150
308
 
151
309
  def merge_dicts(dict_list):
152
- """Merges a list of dictionaries into a single dictionary."""
310
+ """Merge a list of dictionaries into a single dictionary."""
153
311
  result = {}
154
312
  all_keys = set()
155
313
  for d in dict_list:
@@ -160,7 +318,7 @@ def merge_dicts(dict_list):
160
318
 
161
319
 
162
320
  def extract_json_from_string(s):
163
- """Extracts a JSON string from a string."""
321
+ """Extract a JSON string from a string."""
164
322
  # Find the first occurrence of '{'
165
323
  start_idx = s.find("{")
166
324
  # Find the last occurrence of '}'
@@ -175,6 +333,7 @@ def extract_json_from_string(s):
175
333
 
176
334
 
177
335
  def valid_json(json_string):
336
+ """Check if a string is valid JSON."""
178
337
  try:
179
338
  _ = json.loads(json_string)
180
339
  return True
@@ -182,12 +341,18 @@ def valid_json(json_string):
182
341
  return False
183
342
 
184
343
 
185
- def is_valid_variable_name(name):
186
- return name.isidentifier() and not keyword.iskeyword(name)
344
+ def is_valid_variable_name(name, allow_name=True):
345
+ """Check if a string is a valid variable name."""
346
+ if allow_name:
347
+ return name.isidentifier() and not keyword.iskeyword(name)
348
+ else:
349
+ return (
350
+ name.isidentifier() and not keyword.iskeyword(name) and not name == "name"
351
+ )
187
352
 
188
353
 
189
354
  def create_valid_var_name(s, transform_func: Callable = lambda x: x.lower()) -> str:
190
- """Creates a valid variable name from a string."""
355
+ """Create a valid variable name from a string."""
191
356
  if transform_func is None:
192
357
  transform_func = lambda x: x
193
358
 
@@ -221,6 +386,7 @@ def create_valid_var_name(s, transform_func: Callable = lambda x: x.lower()) ->
221
386
 
222
387
 
223
388
  def shorten_string(s, max_length, placeholder="..."):
389
+ """Shorten a string to a maximum length by removing characters from the middle."""
224
390
  if len(s) <= max_length:
225
391
  return s
226
392
 
@@ -244,3 +410,27 @@ def shorten_string(s, max_length, placeholder="..."):
244
410
  end_remove = end_space
245
411
 
246
412
  return s[:start_remove] + placeholder + s[end_remove:]
413
+
414
+
415
+ def write_api_key_to_env(api_key: str) -> str:
416
+ """
417
+ Write the user's Expected Parrot key to their .env file.
418
+
419
+ If a .env file doesn't exist in the current directory, one will be created.
420
+
421
+ Returns a string representing the absolute path to the .env file.
422
+ """
423
+ from pathlib import Path
424
+ from dotenv import set_key
425
+
426
+ # Create .env file if it doesn't exist
427
+ env_path = ".env"
428
+ env_file = Path(env_path)
429
+ env_file.touch(exist_ok=True)
430
+
431
+ # Write API key to file
432
+ set_key(env_path, "EXPECTED_PARROT_API_KEY", str(api_key))
433
+
434
+ absolute_path_to_env = env_file.absolute().as_posix()
435
+
436
+ return absolute_path_to_env
@@ -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
+