edsl 0.1.37.dev4__tar.gz → 0.1.37.dev6__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 (300) hide show
  1. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/PKG-INFO +1 -1
  2. edsl-0.1.37.dev6/edsl/__version__.py +1 -0
  3. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/Agent.py +86 -35
  4. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/AgentList.py +5 -0
  5. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/InvigilatorBase.py +2 -23
  6. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/PromptConstructor.py +147 -106
  7. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/descriptors.py +17 -4
  8. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/config.py +1 -1
  9. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/AgentConstructionMixin.py +11 -3
  10. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conversation/Conversation.py +66 -14
  11. edsl-0.1.37.dev6/edsl/conversation/chips.py +95 -0
  12. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/coop/coop.py +134 -3
  13. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/Cache.py +1 -1
  14. edsl-0.1.37.dev6/edsl/exceptions/BaseException.py +21 -0
  15. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/__init__.py +7 -3
  16. edsl-0.1.37.dev6/edsl/exceptions/agents.py +38 -0
  17. edsl-0.1.37.dev6/edsl/exceptions/results.py +29 -0
  18. edsl-0.1.37.dev6/edsl/exceptions/scenarios.py +22 -0
  19. edsl-0.1.37.dev6/edsl/exceptions/surveys.py +37 -0
  20. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/InferenceServicesCollection.py +32 -9
  21. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/Jobs.py +265 -53
  22. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/InterviewExceptionEntry.py +5 -1
  23. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tasks/TaskHistory.py +1 -0
  24. edsl-0.1.37.dev6/edsl/language_models/KeyLookup.py +30 -0
  25. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/LanguageModel.py +47 -59
  26. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/__init__.py +1 -0
  27. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/prompts/Prompt.py +8 -4
  28. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionBase.py +53 -13
  29. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionBasePromptsMixin.py +1 -33
  30. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionFunctional.py +2 -2
  31. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/descriptors.py +23 -28
  32. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/DatasetExportMixin.py +25 -1
  33. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/Result.py +16 -1
  34. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/Results.py +31 -120
  35. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/ResultsDBMixin.py +1 -1
  36. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/Selector.py +18 -1
  37. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/Scenario.py +48 -12
  38. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/ScenarioHtmlMixin.py +7 -2
  39. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/ScenarioList.py +12 -1
  40. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/Rule.py +10 -4
  41. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/Survey.py +100 -77
  42. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/utilities.py +18 -0
  43. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/pyproject.toml +1 -1
  44. edsl-0.1.37.dev4/edsl/__version__.py +0 -1
  45. edsl-0.1.37.dev4/edsl/exceptions/agents.py +0 -40
  46. edsl-0.1.37.dev4/edsl/exceptions/results.py +0 -26
  47. edsl-0.1.37.dev4/edsl/exceptions/surveys.py +0 -34
  48. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/LICENSE +0 -0
  49. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/README.md +0 -0
  50. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/Base.py +0 -0
  51. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/BaseDiff.py +0 -0
  52. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/TemplateLoader.py +0 -0
  53. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/__init__.py +0 -0
  54. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/Invigilator.py +0 -0
  55. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/__init__.py +0 -0
  56. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/agents/prompt_helpers.py +0 -0
  57. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/AutoStudy.py +0 -0
  58. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StageBase.py +0 -0
  59. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StageGenerateSurvey.py +0 -0
  60. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StageLabelQuestions.py +0 -0
  61. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StagePersona.py +0 -0
  62. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StagePersonaDimensionValueRanges.py +0 -0
  63. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StagePersonaDimensionValues.py +0 -0
  64. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StagePersonaDimensions.py +0 -0
  65. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/StageQuestions.py +0 -0
  66. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/SurveyCreatorPipeline.py +0 -0
  67. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/auto/utilities.py +0 -0
  68. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/base/Base.py +0 -0
  69. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/Conjure.py +0 -0
  70. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/InputData.py +0 -0
  71. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/InputDataCSV.py +0 -0
  72. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/InputDataMixinQuestionStats.py +0 -0
  73. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/InputDataPyRead.py +0 -0
  74. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/InputDataSPSS.py +0 -0
  75. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/InputDataStata.py +0 -0
  76. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/QuestionOptionMixin.py +0 -0
  77. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/QuestionTypeMixin.py +0 -0
  78. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/RawQuestion.py +0 -0
  79. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/SurveyResponses.py +0 -0
  80. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/__init__.py +0 -0
  81. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/examples/placeholder.txt +0 -0
  82. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/naming_utilities.py +0 -0
  83. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conjure/utilities.py +0 -0
  84. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conversation/car_buying.py +0 -0
  85. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conversation/mug_negotiation.py +0 -0
  86. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/conversation/next_speaker_utilities.py +0 -0
  87. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/coop/PriceFetcher.py +0 -0
  88. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/coop/__init__.py +0 -0
  89. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/coop/utils.py +0 -0
  90. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/CacheEntry.py +0 -0
  91. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/CacheHandler.py +0 -0
  92. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/RemoteCacheSync.py +0 -0
  93. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/SQLiteDict.py +0 -0
  94. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/__init__.py +0 -0
  95. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data/orm.py +0 -0
  96. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/data_transfer_models.py +0 -0
  97. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/enums.py +0 -0
  98. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/configuration.py +0 -0
  99. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/coop.py +0 -0
  100. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/data.py +0 -0
  101. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/general.py +0 -0
  102. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/jobs.py +0 -0
  103. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/language_models.py +0 -0
  104. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/prompts.py +0 -0
  105. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/exceptions/questions.py +0 -0
  106. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/AnthropicService.py +0 -0
  107. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/AwsBedrock.py +0 -0
  108. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/AzureAI.py +0 -0
  109. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/DeepInfraService.py +0 -0
  110. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/GoogleService.py +0 -0
  111. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/GroqService.py +0 -0
  112. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/InferenceServiceABC.py +0 -0
  113. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/MistralAIService.py +0 -0
  114. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/OllamaService.py +0 -0
  115. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/OpenAIService.py +0 -0
  116. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/TestService.py +0 -0
  117. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/TogetherAIService.py +0 -0
  118. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/__init__.py +0 -0
  119. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/models_available_cache.py +0 -0
  120. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/rate_limits_cache.py +0 -0
  121. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/registry.py +0 -0
  122. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/inference_services/write_available.py +0 -0
  123. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/Answers.py +0 -0
  124. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/__init__.py +0 -0
  125. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/buckets/BucketCollection.py +0 -0
  126. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/buckets/ModelBuckets.py +0 -0
  127. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/buckets/TokenBucket.py +0 -0
  128. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/Interview.py +0 -0
  129. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/InterviewExceptionCollection.py +0 -0
  130. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/InterviewStatistic.py +0 -0
  131. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/InterviewStatisticsCollection.py +0 -0
  132. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/InterviewStatusDictionary.py +0 -0
  133. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/InterviewStatusLog.py +0 -0
  134. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/ReportErrors.py +0 -0
  135. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/interviews/interview_status_enum.py +0 -0
  136. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/runners/JobsRunnerAsyncio.py +0 -0
  137. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/runners/JobsRunnerStatus.py +0 -0
  138. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/runners/JobsRunnerStatusData.py +0 -0
  139. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tasks/QuestionTaskCreator.py +0 -0
  140. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tasks/TaskCreators.py +0 -0
  141. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tasks/TaskStatusLog.py +0 -0
  142. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tasks/task_status_enum.py +0 -0
  143. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tokens/InterviewTokenUsage.py +0 -0
  144. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/jobs/tokens/TokenUsage.py +0 -0
  145. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/ModelList.py +0 -0
  146. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/RegisterLanguageModelsMeta.py +0 -0
  147. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/fake_openai_call.py +0 -0
  148. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/fake_openai_service.py +0 -0
  149. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/registry.py +0 -0
  150. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/repair.py +0 -0
  151. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/unused/ReplicateBase.py +0 -0
  152. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/language_models/utilities.py +0 -0
  153. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/notebooks/Notebook.py +0 -0
  154. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/notebooks/__init__.py +0 -0
  155. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/prompts/__init__.py +0 -0
  156. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/AnswerValidatorMixin.py +0 -0
  157. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionBaseGenMixin.py +0 -0
  158. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionBudget.py +0 -0
  159. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionCheckBox.py +0 -0
  160. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionExtract.py +0 -0
  161. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionFreeText.py +0 -0
  162. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionList.py +0 -0
  163. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionMultipleChoice.py +0 -0
  164. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionNumerical.py +0 -0
  165. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/QuestionRank.py +0 -0
  166. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/Quick.py +0 -0
  167. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/RegisterQuestionsMeta.py +0 -0
  168. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/ResponseValidatorABC.py +0 -0
  169. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/SimpleAskMixin.py +0 -0
  170. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/__init__.py +0 -0
  171. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/compose_questions.py +0 -0
  172. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/decorators.py +0 -0
  173. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/derived/QuestionLikertFive.py +0 -0
  174. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/derived/QuestionLinearScale.py +0 -0
  175. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/derived/QuestionTopK.py +0 -0
  176. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/derived/QuestionYesNo.py +0 -0
  177. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/derived/__init__.py +0 -0
  178. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_budget.jinja +0 -0
  179. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_checkbox.jinja +0 -0
  180. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_extract.jinja +0 -0
  181. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_free_text.jinja +0 -0
  182. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_linear_scale.jinja +0 -0
  183. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_list.jinja +0 -0
  184. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_multiple_choice.jinja +0 -0
  185. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/prompt_templates/question_numerical.jinja +0 -0
  186. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/question_registry.py +0 -0
  187. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/settings.py +0 -0
  188. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/__init__.py +0 -0
  189. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/__pycache__/__init__.cpython-312.pyc +0 -0
  190. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/budget/__init__.py +0 -0
  191. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/budget/__pycache__/__init__.cpython-312.pyc +0 -0
  192. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/budget/answering_instructions.jinja +0 -0
  193. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/budget/question_presentation.jinja +0 -0
  194. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/checkbox/__init__.py +0 -0
  195. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/checkbox/__pycache__/__init__.cpython-312.pyc +0 -0
  196. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/checkbox/answering_instructions.jinja +0 -0
  197. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/checkbox/question_presentation.jinja +0 -0
  198. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/extract/__init__.py +0 -0
  199. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/extract/__pycache__/__init__.cpython-312.pyc +0 -0
  200. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/extract/answering_instructions.jinja +0 -0
  201. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/extract/question_presentation.jinja +0 -0
  202. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/free_text/__init__.py +0 -0
  203. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/free_text/__pycache__/__init__.cpython-312.pyc +0 -0
  204. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/free_text/answering_instructions.jinja +0 -0
  205. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/free_text/question_presentation.jinja +0 -0
  206. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/likert_five/__init__.py +0 -0
  207. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/likert_five/__pycache__/__init__.cpython-312.pyc +0 -0
  208. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/likert_five/answering_instructions.jinja +0 -0
  209. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/likert_five/question_presentation.jinja +0 -0
  210. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/linear_scale/__init__.py +0 -0
  211. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/linear_scale/__pycache__/__init__.cpython-312.pyc +0 -0
  212. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/linear_scale/answering_instructions.jinja +0 -0
  213. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/linear_scale/question_presentation.jinja +0 -0
  214. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/list/__init__.py +0 -0
  215. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/list/__pycache__/__init__.cpython-312.pyc +0 -0
  216. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/list/answering_instructions.jinja +0 -0
  217. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/list/question_presentation.jinja +0 -0
  218. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/multiple_choice/__init__.py +0 -0
  219. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/multiple_choice/__pycache__/__init__.cpython-312.pyc +0 -0
  220. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/multiple_choice/answering_instructions.jinja +0 -0
  221. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/multiple_choice/html.jinja +0 -0
  222. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/multiple_choice/question_presentation.jinja +0 -0
  223. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/numerical/__init__.py +0 -0
  224. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/numerical/__pycache__/__init__.cpython-312.pyc +0 -0
  225. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/numerical/answering_instructions.jinja +0 -0
  226. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/numerical/question_presentation.jinja +0 -0
  227. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/rank/__init__.py +0 -0
  228. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/rank/__pycache__/__init__.cpython-312.pyc +0 -0
  229. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/rank/answering_instructions.jinja +0 -0
  230. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/rank/question_presentation.jinja +0 -0
  231. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/top_k/__init__.py +0 -0
  232. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/top_k/__pycache__/__init__.cpython-312.pyc +0 -0
  233. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/top_k/answering_instructions.jinja +0 -0
  234. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/top_k/question_presentation.jinja +0 -0
  235. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/yes_no/__init__.py +0 -0
  236. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/yes_no/__pycache__/__init__.cpython-312.pyc +0 -0
  237. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/yes_no/answering_instructions.jinja +0 -0
  238. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/questions/templates/yes_no/question_presentation.jinja +0 -0
  239. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/Dataset.py +0 -0
  240. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/DatasetTree.py +0 -0
  241. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/ResultsExportMixin.py +0 -0
  242. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/ResultsFetchMixin.py +0 -0
  243. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/ResultsGGMixin.py +0 -0
  244. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/ResultsToolsMixin.py +0 -0
  245. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/__init__.py +0 -0
  246. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/results/tree_explore.py +0 -0
  247. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/FileStore.py +0 -0
  248. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/ScenarioListExportMixin.py +0 -0
  249. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/ScenarioListPdfMixin.py +0 -0
  250. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/scenarios/__init__.py +0 -0
  251. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/shared.py +0 -0
  252. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/study/ObjectEntry.py +0 -0
  253. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/study/ProofOfWork.py +0 -0
  254. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/study/SnapShot.py +0 -0
  255. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/study/Study.py +0 -0
  256. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/study/__init__.py +0 -0
  257. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/DAG.py +0 -0
  258. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/Memory.py +0 -0
  259. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/MemoryPlan.py +0 -0
  260. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/RuleCollection.py +0 -0
  261. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/SurveyCSS.py +0 -0
  262. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/SurveyExportMixin.py +0 -0
  263. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/SurveyFlowVisualizationMixin.py +0 -0
  264. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/SurveyQualtricsImport.py +0 -0
  265. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/__init__.py +0 -0
  266. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/base.py +0 -0
  267. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/descriptors.py +0 -0
  268. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/instructions/ChangeInstruction.py +0 -0
  269. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/instructions/Instruction.py +0 -0
  270. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/instructions/InstructionCollection.py +0 -0
  271. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/surveys/instructions/__init__.py +0 -0
  272. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/base.html +0 -0
  273. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/exceptions_by_model.html +0 -0
  274. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/exceptions_by_question_name.html +0 -0
  275. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/exceptions_by_type.html +0 -0
  276. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/interview_details.html +0 -0
  277. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/interviews.html +0 -0
  278. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/overview.html +0 -0
  279. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/performance_plot.html +0 -0
  280. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/report.css +0 -0
  281. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/report.html +0 -0
  282. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/templates/error_reporting/report.js +0 -0
  283. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/tools/__init__.py +0 -0
  284. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/tools/clusters.py +0 -0
  285. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/tools/embeddings.py +0 -0
  286. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/tools/embeddings_plotting.py +0 -0
  287. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/tools/plotting.py +0 -0
  288. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/tools/summarize.py +0 -0
  289. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/SystemInfo.py +0 -0
  290. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/__init__.py +0 -0
  291. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/ast_utilities.py +0 -0
  292. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/data/Registry.py +0 -0
  293. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/data/__init__.py +0 -0
  294. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/data/scooter_results.json +0 -0
  295. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/decorators.py +0 -0
  296. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/gcp_bucket/__init__.py +0 -0
  297. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/gcp_bucket/cloud_storage.py +0 -0
  298. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/interface.py +0 -0
  299. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/repair_functions.py +0 -0
  300. {edsl-0.1.37.dev4 → edsl-0.1.37.dev6}/edsl/utilities/restricted_python.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: edsl
