edsl 0.1.47__py3-none-any.whl → 0.1.48__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (314) hide show
  1. edsl/__init__.py +44 -39
  2. edsl/__version__.py +1 -1
  3. edsl/agents/__init__.py +4 -2
  4. edsl/agents/{Agent.py → agent.py} +442 -152
  5. edsl/agents/{AgentList.py → agent_list.py} +220 -162
  6. edsl/agents/descriptors.py +46 -7
  7. edsl/{exceptions/agents.py → agents/exceptions.py} +3 -12
  8. edsl/base/__init__.py +75 -0
  9. edsl/base/base_class.py +1303 -0
  10. edsl/base/data_transfer_models.py +114 -0
  11. edsl/base/enums.py +215 -0
  12. edsl/base.py +8 -0
  13. edsl/buckets/__init__.py +25 -0
  14. edsl/buckets/bucket_collection.py +324 -0
  15. edsl/buckets/model_buckets.py +206 -0
  16. edsl/buckets/token_bucket.py +502 -0
  17. edsl/{jobs/buckets/TokenBucketAPI.py → buckets/token_bucket_api.py} +1 -1
  18. edsl/buckets/token_bucket_client.py +509 -0
  19. edsl/caching/__init__.py +20 -0
  20. edsl/caching/cache.py +814 -0
  21. edsl/caching/cache_entry.py +427 -0
  22. edsl/{data/CacheHandler.py → caching/cache_handler.py} +14 -15
  23. edsl/caching/exceptions.py +24 -0
  24. edsl/caching/orm.py +30 -0
  25. edsl/{data/RemoteCacheSync.py → caching/remote_cache_sync.py} +3 -3
  26. edsl/caching/sql_dict.py +441 -0
  27. edsl/config/__init__.py +8 -0
  28. edsl/config/config_class.py +177 -0
  29. edsl/config.py +4 -176
  30. edsl/conversation/Conversation.py +7 -7
  31. edsl/conversation/car_buying.py +4 -4
  32. edsl/conversation/chips.py +6 -6
  33. edsl/coop/__init__.py +25 -2
  34. edsl/coop/coop.py +303 -67
  35. edsl/coop/{ExpectedParrotKeyHandler.py → ep_key_handling.py} +86 -10
  36. edsl/coop/exceptions.py +62 -0
  37. edsl/coop/price_fetcher.py +126 -0
  38. edsl/coop/utils.py +89 -24
  39. edsl/data_transfer_models.py +5 -72
  40. edsl/dataset/__init__.py +10 -0
  41. edsl/{results/Dataset.py → dataset/dataset.py} +116 -36
  42. edsl/{results/DatasetExportMixin.py → dataset/dataset_operations_mixin.py} +606 -122
  43. edsl/{results/DatasetTree.py → dataset/dataset_tree.py} +156 -75
  44. edsl/{results/TableDisplay.py → dataset/display/table_display.py} +18 -7
  45. edsl/{results → dataset/display}/table_renderers.py +58 -2
  46. edsl/{results → dataset}/file_exports.py +4 -5
  47. edsl/{results → dataset}/smart_objects.py +2 -2
  48. edsl/enums.py +5 -205
  49. edsl/inference_services/__init__.py +5 -0
  50. edsl/inference_services/{AvailableModelCacheHandler.py → available_model_cache_handler.py} +2 -3
  51. edsl/inference_services/{AvailableModelFetcher.py → available_model_fetcher.py} +8 -14
  52. edsl/inference_services/data_structures.py +3 -2
  53. edsl/{exceptions/inference_services.py → inference_services/exceptions.py} +1 -1
  54. edsl/inference_services/{InferenceServiceABC.py → inference_service_abc.py} +1 -1
  55. edsl/inference_services/{InferenceServicesCollection.py → inference_services_collection.py} +8 -7
  56. edsl/inference_services/registry.py +4 -41
  57. edsl/inference_services/{ServiceAvailability.py → service_availability.py} +5 -25
  58. edsl/inference_services/services/__init__.py +31 -0
  59. edsl/inference_services/{AnthropicService.py → services/anthropic_service.py} +3 -3
  60. edsl/inference_services/{AwsBedrock.py → services/aws_bedrock.py} +2 -2
  61. edsl/inference_services/{AzureAI.py → services/azure_ai.py} +2 -2
  62. edsl/inference_services/{DeepInfraService.py → services/deep_infra_service.py} +1 -3
  63. edsl/inference_services/{DeepSeekService.py → services/deep_seek_service.py} +2 -4
  64. edsl/inference_services/{GoogleService.py → services/google_service.py} +5 -4
  65. edsl/inference_services/{GroqService.py → services/groq_service.py} +1 -1
  66. edsl/inference_services/{MistralAIService.py → services/mistral_ai_service.py} +3 -3
  67. edsl/inference_services/{OllamaService.py → services/ollama_service.py} +1 -7
  68. edsl/inference_services/{OpenAIService.py → services/open_ai_service.py} +5 -6
  69. edsl/inference_services/{PerplexityService.py → services/perplexity_service.py} +3 -7
  70. edsl/inference_services/{TestService.py → services/test_service.py} +7 -6
  71. edsl/inference_services/{TogetherAIService.py → services/together_ai_service.py} +2 -6
  72. edsl/inference_services/{XAIService.py → services/xai_service.py} +1 -1
  73. edsl/inference_services/write_available.py +1 -2
  74. edsl/instructions/__init__.py +6 -0
  75. edsl/{surveys/instructions/Instruction.py → instructions/instruction.py} +11 -6
  76. edsl/{surveys/instructions/InstructionCollection.py → instructions/instruction_collection.py} +10 -5
  77. edsl/{surveys/InstructionHandler.py → instructions/instruction_handler.py} +3 -3
  78. edsl/{jobs/interviews → interviews}/ReportErrors.py +2 -2
  79. edsl/interviews/__init__.py +4 -0
  80. edsl/{jobs/AnswerQuestionFunctionConstructor.py → interviews/answering_function.py} +45 -18
  81. edsl/{jobs/interviews/InterviewExceptionEntry.py → interviews/exception_tracking.py} +107 -22
  82. edsl/interviews/interview.py +638 -0
  83. edsl/{jobs/interviews/InterviewStatusDictionary.py → interviews/interview_status_dictionary.py} +21 -12
  84. edsl/{jobs/interviews/InterviewStatusLog.py → interviews/interview_status_log.py} +16 -7
  85. edsl/{jobs/InterviewTaskManager.py → interviews/interview_task_manager.py} +12 -7
  86. edsl/{jobs/RequestTokenEstimator.py → interviews/request_token_estimator.py} +8 -3
  87. edsl/{jobs/interviews/InterviewStatistic.py → interviews/statistics.py} +36 -10
  88. edsl/invigilators/__init__.py +38 -0
  89. edsl/invigilators/invigilator_base.py +477 -0
  90. edsl/{agents/Invigilator.py → invigilators/invigilators.py} +263 -10
  91. edsl/invigilators/prompt_constructor.py +476 -0
  92. edsl/{agents → invigilators}/prompt_helpers.py +2 -1
  93. edsl/{agents/QuestionInstructionPromptBuilder.py → invigilators/question_instructions_prompt_builder.py} +18 -13
  94. edsl/{agents → invigilators}/question_option_processor.py +96 -21
  95. edsl/{agents/QuestionTemplateReplacementsBuilder.py → invigilators/question_template_replacements_builder.py} +64 -12
  96. edsl/jobs/__init__.py +7 -1
  97. edsl/jobs/async_interview_runner.py +99 -35
  98. edsl/jobs/check_survey_scenario_compatibility.py +7 -5
  99. edsl/jobs/data_structures.py +153 -22
  100. edsl/{exceptions/jobs.py → jobs/exceptions.py} +2 -1
  101. edsl/jobs/{FetchInvigilator.py → fetch_invigilator.py} +4 -4
  102. edsl/jobs/{loggers/HTMLTableJobLogger.py → html_table_job_logger.py} +6 -2
  103. edsl/jobs/{Jobs.py → jobs.py} +313 -167
  104. edsl/jobs/{JobsChecks.py → jobs_checks.py} +15 -7
  105. edsl/jobs/{JobsComponentConstructor.py → jobs_component_constructor.py} +19 -17
  106. edsl/jobs/{InterviewsConstructor.py → jobs_interview_constructor.py} +10 -5
  107. edsl/jobs/jobs_pricing_estimation.py +347 -0
  108. edsl/jobs/{JobsRemoteInferenceLogger.py → jobs_remote_inference_logger.py} +4 -3
  109. edsl/jobs/jobs_runner_asyncio.py +282 -0
  110. edsl/jobs/{JobsRemoteInferenceHandler.py → remote_inference.py} +19 -22
  111. edsl/jobs/results_exceptions_handler.py +2 -2
  112. edsl/key_management/__init__.py +28 -0
  113. edsl/key_management/key_lookup.py +161 -0
  114. edsl/{language_models/key_management/KeyLookupBuilder.py → key_management/key_lookup_builder.py} +118 -47
  115. edsl/key_management/key_lookup_collection.py +82 -0
  116. edsl/key_management/models.py +218 -0
  117. edsl/language_models/__init__.py +7 -2
  118. edsl/language_models/{ComputeCost.py → compute_cost.py} +18 -3
  119. edsl/{exceptions/language_models.py → language_models/exceptions.py} +2 -1
  120. edsl/language_models/language_model.py +1080 -0
  121. edsl/language_models/model.py +10 -25
  122. edsl/language_models/{ModelList.py → model_list.py} +9 -14
  123. edsl/language_models/{RawResponseHandler.py → raw_response_handler.py} +1 -1
  124. edsl/language_models/{RegisterLanguageModelsMeta.py → registry.py} +1 -1
  125. edsl/language_models/repair.py +4 -4
  126. edsl/language_models/utilities.py +4 -4
  127. edsl/notebooks/__init__.py +3 -1
  128. edsl/notebooks/{Notebook.py → notebook.py} +7 -8
  129. edsl/prompts/__init__.py +1 -1
  130. edsl/{exceptions/prompts.py → prompts/exceptions.py} +3 -1
  131. edsl/prompts/{Prompt.py → prompt.py} +101 -95
  132. edsl/questions/HTMLQuestion.py +1 -1
  133. edsl/questions/__init__.py +154 -25
  134. edsl/questions/answer_validator_mixin.py +1 -1
  135. edsl/questions/compose_questions.py +4 -3
  136. edsl/questions/derived/question_likert_five.py +166 -0
  137. edsl/questions/derived/{QuestionLinearScale.py → question_linear_scale.py} +4 -4
  138. edsl/questions/derived/{QuestionTopK.py → question_top_k.py} +4 -4
  139. edsl/questions/derived/{QuestionYesNo.py → question_yes_no.py} +4 -5
  140. edsl/questions/descriptors.py +24 -30
  141. edsl/questions/loop_processor.py +65 -19
  142. edsl/questions/question_base.py +881 -0
  143. edsl/questions/question_base_gen_mixin.py +15 -16
  144. edsl/questions/{QuestionBasePromptsMixin.py → question_base_prompts_mixin.py} +2 -2
  145. edsl/questions/{QuestionBudget.py → question_budget.py} +3 -4
  146. edsl/questions/{QuestionCheckBox.py → question_check_box.py} +16 -16
  147. edsl/questions/{QuestionDict.py → question_dict.py} +39 -5
  148. edsl/questions/{QuestionExtract.py → question_extract.py} +9 -9
  149. edsl/questions/question_free_text.py +282 -0
  150. edsl/questions/{QuestionFunctional.py → question_functional.py} +6 -5
  151. edsl/questions/{QuestionList.py → question_list.py} +6 -7
  152. edsl/questions/{QuestionMatrix.py → question_matrix.py} +6 -5
  153. edsl/questions/{QuestionMultipleChoice.py → question_multiple_choice.py} +126 -21
  154. edsl/questions/{QuestionNumerical.py → question_numerical.py} +5 -5
  155. edsl/questions/{QuestionRank.py → question_rank.py} +6 -6
  156. edsl/questions/question_registry.py +4 -9
  157. edsl/questions/register_questions_meta.py +8 -4
  158. edsl/questions/response_validator_abc.py +17 -16
  159. edsl/results/__init__.py +4 -1
  160. edsl/{exceptions/results.py → results/exceptions.py} +1 -1
  161. edsl/results/report.py +197 -0
  162. edsl/results/{Result.py → result.py} +131 -45
  163. edsl/results/{Results.py → results.py} +365 -220
  164. edsl/results/results_selector.py +344 -25
  165. edsl/scenarios/__init__.py +30 -3
  166. edsl/scenarios/{ConstructDownloadLink.py → construct_download_link.py} +7 -0
  167. edsl/scenarios/directory_scanner.py +156 -13
  168. edsl/scenarios/document_chunker.py +186 -0
  169. edsl/scenarios/exceptions.py +101 -0
  170. edsl/scenarios/file_methods.py +2 -3
  171. edsl/scenarios/{FileStore.py → file_store.py} +275 -189
  172. edsl/scenarios/handlers/__init__.py +14 -14
  173. edsl/scenarios/handlers/{csv.py → csv_file_store.py} +1 -2
  174. edsl/scenarios/handlers/{docx.py → docx_file_store.py} +8 -7
  175. edsl/scenarios/handlers/{html.py → html_file_store.py} +1 -2
  176. edsl/scenarios/handlers/{jpeg.py → jpeg_file_store.py} +1 -1
  177. edsl/scenarios/handlers/{json.py → json_file_store.py} +1 -1
  178. edsl/scenarios/handlers/latex_file_store.py +5 -0
  179. edsl/scenarios/handlers/{md.py → md_file_store.py} +1 -1
  180. edsl/scenarios/handlers/{pdf.py → pdf_file_store.py} +2 -2
  181. edsl/scenarios/handlers/{png.py → png_file_store.py} +1 -1
  182. edsl/scenarios/handlers/{pptx.py → pptx_file_store.py} +8 -7
  183. edsl/scenarios/handlers/{py.py → py_file_store.py} +1 -3
  184. edsl/scenarios/handlers/{sql.py → sql_file_store.py} +2 -1
  185. edsl/scenarios/handlers/{sqlite.py → sqlite_file_store.py} +2 -3
  186. edsl/scenarios/handlers/{txt.py → txt_file_store.py} +1 -1
  187. edsl/scenarios/scenario.py +928 -0
  188. edsl/scenarios/scenario_join.py +18 -5
  189. edsl/scenarios/{ScenarioList.py → scenario_list.py} +294 -106
  190. edsl/scenarios/{ScenarioListPdfMixin.py → scenario_list_pdf_tools.py} +16 -15
  191. edsl/scenarios/scenario_selector.py +5 -1
  192. edsl/study/ObjectEntry.py +2 -2
  193. edsl/study/SnapShot.py +5 -5
  194. edsl/study/Study.py +18 -19
  195. edsl/study/__init__.py +6 -4
  196. edsl/surveys/__init__.py +7 -4
  197. edsl/surveys/dag/__init__.py +2 -0
  198. edsl/surveys/{ConstructDAG.py → dag/construct_dag.py} +3 -3
  199. edsl/surveys/{DAG.py → dag/dag.py} +13 -10
  200. edsl/surveys/descriptors.py +1 -1
  201. edsl/surveys/{EditSurvey.py → edit_survey.py} +9 -9
  202. edsl/{exceptions/surveys.py → surveys/exceptions.py} +1 -2
  203. edsl/surveys/memory/__init__.py +3 -0
  204. edsl/surveys/{MemoryPlan.py → memory/memory_plan.py} +10 -9
  205. edsl/surveys/rules/__init__.py +3 -0
  206. edsl/surveys/{Rule.py → rules/rule.py} +103 -43
  207. edsl/surveys/{RuleCollection.py → rules/rule_collection.py} +21 -30
  208. edsl/surveys/{RuleManager.py → rules/rule_manager.py} +19 -13
  209. edsl/surveys/survey.py +1743 -0
  210. edsl/surveys/{SurveyExportMixin.py → survey_export.py} +22 -27
  211. edsl/surveys/{SurveyFlowVisualization.py → survey_flow_visualization.py} +11 -2
  212. edsl/surveys/{Simulator.py → survey_simulator.py} +10 -3
  213. edsl/tasks/__init__.py +32 -0
  214. edsl/{jobs/tasks/QuestionTaskCreator.py → tasks/question_task_creator.py} +115 -57
  215. edsl/tasks/task_creators.py +135 -0
  216. edsl/{jobs/tasks/TaskHistory.py → tasks/task_history.py} +86 -47
  217. edsl/{jobs/tasks → tasks}/task_status_enum.py +91 -7
  218. edsl/tasks/task_status_log.py +85 -0
  219. edsl/tokens/__init__.py +2 -0
  220. edsl/tokens/interview_token_usage.py +53 -0
  221. edsl/utilities/PrettyList.py +1 -1
  222. edsl/utilities/SystemInfo.py +25 -22
  223. edsl/utilities/__init__.py +29 -21
  224. edsl/utilities/gcp_bucket/__init__.py +2 -0
  225. edsl/utilities/gcp_bucket/cloud_storage.py +99 -96
  226. edsl/utilities/interface.py +44 -536
  227. edsl/{results/MarkdownToPDF.py → utilities/markdown_to_pdf.py} +13 -5
  228. edsl/utilities/repair_functions.py +1 -1
  229. {edsl-0.1.47.dist-info → edsl-0.1.48.dist-info}/METADATA +1 -1
  230. edsl-0.1.48.dist-info/RECORD +347 -0
  231. edsl/Base.py +0 -493
  232. edsl/BaseDiff.py +0 -260
  233. edsl/agents/InvigilatorBase.py +0 -260
  234. edsl/agents/PromptConstructor.py +0 -318
  235. edsl/coop/PriceFetcher.py +0 -54
  236. edsl/data/Cache.py +0 -582
  237. edsl/data/CacheEntry.py +0 -238
  238. edsl/data/SQLiteDict.py +0 -292
  239. edsl/data/__init__.py +0 -5
  240. edsl/data/orm.py +0 -10
  241. edsl/exceptions/cache.py +0 -5
  242. edsl/exceptions/coop.py +0 -14
  243. edsl/exceptions/data.py +0 -14
  244. edsl/exceptions/scenarios.py +0 -29
  245. edsl/jobs/Answers.py +0 -43
  246. edsl/jobs/JobsPrompts.py +0 -354
  247. edsl/jobs/buckets/BucketCollection.py +0 -134
  248. edsl/jobs/buckets/ModelBuckets.py +0 -65
  249. edsl/jobs/buckets/TokenBucket.py +0 -283
  250. edsl/jobs/buckets/TokenBucketClient.py +0 -191
  251. edsl/jobs/interviews/Interview.py +0 -395
  252. edsl/jobs/interviews/InterviewExceptionCollection.py +0 -99
  253. edsl/jobs/interviews/InterviewStatisticsCollection.py +0 -25
  254. edsl/jobs/runners/JobsRunnerAsyncio.py +0 -163
  255. edsl/jobs/runners/JobsRunnerStatusData.py +0 -0
  256. edsl/jobs/tasks/TaskCreators.py +0 -64
  257. edsl/jobs/tasks/TaskStatusLog.py +0 -23
  258. edsl/jobs/tokens/InterviewTokenUsage.py +0 -27
  259. edsl/language_models/LanguageModel.py +0 -635
  260. edsl/language_models/ServiceDataSources.py +0 -0
  261. edsl/language_models/key_management/KeyLookup.py +0 -63
  262. edsl/language_models/key_management/KeyLookupCollection.py +0 -38
  263. edsl/language_models/key_management/models.py +0 -137
  264. edsl/questions/QuestionBase.py +0 -544
  265. edsl/questions/QuestionFreeText.py +0 -130
  266. edsl/questions/derived/QuestionLikertFive.py +0 -76
  267. edsl/results/ResultsExportMixin.py +0 -45
  268. edsl/results/TextEditor.py +0 -50
  269. edsl/results/results_fetch_mixin.py +0 -33
  270. edsl/results/results_tools_mixin.py +0 -98
  271. edsl/scenarios/DocumentChunker.py +0 -104
  272. edsl/scenarios/Scenario.py +0 -548
  273. edsl/scenarios/ScenarioHtmlMixin.py +0 -65
  274. edsl/scenarios/ScenarioListExportMixin.py +0 -45
  275. edsl/scenarios/handlers/latex.py +0 -5
  276. edsl/shared.py +0 -1
  277. edsl/surveys/Survey.py +0 -1301
  278. edsl/surveys/SurveyQualtricsImport.py +0 -284
  279. edsl/surveys/SurveyToApp.py +0 -141
  280. edsl/surveys/instructions/__init__.py +0 -0
  281. edsl/tools/__init__.py +0 -1
  282. edsl/tools/clusters.py +0 -192
  283. edsl/tools/embeddings.py +0 -27
  284. edsl/tools/embeddings_plotting.py +0 -118
  285. edsl/tools/plotting.py +0 -112
  286. edsl/tools/summarize.py +0 -18
  287. edsl/utilities/data/Registry.py +0 -6
  288. edsl/utilities/data/__init__.py +0 -1
  289. edsl/utilities/data/scooter_results.json +0 -1
  290. edsl-0.1.47.dist-info/RECORD +0 -354
  291. /edsl/coop/{CoopFunctionsMixin.py → coop_functions.py} +0 -0
  292. /edsl/{results → dataset/display}/CSSParameterizer.py +0 -0
  293. /edsl/{language_models/key_management → dataset/display}/__init__.py +0 -0
  294. /edsl/{results → dataset/display}/table_data_class.py +0 -0
  295. /edsl/{results → dataset/display}/table_display.css +0 -0
  296. /edsl/{results/ResultsGGMixin.py → dataset/r/ggplot.py} +0 -0
  297. /edsl/{results → dataset}/tree_explore.py +0 -0
  298. /edsl/{surveys/instructions/ChangeInstruction.py → instructions/change_instruction.py} +0 -0
  299. /edsl/{jobs/interviews → interviews}/interview_status_enum.py +0 -0
  300. /edsl/jobs/{runners/JobsRunnerStatus.py → jobs_runner_status.py} +0 -0
  301. /edsl/language_models/{PriceManager.py → price_manager.py} +0 -0
  302. /edsl/language_models/{fake_openai_call.py → unused/fake_openai_call.py} +0 -0
  303. /edsl/language_models/{fake_openai_service.py → unused/fake_openai_service.py} +0 -0
  304. /edsl/notebooks/{NotebookToLaTeX.py → notebook_to_latex.py} +0 -0
  305. /edsl/{exceptions/questions.py → questions/exceptions.py} +0 -0
  306. /edsl/questions/{SimpleAskMixin.py → simple_ask_mixin.py} +0 -0
  307. /edsl/surveys/{Memory.py → memory/memory.py} +0 -0
  308. /edsl/surveys/{MemoryManagement.py → memory/memory_management.py} +0 -0
  309. /edsl/surveys/{SurveyCSS.py → survey_css.py} +0 -0
  310. /edsl/{jobs/tokens/TokenUsage.py → tokens/token_usage.py} +0 -0
  311. /edsl/{results/MarkdownToDocx.py → utilities/markdown_to_docx.py} +0 -0
  312. /edsl/{TemplateLoader.py → utilities/template_loader.py} +0 -0
  313. {edsl-0.1.47.dist-info → edsl-0.1.48.dist-info}/LICENSE +0 -0
  314. {edsl-0.1.47.dist-info → edsl-0.1.48.dist-info}/WHEEL +0 -0
