edsl 0.1.38.dev4__py3-none-any.whl → 0.1.39__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 (212) hide show
  1. edsl/Base.py +197 -116
  2. edsl/__init__.py +15 -7
  3. edsl/__version__.py +1 -1
  4. edsl/agents/Agent.py +351 -147
  5. edsl/agents/AgentList.py +211 -73
  6. edsl/agents/Invigilator.py +101 -50
  7. edsl/agents/InvigilatorBase.py +62 -70
  8. edsl/agents/PromptConstructor.py +143 -225
  9. edsl/agents/QuestionInstructionPromptBuilder.py +128 -0
  10. edsl/agents/QuestionTemplateReplacementsBuilder.py +137 -0
  11. edsl/agents/__init__.py +0 -1
  12. edsl/agents/prompt_helpers.py +3 -3
  13. edsl/agents/question_option_processor.py +172 -0
  14. edsl/auto/AutoStudy.py +18 -5
  15. edsl/auto/StageBase.py +53 -40
  16. edsl/auto/StageQuestions.py +2 -1
  17. edsl/auto/utilities.py +0 -6
  18. edsl/config.py +22 -2
  19. edsl/conversation/car_buying.py +2 -1
  20. edsl/coop/CoopFunctionsMixin.py +15 -0
  21. edsl/coop/ExpectedParrotKeyHandler.py +125 -0
  22. edsl/coop/PriceFetcher.py +1 -1
  23. edsl/coop/coop.py +125 -47
  24. edsl/coop/utils.py +14 -14
  25. edsl/data/Cache.py +45 -27
  26. edsl/data/CacheEntry.py +12 -15
  27. edsl/data/CacheHandler.py +31 -12
  28. edsl/data/RemoteCacheSync.py +154 -46
  29. edsl/data/__init__.py +4 -3
  30. edsl/data_transfer_models.py +2 -1
  31. edsl/enums.py +27 -0
  32. edsl/exceptions/__init__.py +50 -50
  33. edsl/exceptions/agents.py +12 -0
  34. edsl/exceptions/inference_services.py +5 -0
  35. edsl/exceptions/questions.py +24 -6
  36. edsl/exceptions/scenarios.py +7 -0
  37. edsl/inference_services/AnthropicService.py +38 -19
  38. edsl/inference_services/AvailableModelCacheHandler.py +184 -0
  39. edsl/inference_services/AvailableModelFetcher.py +215 -0
  40. edsl/inference_services/AwsBedrock.py +0 -2
  41. edsl/inference_services/AzureAI.py +0 -2
  42. edsl/inference_services/GoogleService.py +7 -12
  43. edsl/inference_services/InferenceServiceABC.py +18 -85
  44. edsl/inference_services/InferenceServicesCollection.py +120 -79
  45. edsl/inference_services/MistralAIService.py +0 -3
  46. edsl/inference_services/OpenAIService.py +47 -35
  47. edsl/inference_services/PerplexityService.py +0 -3
  48. edsl/inference_services/ServiceAvailability.py +135 -0
  49. edsl/inference_services/TestService.py +11 -10
  50. edsl/inference_services/TogetherAIService.py +5 -3
  51. edsl/inference_services/data_structures.py +134 -0
  52. edsl/jobs/AnswerQuestionFunctionConstructor.py +223 -0
  53. edsl/jobs/Answers.py +1 -14
  54. edsl/jobs/FetchInvigilator.py +47 -0
  55. edsl/jobs/InterviewTaskManager.py +98 -0
  56. edsl/jobs/InterviewsConstructor.py +50 -0
  57. edsl/jobs/Jobs.py +356 -431
  58. edsl/jobs/JobsChecks.py +35 -10
  59. edsl/jobs/JobsComponentConstructor.py +189 -0
  60. edsl/jobs/JobsPrompts.py +6 -4
  61. edsl/jobs/JobsRemoteInferenceHandler.py +205 -133
  62. edsl/jobs/JobsRemoteInferenceLogger.py +239 -0
  63. edsl/jobs/RequestTokenEstimator.py +30 -0
  64. edsl/jobs/async_interview_runner.py +138 -0
  65. edsl/jobs/buckets/BucketCollection.py +44 -3
  66. edsl/jobs/buckets/TokenBucket.py +53 -21
  67. edsl/jobs/buckets/TokenBucketAPI.py +211 -0
  68. edsl/jobs/buckets/TokenBucketClient.py +191 -0
  69. edsl/jobs/check_survey_scenario_compatibility.py +85 -0
  70. edsl/jobs/data_structures.py +120 -0
  71. edsl/jobs/decorators.py +35 -0
  72. edsl/jobs/interviews/Interview.py +143 -408
  73. edsl/jobs/jobs_status_enums.py +9 -0
  74. edsl/jobs/loggers/HTMLTableJobLogger.py +304 -0
  75. edsl/jobs/results_exceptions_handler.py +98 -0
  76. edsl/jobs/runners/JobsRunnerAsyncio.py +88 -403
  77. edsl/jobs/runners/JobsRunnerStatus.py +133 -165
  78. edsl/jobs/tasks/QuestionTaskCreator.py +21 -19
  79. edsl/jobs/tasks/TaskHistory.py +38 -18
  80. edsl/jobs/tasks/task_status_enum.py +0 -2
  81. edsl/language_models/ComputeCost.py +63 -0
  82. edsl/language_models/LanguageModel.py +194 -236
  83. edsl/language_models/ModelList.py +28 -19
  84. edsl/language_models/PriceManager.py +127 -0
  85. edsl/language_models/RawResponseHandler.py +106 -0
  86. edsl/language_models/ServiceDataSources.py +0 -0
  87. edsl/language_models/__init__.py +1 -2
  88. edsl/language_models/key_management/KeyLookup.py +63 -0
  89. edsl/language_models/key_management/KeyLookupBuilder.py +273 -0
  90. edsl/language_models/key_management/KeyLookupCollection.py +38 -0
  91. edsl/language_models/key_management/__init__.py +0 -0
  92. edsl/language_models/key_management/models.py +131 -0
  93. edsl/language_models/model.py +256 -0
  94. edsl/language_models/repair.py +2 -2
  95. edsl/language_models/utilities.py +5 -4
  96. edsl/notebooks/Notebook.py +19 -14
  97. edsl/notebooks/NotebookToLaTeX.py +142 -0
  98. edsl/prompts/Prompt.py +29 -39
  99. edsl/questions/ExceptionExplainer.py +77 -0
  100. edsl/questions/HTMLQuestion.py +103 -0
  101. edsl/questions/QuestionBase.py +68 -214
  102. edsl/questions/QuestionBasePromptsMixin.py +7 -3
  103. edsl/questions/QuestionBudget.py +1 -1
  104. edsl/questions/QuestionCheckBox.py +3 -3
  105. edsl/questions/QuestionExtract.py +5 -7
  106. edsl/questions/QuestionFreeText.py +2 -3
  107. edsl/questions/QuestionList.py +10 -18
  108. edsl/questions/QuestionMatrix.py +265 -0
  109. edsl/questions/QuestionMultipleChoice.py +67 -23
  110. edsl/questions/QuestionNumerical.py +2 -4
  111. edsl/questions/QuestionRank.py +7 -17
  112. edsl/questions/SimpleAskMixin.py +4 -3
  113. edsl/questions/__init__.py +2 -1
  114. edsl/questions/{AnswerValidatorMixin.py → answer_validator_mixin.py} +47 -2
  115. edsl/questions/data_structures.py +20 -0
  116. edsl/questions/derived/QuestionLinearScale.py +6 -3
  117. edsl/questions/derived/QuestionTopK.py +1 -1
  118. edsl/questions/descriptors.py +17 -3
  119. edsl/questions/loop_processor.py +149 -0
  120. edsl/questions/{QuestionBaseGenMixin.py → question_base_gen_mixin.py} +57 -50
  121. edsl/questions/question_registry.py +1 -1
  122. edsl/questions/{ResponseValidatorABC.py → response_validator_abc.py} +40 -26
  123. edsl/questions/response_validator_factory.py +34 -0
  124. edsl/questions/templates/matrix/__init__.py +1 -0
  125. edsl/questions/templates/matrix/answering_instructions.jinja +5 -0
  126. edsl/questions/templates/matrix/question_presentation.jinja +20 -0
  127. edsl/results/CSSParameterizer.py +1 -1
  128. edsl/results/Dataset.py +170 -7
  129. edsl/results/DatasetExportMixin.py +168 -305
  130. edsl/results/DatasetTree.py +28 -8
  131. edsl/results/MarkdownToDocx.py +122 -0
  132. edsl/results/MarkdownToPDF.py +111 -0
  133. edsl/results/Result.py +298 -206
  134. edsl/results/Results.py +149 -131
  135. edsl/results/ResultsExportMixin.py +2 -0
  136. edsl/results/TableDisplay.py +98 -171
  137. edsl/results/TextEditor.py +50 -0
  138. edsl/results/__init__.py +1 -1
  139. edsl/results/file_exports.py +252 -0
  140. edsl/results/{Selector.py → results_selector.py} +23 -13
  141. edsl/results/smart_objects.py +96 -0
  142. edsl/results/table_data_class.py +12 -0
  143. edsl/results/table_renderers.py +118 -0
  144. edsl/scenarios/ConstructDownloadLink.py +109 -0
  145. edsl/scenarios/DocumentChunker.py +102 -0
  146. edsl/scenarios/DocxScenario.py +16 -0
  147. edsl/scenarios/FileStore.py +150 -239
  148. edsl/scenarios/PdfExtractor.py +40 -0
  149. edsl/scenarios/Scenario.py +90 -193
  150. edsl/scenarios/ScenarioHtmlMixin.py +4 -3
  151. edsl/scenarios/ScenarioList.py +415 -244
  152. edsl/scenarios/ScenarioListExportMixin.py +0 -7
  153. edsl/scenarios/ScenarioListPdfMixin.py +15 -37
  154. edsl/scenarios/__init__.py +1 -2
  155. edsl/scenarios/directory_scanner.py +96 -0
  156. edsl/scenarios/file_methods.py +85 -0
  157. edsl/scenarios/handlers/__init__.py +13 -0
  158. edsl/scenarios/handlers/csv.py +49 -0
  159. edsl/scenarios/handlers/docx.py +76 -0
  160. edsl/scenarios/handlers/html.py +37 -0
  161. edsl/scenarios/handlers/json.py +111 -0
  162. edsl/scenarios/handlers/latex.py +5 -0
  163. edsl/scenarios/handlers/md.py +51 -0
  164. edsl/scenarios/handlers/pdf.py +68 -0
  165. edsl/scenarios/handlers/png.py +39 -0
  166. edsl/scenarios/handlers/pptx.py +105 -0
  167. edsl/scenarios/handlers/py.py +294 -0
  168. edsl/scenarios/handlers/sql.py +313 -0
  169. edsl/scenarios/handlers/sqlite.py +149 -0
  170. edsl/scenarios/handlers/txt.py +33 -0
  171. edsl/scenarios/{ScenarioJoin.py → scenario_join.py} +10 -6
  172. edsl/scenarios/scenario_selector.py +156 -0
  173. edsl/study/ObjectEntry.py +1 -1
  174. edsl/study/SnapShot.py +1 -1
  175. edsl/study/Study.py +5 -12
  176. edsl/surveys/ConstructDAG.py +92 -0
  177. edsl/surveys/EditSurvey.py +221 -0
  178. edsl/surveys/InstructionHandler.py +100 -0
  179. edsl/surveys/MemoryManagement.py +72 -0
  180. edsl/surveys/Rule.py +5 -4
  181. edsl/surveys/RuleCollection.py +25 -27
  182. edsl/surveys/RuleManager.py +172 -0
  183. edsl/surveys/Simulator.py +75 -0
  184. edsl/surveys/Survey.py +270 -791
  185. edsl/surveys/SurveyCSS.py +20 -8
  186. edsl/surveys/{SurveyFlowVisualizationMixin.py → SurveyFlowVisualization.py} +11 -9
  187. edsl/surveys/SurveyToApp.py +141 -0
  188. edsl/surveys/__init__.py +4 -2
  189. edsl/surveys/descriptors.py +6 -2
  190. edsl/surveys/instructions/ChangeInstruction.py +1 -2
  191. edsl/surveys/instructions/Instruction.py +4 -13
  192. edsl/surveys/instructions/InstructionCollection.py +11 -6
  193. edsl/templates/error_reporting/interview_details.html +1 -1
  194. edsl/templates/error_reporting/report.html +1 -1
  195. edsl/tools/plotting.py +1 -1
  196. edsl/utilities/PrettyList.py +56 -0
  197. edsl/utilities/is_notebook.py +18 -0
  198. edsl/utilities/is_valid_variable_name.py +11 -0
  199. edsl/utilities/remove_edsl_version.py +24 -0
  200. edsl/utilities/utilities.py +35 -23
  201. {edsl-0.1.38.dev4.dist-info → edsl-0.1.39.dist-info}/METADATA +12 -10
  202. edsl-0.1.39.dist-info/RECORD +358 -0
  203. {edsl-0.1.38.dev4.dist-info → edsl-0.1.39.dist-info}/WHEEL +1 -1
  204. edsl/language_models/KeyLookup.py +0 -30
  205. edsl/language_models/registry.py +0 -190
  206. edsl/language_models/unused/ReplicateBase.py +0 -83
  207. edsl/results/ResultsDBMixin.py +0 -238
  208. edsl-0.1.38.dev4.dist-info/RECORD +0 -277
  209. /edsl/questions/{RegisterQuestionsMeta.py → register_questions_meta.py} +0 -0
  210. /edsl/results/{ResultsFetchMixin.py → results_fetch_mixin.py} +0 -0
  211. /edsl/results/{ResultsToolsMixin.py → results_tools_mixin.py} +0 -0
  212. {edsl-0.1.38.dev4.dist-info → edsl-0.1.39.dist-info}/LICENSE +0 -0
