edsl 0.1.46__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 (328) 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 +430 -113
  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/dataset/dataset_operations_mixin.py +1492 -0
  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} +12 -12
  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} +321 -155
  104. edsl/jobs/{JobsChecks.py → jobs_checks.py} +15 -7
  105. edsl/jobs/{JobsComponentConstructor.py → jobs_component_constructor.py} +20 -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 +10 -16
  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} +420 -216
  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/file_store.py +755 -0
  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} +424 -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 +20 -21
  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.46.dist-info → edsl-0.1.48.dist-info}/METADATA +3 -2
  230. edsl-0.1.48.dist-info/RECORD +347 -0
  231. edsl/Base.py +0 -426
  232. edsl/BaseDiff.py +0 -260
  233. edsl/agents/InvigilatorBase.py +0 -260
  234. edsl/agents/PromptConstructor.py +0 -318
  235. edsl/auto/AutoStudy.py +0 -130
  236. edsl/auto/StageBase.py +0 -243
  237. edsl/auto/StageGenerateSurvey.py +0 -178
  238. edsl/auto/StageLabelQuestions.py +0 -125
  239. edsl/auto/StagePersona.py +0 -61
  240. edsl/auto/StagePersonaDimensionValueRanges.py +0 -88
  241. edsl/auto/StagePersonaDimensionValues.py +0 -74
  242. edsl/auto/StagePersonaDimensions.py +0 -69
  243. edsl/auto/StageQuestions.py +0 -74
  244. edsl/auto/SurveyCreatorPipeline.py +0 -21
  245. edsl/auto/utilities.py +0 -218
  246. edsl/base/Base.py +0 -279
  247. edsl/coop/PriceFetcher.py +0 -54
  248. edsl/data/Cache.py +0 -580
  249. edsl/data/CacheEntry.py +0 -230
  250. edsl/data/SQLiteDict.py +0 -292
  251. edsl/data/__init__.py +0 -5
  252. edsl/data/orm.py +0 -10
  253. edsl/exceptions/cache.py +0 -5
  254. edsl/exceptions/coop.py +0 -14
  255. edsl/exceptions/data.py +0 -14
  256. edsl/exceptions/scenarios.py +0 -29
  257. edsl/jobs/Answers.py +0 -43
  258. edsl/jobs/JobsPrompts.py +0 -354
  259. edsl/jobs/buckets/BucketCollection.py +0 -134
  260. edsl/jobs/buckets/ModelBuckets.py +0 -65
  261. edsl/jobs/buckets/TokenBucket.py +0 -283
  262. edsl/jobs/buckets/TokenBucketClient.py +0 -191
  263. edsl/jobs/interviews/Interview.py +0 -395
  264. edsl/jobs/interviews/InterviewExceptionCollection.py +0 -99
  265. edsl/jobs/interviews/InterviewStatisticsCollection.py +0 -25
  266. edsl/jobs/runners/JobsRunnerAsyncio.py +0 -163
  267. edsl/jobs/runners/JobsRunnerStatusData.py +0 -0
  268. edsl/jobs/tasks/TaskCreators.py +0 -64
  269. edsl/jobs/tasks/TaskStatusLog.py +0 -23
  270. edsl/jobs/tokens/InterviewTokenUsage.py +0 -27
  271. edsl/language_models/LanguageModel.py +0 -635
  272. edsl/language_models/ServiceDataSources.py +0 -0
  273. edsl/language_models/key_management/KeyLookup.py +0 -63
  274. edsl/language_models/key_management/KeyLookupCollection.py +0 -38
  275. edsl/language_models/key_management/models.py +0 -137
  276. edsl/questions/QuestionBase.py +0 -539
  277. edsl/questions/QuestionFreeText.py +0 -130
  278. edsl/questions/derived/QuestionLikertFive.py +0 -76
  279. edsl/results/DatasetExportMixin.py +0 -911
  280. edsl/results/ResultsExportMixin.py +0 -45
  281. edsl/results/TextEditor.py +0 -50
  282. edsl/results/results_fetch_mixin.py +0 -33
  283. edsl/results/results_tools_mixin.py +0 -98
  284. edsl/scenarios/DocumentChunker.py +0 -104
  285. edsl/scenarios/FileStore.py +0 -564
  286. edsl/scenarios/Scenario.py +0 -548
  287. edsl/scenarios/ScenarioHtmlMixin.py +0 -65
  288. edsl/scenarios/ScenarioListExportMixin.py +0 -45
  289. edsl/scenarios/handlers/latex.py +0 -5
  290. edsl/shared.py +0 -1
  291. edsl/surveys/Survey.py +0 -1306
  292. edsl/surveys/SurveyQualtricsImport.py +0 -284
  293. edsl/surveys/SurveyToApp.py +0 -141
  294. edsl/surveys/instructions/__init__.py +0 -0
  295. edsl/tools/__init__.py +0 -1
  296. edsl/tools/clusters.py +0 -192
  297. edsl/tools/embeddings.py +0 -27
  298. edsl/tools/embeddings_plotting.py +0 -118
  299. edsl/tools/plotting.py +0 -112
  300. edsl/tools/summarize.py +0 -18
  301. edsl/utilities/data/Registry.py +0 -6
  302. edsl/utilities/data/__init__.py +0 -1
  303. edsl/utilities/data/scooter_results.json +0 -1
  304. edsl-0.1.46.dist-info/RECORD +0 -366
  305. /edsl/coop/{CoopFunctionsMixin.py → coop_functions.py} +0 -0
  306. /edsl/{results → dataset/display}/CSSParameterizer.py +0 -0
  307. /edsl/{language_models/key_management → dataset/display}/__init__.py +0 -0
  308. /edsl/{results → dataset/display}/table_data_class.py +0 -0
  309. /edsl/{results → dataset/display}/table_display.css +0 -0
  310. /edsl/{results/ResultsGGMixin.py → dataset/r/ggplot.py} +0 -0
  311. /edsl/{results → dataset}/tree_explore.py +0 -0
  312. /edsl/{surveys/instructions/ChangeInstruction.py → instructions/change_instruction.py} +0 -0
  313. /edsl/{jobs/interviews → interviews}/interview_status_enum.py +0 -0
  314. /edsl/jobs/{runners/JobsRunnerStatus.py → jobs_runner_status.py} +0 -0
  315. /edsl/language_models/{PriceManager.py → price_manager.py} +0 -0
  316. /edsl/language_models/{fake_openai_call.py → unused/fake_openai_call.py} +0 -0
  317. /edsl/language_models/{fake_openai_service.py → unused/fake_openai_service.py} +0 -0
  318. /edsl/notebooks/{NotebookToLaTeX.py → notebook_to_latex.py} +0 -0
  319. /edsl/{exceptions/questions.py → questions/exceptions.py} +0 -0
  320. /edsl/questions/{SimpleAskMixin.py → simple_ask_mixin.py} +0 -0
  321. /edsl/surveys/{Memory.py → memory/memory.py} +0 -0
  322. /edsl/surveys/{MemoryManagement.py → memory/memory_management.py} +0 -0
  323. /edsl/surveys/{SurveyCSS.py → survey_css.py} +0 -0
  324. /edsl/{jobs/tokens/TokenUsage.py → tokens/token_usage.py} +0 -0
  325. /edsl/{results/MarkdownToDocx.py → utilities/markdown_to_docx.py} +0 -0
  326. /edsl/{TemplateLoader.py → utilities/template_loader.py} +0 -0
  327. {edsl-0.1.46.dist-info → edsl-0.1.48.dist-info}/LICENSE +0 -0
  328. {edsl-0.1.46.dist-info → edsl-0.1.48.dist-info}/WHEEL +0 -0
