edsl 0.1.47__py3-none-any.whl → 0.1.49__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/__init__.py +44 -39
- edsl/__version__.py +1 -1
- edsl/agents/__init__.py +4 -2
- edsl/agents/{Agent.py → agent.py} +442 -152
- edsl/agents/{AgentList.py → agent_list.py} +220 -162
- edsl/agents/descriptors.py +46 -7
- edsl/{exceptions/agents.py → agents/exceptions.py} +3 -12
- edsl/base/__init__.py +75 -0
- edsl/base/base_class.py +1303 -0
- edsl/base/data_transfer_models.py +114 -0
- edsl/base/enums.py +215 -0
- edsl/base.py +8 -0
- edsl/buckets/__init__.py +25 -0
- edsl/buckets/bucket_collection.py +324 -0
- edsl/buckets/model_buckets.py +206 -0
- edsl/buckets/token_bucket.py +502 -0
- edsl/{jobs/buckets/TokenBucketAPI.py → buckets/token_bucket_api.py} +1 -1
- edsl/buckets/token_bucket_client.py +509 -0
- edsl/caching/__init__.py +20 -0
- edsl/caching/cache.py +814 -0
- edsl/caching/cache_entry.py +427 -0
- edsl/{data/CacheHandler.py → caching/cache_handler.py} +14 -15
- edsl/caching/exceptions.py +24 -0
- edsl/caching/orm.py +30 -0
- edsl/{data/RemoteCacheSync.py → caching/remote_cache_sync.py} +3 -3
- edsl/caching/sql_dict.py +441 -0
- edsl/config/__init__.py +8 -0
- edsl/config/config_class.py +177 -0
- edsl/config.py +4 -176
- edsl/conversation/Conversation.py +7 -7
- edsl/conversation/car_buying.py +4 -4
- edsl/conversation/chips.py +6 -6
- edsl/coop/__init__.py +25 -2
- edsl/coop/coop.py +311 -75
- edsl/coop/{ExpectedParrotKeyHandler.py → ep_key_handling.py} +86 -10
- edsl/coop/exceptions.py +62 -0
- edsl/coop/price_fetcher.py +126 -0
- edsl/coop/utils.py +89 -24
- edsl/data_transfer_models.py +5 -72
- edsl/dataset/__init__.py +10 -0
- edsl/{results/Dataset.py → dataset/dataset.py} +116 -36
- edsl/{results/DatasetExportMixin.py → dataset/dataset_operations_mixin.py} +606 -122
- edsl/{results/DatasetTree.py → dataset/dataset_tree.py} +156 -75
- edsl/{results/TableDisplay.py → dataset/display/table_display.py} +18 -7
- edsl/{results → dataset/display}/table_renderers.py +58 -2
- edsl/{results → dataset}/file_exports.py +4 -5
- edsl/{results → dataset}/smart_objects.py +2 -2
- edsl/enums.py +5 -205
- edsl/inference_services/__init__.py +5 -0
- edsl/inference_services/{AvailableModelCacheHandler.py → available_model_cache_handler.py} +2 -3
- edsl/inference_services/{AvailableModelFetcher.py → available_model_fetcher.py} +8 -14
- edsl/inference_services/data_structures.py +3 -2
- edsl/{exceptions/inference_services.py → inference_services/exceptions.py} +1 -1
- edsl/inference_services/{InferenceServiceABC.py → inference_service_abc.py} +1 -1
- edsl/inference_services/{InferenceServicesCollection.py → inference_services_collection.py} +8 -7
- edsl/inference_services/registry.py +4 -41
- edsl/inference_services/{ServiceAvailability.py → service_availability.py} +5 -25
- edsl/inference_services/services/__init__.py +31 -0
- edsl/inference_services/{AnthropicService.py → services/anthropic_service.py} +3 -3
- edsl/inference_services/{AwsBedrock.py → services/aws_bedrock.py} +2 -2
- edsl/inference_services/{AzureAI.py → services/azure_ai.py} +2 -2
- edsl/inference_services/{DeepInfraService.py → services/deep_infra_service.py} +1 -3
- edsl/inference_services/{DeepSeekService.py → services/deep_seek_service.py} +2 -4
- edsl/inference_services/{GoogleService.py → services/google_service.py} +5 -4
- edsl/inference_services/{GroqService.py → services/groq_service.py} +1 -1
- edsl/inference_services/{MistralAIService.py → services/mistral_ai_service.py} +3 -3
- edsl/inference_services/{OllamaService.py → services/ollama_service.py} +1 -7
- edsl/inference_services/{OpenAIService.py → services/open_ai_service.py} +5 -6
- edsl/inference_services/{PerplexityService.py → services/perplexity_service.py} +3 -7
- edsl/inference_services/{TestService.py → services/test_service.py} +7 -6
- edsl/inference_services/{TogetherAIService.py → services/together_ai_service.py} +2 -6
- edsl/inference_services/{XAIService.py → services/xai_service.py} +1 -1
- edsl/inference_services/write_available.py +1 -2
- edsl/instructions/__init__.py +6 -0
- edsl/{surveys/instructions/Instruction.py → instructions/instruction.py} +11 -6
- edsl/{surveys/instructions/InstructionCollection.py → instructions/instruction_collection.py} +10 -5
- edsl/{surveys/InstructionHandler.py → instructions/instruction_handler.py} +3 -3
- edsl/{jobs/interviews → interviews}/ReportErrors.py +2 -2
- edsl/interviews/__init__.py +4 -0
- edsl/{jobs/AnswerQuestionFunctionConstructor.py → interviews/answering_function.py} +45 -18
- edsl/{jobs/interviews/InterviewExceptionEntry.py → interviews/exception_tracking.py} +107 -22
- edsl/interviews/interview.py +638 -0
- edsl/{jobs/interviews/InterviewStatusDictionary.py → interviews/interview_status_dictionary.py} +21 -12
- edsl/{jobs/interviews/InterviewStatusLog.py → interviews/interview_status_log.py} +16 -7
- edsl/{jobs/InterviewTaskManager.py → interviews/interview_task_manager.py} +12 -7
- edsl/{jobs/RequestTokenEstimator.py → interviews/request_token_estimator.py} +8 -3
- edsl/{jobs/interviews/InterviewStatistic.py → interviews/statistics.py} +36 -10
- edsl/invigilators/__init__.py +38 -0
- edsl/invigilators/invigilator_base.py +477 -0
- edsl/{agents/Invigilator.py → invigilators/invigilators.py} +263 -10
- edsl/invigilators/prompt_constructor.py +476 -0
- edsl/{agents → invigilators}/prompt_helpers.py +2 -1
- edsl/{agents/QuestionInstructionPromptBuilder.py → invigilators/question_instructions_prompt_builder.py} +18 -13
- edsl/{agents → invigilators}/question_option_processor.py +96 -21
- edsl/{agents/QuestionTemplateReplacementsBuilder.py → invigilators/question_template_replacements_builder.py} +64 -12
- edsl/jobs/__init__.py +7 -1
- edsl/jobs/async_interview_runner.py +99 -35
- edsl/jobs/check_survey_scenario_compatibility.py +7 -5
- edsl/jobs/data_structures.py +153 -22
- edsl/{exceptions/jobs.py → jobs/exceptions.py} +2 -1
- edsl/jobs/{FetchInvigilator.py → fetch_invigilator.py} +4 -4
- edsl/jobs/{loggers/HTMLTableJobLogger.py → html_table_job_logger.py} +6 -2
- edsl/jobs/{Jobs.py → jobs.py} +313 -167
- edsl/jobs/{JobsChecks.py → jobs_checks.py} +15 -7
- edsl/jobs/{JobsComponentConstructor.py → jobs_component_constructor.py} +19 -17
- edsl/jobs/{InterviewsConstructor.py → jobs_interview_constructor.py} +10 -5
- edsl/jobs/jobs_pricing_estimation.py +347 -0
- edsl/jobs/{JobsRemoteInferenceLogger.py → jobs_remote_inference_logger.py} +4 -3
- edsl/jobs/jobs_runner_asyncio.py +282 -0
- edsl/jobs/{JobsRemoteInferenceHandler.py → remote_inference.py} +19 -22
- edsl/jobs/results_exceptions_handler.py +2 -2
- edsl/key_management/__init__.py +28 -0
- edsl/key_management/key_lookup.py +161 -0
- edsl/{language_models/key_management/KeyLookupBuilder.py → key_management/key_lookup_builder.py} +118 -47
- edsl/key_management/key_lookup_collection.py +82 -0
- edsl/key_management/models.py +218 -0
- edsl/language_models/__init__.py +7 -2
- edsl/language_models/{ComputeCost.py → compute_cost.py} +18 -3
- edsl/{exceptions/language_models.py → language_models/exceptions.py} +2 -1
- edsl/language_models/language_model.py +1080 -0
- edsl/language_models/model.py +10 -25
- edsl/language_models/{ModelList.py → model_list.py} +9 -14
- edsl/language_models/{RawResponseHandler.py → raw_response_handler.py} +1 -1
- edsl/language_models/{RegisterLanguageModelsMeta.py → registry.py} +1 -1
- edsl/language_models/repair.py +4 -4
- edsl/language_models/utilities.py +4 -4
- edsl/notebooks/__init__.py +3 -1
- edsl/notebooks/{Notebook.py → notebook.py} +7 -8
- edsl/prompts/__init__.py +1 -1
- edsl/{exceptions/prompts.py → prompts/exceptions.py} +3 -1
- edsl/prompts/{Prompt.py → prompt.py} +101 -95
- edsl/questions/HTMLQuestion.py +1 -1
- edsl/questions/__init__.py +154 -25
- edsl/questions/answer_validator_mixin.py +1 -1
- edsl/questions/compose_questions.py +4 -3
- edsl/questions/derived/question_likert_five.py +166 -0
- edsl/questions/derived/{QuestionLinearScale.py → question_linear_scale.py} +4 -4
- edsl/questions/derived/{QuestionTopK.py → question_top_k.py} +4 -4
- edsl/questions/derived/{QuestionYesNo.py → question_yes_no.py} +4 -5
- edsl/questions/descriptors.py +24 -30
- edsl/questions/loop_processor.py +65 -19
- edsl/questions/question_base.py +881 -0
- edsl/questions/question_base_gen_mixin.py +15 -16
- edsl/questions/{QuestionBasePromptsMixin.py → question_base_prompts_mixin.py} +2 -2
- edsl/questions/{QuestionBudget.py → question_budget.py} +3 -4
- edsl/questions/{QuestionCheckBox.py → question_check_box.py} +16 -16
- edsl/questions/{QuestionDict.py → question_dict.py} +39 -5
- edsl/questions/{QuestionExtract.py → question_extract.py} +9 -9
- edsl/questions/question_free_text.py +282 -0
- edsl/questions/{QuestionFunctional.py → question_functional.py} +6 -5
- edsl/questions/{QuestionList.py → question_list.py} +6 -7
- edsl/questions/{QuestionMatrix.py → question_matrix.py} +6 -5
- edsl/questions/{QuestionMultipleChoice.py → question_multiple_choice.py} +126 -21
- edsl/questions/{QuestionNumerical.py → question_numerical.py} +5 -5
- edsl/questions/{QuestionRank.py → question_rank.py} +6 -6
- edsl/questions/question_registry.py +4 -9
- edsl/questions/register_questions_meta.py +8 -4
- edsl/questions/response_validator_abc.py +17 -16
- edsl/results/__init__.py +4 -1
- edsl/{exceptions/results.py → results/exceptions.py} +1 -1
- edsl/results/report.py +197 -0
- edsl/results/{Result.py → result.py} +131 -45
- edsl/results/{Results.py → results.py} +365 -220
- edsl/results/results_selector.py +344 -25
- edsl/scenarios/__init__.py +30 -3
- edsl/scenarios/{ConstructDownloadLink.py → construct_download_link.py} +7 -0
- edsl/scenarios/directory_scanner.py +156 -13
- edsl/scenarios/document_chunker.py +186 -0
- edsl/scenarios/exceptions.py +101 -0
- edsl/scenarios/file_methods.py +2 -3
- edsl/scenarios/{FileStore.py → file_store.py} +275 -189
- edsl/scenarios/handlers/__init__.py +14 -14
- edsl/scenarios/handlers/{csv.py → csv_file_store.py} +1 -2
- edsl/scenarios/handlers/{docx.py → docx_file_store.py} +8 -7
- edsl/scenarios/handlers/{html.py → html_file_store.py} +1 -2
- edsl/scenarios/handlers/{jpeg.py → jpeg_file_store.py} +1 -1
- edsl/scenarios/handlers/{json.py → json_file_store.py} +1 -1
- edsl/scenarios/handlers/latex_file_store.py +5 -0
- edsl/scenarios/handlers/{md.py → md_file_store.py} +1 -1
- edsl/scenarios/handlers/{pdf.py → pdf_file_store.py} +2 -2
- edsl/scenarios/handlers/{png.py → png_file_store.py} +1 -1
- edsl/scenarios/handlers/{pptx.py → pptx_file_store.py} +8 -7
- edsl/scenarios/handlers/{py.py → py_file_store.py} +1 -3
- edsl/scenarios/handlers/{sql.py → sql_file_store.py} +2 -1
- edsl/scenarios/handlers/{sqlite.py → sqlite_file_store.py} +2 -3
- edsl/scenarios/handlers/{txt.py → txt_file_store.py} +1 -1
- edsl/scenarios/scenario.py +928 -0
- edsl/scenarios/scenario_join.py +18 -5
- edsl/scenarios/{ScenarioList.py → scenario_list.py} +294 -106
- edsl/scenarios/{ScenarioListPdfMixin.py → scenario_list_pdf_tools.py} +16 -15
- edsl/scenarios/scenario_selector.py +5 -1
- edsl/study/ObjectEntry.py +2 -2
- edsl/study/SnapShot.py +5 -5
- edsl/study/Study.py +18 -19
- edsl/study/__init__.py +6 -4
- edsl/surveys/__init__.py +7 -4
- edsl/surveys/dag/__init__.py +2 -0
- edsl/surveys/{ConstructDAG.py → dag/construct_dag.py} +3 -3
- edsl/surveys/{DAG.py → dag/dag.py} +13 -10
- edsl/surveys/descriptors.py +1 -1
- edsl/surveys/{EditSurvey.py → edit_survey.py} +9 -9
- edsl/{exceptions/surveys.py → surveys/exceptions.py} +1 -2
- edsl/surveys/memory/__init__.py +3 -0
- edsl/surveys/{MemoryPlan.py → memory/memory_plan.py} +10 -9
- edsl/surveys/rules/__init__.py +3 -0
- edsl/surveys/{Rule.py → rules/rule.py} +103 -43
- edsl/surveys/{RuleCollection.py → rules/rule_collection.py} +21 -30
- edsl/surveys/{RuleManager.py → rules/rule_manager.py} +19 -13
- edsl/surveys/survey.py +1743 -0
- edsl/surveys/{SurveyExportMixin.py → survey_export.py} +22 -27
- edsl/surveys/{SurveyFlowVisualization.py → survey_flow_visualization.py} +11 -2
- edsl/surveys/{Simulator.py → survey_simulator.py} +10 -3
- edsl/tasks/__init__.py +32 -0
- edsl/{jobs/tasks/QuestionTaskCreator.py → tasks/question_task_creator.py} +115 -57
- edsl/tasks/task_creators.py +135 -0
- edsl/{jobs/tasks/TaskHistory.py → tasks/task_history.py} +86 -47
- edsl/{jobs/tasks → tasks}/task_status_enum.py +91 -7
- edsl/tasks/task_status_log.py +85 -0
- edsl/tokens/__init__.py +2 -0
- edsl/tokens/interview_token_usage.py +53 -0
- edsl/utilities/PrettyList.py +1 -1
- edsl/utilities/SystemInfo.py +25 -22
- edsl/utilities/__init__.py +29 -21
- edsl/utilities/gcp_bucket/__init__.py +2 -0
- edsl/utilities/gcp_bucket/cloud_storage.py +99 -96
- edsl/utilities/interface.py +44 -536
- edsl/{results/MarkdownToPDF.py → utilities/markdown_to_pdf.py} +13 -5
- edsl/utilities/repair_functions.py +1 -1
- {edsl-0.1.47.dist-info → edsl-0.1.49.dist-info}/METADATA +1 -1
- edsl-0.1.49.dist-info/RECORD +347 -0
- edsl/Base.py +0 -493
- edsl/BaseDiff.py +0 -260
- edsl/agents/InvigilatorBase.py +0 -260
- edsl/agents/PromptConstructor.py +0 -318
- edsl/coop/PriceFetcher.py +0 -54
- edsl/data/Cache.py +0 -582
- edsl/data/CacheEntry.py +0 -238
- edsl/data/SQLiteDict.py +0 -292
- edsl/data/__init__.py +0 -5
- edsl/data/orm.py +0 -10
- edsl/exceptions/cache.py +0 -5
- edsl/exceptions/coop.py +0 -14
- edsl/exceptions/data.py +0 -14
- edsl/exceptions/scenarios.py +0 -29
- edsl/jobs/Answers.py +0 -43
- edsl/jobs/JobsPrompts.py +0 -354
- edsl/jobs/buckets/BucketCollection.py +0 -134
- edsl/jobs/buckets/ModelBuckets.py +0 -65
- edsl/jobs/buckets/TokenBucket.py +0 -283
- edsl/jobs/buckets/TokenBucketClient.py +0 -191
- edsl/jobs/interviews/Interview.py +0 -395
- edsl/jobs/interviews/InterviewExceptionCollection.py +0 -99
- edsl/jobs/interviews/InterviewStatisticsCollection.py +0 -25
- edsl/jobs/runners/JobsRunnerAsyncio.py +0 -163
- edsl/jobs/runners/JobsRunnerStatusData.py +0 -0
- edsl/jobs/tasks/TaskCreators.py +0 -64
- edsl/jobs/tasks/TaskStatusLog.py +0 -23
- edsl/jobs/tokens/InterviewTokenUsage.py +0 -27
- edsl/language_models/LanguageModel.py +0 -635
- edsl/language_models/ServiceDataSources.py +0 -0
- edsl/language_models/key_management/KeyLookup.py +0 -63
- edsl/language_models/key_management/KeyLookupCollection.py +0 -38
- edsl/language_models/key_management/models.py +0 -137
- edsl/questions/QuestionBase.py +0 -544
- edsl/questions/QuestionFreeText.py +0 -130
- edsl/questions/derived/QuestionLikertFive.py +0 -76
- edsl/results/ResultsExportMixin.py +0 -45
- edsl/results/TextEditor.py +0 -50
- edsl/results/results_fetch_mixin.py +0 -33
- edsl/results/results_tools_mixin.py +0 -98
- edsl/scenarios/DocumentChunker.py +0 -104
- edsl/scenarios/Scenario.py +0 -548
- edsl/scenarios/ScenarioHtmlMixin.py +0 -65
- edsl/scenarios/ScenarioListExportMixin.py +0 -45
- edsl/scenarios/handlers/latex.py +0 -5
- edsl/shared.py +0 -1
- edsl/surveys/Survey.py +0 -1301
- edsl/surveys/SurveyQualtricsImport.py +0 -284
- edsl/surveys/SurveyToApp.py +0 -141
- edsl/surveys/instructions/__init__.py +0 -0
- edsl/tools/__init__.py +0 -1
- edsl/tools/clusters.py +0 -192
- edsl/tools/embeddings.py +0 -27
- edsl/tools/embeddings_plotting.py +0 -118
- edsl/tools/plotting.py +0 -112
- edsl/tools/summarize.py +0 -18
- edsl/utilities/data/Registry.py +0 -6
- edsl/utilities/data/__init__.py +0 -1
- edsl/utilities/data/scooter_results.json +0 -1
- edsl-0.1.47.dist-info/RECORD +0 -354
- /edsl/coop/{CoopFunctionsMixin.py → coop_functions.py} +0 -0
- /edsl/{results → dataset/display}/CSSParameterizer.py +0 -0
- /edsl/{language_models/key_management → dataset/display}/__init__.py +0 -0
- /edsl/{results → dataset/display}/table_data_class.py +0 -0
- /edsl/{results → dataset/display}/table_display.css +0 -0
- /edsl/{results/ResultsGGMixin.py → dataset/r/ggplot.py} +0 -0
- /edsl/{results → dataset}/tree_explore.py +0 -0
- /edsl/{surveys/instructions/ChangeInstruction.py → instructions/change_instruction.py} +0 -0
- /edsl/{jobs/interviews → interviews}/interview_status_enum.py +0 -0
- /edsl/jobs/{runners/JobsRunnerStatus.py → jobs_runner_status.py} +0 -0
- /edsl/language_models/{PriceManager.py → price_manager.py} +0 -0
- /edsl/language_models/{fake_openai_call.py → unused/fake_openai_call.py} +0 -0
- /edsl/language_models/{fake_openai_service.py → unused/fake_openai_service.py} +0 -0
- /edsl/notebooks/{NotebookToLaTeX.py → notebook_to_latex.py} +0 -0
- /edsl/{exceptions/questions.py → questions/exceptions.py} +0 -0
- /edsl/questions/{SimpleAskMixin.py → simple_ask_mixin.py} +0 -0
- /edsl/surveys/{Memory.py → memory/memory.py} +0 -0
- /edsl/surveys/{MemoryManagement.py → memory/memory_management.py} +0 -0
- /edsl/surveys/{SurveyCSS.py → survey_css.py} +0 -0
- /edsl/{jobs/tokens/TokenUsage.py → tokens/token_usage.py} +0 -0
- /edsl/{results/MarkdownToDocx.py → utilities/markdown_to_docx.py} +0 -0
- /edsl/{TemplateLoader.py → utilities/template_loader.py} +0 -0
- {edsl-0.1.47.dist-info → edsl-0.1.49.dist-info}/LICENSE +0 -0
- {edsl-0.1.47.dist-info → edsl-0.1.49.dist-info}/WHEEL +0 -0
@@ -0,0 +1,206 @@
|
|
1
|
+
"""
|
2
|
+
ModelBuckets module for managing rate limits for language model calls.
|
3
|
+
|
4
|
+
This module provides the ModelBuckets class, which manages both requests-per-minute
|
5
|
+
and tokens-per-minute rate limits for language model API services. Each ModelBuckets
|
6
|
+
instance contains two TokenBucket instances - one for requests and one for tokens.
|
7
|
+
"""
|
8
|
+
|
9
|
+
from typing import TYPE_CHECKING, Tuple, Optional, Any
|
10
|
+
import matplotlib.pyplot as plt
|
11
|
+
from matplotlib.figure import Figure
|
12
|
+
|
13
|
+
if TYPE_CHECKING:
|
14
|
+
from .token_bucket import TokenBucket
|
15
|
+
|
16
|
+
class ModelBuckets:
|
17
|
+
"""
|
18
|
+
Manages rate limits for a language model with separate request and token buckets.
|
19
|
+
|
20
|
+
ModelBuckets encapsulates two TokenBucket instances - one for tracking API request
|
21
|
+
limits (requests-per-minute) and another for tracking token usage limits
|
22
|
+
(tokens-per-minute). Most language model providers enforce both types of limits.
|
23
|
+
|
24
|
+
Note on terminology: While language models use "tokens" as units of text,
|
25
|
+
the term "token" in this context refers to rate limiting tokens in the
|
26
|
+
token bucket algorithm. This is different from the language model tokens.
|
27
|
+
|
28
|
+
Attributes:
|
29
|
+
requests_bucket (TokenBucket): Controls request rate limits (RPM)
|
30
|
+
tokens_bucket (TokenBucket): Controls token usage rate limits (TPM)
|
31
|
+
|
32
|
+
Example:
|
33
|
+
>>> from ..buckets.token_bucket import TokenBucket
|
34
|
+
>>> requests_bucket = TokenBucket(bucket_name="gpt-4", bucket_type="requests",
|
35
|
+
... capacity=100, refill_rate=10)
|
36
|
+
>>> tokens_bucket = TokenBucket(bucket_name="gpt-4", bucket_type="tokens",
|
37
|
+
... capacity=100000, refill_rate=10000)
|
38
|
+
>>> model_buckets = ModelBuckets(requests_bucket, tokens_bucket)
|
39
|
+
"""
|
40
|
+
|
41
|
+
def __init__(self, requests_bucket: "TokenBucket", tokens_bucket: "TokenBucket"):
|
42
|
+
"""
|
43
|
+
Initialize a ModelBuckets instance with request and token rate limiting buckets.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
requests_bucket: TokenBucket controlling requests-per-minute (RPM) limits
|
47
|
+
tokens_bucket: TokenBucket controlling tokens-per-minute (TPM) limits
|
48
|
+
|
49
|
+
Example:
|
50
|
+
>>> from edsl.buckets import TokenBucket
|
51
|
+
>>> requests_bucket = TokenBucket(bucket_name="gpt-4", bucket_type="requests", capacity=100, refill_rate=10)
|
52
|
+
>>> tokens_bucket = TokenBucket(bucket_name="gpt-4", bucket_type="tokens", capacity=100000, refill_rate=10000)
|
53
|
+
>>> buckets = ModelBuckets(requests_bucket, tokens_bucket)
|
54
|
+
"""
|
55
|
+
self.requests_bucket = requests_bucket
|
56
|
+
self.tokens_bucket = tokens_bucket
|
57
|
+
|
58
|
+
def __add__(self, other: "ModelBuckets") -> "ModelBuckets":
|
59
|
+
"""
|
60
|
+
Combine two ModelBuckets instances to create a merged bucket.
|
61
|
+
|
62
|
+
This method allows combining rate limits from two different ModelBuckets
|
63
|
+
instances. The resulting bucket will have the combined capacity and refill
|
64
|
+
rates of both the input buckets.
|
65
|
+
|
66
|
+
Args:
|
67
|
+
other: Another ModelBuckets instance to combine with this one
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
A new ModelBuckets instance with combined rate limits
|
71
|
+
|
72
|
+
Example:
|
73
|
+
>>> # Create two model buckets and combine them
|
74
|
+
>>> from edsl.buckets.token_bucket import TokenBucket
|
75
|
+
>>> bucket1 = ModelBuckets.infinity_bucket("model1")
|
76
|
+
>>> bucket2 = ModelBuckets.infinity_bucket("model2")
|
77
|
+
>>> combined = bucket1 + bucket2
|
78
|
+
"""
|
79
|
+
return ModelBuckets(
|
80
|
+
requests_bucket=self.requests_bucket + other.requests_bucket,
|
81
|
+
tokens_bucket=self.tokens_bucket + other.tokens_bucket,
|
82
|
+
)
|
83
|
+
|
84
|
+
def turbo_mode_on(self) -> None:
|
85
|
+
"""
|
86
|
+
Enable turbo mode for both request and token buckets.
|
87
|
+
|
88
|
+
Turbo mode sets the refill rate to infinity for both buckets,
|
89
|
+
effectively bypassing rate limits. This is useful for testing
|
90
|
+
or when rate limits are not needed.
|
91
|
+
|
92
|
+
Example:
|
93
|
+
>>> buckets = ModelBuckets.infinity_bucket("test")
|
94
|
+
>>> buckets.turbo_mode_on() # Now rate limits are bypassed
|
95
|
+
"""
|
96
|
+
self.requests_bucket.turbo_mode_on()
|
97
|
+
self.tokens_bucket.turbo_mode_on()
|
98
|
+
|
99
|
+
def turbo_mode_off(self) -> None:
|
100
|
+
"""
|
101
|
+
Disable turbo mode and restore original rate limits.
|
102
|
+
|
103
|
+
This method restores the original refill rates for both buckets,
|
104
|
+
re-enabling rate limiting after it was bypassed with turbo_mode_on().
|
105
|
+
|
106
|
+
Example:
|
107
|
+
>>> buckets = ModelBuckets.infinity_bucket("test")
|
108
|
+
>>> buckets.turbo_mode_on() # Bypass rate limits
|
109
|
+
>>> # Do some work without rate limiting
|
110
|
+
>>> buckets.turbo_mode_off() # Restore rate limits
|
111
|
+
"""
|
112
|
+
self.requests_bucket.turbo_mode_off()
|
113
|
+
self.tokens_bucket.turbo_mode_off()
|
114
|
+
|
115
|
+
@classmethod
|
116
|
+
def infinity_bucket(cls, model_name: str = "not_specified") -> "ModelBuckets":
|
117
|
+
"""
|
118
|
+
Create a ModelBuckets instance with unlimited capacity and refill rate.
|
119
|
+
|
120
|
+
This factory method creates a ModelBuckets with infinite capacity and
|
121
|
+
refill rate for both request and token buckets, effectively creating
|
122
|
+
a bucket with no rate limits.
|
123
|
+
|
124
|
+
Args:
|
125
|
+
model_name: Name identifier for the model (default: "not_specified")
|
126
|
+
|
127
|
+
Returns:
|
128
|
+
A ModelBuckets instance with unlimited rate limits
|
129
|
+
|
130
|
+
Example:
|
131
|
+
>>> unlimited = ModelBuckets.infinity_bucket("gpt-4")
|
132
|
+
>>> # This bucket will never throttle requests
|
133
|
+
"""
|
134
|
+
from .token_bucket import TokenBucket
|
135
|
+
|
136
|
+
return cls(
|
137
|
+
requests_bucket=TokenBucket(
|
138
|
+
bucket_name=model_name,
|
139
|
+
bucket_type="requests",
|
140
|
+
capacity=float("inf"),
|
141
|
+
refill_rate=float("inf"),
|
142
|
+
),
|
143
|
+
tokens_bucket=TokenBucket(
|
144
|
+
bucket_name=model_name,
|
145
|
+
bucket_type="tokens",
|
146
|
+
capacity=float("inf"),
|
147
|
+
refill_rate=float("inf"),
|
148
|
+
),
|
149
|
+
)
|
150
|
+
|
151
|
+
def visualize(self) -> Tuple[Figure, Figure]:
|
152
|
+
"""
|
153
|
+
Create visualizations of token usage over time for both buckets.
|
154
|
+
|
155
|
+
This method generates matplotlib plots showing token usage over time
|
156
|
+
for both the request bucket and token bucket, which can be useful for
|
157
|
+
monitoring and debugging rate limit issues.
|
158
|
+
|
159
|
+
Returns:
|
160
|
+
A tuple containing two matplotlib Figures (requests_plot, tokens_plot)
|
161
|
+
|
162
|
+
Example:
|
163
|
+
>>> ## buckets = ModelBuckets.infinity_bucket("test")
|
164
|
+
>>> ## request_plot, token_plot = buckets.visualize()
|
165
|
+
>>> ## Now you can display or save these plots
|
166
|
+
"""
|
167
|
+
plot1 = self.requests_bucket.visualize()
|
168
|
+
plot2 = self.tokens_bucket.visualize()
|
169
|
+
return plot1, plot2
|
170
|
+
|
171
|
+
def __repr__(self) -> str:
|
172
|
+
"""
|
173
|
+
Generate a string representation of the ModelBuckets instance.
|
174
|
+
|
175
|
+
Returns:
|
176
|
+
A string showing the requests and tokens buckets contained in this instance
|
177
|
+
"""
|
178
|
+
return f"ModelBuckets(requests_bucket={self.requests_bucket}, tokens_bucket={self.tokens_bucket})"
|
179
|
+
|
180
|
+
|
181
|
+
# Example usage and doctests
|
182
|
+
if __name__ == "__main__":
|
183
|
+
import doctest
|
184
|
+
|
185
|
+
# Example showing how to create and use ModelBuckets
|
186
|
+
def example_usage():
|
187
|
+
"""
|
188
|
+
Example demonstrating how to use ModelBuckets:
|
189
|
+
|
190
|
+
>>> from edsl.buckets.token_bucket import TokenBucket
|
191
|
+
>>> # Create buckets for a model with RPM=100, TPM=100000
|
192
|
+
>>> requests_bucket = TokenBucket("gpt-4", "requests", 100, 10)
|
193
|
+
>>> tokens_bucket = TokenBucket("gpt-4", "tokens", 100000, 10000)
|
194
|
+
>>> model_buckets = ModelBuckets(requests_bucket, tokens_bucket)
|
195
|
+
>>>
|
196
|
+
>>> # Use turbo mode to temporarily bypass rate limits
|
197
|
+
>>> model_buckets.turbo_mode_on()
|
198
|
+
>>> model_buckets.turbo_mode_off()
|
199
|
+
>>>
|
200
|
+
>>> # Visualize the current state of the buckets
|
201
|
+
>>> # plots = model_buckets.visualize()
|
202
|
+
"""
|
203
|
+
pass
|
204
|
+
|
205
|
+
# Run doctests
|
206
|
+
doctest.testmod(optionflags=doctest.ELLIPSIS)
|