3
- Version: 0.1.37.dev4
3
+ Version: 0.1.37.dev6
4
4
  Summary: Create and analyze LLM-based surveys
5
5
  Home-page: https://www.expectedparrot.com/
6
6
  License: MIT
@@ -0,0 +1 @@
1
+ __version__ = "0.1.37.dev6"
@@ -4,14 +4,23 @@ from __future__ import annotations
4
4
  import copy
5
5
  import inspect
6
6
  import types
7
- from typing import Callable, Optional, Union, Any
7
+ from typing import Callable, Optional, Union, Any, TYPE_CHECKING
8
+
9
+ if TYPE_CHECKING:
10
+ from edsl import Cache, Survey, Scenario
11
+ from edsl.language_models import LanguageModel
12
+ from edsl.surveys.MemoryPlan import MemoryPlan
13
+ from edsl.questions import QuestionBase
14
+ from edsl.agents.Invigilator import InvigilatorBase
15
+
8
16
  from uuid import uuid4
9
- from edsl.Base import Base
10
17
 
18
+ from edsl.Base import Base
11
19
  from edsl.prompts import Prompt
12
20
  from edsl.exceptions import QuestionScenarioRenderError
13
21
 
14
22
  from edsl.exceptions.agents import (
23
+ AgentErrors,
15
24
  AgentCombinationError,
16
25
  AgentDirectAnswerFunctionError,
17
26
  AgentDynamicTraitsFunctionError,
@@ -33,7 +42,9 @@ from edsl.utilities.restricted_python import create_restricted_function
33
42
 
34
43
 
35
44
  class Agent(Base):
36
- """An Agent that can answer questions."""
45
+ """An class representing an agent that can answer questions."""
46
+
47
+ __doc__ = "https://docs.expectedparrot.com/en/latest/agents.html"
37
48
 
38
49
  default_instruction = """You are answering questions as if you were a human. Do not break character."""
39
50
 
@@ -148,9 +159,10 @@ class Agent(Base):
148
159
  self.current_question = None
149
160
 
150
161
  if traits_presentation_template is not None:
162
+ self._traits_presentation_template = traits_presentation_template
151
163
  self.traits_presentation_template = traits_presentation_template
152
164
  else:
153
- self.traits_presentation_template = """Your traits: {{ traits }}"""
165
+ self.traits_presentation_template = "Your traits: {{traits}}"
154
166
 
155
167
  @property
156
168
  def agent_persona(self) -> Prompt:
@@ -181,13 +193,23 @@ class Agent(Base):
181
193
  """Check whether dynamic trait function is valid.
182
194
 
183
195
  This checks whether the dynamic traits function is valid.
196
+
197
+ >>> def f(question): return {"age": 10, "hair": "brown", "height": 5.5}
198
+ >>> a = Agent(dynamic_traits_function = f)
199
+ >>> a._check_dynamic_traits_function()
200
+
201
+ >>> def g(question, poo): return {"age": 10, "hair": "brown", "height": 5.5}
202
+ >>> a = Agent(dynamic_traits_function = g)
203
+ Traceback (most recent call last):
204
+ ...
205
+ edsl.exceptions.agents.AgentDynamicTraitsFunctionError: ...
184
206
  """
185
207
  if self.has_dynamic_traits_function:
186
208
  sig = inspect.signature(self.dynamic_traits_function)
187
209
  if "question" in sig.parameters:
188
210
  if len(sig.parameters) > 1:
189
211
  raise AgentDynamicTraitsFunctionError(
190
- f"The dynamic traits function {self.dynamic_traits_function} has too many parameters. It should only have one parameter: 'question'."
212
+ message=f"The dynamic traits function {self.dynamic_traits_function} has too many parameters. It should only have one parameter: 'question'."
191
213
  )
192
214
  else:
193
215
  if len(sig.parameters) > 0:
@@ -221,7 +243,38 @@ class Agent(Base):
221
243
  else:
222
244
  return self._traits
223
245
 
224
- def rename(self, old_name: str, new_name: str) -> Agent:
246
+ def rename(
247
+ self, old_name_or_dict: Union[str, dict], new_name: Optional[str] = None
248
+ ) -> Agent:
249
+ """Rename a trait.
250
+
251
+ Example usage:
252
+
253
+ >>> a = Agent(traits = {"age": 10, "hair": "brown", "height": 5.5})
254
+ >>> a.rename("age", "years") == Agent(traits = {'years': 10, 'hair': 'brown', 'height': 5.5})
255
+ True
256
+
257
+ >>> a.rename({'years': 'smage'})
258
+ Agent(traits = {'hair': 'brown', 'height': 5.5, 'smage': 10})
259
+
260
+ """
261
+ if isinstance(old_name_or_dict, dict) and new_name is None:
262
+ for old_name, new_name in old_name_or_dict.items():
263
+ self = self._rename(old_name, new_name)
264
+ return self
265
+
266
+ if isinstance(old_name_or_dict, dict) and new_name:
267
+ raise AgentErrors(
268
+ f"You passed a dict: {old_name_or_dict} and a new name: {new_name}. You should pass only a dict."
269
+ )
270
+
271
+ if isinstance(old_name_or_dict, str):
272
+ self._rename(old_name_or_dict, new_name)
273
+ return self
274
+
275
+ raise AgentErrors("Something is not right with Agent renaming")
276
+
277
+ def _rename(self, old_name: str, new_name: str) -> Agent:
225
278
  """Rename a trait.
226
279
 
227
280
  Example usage:
@@ -267,8 +320,11 @@ class Agent(Base):
267
320
  translate_response: bool = False,
268
321
  ) -> None:
269
322
  """Add a method to the agent that can answer a particular question type.
323
+ https://docs.expectedparrot.com/en/latest/agents.html#agent-direct-answering-methods
270
324
 
271
325
  :param method: A method that can answer a question directly.
326
+ :param validate_response: Whether to validate the response.
327
+ :param translate_response: Whether to translate the response.
272
328
 
273
329
  Example usage:
274
330
 
@@ -304,10 +360,10 @@ class Agent(Base):
304
360
  question: "QuestionBase",
305
361
  cache: "Cache",
306
362
  survey: Optional["Survey"] = None,
307
- scenario: Optional[Scenario] = None,
308
- model: Optional[LanguageModel] = None,
363
+ scenario: Optional["Scenario"] = None,
364
+ model: Optional["LanguageModel"] = None,
309
365
  debug: bool = False,
310
- memory_plan: Optional[MemoryPlan] = None,
366
+ memory_plan: Optional["MemoryPlan"] = None,
311
367
  current_answers: Optional[dict] = None,
312
368
  iteration: int = 1,
313
369
  sidecar_model=None,
@@ -354,13 +410,13 @@ class Agent(Base):
354
410
  async def async_answer_question(
355
411
  self,
356
412
  *,
357
- question: "QuestionBase",
358
- cache: "Cache",
359
- scenario: Optional["Scenario"] = None,
360
- survey: Optional["Survey"] = None,
361
- model: Optional["LanguageModel"] = None,
413
+ question: QuestionBase,
414
+ cache: Cache,
415
+ scenario: Optional[Scenario] = None,
416
+ survey: Optional[Survey] = None,
417
+ model: Optional[LanguageModel] = None,
362
418
  debug: bool = False,
363
- memory_plan: Optional["MemoryPlan"] = None,
419
+ memory_plan: Optional[MemoryPlan] = None,
364
420
  current_answers: Optional[dict] = None,
365
421
  iteration: int = 0,
366
422
  ) -> AgentResponseDict:
@@ -404,13 +460,13 @@ class Agent(Base):
404
460
 
405
461
  def _create_invigilator(
406
462
  self,
407
- question: "QuestionBase",
408
- cache: Optional["Cache"] = None,
409
- scenario: Optional["Scenario"] = None,
410
- model: Optional["LanguageModel"] = None,
411
- survey: Optional["Survey"] = None,
463
+ question: QuestionBase,
464
+ cache: Optional[Cache] = None,
465
+ scenario: Optional[Scenario] = None,
466
+ model: Optional[LanguageModel] = None,
467
+ survey: Optional[Survey] = None,
412
468
  debug: bool = False,
413
- memory_plan: Optional["MemoryPlan"] = None,
469
+ memory_plan: Optional[MemoryPlan] = None,
414
470
  current_answers: Optional[dict] = None,
415
471
  iteration: int = 0,
416
472
  sidecar_model=None,
@@ -493,9 +549,6 @@ class Agent(Base):
493
549
 
494
550
  return Agent(traits={trait: self.traits[trait] for trait in traits_to_select})
495
551
 
496
- ################
497
- # Dunder Methods
498
- ################
499
552
  def __add__(self, other_agent: Optional[Agent] = None) -> Agent:
500
553
  """
501
554
  Combine two agents by joining their traits.
@@ -512,6 +565,7 @@ class Agent(Base):
512
565
  Traceback (most recent call last):
513
566
  ...
514
567
  edsl.exceptions.agents.AgentCombinationError: The agents have overlapping traits: {'age'}.
568
+ ...
515
569
  """
516
570
  if other_agent is None:
517
571
  return self
@@ -540,12 +594,12 @@ class Agent(Base):
540
594
 
541
595
  def __getattr__(self, name):
542
596
  # This will be called only if 'name' is not found in the usual places
543
- # breakpoint()
544
597
  if name == "has_dynamic_traits_function":
545
598
  return self.has_dynamic_traits_function
546
599
 
547
600
  if name in self._traits:
548
601
  return self._traits[name]
602
+
549
603
  raise AttributeError(
550
604
  f"'{type(self).__name__}' object has no attribute '{name}'"
551
605
  )
@@ -598,6 +652,7 @@ class Agent(Base):
598
652
  for k, v in self.__dict__.items()
599
653
  if k.startswith("_")
600
654
  }
655
+
601
656
  if hasattr(self, "set_instructions"):
602
657
  if not self.set_instructions:
603
658
  raw_data.pop("instruction")
@@ -622,8 +677,6 @@ class Agent(Base):
622
677
  "answer_question_directly", None
623
678
  ) # in case answer_question_directly will appear with _ in self.__dict__