@@ -136,9 +136,6 @@ class Tree:
136
136
  suffix="docx",
137
137
  base64_string=base64_string,
138
138
  )
139
- # doc.save(filename)
140
- # from edsl.utilities.utilities import file_notice
141
- # file_notice(filename)
142
139
 
143
140
  def _repr_html_(self):
144
141
  """Returns an interactive HTML representation of the tree with collapsible sections."""
@@ -187,8 +184,8 @@ class Tree:
187
184
  content_html = "".join(content)
188
185
 
189
186
  if node.children:
190
- # Node with children
191
- html.append(f'<details {"open" if level < 1 else ""}>')
187
+ # Node with children - removed the "open" condition to keep all nodes closed by default
188
+ html.append("<details>")
192
189
  html.append(f"<summary>{content_html}</summary>")
193
190
  for child in node.children.values():
194
191
  html.append(node_to_html(child, level + 1, print_keys))
@@ -207,40 +204,6 @@ class Tree:
207
204
  tree_html = node_to_html(self.root)
208
205
  return f"{styles}{tree_html}</div>"
209
206
 
210
- # def _repr_html_(self):
211
- # """Returns an HTML representation of the tree, following the same logic as print_tree."""
212
- # styles = """
213
- # <style>
214
- # .tree-container {
215
- # font-family: monospace;
216
- # white-space: pre;
217
- # margin: 10px;
218
- # }
219
- # </style>
220
- # """
221
-
222
- # def node_to_html(node, level=0, print_keys=False):
223
- # if node is None:
224
- # node = self.root
225
- # if node is None:
226
- # return "Tree has not been constructed yet."
227
-
228
- # html = []
229
- # if node.value is not None:
230
- # indent = "&nbsp;" * 2 * level # Using &nbsp; for HTML spaces
231
- # if print_keys and node.key is not None:
232
- # html.append(f"{indent}{node.key}: {node.value}<br>")
233
- # else:
234
- # html.append(f"{indent}{node.value}<br>")
235
-
236
- # for child in node.children.values():
237
- # html.append(node_to_html(child, level + 1, print_keys))
238
-
239
- # return "".join(html)
240
-
241
- # tree_html = node_to_html(self.root)
242
- # return f'<div class="tree-container">{tree_html}</div>{styles}'
243
-
244
207
  def _add_to_docx(self, doc, node: TreeNode, level: int):
