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,184 +0,0 @@
1
- import pandas as pd
2
- import sqlite3
3
- from sqlalchemy import create_engine
4
- from enum import Enum
5
-
6
-
7
- class SQLDataShape(Enum):
8
- WIDE = "wide"
9
- LONG = "long"
10
-
11
-
12
- class ResultsDBMixin:
13
- def rows(self):
14
- for index, result in enumerate(self):
15
- yield from result.rows(index)
16
-
17
- def export_sql_dump(self, shape, filename):
18
- shape_enum = self._get_shape_enum(shape)
19
- conn = self.db(shape=shape_enum)
20
-
21
- # Open file to write SQL dump
22
- with open(filename, "w") as f:
23
- for line in conn.iterdump():
24
- f.write(f"{line}\n")
25
-
26
- # Close the connection
27
- conn.close()
28
-
29
- def backup_db_to_file(self, shape, filename):
30
- shape_enum = self._get_shape_enum(shape)
31
- # Source database connection (in-memory)
32
- source_conn = self.db(shape=shape_enum)
33
-
34
- # Destination database connection (file)
35
- dest_conn = sqlite3.connect(filename)
36
-
37
- # Backup in-memory database to file
38
- with source_conn:
39
- source_conn.backup(dest_conn)
40
-
41
- # Close both connections
42
- source_conn.close()
43
- dest_conn.close()
44
-
45
- def db(self, shape: SQLDataShape, remove_prefix=False):
46
- if shape == SQLDataShape.LONG:
47
- # Step 2: Create a SQLite Database in Memory
48
- conn = sqlite3.connect(":memory:")
49
-
50
- create_table_query = """
51
- CREATE TABLE self (
52
- id INTEGER,
53
- data_type TEXT,
54
- key TEXT,
55
- value TEXT
56
- )
57
- """
58
- conn.execute(create_table_query)
59
-
60
- # # Step 3: Insert the tuples into the table
61
- list_of_tuples = list(self.rows())
62
- insert_query = (
63
- "INSERT INTO self (id, data_type, key, value) VALUES (?, ?, ?, ?)"
64
- )
65
- conn.executemany(insert_query, list_of_tuples)
66
- conn.commit()
67
- return conn
68
- elif shape == SQLDataShape.WIDE:
69
- db_uri = "sqlite:///:memory:"
70
-
71
- # Create SQLAlchemy engine with the in-memory database connection string
72
- engine = create_engine(db_uri)
73
-
74
- # Convert DataFrame to SQLite in-memory database
75
- df = self.to_pandas(remove_prefix=remove_prefix)
76
- df.to_sql("self", engine, index=False, if_exists="replace")
77
-
78
- # Create a connection to the SQLite database
79
- conn = engine.connect()
80
- return conn
81
- else:
82
- raise Exception("Invalid SQLDataShape")
83
-
84
- def _get_shape_enum(self, shape: str):
85
- if shape is None:
86
- raise Exception("Must select either 'wide' or 'long' format")
87
- elif shape == "wide":
88
- return SQLDataShape.WIDE
89
- elif shape == "long":
90
- return SQLDataShape.LONG
91
- else:
92
- raise Exception("Invalid shape: must be either 'long' or 'wide'")
93
-
94
- def sql(
95
- self,
96
- query: str,
97
- shape: str,
98
- remove_prefix: bool = False,
99
- transpose: bool = None,
100
- transpose_by: str = None,
101
- csv: bool = False,
102
- ):
103
- """Execute a SQL query and return the results as a DataFrame.
104
- :param query: The SQL query to execute
105
- :param transpose: Transpose the DataFrame if True
106
- :param transpose_by: Column to use as the index when transposing, otherwise the first column
107
- :param csv: Return the DataFrame as a CSV string if True
108
- """
109
- shape_enum = self._get_shape_enum(shape)
110
-
111
- conn = self.db(shape=shape_enum, remove_prefix=remove_prefix)
112
- df = pd.read_sql_query(query, conn)
113
-
114
- # Transpose the DataFrame if transpose is True
115
- if transpose or transpose_by:
116
- df = pd.DataFrame(df)
117
- if transpose_by:
118
- df = df.set_index(transpose_by)
119
- else:
120
- df = df.set_index(df.columns[0])
121
- df = df.transpose()
122
-
123
- # Return as CSV if output is "csv"
124
- if csv:
125
- return df.to_csv(index=False)
126
- else:
127
- return df
128
-
129
- def show_schema(self, shape: str, remove_prefix: bool = False):
130
- shape_enum = self._get_shape_enum(shape)
131
- conn = self.db(shape=shape_enum, remove_prefix=remove_prefix)
132
-
133
- if shape_enum == SQLDataShape.LONG:
134
- # Query to get the schema of all tables
135
- query = "SELECT type, name, sql FROM sqlite_master WHERE type='table'"
136
-
137
- # Execute the query
138
- cursor = conn.execute(query)
139
- schema = cursor.fetchall()
140
-
141
- # Close the connection
142
- conn.close()
143
-
144
- # Format and return the schema information
145
- schema_info = ""
146
- for row in schema:
147
- schema_info += f"Type: {row[0]}, Name: {row[1]}, SQL: {row[2]}\n"
148
-
149
- print(schema_info)
150
- elif shape_enum == SQLDataShape.WIDE:
151
- query = f"PRAGMA table_info(self)"
152
- schema = pd.read_sql(query, conn)
153
- print(schema)
154
-
155
-
156
- if __name__ == "__main__":
157
- from edsl.results import Results
158
-
159
- r = Results.example()
160
-
161
- df = r.sql(
162
- "select data_type, key, value from self where data_type = 'answer'",
163
- shape="long",
164
- )
165
- print(df)
166
-
167
- df = r.sql(
168
- "select * from self",
169
- shape="wide",
170
- )
171
-
172
- df = r.sql(
173
- "select * from self",
174
- shape="wide",
175
- )
176
-
177
- r.show_schema(shape="long")
178
-
179
- df = r.sql(
180
- "select * from self",
181
- shape="wide",
182
- )
183
-
184
- print(df)
@@ -1,92 +0,0 @@
1
- import pydot
2
- import tempfile
3
- from IPython.display import Image
4
- from edsl.utilities import is_notebook
5
- from edsl.surveys.base import RulePriority, EndOfSurvey
6
-
7
-
8
- class SurveyFlowVisualizationMixin:
9
- def show_flow(self):
10
- "Creates an image showing the flow of users through the survey."
11
- # Create a graph object
12
- graph = pydot.Dot(graph_type="digraph")
13
-
14
- # Add nodes
15
- for index, question in enumerate(self.questions):
16
- graph.add_node(
17
- pydot.Node(
18
- f"Q{index}", label=f"{question.question_name}", shape="ellipse"
19
- )
20
- )
21
-
22
- # Add an "EndOfSurvey" node
23
- graph.add_node(
24
- pydot.Node("EndOfSurvey", label="End of Survey", shape="rectangle")
25
- )
26
-
27
- # Add edges for normal flow
28
- num_questions = len(self.questions)
29
- for index in range(num_questions - 1): # From Q1 to Q3
30
- graph.add_edge(pydot.Edge(f"Q{index}", f"Q{index+1}"))
31
-
32
- graph.add_edge(pydot.Edge(f"Q{num_questions-1}", "EndOfSurvey"))
33
-
34
- relevant_rules = [
35
- rule
36
- for rule in self.rule_collection
37
- if rule.priority > RulePriority.DEFAULT.value
38
- ]
39
-
40
- colors = [
41
- "blue",
42
- "red",
43
- "purple",
44
- "orange",
45
- "pink",
46
- "brown",
47
- "grey",
48
- "cyan",
49
- "green",
50
- ]
51
- rule_colors = {
52
- rule: colors[i % len(colors)] for i, rule in enumerate(relevant_rules)
53
- }
54
-
55
- for rule in relevant_rules:
56
- color = rule_colors[rule]
57
- edge_label = f"if {rule.expression}"
58
- source_node = f"Q{rule.current_q}"
59
- target_node = (
60
- f"Q{rule.next_q}" if rule.next_q != EndOfSurvey else "EndOfSurvey"
61
- )
62
- edge = pydot.Edge(
63
- source_node, target_node, label=edge_label, color=color, fontcolor=color
64
- )
65
- graph.add_edge(edge)
66
-
67
- with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmp_file:
68
- try:
69
- graph.write_png(tmp_file.name)
70
- except FileNotFoundError:
71
- print(
72
- """File not found. Most likely it's because you don't have graphviz installed. Please install it and try again.
73
- It's
74
- $ sudo apt-get install graphviz
75
- on Ubuntu.
76
- """
77
- )
78
-
79
- if is_notebook():
80
- display(Image(tmp_file.name))
81
- else:
82
- import os
83
- import sys
84
-
85
- if os.name == "nt": # Windows
86
- os.system(f"start {tmp_file.name}")
87
- elif os.name == "posix": # macOS, Linux, Unix, etc.
88
- os.system(
89
- f"open {tmp_file.name}"
90
- if sys.platform == "darwin"
91
- else f"xdg-open {tmp_file.name}"
92
- )
edsl/trackers/Tracker.py DELETED
@@ -1,91 +0,0 @@
1
- """
2
- This an ABC for a tracker that monitors a Python queue.
3
-
4
- Contained within the namespace is a class called TrackerEvent, which is also an ABC.
5
- This is the kind of event that will be placed in the queue the tracker is monitoring.
6
- Each child class of TrackerEvent needs to know how to update the state of the tracker.
7
-
8
- Each child has to implement a tracked_values method which tells what values the
9
- tracker is tracking - this is so it can pretty-print them.
10
-
11
- All child classes have to implement an allowed_events class variable.
12
-
13
- """
14
- import time
15
- from abc import ABC, abstractmethod
16
- from queue import Empty
17
- from edsl.utilities.interface import print_dict_with_rich
18
-
19
-
20
- class Tracker(ABC):
21
- "Meant to be single-threaded"
22
-
23
- class TrackerEvent(ABC):
24
- "Each child event needs to know how to update the state of the tracker."
25
-
26
- @abstractmethod
27
- def apply(self, tracker):
28
- pass
29
-
30
- def __init__(self, event_queue, verbose=False):
31
- self.event_queue = event_queue
32
- self.observed_events = []
33
- self.verbose = verbose
34
- if self.verbose:
35
- print("Tracker instantiated")
36
-
37
- @abstractmethod
38
- def allowed_events(self) -> set:
39
- "What events (classes) are allowed to be placed in the queue?"
40
- pass
41
-
42
- @abstractmethod
43
- def tracked_values(self) -> dict:
44
- "What values are tracked by this tracker (should be flat dictionary)?"
45
- pass
46
-
47
- def get_from_queue(self):
48
- """Gets events from the queue and stores them in a list.
49
- It runs until the event_queue is empty.
50
- """
51
- while True:
52
- try:
53
- event = self.event_queue.get(block=False)
54
- except Empty as e:
55
- if self.verbose:
56
- print("The queue is empty.")
57
- break
58
- else:
59
- self.observed_events.append(event)
60
- self.process_event(event)
61
- self.event_queue.task_done()
62
-
63
- def __call__(self, all_done, interval=1):
64
- if self.verbose:
65
- print("Tracking thread is starting.")
66
- while not all_done.is_set():
67
- self.get_from_queue()
68
- time.sleep(interval)
69
-
70
- # Run one last time to get anything still left in the event_queue
71
- self.get_from_queue()
72
-
73
- def process_event(self, event):
74
- """Processes an event from the event queue."""
75
-
76
- ## diabling this for now as two error-prone:
77
- # https://chat.openai.com/share/6e0e2ae2-30d7-4281-982a-a69a218c4e76
78
-
79
- # if not isinstance(event, tuple(self.allowed_events())):
80
- # print(f"Event type: {type(event).__name__}")
81
- # print(f"Allowed events: {self.allowed_events()}")
82
- # raise ValueError(f"Invalid event type: {type(event).__name__}")
83
-
84
- event.apply(self)
85
- if self.verbose:
86
- self.show_status()
87
-
88
- def show_status(self):
89
- """Prints the status of the interview manager."""
90
- data = self.tracked_values()
91
- print_dict_with_rich(data)
@@ -1,196 +0,0 @@
1
- """This tracker tracks API calls."""
2
- import json
3
- import time
4
- from collections import namedtuple
5
- from threading import Lock, Event
6
- from edsl.trackers.Tracker import Tracker
7
-
8
- UsageRates = namedtuple(
9
- "UsageRates",
10
- [
11
- "estimated_tokens_per_minute_k",
12
- "pct_of_tpm_limit",
13
- "estimated_requests_per_minute_k",
14
- "pct_of_rpm_limit",
15
- ],
16
- )
17
-
18
-
19
- class TrackerAPI(Tracker):
20
- """ """
21
-
22
- class APICallDetails(Tracker.TrackerEvent):
23
- def __init__(self, details):
24
- self.details = details
25
-
26
- def apply(self, tracker):
27
- with tracker.lock:
28
- tracker.usage.append(self.details)
29
-
30
- def __init__(
31
- self, lock, monitored_queue, tokens_per_minute_k=90, requests_per_minute_k=2
32
- ):
33
- self.lock = lock
34
- self.tokens_per_minute_k = tokens_per_minute_k
35
- self.requests_per_minute_k = requests_per_minute_k
36
- self.usage = []
37
-
38
- super().__init__(monitored_queue)
39
-
40
- def usage_rates(self, last_seconds=60):
41
- with self.lock:
42
- right_now = time.time()
43
- relevant_usage = [
44
- x
45
- for x in self.usage
46
- if (x["timestamp"] > right_now - last_seconds)
47
- and not x["cached_response"]
48
- ]
49
- if relevant_usage == []:
50
- return UsageRates(**{k: 0 for k in UsageRates._fields})
51
- else:
52
- elapsed_seconds = right_now - relevant_usage[0]["timestamp"]
53
- total_tokens = sum([x["total_tokens"] for x in relevant_usage])
54
-
55
- estimated_tokens_per_minute_k = round(
56
- total_tokens / (elapsed_seconds / 60.0) / 1000, 0
57
- )
58
- pct_of_tpm_limit = round(
59
- 100 * estimated_tokens_per_minute_k / self.tokens_per_minute_k
60
- )
61
-
62
- estimated_requests_per_minute_k = round(
63
- len(relevant_usage) / (elapsed_seconds / 60.0) / 1000, 2
64
- )
65
- pct_of_rpm_limit = round(
66
- 100 * estimated_requests_per_minute_k / self.requests_per_minute_k
67
- )
68
-
69
- usage_rates = UsageRates(
70
- estimated_tokens_per_minute_k=estimated_tokens_per_minute_k,
71
- pct_of_tpm_limit=pct_of_tpm_limit,
72
- estimated_requests_per_minute_k=estimated_requests_per_minute_k,
73
- pct_of_rpm_limit=pct_of_rpm_limit,
74
- )
75
-
76
- return usage_rates
77
-
78
- def tracked_values(self) -> dict:
79
- return {
80
- "Calls": len(self.usage),
81
- }
82
-
83
- def allowed_events(self):
84
- return set([TrackerAPI.APICallDetails])
85
-
86
- @classmethod
87
- def fromJSON(cls, filename):
88
- """This loads a tracker from a JSON file. Just for testing purposes"""
89
- with open(filename, "r") as f:
90
- json_dict = f.read()
91
- usage = json.loads(json_dict)
92
- # pretend responses are not cached for each testing, as the
93
- # usage_rate methods only compute w/ non-cached responses
94
- [x.update({"cached_response": False}) for x in usage]
95
- instance = cls(Lock(), None)
96
- instance.usage = usage
97
- return instance
98
-
99
- def toJSON(self, filename="sample_data.json"):
100
- with open(filename, "w") as f:
101
- json.dump(self.usage, f)
102
-
103
- def status(self):
104
- """This prints the status of the interview manager, while interviews are doing on."""
105
- estimated_length = 100
106
- completed = self.status_tracker.complete
107
- pct_completed = self.status_tracker.percentage_complete
108
- usage_rates = self.current_tpm(10)
109
- heartbeat = next(self.status_tracker.hearbeat)
110
- status_str = (
111
- f"{heartbeat} Completed: {completed} ({pct_completed} of total); "
112
- f"Est. TPM (k): {usage_rates.estimated_tokens_per_minute_k: ,} ({usage_rates.frac_of_tpm_limit}% of lim.); "
113
- f"Est. RPM (k): {usage_rates.estimated_requests_per_minute_k:,} ({usage_rates.frac_of_rpm_limit}% of lim.)); "
114
- )
115
- # Pad with spaces to reach the estimated length
116
- padded_status_str = status_str.ljust(estimated_length)
117
- print(f"\r{padded_status_str}", end="", flush=True)
118
-
119
-
120
- if __name__ == "__main__":
121
- import textwrap
122
- from language_models import LanguageModelOpenAIThreeFiveTurbo
123
-
124
- m = LanguageModelOpenAIThreeFiveTurbo(use_cache=True)
125
-
126
- # the language model is attached to the queue
127
- print(m.api_queue)
128
-
129
- # the tracker expects a lock and an event
130
- lock = Lock()
131
- all_done = Event()
132
-
133
- # tracker attached to the queue
134
- tracker = TrackerAPI(lock=lock, monitored_queue=m.api_queue)
135
-
136
- # the queue is empty to start
137
- print(f"Queue size: {m.api_queue.qsize()}")
138
-
139
- # a call is made to the language model
140
- raw = m.get_raw_response(
141
- prompt="What is your favorite color?",
142
- system_prompt=textwrap.dedent(
143
- """\
144
- You are pretending to be a human taking a survey.
145
- Do not break character.
146
- """
147
- ),
148
- )
149
-
150
- # sleep for a second, as queue puts are non-blocking
151
- import time
152
-
153
- print("Sleeping for 1 second")
154
- time.sleep(1)
155
- # see that the queue updated
156
- print(f"Queue size: {m.api_queue.qsize()}")
157
- print(m.parse_response(raw))
158
- # indicate we are all done
159
- all_done.set()
160
- # have the tracker finish up
161
- tracker(all_done, interval=1)
162
- # how many calls did the API observe?
163
- print(tracker.tracked_values())
164
- # what is in the tracker queue?
165
- print(tracker.usage)
166
- # confirm that the API queue is empty
167
- print(f"Queue size: {m.api_queue.qsize()}")
168
-
169
- ## Next example - compute queue statistics
170
- all_done = Event()
171
-
172
- tracker_two = TrackerAPI(lock=lock, monitored_queue=m.api_queue)
173
-
174
- for i in range(10):
175
- raw = m.get_raw_response(
176
- prompt=f"What emotions are associated with {i}?",
177
- system_prompt=textwrap.dedent(
178
- """\
179
- You are pretending to be a human taking a survey.
180
- Do not break character.
181
- """
182
- ),
183
- )
184
-
185
- time.sleep(1)
186
- all_done.set()
187
- # have the tracker finish up
188
- tracker(all_done, interval=1)
189
- # print(tracker.usage)
190
- tracker.toJSON(filename="sample_data.json")
191
-
192
- # from .example_api_call_data import sample_data
193
- tracker = TrackerAPI.fromJSON("sample_data.json")
194
- print(tracker.usage)
195
-
196
- print(tracker.usage_rates(1000000))
@@ -1,70 +0,0 @@
1
- from edsl.trackers.Tracker import Tracker
2
- from edsl.utilities.interface import heartbeat_generator, human_readable_labeler_creator
3
-
4
-
5
- class TrackerTasks(Tracker):
6
- """ """
7
-
8
- class WorkerActivated(Tracker.TrackerEvent):
9
- def apply(self, tracker):
10
- with tracker.lock:
11
- tracker.active_workers += 1
12
-
13
- class WorkerDeactivated(Tracker.TrackerEvent):
14
- def apply(self, tracker):
15
- with tracker.lock:
16
- tracker.active_workers -= 1
17
-
18
- class TaskStarted(Tracker.TrackerEvent):
19
- def apply(self, tracker):
20
- with tracker.lock:
21
- tracker.interviews_started += 1
22
-
23
- class TaskCompleted(Tracker.TrackerEvent):
24
- def apply(self, tracker):
25
- with tracker.lock:
26
- tracker.interviews_completed += 1
27
-
28
- class ThreadStatus(Tracker.TrackerEvent):
29
- def __init__(self, thread_id, status):
30
- self.thread_id = thread_id
31
- self.status = status
32
-
33
- def apply(self, tracker):
34
- with tracker.lock:
35
- tracker.thread_status[self.thread_id] = self.status
36
-
37
- def __init__(self, num_interviews, lock, monitored_queue):
38
- self.num_interviews = num_interviews # how many interviews are there in total
39
- self.lock = lock
40
- self.hearbeat = heartbeat_generator() # generator to show responses coming in
41
- self.active_workers = 0
42
- self.interviews_started = 0
43
- self.interviews_completed = 0
44
- self.thread_status = dict()
45
- # this is a function that takes thread IDs and turns them into successive integers
46
- self.human_readable_labeler = human_readable_labeler_creator()
47
-
48
- super().__init__(monitored_queue)
49
-
50
- def tracked_values(self) -> dict:
51
- return {
52
- "Active Workers": self.active_workers,
53
- "Interviews Started": self.interviews_started,
54
- "Completed Interviews": self.interviews_completed,
55
- }
56
-
57
- def allowed_events(self):
58
- return set(
59
- [
60
- TrackerTasks.WorkerActivated,
61
- TrackerTasks.WorkerDeactivated,
62
- TrackerTasks.TaskStarted,
63
- TrackerTasks.TaskCompleted,
64
- TrackerTasks.ThreadStatus,
65
- ]
66
- )
67
-
68
- @property
69
- def percentage_complete(self):
70
- return round(100 * self.interviews_completed / self.num_interviews, 2)