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
edsl/agents/AgentList.py CHANGED
@@ -1,55 +1,551 @@
1
+ """A list of Agents
2
+ """
3
+
1
4
  from __future__ import annotations
2
- import io
5
+ import csv
6
+ import sys
3
7
  from collections import UserList
4
- from typing import Optional, Union
8
+ from collections.abc import Iterable
9
+
10
+ from typing import Any, List, Optional, Union, TYPE_CHECKING
5
11
 
6
- from rich.console import Console
7
- from rich.table import Table
12
+ from simpleeval import EvalWithCompoundTypes, NameNotDefined
8
13
 
9
- from edsl.agents import Agent
10
- from edsl.agents.AgentListExportMixin import AgentListExportMixin
11
14
  from edsl.Base import Base
15
+ from edsl.utilities.remove_edsl_version import remove_edsl_version
16
+ from edsl.exceptions.agents import AgentListError
17
+ from edsl.utilities.is_notebook import is_notebook
18
+ from edsl.results.ResultsExportMixin import ResultsExportMixin
19
+ import logging
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+ if TYPE_CHECKING:
24
+ from edsl.scenarios.ScenarioList import ScenarioList
25
+ from edsl.agents.Agent import Agent
26
+ from pandas import DataFrame
27
+
28
+
29
+ def is_iterable(obj):
30
+ return isinstance(obj, Iterable)
31
+
12
32
 
33
+ class EmptyAgentList:
34
+ def __repr__(self):
35
+ return "Empty AgentList"
13
36
 
14
- class AgentList(UserList, Base, AgentListExportMixin):
15
- def __init__(self, data: Optional[list] = None):
37
+
38
+ # ResultsExportMixin,
39
+ class AgentList(UserList, Base):
40
+ """A list of Agents."""
41
+
42
+ __documentation__ = (
43
+ "https://docs.expectedparrot.com/en/latest/agents.html#agentlist-class"
44
+ )
45
+
46
+ def __init__(self, data: Optional[list["Agent"]] = None):
47
+ """Initialize a new AgentList.
48
+
49
+ :param data: A list of Agents.
50
+ """
16
51
  if data is not None:
17
52
  super().__init__(data)
18
53
  else:
19
54
  super().__init__()
20
55
 