245
208
  if node.value is not None:
246
209
  if level == 0:
@@ -256,40 +219,158 @@ class Tree:
256
219
  for child in node.children.values():
257
220
  self._add_to_docx(doc, child, level + 1)
258
221
 
222
+ def to_dict(self, node: Optional[TreeNode] = None) -> tuple[dict, list[str]]:
223
+ """Converts the tree structure into a nested dictionary and returns the schema.
224
+
225
+ Args:
226
+ node: The current node being processed. Defaults to the root node.
227
+
228
+ Returns:
229
+ A tuple of (nested_dict, schema) where:
230
+ - nested_dict: The hierarchical data structure
231
+ - schema: List of keys in order of hierarchy
232
+
233
+ Examples:
234
+ >>> tree = Tree.example()
235
+ >>> result, schema = tree.to_dict()
236
+ >>> print(schema) # Shows the hierarchy of the data
237
+ ['continent', 'country', 'city', 'population']
238
+ >>> # Access a leaf node value (note: numbers are converted to strings)
239
+ >>> print(result['North America']['US']['New York']['8419000'] is None)
240
+ True
241
+ >>> # Verify the structure is correct
242
+ >>> print(sorted(result['North America'].keys()))
243
+ ['Canada', 'US']
244
+ """
245
+ if node is None:
246
+ node = self.root
247
+ if node is None:
248
+ return {}, []
249
+
250
+ result = {}
251
+ for value, child in node.children.items():
252
+ if child.children:
253
+ nested_dict, _ = self.to_dict(child) # Always unpack tuple, ignore schema except at root
254
+ result[value] = nested_dict
255
+ else:
256
+ result[value] = None
257
+
258
+ # Only return the schema with the root call
259
+ if node == self.root:
260
+ return result, self.node_order if self.node_order else []
261
+ return result, [] # Return empty schema for non-root nodes
262
+
263
+ @classmethod
264
+ def example(cls) -> "Tree":
265
+ """Creates an example Tree instance with geographic data.
266
+
267
+ Returns:
268
+ Tree: A sample tree with continent/country/city/population data
269
+
270
+ Examples:
271
+ >>> tree = Tree.example()
272
+ >>> result, schema = tree.to_dict()
273
+ >>> print(schema)
274
+ ['continent', 'country', 'city', 'population']
275
+ >>> # Verify the structure is correct
276
+ >>> print(sorted(result['North America'].keys()))
277
+ ['Canada', 'US']
278
+ """
279
+ from .dataset import Dataset
280
+
281
+ data = Dataset([
282
+ {"continent": ["North America", "Asia", "Europe", "North America", "Asia"]},
283
+ {"country": ["US", "China", "France", "Canada", "Japan"]},
284
+ {"city": ["New York", "Beijing", "Paris", "Toronto", "Tokyo"]},
285
+ {"population": ["8419000", "21540000", "2161000", "2930000", "13960000"]}, # Convert to strings
286
+ ])
287
+
288
+ node_order = ["continent", "country", "city", "population"]
289
+ tree = cls(data, node_order=node_order) # Explicitly pass node_order
290
+ return tree
291
+
292
+ @staticmethod
293
+ def _adjust_markdown_levels(text: str, base_level: int) -> str:
294
+ """Adjusts markdown heading levels by adding or removing '#' characters.
295
+
296
+ Args:
297
+ text: The markdown text to adjust
298
+ base_level: The level to adjust headings to (e.g., 2 means h2)
299
+
300
+ Returns:
301
+ Adjusted markdown text with updated heading levels
302
+
303
+ Examples:
304
+ >>> text = "# Title\\n## Subtitle\\nContent"
305
+ >>> print(Tree._adjust_markdown_levels(text, 2))
306
+ ## Title
307
+ ### Subtitle
308
+ Content
309
+ """
310
+ lines = []
311
+ for line in text.split('\n'):
312
+ if line.strip().startswith('#'):
313
+ # Count leading '#' characters
314
+ heading_level = len(line) - len(line.lstrip('#'))
315
+ # Adjust the heading level by adding base_level - 1
316
+ new_level = heading_level + (base_level - 1)
317
+ # Replace the original heading markers with the new level
318
+ lines.append('#' * new_level + line[heading_level:])
319
+ else:
320
+ lines.append(line)
321
+ return '\n'.join(lines)
322
+
323
+ def report(self, node: Optional[TreeNode] = None, level: int = 1, render: bool = True) -> str:
324
+ """Generates a markdown document representing the tree structure.
325
+
326
+ Args:
327
+ node: The current node being processed. Defaults to the root node.
328
+ level: Current heading level (h1-h6). Defaults to 1.
329
+ render: Whether to render the markdown in notebooks. Defaults to True.
330
+
331
+ Returns:
332
+ A string containing the markdown document, or renders markdown in notebooks.
333
+ """
334
+ from edsl.utilities.utilities import is_notebook
335
+ from IPython.display import Markdown, display
336
+
337
+ if node is None:
338
+ node = self.root
339
+ if node is None:
340
+ return "Tree has not been constructed yet."
259
341
 