@@ -0,0 +1,122 @@
1
+ from typing import Optional
2
+ import subprocess
3
+ import os
4
+ from pathlib import Path
5
+ import tempfile
6
+
7
+
8
+ class MarkdownToDocx:
9
+ def __init__(self, markdown_content: str, filename: Optional[str] = None):
10
+ """
11
+ Initialize the converter with markdown content.
12
+
13
+ Args:
14
+ markdown_content (str): The markdown content to be converted
15
+ """
16
+ self.markdown_content = markdown_content
17
+ self.filename = filename
18
+ self._check_pandoc()
19
+
20
+ def _check_pandoc(self):
21
+ """Check if pandoc is installed and accessible."""
22
+ try:
23
+ subprocess.run(["pandoc", "--version"], capture_output=True, check=True)
24
+ except (subprocess.CalledProcessError, FileNotFoundError):
25
+ raise RuntimeError(
26
+ "Pandoc is not installed or not found in PATH. "
27
+ "Please install pandoc before using this converter."
28
+ )
29
+
30
+ def convert(self, output_path: str, **options) -> bool:
31
+ """
32
+ Convert the markdown content to DOCX.
33
+
34
+ Args:
35
+ output_path (str): Path where the DOCX should be saved
36
+ **options: Additional conversion options
37
+ reference_doc (str): Path to reference docx for styling
38
+ toc (bool): Include table of contents (default: False)
39
+ number_sections (bool): Number sections (default: False)
40
+ highlight_style (str): Code highlighting style (default: "tango")
41
+
42
+ Returns:
43
+ bool: True if conversion was successful, False otherwise
44
+ """
45
+ # Ensure output directory exists
46
+ output_path = Path(output_path)
47
+ output_path.parent.mkdir(parents=True, exist_ok=True)
48
+
49
+ # Build pandoc command
50
+ cmd = ["pandoc", "-f", "markdown", "-t", "docx", "-o", str(output_path)]
51
+
52
+ # Add reference doc if provided
53
+ if "reference_doc" in options:
54
+ ref_doc = Path(options["reference_doc"])
55
+ if ref_doc.exists():
56
+ cmd.extend(["--reference-doc", str(ref_doc)])
57
+ else:
58
+ print(f"Warning: Reference document {ref_doc} not found")
59
+
60
+ # Add optional parameters
61
+ if options.get("toc", False):
62
+ cmd.append("--toc")
63
+
64
+ if options.get("number_sections", False):
65
+ cmd.append("--number-sections")
66
+
67
+ if "highlight_style" in options:
68
+ cmd.extend(["--highlight-style", options["highlight_style"]])
69
+
70
+ try:
71
+ # Run pandoc command
72
+ result = subprocess.run(
73
+ cmd,
74
+ input=self.markdown_content,
75
+ text=True,
76
+ capture_output=True,
77
+ check=True,
78
+ )
79
+ return True
80
+ except subprocess.CalledProcessError as e:
81
+ print(f"Error converting markdown to DOCX: {e.stderr}")
82
+ return False
83
+
84
+ def preview(self) -> str:
85
+ """
86
+ Generate a temporary DOCX and return its path.
87
+
88
+ Returns:
89
+ str: Path to the temporary DOCX file
90
+ """
91
+ temp_dir = tempfile.mkdtemp()
92
+ if self.filename:
93
+ temp_docx = os.path.join(temp_dir, self.filename)
94
+ else:
95
+ temp_docx = os.path.join(temp_dir, "preview.docx")
96
+
97
+ if self.convert(temp_docx):
98
+ from edsl.scenarios.FileStore import FileStore
99
+
100
+ return FileStore(path=temp_docx)
101
+
102
+ return None
103
+
104
+ def create_template(self, output_path: str) -> bool:
105
+ """
106
+ Create a reference DOCX template that can be modified for styling.
107
+
108
+ Args:
109
+ output_path (str): Path where the template should be saved
110
+
111
+ Returns:
112
+ bool: True if template was created successfully, False otherwise
113
+ """
114
+ try:
115
+ cmd = ["pandoc", "--print-default-data-file", "reference.docx"]
116
+
117
+ with open(output_path, "wb") as f:
118
+ result = subprocess.run(cmd, stdout=f, check=True)
119
+ return True
120
+ except subprocess.CalledProcessError as e:
121
+ print(f"Error creating template: {e.stderr}")
122
+ return False
@@ -0,0 +1,111 @@
1
+ from typing import Optional
2
+ import subprocess
3
+ import os
4
+ from pathlib import Path
5
+ import tempfile
6
+
7
+
8
+ class MarkdownToPDF:
9
+ def __init__(self, markdown_content: str, filename: Optional[str] = None):
10
+ """
11
+ Initialize the converter with markdown content.
12
+
13
+ Args:
14
+ markdown_content (str): The markdown content to be converted
15
+ """
16
+ self.markdown_content = markdown_content
17
+ self.filename = filename
18
+ self._check_pandoc()
19
+ # self.convert()
20
+
21
+ def _check_pandoc(self):
22
+ """Check if pandoc is installed and accessible."""
23
+ try:
24
+ subprocess.run(["pandoc", "--version"], capture_output=True, check=True)
25
+ except (subprocess.CalledProcessError, FileNotFoundError):
26
+ raise RuntimeError(
27
+ "Pandoc is not installed or not found in PATH. "
28
+ "Please install pandoc before using this converter."
29
+ )
30
+
31
+ def convert(self, output_path: str, **options) -> bool:
32
+ """
33
+ Convert the markdown content to PDF.
34
+
35
+ Args:
36
+ output_path (str): Path where the PDF should be saved
37
+ **options: Additional conversion options
38
+ margin (str): Page margin (default: "1in")
39
+ font_size (str): Font size (default: "12pt")
40
+ toc (bool): Include table of contents (default: False)
41
+ number_sections (bool): Number sections (default: False)
42
+ highlight_style (str): Code highlighting style (default: "tango")
43
+
44
+ Returns:
45
+ bool: True if conversion was successful, False otherwise
46
+ """
47
+ # Ensure output directory exists
48
+ output_path = Path(output_path)
49
+ output_path.parent.mkdir(parents=True, exist_ok=True)
50
+
51
+ # Build pandoc command with default options
52
+ cmd = [
53
+ "pandoc",
54
+ "-f",
55
+ "markdown",
56
+ "-o",
57
+ str(output_path),
58
+ "--pdf-engine=xelatex",
59
+ "--variable",
60
+ f'geometry:margin={options.get("margin", "1in")}',
61
+ "--variable",
62
+ f'fontsize={options.get("font_size", "12pt")}',
63
+ ]
64
+
65
+ # Add font only if specifically provided
66
+ if "font" in options:
67
+ cmd.extend(["--variable", f'mainfont={options["font"]}'])
68
+
69
+ # Add optional parameters
70
+ if options.get("toc", False):
71
+ cmd.append("--toc")
72
+
73
+ if options.get("number_sections", False):
74
+ cmd.append("--number-sections")
75
+
76
+ if "highlight_style" in options:
77
+ cmd.extend(["--highlight-style", options["highlight_style"]])
78
+
79
+ try:
80
+ # Run pandoc command
81
+ result = subprocess.run(
82
+ cmd,
83
+ input=self.markdown_content,
84
+ text=True,
85
+ capture_output=True,
86
+ check=True,
87
+ )
88
+ return True
89
+ except subprocess.CalledProcessError as e:
90
+ print(f"Error converting markdown to PDF: {e.stderr}")
91
+ return False
92
+
93
+ def preview(self) -> str:
94
+ """
95
+ Generate a temporary PDF and return its path.
96
+
97
+ Returns:
98
+ str: Path to the temporary PDF file
99
+ """
100
+ temp_dir = tempfile.mkdtemp()
101
+ if self.filename:
102
+ temp_pdf = os.path.join(temp_dir, f"{self.filename}.pdf")
103
+ else:
104
+ temp_pdf = os.path.join(temp_dir, "preview.pdf")
105
+
106
+ if self.convert(temp_pdf):
107
+ from edsl.scenarios.FileStore import FileStore
108
+
109
+ return FileStore(temp_pdf)
110
+
111
+ return None