624
679
  answer_question_directly_func = self.answer_question_directly
625
- # print(answer_question_directly_func)
626
- # print(type(answer_question_directly_func), flush=True)
627
680
 
628
681
  if (
629
682
  answer_question_directly_func
@@ -644,12 +697,12 @@ class Agent(Base):
644
697
  return dict_hash(self._to_dict())
645
698
 
646
699
  def _to_dict(self) -> dict[str, Union[dict, bool]]:
647
- """Serialize to a dictionary."""
700
+ """Serialize to a dictionary without EDSL info"""
648
701
  return self.data
649
702
 
650
703
  @add_edsl_version
651
704
  def to_dict(self) -> dict[str, Union[dict, bool]]:
652
- """Serialize to a dictionary.
705
+ """Serialize to a dictionary with EDSL info.
653
706
 
654
707
  Example usage:
655
708
 
@@ -672,10 +725,6 @@ class Agent(Base):
672
725
  """
673
726
  return cls(**agent_dict)
674
727
 
675
- ################
676
- # DISPLAY Methods
677
- ################
678
-
679
728
  def _table(self) -> tuple[dict, list]:
680
729
  """Prepare generic table data."""
681
730
  table_data = []
@@ -691,14 +740,16 @@ class Agent(Base):
691
740
  return self
692
741
 
693
742
  if isinstance(trait_name_or_dict, dict) and value:
694
- raise ValueError(f"You passed a dict: {trait_name_or_dict}")
743
+ raise AgentErrors(
744
+ f"You passed a dict: {trait_name_or_dict} and a value: {value}. You should pass only a dict."
745
+ )
695
746
 
696
747
  if isinstance(trait_name_or_dict, str):
697
748
  trait = trait_name_or_dict
698
749
  self.traits[trait] = value
699
750
  return self
700
751
 
701
- raise Exception("Something is not right with adding")
752
+ raise AgentErrors("Something is not right with adding a trait to an Agent")
702
753
 
703
754
  def remove_trait(self, trait: str) -> Agent:
704
755
  """Remove a trait from the agent.
@@ -151,6 +151,11 @@ class AgentList(UserList, Base):
151
151
  with open(file_path, "r") as f:
152
152
  reader = csv.DictReader(f)
153
153
  for row in reader:
154
+ if "name" in row:
155
+ import warnings
156
+
157
+ warnings.warn("Using 'name' field in the CSV for the Agent name")
158
+ name_field = "name"
154
159
  if name_field is not None:
155
160
  agent_name = row.pop(name_field)
156
161
  agent_list.append(Agent(traits=row, name=agent_name))
@@ -236,24 +236,6 @@ class InvigilatorBase(ABC):
236
236
  from edsl import Model
237
237
 
238
238
  model = Model("test", canned_response="SPAM!")
239
- # class TestLanguageModelGood(LanguageModel):
240
- # """A test language model."""
241
-
242
- # _model_ = "test"
243
- # _parameters_ = {"temperature": 0.5}
244
- # _inference_service_ = InferenceServiceType.TEST.value
245
-
246
- # async def async_execute_model_call(
247
- # self, user_prompt: str, system_prompt: str
248
- # ) -> dict[str, Any]:
249
- # await asyncio.sleep(0.1)
250
- # if hasattr(self, "throw_an_exception"):
251
- # raise Exception("Error!")
252
- # return {"message": """{"answer": "SPAM!"}"""}
253
-
254
- # def parse_response(self, raw_response: dict[str, Any]) -> str:
255
- # """Parse the response from the model."""
256
- # return raw_response["message"]
257
239
 
258
240
  if throw_an_exception:
259
241
  model.throw_an_exception = True
@@ -263,11 +245,8 @@ class InvigilatorBase(ABC):
263
245
 
264
246
  if not survey:
265
247
  survey = Survey.example()
266
- # if question:
267
- # need to have the focal question name in the list of names
268
- # survey._questions[0].question_name = question.question_name
269
- # survey.add_question(question)
270
- if question:
248
+
249
+ if question not in survey.questions and question is not None:
271
250
  survey.add_question(question)
272
251
 
273
252
  question = question or survey.questions[0]
@@ -7,6 +7,23 @@ from edsl.prompts.Prompt import Prompt
7
7
  from edsl.agents.prompt_helpers import PromptPlan
8
8
 
9
9
 
10
+ class PlaceholderAnswer:
11
+ """A placeholder answer for when a question is not yet answered."""
12
+
13
+ def __init__(self):
14
+ self.answer = "N/A"
15
+ self.comment = "Will be populated by prior answer"
16
+
17
+ def __getitem__(self, index):
18
+ return ""
19
+
20
+ def __str__(self):
21
+ return "<<PlaceholderAnswer>>"
22
+
23
+ def __repr__(self):
24
+ return "<<PlaceholderAnswer>>"
25
+
26
+
10
27
  def get_jinja2_variables(template_str: str) -> Set[str]:
11
28
  """
12
29
  Extracts all variable names from a Jinja2 template using Jinja2's built-in parsing.
@@ -88,15 +105,20 @@ class PromptConstructor:
88
105
  return self.agent.prompt()
89
106
 
90
107
  def prior_answers_dict(self) -> dict:
108
+ # this is all questions
91
109
  d = self.survey.question_names_to_questions()
92
110
  # This attaches the answer to the question
93
- for question, answer in self.current_answers.items():
94
- if question in d:
95
- d[question].answer = answer
111
+ for question in d:
112
+ if question in self.current_answers:
113
+ d[question].answer = self.current_answers[question]
96
114
  else:
97
- # adds a comment to the question
98
- if (new_question := question.split("_comment")[0]) in d:
99
- d[new_question].comment = answer
115
+ d[question].answer = PlaceholderAnswer()
116
+
117
+ # if (new_question := question.split("_comment")[0]) in d:
118
+ # d[new_question].comment = answer
119
+ # d[question].answer = PlaceholderAnswer()
120
+
121
+ # breakpoint()
100
122
  return d
101
123
 
102
124
  @property
@@ -109,6 +131,123 @@ class PromptConstructor:
109
131
  question_file_keys.append(var)
110
132
  return question_file_keys
111
133
 
134
+ def build_replacement_dict(self, question_data: dict):
135
+ """
136
+ Builds a dictionary of replacement values by combining multiple data sources.
137
+ """
138
+ # File references dictionary
139
+ file_refs = {key: f"<see file {key}>" for key in self.scenario_file_keys}
140
+
141
+ # Scenario items excluding file keys
142
+ scenario_items = {
143
+ k: v for k, v in self.scenario.items() if k not in self.scenario_file_keys
144
+ }
145
+
146
+ # Question settings with defaults
147
+ question_settings = {
148
+ "use_code": getattr(self.question, "_use_code", True),
149
+ "include_comment": getattr(self.question, "_include_comment", False),
150
+ }
151
+
152
+ # Combine all dictionaries using dict.update() for clarity
153
+ replacement_dict = {}
154
+ for d in [
155
+ file_refs,
156
+ question_data,
157
+ scenario_items,
158
+ self.prior_answers_dict(),
159
+ {"agent": self.agent},
160
+ question_settings,
161
+ ]:
162
+ replacement_dict.update(d)
163
+
164
+ return replacement_dict
165
+
166
+ def _get_question_options(self, question_data):
167
+ question_options_entry = question_data.get("question_options", None)
168
+ question_options = question_options_entry
169
+
170
+ placeholder = ["<< Option 1 - Placholder >>", "<< Option 2 - Placholder >>"]
171
+
172
+ if isinstance(question_options_entry, str):
173
+ env = Environment()
174
+ parsed_content = env.parse(question_options_entry)
175
+ question_option_key = list(meta.find_undeclared_variables(parsed_content))[
176
+ 0
177
+ ]
178
+ if isinstance(self.scenario.get(question_option_key), list):
179
+ question_options = self.scenario.get(question_option_key)
180
+
181
+ # might be getting it from the prior answers
182
+ if self.prior_answers_dict().get(question_option_key) is not None:
183
+ prior_question = self.prior_answers_dict().get(question_option_key)
184
+ if hasattr(prior_question, "answer"):
185
+ if isinstance(prior_question.answer, list):
186
+ question_options = prior_question.answer
187
+ else:
188
+ question_options = placeholder
189
+ else:
190
+ question_options = placeholder
191
+
192
+ return question_options
193
+
194
+ def build_question_instructions_prompt(self):
195
+ """Buils the question instructions prompt."""
196
+
197
+ question_prompt = Prompt(self.question.get_instructions(model=self.model.model))
198
+
199
+ # Get the data for the question - this is a dictionary of the question data
200
+ # e.g., {'question_text': 'Do you like school?', 'question_name': 'q0', 'question_options': ['yes', 'no']}
201
+ question_data = self.question.data.copy()
202
+
203
+ if "question_options" in question_data:
204
+ question_options = self._get_question_options(question_data)
205
+ question_data["question_options"] = question_options
206
+
207
+ # check to see if the question_options is actually a string
208
+ # This is used when the user is using the question_options as a variable from a scenario
209
+ # if "question_options" in question_data:
210
+ replacement_dict = self.build_replacement_dict(question_data)
211
+ rendered_instructions = question_prompt.render(replacement_dict)
212
+
213
+ # is there anything left to render?
214
+ undefined_template_variables = (
215
+ rendered_instructions.undefined_template_variables({})
216
+ )
217
+
218
+ # Check if it's the name of a question in the survey
219
+ for question_name in self.survey.question_names:
220
+ if question_name in undefined_template_variables:
221
+ print(
222
+ "Question name found in undefined_template_variables: ",
223
+ question_name,
224
+ )
225
+
226
+ if undefined_template_variables:
227
+ msg = f"Question instructions still has variables: {undefined_template_variables}."
228
+ import warnings
229
+
230
+ warnings.warn(msg)
231
+ # raise QuestionScenarioRenderError(
232
+ # f"Question instructions still has variables: {undefined_template_variables}."
233
+ # )
234
+
235
+ # Check if question has instructions - these are instructions in a Survey that can apply to multiple follow-on questions
236
+ relevant_instructions = self.survey.relevant_instructions(
237
+ self.question.question_name
238
+ )
239
+
240
+ if relevant_instructions != []:
241
+ # preamble_text = Prompt(
242
+ # text="You were given the following instructions: "
243
+ # )
244
+ preamble_text = Prompt(text="")
245
+ for instruction in relevant_instructions:
246
+ preamble_text += instruction.text
247
+ rendered_instructions = preamble_text + rendered_instructions
248
+
249
+ return rendered_instructions
250
+
112
251
  @property
113
252
  def question_instructions_prompt(self) -> Prompt:
114
253
  """
@@ -118,109 +257,11 @@ class PromptConstructor:
118
257
  Prompt(text=\"""...
119
258
  ...
120
259
  """
121
- # The user might have passed a custom prompt, which would be stored in _question_instructions_prompt
122
260
  if not hasattr(self, "_question_instructions_prompt"):
123
- # Gets the instructions for the question - this is how the question should be answered
124
- question_prompt = Prompt(
125
- self.question.get_instructions(model=self.model.model)
261
+ self._question_instructions_prompt = (
262
+ self.build_question_instructions_prompt()
126
263
  )
127
264
 
128
- # Get the data for the question - this is a dictionary of the question data
129
- # e.g., {'question_text': 'Do you like school?', 'question_name': 'q0', 'question_options': ['yes', 'no']}
130
- question_data = self.question.data.copy()
131
-
132
- # check to see if the question_options is actually a string
133
- # This is used when the user is using the question_options as a variable from a scenario
134
- # if "question_options" in question_data:
135
- if isinstance(self.question.data.get("question_options", None), str):
136
- env = Environment()
137
- parsed_content = env.parse(self.question.data["question_options"])
138
- question_option_key = list(
139
- meta.find_undeclared_variables(parsed_content)
140
- )[0]
141
-
142
- # look to see if the question_option_key is in the scenario
143
- if isinstance(
144
- question_options := self.scenario.get(question_option_key), list
145
- ):
146
- question_data["question_options"] = question_options
147
- self.question.question_options = question_options
148
-
149
- # might be getting it from the prior answers
150
- if self.prior_answers_dict().get(question_option_key) is not None:
151
- prior_question = self.prior_answers_dict().get(question_option_key)
152
- if hasattr(prior_question, "answer"):
153
- if isinstance(prior_question.answer, list):
154
- question_data["question_options"] = prior_question.answer
155
- self.question.question_options = prior_question.answer
156
- else:
157
- placeholder_options = [
158
- "N/A",
159
- "Will be populated by prior answer",
160
- "These are placeholder options",
161
- ]
162
- question_data["question_options"] = placeholder_options
163
- self.question.question_options = placeholder_options
164
-
165
- replacement_dict = (
166
- {key: f"<see file {key}>" for key in self.scenario_file_keys}
167
- | question_data
168
- | {
169
- k: v
170
- for k, v in self.scenario.items()
171
- if k not in self.scenario_file_keys
172
- } # don't include images in the replacement dict
173
- | self.prior_answers_dict()
174
- | {"agent": self.agent}
175
- | {
176
- "use_code": getattr(self.question, "_use_code", True),
177
- "include_comment": getattr(
178
- self.question, "_include_comment", False
179
- ),
180
- }
181
- )
182
-
183
- rendered_instructions = question_prompt.render(replacement_dict)
184
-
185
- # is there anything left to render?
186
- undefined_template_variables = (
187
- rendered_instructions.undefined_template_variables({})
188
- )
189
-
190
- # Check if it's the name of a question in the survey
191
- for question_name in self.survey.question_names:
192
- if question_name in undefined_template_variables:
193
- print(
194
- "Question name found in undefined_template_variables: ",
195
- question_name,
196
- )
197
-
198
- if undefined_template_variables:
199
- msg = f"Question instructions still has variables: {undefined_template_variables}."
200
- import warnings
201
-
202
- warnings.warn(msg)
203
- # raise QuestionScenarioRenderError(
204
- # f"Question instructions still has variables: {undefined_template_variables}."
205
- # )
206
-
207
- ####################################
208
- # Check if question has instructions - these are instructions in a Survey that can apply to multiple follow-on questions
209
- ####################################
210
- relevant_instructions = self.survey.relevant_instructions(
211
- self.question.question_name
212
- )
213
-
214
- if relevant_instructions != []:
215
- # preamble_text = Prompt(
216
- # text="You were given the following instructions: "
217
- # )
218
- preamble_text = Prompt(text="")
219
- for instruction in relevant_instructions:
220
- preamble_text += instruction.text
221
- rendered_instructions = preamble_text + rendered_instructions
222
-
223
- self._question_instructions_prompt = rendered_instructions
224
265
  return self._question_instructions_prompt
225
266
 
226
267
  @property
@@ -4,6 +4,20 @@ from typing import Dict
4
4
  from edsl.exceptions.agents import AgentNameError, AgentTraitKeyError
5
5
 
6
6
 
7
+ def convert_agent_name(x):
8
+ # potentially a numpy int64
9
+ import numpy as np
10
+
11
+ if isinstance(x, np.int64):
12
+ return int(x)
13
+ elif x is None:
14
+ return None
15
+ elif isinstance(x, int):
16
+ return x
17
+ else:
18
+ return str(x)
19
+
20
+
7
21
  class NameDescriptor:
8
22
  """ABC for something."""
9
23
 
@@ -13,7 +27,7 @@ class NameDescriptor:
13
27
 
14
28
  def __set__(self, instance, name: str) -> None:
15
29
  """Set the value of the attribute."""
16
- instance.__dict__[self.name] = name
30
+ instance.__dict__[self.name] = convert_agent_name(name)
17
31
 
18
32
  def __set_name__(self, owner, name: str) -> None:
19
33
  """Set the name of the attribute."""
@@ -34,9 +48,8 @@ class TraitsDescriptor:
34
48
  for key, value in traits_dict.items():
35
49
  if key == "name":
36
50
  raise AgentNameError(
37
- """Trait keys cannot be 'name'. Instead, use the 'name' attribute directly e.g.,
38
- Agent(name="my_agent", traits={"trait1": "value1", "trait2": "value2"})
39
- """
51
+ "Trait keys cannot be 'name'. Instead, use the 'name' attribute directly e.g.,\n"
52
+ 'Agent(name="my_agent", traits={"trait1": "value1", "trait2": "value2"})'
40
53
  )
41
54
 
42
55
  if not is_valid_variable_name(key):
@@ -58,7 +58,7 @@ CONFIG_MAP = {
58
58
  "info": "This config var holds the maximum number of tokens per minute for all models. Model-specific values provided in env vars such as EDSL_SERVICE_TPM_OPENAI will override this value for the corresponding model.",
59
59
  },
60
60
  "EXPECTED_PARROT_URL": {
61
- "default": "https://www.expectedparrot.com",
61
+ "default": "https://api.expectedparrot.com",
62
62
  "info": "This config var holds the URL of the Expected Parrot API.",
63
63
  },
64
64
  }