260
- # Example usage (commented out)
261
- """
262
- from edsl.results.Dataset import Dataset
263
-
264
- data = Dataset(
265
- [
266
- {"continent": ["North America", "Asia", "Europe", "North America", "Asia"]},
267
- {"country": ["US", "China", "France", "Canada", "Japan"]},
268
- {"city": ["New York", "Beijing", "Paris", "Toronto", "Tokyo"]},
269
- {"population": [8419000, 21540000, 2161000, 2930000, 13960000]},
270
- ]
271
- )
272
-
273
- tree = Tree(data)
274
-
275
- try:
276
- tree.construct_tree(["continent", "country", "city", "population"])
277
- print("Tree without key names:")
278
- tree.print_tree()
279
- print("\nTree with key names:")
280
- tree.print_tree(print_keys=True)
281
- except ValueError as e:
282
- print(f"Error: {e}")
283
-
284
- # Demonstrating validation
285
- try:
286
- tree.construct_tree(["continent", "country", "invalid_key"])
287
- except ValueError as e:
288
- print(f"\nValidation Error: {e}")
289
-
290
- tree = Tree(data)
291
- tree.construct_tree(["continent", "country", "city", "population"])
292
- tree.print_tree(print_keys=True)
293
- tree.to_docx("tree_structure.docx")
294
- print("DocX file 'tree_structure.docx' has been created.")
295
- """
342
+ lines = []
343
+
344
+ # Process current node
345
+ if node != self.root: # Skip the root node as it has no value
346
+ if isinstance(node.value, str) and node.value.startswith('#'):
347
+ # If the value is markdown, adjust its heading levels
348
+ adjusted_markdown = self._adjust_markdown_levels(node.value, level)
349
+ lines.append(adjusted_markdown)
350
+ elif node.children: # Non-leaf nodes get headings
351
+ # Ensure we don't exceed h6
352
+ heading_level = min(level, 6)
353
+ lines.append(f"{'#' * heading_level} {node.key.title()}: {node.value}")
354
+ else: # Leaf nodes get regular text
355
+ lines.append(f"{node.key.title()}: {node.value}")
356
+
357
+ # Process children in sorted order for consistent output
358
+ for value in sorted(node.children.keys()):
359
+ child = node.children[value]
360
+ lines.append(self.report(child, level + 1, render=False)) # Don't render recursive calls
361
+
362
+ markdown_text = "\n".join(lines)
363
+
364
+ # Only attempt to render at the top level call
365
+ if node == self.root and render and is_notebook():
366
+ display(Markdown(markdown_text))
367
+ return "" # Return empty string since we've displayed the content
368
+
369
+ return markdown_text
370
+
371
+
372
+ if __name__ == "__main__":
373
+ #tree = Tree.example()
374
+ #print(tree.to_dict())
375
+ import doctest
376
+ doctest.testmod()
@@ -10,15 +10,15 @@ from typing import (
10
10
  )