21
- def to(self, question_or_survey: Union["Question", "Survey"]):
22
- return question_or_survey.by(*self)
56
+ def shuffle(self, seed: Optional[str] = None) -> AgentList:
57
+ """Shuffle the AgentList.
58
+
59
+ :param seed: The seed for the random number generator.
60
+ """
61
+ import random
62
+
63
+ if seed is not None:
64
+ random.seed(seed)
65
+ random.shuffle(self.data)
66
+ return self
67
+
68
+ def sample(self, n: int, seed: Optional[str] = None) -> AgentList:
69
+ """Return a random sample of agents.
70
+
71
+ :param n: The number of agents to sample.
72
+ :param seed: The seed for the random number generator.
73
+ """
74
+ import random
75
+
76
+ if seed:
77
+ random.seed(seed)
78
+ return AgentList(random.sample(self.data, n))
79
+
80
+ def to_pandas(self) -> "DataFrame":
81
+ """Return a pandas DataFrame.
82
+
83
+ >>> from edsl.agents.Agent import Agent
84
+ >>> al = AgentList([Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5}), Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5})])
85
+ >>> al.to_pandas()
86
+ age hair height
87
+ 0 22 brown 5.5
88
+ 1 22 brown 5.5
89
+ """
90
+ return self.to_scenario_list().to_pandas()
91
+
92
+ def tally(
93
+ self, *fields: Optional[str], top_n: Optional[int] = None, output="Dataset"
94
+ ) -> Union[dict, "Dataset"]:
95
+ """Tally the values of a field or perform a cross-tab of multiple fields.
96
+
97
+ :param fields: The field(s) to tally, multiple fields for cross-tabulation.
98
+
99
+ >>> al = AgentList.example()
100
+ >>> al.tally('age')
101
+ Dataset([{'age': [22]}, {'count': [2]}])
102
+ """
103
+ return self.to_scenario_list().tally(*fields, top_n=top_n, output=output)
104
+
105
+ def duplicate(self):
106
+ """Duplicate the AgentList.
107
+
108
+ >>> al = AgentList.example()
109
+ >>> al2 = al.duplicate()
110
+ >>> al2 == al
111
+ True
112
+ >>> id(al2) == id(al)
113
+ False
114
+ """
115
+ return AgentList([a.duplicate() for a in self.data])
116
+
117
+ def rename(self, old_name, new_name) -> AgentList:
118
+ """Rename a trait in the AgentList.
119
+
120
+ :param old_name: The old name of the trait.
121
+ :param new_name: The new name of the trait.
122
+ :param inplace: Whether to rename the trait in place.
123
+
124
+ >>> from edsl.agents.Agent import Agent
125
+ >>> al = AgentList([Agent(traits = {'a': 1, 'b': 1}), Agent(traits = {'a': 1, 'b': 2})])
126
+ >>> al2 = al.rename('a', 'c')
127
+ >>> assert al2 == AgentList([Agent(traits = {'c': 1, 'b': 1}), Agent(traits = {'c': 1, 'b': 2})])
128
+ >>> assert al != al2
129
+ """
130
+ newagents = []
131
+ for agent in self:
132
+ newagents.append(agent.rename(old_name, new_name))
133
+ return AgentList(newagents)
134
+
135
+ def select(self, *traits) -> AgentList:
136
+ """Selects agents with only the references traits.
137
+
138
+ >>> from edsl.agents.Agent import Agent
139
+ >>> al = AgentList([Agent(traits = {'a': 1, 'b': 1}), Agent(traits = {'a': 1, 'b': 2})])
140
+ >>> al.select('a')
141
+ AgentList([Agent(traits = {'a': 1}), Agent(traits = {'a': 1})])
142
+
143
+ """
144
+
145
+ if len(traits) == 1:
146
+ traits_to_select = [list(traits)[0]]
147
+ else:
148
+ traits_to_select = list(traits)
149
+
150
+ return AgentList([agent.select(*traits_to_select) for agent in self.data])
151
+
152
+ def filter(self, expression: str) -> AgentList:
153
+ """
154
+ Filter a list of agents based on an expression.
155
+
156
+ >>> from edsl.agents.Agent import Agent
157
+ >>> al = AgentList([Agent(traits = {'a': 1, 'b': 1}), Agent(traits = {'a': 1, 'b': 2})])
158
+ >>> al.filter("b == 2")
159
+ AgentList([Agent(traits = {'a': 1, 'b': 2})])
160
+ """
161
+
162
+ def create_evaluator(agent: "Agent"):
163
+ """Create an evaluator for the given result.
164
+ The 'combined_dict' is a mapping of all values for that Result object.
165
+ """
166
+ return EvalWithCompoundTypes(names=agent.traits)
167
+
168
+ # iterates through all the results and evaluates the expression
169
+
170
+ try:
171
+ new_data = [
172
+ agent for agent in self.data if create_evaluator(agent).eval(expression)
173
+ ]
174
+ except NameNotDefined as e:
175
+ e = AgentListError(f"'{expression}' is not a valid expression.")
176
+ if is_notebook():
177
+ print(e, file=sys.stderr)
178
+ else:
179
+ raise e
180
+
181
+ return EmptyAgentList()
182
+
183
+ if len(new_data) == 0:
184
+ return EmptyAgentList()
185
+
186
+ return AgentList(new_data)
187
+
188
+ @property
189
+ def all_traits(self) -> list[str]:
190
+ """Return all traits in the AgentList.
191
+ >>> from edsl.agents.Agent import Agent
192
+ >>> agent_1 = Agent(traits = {'age': 22})
193
+ >>> agent_2 = Agent(traits = {'hair': 'brown'})
194
+ >>> al = AgentList([agent_1, agent_2])
195
+ >>> al.all_traits
196
+ ['age', 'hair']
197
+ """
198
+ d = {}
199
+ for agent in self:
200
+ d.update(agent.traits)
201
+ return list(d.keys())
202
+
203
+ @classmethod
204
+ def from_csv(cls, file_path: str, name_field: Optional[str] = None):
205
+ """Load AgentList from a CSV file.
206
+
207
+ >>> import csv
208
+ >>> import os
209
+ >>> with open('/tmp/agents.csv', 'w') as f:
210
+ ... writer = csv.writer(f)
211
+ ... _ = writer.writerow(['age', 'hair', 'height'])
212
+ ... _ = writer.writerow([22, 'brown', 5.5])
213
+ >>> al = AgentList.from_csv('/tmp/agents.csv')
214
+ >>> al
215
+ AgentList([Agent(traits = {'age': '22', 'hair': 'brown', 'height': '5.5'})])
216
+ >>> al = AgentList.from_csv('/tmp/agents.csv', name_field='hair')
217
+ >>> al
218
+ AgentList([Agent(name = \"""brown\""", traits = {'age': '22', 'height': '5.5'})])
219
+ >>> os.remove('/tmp/agents.csv')
220
+
221
+ :param file_path: The path to the CSV file.
222
+ :param name_field: The name of the field to use as the agent name.
223
+ """
224
+ from edsl.agents.Agent import Agent
225
+
226
+ agent_list = []
227
+ with open(file_path, "r") as f:
228
+ reader = csv.DictReader(f)
229
+ for row in reader:
230
+ if "name" in row:
231
+ import warnings
232
+
233
+ warnings.warn("Using 'name' field in the CSV for the Agent name")
234
+ name_field = "name"
235
+ if name_field is not None:
236
+ agent_name = row.pop(name_field)
237
+ agent_list.append(Agent(traits=row, name=agent_name))
238
+ else:
239
+ agent_list.append(Agent(traits=row))
240
+ return cls(agent_list)
241
+
242
+ def translate_traits(self, codebook: dict[str, str]):
243
+ """Translate traits to a new codebook.
244
+
245
+ :param codebook: The new codebook.
246
+
247
+ >>> al = AgentList.example()
248
+ >>> codebook = {'hair': {'brown':'Secret word for green'}}
249
+ >>> al.translate_traits(codebook)
250
+ AgentList([Agent(traits = {'age': 22, 'hair': 'Secret word for green', 'height': 5.5}), Agent(traits = {'age': 22, 'hair': 'Secret word for green', 'height': 5.5})])
251
+ """
252
+ new_agents = []
253
+ for agent in self.data:
254
+ new_agents.append(agent.translate_traits(codebook))
255
+ return AgentList(new_agents)
256
+
257
+ def remove_trait(self, trait: str):
258
+ """Remove traits from the AgentList.
259
+
260
+ :param traits: The traits to remove.
261
+ >>> from edsl.agents.Agent import Agent
262
+ >>> al = AgentList([Agent({'age': 22, 'hair': 'brown', 'height': 5.5}), Agent({'age': 22, 'hair': 'brown', 'height': 5.5})])
263
+ >>> al.remove_trait('age')
264
+ AgentList([Agent(traits = {'hair': 'brown', 'height': 5.5}), Agent(traits = {'hair': 'brown', 'height': 5.5})])
265
+ """
266
+ agents = []
267
+ new_al = self.duplicate()
268
+ for agent in new_al.data:
269
+ agents.append(agent.remove_trait(trait))
270
+ return AgentList(agents)
23
271
 
