edsl 0.1.39.dev1__py3-none-any.whl → 0.1.39.dev2__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 (194) hide show
  1. edsl/Base.py +169 -116
  2. edsl/__init__.py +14 -6
  3. edsl/__version__.py +1 -1
  4. edsl/agents/Agent.py +358 -146
  5. edsl/agents/AgentList.py +211 -73
  6. edsl/agents/Invigilator.py +88 -36
  7. edsl/agents/InvigilatorBase.py +59 -70
  8. edsl/agents/PromptConstructor.py +117 -219
  9. edsl/agents/QuestionInstructionPromptBuilder.py +128 -0
  10. edsl/agents/QuestionOptionProcessor.py +172 -0
  11. edsl/agents/QuestionTemplateReplacementsBuilder.py +137 -0
  12. edsl/agents/__init__.py +0 -1
  13. edsl/agents/prompt_helpers.py +3 -3
  14. edsl/config.py +22 -2
  15. edsl/conversation/car_buying.py +2 -1
  16. edsl/coop/CoopFunctionsMixin.py +15 -0
  17. edsl/coop/ExpectedParrotKeyHandler.py +125 -0
  18. edsl/coop/PriceFetcher.py +1 -1
  19. edsl/coop/coop.py +104 -42
  20. edsl/coop/utils.py +14 -14
  21. edsl/data/Cache.py +21 -14
  22. edsl/data/CacheEntry.py +12 -15
  23. edsl/data/CacheHandler.py +33 -12
  24. edsl/data/__init__.py +4 -3
  25. edsl/data_transfer_models.py +2 -1
  26. edsl/enums.py +20 -0
  27. edsl/exceptions/__init__.py +50 -50
  28. edsl/exceptions/agents.py +12 -0
  29. edsl/exceptions/inference_services.py +5 -0
  30. edsl/exceptions/questions.py +24 -6
  31. edsl/exceptions/scenarios.py +7 -0
  32. edsl/inference_services/AnthropicService.py +0 -3
  33. edsl/inference_services/AvailableModelCacheHandler.py +184 -0
  34. edsl/inference_services/AvailableModelFetcher.py +209 -0
  35. edsl/inference_services/AwsBedrock.py +0 -2
  36. edsl/inference_services/AzureAI.py +0 -2
  37. edsl/inference_services/GoogleService.py +2 -11
  38. edsl/inference_services/InferenceServiceABC.py +18 -85
  39. edsl/inference_services/InferenceServicesCollection.py +105 -80
  40. edsl/inference_services/MistralAIService.py +0 -3
  41. edsl/inference_services/OpenAIService.py +1 -4
  42. edsl/inference_services/PerplexityService.py +0 -3
  43. edsl/inference_services/ServiceAvailability.py +135 -0
  44. edsl/inference_services/TestService.py +11 -8
  45. edsl/inference_services/data_structures.py +62 -0
  46. edsl/jobs/AnswerQuestionFunctionConstructor.py +188 -0
  47. edsl/jobs/Answers.py +1 -14
  48. edsl/jobs/FetchInvigilator.py +40 -0
  49. edsl/jobs/InterviewTaskManager.py +98 -0
  50. edsl/jobs/InterviewsConstructor.py +48 -0
  51. edsl/jobs/Jobs.py +102 -243
  52. edsl/jobs/JobsChecks.py +35 -10
  53. edsl/jobs/JobsComponentConstructor.py +189 -0
  54. edsl/jobs/JobsPrompts.py +5 -3
  55. edsl/jobs/JobsRemoteInferenceHandler.py +128 -80
  56. edsl/jobs/JobsRemoteInferenceLogger.py +239 -0
  57. edsl/jobs/RequestTokenEstimator.py +30 -0
  58. edsl/jobs/buckets/BucketCollection.py +44 -3
  59. edsl/jobs/buckets/TokenBucket.py +53 -21
  60. edsl/jobs/buckets/TokenBucketAPI.py +211 -0
  61. edsl/jobs/buckets/TokenBucketClient.py +191 -0
  62. edsl/jobs/decorators.py +35 -0
  63. edsl/jobs/interviews/Interview.py +77 -380
  64. edsl/jobs/jobs_status_enums.py +9 -0
  65. edsl/jobs/loggers/HTMLTableJobLogger.py +304 -0
  66. edsl/jobs/runners/JobsRunnerAsyncio.py +4 -49
  67. edsl/jobs/tasks/QuestionTaskCreator.py +21 -19
  68. edsl/jobs/tasks/TaskHistory.py +14 -15
  69. edsl/jobs/tasks/task_status_enum.py +0 -2
  70. edsl/language_models/ComputeCost.py +63 -0
  71. edsl/language_models/LanguageModel.py +137 -234
  72. edsl/language_models/ModelList.py +11 -13
  73. edsl/language_models/PriceManager.py +127 -0
  74. edsl/language_models/RawResponseHandler.py +106 -0
  75. edsl/language_models/ServiceDataSources.py +0 -0
  76. edsl/language_models/__init__.py +0 -1
  77. edsl/language_models/key_management/KeyLookup.py +63 -0
  78. edsl/language_models/key_management/KeyLookupBuilder.py +273 -0
  79. edsl/language_models/key_management/KeyLookupCollection.py +38 -0
  80. edsl/language_models/key_management/__init__.py +0 -0
  81. edsl/language_models/key_management/models.py +131 -0
  82. edsl/language_models/registry.py +49 -59
  83. edsl/language_models/repair.py +2 -2
  84. edsl/language_models/utilities.py +5 -4
  85. edsl/notebooks/Notebook.py +19 -14
  86. edsl/notebooks/NotebookToLaTeX.py +142 -0
  87. edsl/prompts/Prompt.py +29 -39
  88. edsl/questions/AnswerValidatorMixin.py +47 -2
  89. edsl/questions/ExceptionExplainer.py +77 -0
  90. edsl/questions/HTMLQuestion.py +103 -0
  91. edsl/questions/LoopProcessor.py +149 -0
  92. edsl/questions/QuestionBase.py +37 -192
  93. edsl/questions/QuestionBaseGenMixin.py +52 -48
  94. edsl/questions/QuestionBasePromptsMixin.py +7 -3
  95. edsl/questions/QuestionCheckBox.py +1 -1
  96. edsl/questions/QuestionExtract.py +1 -1
  97. edsl/questions/QuestionFreeText.py +1 -2
  98. edsl/questions/QuestionList.py +3 -5
  99. edsl/questions/QuestionMatrix.py +265 -0
  100. edsl/questions/QuestionMultipleChoice.py +66 -22
  101. edsl/questions/QuestionNumerical.py +1 -3
  102. edsl/questions/QuestionRank.py +6 -16
  103. edsl/questions/ResponseValidatorABC.py +37 -11
  104. edsl/questions/ResponseValidatorFactory.py +28 -0
  105. edsl/questions/SimpleAskMixin.py +4 -3
  106. edsl/questions/__init__.py +1 -0
  107. edsl/questions/derived/QuestionLinearScale.py +6 -3
  108. edsl/questions/derived/QuestionTopK.py +1 -1
  109. edsl/questions/descriptors.py +17 -3
  110. edsl/questions/question_registry.py +1 -1
  111. edsl/questions/templates/matrix/__init__.py +1 -0
  112. edsl/questions/templates/matrix/answering_instructions.jinja +5 -0
  113. edsl/questions/templates/matrix/question_presentation.jinja +20 -0
  114. edsl/results/CSSParameterizer.py +1 -1
  115. edsl/results/Dataset.py +170 -7
  116. edsl/results/DatasetExportMixin.py +224 -302
  117. edsl/results/DatasetTree.py +28 -8
  118. edsl/results/MarkdownToDocx.py +122 -0
  119. edsl/results/MarkdownToPDF.py +111 -0
  120. edsl/results/Result.py +192 -206
  121. edsl/results/Results.py +120 -113
  122. edsl/results/ResultsExportMixin.py +2 -0
  123. edsl/results/Selector.py +23 -13
  124. edsl/results/TableDisplay.py +98 -171
  125. edsl/results/TextEditor.py +50 -0
  126. edsl/results/__init__.py +1 -1
  127. edsl/results/smart_objects.py +96 -0
  128. edsl/results/table_data_class.py +12 -0
  129. edsl/results/table_renderers.py +118 -0
  130. edsl/scenarios/ConstructDownloadLink.py +109 -0
  131. edsl/scenarios/DirectoryScanner.py +96 -0
  132. edsl/scenarios/DocumentChunker.py +102 -0
  133. edsl/scenarios/DocxScenario.py +16 -0
  134. edsl/scenarios/FileStore.py +118 -239
  135. edsl/scenarios/PdfExtractor.py +40 -0
  136. edsl/scenarios/Scenario.py +90 -193
  137. edsl/scenarios/ScenarioHtmlMixin.py +4 -3
  138. edsl/scenarios/ScenarioJoin.py +10 -6
  139. edsl/scenarios/ScenarioList.py +383 -240
  140. edsl/scenarios/ScenarioListExportMixin.py +0 -7
  141. edsl/scenarios/ScenarioListPdfMixin.py +15 -37
  142. edsl/scenarios/ScenarioSelector.py +156 -0
  143. edsl/scenarios/__init__.py +1 -2
  144. edsl/scenarios/file_methods.py +85 -0
  145. edsl/scenarios/handlers/__init__.py +13 -0
  146. edsl/scenarios/handlers/csv.py +38 -0
  147. edsl/scenarios/handlers/docx.py +76 -0
  148. edsl/scenarios/handlers/html.py +37 -0
  149. edsl/scenarios/handlers/json.py +111 -0
  150. edsl/scenarios/handlers/latex.py +5 -0
  151. edsl/scenarios/handlers/md.py +51 -0
  152. edsl/scenarios/handlers/pdf.py +68 -0
  153. edsl/scenarios/handlers/png.py +39 -0
  154. edsl/scenarios/handlers/pptx.py +105 -0
  155. edsl/scenarios/handlers/py.py +294 -0
  156. edsl/scenarios/handlers/sql.py +313 -0
  157. edsl/scenarios/handlers/sqlite.py +149 -0
  158. edsl/scenarios/handlers/txt.py +33 -0
  159. edsl/study/ObjectEntry.py +1 -1
  160. edsl/study/SnapShot.py +1 -1
  161. edsl/study/Study.py +5 -12
  162. edsl/surveys/ConstructDAG.py +92 -0
  163. edsl/surveys/EditSurvey.py +221 -0
  164. edsl/surveys/InstructionHandler.py +100 -0
  165. edsl/surveys/MemoryManagement.py +72 -0
  166. edsl/surveys/Rule.py +5 -4
  167. edsl/surveys/RuleCollection.py +25 -27
  168. edsl/surveys/RuleManager.py +172 -0
  169. edsl/surveys/Simulator.py +75 -0
  170. edsl/surveys/Survey.py +199 -771
  171. edsl/surveys/SurveyCSS.py +20 -8
  172. edsl/surveys/{SurveyFlowVisualizationMixin.py → SurveyFlowVisualization.py} +11 -9
  173. edsl/surveys/SurveyToApp.py +141 -0
  174. edsl/surveys/__init__.py +4 -2
  175. edsl/surveys/descriptors.py +6 -2
  176. edsl/surveys/instructions/ChangeInstruction.py +1 -2
  177. edsl/surveys/instructions/Instruction.py +4 -13
  178. edsl/surveys/instructions/InstructionCollection.py +11 -6
  179. edsl/templates/error_reporting/interview_details.html +1 -1
  180. edsl/templates/error_reporting/report.html +1 -1
  181. edsl/tools/plotting.py +1 -1
  182. edsl/utilities/PrettyList.py +56 -0
  183. edsl/utilities/is_notebook.py +18 -0
  184. edsl/utilities/is_valid_variable_name.py +11 -0
  185. edsl/utilities/remove_edsl_version.py +24 -0
  186. edsl/utilities/utilities.py +35 -23
  187. {edsl-0.1.39.dev1.dist-info → edsl-0.1.39.dev2.dist-info}/METADATA +12 -10
  188. edsl-0.1.39.dev2.dist-info/RECORD +352 -0
  189. edsl/language_models/KeyLookup.py +0 -30
  190. edsl/language_models/unused/ReplicateBase.py +0 -83
  191. edsl/results/ResultsDBMixin.py +0 -238
  192. edsl-0.1.39.dev1.dist-info/RECORD +0 -277
  193. {edsl-0.1.39.dev1.dist-info → edsl-0.1.39.dev2.dist-info}/LICENSE +0 -0
  194. {edsl-0.1.39.dev1.dist-info → edsl-0.1.39.dev2.dist-info}/WHEEL +0 -0