@@ -1,318 +0,0 @@
1
- from __future__ import annotations
2
- from typing import Dict, Any, Optional, Set, Union, TYPE_CHECKING, Literal
3
- from functools import cached_property
4
- import time
5
- import logging
6
-
7
- from edsl.prompts.Prompt import Prompt
8
-
9
- from edsl.agents.prompt_helpers import PromptPlan
10
- from edsl.agents.QuestionTemplateReplacementsBuilder import (
11
- QuestionTemplateReplacementsBuilder,
12
- )
13
- from edsl.agents.question_option_processor import QuestionOptionProcessor
14
-
15
- if TYPE_CHECKING:
16
- from edsl.agents.InvigilatorBase import InvigilatorBase
17
- from edsl.questions.QuestionBase import QuestionBase
18
- from edsl.agents.Agent import Agent
19
- from edsl.surveys.Survey import Survey
20
- from edsl.language_models.LanguageModel import LanguageModel
21
- from edsl.surveys.MemoryPlan import MemoryPlan
22
- from edsl.questions.QuestionBase import QuestionBase
23
- from edsl.scenarios.Scenario import Scenario
24
-
25
- logger = logging.getLogger(__name__)
26
-
27
- class BasePlaceholder:
28
- """Base class for placeholder values when a question is not yet answered."""
29
-
30
- def __init__(self, placeholder_type: str = "answer"):
31
- self.value = "N/A"
32
- self.comment = "Will be populated by prior answer"
33
- self._type = placeholder_type
34
-
35
- def __getitem__(self, index):
36
- return ""
37
-
38
- def __str__(self):
39
- return f"<<{self.__class__.__name__}:{self._type}>>"
40
-
41
- def __repr__(self):
42
- return self.__str__()
43
-
44
-
45
- class PlaceholderAnswer(BasePlaceholder):
46
- def __init__(self):
47
- super().__init__("answer")
48
-
49
-
50
- class PlaceholderComment(BasePlaceholder):
51
- def __init__(self):
52
- super().__init__("comment")
53
-
54
-
55
- class PlaceholderGeneratedTokens(BasePlaceholder):
56
- def __init__(self):
57
- super().__init__("generated_tokens")
58
-
59
-
60
- class PromptConstructor:
61
- """
62
- This class constructs the prompts for the language model.
63
-
64
- The pieces of a prompt are:
65
- - The agent instructions - "You are answering questions as if you were a human. Do not break character."
66
- - The persona prompt - "You are an agent with the following persona: {'age': 22, 'hair': 'brown', 'height': 5.5}"
67
- - The question instructions - "You are being asked the following question: Do you like school? The options are 0: yes 1: no Return a valid JSON formatted like this, selecting only the number of the option: {"answer": <put answer code here>, "comment": "<put explanation here>"} Only 1 option may be selected."
68
- - The memory prompt - "Before the question you are now answering, you already answered the following question(s): Question: Do you like school? Answer: Prior answer"
69
- """
70
- @classmethod
71
- def from_invigilator(
72
- cls,
73
- invigilator: "InvigilatorBase",
74
- prompt_plan: Optional["PromptPlan"] = None
75
- ) -> "PromptConstructor":
76
- return cls(
77
- agent=invigilator.agent,
78
- question=invigilator.question,
79
- scenario=invigilator.scenario,
80
- survey=invigilator.survey,
81
- model=invigilator.model,
82
- current_answers=invigilator.current_answers,
83
- memory_plan=invigilator.memory_plan,
84
- prompt_plan=prompt_plan
85
- )
86
-
87
- def __init__(
88
- self,
89
- agent: "Agent",
90
- question: "QuestionBase",
91
- scenario: "Scenario",
92
- survey: "Survey",
93
- model: "LanguageModel",
94
- current_answers: dict,
95
- memory_plan: "MemoryPlan",
96
- prompt_plan: Optional["PromptPlan"] = None
97
- ):
98
- self.agent = agent
99
- self.question = question
100
- self.scenario = scenario
101
- self.survey = survey
102
- self.model = model
103
- self.current_answers = current_answers
104
- self.memory_plan = memory_plan
105
- self.prompt_plan = prompt_plan or PromptPlan()
106
-
107
- def get_question_options(self, question_data: dict) -> list[str]:
108
- """Get the question options."""
109
- return (QuestionOptionProcessor
110
- .from_prompt_constructor(self)
111
- .get_question_options(question_data)
112
- )
113
-
114
- @cached_property
115
- def agent_instructions_prompt(self) -> Prompt:
116
- """
117
- >>> from edsl.agents.InvigilatorBase import InvigilatorBase
118
- >>> i = InvigilatorBase.example()
119
- >>> i.prompt_constructor.agent_instructions_prompt
120
- Prompt(text=\"""You are answering questions as if you were a human. Do not break character.\""")
121
- """
122
- from edsl.agents.Agent import Agent
123
-
124
- if self.agent == Agent(): # if agent is empty, then return an empty prompt
125
- return Prompt(text="")
126
-
127
- return Prompt(text=self.agent.instruction)
128
-
129
- @cached_property
130
- def agent_persona_prompt(self) -> Prompt:
131
- """
132
- >>> from edsl.agents.InvigilatorBase import InvigilatorBase
133
- >>> i = InvigilatorBase.example()
134
- >>> i.prompt_constructor.agent_persona_prompt
135
- Prompt(text=\"""Your traits: {'age': 22, 'hair': 'brown', 'height': 5.5}\""")
136
- """
137
- from edsl.agents.Agent import Agent
138
-
139
- if self.agent == Agent(): # if agent is empty, then return an empty prompt
140
- return Prompt(text="")
141
-
142
- return self.agent.prompt()
143
-
144
- def prior_answers_dict(self) -> dict[str, "QuestionBase"]:
145
- """This is a dictionary of prior answers, if they exist.
146
-
147
- >>> from edsl.agents.InvigilatorBase import InvigilatorBase
148
- >>> i = InvigilatorBase.example()
149
- >>> i.prompt_constructor.prior_answers_dict()
150
- {'q0': ..., 'q1': ...}
151
- """
152
- return self._add_answers(
153
- self.survey.question_names_to_questions(), self.current_answers
154
- )
155
-
156
- @staticmethod
157
- def _extract_question_and_entry_type(key_entry) -> tuple[str, str]:
158
- """
159
- Extracts the question name and type for the current answer dictionary key entry.
160
-
161
- >>> PromptConstructor._extract_question_and_entry_type("q0")
162
- ('q0', 'answer')
163
- >>> PromptConstructor._extract_question_and_entry_type("q0_comment")
164
- ('q0', 'comment')
165
- >>> PromptConstructor._extract_question_and_entry_type("q0_alternate_generated_tokens")
166
- ('q0_alternate', 'generated_tokens')
167
- >>> PromptConstructor._extract_question_and_entry_type("q0_alt_comment")
168
- ('q0_alt', 'comment')
169
- """
170
- split_list = key_entry.rsplit("_", maxsplit=1)
171
- if len(split_list) == 1:
172
- question_name = split_list[0]
173
- entry_type = "answer"
174
- else:
175
- if split_list[1] == "comment":
176
- question_name = split_list[0]
177
- entry_type = "comment"
178
- elif split_list[1] == "tokens": # it's actually 'generated_tokens'
179
- question_name = key_entry.replace("_generated_tokens", "")
180
- entry_type = "generated_tokens"
181
- else:
182
- question_name = key_entry
183
- entry_type = "answer"
184
- return question_name, entry_type
185
-
186
- @staticmethod
187
- def _augmented_answers_dict(current_answers: dict) -> dict:
188
- """
189
- >>> PromptConstructor._augmented_answers_dict({"q0": "LOVE IT!", "q0_comment": "I love school!"})
190
- {'q0': {'answer': 'LOVE IT!', 'comment': 'I love school!'}}
191
- """
192
- from collections import defaultdict
193
-
194
- d = defaultdict(dict)
195
- for key, value in current_answers.items():
196
- question_name, entry_type = (
197
- PromptConstructor._extract_question_and_entry_type(key)
198
- )
199
- d[question_name][entry_type] = value
200
- return dict(d)
201
-
202
- @staticmethod
203
- def _add_answers(
204
- answer_dict: dict, current_answers: dict
205
- ) -> dict[str, "QuestionBase"]:
206
- """
207
- >>> from edsl import QuestionFreeText
208
- >>> d = {"q0": QuestionFreeText(question_text="Do you like school?", question_name = "q0")}
209
- >>> current_answers = {"q0": "LOVE IT!"}
210
- >>> PromptConstructor._add_answers(d, current_answers)['q0'].answer
211
- 'LOVE IT!'
212
- """
213
- augmented_answers = PromptConstructor._augmented_answers_dict(current_answers)
214
-
215
- for question in answer_dict:
216
- if question in augmented_answers:
217
- for entry_type, value in augmented_answers[question].items():
218
- setattr(answer_dict[question], entry_type, value)
219
- else:
220
- answer_dict[question].answer = PlaceholderAnswer()
221
- answer_dict[question].comment = PlaceholderComment()
222
- answer_dict[question].generated_tokens = PlaceholderGeneratedTokens()
223
- return answer_dict
224
-
225
- @cached_property
226
- def question_file_keys(self) -> list:
227
- """Extracts the file keys from the question text.
228
-
229
- It checks if the variables in the question text are in the scenario file keys.
230
- """
231
- return QuestionTemplateReplacementsBuilder.from_prompt_constructor(self).question_file_keys()
232
-
233
- @cached_property
234
- def question_instructions_prompt(self) -> Prompt:
235
- """
236
- >>> from edsl.agents.InvigilatorBase import InvigilatorBase
237
- >>> i = InvigilatorBase.example()
238
- >>> i.prompt_constructor.question_instructions_prompt
239
- Prompt(text=\"""...
240
- ...
241
- """
242
- return self.build_question_instructions_prompt()
243
-
244
- def build_question_instructions_prompt(self) -> Prompt:
245
- """Buils the question instructions prompt."""
246
- from edsl.agents.QuestionInstructionPromptBuilder import (
247
- QuestionInstructionPromptBuilder,
248
- )
249
-
250
- return QuestionInstructionPromptBuilder.from_prompt_constructor(self).build()
251
-
252
- @cached_property
253
- def prior_question_memory_prompt(self) -> Prompt:
254
- memory_prompt = Prompt(text="")
255
- if self.memory_plan is not None:
256
- memory_prompt += self.create_memory_prompt(
257
- self.question.question_name
258
- ).render(self.scenario | self.prior_answers_dict())
259
- return memory_prompt
260
-
261
- def create_memory_prompt(self, question_name: str) -> Prompt:
262
- """Create a memory for the agent.
263
-
264
- The returns a memory prompt for the agent.
265
-
266
- >>> from edsl.agents.InvigilatorBase import InvigilatorBase
267
- >>> i = InvigilatorBase.example()
268
- >>> i.current_answers = {"q0": "Prior answer"}
269
- >>> i.memory_plan.add_single_memory("q1", "q0")
270
- >>> p = i.prompt_constructor.create_memory_prompt("q1")
271
- >>> p.text.strip().replace("\\n", " ").replace("\\t", " ")
272
- 'Before the question you are now answering, you already answered the following question(s): Question: Do you like school? Answer: Prior answer'
273
- """
274
- return self.memory_plan.get_memory_prompt_fragment(
275
- question_name, self.current_answers
276
- )
277
-
278
- def get_prompts(self) -> Dict[str, Any]:
279
- """Get the prompts for the question."""
280
- start = time.time()
281
-
282
- # Build all the components
283
- agent_instructions = self.agent_instructions_prompt
284
- agent_persona = self.agent_persona_prompt
285
- question_instructions = self.question_instructions_prompt
286
- prior_question_memory = self.prior_question_memory_prompt
287
-
288
- # Get components dict
289
- components = {
290
- "agent_instructions": agent_instructions.text,
291
- "agent_persona": agent_persona.text,
292
- "question_instructions": question_instructions.text,
293
- "prior_question_memory": prior_question_memory.text,
294
- }
295
- # Get arranged components first
296
- arranged = self.prompt_plan.arrange_components(**components)
297
-
298
- prompts = self.prompt_plan.get_prompts(**components)
299
-
300
- # Handle file keys if present
301
- if hasattr(self, 'question_file_keys') and self.question_file_keys:
302
- files_list = []
303
- for key in self.question_file_keys:
304
- files_list.append(self.scenario[key])
305
- prompts["files_list"] = files_list
306
-
307
- return prompts
308
-
309
-
310
- # def _process_prompt(args):
311
- # """Helper function to process a single prompt list with its replacements."""
312
- # prompt_list, replacements = args
313
- # return prompt_list.reduce()
314
-
315
-
316
- if __name__ == '__main__':
317
- import doctest
318
- doctest.testmod(optionflags=doctest.ELLIPSIS)
edsl/coop/PriceFetcher.py DELETED
@@ -1,54 +0,0 @@
1
- import requests
2
- import csv
3
- from io import StringIO
4
-
5
-
6
- class PriceFetcher:
7
- _instance = None
8
-
9
- def __new__(cls):
10
- if cls._instance is None:
11
- cls._instance = super(PriceFetcher, cls).__new__(cls)
12
- cls._instance._cached_prices = None
13
- return cls._instance
14
-
15
- def fetch_prices(self):
16
- if self._cached_prices is not None:
17
- return self._cached_prices
18
-
19
- import os
20
- import requests
21
- from edsl.config import CONFIG
22
-
23
- try:
24
- # Fetch the pricing data
25
- url = f"{CONFIG.EXPECTED_PARROT_URL}/api/v0/prices"
26
- api_key = os.getenv("EXPECTED_PARROT_API_KEY")
27
- headers = {}
28
- if api_key:
29
- headers["Authorization"] = f"Bearer {api_key}"
30
- else:
31
- headers["Authorization"] = f"Bearer None"
32
-
33
- response = requests.get(url, headers=headers, timeout=20)
34
- response.raise_for_status() # Raise an exception for bad responses
35
-
36
- # Parse the data
37
- data = response.json()
38
-
39
- price_lookup = {}
40
- for entry in data:
41
- service = entry.get("service", None)
42
- model = entry.get("model", None)
43
- if service and model:
44
- token_type = entry.get("token_type", None)
45
- if (service, model) in price_lookup:
46
- price_lookup[(service, model)].update({token_type: entry})
47
- else:
48
- price_lookup[(service, model)] = {token_type: entry}
49
- self._cached_prices = price_lookup
50
- return self._cached_prices
51
-
52
- except requests.RequestException as e:
53
- # print(f"An error occurred: {e}")
54
- return {}