edsl 0.1.39.dev3__py3-none-any.whl → 0.1.39.dev5__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 +413 -332
- edsl/BaseDiff.py +260 -260
- edsl/TemplateLoader.py +24 -24
- edsl/__init__.py +57 -49
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +1071 -867
- edsl/agents/AgentList.py +551 -413
- edsl/agents/Invigilator.py +284 -233
- edsl/agents/InvigilatorBase.py +257 -270
- edsl/agents/PromptConstructor.py +272 -354
- edsl/agents/QuestionInstructionPromptBuilder.py +128 -0
- edsl/agents/QuestionTemplateReplacementsBuilder.py +137 -0
- edsl/agents/__init__.py +2 -3
- edsl/agents/descriptors.py +99 -99
- edsl/agents/prompt_helpers.py +129 -129
- edsl/agents/question_option_processor.py +172 -0
- edsl/auto/AutoStudy.py +130 -117
- edsl/auto/StageBase.py +243 -230
- edsl/auto/StageGenerateSurvey.py +178 -178
- edsl/auto/StageLabelQuestions.py +125 -125
- edsl/auto/StagePersona.py +61 -61
- edsl/auto/StagePersonaDimensionValueRanges.py +88 -88
- edsl/auto/StagePersonaDimensionValues.py +74 -74
- edsl/auto/StagePersonaDimensions.py +69 -69
- edsl/auto/StageQuestions.py +74 -73
- edsl/auto/SurveyCreatorPipeline.py +21 -21
- edsl/auto/utilities.py +218 -224
- edsl/base/Base.py +279 -279
- edsl/config.py +177 -157
- edsl/conversation/Conversation.py +290 -290
- edsl/conversation/car_buying.py +59 -58
- edsl/conversation/chips.py +95 -95
- edsl/conversation/mug_negotiation.py +81 -81
- edsl/conversation/next_speaker_utilities.py +93 -93
- edsl/coop/CoopFunctionsMixin.py +15 -0
- edsl/coop/ExpectedParrotKeyHandler.py +125 -0
- edsl/coop/PriceFetcher.py +54 -54
- edsl/coop/__init__.py +2 -2
- edsl/coop/coop.py +1106 -1028
- edsl/coop/utils.py +131 -131
- edsl/data/Cache.py +573 -555
- edsl/data/CacheEntry.py +230 -233
- edsl/data/CacheHandler.py +168 -149
- edsl/data/RemoteCacheSync.py +186 -78
- edsl/data/SQLiteDict.py +292 -292
- edsl/data/__init__.py +5 -4
- edsl/data/orm.py +10 -10
- edsl/data_transfer_models.py +74 -73
- edsl/enums.py +202 -175
- edsl/exceptions/BaseException.py +21 -21
- edsl/exceptions/__init__.py +54 -54
- edsl/exceptions/agents.py +54 -42
- edsl/exceptions/cache.py +5 -5
- edsl/exceptions/configuration.py +16 -16
- edsl/exceptions/coop.py +10 -10
- edsl/exceptions/data.py +14 -14
- edsl/exceptions/general.py +34 -34
- edsl/exceptions/inference_services.py +5 -0
- edsl/exceptions/jobs.py +33 -33
- edsl/exceptions/language_models.py +63 -63
- edsl/exceptions/prompts.py +15 -15
- edsl/exceptions/questions.py +109 -91
- edsl/exceptions/results.py +29 -29
- edsl/exceptions/scenarios.py +29 -22
- edsl/exceptions/surveys.py +37 -37
- edsl/inference_services/AnthropicService.py +106 -87
- edsl/inference_services/AvailableModelCacheHandler.py +184 -0
- edsl/inference_services/AvailableModelFetcher.py +215 -0
- edsl/inference_services/AwsBedrock.py +118 -120
- edsl/inference_services/AzureAI.py +215 -217
- edsl/inference_services/DeepInfraService.py +18 -18
- edsl/inference_services/GoogleService.py +143 -148
- edsl/inference_services/GroqService.py +20 -20
- edsl/inference_services/InferenceServiceABC.py +80 -147
- edsl/inference_services/InferenceServicesCollection.py +138 -97
- edsl/inference_services/MistralAIService.py +120 -123
- edsl/inference_services/OllamaService.py +18 -18
- edsl/inference_services/OpenAIService.py +236 -224
- edsl/inference_services/PerplexityService.py +160 -163
- edsl/inference_services/ServiceAvailability.py +135 -0
- edsl/inference_services/TestService.py +90 -89
- edsl/inference_services/TogetherAIService.py +172 -170
- edsl/inference_services/data_structures.py +134 -0
- edsl/inference_services/models_available_cache.py +118 -118
- edsl/inference_services/rate_limits_cache.py +25 -25
- edsl/inference_services/registry.py +41 -41
- edsl/inference_services/write_available.py +10 -10
- edsl/jobs/AnswerQuestionFunctionConstructor.py +223 -0
- edsl/jobs/Answers.py +43 -56
- edsl/jobs/FetchInvigilator.py +47 -0
- edsl/jobs/InterviewTaskManager.py +98 -0
- edsl/jobs/InterviewsConstructor.py +50 -0
- edsl/jobs/Jobs.py +823 -898
- edsl/jobs/JobsChecks.py +172 -147
- edsl/jobs/JobsComponentConstructor.py +189 -0
- edsl/jobs/JobsPrompts.py +270 -268
- edsl/jobs/JobsRemoteInferenceHandler.py +311 -239
- edsl/jobs/JobsRemoteInferenceLogger.py +239 -0
- edsl/jobs/RequestTokenEstimator.py +30 -0
- edsl/jobs/__init__.py +1 -1
- edsl/jobs/async_interview_runner.py +138 -0
- edsl/jobs/buckets/BucketCollection.py +104 -63
- edsl/jobs/buckets/ModelBuckets.py +65 -65
- edsl/jobs/buckets/TokenBucket.py +283 -251
- 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 +396 -661
- edsl/jobs/interviews/InterviewExceptionCollection.py +99 -99
- edsl/jobs/interviews/InterviewExceptionEntry.py +186 -186
- edsl/jobs/interviews/InterviewStatistic.py +63 -63
- edsl/jobs/interviews/InterviewStatisticsCollection.py +25 -25
- edsl/jobs/interviews/InterviewStatusDictionary.py +78 -78
- edsl/jobs/interviews/InterviewStatusLog.py +92 -92
- edsl/jobs/interviews/ReportErrors.py +66 -66
- edsl/jobs/interviews/interview_status_enum.py +9 -9
- 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 -466
- edsl/jobs/runners/JobsRunnerStatus.py +297 -330
- edsl/jobs/tasks/QuestionTaskCreator.py +244 -242
- edsl/jobs/tasks/TaskCreators.py +64 -64
- edsl/jobs/tasks/TaskHistory.py +470 -450
- edsl/jobs/tasks/TaskStatusLog.py +23 -23
- edsl/jobs/tasks/task_status_enum.py +161 -163
- edsl/jobs/tokens/InterviewTokenUsage.py +27 -27
- edsl/jobs/tokens/TokenUsage.py +34 -34
- edsl/language_models/ComputeCost.py +63 -0
- edsl/language_models/LanguageModel.py +626 -668
- edsl/language_models/ModelList.py +164 -155
- edsl/language_models/PriceManager.py +127 -0
- edsl/language_models/RawResponseHandler.py +106 -0
- edsl/language_models/RegisterLanguageModelsMeta.py +184 -184
- edsl/language_models/ServiceDataSources.py +0 -0
- edsl/language_models/__init__.py +2 -3
- edsl/language_models/fake_openai_call.py +15 -15
- edsl/language_models/fake_openai_service.py +61 -61
- 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 +156 -156
- edsl/language_models/utilities.py +65 -64
- edsl/notebooks/Notebook.py +263 -258
- edsl/notebooks/NotebookToLaTeX.py +142 -0
- edsl/notebooks/__init__.py +1 -1
- edsl/prompts/Prompt.py +352 -362
- edsl/prompts/__init__.py +2 -2
- edsl/questions/ExceptionExplainer.py +77 -0
- edsl/questions/HTMLQuestion.py +103 -0
- edsl/questions/QuestionBase.py +518 -664
- edsl/questions/QuestionBasePromptsMixin.py +221 -217
- edsl/questions/QuestionBudget.py +227 -227
- edsl/questions/QuestionCheckBox.py +359 -359
- edsl/questions/QuestionExtract.py +180 -182
- edsl/questions/QuestionFreeText.py +113 -114
- edsl/questions/QuestionFunctional.py +166 -166
- edsl/questions/QuestionList.py +223 -231
- edsl/questions/QuestionMatrix.py +265 -0
- edsl/questions/QuestionMultipleChoice.py +330 -286
- edsl/questions/QuestionNumerical.py +151 -153
- edsl/questions/QuestionRank.py +314 -324
- edsl/questions/Quick.py +41 -41
- edsl/questions/SimpleAskMixin.py +74 -73
- edsl/questions/__init__.py +27 -26
- edsl/questions/{AnswerValidatorMixin.py → answer_validator_mixin.py} +334 -289
- edsl/questions/compose_questions.py +98 -98
- edsl/questions/data_structures.py +20 -0
- edsl/questions/decorators.py +21 -21
- edsl/questions/derived/QuestionLikertFive.py +76 -76
- edsl/questions/derived/QuestionLinearScale.py +90 -87
- edsl/questions/derived/QuestionTopK.py +93 -93
- edsl/questions/derived/QuestionYesNo.py +82 -82
- edsl/questions/descriptors.py +427 -413
- edsl/questions/loop_processor.py +149 -0
- edsl/questions/prompt_templates/question_budget.jinja +13 -13
- edsl/questions/prompt_templates/question_checkbox.jinja +32 -32
- edsl/questions/prompt_templates/question_extract.jinja +11 -11
- edsl/questions/prompt_templates/question_free_text.jinja +3 -3
- edsl/questions/prompt_templates/question_linear_scale.jinja +11 -11
- edsl/questions/prompt_templates/question_list.jinja +17 -17
- edsl/questions/prompt_templates/question_multiple_choice.jinja +33 -33
- edsl/questions/prompt_templates/question_numerical.jinja +36 -36
- edsl/questions/{QuestionBaseGenMixin.py → question_base_gen_mixin.py} +168 -161
- edsl/questions/question_registry.py +177 -177
- edsl/questions/{RegisterQuestionsMeta.py → register_questions_meta.py} +71 -71
- edsl/questions/{ResponseValidatorABC.py → response_validator_abc.py} +188 -174
- edsl/questions/response_validator_factory.py +34 -0
- edsl/questions/settings.py +12 -12
- edsl/questions/templates/budget/answering_instructions.jinja +7 -7
- edsl/questions/templates/budget/question_presentation.jinja +7 -7
- edsl/questions/templates/checkbox/answering_instructions.jinja +10 -10
- edsl/questions/templates/checkbox/question_presentation.jinja +22 -22
- edsl/questions/templates/extract/answering_instructions.jinja +7 -7
- edsl/questions/templates/likert_five/answering_instructions.jinja +10 -10
- edsl/questions/templates/likert_five/question_presentation.jinja +11 -11
- edsl/questions/templates/linear_scale/answering_instructions.jinja +5 -5
- edsl/questions/templates/linear_scale/question_presentation.jinja +5 -5
- edsl/questions/templates/list/answering_instructions.jinja +3 -3
- edsl/questions/templates/list/question_presentation.jinja +5 -5
- 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/answering_instructions.jinja +9 -9
- edsl/questions/templates/multiple_choice/question_presentation.jinja +11 -11
- edsl/questions/templates/numerical/answering_instructions.jinja +6 -6
- edsl/questions/templates/numerical/question_presentation.jinja +6 -6
- edsl/questions/templates/rank/answering_instructions.jinja +11 -11
- edsl/questions/templates/rank/question_presentation.jinja +15 -15
- edsl/questions/templates/top_k/answering_instructions.jinja +8 -8
- edsl/questions/templates/top_k/question_presentation.jinja +22 -22
- edsl/questions/templates/yes_no/answering_instructions.jinja +6 -6
- edsl/questions/templates/yes_no/question_presentation.jinja +11 -11
- edsl/results/CSSParameterizer.py +108 -108
- edsl/results/Dataset.py +587 -424
- edsl/results/DatasetExportMixin.py +594 -731
- edsl/results/DatasetTree.py +295 -275
- edsl/results/MarkdownToDocx.py +122 -0
- edsl/results/MarkdownToPDF.py +111 -0
- edsl/results/Result.py +557 -465
- edsl/results/Results.py +1183 -1165
- edsl/results/ResultsExportMixin.py +45 -43
- edsl/results/ResultsGGMixin.py +121 -121
- edsl/results/TableDisplay.py +125 -198
- edsl/results/TextEditor.py +50 -0
- edsl/results/__init__.py +2 -2
- edsl/results/file_exports.py +252 -0
- edsl/results/{ResultsFetchMixin.py → results_fetch_mixin.py} +33 -33
- edsl/results/{Selector.py → results_selector.py} +145 -135
- edsl/results/{ResultsToolsMixin.py → results_tools_mixin.py} +98 -98
- edsl/results/smart_objects.py +96 -0
- edsl/results/table_data_class.py +12 -0
- edsl/results/table_display.css +77 -77
- edsl/results/table_renderers.py +118 -0
- edsl/results/tree_explore.py +115 -115
- edsl/scenarios/ConstructDownloadLink.py +109 -0
- edsl/scenarios/DocumentChunker.py +102 -0
- edsl/scenarios/DocxScenario.py +16 -0
- edsl/scenarios/FileStore.py +511 -632
- edsl/scenarios/PdfExtractor.py +40 -0
- edsl/scenarios/Scenario.py +498 -601
- edsl/scenarios/ScenarioHtmlMixin.py +65 -64
- edsl/scenarios/ScenarioList.py +1458 -1287
- edsl/scenarios/ScenarioListExportMixin.py +45 -52
- edsl/scenarios/ScenarioListPdfMixin.py +239 -261
- edsl/scenarios/__init__.py +3 -4
- 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 +38 -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/{ScenarioJoin.py → scenario_join.py} +131 -127
- edsl/scenarios/scenario_selector.py +156 -0
- edsl/shared.py +1 -1
- edsl/study/ObjectEntry.py +173 -173
- edsl/study/ProofOfWork.py +113 -113
- edsl/study/SnapShot.py +80 -80
- edsl/study/Study.py +521 -528
- edsl/study/__init__.py +4 -4
- edsl/surveys/ConstructDAG.py +92 -0
- edsl/surveys/DAG.py +148 -148
- edsl/surveys/EditSurvey.py +221 -0
- edsl/surveys/InstructionHandler.py +100 -0
- edsl/surveys/Memory.py +31 -31
- edsl/surveys/MemoryManagement.py +72 -0
- edsl/surveys/MemoryPlan.py +244 -244
- edsl/surveys/Rule.py +327 -326
- edsl/surveys/RuleCollection.py +385 -387
- edsl/surveys/RuleManager.py +172 -0
- edsl/surveys/Simulator.py +75 -0
- edsl/surveys/Survey.py +1280 -1801
- edsl/surveys/SurveyCSS.py +273 -261
- edsl/surveys/SurveyExportMixin.py +259 -259
- edsl/surveys/{SurveyFlowVisualizationMixin.py → SurveyFlowVisualization.py} +181 -179
- edsl/surveys/SurveyQualtricsImport.py +284 -284
- edsl/surveys/SurveyToApp.py +141 -0
- edsl/surveys/__init__.py +5 -3
- edsl/surveys/base.py +53 -53
- edsl/surveys/descriptors.py +60 -56
- edsl/surveys/instructions/ChangeInstruction.py +48 -49
- edsl/surveys/instructions/Instruction.py +56 -65
- edsl/surveys/instructions/InstructionCollection.py +82 -77
- edsl/templates/error_reporting/base.html +23 -23
- edsl/templates/error_reporting/exceptions_by_model.html +34 -34
- edsl/templates/error_reporting/exceptions_by_question_name.html +16 -16
- edsl/templates/error_reporting/exceptions_by_type.html +16 -16
- edsl/templates/error_reporting/interview_details.html +115 -115
- edsl/templates/error_reporting/interviews.html +19 -19
- edsl/templates/error_reporting/overview.html +4 -4
- edsl/templates/error_reporting/performance_plot.html +1 -1
- edsl/templates/error_reporting/report.css +73 -73
- edsl/templates/error_reporting/report.html +117 -117
- edsl/templates/error_reporting/report.js +25 -25
- edsl/tools/__init__.py +1 -1
- edsl/tools/clusters.py +192 -192
- edsl/tools/embeddings.py +27 -27
- edsl/tools/embeddings_plotting.py +118 -118
- edsl/tools/plotting.py +112 -112
- edsl/tools/summarize.py +18 -18
- edsl/utilities/PrettyList.py +56 -0
- edsl/utilities/SystemInfo.py +28 -28
- edsl/utilities/__init__.py +22 -22
- edsl/utilities/ast_utilities.py +25 -25
- edsl/utilities/data/Registry.py +6 -6
- edsl/utilities/data/__init__.py +1 -1
- edsl/utilities/data/scooter_results.json +1 -1
- edsl/utilities/decorators.py +77 -77
- edsl/utilities/gcp_bucket/cloud_storage.py +96 -96
- edsl/utilities/interface.py +627 -627
- edsl/utilities/is_notebook.py +18 -0
- edsl/utilities/is_valid_variable_name.py +11 -0
- edsl/utilities/naming_utilities.py +263 -263
- edsl/utilities/remove_edsl_version.py +24 -0
- edsl/utilities/repair_functions.py +28 -28
- edsl/utilities/restricted_python.py +70 -70
- edsl/utilities/utilities.py +436 -424
- {edsl-0.1.39.dev3.dist-info → edsl-0.1.39.dev5.dist-info}/LICENSE +21 -21
- {edsl-0.1.39.dev3.dist-info → edsl-0.1.39.dev5.dist-info}/METADATA +13 -11
- edsl-0.1.39.dev5.dist-info/RECORD +358 -0
- {edsl-0.1.39.dev3.dist-info → edsl-0.1.39.dev5.dist-info}/WHEEL +1 -1
- edsl/language_models/KeyLookup.py +0 -30
- edsl/language_models/registry.py +0 -190
- edsl/language_models/unused/ReplicateBase.py +0 -83
- edsl/results/ResultsDBMixin.py +0 -238
- edsl-0.1.39.dev3.dist-info/RECORD +0 -277
@@ -1,217 +1,215 @@
|
|
1
|
-
import os
|
2
|
-
from typing import Any, Optional, List
|
3
|
-
import re
|
4
|
-
from openai import AsyncAzureOpenAI
|
5
|
-
from edsl.inference_services.InferenceServiceABC import InferenceServiceABC
|
6
|
-
from edsl.language_models.LanguageModel import LanguageModel
|
7
|
-
|
8
|
-
from azure.ai.inference.aio import ChatCompletionsClient
|
9
|
-
from azure.core.credentials import AzureKeyCredential
|
10
|
-
from azure.ai.inference.models import SystemMessage, UserMessage
|
11
|
-
import asyncio
|
12
|
-
import json
|
13
|
-
from edsl.utilities.utilities import fix_partial_correct_response
|
14
|
-
|
15
|
-
|
16
|
-
def json_handle_none(value: Any) -> Any:
|
17
|
-
"""
|
18
|
-
Handle None values during JSON serialization.
|
19
|
-
- Return "null" if the value is None. Otherwise, don't return anything.
|
20
|
-
"""
|
21
|
-
if value is None:
|
22
|
-
return "null"
|
23
|
-
|
24
|
-
|
25
|
-
class AzureAIService(InferenceServiceABC):
|
26
|
-
"""Azure AI service class."""
|
27
|
-
|
28
|
-
# key_sequence = ["content", 0, "text"] # ["content"][0]["text"]
|
29
|
-
key_sequence = ["choices", 0, "message", "content"]
|
30
|
-
usage_sequence = ["usage"]
|
31
|
-
input_token_name = "prompt_tokens"
|
32
|
-
output_token_name = "completion_tokens"
|
33
|
-
|
34
|
-
_inference_service_ = "azure"
|
35
|
-
_env_key_name_ = (
|
36
|
-
"AZURE_ENDPOINT_URL_AND_KEY" # Environment variable for Azure API key
|
37
|
-
)
|
38
|
-
_model_id_to_endpoint_and_key = {}
|
39
|
-
model_exclude_list = [
|
40
|
-
"Cohere-command-r-plus-xncmg",
|
41
|
-
"Mistral-Nemo-klfsi",
|
42
|
-
"Mistral-large-2407-ojfld",
|
43
|
-
]
|
44
|
-
|
45
|
-
@classmethod
|
46
|
-
def available(cls):
|
47
|
-
out = []
|
48
|
-
azure_endpoints = os.getenv("AZURE_ENDPOINT_URL_AND_KEY", None)
|
49
|
-
if not azure_endpoints:
|
50
|
-
raise EnvironmentError(f"AZURE_ENDPOINT_URL_AND_KEY is not defined")
|
51
|
-
azure_endpoints = azure_endpoints.split(",")
|
52
|
-
for data in azure_endpoints:
|
53
|
-
try:
|
54
|
-
# data has this format for non openai models https://model_id.azure_endpoint:azure_key
|
55
|
-
_, endpoint, azure_endpoint_key = data.split(":")
|
56
|
-
if "openai" not in endpoint:
|
57
|
-
model_id = endpoint.split(".")[0].replace("/", "")
|
58
|
-
out.append(model_id)
|
59
|
-
cls._model_id_to_endpoint_and_key[model_id] = {
|
60
|
-
"endpoint": f"https:{endpoint}",
|
61
|
-
"azure_endpoint_key": azure_endpoint_key,
|
62
|
-
}
|
63
|
-
else:
|
64
|
-
# data has this format for openai models ,https://azure_project_id.openai.azure.com/openai/deployments/gpt-4o-mini/chat/completions?api-version=2023-03-15-preview:azure_key
|
65
|
-
if "/deployments/" in endpoint:
|
66
|
-
start_idx = endpoint.index("/deployments/") + len(
|
67
|
-
"/deployments/"
|
68
|
-
)
|
69
|
-
end_idx = (
|
70
|
-
endpoint.index("/", start_idx)
|
71
|
-
if "/" in endpoint[start_idx:]
|
72
|
-
else len(endpoint)
|
73
|
-
)
|
74
|
-
model_id = endpoint[start_idx:end_idx]
|
75
|
-
api_version_value = None
|
76
|
-
if "api-version=" in endpoint:
|
77
|
-
start_idx = endpoint.index("api-version=") + len(
|
78
|
-
"api-version="
|
79
|
-
)
|
80
|
-
end_idx = (
|
81
|
-
endpoint.index("&", start_idx)
|
82
|
-
if "&" in endpoint[start_idx:]
|
83
|
-
else len(endpoint)
|
84
|
-
)
|
85
|
-
api_version_value = endpoint[start_idx:end_idx]
|
86
|
-
|
87
|
-
cls._model_id_to_endpoint_and_key[f"azure:{model_id}"] = {
|
88
|
-
"endpoint": f"https:{endpoint}",
|
89
|
-
"azure_endpoint_key": azure_endpoint_key,
|
90
|
-
"api_version": api_version_value,
|
91
|
-
}
|
92
|
-
out.append(f"azure:{model_id}")
|
93
|
-
|
94
|
-
except Exception as e:
|
95
|
-
raise e
|
96
|
-
return [m for m in out if m not in cls.model_exclude_list]
|
97
|
-
|
98
|
-
@classmethod
|
99
|
-
def create_model(
|
100
|
-
cls, model_name: str = "azureai", model_class_name=None
|
101
|
-
) -> LanguageModel:
|
102
|
-
if model_class_name is None:
|
103
|
-
model_class_name = cls.to_class_name(model_name)
|
104
|
-
|
105
|
-
class LLM(LanguageModel):
|
106
|
-
"""
|
107
|
-
Child class of LanguageModel for interacting with Azure OpenAI models.
|
108
|
-
"""
|
109
|
-
|
110
|
-
key_sequence = cls.key_sequence
|
111
|
-
usage_sequence = cls.usage_sequence
|
112
|
-
input_token_name = cls.input_token_name
|
113
|
-
output_token_name = cls.output_token_name
|
114
|
-
_inference_service_ = cls._inference_service_
|
115
|
-
_model_ = model_name
|
116
|
-
_parameters_ = {
|
117
|
-
"temperature": 0.5,
|
118
|
-
"max_tokens": 512,
|
119
|
-
"top_p": 0.9,
|
120
|
-
}
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
endpoint =
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
)
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
#
|
196
|
-
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
# raw_response
|
200
|
-
#
|
201
|
-
#
|
202
|
-
#
|
203
|
-
#
|
204
|
-
#
|
205
|
-
#
|
206
|
-
#
|
207
|
-
#
|
208
|
-
#
|
209
|
-
#
|
210
|
-
#
|
211
|
-
#
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
LLM
|
216
|
-
|
217
|
-
return LLM
|
1
|
+
import os
|
2
|
+
from typing import Any, Optional, List
|
3
|
+
import re
|
4
|
+
from openai import AsyncAzureOpenAI
|
5
|
+
from edsl.inference_services.InferenceServiceABC import InferenceServiceABC
|
6
|
+
from edsl.language_models.LanguageModel import LanguageModel
|
7
|
+
|
8
|
+
from azure.ai.inference.aio import ChatCompletionsClient
|
9
|
+
from azure.core.credentials import AzureKeyCredential
|
10
|
+
from azure.ai.inference.models import SystemMessage, UserMessage
|
11
|
+
import asyncio
|
12
|
+
import json
|
13
|
+
from edsl.utilities.utilities import fix_partial_correct_response
|
14
|
+
|
15
|
+
|
16
|
+
def json_handle_none(value: Any) -> Any:
|
17
|
+
"""
|
18
|
+
Handle None values during JSON serialization.
|
19
|
+
- Return "null" if the value is None. Otherwise, don't return anything.
|
20
|
+
"""
|
21
|
+
if value is None:
|
22
|
+
return "null"
|
23
|
+
|
24
|
+
|
25
|
+
class AzureAIService(InferenceServiceABC):
|
26
|
+
"""Azure AI service class."""
|
27
|
+
|
28
|
+
# key_sequence = ["content", 0, "text"] # ["content"][0]["text"]
|
29
|
+
key_sequence = ["choices", 0, "message", "content"]
|
30
|
+
usage_sequence = ["usage"]
|
31
|
+
input_token_name = "prompt_tokens"
|
32
|
+
output_token_name = "completion_tokens"
|
33
|
+
|
34
|
+
_inference_service_ = "azure"
|
35
|
+
_env_key_name_ = (
|
36
|
+
"AZURE_ENDPOINT_URL_AND_KEY" # Environment variable for Azure API key
|
37
|
+
)
|
38
|
+
_model_id_to_endpoint_and_key = {}
|
39
|
+
model_exclude_list = [
|
40
|
+
"Cohere-command-r-plus-xncmg",
|
41
|
+
"Mistral-Nemo-klfsi",
|
42
|
+
"Mistral-large-2407-ojfld",
|
43
|
+
]
|
44
|
+
|
45
|
+
@classmethod
|
46
|
+
def available(cls):
|
47
|
+
out = []
|
48
|
+
azure_endpoints = os.getenv("AZURE_ENDPOINT_URL_AND_KEY", None)
|
49
|
+
if not azure_endpoints:
|
50
|
+
raise EnvironmentError(f"AZURE_ENDPOINT_URL_AND_KEY is not defined")
|
51
|
+
azure_endpoints = azure_endpoints.split(",")
|
52
|
+
for data in azure_endpoints:
|
53
|
+
try:
|
54
|
+
# data has this format for non openai models https://model_id.azure_endpoint:azure_key
|
55
|
+
_, endpoint, azure_endpoint_key = data.split(":")
|
56
|
+
if "openai" not in endpoint:
|
57
|
+
model_id = endpoint.split(".")[0].replace("/", "")
|
58
|
+
out.append(model_id)
|
59
|
+
cls._model_id_to_endpoint_and_key[model_id] = {
|
60
|
+
"endpoint": f"https:{endpoint}",
|
61
|
+
"azure_endpoint_key": azure_endpoint_key,
|
62
|
+
}
|
63
|
+
else:
|
64
|
+
# data has this format for openai models ,https://azure_project_id.openai.azure.com/openai/deployments/gpt-4o-mini/chat/completions?api-version=2023-03-15-preview:azure_key
|
65
|
+
if "/deployments/" in endpoint:
|
66
|
+
start_idx = endpoint.index("/deployments/") + len(
|
67
|
+
"/deployments/"
|
68
|
+
)
|
69
|
+
end_idx = (
|
70
|
+
endpoint.index("/", start_idx)
|
71
|
+
if "/" in endpoint[start_idx:]
|
72
|
+
else len(endpoint)
|
73
|
+
)
|
74
|
+
model_id = endpoint[start_idx:end_idx]
|
75
|
+
api_version_value = None
|
76
|
+
if "api-version=" in endpoint:
|
77
|
+
start_idx = endpoint.index("api-version=") + len(
|
78
|
+
"api-version="
|
79
|
+
)
|
80
|
+
end_idx = (
|
81
|
+
endpoint.index("&", start_idx)
|
82
|
+
if "&" in endpoint[start_idx:]
|
83
|
+
else len(endpoint)
|
84
|
+
)
|
85
|
+
api_version_value = endpoint[start_idx:end_idx]
|
86
|
+
|
87
|
+
cls._model_id_to_endpoint_and_key[f"azure:{model_id}"] = {
|
88
|
+
"endpoint": f"https:{endpoint}",
|
89
|
+
"azure_endpoint_key": azure_endpoint_key,
|
90
|
+
"api_version": api_version_value,
|
91
|
+
}
|
92
|
+
out.append(f"azure:{model_id}")
|
93
|
+
|
94
|
+
except Exception as e:
|
95
|
+
raise e
|
96
|
+
return [m for m in out if m not in cls.model_exclude_list]
|
97
|
+
|
98
|
+
@classmethod
|
99
|
+
def create_model(
|
100
|
+
cls, model_name: str = "azureai", model_class_name=None
|
101
|
+
) -> LanguageModel:
|
102
|
+
if model_class_name is None:
|
103
|
+
model_class_name = cls.to_class_name(model_name)
|
104
|
+
|
105
|
+
class LLM(LanguageModel):
|
106
|
+
"""
|
107
|
+
Child class of LanguageModel for interacting with Azure OpenAI models.
|
108
|
+
"""
|
109
|
+
|
110
|
+
key_sequence = cls.key_sequence
|
111
|
+
usage_sequence = cls.usage_sequence
|
112
|
+
input_token_name = cls.input_token_name
|
113
|
+
output_token_name = cls.output_token_name
|
114
|
+
_inference_service_ = cls._inference_service_
|
115
|
+
_model_ = model_name
|
116
|
+
_parameters_ = {
|
117
|
+
"temperature": 0.5,
|
118
|
+
"max_tokens": 512,
|
119
|
+
"top_p": 0.9,
|
120
|
+
}
|
121
|
+
|
122
|
+
async def async_execute_model_call(
|
123
|
+
self,
|
124
|
+
user_prompt: str,
|
125
|
+
system_prompt: str = "",
|
126
|
+
files_list: Optional[List["FileStore"]] = None,
|
127
|
+
) -> dict[str, Any]:
|
128
|
+
"""Calls the Azure OpenAI API and returns the API response."""
|
129
|
+
|
130
|
+
try:
|
131
|
+
api_key = cls._model_id_to_endpoint_and_key[model_name][
|
132
|
+
"azure_endpoint_key"
|
133
|
+
]
|
134
|
+
except:
|
135
|
+
api_key = None
|
136
|
+
|
137
|
+
if not api_key:
|
138
|
+
raise EnvironmentError(
|
139
|
+
f"AZURE_ENDPOINT_URL_AND_KEY doesn't have the endpoint:key pair for your model: {model_name}"
|
140
|
+
)
|
141
|
+
|
142
|
+
try:
|
143
|
+
endpoint = cls._model_id_to_endpoint_and_key[model_name]["endpoint"]
|
144
|
+
except:
|
145
|
+
endpoint = None
|
146
|
+
|
147
|
+
if not endpoint:
|
148
|
+
raise EnvironmentError(
|
149
|
+
f"AZURE_ENDPOINT_URL_AND_KEY doesn't have the endpoint:key pair for your model: {model_name}"
|
150
|
+
)
|
151
|
+
|
152
|
+
if "openai" not in endpoint:
|
153
|
+
client = ChatCompletionsClient(
|
154
|
+
endpoint=endpoint,
|
155
|
+
credential=AzureKeyCredential(api_key),
|
156
|
+
temperature=self.temperature,
|
157
|
+
top_p=self.top_p,
|
158
|
+
max_tokens=self.max_tokens,
|
159
|
+
)
|
160
|
+
try:
|
161
|
+
response = await client.complete(
|
162
|
+
messages=[
|
163
|
+
SystemMessage(content=system_prompt),
|
164
|
+
UserMessage(content=user_prompt),
|
165
|
+
],
|
166
|
+
# model_extras={"safe_mode": True},
|
167
|
+
)
|
168
|
+
await client.close()
|
169
|
+
return response.as_dict()
|
170
|
+
except Exception as e:
|
171
|
+
await client.close()
|
172
|
+
return {"error": str(e)}
|
173
|
+
else:
|
174
|
+
api_version = cls._model_id_to_endpoint_and_key[model_name][
|
175
|
+
"api_version"
|
176
|
+
]
|
177
|
+
client = AsyncAzureOpenAI(
|
178
|
+
azure_endpoint=endpoint,
|
179
|
+
api_version=api_version,
|
180
|
+
api_key=api_key,
|
181
|
+
)
|
182
|
+
response = await client.chat.completions.create(
|
183
|
+
model=model_name,
|
184
|
+
messages=[
|
185
|
+
{
|
186
|
+
"role": "user",
|
187
|
+
"content": user_prompt, # Your question can go here
|
188
|
+
},
|
189
|
+
],
|
190
|
+
)
|
191
|
+
return response.model_dump()
|
192
|
+
|
193
|
+
# @staticmethod
|
194
|
+
# def parse_response(raw_response: dict[str, Any]) -> str:
|
195
|
+
# """Parses the API response and returns the response text."""
|
196
|
+
# if (
|
197
|
+
# raw_response
|
198
|
+
# and "choices" in raw_response
|
199
|
+
# and raw_response["choices"]
|
200
|
+
# ):
|
201
|
+
# response = raw_response["choices"][0]["message"]["content"]
|
202
|
+
# pattern = r"^```json(?:\\n|\n)(.+?)(?:\\n|\n)```$"
|
203
|
+
# match = re.match(pattern, response, re.DOTALL)
|
204
|
+
# if match:
|
205
|
+
# return match.group(1)
|
206
|
+
# else:
|
207
|
+
# out = fix_partial_correct_response(response)
|
208
|
+
# if "error" not in out:
|
209
|
+
# response = out["extracted_json"]
|
210
|
+
# return response
|
211
|
+
# return "Error parsing response"
|
212
|
+
|
213
|
+
LLM.__name__ = model_class_name
|
214
|
+
|
215
|
+
return LLM
|
@@ -1,18 +1,18 @@
|
|
1
|
-
import aiohttp
|
2
|
-
import json
|
3
|
-
import requests
|
4
|
-
from typing import Any, List
|
5
|
-
|
6
|
-
# from edsl.inference_services.InferenceServiceABC import InferenceServiceABC
|
7
|
-
from edsl.language_models import LanguageModel
|
8
|
-
|
9
|
-
from edsl.inference_services.OpenAIService import OpenAIService
|
10
|
-
|
11
|
-
|
12
|
-
class DeepInfraService(OpenAIService):
|
13
|
-
"""DeepInfra service class."""
|
14
|
-
|
15
|
-
_inference_service_ = "deep_infra"
|
16
|
-
_env_key_name_ = "DEEP_INFRA_API_KEY"
|
17
|
-
_base_url_ = "https://api.deepinfra.com/v1/openai"
|
18
|
-
_models_list_cache: List[str] = []
|
1
|
+
import aiohttp
|
2
|
+
import json
|
3
|
+
import requests
|
4
|
+
from typing import Any, List
|
5
|
+
|
6
|
+
# from edsl.inference_services.InferenceServiceABC import InferenceServiceABC
|
7
|
+
from edsl.language_models import LanguageModel
|
8
|
+
|
9
|
+
from edsl.inference_services.OpenAIService import OpenAIService
|
10
|
+
|
11
|
+
|
12
|
+
class DeepInfraService(OpenAIService):
|
13
|
+
"""DeepInfra service class."""
|
14
|
+
|
15
|
+
_inference_service_ = "deep_infra"
|
16
|
+
_env_key_name_ = "DEEP_INFRA_API_KEY"
|
17
|
+
_base_url_ = "https://api.deepinfra.com/v1/openai"
|
18
|
+
_models_list_cache: List[str] = []
|