@@ -1,8 +1,4 @@
1
1
  from typing import Dict, List, Any, Optional, List
2
- from docx import Document
3
- from docx.shared import Inches, Pt
4
- from docx.enum.text import WD_ALIGN_PARAGRAPH
5
- from docx.enum.style import WD_STYLE_TYPE
6
2
 
7
3
 
8
4
  def is_hashable(v):
@@ -98,6 +94,11 @@ class Tree:
98
94
  if filename is None:
99
95
  filename = "tree_structure.docx"
100
96
 
97
+ from docx import Document
98
+ from docx.shared import Inches, Pt
99
+ from docx.enum.text import WD_ALIGN_PARAGRAPH
100
+ from docx.enum.style import WD_STYLE_TYPE
101
+
101
102
  doc = Document()
102
103
 
103
104
  # Create styles for headings
@@ -115,10 +116,29 @@ class Tree:
115
116
  body_style.font.size = Pt(11)
116
117
 
117
118
  self._add_to_docx(doc, self.root, 0)
118
- doc.save(filename)
119
- from edsl.utilities.utilities import file_notice
120
-
121
- file_notice(filename)
119
+ import base64
120
+ from io import BytesIO
121
+ import base64
122
+
123
+ # Save document to bytes buffer
124
+ doc_buffer = BytesIO()
125
+ doc.save(doc_buffer)
126
+ doc_buffer.seek(0)
127
+
128
+ base64_string = base64.b64encode(doc_buffer.getvalue()).decode("utf-8")
129
+ from edsl.scenarios.FileStore import FileStore
130
+
131
+ # Create and return FileStore instance
132
+ return FileStore(
133
+ path="tree_structure.docx", # Default name
134
+ mime_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
135
+ binary=True,
136
+ suffix="docx",
137
+ base64_string=base64_string,
138
+ )
139
+ # doc.save(filename)
140
+ # from edsl.utilities.utilities import file_notice
141
+ # file_notice(filename)
122
142
 
123
143
  def _repr_html_(self):
124
144
  """Returns an interactive HTML representation of the tree with collapsible sections."""
@@ -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