edsl 0.1.14__py3-none-any.whl → 0.1.40__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.
- edsl/Base.py +348 -38
- edsl/BaseDiff.py +260 -0
- edsl/TemplateLoader.py +24 -0
- edsl/__init__.py +46 -10
- edsl/__version__.py +1 -0
- edsl/agents/Agent.py +842 -144
- edsl/agents/AgentList.py +521 -25
- edsl/agents/Invigilator.py +250 -374
- edsl/agents/InvigilatorBase.py +257 -0
- edsl/agents/PromptConstructor.py +272 -0
- edsl/agents/QuestionInstructionPromptBuilder.py +128 -0
- edsl/agents/QuestionTemplateReplacementsBuilder.py +137 -0
- edsl/agents/descriptors.py +43 -13
- edsl/agents/prompt_helpers.py +129 -0
- edsl/agents/question_option_processor.py +172 -0
- edsl/auto/AutoStudy.py +130 -0
- edsl/auto/StageBase.py +243 -0
- edsl/auto/StageGenerateSurvey.py +178 -0
- edsl/auto/StageLabelQuestions.py +125 -0
- edsl/auto/StagePersona.py +61 -0
- edsl/auto/StagePersonaDimensionValueRanges.py +88 -0
- edsl/auto/StagePersonaDimensionValues.py +74 -0
- edsl/auto/StagePersonaDimensions.py +69 -0
- edsl/auto/StageQuestions.py +74 -0
- edsl/auto/SurveyCreatorPipeline.py +21 -0
- edsl/auto/utilities.py +218 -0
- edsl/base/Base.py +279 -0
- edsl/config.py +121 -104
- edsl/conversation/Conversation.py +290 -0
- edsl/conversation/car_buying.py +59 -0
- edsl/conversation/chips.py +95 -0
- edsl/conversation/mug_negotiation.py +81 -0
- edsl/conversation/next_speaker_utilities.py +93 -0
- edsl/coop/CoopFunctionsMixin.py +15 -0
- edsl/coop/ExpectedParrotKeyHandler.py +125 -0
- edsl/coop/PriceFetcher.py +54 -0
- edsl/coop/__init__.py +1 -0
- edsl/coop/coop.py +1029 -134
- edsl/coop/utils.py +131 -0
- edsl/data/Cache.py +560 -89
- edsl/data/CacheEntry.py +230 -0
- edsl/data/CacheHandler.py +168 -0
- edsl/data/RemoteCacheSync.py +186 -0
- edsl/data/SQLiteDict.py +292 -0
- edsl/data/__init__.py +5 -3
- edsl/data/orm.py +6 -33
- edsl/data_transfer_models.py +74 -27
- edsl/enums.py +165 -8
- edsl/exceptions/BaseException.py +21 -0
- edsl/exceptions/__init__.py +52 -46
- edsl/exceptions/agents.py +33 -15
- edsl/exceptions/cache.py +5 -0
- edsl/exceptions/coop.py +8 -0
- edsl/exceptions/general.py +34 -0
- edsl/exceptions/inference_services.py +5 -0
- edsl/exceptions/jobs.py +15 -0
- edsl/exceptions/language_models.py +46 -1
- edsl/exceptions/questions.py +80 -5
- edsl/exceptions/results.py +16 -5
- edsl/exceptions/scenarios.py +29 -0
- edsl/exceptions/surveys.py +13 -10
- edsl/inference_services/AnthropicService.py +106 -0
- edsl/inference_services/AvailableModelCacheHandler.py +184 -0
- edsl/inference_services/AvailableModelFetcher.py +215 -0
- edsl/inference_services/AwsBedrock.py +118 -0
- edsl/inference_services/AzureAI.py +215 -0
- edsl/inference_services/DeepInfraService.py +18 -0
- edsl/inference_services/GoogleService.py +143 -0
- edsl/inference_services/GroqService.py +20 -0
- edsl/inference_services/InferenceServiceABC.py +80 -0
- edsl/inference_services/InferenceServicesCollection.py +138 -0
- edsl/inference_services/MistralAIService.py +120 -0
- edsl/inference_services/OllamaService.py +18 -0
- edsl/inference_services/OpenAIService.py +236 -0
- edsl/inference_services/PerplexityService.py +160 -0
- edsl/inference_services/ServiceAvailability.py +135 -0
- edsl/inference_services/TestService.py +90 -0
- edsl/inference_services/TogetherAIService.py +172 -0
- edsl/inference_services/data_structures.py +134 -0
- edsl/inference_services/models_available_cache.py +118 -0
- edsl/inference_services/rate_limits_cache.py +25 -0
- edsl/inference_services/registry.py +41 -0
- edsl/inference_services/write_available.py +10 -0
- edsl/jobs/AnswerQuestionFunctionConstructor.py +223 -0
- edsl/jobs/Answers.py +21 -20
- edsl/jobs/FetchInvigilator.py +47 -0
- edsl/jobs/InterviewTaskManager.py +98 -0
- edsl/jobs/InterviewsConstructor.py +50 -0
- edsl/jobs/Jobs.py +684 -204
- edsl/jobs/JobsChecks.py +172 -0
- edsl/jobs/JobsComponentConstructor.py +189 -0
- edsl/jobs/JobsPrompts.py +270 -0
- edsl/jobs/JobsRemoteInferenceHandler.py +311 -0
- edsl/jobs/JobsRemoteInferenceLogger.py +239 -0
- edsl/jobs/RequestTokenEstimator.py +30 -0
- edsl/jobs/async_interview_runner.py +138 -0
- edsl/jobs/buckets/BucketCollection.py +104 -0
- edsl/jobs/buckets/ModelBuckets.py +65 -0
- edsl/jobs/buckets/TokenBucket.py +283 -0
- edsl/jobs/buckets/TokenBucketAPI.py +211 -0
- edsl/jobs/buckets/TokenBucketClient.py +191 -0
- edsl/jobs/check_survey_scenario_compatibility.py +85 -0
- edsl/jobs/data_structures.py +120 -0
- edsl/jobs/decorators.py +35 -0
- edsl/jobs/interviews/Interview.py +392 -0
- edsl/jobs/interviews/InterviewExceptionCollection.py +99 -0
- edsl/jobs/interviews/InterviewExceptionEntry.py +186 -0
- edsl/jobs/interviews/InterviewStatistic.py +63 -0
- edsl/jobs/interviews/InterviewStatisticsCollection.py +25 -0
- edsl/jobs/interviews/InterviewStatusDictionary.py +78 -0
- edsl/jobs/interviews/InterviewStatusLog.py +92 -0
- edsl/jobs/interviews/ReportErrors.py +66 -0
- edsl/jobs/interviews/interview_status_enum.py +9 -0
- edsl/jobs/jobs_status_enums.py +9 -0
- edsl/jobs/loggers/HTMLTableJobLogger.py +304 -0
- edsl/jobs/results_exceptions_handler.py +98 -0
- edsl/jobs/runners/JobsRunnerAsyncio.py +151 -110
- edsl/jobs/runners/JobsRunnerStatus.py +298 -0
- edsl/jobs/tasks/QuestionTaskCreator.py +244 -0
- edsl/jobs/tasks/TaskCreators.py +64 -0
- edsl/jobs/tasks/TaskHistory.py +470 -0
- edsl/jobs/tasks/TaskStatusLog.py +23 -0
- edsl/jobs/tasks/task_status_enum.py +161 -0
- edsl/jobs/tokens/InterviewTokenUsage.py +27 -0
- edsl/jobs/tokens/TokenUsage.py +34 -0
- edsl/language_models/ComputeCost.py +63 -0
- edsl/language_models/LanguageModel.py +507 -386
- edsl/language_models/ModelList.py +164 -0
- edsl/language_models/PriceManager.py +127 -0
- edsl/language_models/RawResponseHandler.py +106 -0
- edsl/language_models/RegisterLanguageModelsMeta.py +184 -0
- edsl/language_models/__init__.py +1 -8
- edsl/language_models/fake_openai_call.py +15 -0
- edsl/language_models/fake_openai_service.py +61 -0
- edsl/language_models/key_management/KeyLookup.py +63 -0
- edsl/language_models/key_management/KeyLookupBuilder.py +273 -0
- edsl/language_models/key_management/KeyLookupCollection.py +38 -0
- edsl/language_models/key_management/__init__.py +0 -0
- edsl/language_models/key_management/models.py +131 -0
- edsl/language_models/model.py +256 -0
- edsl/language_models/repair.py +109 -41
- edsl/language_models/utilities.py +65 -0
- edsl/notebooks/Notebook.py +263 -0
- edsl/notebooks/NotebookToLaTeX.py +142 -0
- edsl/notebooks/__init__.py +1 -0
- edsl/prompts/Prompt.py +222 -93
- edsl/prompts/__init__.py +1 -1
- edsl/questions/ExceptionExplainer.py +77 -0
- edsl/questions/HTMLQuestion.py +103 -0
- edsl/questions/QuestionBase.py +518 -0
- edsl/questions/QuestionBasePromptsMixin.py +221 -0
- edsl/questions/QuestionBudget.py +164 -67
- edsl/questions/QuestionCheckBox.py +281 -62
- edsl/questions/QuestionDict.py +343 -0
- edsl/questions/QuestionExtract.py +136 -50
- edsl/questions/QuestionFreeText.py +79 -55
- edsl/questions/QuestionFunctional.py +138 -41
- edsl/questions/QuestionList.py +184 -57
- edsl/questions/QuestionMatrix.py +265 -0
- edsl/questions/QuestionMultipleChoice.py +293 -69
- edsl/questions/QuestionNumerical.py +109 -56
- edsl/questions/QuestionRank.py +244 -49
- edsl/questions/Quick.py +41 -0
- edsl/questions/SimpleAskMixin.py +74 -0
- edsl/questions/__init__.py +9 -6
- edsl/questions/{AnswerValidatorMixin.py → answer_validator_mixin.py} +153 -38
- edsl/questions/compose_questions.py +13 -7
- edsl/questions/data_structures.py +20 -0
- edsl/questions/decorators.py +21 -0
- edsl/questions/derived/QuestionLikertFive.py +28 -26
- edsl/questions/derived/QuestionLinearScale.py +41 -28
- edsl/questions/derived/QuestionTopK.py +34 -26
- edsl/questions/derived/QuestionYesNo.py +40 -27
- edsl/questions/descriptors.py +228 -74
- edsl/questions/loop_processor.py +149 -0
- edsl/questions/prompt_templates/question_budget.jinja +13 -0
- edsl/questions/prompt_templates/question_checkbox.jinja +32 -0
- edsl/questions/prompt_templates/question_extract.jinja +11 -0
- edsl/questions/prompt_templates/question_free_text.jinja +3 -0
- edsl/questions/prompt_templates/question_linear_scale.jinja +11 -0
- edsl/questions/prompt_templates/question_list.jinja +17 -0
- edsl/questions/prompt_templates/question_multiple_choice.jinja +33 -0
- edsl/questions/prompt_templates/question_numerical.jinja +37 -0
- edsl/questions/question_base_gen_mixin.py +168 -0
- edsl/questions/question_registry.py +130 -46
- edsl/questions/register_questions_meta.py +71 -0
- edsl/questions/response_validator_abc.py +188 -0
- edsl/questions/response_validator_factory.py +34 -0
- edsl/questions/settings.py +5 -2
- edsl/questions/templates/__init__.py +0 -0
- edsl/questions/templates/budget/__init__.py +0 -0
- edsl/questions/templates/budget/answering_instructions.jinja +7 -0
- edsl/questions/templates/budget/question_presentation.jinja +7 -0
- edsl/questions/templates/checkbox/__init__.py +0 -0
- edsl/questions/templates/checkbox/answering_instructions.jinja +10 -0
- edsl/questions/templates/checkbox/question_presentation.jinja +22 -0
- edsl/questions/templates/dict/__init__.py +0 -0
- edsl/questions/templates/dict/answering_instructions.jinja +21 -0
- edsl/questions/templates/dict/question_presentation.jinja +1 -0
- edsl/questions/templates/extract/__init__.py +0 -0
- edsl/questions/templates/extract/answering_instructions.jinja +7 -0
- edsl/questions/templates/extract/question_presentation.jinja +1 -0
- edsl/questions/templates/free_text/__init__.py +0 -0
- edsl/questions/templates/free_text/answering_instructions.jinja +0 -0
- edsl/questions/templates/free_text/question_presentation.jinja +1 -0
- edsl/questions/templates/likert_five/__init__.py +0 -0
- edsl/questions/templates/likert_five/answering_instructions.jinja +10 -0
- edsl/questions/templates/likert_five/question_presentation.jinja +12 -0
- edsl/questions/templates/linear_scale/__init__.py +0 -0
- edsl/questions/templates/linear_scale/answering_instructions.jinja +5 -0
- edsl/questions/templates/linear_scale/question_presentation.jinja +5 -0
- edsl/questions/templates/list/__init__.py +0 -0
- edsl/questions/templates/list/answering_instructions.jinja +4 -0
- edsl/questions/templates/list/question_presentation.jinja +5 -0
- edsl/questions/templates/matrix/__init__.py +1 -0
- edsl/questions/templates/matrix/answering_instructions.jinja +5 -0
- edsl/questions/templates/matrix/question_presentation.jinja +20 -0
- edsl/questions/templates/multiple_choice/__init__.py +0 -0
- edsl/questions/templates/multiple_choice/answering_instructions.jinja +9 -0
- edsl/questions/templates/multiple_choice/html.jinja +0 -0
- edsl/questions/templates/multiple_choice/question_presentation.jinja +12 -0
- edsl/questions/templates/numerical/__init__.py +0 -0
- edsl/questions/templates/numerical/answering_instructions.jinja +7 -0
- edsl/questions/templates/numerical/question_presentation.jinja +7 -0
- edsl/questions/templates/rank/__init__.py +0 -0
- edsl/questions/templates/rank/answering_instructions.jinja +11 -0
- edsl/questions/templates/rank/question_presentation.jinja +15 -0
- edsl/questions/templates/top_k/__init__.py +0 -0
- edsl/questions/templates/top_k/answering_instructions.jinja +8 -0
- edsl/questions/templates/top_k/question_presentation.jinja +22 -0
- edsl/questions/templates/yes_no/__init__.py +0 -0
- edsl/questions/templates/yes_no/answering_instructions.jinja +6 -0
- edsl/questions/templates/yes_no/question_presentation.jinja +12 -0
- edsl/results/CSSParameterizer.py +108 -0
- edsl/results/Dataset.py +550 -19
- edsl/results/DatasetExportMixin.py +594 -0
- edsl/results/DatasetTree.py +295 -0
- edsl/results/MarkdownToDocx.py +122 -0
- edsl/results/MarkdownToPDF.py +111 -0
- edsl/results/Result.py +477 -173
- edsl/results/Results.py +987 -269
- edsl/results/ResultsExportMixin.py +28 -125
- edsl/results/ResultsGGMixin.py +83 -15
- edsl/results/TableDisplay.py +125 -0
- edsl/results/TextEditor.py +50 -0
- edsl/results/__init__.py +1 -1
- edsl/results/file_exports.py +252 -0
- edsl/results/results_fetch_mixin.py +33 -0
- edsl/results/results_selector.py +145 -0
- edsl/results/results_tools_mixin.py +98 -0
- edsl/results/smart_objects.py +96 -0
- edsl/results/table_data_class.py +12 -0
- edsl/results/table_display.css +78 -0
- edsl/results/table_renderers.py +118 -0
- edsl/results/tree_explore.py +115 -0
- edsl/scenarios/ConstructDownloadLink.py +109 -0
- edsl/scenarios/DocumentChunker.py +102 -0
- edsl/scenarios/DocxScenario.py +16 -0
- edsl/scenarios/FileStore.py +543 -0
- edsl/scenarios/PdfExtractor.py +40 -0
- edsl/scenarios/Scenario.py +431 -62
- edsl/scenarios/ScenarioHtmlMixin.py +65 -0
- edsl/scenarios/ScenarioList.py +1415 -45
- edsl/scenarios/ScenarioListExportMixin.py +45 -0
- edsl/scenarios/ScenarioListPdfMixin.py +239 -0
- edsl/scenarios/__init__.py +2 -0
- edsl/scenarios/directory_scanner.py +96 -0
- edsl/scenarios/file_methods.py +85 -0
- edsl/scenarios/handlers/__init__.py +13 -0
- edsl/scenarios/handlers/csv.py +49 -0
- edsl/scenarios/handlers/docx.py +76 -0
- edsl/scenarios/handlers/html.py +37 -0
- edsl/scenarios/handlers/json.py +111 -0
- edsl/scenarios/handlers/latex.py +5 -0
- edsl/scenarios/handlers/md.py +51 -0
- edsl/scenarios/handlers/pdf.py +68 -0
- edsl/scenarios/handlers/png.py +39 -0
- edsl/scenarios/handlers/pptx.py +105 -0
- edsl/scenarios/handlers/py.py +294 -0
- edsl/scenarios/handlers/sql.py +313 -0
- edsl/scenarios/handlers/sqlite.py +149 -0
- edsl/scenarios/handlers/txt.py +33 -0
- edsl/scenarios/scenario_join.py +131 -0
- edsl/scenarios/scenario_selector.py +156 -0
- edsl/shared.py +1 -0
- edsl/study/ObjectEntry.py +173 -0
- edsl/study/ProofOfWork.py +113 -0
- edsl/study/SnapShot.py +80 -0
- edsl/study/Study.py +521 -0
- edsl/study/__init__.py +4 -0
- edsl/surveys/ConstructDAG.py +92 -0
- edsl/surveys/DAG.py +92 -11
- edsl/surveys/EditSurvey.py +221 -0
- edsl/surveys/InstructionHandler.py +100 -0
- edsl/surveys/Memory.py +9 -4
- edsl/surveys/MemoryManagement.py +72 -0
- edsl/surveys/MemoryPlan.py +156 -35
- edsl/surveys/Rule.py +221 -74
- edsl/surveys/RuleCollection.py +241 -61
- edsl/surveys/RuleManager.py +172 -0
- edsl/surveys/Simulator.py +75 -0
- edsl/surveys/Survey.py +1079 -339
- edsl/surveys/SurveyCSS.py +273 -0
- edsl/surveys/SurveyExportMixin.py +235 -40
- edsl/surveys/SurveyFlowVisualization.py +181 -0
- edsl/surveys/SurveyQualtricsImport.py +284 -0
- edsl/surveys/SurveyToApp.py +141 -0
- edsl/surveys/__init__.py +4 -2
- edsl/surveys/base.py +19 -3
- edsl/surveys/descriptors.py +17 -6
- edsl/surveys/instructions/ChangeInstruction.py +48 -0
- edsl/surveys/instructions/Instruction.py +56 -0
- edsl/surveys/instructions/InstructionCollection.py +82 -0
- edsl/surveys/instructions/__init__.py +0 -0
- edsl/templates/error_reporting/base.html +24 -0
- edsl/templates/error_reporting/exceptions_by_model.html +35 -0
- edsl/templates/error_reporting/exceptions_by_question_name.html +17 -0
- edsl/templates/error_reporting/exceptions_by_type.html +17 -0
- edsl/templates/error_reporting/interview_details.html +116 -0
- edsl/templates/error_reporting/interviews.html +19 -0
- edsl/templates/error_reporting/overview.html +5 -0
- edsl/templates/error_reporting/performance_plot.html +2 -0
- edsl/templates/error_reporting/report.css +74 -0
- edsl/templates/error_reporting/report.html +118 -0
- edsl/templates/error_reporting/report.js +25 -0
- edsl/tools/__init__.py +1 -0
- edsl/tools/clusters.py +192 -0
- edsl/tools/embeddings.py +27 -0
- edsl/tools/embeddings_plotting.py +118 -0
- edsl/tools/plotting.py +112 -0
- edsl/tools/summarize.py +18 -0
- edsl/utilities/PrettyList.py +56 -0
- edsl/utilities/SystemInfo.py +5 -0
- edsl/utilities/__init__.py +21 -20
- edsl/utilities/ast_utilities.py +3 -0
- edsl/utilities/data/Registry.py +2 -0
- edsl/utilities/decorators.py +41 -0
- edsl/utilities/gcp_bucket/__init__.py +0 -0
- edsl/utilities/gcp_bucket/cloud_storage.py +96 -0
- edsl/utilities/interface.py +310 -60
- edsl/utilities/is_notebook.py +18 -0
- edsl/utilities/is_valid_variable_name.py +11 -0
- edsl/utilities/naming_utilities.py +263 -0
- edsl/utilities/remove_edsl_version.py +24 -0
- edsl/utilities/repair_functions.py +28 -0
- edsl/utilities/restricted_python.py +70 -0
- edsl/utilities/utilities.py +203 -13
- edsl-0.1.40.dist-info/METADATA +111 -0
- edsl-0.1.40.dist-info/RECORD +362 -0
- {edsl-0.1.14.dist-info → edsl-0.1.40.dist-info}/WHEEL +1 -1
- edsl/agents/AgentListExportMixin.py +0 -24
- edsl/coop/old.py +0 -31
- edsl/data/Database.py +0 -141
- edsl/data/crud.py +0 -121
- edsl/jobs/Interview.py +0 -417
- edsl/jobs/JobsRunner.py +0 -63
- edsl/jobs/JobsRunnerStatusMixin.py +0 -115
- edsl/jobs/base.py +0 -47
- edsl/jobs/buckets.py +0 -166
- edsl/jobs/runners/JobsRunnerDryRun.py +0 -19
- edsl/jobs/runners/JobsRunnerStreaming.py +0 -54
- edsl/jobs/task_management.py +0 -218
- edsl/jobs/token_tracking.py +0 -78
- edsl/language_models/DeepInfra.py +0 -69
- edsl/language_models/OpenAI.py +0 -98
- edsl/language_models/model_interfaces/GeminiPro.py +0 -66
- edsl/language_models/model_interfaces/LanguageModelOpenAIFour.py +0 -8
- edsl/language_models/model_interfaces/LanguageModelOpenAIThreeFiveTurbo.py +0 -8
- edsl/language_models/model_interfaces/LlamaTwo13B.py +0 -21
- edsl/language_models/model_interfaces/LlamaTwo70B.py +0 -21
- edsl/language_models/model_interfaces/Mixtral8x7B.py +0 -24
- edsl/language_models/registry.py +0 -81
- edsl/language_models/schemas.py +0 -15
- edsl/language_models/unused/ReplicateBase.py +0 -83
- edsl/prompts/QuestionInstructionsBase.py +0 -6
- edsl/prompts/library/agent_instructions.py +0 -29
- edsl/prompts/library/agent_persona.py +0 -17
- edsl/prompts/library/question_budget.py +0 -26
- edsl/prompts/library/question_checkbox.py +0 -32
- edsl/prompts/library/question_extract.py +0 -19
- edsl/prompts/library/question_freetext.py +0 -14
- edsl/prompts/library/question_linear_scale.py +0 -20
- edsl/prompts/library/question_list.py +0 -22
- edsl/prompts/library/question_multiple_choice.py +0 -44
- edsl/prompts/library/question_numerical.py +0 -31
- edsl/prompts/library/question_rank.py +0 -21
- edsl/prompts/prompt_config.py +0 -33
- edsl/prompts/registry.py +0 -185
- edsl/questions/Question.py +0 -240
- edsl/report/InputOutputDataTypes.py +0 -134
- edsl/report/RegressionMixin.py +0 -28
- edsl/report/ReportOutputs.py +0 -1228
- edsl/report/ResultsFetchMixin.py +0 -106
- edsl/report/ResultsOutputMixin.py +0 -14
- edsl/report/demo.ipynb +0 -645
- edsl/results/ResultsDBMixin.py +0 -184
- edsl/surveys/SurveyFlowVisualizationMixin.py +0 -92
- edsl/trackers/Tracker.py +0 -91
- edsl/trackers/TrackerAPI.py +0 -196
- edsl/trackers/TrackerTasks.py +0 -70
- edsl/utilities/pastebin.py +0 -141
- edsl-0.1.14.dist-info/METADATA +0 -69
- edsl-0.1.14.dist-info/RECORD +0 -141
- /edsl/{language_models/model_interfaces → inference_services}/__init__.py +0 -0
- /edsl/{report/__init__.py → jobs/runners/JobsRunnerStatusData.py} +0 -0
- /edsl/{trackers/__init__.py → language_models/ServiceDataSources.py} +0 -0
- {edsl-0.1.14.dist-info → edsl-0.1.40.dist-info}/LICENSE +0 -0
edsl/results/ResultsDBMixin.py
DELETED
@@ -1,184 +0,0 @@
|
|
1
|
-
import pandas as pd
|
2
|
-
import sqlite3
|
3
|
-
from sqlalchemy import create_engine
|
4
|
-
from enum import Enum
|
5
|
-
|
6
|
-
|
7
|
-
class SQLDataShape(Enum):
|
8
|
-
WIDE = "wide"
|
9
|
-
LONG = "long"
|
10
|
-
|
11
|
-
|
12
|
-
class ResultsDBMixin:
|
13
|
-
def rows(self):
|
14
|
-
for index, result in enumerate(self):
|
15
|
-
yield from result.rows(index)
|
16
|
-
|
17
|
-
def export_sql_dump(self, shape, filename):
|
18
|
-
shape_enum = self._get_shape_enum(shape)
|
19
|
-
conn = self.db(shape=shape_enum)
|
20
|
-
|
21
|
-
# Open file to write SQL dump
|
22
|
-
with open(filename, "w") as f:
|
23
|
-
for line in conn.iterdump():
|
24
|
-
f.write(f"{line}\n")
|
25
|
-
|
26
|
-
# Close the connection
|
27
|
-
conn.close()
|
28
|
-
|
29
|
-
def backup_db_to_file(self, shape, filename):
|
30
|
-
shape_enum = self._get_shape_enum(shape)
|
31
|
-
# Source database connection (in-memory)
|
32
|
-
source_conn = self.db(shape=shape_enum)
|
33
|
-
|
34
|
-
# Destination database connection (file)
|
35
|
-
dest_conn = sqlite3.connect(filename)
|
36
|
-
|
37
|
-
# Backup in-memory database to file
|
38
|
-
with source_conn:
|
39
|
-
source_conn.backup(dest_conn)
|
40
|
-
|
41
|
-
# Close both connections
|
42
|
-
source_conn.close()
|
43
|
-
dest_conn.close()
|
44
|
-
|
45
|
-
def db(self, shape: SQLDataShape, remove_prefix=False):
|
46
|
-
if shape == SQLDataShape.LONG:
|
47
|
-
# Step 2: Create a SQLite Database in Memory
|
48
|
-
conn = sqlite3.connect(":memory:")
|
49
|
-
|
50
|
-
create_table_query = """
|
51
|
-
CREATE TABLE self (
|
52
|
-
id INTEGER,
|
53
|
-
data_type TEXT,
|
54
|
-
key TEXT,
|
55
|
-
value TEXT
|
56
|
-
)
|
57
|
-
"""
|
58
|
-
conn.execute(create_table_query)
|
59
|
-
|
60
|
-
# # Step 3: Insert the tuples into the table
|
61
|
-
list_of_tuples = list(self.rows())
|
62
|
-
insert_query = (
|
63
|
-
"INSERT INTO self (id, data_type, key, value) VALUES (?, ?, ?, ?)"
|
64
|
-
)
|
65
|
-
conn.executemany(insert_query, list_of_tuples)
|
66
|
-
conn.commit()
|
67
|
-
return conn
|
68
|
-
elif shape == SQLDataShape.WIDE:
|
69
|
-
db_uri = "sqlite:///:memory:"
|
70
|
-
|
71
|
-
# Create SQLAlchemy engine with the in-memory database connection string
|
72
|
-
engine = create_engine(db_uri)
|
73
|
-
|
74
|
-
# Convert DataFrame to SQLite in-memory database
|
75
|
-
df = self.to_pandas(remove_prefix=remove_prefix)
|
76
|
-
df.to_sql("self", engine, index=False, if_exists="replace")
|
77
|
-
|
78
|
-
# Create a connection to the SQLite database
|
79
|
-
conn = engine.connect()
|
80
|
-
return conn
|
81
|
-
else:
|
82
|
-
raise Exception("Invalid SQLDataShape")
|
83
|
-
|
84
|
-
def _get_shape_enum(self, shape: str):
|
85
|
-
if shape is None:
|
86
|
-
raise Exception("Must select either 'wide' or 'long' format")
|
87
|
-
elif shape == "wide":
|
88
|
-
return SQLDataShape.WIDE
|
89
|
-
elif shape == "long":
|
90
|
-
return SQLDataShape.LONG
|
91
|
-
else:
|
92
|
-
raise Exception("Invalid shape: must be either 'long' or 'wide'")
|
93
|
-
|
94
|
-
def sql(
|
95
|
-
self,
|
96
|
-
query: str,
|
97
|
-
shape: str,
|
98
|
-
remove_prefix: bool = False,
|
99
|
-
transpose: bool = None,
|
100
|
-
transpose_by: str = None,
|
101
|
-
csv: bool = False,
|
102
|
-
):
|
103
|
-
"""Execute a SQL query and return the results as a DataFrame.
|
104
|
-
:param query: The SQL query to execute
|
105
|
-
:param transpose: Transpose the DataFrame if True
|
106
|
-
:param transpose_by: Column to use as the index when transposing, otherwise the first column
|
107
|
-
:param csv: Return the DataFrame as a CSV string if True
|
108
|
-
"""
|
109
|
-
shape_enum = self._get_shape_enum(shape)
|
110
|
-
|
111
|
-
conn = self.db(shape=shape_enum, remove_prefix=remove_prefix)
|
112
|
-
df = pd.read_sql_query(query, conn)
|
113
|
-
|
114
|
-
# Transpose the DataFrame if transpose is True
|
115
|
-
if transpose or transpose_by:
|
116
|
-
df = pd.DataFrame(df)
|
117
|
-
if transpose_by:
|
118
|
-
df = df.set_index(transpose_by)
|
119
|
-
else:
|
120
|
-
df = df.set_index(df.columns[0])
|
121
|
-
df = df.transpose()
|
122
|
-
|
123
|
-
# Return as CSV if output is "csv"
|
124
|
-
if csv:
|
125
|
-
return df.to_csv(index=False)
|
126
|
-
else:
|
127
|
-
return df
|
128
|
-
|
129
|
-
def show_schema(self, shape: str, remove_prefix: bool = False):
|
130
|
-
shape_enum = self._get_shape_enum(shape)
|
131
|
-
conn = self.db(shape=shape_enum, remove_prefix=remove_prefix)
|
132
|
-
|
133
|
-
if shape_enum == SQLDataShape.LONG:
|
134
|
-
# Query to get the schema of all tables
|
135
|
-
query = "SELECT type, name, sql FROM sqlite_master WHERE type='table'"
|
136
|
-
|
137
|
-
# Execute the query
|
138
|
-
cursor = conn.execute(query)
|
139
|
-
schema = cursor.fetchall()
|
140
|
-
|
141
|
-
# Close the connection
|
142
|
-
conn.close()
|
143
|
-
|
144
|
-
# Format and return the schema information
|
145
|
-
schema_info = ""
|
146
|
-
for row in schema:
|
147
|
-
schema_info += f"Type: {row[0]}, Name: {row[1]}, SQL: {row[2]}\n"
|
148
|
-
|
149
|
-
print(schema_info)
|
150
|
-
elif shape_enum == SQLDataShape.WIDE:
|
151
|
-
query = f"PRAGMA table_info(self)"
|
152
|
-
schema = pd.read_sql(query, conn)
|
153
|
-
print(schema)
|
154
|
-
|
155
|
-
|
156
|
-
if __name__ == "__main__":
|
157
|
-
from edsl.results import Results
|
158
|
-
|
159
|
-
r = Results.example()
|
160
|
-
|
161
|
-
df = r.sql(
|
162
|
-
"select data_type, key, value from self where data_type = 'answer'",
|
163
|
-
shape="long",
|
164
|
-
)
|
165
|
-
print(df)
|
166
|
-
|
167
|
-
df = r.sql(
|
168
|
-
"select * from self",
|
169
|
-
shape="wide",
|
170
|
-
)
|
171
|
-
|
172
|
-
df = r.sql(
|
173
|
-
"select * from self",
|
174
|
-
shape="wide",
|
175
|
-
)
|
176
|
-
|
177
|
-
r.show_schema(shape="long")
|
178
|
-
|
179
|
-
df = r.sql(
|
180
|
-
"select * from self",
|
181
|
-
shape="wide",
|
182
|
-
)
|
183
|
-
|
184
|
-
print(df)
|
@@ -1,92 +0,0 @@
|
|
1
|
-
import pydot
|
2
|
-
import tempfile
|
3
|
-
from IPython.display import Image
|
4
|
-
from edsl.utilities import is_notebook
|
5
|
-
from edsl.surveys.base import RulePriority, EndOfSurvey
|
6
|
-
|
7
|
-
|
8
|
-
class SurveyFlowVisualizationMixin:
|
9
|
-
def show_flow(self):
|
10
|
-
"Creates an image showing the flow of users through the survey."
|
11
|
-
# Create a graph object
|
12
|
-
graph = pydot.Dot(graph_type="digraph")
|
13
|
-
|
14
|
-
# Add nodes
|
15
|
-
for index, question in enumerate(self.questions):
|
16
|
-
graph.add_node(
|
17
|
-
pydot.Node(
|
18
|
-
f"Q{index}", label=f"{question.question_name}", shape="ellipse"
|
19
|
-
)
|
20
|
-
)
|
21
|
-
|
22
|
-
# Add an "EndOfSurvey" node
|
23
|
-
graph.add_node(
|
24
|
-
pydot.Node("EndOfSurvey", label="End of Survey", shape="rectangle")
|
25
|
-
)
|
26
|
-
|
27
|
-
# Add edges for normal flow
|
28
|
-
num_questions = len(self.questions)
|
29
|
-
for index in range(num_questions - 1): # From Q1 to Q3
|
30
|
-
graph.add_edge(pydot.Edge(f"Q{index}", f"Q{index+1}"))
|
31
|
-
|
32
|
-
graph.add_edge(pydot.Edge(f"Q{num_questions-1}", "EndOfSurvey"))
|
33
|
-
|
34
|
-
relevant_rules = [
|
35
|
-
rule
|
36
|
-
for rule in self.rule_collection
|
37
|
-
if rule.priority > RulePriority.DEFAULT.value
|
38
|
-
]
|
39
|
-
|
40
|
-
colors = [
|
41
|
-
"blue",
|
42
|
-
"red",
|
43
|
-
"purple",
|
44
|
-
"orange",
|
45
|
-
"pink",
|
46
|
-
"brown",
|
47
|
-
"grey",
|
48
|
-
"cyan",
|
49
|
-
"green",
|
50
|
-
]
|
51
|
-
rule_colors = {
|
52
|
-
rule: colors[i % len(colors)] for i, rule in enumerate(relevant_rules)
|
53
|
-
}
|
54
|
-
|
55
|
-
for rule in relevant_rules:
|
56
|
-
color = rule_colors[rule]
|
57
|
-
edge_label = f"if {rule.expression}"
|
58
|
-
source_node = f"Q{rule.current_q}"
|
59
|
-
target_node = (
|
60
|
-
f"Q{rule.next_q}" if rule.next_q != EndOfSurvey else "EndOfSurvey"
|
61
|
-
)
|
62
|
-
edge = pydot.Edge(
|
63
|
-
source_node, target_node, label=edge_label, color=color, fontcolor=color
|
64
|
-
)
|
65
|
-
graph.add_edge(edge)
|
66
|
-
|
67
|
-
with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmp_file:
|
68
|
-
try:
|
69
|
-
graph.write_png(tmp_file.name)
|
70
|
-
except FileNotFoundError:
|
71
|
-
print(
|
72
|
-
"""File not found. Most likely it's because you don't have graphviz installed. Please install it and try again.
|
73
|
-
It's
|
74
|
-
$ sudo apt-get install graphviz
|
75
|
-
on Ubuntu.
|
76
|
-
"""
|
77
|
-
)
|
78
|
-
|
79
|
-
if is_notebook():
|
80
|
-
display(Image(tmp_file.name))
|
81
|
-
else:
|
82
|
-
import os
|
83
|
-
import sys
|
84
|
-
|
85
|
-
if os.name == "nt": # Windows
|
86
|
-
os.system(f"start {tmp_file.name}")
|
87
|
-
elif os.name == "posix": # macOS, Linux, Unix, etc.
|
88
|
-
os.system(
|
89
|
-
f"open {tmp_file.name}"
|
90
|
-
if sys.platform == "darwin"
|
91
|
-
else f"xdg-open {tmp_file.name}"
|
92
|
-
)
|
edsl/trackers/Tracker.py
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
This an ABC for a tracker that monitors a Python queue.
|
3
|
-
|
4
|
-
Contained within the namespace is a class called TrackerEvent, which is also an ABC.
|
5
|
-
This is the kind of event that will be placed in the queue the tracker is monitoring.
|
6
|
-
Each child class of TrackerEvent needs to know how to update the state of the tracker.
|
7
|
-
|
8
|
-
Each child has to implement a tracked_values method which tells what values the
|
9
|
-
tracker is tracking - this is so it can pretty-print them.
|
10
|
-
|
11
|
-
All child classes have to implement an allowed_events class variable.
|
12
|
-
|
13
|
-
"""
|
14
|
-
import time
|
15
|
-
from abc import ABC, abstractmethod
|
16
|
-
from queue import Empty
|
17
|
-
from edsl.utilities.interface import print_dict_with_rich
|
18
|
-
|
19
|
-
|
20
|
-
class Tracker(ABC):
|
21
|
-
"Meant to be single-threaded"
|
22
|
-
|
23
|
-
class TrackerEvent(ABC):
|
24
|
-
"Each child event needs to know how to update the state of the tracker."
|
25
|
-
|
26
|
-
@abstractmethod
|
27
|
-
def apply(self, tracker):
|
28
|
-
pass
|
29
|
-
|
30
|
-
def __init__(self, event_queue, verbose=False):
|
31
|
-
self.event_queue = event_queue
|
32
|
-
self.observed_events = []
|
33
|
-
self.verbose = verbose
|
34
|
-
if self.verbose:
|
35
|
-
print("Tracker instantiated")
|
36
|
-
|
37
|
-
@abstractmethod
|
38
|
-
def allowed_events(self) -> set:
|
39
|
-
"What events (classes) are allowed to be placed in the queue?"
|
40
|
-
pass
|
41
|
-
|
42
|
-
@abstractmethod
|
43
|
-
def tracked_values(self) -> dict:
|
44
|
-
"What values are tracked by this tracker (should be flat dictionary)?"
|
45
|
-
pass
|
46
|
-
|
47
|
-
def get_from_queue(self):
|
48
|
-
"""Gets events from the queue and stores them in a list.
|
49
|
-
It runs until the event_queue is empty.
|
50
|
-
"""
|
51
|
-
while True:
|
52
|
-
try:
|
53
|
-
event = self.event_queue.get(block=False)
|
54
|
-
except Empty as e:
|
55
|
-
if self.verbose:
|
56
|
-
print("The queue is empty.")
|
57
|
-
break
|
58
|
-
else:
|
59
|
-
self.observed_events.append(event)
|
60
|
-
self.process_event(event)
|
61
|
-
self.event_queue.task_done()
|
62
|
-
|
63
|
-
def __call__(self, all_done, interval=1):
|
64
|
-
if self.verbose:
|
65
|
-
print("Tracking thread is starting.")
|
66
|
-
while not all_done.is_set():
|
67
|
-
self.get_from_queue()
|
68
|
-
time.sleep(interval)
|
69
|
-
|
70
|
-
# Run one last time to get anything still left in the event_queue
|
71
|
-
self.get_from_queue()
|
72
|
-
|
73
|
-
def process_event(self, event):
|
74
|
-
"""Processes an event from the event queue."""
|
75
|
-
|
76
|
-
## diabling this for now as two error-prone:
|
77
|
-
# https://chat.openai.com/share/6e0e2ae2-30d7-4281-982a-a69a218c4e76
|
78
|
-
|
79
|
-
# if not isinstance(event, tuple(self.allowed_events())):
|
80
|
-
# print(f"Event type: {type(event).__name__}")
|
81
|
-
# print(f"Allowed events: {self.allowed_events()}")
|
82
|
-
# raise ValueError(f"Invalid event type: {type(event).__name__}")
|
83
|
-
|
84
|
-
event.apply(self)
|
85
|
-
if self.verbose:
|
86
|
-
self.show_status()
|
87
|
-
|
88
|
-
def show_status(self):
|
89
|
-
"""Prints the status of the interview manager."""
|
90
|
-
data = self.tracked_values()
|
91
|
-
print_dict_with_rich(data)
|
edsl/trackers/TrackerAPI.py
DELETED
@@ -1,196 +0,0 @@
|
|
1
|
-
"""This tracker tracks API calls."""
|
2
|
-
import json
|
3
|
-
import time
|
4
|
-
from collections import namedtuple
|
5
|
-
from threading import Lock, Event
|
6
|
-
from edsl.trackers.Tracker import Tracker
|
7
|
-
|
8
|
-
UsageRates = namedtuple(
|
9
|
-
"UsageRates",
|
10
|
-
[
|
11
|
-
"estimated_tokens_per_minute_k",
|
12
|
-
"pct_of_tpm_limit",
|
13
|
-
"estimated_requests_per_minute_k",
|
14
|
-
"pct_of_rpm_limit",
|
15
|
-
],
|
16
|
-
)
|
17
|
-
|
18
|
-
|
19
|
-
class TrackerAPI(Tracker):
|
20
|
-
""" """
|
21
|
-
|
22
|
-
class APICallDetails(Tracker.TrackerEvent):
|
23
|
-
def __init__(self, details):
|
24
|
-
self.details = details
|
25
|
-
|
26
|
-
def apply(self, tracker):
|
27
|
-
with tracker.lock:
|
28
|
-
tracker.usage.append(self.details)
|
29
|
-
|
30
|
-
def __init__(
|
31
|
-
self, lock, monitored_queue, tokens_per_minute_k=90, requests_per_minute_k=2
|
32
|
-
):
|
33
|
-
self.lock = lock
|
34
|
-
self.tokens_per_minute_k = tokens_per_minute_k
|
35
|
-
self.requests_per_minute_k = requests_per_minute_k
|
36
|
-
self.usage = []
|
37
|
-
|
38
|
-
super().__init__(monitored_queue)
|
39
|
-
|
40
|
-
def usage_rates(self, last_seconds=60):
|
41
|
-
with self.lock:
|
42
|
-
right_now = time.time()
|
43
|
-
relevant_usage = [
|
44
|
-
x
|
45
|
-
for x in self.usage
|
46
|
-
if (x["timestamp"] > right_now - last_seconds)
|
47
|
-
and not x["cached_response"]
|
48
|
-
]
|
49
|
-
if relevant_usage == []:
|
50
|
-
return UsageRates(**{k: 0 for k in UsageRates._fields})
|
51
|
-
else:
|
52
|
-
elapsed_seconds = right_now - relevant_usage[0]["timestamp"]
|
53
|
-
total_tokens = sum([x["total_tokens"] for x in relevant_usage])
|
54
|
-
|
55
|
-
estimated_tokens_per_minute_k = round(
|
56
|
-
total_tokens / (elapsed_seconds / 60.0) / 1000, 0
|
57
|
-
)
|
58
|
-
pct_of_tpm_limit = round(
|
59
|
-
100 * estimated_tokens_per_minute_k / self.tokens_per_minute_k
|
60
|
-
)
|
61
|
-
|
62
|
-
estimated_requests_per_minute_k = round(
|
63
|
-
len(relevant_usage) / (elapsed_seconds / 60.0) / 1000, 2
|
64
|
-
)
|
65
|
-
pct_of_rpm_limit = round(
|
66
|
-
100 * estimated_requests_per_minute_k / self.requests_per_minute_k
|
67
|
-
)
|
68
|
-
|
69
|
-
usage_rates = UsageRates(
|
70
|
-
estimated_tokens_per_minute_k=estimated_tokens_per_minute_k,
|
71
|
-
pct_of_tpm_limit=pct_of_tpm_limit,
|
72
|
-
estimated_requests_per_minute_k=estimated_requests_per_minute_k,
|
73
|
-
pct_of_rpm_limit=pct_of_rpm_limit,
|
74
|
-
)
|
75
|
-
|
76
|
-
return usage_rates
|
77
|
-
|
78
|
-
def tracked_values(self) -> dict:
|
79
|
-
return {
|
80
|
-
"Calls": len(self.usage),
|
81
|
-
}
|
82
|
-
|
83
|
-
def allowed_events(self):
|
84
|
-
return set([TrackerAPI.APICallDetails])
|
85
|
-
|
86
|
-
@classmethod
|
87
|
-
def fromJSON(cls, filename):
|
88
|
-
"""This loads a tracker from a JSON file. Just for testing purposes"""
|
89
|
-
with open(filename, "r") as f:
|
90
|
-
json_dict = f.read()
|
91
|
-
usage = json.loads(json_dict)
|
92
|
-
# pretend responses are not cached for each testing, as the
|
93
|
-
# usage_rate methods only compute w/ non-cached responses
|
94
|
-
[x.update({"cached_response": False}) for x in usage]
|
95
|
-
instance = cls(Lock(), None)
|
96
|
-
instance.usage = usage
|
97
|
-
return instance
|
98
|
-
|
99
|
-
def toJSON(self, filename="sample_data.json"):
|
100
|
-
with open(filename, "w") as f:
|
101
|
-
json.dump(self.usage, f)
|
102
|
-
|
103
|
-
def status(self):
|
104
|
-
"""This prints the status of the interview manager, while interviews are doing on."""
|
105
|
-
estimated_length = 100
|
106
|
-
completed = self.status_tracker.complete
|
107
|
-
pct_completed = self.status_tracker.percentage_complete
|
108
|
-
usage_rates = self.current_tpm(10)
|
109
|
-
heartbeat = next(self.status_tracker.hearbeat)
|
110
|
-
status_str = (
|
111
|
-
f"{heartbeat} Completed: {completed} ({pct_completed} of total); "
|
112
|
-
f"Est. TPM (k): {usage_rates.estimated_tokens_per_minute_k: ,} ({usage_rates.frac_of_tpm_limit}% of lim.); "
|
113
|
-
f"Est. RPM (k): {usage_rates.estimated_requests_per_minute_k:,} ({usage_rates.frac_of_rpm_limit}% of lim.)); "
|
114
|
-
)
|
115
|
-
# Pad with spaces to reach the estimated length
|
116
|
-
padded_status_str = status_str.ljust(estimated_length)
|
117
|
-
print(f"\r{padded_status_str}", end="", flush=True)
|
118
|
-
|
119
|
-
|
120
|
-
if __name__ == "__main__":
|
121
|
-
import textwrap
|
122
|
-
from language_models import LanguageModelOpenAIThreeFiveTurbo
|
123
|
-
|
124
|
-
m = LanguageModelOpenAIThreeFiveTurbo(use_cache=True)
|
125
|
-
|
126
|
-
# the language model is attached to the queue
|
127
|
-
print(m.api_queue)
|
128
|
-
|
129
|
-
# the tracker expects a lock and an event
|
130
|
-
lock = Lock()
|
131
|
-
all_done = Event()
|
132
|
-
|
133
|
-
# tracker attached to the queue
|
134
|
-
tracker = TrackerAPI(lock=lock, monitored_queue=m.api_queue)
|
135
|
-
|
136
|
-
# the queue is empty to start
|
137
|
-
print(f"Queue size: {m.api_queue.qsize()}")
|
138
|
-
|
139
|
-
# a call is made to the language model
|
140
|
-
raw = m.get_raw_response(
|
141
|
-
prompt="What is your favorite color?",
|
142
|
-
system_prompt=textwrap.dedent(
|
143
|
-
"""\
|
144
|
-
You are pretending to be a human taking a survey.
|
145
|
-
Do not break character.
|
146
|
-
"""
|
147
|
-
),
|
148
|
-
)
|
149
|
-
|
150
|
-
# sleep for a second, as queue puts are non-blocking
|
151
|
-
import time
|
152
|
-
|
153
|
-
print("Sleeping for 1 second")
|
154
|
-
time.sleep(1)
|
155
|
-
# see that the queue updated
|
156
|
-
print(f"Queue size: {m.api_queue.qsize()}")
|
157
|
-
print(m.parse_response(raw))
|
158
|
-
# indicate we are all done
|
159
|
-
all_done.set()
|
160
|
-
# have the tracker finish up
|
161
|
-
tracker(all_done, interval=1)
|
162
|
-
# how many calls did the API observe?
|
163
|
-
print(tracker.tracked_values())
|
164
|
-
# what is in the tracker queue?
|
165
|
-
print(tracker.usage)
|
166
|
-
# confirm that the API queue is empty
|
167
|
-
print(f"Queue size: {m.api_queue.qsize()}")
|
168
|
-
|
169
|
-
## Next example - compute queue statistics
|
170
|
-
all_done = Event()
|
171
|
-
|
172
|
-
tracker_two = TrackerAPI(lock=lock, monitored_queue=m.api_queue)
|
173
|
-
|
174
|
-
for i in range(10):
|
175
|
-
raw = m.get_raw_response(
|
176
|
-
prompt=f"What emotions are associated with {i}?",
|
177
|
-
system_prompt=textwrap.dedent(
|
178
|
-
"""\
|
179
|
-
You are pretending to be a human taking a survey.
|
180
|
-
Do not break character.
|
181
|
-
"""
|
182
|
-
),
|
183
|
-
)
|
184
|
-
|
185
|
-
time.sleep(1)
|
186
|
-
all_done.set()
|
187
|
-
# have the tracker finish up
|
188
|
-
tracker(all_done, interval=1)
|
189
|
-
# print(tracker.usage)
|
190
|
-
tracker.toJSON(filename="sample_data.json")
|
191
|
-
|
192
|
-
# from .example_api_call_data import sample_data
|
193
|
-
tracker = TrackerAPI.fromJSON("sample_data.json")
|
194
|
-
print(tracker.usage)
|
195
|
-
|
196
|
-
print(tracker.usage_rates(1000000))
|
edsl/trackers/TrackerTasks.py
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
from edsl.trackers.Tracker import Tracker
|
2
|
-
from edsl.utilities.interface import heartbeat_generator, human_readable_labeler_creator
|
3
|
-
|
4
|
-
|
5
|
-
class TrackerTasks(Tracker):
|
6
|
-
""" """
|
7
|
-
|
8
|
-
class WorkerActivated(Tracker.TrackerEvent):
|
9
|
-
def apply(self, tracker):
|
10
|
-
with tracker.lock:
|
11
|
-
tracker.active_workers += 1
|
12
|
-
|
13
|
-
class WorkerDeactivated(Tracker.TrackerEvent):
|
14
|
-
def apply(self, tracker):
|
15
|
-
with tracker.lock:
|
16
|
-
tracker.active_workers -= 1
|
17
|
-
|
18
|
-
class TaskStarted(Tracker.TrackerEvent):
|
19
|
-
def apply(self, tracker):
|
20
|
-
with tracker.lock:
|
21
|
-
tracker.interviews_started += 1
|
22
|
-
|
23
|
-
class TaskCompleted(Tracker.TrackerEvent):
|
24
|
-
def apply(self, tracker):
|
25
|
-
with tracker.lock:
|
26
|
-
tracker.interviews_completed += 1
|
27
|
-
|
28
|
-
class ThreadStatus(Tracker.TrackerEvent):
|
29
|
-
def __init__(self, thread_id, status):
|
30
|
-
self.thread_id = thread_id
|
31
|
-
self.status = status
|
32
|
-
|
33
|
-
def apply(self, tracker):
|
34
|
-
with tracker.lock:
|
35
|
-
tracker.thread_status[self.thread_id] = self.status
|
36
|
-
|
37
|
-
def __init__(self, num_interviews, lock, monitored_queue):
|
38
|
-
self.num_interviews = num_interviews # how many interviews are there in total
|
39
|
-
self.lock = lock
|
40
|
-
self.hearbeat = heartbeat_generator() # generator to show responses coming in
|
41
|
-
self.active_workers = 0
|
42
|
-
self.interviews_started = 0
|
43
|
-
self.interviews_completed = 0
|
44
|
-
self.thread_status = dict()
|
45
|
-
# this is a function that takes thread IDs and turns them into successive integers
|
46
|
-
self.human_readable_labeler = human_readable_labeler_creator()
|
47
|
-
|
48
|
-
super().__init__(monitored_queue)
|
49
|
-
|
50
|
-
def tracked_values(self) -> dict:
|
51
|
-
return {
|
52
|
-
"Active Workers": self.active_workers,
|
53
|
-
"Interviews Started": self.interviews_started,
|
54
|
-
"Completed Interviews": self.interviews_completed,
|
55
|
-
}
|
56
|
-
|
57
|
-
def allowed_events(self):
|
58
|
-
return set(
|
59
|
-
[
|
60
|
-
TrackerTasks.WorkerActivated,
|
61
|
-
TrackerTasks.WorkerDeactivated,
|
62
|
-
TrackerTasks.TaskStarted,
|
63
|
-
TrackerTasks.TaskCompleted,
|
64
|
-
TrackerTasks.ThreadStatus,
|
65
|
-
]
|
66
|
-
)
|
67
|
-
|
68
|
-
@property
|
69
|
-
def percentage_complete(self):
|
70
|
-
return round(100 * self.interviews_completed / self.num_interviews, 2)
|