24
- def to_dict(self):
25
- return {"agent_list": [agent.to_dict() for agent in self.data]}
272
+ def add_trait(self, trait: str, values: List[Any]) -> AgentList:
273
+ """Adds a new trait to every agent, with values taken from values.
274
+
275
+ :param trait: The name of the trait.
276
+ :param values: The valeues(s) of the trait. If a single value is passed, it is used for all agents.
277
+
278
+ >>> al = AgentList.example()
279
+ >>> new_al = al.add_trait('new_trait', 1)
280
+ >>> new_al.select('new_trait').to_scenario_list().to_list()
281
+ [1, 1]
282
+ >>> al.add_trait('new_trait', [1, 2, 3])
283
+ Traceback (most recent call last):
284
+ ...
285
+ edsl.exceptions.agents.AgentListError: The passed values have to be the same length as the agent list.
286
+ ...
287
+ """
288
+ if not is_iterable(values):
289
+ new_agents = []
290
+ value = values
291
+ for agent in self.data:
292
+ new_agents.append(agent.add_trait(trait, value))
293
+ return AgentList(new_agents)
294
+
295
+ if len(values) != len(self):
296
+ e = AgentListError(
297
+ "The passed values have to be the same length as the agent list."
298
+ )
299
+ if is_notebook():
300
+ print(e, file=sys.stderr)
301
+ else:
302
+ raise e
303
+ new_agents = []
304
+ for agent, value in zip(self.data, values):
305
+ new_agents.append(agent.add_trait(trait, value))
306
+ return AgentList(new_agents)
307
+
308
+ @staticmethod
309
+ def get_codebook(file_path: str):
310
+ """Return the codebook for a CSV file.
311
+
312
+ :param file_path: The path to the CSV file.
313
+ """
314
+ with open(file_path, "r") as f:
315
+ reader = csv.DictReader(f)
316
+ return {field: None for field in reader.fieldnames}
317
+
318
+ def __hash__(self) -> int:
319
+ """Return the hash of the AgentList.
320
+
321
+ >>> al = AgentList.example()
322
+ >>> hash(al)
323
+ 1681154913465662422
324
+ """
325
+ from edsl.utilities.utilities import dict_hash
326
+
327
+ return dict_hash(self.to_dict(add_edsl_version=False, sorted=True))
328
+
329
+ def to_dict(self, sorted=False, add_edsl_version=True):
330
+ """Serialize the AgentList to a dictionary.
331
+
332
+ >>> AgentList.example().to_dict(add_edsl_version=False)
333
+ {'agent_list': [{'traits': {'age': 22, 'hair': 'brown', 'height': 5.5}}, {'traits': {'age': 22, 'hair': 'brown', 'height': 5.5}}]}
334
+
335
+ """
336
+ if sorted:
337
+ data = self.data[:]
338
+ data.sort(key=lambda x: hash(x))
339
+ else:
340
+ data = self.data
341
+
342
+ d = {
343
+ "agent_list": [
344
+ agent.to_dict(add_edsl_version=add_edsl_version) for agent in data
345
+ ]
346
+ }
347
+ if add_edsl_version:
348
+ from edsl import __version__
349
+
350
+ d["edsl_version"] = __version__
351
+ d["edsl_class_name"] = "AgentList"
352
+
353
+ return d
354
+
355
+ def __eq__(self, other: AgentList) -> bool:
356
+ return self.to_dict(sorted=True, add_edsl_version=False) == other.to_dict(
357
+ sorted=True, add_edsl_version=False
358
+ )
359
+
360
+ def __repr__(self):
361
+ return f"AgentList({self.data})"
362
+
363
+ def _summary(self):
364
+ return {
365
+ "agents": len(self),
366
+ }
367
+
368
+ def set_codebook(self, codebook: dict[str, str]) -> AgentList:
369
+ """Set the codebook for the AgentList.
370
+
371
+ >>> from edsl.agents.Agent import Agent
372
+ >>> a = Agent(traits = {'hair': 'brown'})
373
+ >>> al = AgentList([a, a])
374
+ >>> _ = al.set_codebook({'hair': "Color of hair on driver's license"})
375
+ >>> al[0].codebook
376
+ {'hair': "Color of hair on driver's license"}
377
+
378
+
379
+ :param codebook: The codebook.
380
+ """
381
+ for agent in self.data:
382
+ agent.codebook = codebook
383
+
384
+ return self
385
+
386
+ def to_csv(self, file_path: str):
387
+ """Save the AgentList to a CSV file.
388
+
389
+ :param file_path: The path to the CSV file.
390
+ """
391
+ self.to_scenario_list().to_csv(file_path)
392
+
393
+ def to_list(self, include_agent_name=False) -> list[tuple]:
394
+ """Return a list of tuples."""
395
+ return self.to_scenario_list(include_agent_name).to_list()
396
+
397
+ def to_scenario_list(
398
+ self, include_agent_name: bool = False, include_instruction: bool = False
399
+ ) -> ScenarioList:
400
+ """Converts the agent to a scenario list."""
401
+ from edsl.scenarios.ScenarioList import ScenarioList
402
+ from edsl.scenarios.Scenario import Scenario
403
+
404
+ # raise NotImplementedError("This method is not implemented yet.")
405
+
406
+ scenario_list = ScenarioList()
407
+ for agent in self.data:
408
+ d = agent.traits
409
+ if include_agent_name:
410
+ d["agent_name"] = agent.name
411
+ if include_instruction:
412
+ d["instruction"] = agent.instruction
413
+ scenario_list.append(Scenario(d))
414
+ return scenario_list
415
+
416
+ # if include_agent_name:
417
+ # return ScenarioList(
418
+ # [
419
+ # Scenario(agent.traits | {"agent_name": agent.name} | })
420
+ # for agent in self.data
421
+ # ]
422
+ # )
423
+ # return ScenarioList([Scenario(agent.traits) for agent in self.data])
424
+
425
+ def table(
426
+ self,
427
+ *fields,
428
+ tablefmt: Optional[str] = None,
429
+ pretty_labels: Optional[dict] = None,
430
+ ) -> Table:
431
+ if len(self) == 0:
432
+ e = AgentListError("Cannot create a table from an empty AgentList.")
433
+ if is_notebook():
434
+ print(e, file=sys.stderr)
435
+ return None
436
+ else:
437
+ raise e
438
+ return (
439
+ self.to_scenario_list()
440
+ .to_dataset()
441
+ .table(*fields, tablefmt=tablefmt, pretty_labels=pretty_labels)
442
+ )
443
+
444
+ def to_dataset(self, traits_only: bool = True):
445
+ """
446
+ Convert the AgentList to a Dataset.
447
+
448
+ >>> from edsl.agents.AgentList import AgentList
449
+ >>> al = AgentList.example()
450
+ >>> al.to_dataset()
451
+ Dataset([{'age': [22, 22]}, {'hair': ['brown', 'brown']}, {'height': [5.5, 5.5]}])
452
+ >>> al.to_dataset(traits_only = False)
453
+ Dataset([{'age': [22, 22]}, {'hair': ['brown', 'brown']}, {'height': [5.5, 5.5]}, {'agent_parameters': [{'instruction': 'You are answering questions as if you were a human. Do not break character.', 'agent_name': None}, {'instruction': 'You are answering questions as if you were a human. Do not break character.', 'agent_name': None}]}])
454
+ """
455
+ from edsl.results.Dataset import Dataset
456
+ from collections import defaultdict
457
+
458
+ agent_trait_keys = []
459
+ for agent in self:
460
+ agent_keys = list(agent.traits.keys())
461
+ for key in agent_keys:
462
+ if key not in agent_trait_keys:
463
+ agent_trait_keys.append(key)
464
+
465
+ data = defaultdict(list)
466
+ for agent in self:
467
+ for trait_key in agent_trait_keys:
468
+ data[trait_key].append(agent.traits.get(trait_key, None))
469
+ if not traits_only:
470
+ data["agent_parameters"].append(
471
+ {"instruction": agent.instruction, "agent_name": agent.name}
472
+ )
473
+ return Dataset([{key: entry} for key, entry in data.items()])
474
+
475
+ def tree(self, node_order: Optional[List[str]] = None):
476
+ return self.to_scenario_list().tree(node_order)
26
477
 
