edsl 0.1.41__tar.gz → 0.1.42__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (369) hide show
  1. {edsl-0.1.41 → edsl-0.1.42}/PKG-INFO +2 -2
  2. {edsl-0.1.41 → edsl-0.1.42}/README.md +1 -1
  3. edsl-0.1.42/edsl/__version__.py +1 -0
  4. {edsl-0.1.41 → edsl-0.1.42}/edsl/agents/Invigilator.py +3 -2
  5. {edsl-0.1.41 → edsl-0.1.42}/edsl/agents/InvigilatorBase.py +2 -1
  6. {edsl-0.1.41 → edsl-0.1.42}/edsl/agents/QuestionTemplateReplacementsBuilder.py +7 -2
  7. {edsl-0.1.41 → edsl-0.1.42}/edsl/coop/coop.py +32 -0
  8. {edsl-0.1.41 → edsl-0.1.42}/edsl/enums.py +3 -0
  9. edsl-0.1.42/edsl/exceptions/jobs.py +25 -0
  10. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/language_models.py +8 -4
  11. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/questions.py +8 -11
  12. edsl-0.1.42/edsl/inference_services/DeepSeekService.py +18 -0
  13. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/registry.py +2 -0
  14. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/Jobs.py +18 -11
  15. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/JobsPrompts.py +11 -1
  16. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/JobsRemoteInferenceHandler.py +1 -0
  17. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/JobsRemoteInferenceLogger.py +1 -1
  18. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/interviews/Interview.py +1 -1
  19. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/loggers/HTMLTableJobLogger.py +6 -1
  20. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/results_exceptions_handler.py +2 -7
  21. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/tasks/TaskHistory.py +49 -17
  22. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/LanguageModel.py +7 -4
  23. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/ModelList.py +1 -1
  24. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/model.py +49 -0
  25. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/descriptors.py +5 -5
  26. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/Result.py +9 -3
  27. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/Results.py +1 -1
  28. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/PdfExtractor.py +3 -6
  29. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/Scenario.py +2 -1
  30. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/Survey.py +1 -1
  31. {edsl-0.1.41 → edsl-0.1.42}/edsl/templates/error_reporting/base.html +2 -4
  32. edsl-0.1.42/edsl/templates/error_reporting/exceptions_table.html +35 -0
  33. {edsl-0.1.41 → edsl-0.1.42}/edsl/templates/error_reporting/interview_details.html +67 -53
  34. edsl-0.1.42/edsl/templates/error_reporting/interviews.html +6 -0
  35. edsl-0.1.42/edsl/templates/error_reporting/overview.html +31 -0
  36. edsl-0.1.42/edsl/templates/error_reporting/performance_plot.html +2 -0
  37. {edsl-0.1.41 → edsl-0.1.42}/pyproject.toml +1 -1
  38. edsl-0.1.41/edsl/__version__.py +0 -1
  39. edsl-0.1.41/edsl/exceptions/jobs.py +0 -33
  40. edsl-0.1.41/edsl/templates/error_reporting/interviews.html +0 -19
  41. edsl-0.1.41/edsl/templates/error_reporting/overview.html +0 -5
  42. edsl-0.1.41/edsl/templates/error_reporting/performance_plot.html +0 -2
  43. {edsl-0.1.41 → edsl-0.1.42}/LICENSE +0 -0
  44. {edsl-0.1.41 → edsl-0.1.42}/edsl/Base.py +0 -0
  45. {edsl-0.1.41 → edsl-0.1.42}/edsl/BaseDiff.py +0 -0
  46. {edsl-0.1.41 → edsl-0.1.42}/edsl/TemplateLoader.py +0 -0
  47. {edsl-0.1.41 → edsl-0.1.42}/edsl/__init__.py +0 -0
  48. {edsl-0.1.41 → edsl-0.1.42}/edsl/agents/Agent.py +0 -0
  49. {edsl-0.1.41 → edsl-0.1.42}/edsl/agents/AgentList.py +0 -0
  50. {edsl-0.1.41 → edsl-0.1.42}/edsl/agents/PromptConstructor.py +0 -0
  51. {edsl-0.1.41 → edsl-0.1.42}/edsl/agents/QuestionInstructionPromptBuilder.py +0 -0
  52. {edsl-0.1.41 → edsl-0.1.42}/edsl/agents/__init__.py +0 -0
  53. {edsl-0.1.41 → edsl-0.1.42}/edsl/agents/descriptors.py +0 -0
  54. {edsl-0.1.41 → edsl-0.1.42}/edsl/agents/prompt_helpers.py +0 -0
  55. {edsl-0.1.41 → edsl-0.1.42}/edsl/agents/question_option_processor.py +0 -0
  56. {edsl-0.1.41 → edsl-0.1.42}/edsl/auto/AutoStudy.py +0 -0
  57. {edsl-0.1.41 → edsl-0.1.42}/edsl/auto/StageBase.py +0 -0
  58. {edsl-0.1.41 → edsl-0.1.42}/edsl/auto/StageGenerateSurvey.py +0 -0
  59. {edsl-0.1.41 → edsl-0.1.42}/edsl/auto/StageLabelQuestions.py +0 -0
  60. {edsl-0.1.41 → edsl-0.1.42}/edsl/auto/StagePersona.py +0 -0
  61. {edsl-0.1.41 → edsl-0.1.42}/edsl/auto/StagePersonaDimensionValueRanges.py +0 -0
  62. {edsl-0.1.41 → edsl-0.1.42}/edsl/auto/StagePersonaDimensionValues.py +0 -0
  63. {edsl-0.1.41 → edsl-0.1.42}/edsl/auto/StagePersonaDimensions.py +0 -0
  64. {edsl-0.1.41 → edsl-0.1.42}/edsl/auto/StageQuestions.py +0 -0
  65. {edsl-0.1.41 → edsl-0.1.42}/edsl/auto/SurveyCreatorPipeline.py +0 -0
  66. {edsl-0.1.41 → edsl-0.1.42}/edsl/auto/utilities.py +0 -0
  67. {edsl-0.1.41 → edsl-0.1.42}/edsl/base/Base.py +0 -0
  68. {edsl-0.1.41 → edsl-0.1.42}/edsl/config.py +0 -0
  69. {edsl-0.1.41 → edsl-0.1.42}/edsl/conversation/Conversation.py +0 -0
  70. {edsl-0.1.41 → edsl-0.1.42}/edsl/conversation/car_buying.py +0 -0
  71. {edsl-0.1.41 → edsl-0.1.42}/edsl/conversation/chips.py +0 -0
  72. {edsl-0.1.41 → edsl-0.1.42}/edsl/conversation/mug_negotiation.py +0 -0
  73. {edsl-0.1.41 → edsl-0.1.42}/edsl/conversation/next_speaker_utilities.py +0 -0
  74. {edsl-0.1.41 → edsl-0.1.42}/edsl/coop/CoopFunctionsMixin.py +0 -0
  75. {edsl-0.1.41 → edsl-0.1.42}/edsl/coop/ExpectedParrotKeyHandler.py +0 -0
  76. {edsl-0.1.41 → edsl-0.1.42}/edsl/coop/PriceFetcher.py +0 -0
  77. {edsl-0.1.41 → edsl-0.1.42}/edsl/coop/__init__.py +0 -0
  78. {edsl-0.1.41 → edsl-0.1.42}/edsl/coop/utils.py +0 -0
  79. {edsl-0.1.41 → edsl-0.1.42}/edsl/data/Cache.py +0 -0
  80. {edsl-0.1.41 → edsl-0.1.42}/edsl/data/CacheEntry.py +0 -0
  81. {edsl-0.1.41 → edsl-0.1.42}/edsl/data/CacheHandler.py +0 -0
  82. {edsl-0.1.41 → edsl-0.1.42}/edsl/data/RemoteCacheSync.py +0 -0
  83. {edsl-0.1.41 → edsl-0.1.42}/edsl/data/SQLiteDict.py +0 -0
  84. {edsl-0.1.41 → edsl-0.1.42}/edsl/data/__init__.py +0 -0
  85. {edsl-0.1.41 → edsl-0.1.42}/edsl/data/orm.py +0 -0
  86. {edsl-0.1.41 → edsl-0.1.42}/edsl/data_transfer_models.py +0 -0
  87. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/BaseException.py +0 -0
  88. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/__init__.py +0 -0
  89. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/agents.py +0 -0
  90. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/cache.py +0 -0
  91. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/configuration.py +0 -0
  92. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/coop.py +0 -0
  93. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/data.py +0 -0
  94. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/general.py +0 -0
  95. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/inference_services.py +0 -0
  96. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/prompts.py +0 -0
  97. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/results.py +0 -0
  98. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/scenarios.py +0 -0
  99. {edsl-0.1.41 → edsl-0.1.42}/edsl/exceptions/surveys.py +0 -0
  100. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/AnthropicService.py +0 -0
  101. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/AvailableModelCacheHandler.py +0 -0
  102. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/AvailableModelFetcher.py +0 -0
  103. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/AwsBedrock.py +0 -0
  104. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/AzureAI.py +0 -0
  105. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/DeepInfraService.py +0 -0
  106. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/GoogleService.py +0 -0
  107. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/GroqService.py +0 -0
  108. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/InferenceServiceABC.py +0 -0
  109. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/InferenceServicesCollection.py +0 -0
  110. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/MistralAIService.py +0 -0
  111. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/OllamaService.py +0 -0
  112. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/OpenAIService.py +0 -0
  113. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/PerplexityService.py +0 -0
  114. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/ServiceAvailability.py +0 -0
  115. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/TestService.py +0 -0
  116. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/TogetherAIService.py +0 -0
  117. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/__init__.py +0 -0
  118. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/data_structures.py +0 -0
  119. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/models_available_cache.py +0 -0
  120. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/rate_limits_cache.py +0 -0
  121. {edsl-0.1.41 → edsl-0.1.42}/edsl/inference_services/write_available.py +0 -0
  122. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/AnswerQuestionFunctionConstructor.py +0 -0
  123. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/Answers.py +0 -0
  124. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/FetchInvigilator.py +0 -0
  125. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/InterviewTaskManager.py +0 -0
  126. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/InterviewsConstructor.py +0 -0
  127. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/JobsChecks.py +0 -0
  128. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/JobsComponentConstructor.py +0 -0
  129. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/RequestTokenEstimator.py +0 -0
  130. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/__init__.py +0 -0
  131. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/async_interview_runner.py +0 -0
  132. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/buckets/BucketCollection.py +0 -0
  133. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/buckets/ModelBuckets.py +0 -0
  134. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/buckets/TokenBucket.py +0 -0
  135. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/buckets/TokenBucketAPI.py +0 -0
  136. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/buckets/TokenBucketClient.py +0 -0
  137. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/check_survey_scenario_compatibility.py +0 -0
  138. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/data_structures.py +0 -0
  139. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/decorators.py +0 -0
  140. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/interviews/InterviewExceptionCollection.py +0 -0
  141. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/interviews/InterviewExceptionEntry.py +0 -0
  142. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/interviews/InterviewStatistic.py +0 -0
  143. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/interviews/InterviewStatisticsCollection.py +0 -0
  144. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/interviews/InterviewStatusDictionary.py +0 -0
  145. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/interviews/InterviewStatusLog.py +0 -0
  146. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/interviews/ReportErrors.py +0 -0
  147. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/interviews/interview_status_enum.py +0 -0
  148. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/jobs_status_enums.py +0 -0
  149. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/runners/JobsRunnerAsyncio.py +0 -0
  150. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/runners/JobsRunnerStatus.py +0 -0
  151. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/runners/JobsRunnerStatusData.py +0 -0
  152. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/tasks/QuestionTaskCreator.py +0 -0
  153. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/tasks/TaskCreators.py +0 -0
  154. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/tasks/TaskStatusLog.py +0 -0
  155. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/tasks/task_status_enum.py +0 -0
  156. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/tokens/InterviewTokenUsage.py +0 -0
  157. {edsl-0.1.41 → edsl-0.1.42}/edsl/jobs/tokens/TokenUsage.py +0 -0
  158. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/ComputeCost.py +0 -0
  159. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/PriceManager.py +0 -0
  160. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/RawResponseHandler.py +0 -0
  161. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/RegisterLanguageModelsMeta.py +0 -0
  162. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/ServiceDataSources.py +0 -0
  163. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/__init__.py +0 -0
  164. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/fake_openai_call.py +0 -0
  165. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/fake_openai_service.py +0 -0
  166. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/key_management/KeyLookup.py +0 -0
  167. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/key_management/KeyLookupBuilder.py +0 -0
  168. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/key_management/KeyLookupCollection.py +0 -0
  169. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/key_management/__init__.py +0 -0
  170. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/key_management/models.py +0 -0
  171. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/repair.py +0 -0
  172. {edsl-0.1.41 → edsl-0.1.42}/edsl/language_models/utilities.py +0 -0
  173. {edsl-0.1.41 → edsl-0.1.42}/edsl/notebooks/Notebook.py +0 -0
  174. {edsl-0.1.41 → edsl-0.1.42}/edsl/notebooks/NotebookToLaTeX.py +0 -0
  175. {edsl-0.1.41 → edsl-0.1.42}/edsl/notebooks/__init__.py +0 -0
  176. {edsl-0.1.41 → edsl-0.1.42}/edsl/prompts/Prompt.py +0 -0
  177. {edsl-0.1.41 → edsl-0.1.42}/edsl/prompts/__init__.py +0 -0
  178. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/ExceptionExplainer.py +0 -0
  179. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/HTMLQuestion.py +0 -0
  180. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionBase.py +0 -0
  181. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionBasePromptsMixin.py +0 -0
  182. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionBudget.py +0 -0
  183. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionCheckBox.py +0 -0
  184. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionDict.py +0 -0
  185. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionExtract.py +0 -0
  186. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionFreeText.py +0 -0
  187. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionFunctional.py +0 -0
  188. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionList.py +0 -0
  189. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionMatrix.py +0 -0
  190. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionMultipleChoice.py +0 -0
  191. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionNumerical.py +0 -0
  192. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/QuestionRank.py +0 -0
  193. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/Quick.py +0 -0
  194. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/SimpleAskMixin.py +0 -0
  195. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/__init__.py +0 -0
  196. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/answer_validator_mixin.py +0 -0
  197. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/compose_questions.py +0 -0
  198. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/data_structures.py +0 -0
  199. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/decorators.py +0 -0
  200. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/derived/QuestionLikertFive.py +0 -0
  201. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/derived/QuestionLinearScale.py +0 -0
  202. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/derived/QuestionTopK.py +0 -0
  203. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/derived/QuestionYesNo.py +0 -0
  204. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/derived/__init__.py +0 -0
  205. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/loop_processor.py +0 -0
  206. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/prompt_templates/question_budget.jinja +0 -0
  207. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/prompt_templates/question_checkbox.jinja +0 -0
  208. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/prompt_templates/question_extract.jinja +0 -0
  209. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/prompt_templates/question_free_text.jinja +0 -0
  210. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/prompt_templates/question_linear_scale.jinja +0 -0
  211. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/prompt_templates/question_list.jinja +0 -0
  212. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/prompt_templates/question_multiple_choice.jinja +0 -0
  213. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/prompt_templates/question_numerical.jinja +0 -0
  214. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/question_base_gen_mixin.py +0 -0
  215. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/question_registry.py +0 -0
  216. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/register_questions_meta.py +0 -0
  217. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/response_validator_abc.py +0 -0
  218. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/response_validator_factory.py +0 -0
  219. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/settings.py +0 -0
  220. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/__init__.py +0 -0
  221. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/budget/__init__.py +0 -0
  222. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/budget/answering_instructions.jinja +0 -0
  223. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/budget/question_presentation.jinja +0 -0
  224. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/checkbox/__init__.py +0 -0
  225. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/checkbox/answering_instructions.jinja +0 -0
  226. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/checkbox/question_presentation.jinja +0 -0
  227. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/dict/__init__.py +0 -0
  228. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/dict/answering_instructions.jinja +0 -0
  229. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/dict/question_presentation.jinja +0 -0
  230. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/extract/__init__.py +0 -0
  231. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/extract/answering_instructions.jinja +0 -0
  232. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/extract/question_presentation.jinja +0 -0
  233. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/free_text/__init__.py +0 -0
  234. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/free_text/answering_instructions.jinja +0 -0
  235. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/free_text/question_presentation.jinja +0 -0
  236. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/likert_five/__init__.py +0 -0
  237. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/likert_five/answering_instructions.jinja +0 -0
  238. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/likert_five/question_presentation.jinja +0 -0
  239. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/linear_scale/__init__.py +0 -0
  240. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/linear_scale/answering_instructions.jinja +0 -0
  241. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/linear_scale/question_presentation.jinja +0 -0
  242. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/list/__init__.py +0 -0
  243. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/list/answering_instructions.jinja +0 -0
  244. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/list/question_presentation.jinja +0 -0
  245. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/matrix/__init__.py +0 -0
  246. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/matrix/answering_instructions.jinja +0 -0
  247. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/matrix/question_presentation.jinja +0 -0
  248. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/multiple_choice/__init__.py +0 -0
  249. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/multiple_choice/answering_instructions.jinja +0 -0
  250. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/multiple_choice/html.jinja +0 -0
  251. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/multiple_choice/question_presentation.jinja +0 -0
  252. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/numerical/__init__.py +0 -0
  253. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/numerical/answering_instructions.jinja +0 -0
  254. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/numerical/question_presentation.jinja +0 -0
  255. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/rank/__init__.py +0 -0
  256. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/rank/answering_instructions.jinja +0 -0
  257. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/rank/question_presentation.jinja +0 -0
  258. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/top_k/__init__.py +0 -0
  259. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/top_k/answering_instructions.jinja +0 -0
  260. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/top_k/question_presentation.jinja +0 -0
  261. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/yes_no/__init__.py +0 -0
  262. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/yes_no/answering_instructions.jinja +0 -0
  263. {edsl-0.1.41 → edsl-0.1.42}/edsl/questions/templates/yes_no/question_presentation.jinja +0 -0
  264. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/CSSParameterizer.py +0 -0
  265. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/Dataset.py +0 -0
  266. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/DatasetExportMixin.py +0 -0
  267. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/DatasetTree.py +0 -0
  268. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/MarkdownToDocx.py +0 -0
  269. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/MarkdownToPDF.py +0 -0
  270. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/ResultsExportMixin.py +0 -0
  271. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/ResultsGGMixin.py +0 -0
  272. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/TableDisplay.py +0 -0
  273. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/TextEditor.py +0 -0
  274. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/__init__.py +0 -0
  275. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/file_exports.py +0 -0
  276. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/results_fetch_mixin.py +0 -0
  277. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/results_selector.py +0 -0
  278. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/results_tools_mixin.py +0 -0
  279. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/smart_objects.py +0 -0
  280. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/table_data_class.py +0 -0
  281. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/table_display.css +0 -0
  282. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/table_renderers.py +0 -0
  283. {edsl-0.1.41 → edsl-0.1.42}/edsl/results/tree_explore.py +0 -0
  284. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/ConstructDownloadLink.py +0 -0
  285. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/DocumentChunker.py +0 -0
  286. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/DocxScenario.py +0 -0
  287. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/FileStore.py +0 -0
  288. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/ScenarioHtmlMixin.py +0 -0
  289. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/ScenarioList.py +0 -0
  290. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/ScenarioListExportMixin.py +0 -0
  291. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/ScenarioListPdfMixin.py +0 -0
  292. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/__init__.py +0 -0
  293. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/directory_scanner.py +0 -0
  294. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/file_methods.py +0 -0
  295. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/__init__.py +0 -0
  296. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/csv.py +0 -0
  297. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/docx.py +0 -0
  298. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/html.py +0 -0
  299. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/json.py +0 -0
  300. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/latex.py +0 -0
  301. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/md.py +0 -0
  302. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/pdf.py +0 -0
  303. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/png.py +0 -0
  304. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/pptx.py +0 -0
  305. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/py.py +0 -0
  306. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/sql.py +0 -0
  307. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/sqlite.py +0 -0
  308. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/handlers/txt.py +0 -0
  309. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/scenario_join.py +0 -0
  310. {edsl-0.1.41 → edsl-0.1.42}/edsl/scenarios/scenario_selector.py +0 -0
  311. {edsl-0.1.41 → edsl-0.1.42}/edsl/shared.py +0 -0
  312. {edsl-0.1.41 → edsl-0.1.42}/edsl/study/ObjectEntry.py +0 -0
  313. {edsl-0.1.41 → edsl-0.1.42}/edsl/study/ProofOfWork.py +0 -0
  314. {edsl-0.1.41 → edsl-0.1.42}/edsl/study/SnapShot.py +0 -0
  315. {edsl-0.1.41 → edsl-0.1.42}/edsl/study/Study.py +0 -0
  316. {edsl-0.1.41 → edsl-0.1.42}/edsl/study/__init__.py +0 -0
  317. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/ConstructDAG.py +0 -0
  318. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/DAG.py +0 -0
  319. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/EditSurvey.py +0 -0
  320. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/InstructionHandler.py +0 -0
  321. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/Memory.py +0 -0
  322. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/MemoryManagement.py +0 -0
  323. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/MemoryPlan.py +0 -0
  324. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/Rule.py +0 -0
  325. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/RuleCollection.py +0 -0
  326. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/RuleManager.py +0 -0
  327. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/Simulator.py +0 -0
  328. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/SurveyCSS.py +0 -0
  329. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/SurveyExportMixin.py +0 -0
  330. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/SurveyFlowVisualization.py +0 -0
  331. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/SurveyQualtricsImport.py +0 -0
  332. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/SurveyToApp.py +0 -0
  333. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/__init__.py +0 -0
  334. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/base.py +0 -0
  335. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/descriptors.py +0 -0
  336. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/instructions/ChangeInstruction.py +0 -0
  337. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/instructions/Instruction.py +0 -0
  338. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/instructions/InstructionCollection.py +0 -0
  339. {edsl-0.1.41 → edsl-0.1.42}/edsl/surveys/instructions/__init__.py +0 -0
  340. {edsl-0.1.41 → edsl-0.1.42}/edsl/templates/error_reporting/exceptions_by_model.html +0 -0
  341. {edsl-0.1.41 → edsl-0.1.42}/edsl/templates/error_reporting/exceptions_by_question_name.html +0 -0
  342. {edsl-0.1.41 → edsl-0.1.42}/edsl/templates/error_reporting/exceptions_by_type.html +0 -0
  343. {edsl-0.1.41 → edsl-0.1.42}/edsl/templates/error_reporting/report.css +0 -0
  344. {edsl-0.1.41 → edsl-0.1.42}/edsl/templates/error_reporting/report.html +0 -0
  345. {edsl-0.1.41 → edsl-0.1.42}/edsl/templates/error_reporting/report.js +0 -0
  346. {edsl-0.1.41 → edsl-0.1.42}/edsl/tools/__init__.py +0 -0
  347. {edsl-0.1.41 → edsl-0.1.42}/edsl/tools/clusters.py +0 -0
  348. {edsl-0.1.41 → edsl-0.1.42}/edsl/tools/embeddings.py +0 -0
  349. {edsl-0.1.41 → edsl-0.1.42}/edsl/tools/embeddings_plotting.py +0 -0
  350. {edsl-0.1.41 → edsl-0.1.42}/edsl/tools/plotting.py +0 -0
  351. {edsl-0.1.41 → edsl-0.1.42}/edsl/tools/summarize.py +0 -0
  352. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/PrettyList.py +0 -0
  353. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/SystemInfo.py +0 -0
  354. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/__init__.py +0 -0
  355. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/ast_utilities.py +0 -0
  356. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/data/Registry.py +0 -0
  357. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/data/__init__.py +0 -0
  358. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/data/scooter_results.json +0 -0
  359. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/decorators.py +0 -0
  360. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/gcp_bucket/__init__.py +0 -0
  361. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/gcp_bucket/cloud_storage.py +0 -0
  362. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/interface.py +0 -0
  363. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/is_notebook.py +0 -0
  364. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/is_valid_variable_name.py +0 -0
  365. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/naming_utilities.py +0 -0
  366. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/remove_edsl_version.py +0 -0
  367. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/repair_functions.py +0 -0
  368. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/restricted_python.py +0 -0
  369. {edsl-0.1.41 → edsl-0.1.42}/edsl/utilities/utilities.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: edsl