11
11
 
12
12
  if TYPE_CHECKING:
13
- from edsl.results.Dataset import Dataset
13
+ from ..dataset import Dataset
14
14
 
15
- from edsl.results.table_data_class import TableData
15
+ from .table_data_class import TableData
16
16
 
17
- from edsl.results.table_renderers import DataTablesRenderer, PandasStyleRenderer
17
+ from .table_renderers import DataTablesRenderer, PandasStyleRenderer, RichRenderer
18
18
 
19
19
  Row = Sequence[Union[str, int, float, bool, None]]
20
20
  TableFormat = Literal[
21
- "grid", "simple", "pipe", "orgtbl", "rst", "mediawiki", "html", "latex"
21
+ "grid", "simple", "pipe", "orgtbl", "rst", "mediawiki", "html", "latex", "rich"
22
22
  ]
23
23
 
24
24
 
@@ -66,9 +66,20 @@ class TableDisplay:
66
66
  return self.renderer_class(table_data).render_html()
67
67
 
68
68
  def __repr__(self):
69
- from tabulate import tabulate
70
-
71
- return tabulate(self.data, headers=self.headers, tablefmt=self.tablefmt)
69
+ # If rich format is requested, use RichRenderer
70
+ if self.tablefmt == "rich":
71
+ table_data = TableData(
72
+ headers=self.headers,
73
+ data=self.data,
74
+ parameters=self.printing_parameters,
75
+ raw_data_set=self.raw_data_set,
76
+ )
77
+ RichRenderer(table_data).render_terminal()
78
+ return "" # Return empty string since the table is already printed
79
+ else:
80
+ # Fall back to tabulate for other formats
81
+ from tabulate import tabulate
82
+ return tabulate(self.data, headers=self.headers, tablefmt=self.tablefmt)
72
83
 
73
84
  @classmethod