27
478
  @classmethod
479
+ @remove_edsl_version
28
480
  def from_dict(cls, data: dict) -> "AgentList":
29
- """Deserializes the dictionary back to an Agent List object."""
481
+ """Deserialize the dictionary back to an AgentList object.
482
+
483
+ :param: data: A dictionary representing an AgentList.
484
+ >>> from edsl.agents.Agent import Agent
485
+ >>> al = AgentList([Agent.example(), Agent.example()])
486
+ >>> al2 = AgentList.from_dict(al.to_dict())
487
+ >>> al2 == al
488
+ True
489
+ """
490
+ from edsl.agents.Agent import Agent
491
+
30
492
  agents = [Agent.from_dict(agent_dict) for agent_dict in data["agent_list"]]
31
493
  return cls(agents)
32
494
 
33
495
  @classmethod
34
- def example(cls):
35
- return cls([Agent.example(), Agent.example()])
496
+ def example(cls, randomize: bool = False) -> AgentList:
497
+ """
498
+ Returns an example AgentList instance.
36
499
 
37
- def code(self):
500
+ :param randomize: If True, uses Agent's randomize method.
501
+ """
502
+ from edsl.agents.Agent import Agent
503
+
504
+ return cls([Agent.example(randomize), Agent.example(randomize)])
505
+
506
+ @classmethod
507
+ def from_list(self, trait_name: str, values: List[Any]):
508
+ """Create an AgentList from a list of values.
509
+
510
+ :param trait_name: The name of the trait.
511
+ :param values: A list of values.
512
+
513
+ >>> AgentList.from_list('age', [22, 23])
514
+ AgentList([Agent(traits = {'age': 22}), Agent(traits = {'age': 23})])
515
+ """
516
+ from edsl.agents.Agent import Agent
517
+
518
+ return AgentList([Agent({trait_name: value}) for value in values])
519
+
520
+ def __mul__(self, other: AgentList) -> AgentList:
521
+ """Takes the cross product of two AgentLists."""
522
+ from itertools import product
523
+
524
+ new_sl = []
525
+ for s1, s2 in list(product(self, other)):
526
+ new_sl.append(s1 + s2)
527
+ return AgentList(new_sl)
528
+
529
+ def code(self, string=True) -> Union[str, list[str]]:
530
+ """Return code to construct an AgentList.
531
+
532
+ >>> al = AgentList.example()
533
+ >>> print(al.code())
534
+ from edsl.agents.Agent import Agent
535
+ from edsl.agents.AgentList import AgentList
536
+ agent_list = AgentList([Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5}), Agent(traits = {'age': 22, 'hair': 'brown', 'height': 5.5})])
537
+ """
38
538
  lines = [
39
539
  "from edsl.agents.Agent import Agent",
40
540
  "from edsl.agents.AgentList import AgentList",
41
541
  ]
42
542
  lines.append(f"agent_list = AgentList({self.data})")
543
+ if string:
544
+ return "\n".join(lines)
43
545
  return lines
44
546
 
45
- def rich_print(self):
46
- """Displays an object as a table."""
47
- table = Table(title="AgentList")
48
- table.add_column("Agents", style="bold")
49
- for agent in self.data:
50
- table.add_row(agent.rich_print())
51
- return table
52
-
53
547
 
54
548
  if __name__ == "__main__":
55
- pass
549
+ import doctest
550
+
551
+ doctest.testmod(optionflags=doctest.ELLIPSIS)