3
- Version: 0.1.41
3
+ Version: 0.1.42
4
4
  Summary: Create and analyze LLM-based surveys
5
5
  Home-page: https://www.expectedparrot.com/
6
6
  License: MIT
@@ -107,5 +107,5 @@ See instructions on [storing API keys](https://docs.expectedparrot.com/en/latest
107
107
 
108
108
  ## 💡 Contributions, feature requests & bugs
109
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).
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
111
 
@@ -51,4 +51,4 @@ See instructions on [storing API keys](https://docs.expectedparrot.com/en/latest
51
51
 
52
52
  ## 💡 Contributions, feature requests & bugs
53
53
  Interested in contributing? Want us to add a new feature? Found a bug for us to squash?
54
- Please send us an email at [info@expectedparrot.com](mailto:info@expectedparrot.com) or message us at our [Discord channel](https://discord.com/invite/mxAYkjfy9m).
54
+ Please send us an email at [info@expectedparrot.com](mailto:info@expectedparrot.com) or message us at our [Discord channel](https://discord.com/invite/mxAYkjfy9m)..
@@ -0,0 +1 @@
1
+ __version__ = "0.1.42"
@@ -1,6 +1,6 @@
1
1
  """Module for creating Invigilators, which are objects to administer a question to an Agent."""
2
2
 
3
- from typing import Dict, Any, Optional, TYPE_CHECKING
3
+ from typing import Dict, Any, Optional, TYPE_CHECKING, Literal
4
4
 
5
5
  from edsl.utilities.decorators import sync_wrapper
6
6
  from edsl.exceptions.questions import QuestionAnswerValidationError
@@ -12,6 +12,7 @@ if TYPE_CHECKING:
12
12
  from edsl.scenarios.Scenario import Scenario
13
13
  from edsl.surveys.Survey import Survey
14
14
 
15
+ PromptType = Literal["user_prompt", "system_prompt", "encoded_image", "files_list"]
15
16
 
16
17
  NA = "Not Applicable"
17
18
 
@@ -19,7 +20,7 @@ NA = "Not Applicable"
19
20
  class InvigilatorAI(InvigilatorBase):
20
21
  """An invigilator that uses an AI model to answer questions."""
21
22
 
22
- def get_prompts(self) -> Dict[str, "Prompt"]:
23
+ def get_prompts(self) -> Dict[PromptType, "Prompt"]:
23
24
  """Return the prompts used."""
24
25
  return self.prompt_constructor.get_prompts()
25
26
 
@@ -135,6 +135,7 @@ class InvigilatorBase(ABC):
135
135
  d["additional_prompt_data"] = data["additional_prompt_data"]
136
136
 
137
137
  d = cls(**d)
138
+ return d
138
139
 
139
140
  def __repr__(self) -> str:
140
141
  """Return a string representation of the Invigilator.
@@ -143,7 +144,7 @@ class InvigilatorBase(ABC):
143
144
  'InvigilatorExample(...)'
144
145
 
145
146
  """
146
- return f"{self.__class__.__name__}(agent={repr(self.agent)}, question={repr(self.question)}, scneario={repr(self.scenario)}, model={repr(self.model)}, memory_plan={repr(self.memory_plan)}, current_answers={repr(self.current_answers)}, iteration{repr(self.iteration)}, additional_prompt_data={repr(self.additional_prompt_data)}, cache={repr(self.cache)})"
147
+ return f"{self.__class__.__name__}(agent={repr(self.agent)}, question={repr(self.question)}, scenario={repr(self.scenario)}, model={repr(self.model)}, memory_plan={repr(self.memory_plan)}, current_answers={repr(self.current_answers)}, iteration={repr(self.iteration)}, additional_prompt_data={repr(self.additional_prompt_data)}, cache={repr(self.cache)})"
147
148
 
148
149
  def get_failed_task_result(self, failure_reason: str) -> EDSLResultObjectInput:
149
150
  """Return an AgentResponseDict used in case the question-asking fails.
@@ -1,4 +1,4 @@
1
- from jinja2 import Environment, meta
1
+ from jinja2 import Environment, meta, TemplateSyntaxError
2
2
  from typing import Any, Set, TYPE_CHECKING
3
3
 
4
4
  if TYPE_CHECKING:
@@ -29,7 +29,12 @@ class QuestionTemplateReplacementsBuilder:
29
29
  Set[str]: A set of variable names found in the template
30
30
  """
31
31
  env = Environment()
32
- ast = env.parse(template_str)
32
+ try:
33
+ ast = env.parse(template_str)
34
+ except TemplateSyntaxError:
35
+ print(f"Error parsing template: {template_str}")
36
+ raise
37
+
33
38
  return meta.find_undeclared_variables(ast)
34
39
 
35
40
  @staticmethod
@@ -894,6 +894,38 @@ class Coop(CoopFunctionsMixin):
894
894
  data = response.json()
895
895
  return ServiceToModelsMapping(data)
896
896
 
897
+ def fetch_working_models(self) -> list[dict]:
898
+ """
899
+ Fetch a list of working models from Coop.
900
+
901
+ Example output:
902
+
903
+ [
904
+ {
905
+ "service": "openai",
906
+ "model": "gpt-4o",
907
+ "works_with_text": True,
908
+ "works_with_images": True,
909
+ "usd_per_1M_input_tokens": 2.5,
910
+ "usd_per_1M_output_tokens": 10.0,
911
+ }
912
+ ]
913
+ """
914
+ response = self._send_server_request(uri="api/v0/working-models", method="GET")
915
+ self._resolve_server_response(response)
916
+ data = response.json()
917
+ return [
918
+ {
919
+ "service": record.get("service"),
920
+ "model": record.get("model"),
921
+ "works_with_text": record.get("works_with_text"),
922
+ "works_with_images": record.get("works_with_images"),
923
+ "usd_per_1M_input_tokens": record.get("input_price_per_1M_tokens"),
924
+ "usd_per_1M_output_tokens": record.get("output_price_per_1M_tokens"),
925
+ }
926
+ for record in data
927
+ ]
928
+
897
929
  def fetch_rate_limit_config_vars(self) -> dict:
898
930
  """
899
931
  Fetch a dict of rate limit config vars from Coop.
@@ -66,6 +66,7 @@ class InferenceServiceType(EnumWithChecks):
66
66
  MISTRAL = "mistral"
67
67
  TOGETHER = "together"
68
68
  PERPLEXITY = "perplexity"
69
+ DEEPSEEK = "deepseek"
69
70
 
70
71
 
71
72
  # unavoidable violation of the DRY principle but it is necessary
@@ -84,6 +85,7 @@ InferenceServiceLiteral = Literal[
84
85
  "mistral",
85
86
  "together",
86
87
  "perplexity",
88
+ "deepseek",
87
89
  ]
88
90
 
89
91
  available_models_urls = {
@@ -107,6 +109,7 @@ service_to_api_keyname = {
107
109
  InferenceServiceType.MISTRAL.value: "MISTRAL_API_KEY",
108
110
  InferenceServiceType.TOGETHER.value: "TOGETHER_API_KEY",
109
111
  InferenceServiceType.PERPLEXITY.value: "PERPLEXITY_API_KEY",
112
+ InferenceServiceType.DEEPSEEK.value: "DEEPSEEK_API_KEY",
110
113
  }
111
114
 
112
115
 
@@ -0,0 +1,25 @@
1
+ from textwrap import dedent
2
+
3
+
4
+ class JobsErrors(Exception):
5
+ pass
6
+
7
+
8
+ class JobsRunError(JobsErrors):
9
+ pass
10
+
11
+
12
+ class MissingRemoteInferenceError(JobsErrors):
13
+ pass
14
+
15
+
16
+ class InterviewError(Exception):
17
+ pass
18
+
19
+
20
+ class InterviewErrorPriorTaskCanceled(InterviewError):
21
+ pass
22
+
23
+
24
+ class InterviewTimeoutError(InterviewError):
25
+ pass
@@ -34,11 +34,15 @@ class LanguageModelNotFound(LanguageModelExceptions):
34
34
  msg = dedent(
35
35
  f"""\
36
36
  Model {model_name} not found.
37
- To create an instance, you can do:
38
- >>> m = Model('gpt-4-1106-preview', temperature=0.5, ...)
37
+ To create an instance of this model, pass the model name to a `Model` object.
38
+ You can optionally pass additional parameters to the model, e.g.:
39
+ >>> m = Model('gpt-4-1106-preview', temperature=0.5)
39
40
 
40
- To get the default model, you can leave out the model name.
41
- To see the available models, you can do:
41
+ To use the default model, simply run your job without specifying a model.
42
+ To check the default model, run the following code:
43
+ >>> Model()
44
+
45
+ To see information about all available models, run the following code:
42
46
  >>> Model.available()
43
47
 
44
48
  See https://docs.expectedparrot.com/en/latest/language_models.html#available-models for more details.
@@ -16,7 +16,8 @@ class QuestionErrors(Exception):
16
16
  class QuestionAnswerValidationError(QuestionErrors):
17
17
  documentation = "https://docs.expectedparrot.com/en/latest/exceptions.html"
18
18
 
19
- explanation = """This when the answer coming from the Language Model does not conform to the expectation for that question type.
19
+ explanation = """
20
+ This can occur when the answer coming from the Language Model does not conform to the expectations for the question type.
20
21
  For example, if the question is a multiple choice question, the answer should be drawn from the list of options provided.
21
22
  """
22
23
 
@@ -52,28 +53,24 @@ class QuestionAnswerValidationError(QuestionErrors):
52
53
 
53
54
  def to_html_dict(self):
54
55
  return {
55
- "error_type": ("Name of the exception", "p", "/p", self.__class__.__name__),
56
- "explaination": ("Explanation", "p", "/p", self.explanation),
57
- "edsl answer": (
58
- "What model returned",
56
+ "Exception type": ("p", "/p", self.__class__.__name__),
57
+ "Explanation": ("p", "/p", self.explanation),
58
+ "EDSL response": (
59
59
  "pre",
60
60
  "/pre",
61
61
  json.dumps(self.data, indent=2),
62
62
  ),
63
- "validating_model": (
64
- "Pydantic model for answers",
63
+ "Validating model": (
65
64
  "pre",
66
65
  "/pre",
67
66
  json.dumps(self.model.model_json_schema(), indent=2),
68
67
  ),
69
- "error_message": (
70
- "Error message Pydantic returned",
68
+ "Error message": (
71
69
  "p",
72
70
  "/p",
73
71
  self.message,
74
72
  ),
75
- "documentation_url": (
76
- "URL to EDSL docs",
73
+ "Documentation": (
77
74
  f"a href='{self.documentation}'",
78
75
  "/a",
79
76
  self.documentation,
@@ -0,0 +1,18 @@
1
+ import aiohttp
2
+ import json
3
+ import requests
4
+ from typing import Any, List
5
+
6
+ # from edsl.inference_services.InferenceServiceABC import InferenceServiceABC
7
+ from edsl.language_models import LanguageModel
8
+
9
+ from edsl.inference_services.OpenAIService import OpenAIService
10
+
11
+
12
+ class DeepSeekService(OpenAIService):
13
+ """DeepInfra service class."""
14
+
15
+ _inference_service_ = "deepseek"
16
+ _env_key_name_ = "DEEPSEEK_API_KEY"
17
+ _base_url_ = "https://api.deepseek.com"
18
+ _models_list_cache: List[str] = []
@@ -13,6 +13,7 @@ from edsl.inference_services.OllamaService import OllamaService
13
13
  from edsl.inference_services.TestService import TestService
14
14
  from edsl.inference_services.TogetherAIService import TogetherAIService
15
15
  from edsl.inference_services.PerplexityService import PerplexityService
16
+ from edsl.inference_services.DeepSeekService import DeepSeekService
16
17
 
17
18
  try:
18
19
  from edsl.inference_services.MistralAIService import MistralAIService
@@ -33,6 +34,7 @@ services = [
33
34
  TestService,
34
35
  TogetherAIService,
35
36
  PerplexityService,
37
+ DeepSeekService,
36
38
  ]
37
39
 
38
40
  if mistral_available:
@@ -521,16 +521,18 @@ class Jobs(Base):
521
521
  results = runner.run(self.run_config.parameters)
522
522
  return results
523
523
 
524
- def _setup_and_check(self) -> Tuple[RunConfig, Optional[Results]]:
525
- self._prepare_to_run()
526
- self._check_if_remote_keys_ok()
524
+ # def _setup_and_check(self) -> Tuple[RunConfig, Optional[Results]]:
525
+ # self._prepare_to_run()
526
+ # self._check_if_remote_keys_ok()
527
527
 
528
- # first try to run the job remotely
529
- if results := self._remote_results():
530
- return results
528
+ # # first try to run the job remotely
529
+ # results = self._remote_results()
530
+ # #breakpoint()
531
+ # if results is not None:
532
+ # return results
531
533
 
532
- self._check_if_local_keys_ok()
533
- return None
534
+ # self._check_if_local_keys_ok()
535
+ # return None
534
536
 
535
537
  @property
536
538
  def num_interviews(self):
@@ -539,7 +541,7 @@ class Jobs(Base):
539
541
  else:
540
542
  return len(self) * self.run_config.parameters.n
541
543
 
542
- def _run(self, config: RunConfig):
544
+ def _run(self, config: RunConfig) -> Union[None, "Results"]:
543
545
  "Shared code for run and run_async"
544
546
  if config.environment.cache is not None:
545
547
  self.run_config.environment.cache = config.environment.cache
@@ -581,7 +583,7 @@ class Jobs(Base):
581
583
  # first try to run the job remotely
582
584
  if results := self._remote_results():
583
585
  return results
584
-
586
+
585
587
  self._check_if_local_keys_ok()
586
588
 
587
589
  if config.environment.bucket_collection is None:
@@ -589,6 +591,8 @@ class Jobs(Base):
589
591
  self.create_bucket_collection()
590
592
  )
591
593
 
594
+ return None
595
+
592
596
  @with_config
593
597
  def run(self, *, config: RunConfig) -> "Results":
594
598
  """
@@ -608,7 +612,10 @@ class Jobs(Base):
608
612
  :param bucket_collection: A BucketCollection object to track API calls
609
613
  :param key_lookup: A KeyLookup object to manage API keys
610
614
  """
611
- self._run(config)
615
+ potentially_completed_results = self._run(config)
616
+
617
+ if potentially_completed_results is not None:
618
+ return potentially_completed_results
612
619
 
613
620
  return asyncio.run(self._execute_with_remote_cache(run_job_async=False))
614
621
 
@@ -12,6 +12,7 @@ if TYPE_CHECKING:
12
12
  # from edsl.surveys.Survey import Survey
13
13
 
14
14
  from edsl.jobs.FetchInvigilator import FetchInvigilator
15
+ from edsl.data.CacheEntry import CacheEntry
15
16
 
16
17
 
17
18
  class JobsPrompts:
@@ -47,7 +48,7 @@ class JobsPrompts:
47
48
  agent_indices = []
48
49
  models = []
49
50
  costs = []
50
-
51
+ cache_keys = []
51
52
  for interview_index, interview in enumerate(interviews):
52
53
  invigilators = [
53
54
  FetchInvigilator(interview)(question)
@@ -76,6 +77,14 @@ class JobsPrompts:
76
77
  )
77
78
  costs.append(prompt_cost["cost_usd"])
78
79
 
80
+ cache_key = CacheEntry.gen_key(
81
+ model=invigilator.model.model,
82
+ parameters=invigilator.model.parameters,
83
+ system_prompt=system_prompt,
84
+ user_prompt=user_prompt,
85
+ iteration=0, # TODO how to handle when there are multiple iterations?
86
+ )
87
+ cache_keys.append(cache_key)
79
88
  d = Dataset(
80
89
  [
81
90
  {"user_prompt": user_prompts},
@@ -86,6 +95,7 @@ class JobsPrompts:
86
95
  {"agent_index": agent_indices},
87
96
  {"model": models},
88
97
  {"estimated_cost": costs},
98
+ {"cache_key": cache_keys},
89
99
  ]
90
100
  )
91
101
  return d
@@ -219,6 +219,7 @@ class JobsRemoteInferenceHandler:
219
219
  job_info.logger.add_info("results_uuid", results_uuid)
220
220
  results = object_fetcher(results_uuid, expected_object_type="results")
221
221
  results_url = remote_job_data.get("results_url")
222
+ job_info.logger.add_info("results_url", results_url)
222
223
  job_info.logger.update(
223
224
  f"Job completed and Results stored on Coop: {results_url}",
224
225
  status=JobsStatus.COMPLETED,
@@ -32,7 +32,7 @@ class JobsInfo:
32
32
  pretty_names = {
33
33
  "job_uuid": "Job UUID",
34
34
  "progress_bar_url": "Progress Bar URL",
35
- "error_report_url": "Error Report URL",
35
+ "error_report_url": "Exceptions Report URL",
36
36
  "results_uuid": "Results UUID",
37
37
  "results_url": "Results URL",
38
38
  }
@@ -153,7 +153,7 @@ class Interview:
153
153
 
154
154
  >>> i = Interview.example()
155
155
  >>> hash(i)
156
- 193593189022259693
156
+ 767745459362662063
157
157
  """
158
158
  d = {
159
159
  "agent": self.agent.to_dict(add_edsl_version=add_edsl_version),
@@ -9,7 +9,8 @@ from edsl.jobs.jobs_status_enums import JobsStatus
9
9
  class HTMLTableJobLogger(JobLogger):
10
10
  def __init__(self, verbose=True, theme="auto", **kwargs):
11
11
  super().__init__(verbose=verbose)
12
- self.display_handle = display(HTML(""), display_id=True)
12
+ self.display_handle = display(HTML(""), display_id=True) if verbose else None
13
+ #self.display_handle = display(HTML(""), display_id=True)
13
14
  self.current_message = None
14
15
  self.log_id = str(uuid.uuid4())
15
16
  self.is_expanded = True
@@ -22,6 +23,9 @@ class HTMLTableJobLogger(JobLogger):
22
23
 
23
24
  def _init_css(self):
24
25
  """Initialize the CSS styles with enhanced theme support"""
26
+ if not self.verbose:
27
+ return None
28
+
25
29
  css = """
26
30
  <style>
27
31
  /* Base theme variables */
@@ -217,6 +221,7 @@ class HTMLTableJobLogger(JobLogger):
217
221
  }});
218
222
  </script>
219
223
  """
224
+
220
225
 
221
226
  display(HTML(css + init_script))
222
227
 
@@ -66,9 +66,7 @@ class ResultsExceptionsHandler:
66
66
 
67
67
  def _generate_error_message(self, indices) -> str:
68
68
  """Generate appropriate error message based on number of exceptions."""
69
- msg = f"Exceptions were raised in {len(indices)} interviews.\n"
70
- if len(indices) > 5:
71
- msg += f"Exceptions were raised in the following interviews: {indices}.\n"
69
+ msg = f"Exceptions were raised.\n"
72
70
  return msg
73
71
 
74
72
  def handle_exceptions(self) -> None:
@@ -84,7 +82,6 @@ class ResultsExceptionsHandler:
84
82
 
85
83
  # Generate HTML report
86
84
  filepath = self.results.task_history.html(
87
- cta="Open report to see details.",
88
85
  open_in_browser=self.open_in_browser,
89
86
  return_link=True,
90
87
  )
@@ -92,7 +89,5 @@ class ResultsExceptionsHandler:
92
89
  # Handle remote logging if enabled
93
90
  if self.remote_logging:
94
91
  filestore = HTMLFileStore(filepath)
95
- coop_details = filestore.push(description="Error report")
92
+ coop_details = filestore.push(description="Exceptions Report")
96
93
  print(coop_details)
97
-
98
- print("Also see: https://docs.expectedparrot.com/en/latest/exceptions.html")
@@ -264,9 +264,27 @@ class TaskHistory(RepresentationMixin):
264
264
  js = env.joinpath("report.js").read_text()
265
265
  return js
266
266
 
267
+ @property
268
+ def exceptions_table(self) -> dict:
269
+ """Return a dictionary of exceptions organized by type, service, model, and question name."""
270
+ exceptions_table = {}
271
+ for interview in self.total_interviews:
272
+ for question_name, exceptions in interview.exceptions.items():
273
+ for exception in exceptions:
274
+ key = (
275
+ exception.exception.__class__.__name__, # Exception type
276
+ interview.model._inference_service_, # Service
277
+ interview.model.model, # Model
278
+ question_name # Question name
279
+ )
280
+ if key not in exceptions_table:
281
+ exceptions_table[key] = 0
282
+ exceptions_table[key] += 1
283
+ return exceptions_table
284
+
267
285
  @property
268
286
  def exceptions_by_type(self) -> dict:
269
- """Return a dictionary of exceptions by type."""
287
+ """Return a dictionary of exceptions tallied by type."""
270
288
  exceptions_by_type = {}
271
289
  for interview in self.total_interviews:
272
290
  for question_name, exceptions in interview.exceptions.items():
@@ -324,6 +342,27 @@ class TaskHistory(RepresentationMixin):
324
342
  }
325
343
  return sorted_exceptions_by_question_name
326
344
 
345
+ # @property
346
+ # def exceptions_by_model(self) -> dict:
347
+ # """Return a dictionary of exceptions tallied by model and question name."""
348
+ # exceptions_by_model = {}
349
+ # for interview in self.total_interviews:
350
+ # model = interview.model.model
351
+ # service = interview.model._inference_service_
352
+ # if (service, model) not in exceptions_by_model:
353
+ # exceptions_by_model[(service, model)] = 0
354
+ # if interview.exceptions != {}:
355
+ # exceptions_by_model[(service, model)] += len(interview.exceptions)
356
+
357
+ # # sort the exceptions by model
358
+ # sorted_exceptions_by_model = {
359
+ # k: v
360
+ # for k, v in sorted(
361
+ # exceptions_by_model.items(), key=lambda item: item[1], reverse=True
362
+ # )
363
+ # }
364
+ # return sorted_exceptions_by_model
365
+
327
366
  @property
328
367
  def exceptions_by_model(self) -> dict:
329
368
  """Return a dictionary of exceptions tallied by model and question name."""
@@ -331,19 +370,12 @@ class TaskHistory(RepresentationMixin):
331
370
  for interview in self.total_interviews:
332
371
  model = interview.model.model
333
372
  service = interview.model._inference_service_
334
- if (service, model) not in exceptions_by_model:
335
- exceptions_by_model[(service, model)] = 0
336
- if interview.exceptions != {}:
337
- exceptions_by_model[(service, model)] += len(interview.exceptions)
338
-
339
- # sort the exceptions by model
340
- sorted_exceptions_by_model = {
341
- k: v
342
- for k, v in sorted(
343
- exceptions_by_model.items(), key=lambda item: item[1], reverse=True
344
- )
345
- }
346
- return sorted_exceptions_by_model
373
+ for question_name, exceptions in interview.exceptions.items():
374
+ key = (service, model, question_name)
375
+ if key not in exceptions_by_model:
376
+ exceptions_by_model[key] = 0
377
+ exceptions_by_model[key] += len(exceptions)
378
+ return exceptions_by_model
347
379
 
348
380
  def generate_html_report(self, css: Optional[str], include_plot=False):
349
381
  if include_plot:
@@ -372,6 +404,7 @@ class TaskHistory(RepresentationMixin):
372
404
  javascript=self.javascript(),
373
405
  num_exceptions=len(self.exceptions),
374
406
  performance_plot_html=performance_plot_html,
407
+ exceptions_table=self.exceptions_table,
375
408
  exceptions_by_type=self.exceptions_by_type,
376
409
  exceptions_by_question_name=self.exceptions_by_question_name,
377
410
  exceptions_by_model=self.exceptions_by_model,
@@ -386,11 +419,10 @@ class TaskHistory(RepresentationMixin):
386
419
  filename: Optional[str] = None,
387
420
  return_link=False,
388
421
  css=None,
389
- cta="Open Report in New Tab",
422
+ cta="\nClick to open the report in a new tab\n",
390
423
  open_in_browser=False,
391
424
  ):
392
425
  """Return an HTML report."""
393
-
394
426
  from IPython.display import display, HTML
395
427
  import tempfile
396
428
  import os
@@ -419,7 +451,7 @@ class TaskHistory(RepresentationMixin):
419
451
  html_link = f'<a href="{html_url}" target="_blank">{cta}</a>'
420
452
  display(HTML(html_link))
421
453
  escaped_output = html.escape(output)
422
- iframe = f""""
454
+ iframe = f"""
423
455
  <iframe srcdoc="{ escaped_output }" style="width: 800px; height: 600px;"></iframe>
424
456
  """
425
457
  display(HTML(iframe))
@@ -244,7 +244,7 @@ class LanguageModel(
244
244
 
245
245
  >>> m = LanguageModel.example()
246
246
  >>> hash(m)
247
- 1811901442659237949
247
+ 325654563661254408
248
248
  """
249
249
  from edsl.utilities.utilities import dict_hash
250
250
 
@@ -495,11 +495,12 @@ class LanguageModel(
495
495
 
496
496
  >>> m = LanguageModel.example()
497
497
  >>> m.to_dict()
498
- {'model': '...', 'parameters': {'temperature': ..., 'max_tokens': ..., 'top_p': ..., 'frequency_penalty': ..., 'presence_penalty': ..., 'logprobs': False, 'top_logprobs': ...}, 'edsl_version': '...', 'edsl_class_name': 'LanguageModel'}
498
+ {'model': '...', 'parameters': {'temperature': ..., 'max_tokens': ..., 'top_p': ..., 'frequency_penalty': ..., 'presence_penalty': ..., 'logprobs': False, 'top_logprobs': ...}, 'inference_service': 'openai', 'edsl_version': '...', 'edsl_class_name': 'LanguageModel'}
499
499
  """
500
500
  d = {
501
501
  "model": self.model,
502
502
  "parameters": self.parameters,
503
+ "inference_service": self._inference_service_,
503
504
  }
504
505
  if add_edsl_version:
505
506
  from edsl import __version__
@@ -511,7 +512,10 @@ class LanguageModel(
511
512
  @classmethod
512
513
  @remove_edsl_version
513
514
  def from_dict(cls, data: dict) -> Type[LanguageModel]:
514
- """Convert dictionary to a LanguageModel child instance."""
515
+ """Convert dictionary to a LanguageModel child instance.
516
+
517
+ NB: This method does not use the stores inference_service but rather just fetches a model class based on the name.
518
+ """
515
519
  from edsl.language_models.model import get_model_class
516
520
 
517
521
  model_class = get_model_class(data["model"])
@@ -558,7 +562,6 @@ class LanguageModel(
558
562
  >>> m = LanguageModel.example(test_model = True, canned_response = "WOWZA!", throw_exception = True)
559
563
  >>> r = q.by(m).run(cache = False, disable_remote_cache = True, disable_remote_inference = True, print_exceptions = True)
560
564
  Exception report saved to ...
561
- Also see: ...
562
565
  """
563
566
  from edsl.language_models.model import Model
564
567
 
@@ -60,7 +60,7 @@ class ModelList(Base, UserList):
60
60
 
61
61
  sl = ScenarioList()
62
62
  for model in self:
63
- d = {"model": model.model}
63
+ d = {"model": model.model, "inference_service": model._inference_service_}
64
64
  d.update(model.parameters)
65
65
  sl.append(Scenario(d))
66
66
  return sl