edsl 0.1.39__py3-none-any.whl → 0.1.39.dev1__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 +116 -197
- edsl/__init__.py +7 -15
- edsl/__version__.py +1 -1
- edsl/agents/Agent.py +147 -351
- edsl/agents/AgentList.py +73 -211
- edsl/agents/Invigilator.py +50 -101
- edsl/agents/InvigilatorBase.py +70 -62
- edsl/agents/PromptConstructor.py +225 -143
- edsl/agents/__init__.py +1 -0
- edsl/agents/prompt_helpers.py +3 -3
- edsl/auto/AutoStudy.py +5 -18
- edsl/auto/StageBase.py +40 -53
- edsl/auto/StageQuestions.py +1 -2
- edsl/auto/utilities.py +6 -0
- edsl/config.py +2 -22
- edsl/conversation/car_buying.py +1 -2
- edsl/coop/PriceFetcher.py +1 -1
- edsl/coop/coop.py +47 -125
- edsl/coop/utils.py +14 -14
- edsl/data/Cache.py +27 -45
- edsl/data/CacheEntry.py +15 -12
- edsl/data/CacheHandler.py +12 -31
- edsl/data/RemoteCacheSync.py +46 -154
- edsl/data/__init__.py +3 -4
- edsl/data_transfer_models.py +1 -2
- edsl/enums.py +0 -27
- edsl/exceptions/__init__.py +50 -50
- edsl/exceptions/agents.py +0 -12
- edsl/exceptions/questions.py +6 -24
- edsl/exceptions/scenarios.py +0 -7
- edsl/inference_services/AnthropicService.py +19 -38
- edsl/inference_services/AwsBedrock.py +2 -0
- edsl/inference_services/AzureAI.py +2 -0
- edsl/inference_services/GoogleService.py +12 -7
- edsl/inference_services/InferenceServiceABC.py +85 -18
- edsl/inference_services/InferenceServicesCollection.py +79 -120
- edsl/inference_services/MistralAIService.py +3 -0
- edsl/inference_services/OpenAIService.py +35 -47
- edsl/inference_services/PerplexityService.py +3 -0
- edsl/inference_services/TestService.py +10 -11
- edsl/inference_services/TogetherAIService.py +3 -5
- edsl/jobs/Answers.py +14 -1
- edsl/jobs/Jobs.py +431 -356
- edsl/jobs/JobsChecks.py +10 -35
- edsl/jobs/JobsPrompts.py +4 -6
- edsl/jobs/JobsRemoteInferenceHandler.py +133 -205
- edsl/jobs/buckets/BucketCollection.py +3 -44
- edsl/jobs/buckets/TokenBucket.py +21 -53
- edsl/jobs/interviews/Interview.py +408 -143
- edsl/jobs/runners/JobsRunnerAsyncio.py +403 -88
- edsl/jobs/runners/JobsRunnerStatus.py +165 -133
- edsl/jobs/tasks/QuestionTaskCreator.py +19 -21
- edsl/jobs/tasks/TaskHistory.py +18 -38
- edsl/jobs/tasks/task_status_enum.py +2 -0
- edsl/language_models/KeyLookup.py +30 -0
- edsl/language_models/LanguageModel.py +236 -194
- edsl/language_models/ModelList.py +19 -28
- edsl/language_models/__init__.py +2 -1
- edsl/language_models/registry.py +190 -0
- edsl/language_models/repair.py +2 -2
- edsl/language_models/unused/ReplicateBase.py +83 -0
- edsl/language_models/utilities.py +4 -5
- edsl/notebooks/Notebook.py +14 -19
- edsl/prompts/Prompt.py +39 -29
- edsl/questions/{answer_validator_mixin.py → AnswerValidatorMixin.py} +2 -47
- edsl/questions/QuestionBase.py +214 -68
- edsl/questions/{question_base_gen_mixin.py → QuestionBaseGenMixin.py} +50 -57
- edsl/questions/QuestionBasePromptsMixin.py +3 -7
- edsl/questions/QuestionBudget.py +1 -1
- edsl/questions/QuestionCheckBox.py +3 -3
- edsl/questions/QuestionExtract.py +7 -5
- edsl/questions/QuestionFreeText.py +3 -2
- edsl/questions/QuestionList.py +18 -10
- edsl/questions/QuestionMultipleChoice.py +23 -67
- edsl/questions/QuestionNumerical.py +4 -2
- edsl/questions/QuestionRank.py +17 -7
- edsl/questions/{response_validator_abc.py → ResponseValidatorABC.py} +26 -40
- edsl/questions/SimpleAskMixin.py +3 -4
- edsl/questions/__init__.py +1 -2
- edsl/questions/derived/QuestionLinearScale.py +3 -6
- edsl/questions/derived/QuestionTopK.py +1 -1
- edsl/questions/descriptors.py +3 -17
- edsl/questions/question_registry.py +1 -1
- edsl/results/CSSParameterizer.py +1 -1
- edsl/results/Dataset.py +7 -170
- edsl/results/DatasetExportMixin.py +305 -168
- edsl/results/DatasetTree.py +8 -28
- edsl/results/Result.py +206 -298
- edsl/results/Results.py +131 -149
- edsl/results/ResultsDBMixin.py +238 -0
- edsl/results/ResultsExportMixin.py +0 -2
- edsl/results/{results_selector.py → Selector.py} +13 -23
- edsl/results/TableDisplay.py +171 -98
- edsl/results/__init__.py +1 -1
- edsl/scenarios/FileStore.py +239 -150
- edsl/scenarios/Scenario.py +193 -90
- edsl/scenarios/ScenarioHtmlMixin.py +3 -4
- edsl/scenarios/{scenario_join.py → ScenarioJoin.py} +6 -10
- edsl/scenarios/ScenarioList.py +244 -415
- edsl/scenarios/ScenarioListExportMixin.py +7 -0
- edsl/scenarios/ScenarioListPdfMixin.py +37 -15
- edsl/scenarios/__init__.py +2 -1
- edsl/study/ObjectEntry.py +1 -1
- edsl/study/SnapShot.py +1 -1
- edsl/study/Study.py +12 -5
- edsl/surveys/Rule.py +4 -5
- edsl/surveys/RuleCollection.py +27 -25
- edsl/surveys/Survey.py +791 -270
- edsl/surveys/SurveyCSS.py +8 -20
- edsl/surveys/{SurveyFlowVisualization.py → SurveyFlowVisualizationMixin.py} +9 -11
- edsl/surveys/__init__.py +2 -4
- edsl/surveys/descriptors.py +2 -6
- edsl/surveys/instructions/ChangeInstruction.py +2 -1
- edsl/surveys/instructions/Instruction.py +13 -4
- edsl/surveys/instructions/InstructionCollection.py +6 -11
- edsl/templates/error_reporting/interview_details.html +1 -1
- edsl/templates/error_reporting/report.html +1 -1
- edsl/tools/plotting.py +1 -1
- edsl/utilities/utilities.py +23 -35
- {edsl-0.1.39.dist-info → edsl-0.1.39.dev1.dist-info}/METADATA +10 -12
- edsl-0.1.39.dev1.dist-info/RECORD +277 -0
- {edsl-0.1.39.dist-info → edsl-0.1.39.dev1.dist-info}/WHEEL +1 -1
- edsl/agents/QuestionInstructionPromptBuilder.py +0 -128
- edsl/agents/QuestionTemplateReplacementsBuilder.py +0 -137
- edsl/agents/question_option_processor.py +0 -172
- edsl/coop/CoopFunctionsMixin.py +0 -15
- edsl/coop/ExpectedParrotKeyHandler.py +0 -125
- edsl/exceptions/inference_services.py +0 -5
- edsl/inference_services/AvailableModelCacheHandler.py +0 -184
- edsl/inference_services/AvailableModelFetcher.py +0 -215
- edsl/inference_services/ServiceAvailability.py +0 -135
- edsl/inference_services/data_structures.py +0 -134
- edsl/jobs/AnswerQuestionFunctionConstructor.py +0 -223
- edsl/jobs/FetchInvigilator.py +0 -47
- edsl/jobs/InterviewTaskManager.py +0 -98
- edsl/jobs/InterviewsConstructor.py +0 -50
- edsl/jobs/JobsComponentConstructor.py +0 -189
- edsl/jobs/JobsRemoteInferenceLogger.py +0 -239
- edsl/jobs/RequestTokenEstimator.py +0 -30
- edsl/jobs/async_interview_runner.py +0 -138
- edsl/jobs/buckets/TokenBucketAPI.py +0 -211
- edsl/jobs/buckets/TokenBucketClient.py +0 -191
- edsl/jobs/check_survey_scenario_compatibility.py +0 -85
- edsl/jobs/data_structures.py +0 -120
- edsl/jobs/decorators.py +0 -35
- edsl/jobs/jobs_status_enums.py +0 -9
- edsl/jobs/loggers/HTMLTableJobLogger.py +0 -304
- edsl/jobs/results_exceptions_handler.py +0 -98
- edsl/language_models/ComputeCost.py +0 -63
- edsl/language_models/PriceManager.py +0 -127
- edsl/language_models/RawResponseHandler.py +0 -106
- edsl/language_models/ServiceDataSources.py +0 -0
- edsl/language_models/key_management/KeyLookup.py +0 -63
- edsl/language_models/key_management/KeyLookupBuilder.py +0 -273
- edsl/language_models/key_management/KeyLookupCollection.py +0 -38
- edsl/language_models/key_management/__init__.py +0 -0
- edsl/language_models/key_management/models.py +0 -131
- edsl/language_models/model.py +0 -256
- edsl/notebooks/NotebookToLaTeX.py +0 -142
- edsl/questions/ExceptionExplainer.py +0 -77
- edsl/questions/HTMLQuestion.py +0 -103
- edsl/questions/QuestionMatrix.py +0 -265
- edsl/questions/data_structures.py +0 -20
- edsl/questions/loop_processor.py +0 -149
- edsl/questions/response_validator_factory.py +0 -34
- edsl/questions/templates/matrix/__init__.py +0 -1
- edsl/questions/templates/matrix/answering_instructions.jinja +0 -5
- edsl/questions/templates/matrix/question_presentation.jinja +0 -20
- edsl/results/MarkdownToDocx.py +0 -122
- edsl/results/MarkdownToPDF.py +0 -111
- edsl/results/TextEditor.py +0 -50
- edsl/results/file_exports.py +0 -252
- edsl/results/smart_objects.py +0 -96
- edsl/results/table_data_class.py +0 -12
- edsl/results/table_renderers.py +0 -118
- edsl/scenarios/ConstructDownloadLink.py +0 -109
- edsl/scenarios/DocumentChunker.py +0 -102
- edsl/scenarios/DocxScenario.py +0 -16
- edsl/scenarios/PdfExtractor.py +0 -40
- edsl/scenarios/directory_scanner.py +0 -96
- edsl/scenarios/file_methods.py +0 -85
- edsl/scenarios/handlers/__init__.py +0 -13
- edsl/scenarios/handlers/csv.py +0 -49
- edsl/scenarios/handlers/docx.py +0 -76
- edsl/scenarios/handlers/html.py +0 -37
- edsl/scenarios/handlers/json.py +0 -111
- edsl/scenarios/handlers/latex.py +0 -5
- edsl/scenarios/handlers/md.py +0 -51
- edsl/scenarios/handlers/pdf.py +0 -68
- edsl/scenarios/handlers/png.py +0 -39
- edsl/scenarios/handlers/pptx.py +0 -105
- edsl/scenarios/handlers/py.py +0 -294
- edsl/scenarios/handlers/sql.py +0 -313
- edsl/scenarios/handlers/sqlite.py +0 -149
- edsl/scenarios/handlers/txt.py +0 -33
- edsl/scenarios/scenario_selector.py +0 -156
- edsl/surveys/ConstructDAG.py +0 -92
- edsl/surveys/EditSurvey.py +0 -221
- edsl/surveys/InstructionHandler.py +0 -100
- edsl/surveys/MemoryManagement.py +0 -72
- edsl/surveys/RuleManager.py +0 -172
- edsl/surveys/Simulator.py +0 -75
- edsl/surveys/SurveyToApp.py +0 -141
- edsl/utilities/PrettyList.py +0 -56
- edsl/utilities/is_notebook.py +0 -18
- edsl/utilities/is_valid_variable_name.py +0 -11
- edsl/utilities/remove_edsl_version.py +0 -24
- edsl-0.1.39.dist-info/RECORD +0 -358
- /edsl/questions/{register_questions_meta.py → RegisterQuestionsMeta.py} +0 -0
- /edsl/results/{results_fetch_mixin.py → ResultsFetchMixin.py} +0 -0
- /edsl/results/{results_tools_mixin.py → ResultsToolsMixin.py} +0 -0
- {edsl-0.1.39.dist-info → edsl-0.1.39.dev1.dist-info}/LICENSE +0 -0
@@ -1,22 +1,18 @@
|
|
1
|
-
from typing import Optional, List
|
1
|
+
from typing import Optional, List
|
2
2
|
from collections import UserList
|
3
|
+
from edsl import Model
|
3
4
|
|
5
|
+
from edsl.language_models import LanguageModel
|
4
6
|
from edsl.Base import Base
|
5
|
-
from edsl.
|
6
|
-
|
7
|
-
|
8
|
-
from edsl.utilities.remove_edsl_version import remove_edsl_version
|
9
|
-
from edsl.utilities.is_valid_variable_name import is_valid_variable_name
|
10
|
-
|
11
|
-
if TYPE_CHECKING:
|
12
|
-
from edsl.inference_services.data_structures import AvailableModels
|
13
|
-
from edsl.language_models import LanguageModel
|
7
|
+
from edsl.utilities.decorators import add_edsl_version, remove_edsl_version
|
8
|
+
from edsl.utilities.utilities import is_valid_variable_name
|
9
|
+
from edsl.utilities.utilities import dict_hash
|
14
10
|
|
15
11
|
|
16
12
|
class ModelList(Base, UserList):
|
17
13
|
__documentation__ = """https://docs.expectedparrot.com/en/latest/language_models.html#module-edsl.language_models.ModelList"""
|
18
14
|
|
19
|
-
def __init__(self, data: Optional[
|
15
|
+
def __init__(self, data: Optional[list] = None):
|
20
16
|
"""Initialize the ScenarioList class.
|
21
17
|
|
22
18
|
>>> from edsl import Model
|
@@ -37,11 +33,14 @@ class ModelList(Base, UserList):
|
|
37
33
|
"""
|
38
34
|
return set([model.model for model in self])
|
39
35
|
|
36
|
+
def rich_print(self):
|
37
|
+
pass
|
38
|
+
|
40
39
|
def __repr__(self):
|
41
40
|
return f"ModelList({super().__repr__()})"
|
42
41
|
|
43
42
|
def _summary(self):
|
44
|
-
return {"
|
43
|
+
return {"EDSL Class": "ModelList", "Number of Models": len(self)}
|
45
44
|
|
46
45
|
def __hash__(self):
|
47
46
|
"""Return a hash of the ModelList. This is used for comparison of ModelLists.
|
@@ -55,8 +54,7 @@ class ModelList(Base, UserList):
|
|
55
54
|
return dict_hash(self.to_dict(sort=True, add_edsl_version=False))
|
56
55
|
|
57
56
|
def to_scenario_list(self):
|
58
|
-
from edsl
|
59
|
-
from edsl.scenarios.Scenario import Scenario
|
57
|
+
from edsl import ScenarioList, Scenario
|
60
58
|
|
61
59
|
sl = ScenarioList()
|
62
60
|
for model in self:
|
@@ -75,7 +73,7 @@ class ModelList(Base, UserList):
|
|
75
73
|
pretty_labels: Optional[dict] = None,
|
76
74
|
):
|
77
75
|
"""
|
78
|
-
>>> ModelList.example().table(
|
76
|
+
>>> ModelList.example().table("model")
|
79
77
|
model
|
80
78
|
-------
|
81
79
|
gpt-4o
|
@@ -88,7 +86,7 @@ class ModelList(Base, UserList):
|
|
88
86
|
.table(*fields, tablefmt=tablefmt, pretty_labels=pretty_labels)
|
89
87
|
)
|
90
88
|
|
91
|
-
def to_list(self)
|
89
|
+
def to_list(self):
|
92
90
|
return self.to_scenario_list().to_list()
|
93
91
|
|
94
92
|
def to_dict(self, sort=False, add_edsl_version=True):
|
@@ -114,6 +112,11 @@ class ModelList(Base, UserList):
|
|
114
112
|
|
115
113
|
return d
|
116
114
|
|
115
|
+
def _repr_html_(self):
|
116
|
+
"""Return an HTML representation of the ModelList."""
|
117
|
+
footer = f"<a href={self.__documentation__}>(docs)</a>"
|
118
|
+
return str(self.summary(format="html")) + footer
|
119
|
+
|
117
120
|
@classmethod
|
118
121
|
def from_names(self, *args, **kwargs):
|
119
122
|
"""A a model list from a list of names"""
|
@@ -121,16 +124,6 @@ class ModelList(Base, UserList):
|
|
121
124
|
args = args[0]
|
122
125
|
return ModelList([Model(model_name, **kwargs) for model_name in args])
|
123
126
|
|
124
|
-
@classmethod
|
125
|
-
def from_available_models(self, available_models_list: "AvailableModels"):
|
126
|
-
"""Create a ModelList from an AvailableModels object"""
|
127
|
-
return ModelList(
|
128
|
-
[
|
129
|
-
Model(model.model_name, service_name=model.service_name)
|
130
|
-
for model in available_models_list
|
131
|
-
]
|
132
|
-
)
|
133
|
-
|
134
127
|
@classmethod
|
135
128
|
@remove_edsl_version
|
136
129
|
def from_dict(cls, data):
|
@@ -140,8 +133,6 @@ class ModelList(Base, UserList):
|
|
140
133
|
>>> newm = ModelList.from_dict(ModelList.example().to_dict())
|
141
134
|
>>> assert ModelList.example() == newm
|
142
135
|
"""
|
143
|
-
from edsl.language_models.LanguageModel import LanguageModel
|
144
|
-
|
145
136
|
return cls(data=[LanguageModel.from_dict(model) for model in data["models"]])
|
146
137
|
|
147
138
|
def code(self):
|
edsl/language_models/__init__.py
CHANGED
@@ -0,0 +1,190 @@
|
|
1
|
+
import textwrap
|
2
|
+
from random import random
|
3
|
+
from edsl.config import CONFIG
|
4
|
+
|
5
|
+
# if "EDSL_DEFAULT_MODEL" not in CONFIG:
|
6
|
+
# default_model = "test"
|
7
|
+
# else:
|
8
|
+
# default_model = CONFIG.get("EDSL_DEFAULT_MODEL")
|
9
|
+
|
10
|
+
from collections import UserList
|
11
|
+
|
12
|
+
|
13
|
+
class PrettyList(UserList):
|
14
|
+
def __init__(self, data=None, columns=None):
|
15
|
+
super().__init__(data)
|
16
|
+
self.columns = columns
|
17
|
+
|
18
|
+
def _repr_html_(self):
|
19
|
+
if isinstance(self[0], list) or isinstance(self[0], tuple):
|
20
|
+
num_cols = len(self[0])
|
21
|
+
else:
|
22
|
+
num_cols = 1
|
23
|
+
|
24
|
+
if self.columns:
|
25
|
+
columns = self.columns
|
26
|
+
else:
|
27
|
+
columns = list(range(num_cols))
|
28
|
+
|
29
|
+
if num_cols > 1:
|
30
|
+
return (
|
31
|
+
"<pre><table>"
|
32
|
+
+ "".join(["<th>" + str(column) + "</th>" for column in columns])
|
33
|
+
+ "".join(
|
34
|
+
[
|
35
|
+
"<tr>"
|
36
|
+
+ "".join(["<td>" + str(x) + "</td>" for x in row])
|
37
|
+
+ "</tr>"
|
38
|
+
for row in self
|
39
|
+
]
|
40
|
+
)
|
41
|
+
+ "</table></pre>"
|
42
|
+
)
|
43
|
+
else:
|
44
|
+
return (
|
45
|
+
"<pre><table>"
|
46
|
+
+ "".join(["<th>" + str(index) + "</th>" for index in columns])
|
47
|
+
+ "".join(
|
48
|
+
["<tr>" + "<td>" + str(row) + "</td>" + "</tr>" for row in self]
|
49
|
+
)
|
50
|
+
+ "</table></pre>"
|
51
|
+
)
|
52
|
+
|
53
|
+
|
54
|
+
def get_model_class(model_name, registry=None):
|
55
|
+
from edsl.inference_services.registry import default
|
56
|
+
|
57
|
+
registry = registry or default
|
58
|
+
factory = registry.create_model_factory(model_name)
|
59
|
+
return factory
|
60
|
+
|
61
|
+
|
62
|
+
class Meta(type):
|
63
|
+
def __repr__(cls):
|
64
|
+
return textwrap.dedent(
|
65
|
+
f"""\
|
66
|
+
Available models: {cls.available()}
|
67
|
+
|
68
|
+
To create an instance, you can do:
|
69
|
+
>>> m = Model('gpt-4-1106-preview', temperature=0.5, ...)
|
70
|
+
|
71
|
+
To get the default model, you can leave out the model name.
|
72
|
+
To see the available models, you can do:
|
73
|
+
>>> Model.available()
|
74
|
+
"""
|
75
|
+
)
|
76
|
+
|
77
|
+
|
78
|
+
class Model(metaclass=Meta):
|
79
|
+
default_model = CONFIG.get("EDSL_DEFAULT_MODEL")
|
80
|
+
|
81
|
+
def __new__(
|
82
|
+
cls, model_name=None, registry=None, service_name=None, *args, **kwargs
|
83
|
+
):
|
84
|
+
# Map index to the respective subclass
|
85
|
+
if model_name is None:
|
86
|
+
model_name = (
|
87
|
+
cls.default_model
|
88
|
+
) # when model_name is None, use the default model, set in the config file
|
89
|
+
from edsl.inference_services.registry import default
|
90
|
+
|
91
|
+
registry = registry or default
|
92
|
+
|
93
|
+
if isinstance(model_name, int): # can refer to a model by index
|
94
|
+
model_name = cls.available(name_only=True)[model_name]
|
95
|
+
|
96
|
+
factory = registry.create_model_factory(model_name, service_name=service_name)
|
97
|
+
return factory(*args, **kwargs)
|
98
|
+
|
99
|
+
@classmethod
|
100
|
+
def add_model(cls, service_name, model_name):
|
101
|
+
from edsl.inference_services.registry import default
|
102
|
+
|
103
|
+
registry = default
|
104
|
+
registry.add_model(service_name, model_name)
|
105
|
+
|
106
|
+
@classmethod
|
107
|
+
def services(cls, registry=None):
|
108
|
+
from edsl.inference_services.registry import default
|
109
|
+
|
110
|
+
registry = registry or default
|
111
|
+
return [r._inference_service_ for r in registry.services]
|
112
|
+
|
113
|
+
@classmethod
|
114
|
+
def available(cls, search_term=None, name_only=False, registry=None, service=None):
|
115
|
+
from edsl.inference_services.registry import default
|
116
|
+
|
117
|
+
registry = registry or default
|
118
|
+
full_list = registry.available()
|
119
|
+
|
120
|
+
if service is not None:
|
121
|
+
if service not in cls.services(registry=registry):
|
122
|
+
raise ValueError(f"Service {service} not found in available services.")
|
123
|
+
|
124
|
+
full_list = [m for m in full_list if m[1] == service]
|
125
|
+
|
126
|
+
if search_term is None:
|
127
|
+
if name_only:
|
128
|
+
return PrettyList(
|
129
|
+
[m[0] for m in full_list],
|
130
|
+
columns=["Model Name", "Service Name", "Code"],
|
131
|
+
)
|
132
|
+
else:
|
133
|
+
return PrettyList(
|
134
|
+
full_list, columns=["Model Name", "Service Name", "Code"]
|
135
|
+
)
|
136
|
+
else:
|
137
|
+
filtered_results = [
|
138
|
+
m for m in full_list if search_term in m[0] or search_term in m[1]
|
139
|
+
]
|
140
|
+
if name_only:
|
141
|
+
return PrettyList(
|
142
|
+
[m[0] for m in filtered_results],
|
143
|
+
columns=["Model Name", "Service Name", "Code"],
|
144
|
+
)
|
145
|
+
else:
|
146
|
+
return PrettyList(
|
147
|
+
filtered_results, columns=["Model Name", "Service Name", "Code"]
|
148
|
+
)
|
149
|
+
|
150
|
+
@classmethod
|
151
|
+
def check_models(cls, verbose=False):
|
152
|
+
print("Checking all available models...\n")
|
153
|
+
for model in cls.available(name_only=True):
|
154
|
+
print(f"Now checking: {model}")
|
155
|
+
try:
|
156
|
+
m = cls(model)
|
157
|
+
except Exception as e:
|
158
|
+
print(f"Error creating instance of {model}: {e}")
|
159
|
+
continue
|
160
|
+
try:
|
161
|
+
results = m.hello(verbose)
|
162
|
+
if verbose:
|
163
|
+
print(f"Results from model call: {results}")
|
164
|
+
except Exception as e:
|
165
|
+
print(f"Error calling 'hello' on {model}: {e}")
|
166
|
+
continue
|
167
|
+
print("OK!")
|
168
|
+
print("\n")
|
169
|
+
|
170
|
+
@classmethod
|
171
|
+
def example(cls, randomize: bool = False) -> "Model":
|
172
|
+
"""
|
173
|
+
Returns an example Model instance.
|
174
|
+
|
175
|
+
:param randomize: If True, the temperature is set to a random decimal between 0 and 1.
|
176
|
+
"""
|
177
|
+
temperature = 0.5 if not randomize else round(random(), 2)
|
178
|
+
model_name = cls.default_model
|
179
|
+
return cls(model_name, temperature=temperature)
|
180
|
+
|
181
|
+
|
182
|
+
if __name__ == "__main__":
|
183
|
+
import doctest
|
184
|
+
|
185
|
+
doctest.testmod(optionflags=doctest.ELLIPSIS)
|
186
|
+
|
187
|
+
available = Model.available()
|
188
|
+
m = Model("gpt-4-1106-preview")
|
189
|
+
results = m.execute_model_call("Hello world")
|
190
|
+
print(results)
|
edsl/language_models/repair.py
CHANGED
@@ -32,11 +32,11 @@ async def async_repair(
|
|
32
32
|
else:
|
33
33
|
return valid_dict, success
|
34
34
|
|
35
|
-
from edsl
|
35
|
+
from edsl import Model
|
36
36
|
|
37
37
|
m = Model()
|
38
38
|
|
39
|
-
from edsl
|
39
|
+
from edsl import QuestionExtract
|
40
40
|
|
41
41
|
with warnings.catch_warnings():
|
42
42
|
warnings.simplefilter("ignore", UserWarning)
|
@@ -0,0 +1,83 @@
|
|
1
|
+
import asyncio
|
2
|
+
import aiohttp
|
3
|
+
import json
|
4
|
+
from typing import Any
|
5
|
+
|
6
|
+
from edsl import CONFIG
|
7
|
+
|
8
|
+
from edsl.language_models.LanguageModel import LanguageModel
|
9
|
+
|
10
|
+
|
11
|
+
def replicate_model_factory(model_name, base_url, api_token):
|
12
|
+
class ReplicateLanguageModelBase(LanguageModel):
|
13
|
+
_model_ = (
|
14
|
+
model_name # Example model name, replace with actual model name if needed
|
15
|
+
)
|
16
|
+
_parameters_ = {
|
17
|
+
"temperature": 0.1,
|
18
|
+
"topK": 50,
|
19
|
+
"topP": 0.9,
|
20
|
+
"max_new_tokens": 500,
|
21
|
+
"min_new_tokens": -1,
|
22
|
+
"repetition_penalty": 1.15,
|
23
|
+
# "version": "5fe0a3d7ac2852264a25279d1dfb798acbc4d49711d126646594e212cb821749",
|
24
|
+
"use_cache": True,
|
25
|
+
}
|
26
|
+
_api_token = api_token
|
27
|
+
_base_url = base_url
|
28
|
+
|
29
|
+
async def async_execute_model_call(
|
30
|
+
self, user_prompt: str, system_prompt: str = ""
|
31
|
+
) -> dict[str, Any]:
|
32
|
+
self.api_token = self._api_token
|
33
|
+
self.headers = {
|
34
|
+
"Authorization": f"Token {self.api_token}",
|
35
|
+
"Content-Type": "application/json",
|
36
|
+
}
|
37
|
+
# combined_prompt = f"{system_prompt} {user_prompt}".strip()
|
38
|
+
# print(f"Prompt: {combined_prompt}")
|
39
|
+
data = {
|
40
|
+
# "version": self._parameters_["version"],
|
41
|
+
"input": {
|
42
|
+
"debug": False,
|
43
|
+
"top_k": self._parameters_["topK"],
|
44
|
+
"top_p": self._parameters_["topP"],
|
45
|
+
"prompt": user_prompt,
|
46
|
+
"system_prompt": system_prompt,
|
47
|
+
"temperature": self._parameters_["temperature"],
|
48
|
+
"max_new_tokens": self._parameters_["max_new_tokens"],
|
49
|
+
"min_new_tokens": self._parameters_["min_new_tokens"],
|
50
|
+
"prompt_template": "{prompt}",
|
51
|
+
"repetition_penalty": self._parameters_["repetition_penalty"],
|
52
|
+
},
|
53
|
+
}
|
54
|
+
|
55
|
+
async with aiohttp.ClientSession() as session:
|
56
|
+
async with session.post(
|
57
|
+
self._base_url, headers=self.headers, data=json.dumps(data)
|
58
|
+
) as response:
|
59
|
+
raw_response_text = await response.text()
|
60
|
+
data = json.loads(raw_response_text)
|
61
|
+
print(f"This was the data returned by the model:{data}")
|
62
|
+
prediction_url = data["urls"]["get"]
|
63
|
+
|
64
|
+
while True:
|
65
|
+
async with session.get(
|
66
|
+
prediction_url, headers=self.headers
|
67
|
+
) as get_response:
|
68
|
+
if get_response.status != 200:
|
69
|
+
# Handle non-success status codes appropriately
|
70
|
+
return None
|
71
|
+
|
72
|
+
get_data = await get_response.text()
|
73
|
+
get_data = json.loads(get_data)
|
74
|
+
if get_data["status"] == "succeeded":
|
75
|
+
return get_data
|
76
|
+
await asyncio.sleep(1)
|
77
|
+
|
78
|
+
def parse_response(self, raw_response: dict[str, Any]) -> str:
|
79
|
+
data = "".join(raw_response["output"])
|
80
|
+
print(f"This is what the model returned: {data}")
|
81
|
+
return data
|
82
|
+
|
83
|
+
return ReplicateLanguageModelBase
|
@@ -1,12 +1,13 @@
|
|
1
1
|
import asyncio
|
2
2
|
from typing import Any, Optional, List
|
3
|
+
from edsl import Survey
|
4
|
+
from edsl.config import CONFIG
|
3
5
|
from edsl.enums import InferenceServiceType
|
6
|
+
from edsl.language_models.LanguageModel import LanguageModel
|
7
|
+
from edsl.questions import QuestionFreeText
|
4
8
|
|
5
9
|
|
6
10
|
def create_survey(num_questions: int, chained: bool = True, take_scenario=False):
|
7
|
-
from edsl.surveys.Survey import Survey
|
8
|
-
from edsl.questions.QuestionFreeText import QuestionFreeText
|
9
|
-
|
10
11
|
survey = Survey()
|
11
12
|
for i in range(num_questions):
|
12
13
|
if take_scenario:
|
@@ -27,8 +28,6 @@ def create_survey(num_questions: int, chained: bool = True, take_scenario=False)
|
|
27
28
|
def create_language_model(
|
28
29
|
exception: Exception, fail_at_number: int, never_ending=False
|
29
30
|
):
|
30
|
-
from edsl.language_models.LanguageModel import LanguageModel
|
31
|
-
|
32
31
|
class LanguageModelFromUtilities(LanguageModel):
|
33
32
|
_model_ = "test"
|
34
33
|
_parameters_ = {"temperature": 0.5}
|
edsl/notebooks/Notebook.py
CHANGED
@@ -17,8 +17,8 @@ class Notebook(Base):
|
|
17
17
|
|
18
18
|
def __init__(
|
19
19
|
self,
|
20
|
-
path: Optional[str] = None,
|
21
20
|
data: Optional[Dict] = None,
|
21
|
+
path: Optional[str] = None,
|
22
22
|
name: Optional[str] = None,
|
23
23
|
):
|
24
24
|
"""
|
@@ -33,16 +33,12 @@ class Notebook(Base):
|
|
33
33
|
import nbformat
|
34
34
|
|
35
35
|
# Load current notebook path as fallback (VS Code only)
|
36
|
-
|
37
|
-
if
|
38
|
-
with open(path, mode="r", encoding="utf-8") as f:
|
39
|
-
data = nbformat.read(f, as_version=4)
|
40
|
-
self.data = json.loads(json.dumps(data))
|
41
|
-
elif data is not None:
|
36
|
+
path = path or globals().get("__vsc_ipynb_file__")
|
37
|
+
if data is not None:
|
42
38
|
nbformat.validate(data)
|
43
39
|
self.data = data
|
44
|
-
elif
|
45
|
-
with open(
|
40
|
+
elif path is not None:
|
41
|
+
with open(path, mode="r", encoding="utf-8") as f:
|
46
42
|
data = nbformat.read(f, as_version=4)
|
47
43
|
self.data = json.loads(json.dumps(data))
|
48
44
|
else:
|
@@ -134,6 +130,15 @@ class Notebook(Base):
|
|
134
130
|
|
135
131
|
nbformat.write(nbformat.from_dict(self.data), fp=path)
|
136
132
|
|
133
|
+
def print(self):
|
134
|
+
"""
|
135
|
+
Print the notebook.
|
136
|
+
"""
|
137
|
+
from rich import print_json
|
138
|
+
import json
|
139
|
+
|
140
|
+
print_json(json.dumps(self.to_dict()))
|
141
|
+
|
137
142
|
def __repr__(self):
|
138
143
|
"""
|
139
144
|
Return representation of Notebook.
|
@@ -245,16 +250,6 @@ class Notebook(Base):
|
|
245
250
|
lines.append(f'nb = Notebook(data={self.data}, name="""{self.name}""")')
|
246
251
|
return lines
|
247
252
|
|
248
|
-
def to_latex(self, filename: str):
|
249
|
-
"""
|
250
|
-
Convert notebook to LaTeX and create a folder with all necessary components.
|
251
|
-
|
252
|
-
:param filename: Name of the output folder and main tex file (without extension)
|
253
|
-
"""
|
254
|
-
from edsl.notebooks.NotebookToLaTeX import NotebookToLaTeX
|
255
|
-
|
256
|
-
NotebookToLaTeX(self).convert(filename)
|
257
|
-
|
258
253
|
|
259
254
|
if __name__ == "__main__":
|
260
255
|
from edsl import Notebook
|
edsl/prompts/Prompt.py
CHANGED
@@ -1,21 +1,43 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
-
from typing import
|
2
|
+
from typing import Optional
|
3
|
+
from abc import ABC
|
4
|
+
from typing import Any, List
|
5
|
+
|
6
|
+
from jinja2 import Environment, FileSystemLoader
|
7
|
+
from typing import Union, Dict
|
3
8
|
from pathlib import Path
|
4
9
|
|
5
|
-
|
10
|
+
from rich.table import Table
|
11
|
+
from jinja2 import Template, Environment, meta, TemplateSyntaxError, Undefined
|
12
|
+
|
13
|
+
|
14
|
+
class PreserveUndefined(Undefined):
|
15
|
+
def __str__(self):
|
16
|
+
return "{{ " + str(self._undefined_name) + " }}"
|
6
17
|
|
7
18
|
|
8
19
|
from edsl.exceptions.prompts import TemplateRenderError
|
9
|
-
from edsl.Base import PersistenceMixin,
|
20
|
+
from edsl.Base import PersistenceMixin, RichPrintingMixin
|
10
21
|
|
11
22
|
MAX_NESTING = 100
|
12
23
|
|
13
24
|
|
14
|
-
class Prompt(PersistenceMixin,
|
25
|
+
class Prompt(PersistenceMixin, RichPrintingMixin):
|
15
26
|
"""Class for creating a prompt to be used in a survey."""
|
16
27
|
|
17
28
|
default_instructions: Optional[str] = "Do good things, friendly LLM!"
|
18
29
|
|
30
|
+
def _repr_html_(self):
|
31
|
+
"""Return an HTML representation of the Prompt."""
|
32
|
+
# from edsl.utilities.utilities import data_to_html
|
33
|
+
# return data_to_html(self.to_dict())
|
34
|
+
d = self.to_dict()
|
35
|
+
data = [[k, v] for k, v in d.items()]
|
36
|
+
from tabulate import tabulate
|
37
|
+
|
38
|
+
table = str(tabulate(data, headers=["keys", "values"], tablefmt="html"))
|
39
|
+
return f"<pre>{table}</pre>"
|
40
|
+
|
19
41
|
def __len__(self):
|
20
42
|
"""Return the length of the prompt text."""
|
21
43
|
return len(self.text)
|
@@ -163,12 +185,6 @@ class Prompt(PersistenceMixin, RepresentationMixin):
|
|
163
185
|
:param template: The template to find the variables in.
|
164
186
|
|
165
187
|
"""
|
166
|
-
from jinja2 import Environment, meta, Undefined
|
167
|
-
|
168
|
-
class PreserveUndefined(Undefined):
|
169
|
-
def __str__(self):
|
170
|
-
return "{{ " + str(self._undefined_name) + " }}"
|
171
|
-
|
172
188
|
env = Environment(undefined=PreserveUndefined)
|
173
189
|
ast = env.parse(template)
|
174
190
|
return list(meta.find_undeclared_variables(ast))
|
@@ -257,12 +273,6 @@ class Prompt(PersistenceMixin, RepresentationMixin):
|
|
257
273
|
>>> p.render({"name": "John", "age": 44}, codebook=codebook)
|
258
274
|
Prompt(text=\"""You are an agent named John. Age: 44\""")
|
259
275
|
"""
|
260
|
-
from jinja2 import Environment, meta, TemplateSyntaxError, Undefined
|
261
|
-
|
262
|
-
class PreserveUndefined(Undefined):
|
263
|
-
def __str__(self):
|
264
|
-
return "{{ " + str(self._undefined_name) + " }}"
|
265
|
-
|
266
276
|
env = Environment(undefined=PreserveUndefined)
|
267
277
|
try:
|
268
278
|
previous_text = None
|
@@ -286,7 +296,7 @@ class Prompt(PersistenceMixin, RepresentationMixin):
|
|
286
296
|
f"Template syntax error: {e}. Bad template: {text}"
|
287
297
|
)
|
288
298
|
|
289
|
-
def to_dict(self
|
299
|
+
def to_dict(self) -> dict[str, Any]:
|
290
300
|
"""Return the `Prompt` as a dictionary.
|
291
301
|
|
292
302
|
Example:
|
@@ -313,18 +323,18 @@ class Prompt(PersistenceMixin, RepresentationMixin):
|
|
313
323
|
# class_name = data["class_name"]
|
314
324
|
return Prompt(text=data["text"])
|
315
325
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
326
|
+
def rich_print(self):
|
327
|
+
"""Display an object as a table."""
|
328
|
+
table = Table(title="Prompt")
|
329
|
+
table.add_column("Attribute", style="bold")
|
330
|
+
table.add_column("Value")
|
331
|
+
|
332
|
+
to_display = self.__dict__.copy()
|
333
|
+
for attr_name, attr_value in to_display.items():
|
334
|
+
table.add_row(attr_name, repr(attr_value))
|
335
|
+
table.add_row("Component type", str(self.component_type))
|
336
|
+
table.add_row("Model", str(getattr(self, "model", "Not specified")))
|
337
|
+
return table
|
328
338
|
|
329
339
|
@classmethod
|
330
340
|
def example(cls):
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
import re
|
4
4
|
from typing import Any, Type, Union
|
5
|
-
from edsl.exceptions
|
5
|
+
from edsl.exceptions import (
|
6
6
|
QuestionAnswerValidationError,
|
7
7
|
)
|
8
8
|
|
@@ -213,12 +213,7 @@ class AnswerValidatorMixin:
|
|
213
213
|
- is not less than `min_value`
|
214
214
|
- is not greater than `max_value`
|
215
215
|
"""
|
216
|
-
|
217
|
-
value = float(answer.get("answer"))
|
218
|
-
except ValueError:
|
219
|
-
raise QuestionAnswerValidationError(
|
220
|
-
f"Answer must real number or convertible to a real number (got {answer.get('answer')})."
|
221
|
-
)
|
216
|
+
value = float(answer.get("answer"))
|
222
217
|
if self.min_value is not None and value < self.min_value:
|
223
218
|
raise QuestionAnswerValidationError(
|
224
219
|
f"Value {value} is less than {self.min_value}"
|
@@ -284,46 +279,6 @@ class AnswerValidatorMixin:
|
|
284
279
|
f"Rank answer {value}, but exactly {self.num_selections} selections required."
|
285
280
|
)
|
286
281
|
|
287
|
-
def _validate_answer_matrix(self, answer: dict[str, Any]) -> None:
|
288
|
-
"""Validate QuestionMatrix-specific answer.
|
289
|
-
|
290
|
-
Check that answer["answer"]:
|
291
|
-
- is a dictionary
|
292
|
-
- has all required question_items as keys
|
293
|
-
- has values that are valid options from question_options
|
294
|
-
- has the correct number of responses (one per item)
|
295
|
-
"""
|
296
|
-
value = answer.get("answer")
|
297
|
-
|
298
|
-
# Check that answer is a dictionary
|
299
|
-
if not isinstance(value, dict):
|
300
|
-
raise QuestionAnswerValidationError(
|
301
|
-
f"Matrix answer must be a dictionary mapping items to responses (got {value})"
|
302
|
-
)
|
303
|
-
|
304
|
-
# Check that all required items are present
|
305
|
-
required_items = set(self.question_items)
|
306
|
-
provided_items = set(value.keys())
|
307
|
-
|
308
|
-
if missing_items := (required_items - provided_items):
|
309
|
-
raise QuestionAnswerValidationError(
|
310
|
-
f"Missing responses for items: {missing_items}"
|
311
|
-
)
|
312
|
-
|
313
|
-
if extra_items := (provided_items - required_items):
|
314
|
-
raise QuestionAnswerValidationError(
|
315
|
-
f"Unexpected responses for items: {extra_items}"
|
316
|
-
)
|
317
|
-
|
318
|
-
# Check that all responses are valid options
|
319
|
-
valid_options = set(self.question_options)
|
320
|
-
for item, response in value.items():
|
321
|
-
if response not in valid_options:
|
322
|
-
raise QuestionAnswerValidationError(
|
323
|
-
f"Invalid response '{response}' for item '{item}'. "
|
324
|
-
f"Must be one of: {valid_options}"
|
325
|
-
)
|
326
|
-
|
327
282
|
|
328
283
|
if __name__ == "__main__":
|
329
284
|
pass
|