74
85
  def from_dictionary(
@@ -1,6 +1,7 @@
1
1
  from abc import ABC, abstractmethod
2
- from edsl.results.table_data_class import TableData
3
-
2
+ import os
3
+ from pathlib import Path
4
+ from .table_data_class import TableData
4
5
 
5
6
  class DataTablesRendererABC(ABC):
6
7
  def __init__(self, table_data: TableData):
@@ -116,3 +117,58 @@ class PandasStyleRenderer(DataTablesRendererABC):
116
117
  @classmethod
117
118
  def get_css(cls) -> str:
118
119
  return "" # Pandas styling handles its own CSS
120
+
121
+
122
+ class RichRenderer(DataTablesRendererABC):
123
+ """Rich-based terminal renderer implementation"""
124
+
125
+ def render_html(self) -> str:
126
+ """
127
+ This method is required by the ABC but is not the primary function
128
+ for this renderer. The render_terminal method below is what's used.
129
+ """
130
+ # Provide a basic HTML fallback for HTML contexts
131
+ html = "<table border='1'><thead><tr>"
132
+ html += "".join(f"<th>{header}</th>" for header in self.table_data.headers)
133
+ html += "</tr></thead><tbody>"
134
+
135
+ for row in self.table_data.data:
136
+ html += "<tr>"
137
+ html += "".join(f"<td>{cell}</td>" for cell in row)
138
+ html += "</tr>"
139
+ html += "</tbody></table>"
140
+
141
+ return html
142
+
143
+ def render_terminal(self) -> None:
144
+ """
145
+ Render the table to the terminal using Rich Console and Table
146
+
147
+ This is the primary rendering method for this renderer.
148
+ """
149
+ try:
150
+ from rich.console import Console
151
+ from rich.table import Table
152
+
153
+ # Create a table with the headers
154
+ table = Table(show_header=True, header_style="bold")
155
+
156
+ # Add columns with headers
157
+ for header in self.table_data.headers:
158
+ table.add_column(str(header))
159
+
160
+ # Add rows
161
+ for row in self.table_data.data:
162
+ # Convert all values to strings and handle None
163
+ str_row = [str(cell) if cell is not None else "" for cell in row]
164
+ table.add_row(*str_row)
165
+
166
+ # Create a console and print the table
167
+ console = Console()
168
+ console.print(table)
169
+
170
+ except ImportError:
171
+ # Fallback if rich is not installed
172
+ print("Rich package is not installed. Install with 'pip install rich'")
173
+ from tabulate import tabulate
174
+ print(tabulate(self.table_data.data, headers=self.table_data.headers, tablefmt="grid"))
@@ -3,9 +3,6 @@ import io
3
3
  import csv
4
4
  import base64
5
5
  from typing import Optional, Union, Tuple, List, Any, Dict
6
- from openpyxl import Workbook
7
-
8
- from edsl.scenarios.FileStore import FileStore
9
6
 
10
7
 
11
8
  class FileExport(ABC):
@@ -47,7 +44,7 @@ class FileExport(ABC):
47
44
  else:
48
45
  base64_string = base64.b64encode(data).decode()
49
46
 
50
- from edsl.scenarios.FileStore import FileStore
47
+ from edsl.scenarios import FileStore
51
48
 
52
49
  path = self.filename or self._get_default_filename()
53
50
 
@@ -93,7 +90,7 @@ class TabularExport(FileExport, ABC):
93
90
 
94
91
  def __init__(self, *args, **kwargs):
95
92
  super().__init__(*args, **kwargs)
96
- self.header, self.rows = self.data._get_tabular_data(
93
+ self.header, self.rows = self.data.get_tabular_data(
97
94
  remove_prefix=self.remove_prefix, pretty_labels=self.pretty_labels
98
95
  )
99
96
 
@@ -121,6 +118,8 @@ class ExcelExport(TabularExport):
121
118
  self.sheet_name = sheet_name or "Results"
122
119
 
123
120
  def format_data(self) -> bytes:
121
+ from openpyxl import Workbook
122
+
124
123
  wb = Workbook()
125
124
  ws = wb.active
126
125
  ws.title = self.sheet_name
@@ -35,13 +35,13 @@ class SmartStr(str):
35
35
 
36
36
  def pdf(self, filename: Optional[str] = None): # Markdown will have this as well
37
37
  # renders the markdown as a pdf that can be downloaded
38
- from edsl.results.MarkdownToPDF import MarkdownToPDF
38
+ from ..utilities.markdown_to_pdf import MarkdownToPDF
39
39
 
40
40
  return MarkdownToPDF(self, filename).preview()
41
41
 
42
42
  def docx(self, filename: Optional[str] = None):
43
43
  # renders the markdown as a docx that can be downloaded
44
- from edsl.results.MarkdownToDocx import MarkdownToDocx
44
+ from ..utilities.markdown_to_docx import MarkdownToDocx
45
45
 
46
46
  return MarkdownToDocx(self, filename).preview()
47
47
 
edsl/enums.py CHANGED
@@ -1,207 +1,7 @@
1
- """Enums for the different types of questions, language models, and inference services."""
1
+ """Enums module wrapper for backward compatibility.
2
2
 
3
- from enum import Enum
4
- from typing import Literal
3
+ This module re-exports everything from the edsl.base.enums module.
4
+ """
5
5
 
6
-
7
- class EnumWithChecks(Enum):
8
- """Base class for all enums with checks."""
9
-
10
- @classmethod
11
- def is_value_valid(cls, value):
12
- """Check if the value is valid."""
13
- return any(value == item.value for item in cls)
14
-
15
-
16
- class QuestionType(EnumWithChecks):
17
- """Enum for the question types."""
18
-
19
- MULTIPLE_CHOICE = "multiple_choice"
20
- YES_NO = "yes_no"
21
- FREE_TEXT = "free_text"
22
- RANK = "rank"
23
- BUDGET = "budget"
24
- CHECKBOX = "checkbox"
25
- EXTRACT = "extract"
26
- FUNCTIONAL = "functional"
27
- LIST = "list"
28
- NUMERICAL = "numerical"
29
- TOP_K = "top_k"
30
- LIKERT_FIVE = "likert_five"
31
- LINEAR_SCALE = "linear_scale"
32
-
33
-
34
- # https://huggingface.co/meta-llama/Llama-2-70b-chat-hf
35
-
36
-
37
- # class LanguageModelType(EnumWithChecks):
38
- # """Enum for the language model types."""
39
-
40
- # GPT_4 = "gpt-4-1106-preview"
41
- # GPT_3_5_Turbo = "gpt-3.5-turbo"
42
- # LLAMA_2_70B_CHAT_HF = "llama-2-70b-chat-hf"
43
- # LLAMA_2_13B_CHAT_HF = "llama-2-13b-chat-hf"
44
- # GEMINI_PRO = "gemini_pro"
45
- # MIXTRAL_8x7B_INSTRUCT = "mixtral-8x7B-instruct-v0.1"
46
- # TEST = "test"
47
- # ANTHROPIC_3_OPUS = "claude-3-opus-20240229"
48
- # ANTHROPIC_3_SONNET = "claude-3-sonnet-20240229"
49
- # ANTHROPIC_3_HAIKU = "claude-3-haiku-20240307"
50
- # DBRX_INSTRUCT = "dbrx-instruct"
51
-
52
-
53
- class InferenceServiceType(EnumWithChecks):
54
- """Enum for the inference service types."""
55
-
56
- BEDROCK = "bedrock"
57
- DEEP_INFRA = "deep_infra"
58
- REPLICATE = "replicate"
59
- OPENAI = "openai"
60
- GOOGLE = "google"
61
- TEST = "test"
62
- ANTHROPIC = "anthropic"
63
- GROQ = "groq"
64
- AZURE = "azure"
65
- OLLAMA = "ollama"
66
- MISTRAL = "mistral"
67
- TOGETHER = "together"
68
- PERPLEXITY = "perplexity"
69
- DEEPSEEK = "deepseek"
70
- XAI = "xai"
71
-
72
-
73
- # unavoidable violation of the DRY principle but it is necessary
74
- # checked w/ a unit test to make sure consistent with services in enums.py
75
- InferenceServiceLiteral = Literal[
76
- "bedrock",
77
- "deep_infra",
78
- "replicate",
79
- "openai",
80
- "google",
81
- "test",
82
- "anthropic",
83
- "groq",
84
- "azure",
85
- "ollama",
86
- "mistral",
87
- "together",
88
- "perplexity",
89
- "deepseek",
90
- "xai",
91
- ]
92
-
93
- available_models_urls = {
94
- "anthropic": "https://docs.anthropic.com/en/docs/about-claude/models",
95
- "openai": "https://platform.openai.com/docs/models/gp",
96
- "groq": "https://console.groq.com/docs/models",
97
- "google": "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models",
98
- }
99
-
100
-
101
- service_to_api_keyname = {
102
- InferenceServiceType.DEEP_INFRA.value: "DEEP_INFRA_API_KEY",
103
- InferenceServiceType.REPLICATE.value: "TBD",
104
- InferenceServiceType.OPENAI.value: "OPENAI_API_KEY",
105
- InferenceServiceType.GOOGLE.value: "GOOGLE_API_KEY",
106
- InferenceServiceType.TEST.value: "TBD",
107
- InferenceServiceType.ANTHROPIC.value: "ANTHROPIC_API_KEY",
108
- InferenceServiceType.GROQ.value: "GROQ_API_KEY",
109
- InferenceServiceType.BEDROCK.value: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"],
110
- InferenceServiceType.MISTRAL.value: "MISTRAL_API_KEY",
111
- InferenceServiceType.TOGETHER.value: "TOGETHER_API_KEY",
112
- InferenceServiceType.PERPLEXITY.value: "PERPLEXITY_API_KEY",
113
- InferenceServiceType.DEEPSEEK.value: "DEEPSEEK_API_KEY",
114
- InferenceServiceType.XAI.value: "XAI_API_KEY",
115
- }
116
-
117
-
118
- class TokenPricing:
119
- def __init__(
120
- self,
121
- *,
122
- model_name,
123
- prompt_token_price_per_k: float,
124
- completion_token_price_per_k: float,
125
- ):
126
- self.model_name = model_name
127
- self.prompt_token_price = prompt_token_price_per_k / 1_000.0
128
- self.completion_token_price = completion_token_price_per_k / 1_000.0
129
-
130
- def __eq__(self, other):
131
- if not isinstance(other, TokenPricing):
132
- return False
133
- return (
134
- self.model_name == other.model_name
135
- and self.prompt_token_price == other.prompt_token_price
136
- and self.completion_token_price == other.completion_token_price
137
- )
138
-
139
-
140
- pricing = {
141
- "dbrx-instruct": TokenPricing(
142
- model_name="dbrx-instruct",
143
- prompt_token_price_per_k=0.0,
144
- completion_token_price_per_k=0.0,
145
- ),
146
- "claude-3-opus-20240229": TokenPricing(
147
- model_name="claude-3-opus-20240229",
148
- prompt_token_price_per_k=0.0,
149
- completion_token_price_per_k=0.0,
150
- ),
151
- "claude-3-haiku-20240307": TokenPricing(
152
- model_name="claude-3-haiku-20240307",
153
- prompt_token_price_per_k=0.0,
154
- completion_token_price_per_k=0.0,
155
- ),
156
- "claude-3-sonnet-20240229": TokenPricing(
157
- model_name="claude-3-sonnet-20240229",
158
- prompt_token_price_per_k=0.0,
159
- completion_token_price_per_k=0.0,
160
- ),
161
- "gpt-3.5-turbo": TokenPricing(
162
- model_name="gpt-3.5-turbo",
163
- prompt_token_price_per_k=0.0005,
164
- completion_token_price_per_k=0.0015,
165
- ),
166
- "gpt-4-1106-preview": TokenPricing(
167
- model_name="gpt-4",
168
- prompt_token_price_per_k=0.01,
169
- completion_token_price_per_k=0.03,
170
- ),
171
- "test": TokenPricing(
172
- model_name="test",
173
- prompt_token_price_per_k=0.0,
174
- completion_token_price_per_k=0.0,
175
- ),
176
- "gemini_pro": TokenPricing(
177
- model_name="gemini_pro",
178
- prompt_token_price_per_k=0.0,
179
- completion_token_price_per_k=0.0,
180
- ),
181
- "llama-2-13b-chat-hf": TokenPricing(
182
- model_name="llama-2-13b-chat-hf",
183
- prompt_token_price_per_k=0.0,
184
- completion_token_price_per_k=0.0,
185
- ),
186
- "llama-2-70b-chat-hf": TokenPricing(
187
- model_name="llama-2-70b-chat-hf",
188
- prompt_token_price_per_k=0.0,
189
- completion_token_price_per_k=0.0,
190
- ),
191
- "mixtral-8x7B-instruct-v0.1": TokenPricing(
192
- model_name="mixtral-8x7B-instruct-v0.1",
193
- prompt_token_price_per_k=0.0,
194
- completion_token_price_per_k=0.0,
195
- ),
196
- }
197
-
198
-
199
- def get_token_pricing(model_name):
200
- if model_name in pricing:
201
- return pricing[model_name]
202
- else:
203
- return TokenPricing(
204
- model_name=model_name,
205
- prompt_token_price_per_k=0.0,
206
- completion_token_price_per_k=0.0,
207
- )
6
+ # Re-export everything from edsl.base.enums module
7
+ from edsl.base.enums import *
@@ -0,0 +1,5 @@
1
+ from .inference_services_collection import InferenceServicesCollection
2
+ from .registry import default
3
+ from .inference_service_abc import InferenceServiceABC
4
+ from .data_structures import AvailableModels
5
+ from .exceptions import InferenceServiceError
@@ -4,11 +4,10 @@ import sqlite3
4
4
  from datetime import datetime
5
5
  import tempfile
6
6
  from platformdirs import user_cache_dir
7
- from dataclasses import dataclass
8
7
  import os
9
8
 
10
- from edsl.inference_services.data_structures import LanguageModelInfo, AvailableModels
11
- from edsl.enums import InferenceServiceLiteral
9
+ from .data_structures import LanguageModelInfo, AvailableModels
10
+ from ..enums import InferenceServiceLiteral
12
11
 
13
12
 
14
13
  class AvailableModelCacheHandler: