freeplay 0.2.30__py3-none-any.whl → 0.2.32__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.
- freeplay/api_support.py +6 -4
- freeplay/completions.py +6 -2
- freeplay/flavors.py +63 -89
- freeplay/freeplay.py +74 -362
- freeplay/freeplay_thin.py +4 -3
- freeplay/model.py +20 -0
- freeplay/py.typed +0 -0
- freeplay/record.py +20 -7
- freeplay/support.py +316 -0
- freeplay/utils.py +39 -9
- {freeplay-0.2.30.dist-info → freeplay-0.2.32.dist-info}/METADATA +1 -1
- freeplay-0.2.32.dist-info/RECORD +20 -0
- {freeplay-0.2.30.dist-info → freeplay-0.2.32.dist-info}/WHEEL +1 -1
- freeplay-0.2.30.dist-info/RECORD +0 -17
- {freeplay-0.2.30.dist-info → freeplay-0.2.32.dist-info}/LICENSE +0 -0
- {freeplay-0.2.30.dist-info → freeplay-0.2.32.dist-info}/entry_points.txt +0 -0
freeplay/record.py
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
import logging
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
3
|
+
from typing import Dict, Optional, Union
|
4
4
|
from abc import abstractmethod, ABC
|
5
|
+
from dataclasses import dataclass
|
6
|
+
from typing import Optional
|
5
7
|
|
6
|
-
from .llm_parameters import LLMParameters
|
7
|
-
from .completions import PromptTemplateWithMetadata
|
8
8
|
from . import api_support
|
9
|
+
from .completions import PromptTemplateWithMetadata
|
10
|
+
from .llm_parameters import LLMParameters
|
11
|
+
from .model import InputVariables
|
9
12
|
|
10
13
|
logger = logging.getLogger(__name__)
|
11
14
|
|
15
|
+
|
12
16
|
@dataclass
|
13
17
|
class RecordCallFields:
|
14
18
|
completion_content: str
|
@@ -18,13 +22,15 @@ class RecordCallFields:
|
|
18
22
|
session_id: str
|
19
23
|
start: float
|
20
24
|
target_template: PromptTemplateWithMetadata
|
21
|
-
variables:
|
25
|
+
variables: InputVariables
|
22
26
|
tag: str
|
23
27
|
test_run_id: Optional[str]
|
28
|
+
test_case_id: Optional[str]
|
24
29
|
record_format_type: Optional[str]
|
25
30
|
model: Optional[str]
|
26
31
|
provider: Optional[str]
|
27
32
|
llm_parameters: Optional[LLMParameters]
|
33
|
+
custom_metadata: Optional[Dict[str, Union[str,int,float]]] = None
|
28
34
|
|
29
35
|
|
30
36
|
class RecordProcessor(ABC):
|
@@ -35,6 +41,7 @@ class RecordProcessor(ABC):
|
|
35
41
|
) -> None:
|
36
42
|
pass
|
37
43
|
|
44
|
+
|
38
45
|
class NoOpRecorder(RecordProcessor):
|
39
46
|
def record_call(
|
40
47
|
self,
|
@@ -42,8 +49,10 @@ class NoOpRecorder(RecordProcessor):
|
|
42
49
|
) -> None:
|
43
50
|
pass
|
44
51
|
|
52
|
+
|
45
53
|
no_op_recorder = NoOpRecorder()
|
46
54
|
|
55
|
+
|
47
56
|
class DefaultRecordProcessor(RecordProcessor):
|
48
57
|
|
49
58
|
def __init__(
|
@@ -55,8 +64,8 @@ class DefaultRecordProcessor(RecordProcessor):
|
|
55
64
|
self.freeplay_api_key = freeplay_api_key
|
56
65
|
|
57
66
|
def record_call(
|
58
|
-
|
59
|
-
|
67
|
+
self,
|
68
|
+
record_call: RecordCallFields
|
60
69
|
) -> None:
|
61
70
|
record_payload = {
|
62
71
|
"session_id": record_call.session_id,
|
@@ -72,12 +81,16 @@ class DefaultRecordProcessor(RecordProcessor):
|
|
72
81
|
"is_complete": record_call.completion_is_complete,
|
73
82
|
"model": record_call.model,
|
74
83
|
"provider": record_call.provider,
|
75
|
-
"llm_parameters": record_call.llm_parameters
|
84
|
+
"llm_parameters": record_call.llm_parameters,
|
85
|
+
"custom_metadata": record_call.custom_metadata,
|
76
86
|
}
|
77
87
|
|
78
88
|
if record_call.test_run_id is not None:
|
79
89
|
record_payload['test_run_id'] = record_call.test_run_id
|
80
90
|
|
91
|
+
if record_call.test_case_id is not None:
|
92
|
+
record_payload['test_case_id'] = record_call.test_case_id
|
93
|
+
|
81
94
|
try:
|
82
95
|
recorded_response = api_support.post_raw(
|
83
96
|
api_key=self.freeplay_api_key,
|
freeplay/support.py
ADDED
@@ -0,0 +1,316 @@
|
|
1
|
+
import json
|
2
|
+
import time
|
3
|
+
from copy import copy
|
4
|
+
from typing import Dict, Any, Optional, Union, List, Generator
|
5
|
+
from uuid import uuid4
|
6
|
+
|
7
|
+
from freeplay import api_support
|
8
|
+
from freeplay.api_support import try_decode
|
9
|
+
from freeplay.completions import PromptTemplates, PromptTemplateWithMetadata, ChatMessage, ChatCompletionResponse, \
|
10
|
+
CompletionChunk, CompletionResponse
|
11
|
+
from freeplay.errors import FreeplayConfigurationError, freeplay_response_error, FreeplayServerError
|
12
|
+
from freeplay.flavors import ChatFlavor, Flavor, pick_flavor_from_config
|
13
|
+
from freeplay.llm_parameters import LLMParameters
|
14
|
+
from freeplay.model import InputVariables
|
15
|
+
from freeplay.provider_config import ProviderConfig
|
16
|
+
from freeplay.record import RecordProcessor, RecordCallFields
|
17
|
+
|
18
|
+
JsonDom = Dict[str, Any]
|
19
|
+
|
20
|
+
|
21
|
+
class TestCaseTestRunResponse:
|
22
|
+
def __init__(self, test_case: JsonDom):
|
23
|
+
self.variables: InputVariables = test_case['variables']
|
24
|
+
self.id: str = test_case['id']
|
25
|
+
|
26
|
+
|
27
|
+
class TestRunResponse:
|
28
|
+
def __init__(
|
29
|
+
self,
|
30
|
+
test_run_id: str,
|
31
|
+
test_cases: list[JsonDom]
|
32
|
+
):
|
33
|
+
self.test_cases = [
|
34
|
+
TestCaseTestRunResponse(test_case)
|
35
|
+
for test_case in test_cases
|
36
|
+
]
|
37
|
+
self.test_run_id = test_run_id
|
38
|
+
|
39
|
+
|
40
|
+
class CallSupport:
|
41
|
+
def __init__(
|
42
|
+
self,
|
43
|
+
freeplay_api_key: str,
|
44
|
+
api_base: str,
|
45
|
+
record_processor: RecordProcessor,
|
46
|
+
**kwargs: Any
|
47
|
+
) -> None:
|
48
|
+
self.api_base = api_base
|
49
|
+
self.freeplay_api_key = freeplay_api_key
|
50
|
+
self.client_params = LLMParameters(kwargs)
|
51
|
+
self.record_processor = record_processor
|
52
|
+
|
53
|
+
@staticmethod
|
54
|
+
def find_template_by_name(prompts: PromptTemplates, template_name: str) -> PromptTemplateWithMetadata:
|
55
|
+
templates = [t for t in prompts.templates if t.name == template_name]
|
56
|
+
if len(templates) == 0:
|
57
|
+
raise FreeplayConfigurationError(f'Could not find template with name "{template_name}"')
|
58
|
+
return templates[0]
|
59
|
+
|
60
|
+
def create_session_id(self) -> str:
|
61
|
+
return str(uuid4())
|
62
|
+
|
63
|
+
def check_all_values_string_or_number(self, metadata: Optional[Dict[str, Union[str, int, float]]]) -> None:
|
64
|
+
if metadata:
|
65
|
+
for key, value in metadata.items():
|
66
|
+
if not isinstance(value, (str, int, float)):
|
67
|
+
raise FreeplayConfigurationError(f"Invalid value for key {key}: Value must be a string or number.")
|
68
|
+
|
69
|
+
def get_prompt(self, project_id: str, template_name: str, environment: str) -> PromptTemplateWithMetadata:
|
70
|
+
prompt_templates = self.get_prompts(project_id, environment)
|
71
|
+
return self.find_template_by_name(prompt_templates, template_name)
|
72
|
+
|
73
|
+
def get_prompts(self, project_id: str, tag: str) -> PromptTemplates:
|
74
|
+
response = api_support.get_raw(
|
75
|
+
api_key=self.freeplay_api_key,
|
76
|
+
url=f'{self.api_base}/projects/{project_id}/templates/all/{tag}'
|
77
|
+
)
|
78
|
+
|
79
|
+
if response.status_code != 200:
|
80
|
+
raise freeplay_response_error("Error getting prompt templates", response)
|
81
|
+
|
82
|
+
maybe_prompts = try_decode(PromptTemplates, response.content)
|
83
|
+
if maybe_prompts is None:
|
84
|
+
raise FreeplayServerError(f'Failed to parse prompt templates from server')
|
85
|
+
|
86
|
+
return maybe_prompts
|
87
|
+
|
88
|
+
def create_test_run(self, project_id: str, testlist: str) -> TestRunResponse:
|
89
|
+
response = api_support.post_raw(
|
90
|
+
api_key=self.freeplay_api_key,
|
91
|
+
url=f'{self.api_base}/projects/{project_id}/test-runs-cases',
|
92
|
+
payload={'testlist_name': testlist},
|
93
|
+
)
|
94
|
+
|
95
|
+
if response.status_code != 201:
|
96
|
+
raise freeplay_response_error('Error while creating a test run.', response)
|
97
|
+
|
98
|
+
json_dom = response.json()
|
99
|
+
|
100
|
+
return TestRunResponse(json_dom['test_run_id'], json_dom['test_cases'])
|
101
|
+
|
102
|
+
# noinspection PyUnboundLocalVariable
|
103
|
+
def prepare_and_make_chat_call(
|
104
|
+
self,
|
105
|
+
session_id: str,
|
106
|
+
flavor: ChatFlavor,
|
107
|
+
provider_config: ProviderConfig,
|
108
|
+
tag: str,
|
109
|
+
target_template: PromptTemplateWithMetadata,
|
110
|
+
variables: InputVariables,
|
111
|
+
message_history: List[ChatMessage],
|
112
|
+
new_messages: Optional[List[ChatMessage]],
|
113
|
+
test_run_id: Optional[str] = None,
|
114
|
+
completion_parameters: Optional[LLMParameters] = None,
|
115
|
+
metadata: Optional[Dict[str, Union[str, int, float]]] = None
|
116
|
+
) -> ChatCompletionResponse:
|
117
|
+
# make call
|
118
|
+
start = time.time()
|
119
|
+
params = target_template.get_params() \
|
120
|
+
.merge_and_override(self.client_params) \
|
121
|
+
.merge_and_override(completion_parameters)
|
122
|
+
prompt_messages = copy(message_history)
|
123
|
+
if new_messages is not None:
|
124
|
+
prompt_messages.extend(new_messages)
|
125
|
+
completion_response = flavor.continue_chat(messages=prompt_messages,
|
126
|
+
provider_config=provider_config,
|
127
|
+
llm_parameters=params)
|
128
|
+
end = time.time()
|
129
|
+
|
130
|
+
model = flavor.get_model_params(params).get('model')
|
131
|
+
formatted_prompt = json.dumps(prompt_messages)
|
132
|
+
# record data
|
133
|
+
record_call_fields = RecordCallFields(
|
134
|
+
completion_content=completion_response.content,
|
135
|
+
completion_is_complete=completion_response.is_complete,
|
136
|
+
end=end,
|
137
|
+
formatted_prompt=formatted_prompt,
|
138
|
+
session_id=session_id,
|
139
|
+
start=start,
|
140
|
+
target_template=target_template,
|
141
|
+
variables=variables,
|
142
|
+
record_format_type=flavor.record_format_type,
|
143
|
+
tag=tag,
|
144
|
+
test_run_id=test_run_id,
|
145
|
+
test_case_id=None,
|
146
|
+
model=model,
|
147
|
+
provider=flavor.provider,
|
148
|
+
llm_parameters=params,
|
149
|
+
custom_metadata=metadata,
|
150
|
+
)
|
151
|
+
self.record_processor.record_call(record_call_fields)
|
152
|
+
|
153
|
+
return completion_response
|
154
|
+
|
155
|
+
# noinspection PyUnboundLocalVariable
|
156
|
+
def prepare_and_make_chat_call_stream(
|
157
|
+
self,
|
158
|
+
session_id: str,
|
159
|
+
flavor: ChatFlavor,
|
160
|
+
provider_config: ProviderConfig,
|
161
|
+
tag: str,
|
162
|
+
target_template: PromptTemplateWithMetadata,
|
163
|
+
variables: InputVariables,
|
164
|
+
message_history: List[ChatMessage],
|
165
|
+
test_run_id: Optional[str] = None,
|
166
|
+
completion_parameters: Optional[LLMParameters] = None,
|
167
|
+
metadata: Optional[Dict[str, Union[str, int, float]]] = None
|
168
|
+
) -> Generator[CompletionChunk, None, None]:
|
169
|
+
# make call
|
170
|
+
start = time.time()
|
171
|
+
prompt_messages = copy(message_history)
|
172
|
+
params = target_template.get_params() \
|
173
|
+
.merge_and_override(self.client_params) \
|
174
|
+
.merge_and_override(completion_parameters)
|
175
|
+
completion_response = flavor.continue_chat_stream(prompt_messages, provider_config, llm_parameters=params)
|
176
|
+
|
177
|
+
str_content = ''
|
178
|
+
last_is_complete = False
|
179
|
+
for chunk in completion_response:
|
180
|
+
str_content += chunk.text or ''
|
181
|
+
last_is_complete = chunk.is_complete
|
182
|
+
yield chunk
|
183
|
+
# End time must be logged /after/ streaming the response above, or else OpenAI latency will not be captured.
|
184
|
+
end = time.time()
|
185
|
+
|
186
|
+
model = flavor.get_model_params(params).get('model')
|
187
|
+
formatted_prompt = json.dumps(prompt_messages)
|
188
|
+
record_call_fields = RecordCallFields(
|
189
|
+
completion_content=str_content,
|
190
|
+
completion_is_complete=last_is_complete,
|
191
|
+
end=end,
|
192
|
+
formatted_prompt=formatted_prompt,
|
193
|
+
session_id=session_id,
|
194
|
+
start=start,
|
195
|
+
target_template=target_template,
|
196
|
+
variables=variables,
|
197
|
+
record_format_type=flavor.record_format_type,
|
198
|
+
tag=tag,
|
199
|
+
test_run_id=test_run_id,
|
200
|
+
test_case_id=None,
|
201
|
+
model=model,
|
202
|
+
provider=flavor.provider,
|
203
|
+
llm_parameters=params,
|
204
|
+
custom_metadata=metadata,
|
205
|
+
)
|
206
|
+
self.record_processor.record_call(record_call_fields)
|
207
|
+
|
208
|
+
# noinspection PyUnboundLocalVariable
|
209
|
+
def prepare_and_make_call(
|
210
|
+
self,
|
211
|
+
session_id: str,
|
212
|
+
prompts: PromptTemplates,
|
213
|
+
template_name: str,
|
214
|
+
variables: InputVariables,
|
215
|
+
flavor: Optional[Flavor],
|
216
|
+
provider_config: ProviderConfig,
|
217
|
+
tag: str,
|
218
|
+
test_run_id: Optional[str] = None,
|
219
|
+
completion_parameters: Optional[LLMParameters] = None,
|
220
|
+
metadata: Optional[Dict[str, Union[str, int, float]]] = None
|
221
|
+
) -> CompletionResponse:
|
222
|
+
target_template = self.find_template_by_name(prompts, template_name)
|
223
|
+
params = target_template.get_params() \
|
224
|
+
.merge_and_override(self.client_params) \
|
225
|
+
.merge_and_override(completion_parameters)
|
226
|
+
|
227
|
+
final_flavor = pick_flavor_from_config(flavor, target_template.flavor_name)
|
228
|
+
formatted_prompt = final_flavor.format(target_template, variables)
|
229
|
+
|
230
|
+
# make call
|
231
|
+
start = time.time()
|
232
|
+
completion_response = final_flavor.call_service(formatted_prompt=formatted_prompt,
|
233
|
+
provider_config=provider_config,
|
234
|
+
llm_parameters=params)
|
235
|
+
end = time.time()
|
236
|
+
|
237
|
+
model = final_flavor.get_model_params(params).get('model')
|
238
|
+
|
239
|
+
# record data
|
240
|
+
record_call_fields = RecordCallFields(
|
241
|
+
completion_content=completion_response.content,
|
242
|
+
completion_is_complete=completion_response.is_complete,
|
243
|
+
end=end,
|
244
|
+
formatted_prompt=formatted_prompt,
|
245
|
+
session_id=session_id,
|
246
|
+
start=start,
|
247
|
+
target_template=target_template,
|
248
|
+
variables=variables,
|
249
|
+
record_format_type=final_flavor.record_format_type,
|
250
|
+
tag=tag,
|
251
|
+
test_run_id=test_run_id,
|
252
|
+
test_case_id=None,
|
253
|
+
model=model,
|
254
|
+
provider=final_flavor.provider,
|
255
|
+
llm_parameters=params,
|
256
|
+
custom_metadata=metadata,
|
257
|
+
)
|
258
|
+
self.record_processor.record_call(record_call_fields)
|
259
|
+
|
260
|
+
return completion_response
|
261
|
+
|
262
|
+
def prepare_and_make_call_stream(
|
263
|
+
self,
|
264
|
+
session_id: str,
|
265
|
+
prompts: PromptTemplates,
|
266
|
+
template_name: str,
|
267
|
+
variables: InputVariables,
|
268
|
+
flavor: Optional[Flavor],
|
269
|
+
provider_config: ProviderConfig,
|
270
|
+
tag: str,
|
271
|
+
test_run_id: Optional[str] = None,
|
272
|
+
completion_parameters: Optional[LLMParameters] = None,
|
273
|
+
metadata: Optional[Dict[str, Union[str, int, float]]] = None
|
274
|
+
) -> Generator[CompletionChunk, None, None]:
|
275
|
+
target_template = self.find_template_by_name(prompts, template_name)
|
276
|
+
params = target_template.get_params() \
|
277
|
+
.merge_and_override(self.client_params) \
|
278
|
+
.merge_and_override(completion_parameters)
|
279
|
+
|
280
|
+
final_flavor = pick_flavor_from_config(flavor, target_template.flavor_name)
|
281
|
+
formatted_prompt = final_flavor.format(target_template, variables)
|
282
|
+
|
283
|
+
# make call
|
284
|
+
start = int(time.time())
|
285
|
+
completion_response = final_flavor.call_service_stream(
|
286
|
+
formatted_prompt=formatted_prompt, provider_config=provider_config, llm_parameters=params)
|
287
|
+
text_chunks = []
|
288
|
+
last_is_complete = False
|
289
|
+
for chunk in completion_response:
|
290
|
+
text_chunks.append(chunk.text)
|
291
|
+
last_is_complete = chunk.is_complete
|
292
|
+
yield chunk
|
293
|
+
# End time must be logged /after/ streaming the response above, or else OpenAI latency will not be captured.
|
294
|
+
end = int(time.time())
|
295
|
+
|
296
|
+
model = final_flavor.get_model_params(params).get('model')
|
297
|
+
|
298
|
+
record_call_fields = RecordCallFields(
|
299
|
+
completion_content=''.join(text_chunks),
|
300
|
+
completion_is_complete=last_is_complete,
|
301
|
+
end=end,
|
302
|
+
formatted_prompt=formatted_prompt,
|
303
|
+
session_id=session_id,
|
304
|
+
start=start,
|
305
|
+
target_template=target_template,
|
306
|
+
variables=variables,
|
307
|
+
record_format_type=final_flavor.record_format_type,
|
308
|
+
tag=tag,
|
309
|
+
test_run_id=test_run_id,
|
310
|
+
test_case_id=None,
|
311
|
+
model=model,
|
312
|
+
provider=final_flavor.provider,
|
313
|
+
llm_parameters=params,
|
314
|
+
custom_metadata=metadata,
|
315
|
+
)
|
316
|
+
self.record_processor.record_call(record_call_fields)
|
freeplay/utils.py
CHANGED
@@ -1,21 +1,51 @@
|
|
1
|
+
from typing import Dict, Union, Optional
|
2
|
+
import importlib.metadata
|
3
|
+
import platform
|
4
|
+
|
1
5
|
import pystache # type: ignore
|
2
|
-
from pydantic import
|
3
|
-
from typing import Any, Dict, List, Union
|
6
|
+
from pydantic import ValidationError
|
4
7
|
|
5
|
-
from .errors import FreeplayError
|
8
|
+
from .errors import FreeplayError, FreeplayConfigurationError
|
9
|
+
from .model import PydanticInputVariables, InputVariables
|
6
10
|
|
7
|
-
InputVariable = RootModel[Union[Dict[str, "InputVariable"], List["InputVariable"], str, int, bool, float]]
|
8
|
-
InputVariable.model_rebuild()
|
9
|
-
InputVariables = Dict[str, Union[str, int, bool, Dict[str, Any], List[Any]]]
|
10
|
-
PydanticInputVariables = RootModel[Dict[str, InputVariable]]
|
11
11
|
|
12
|
-
def
|
12
|
+
def bind_template_variables(template: str, variables: InputVariables) -> str:
|
13
13
|
# Validate that the variables are of the correct type, and do not include functions or None values.
|
14
14
|
try:
|
15
15
|
PydanticInputVariables.model_validate(variables)
|
16
16
|
except ValidationError as err:
|
17
|
-
raise FreeplayError(
|
17
|
+
raise FreeplayError(
|
18
|
+
'Variables must be a string, number, bool, or a possibly nested'
|
19
|
+
' list or dict of strings, numbers and booleans.'
|
20
|
+
)
|
18
21
|
|
19
22
|
# When rendering mustache, do not escape HTML special characters.
|
20
23
|
rendered: str = pystache.Renderer(escape=lambda s: s).render(template, variables)
|
21
24
|
return rendered
|
25
|
+
|
26
|
+
|
27
|
+
def check_all_values_string_or_number(metadata: Optional[Dict[str, Union[str, int, float]]]) -> None:
|
28
|
+
if metadata:
|
29
|
+
for key, value in metadata.items():
|
30
|
+
if not isinstance(value, (str, int, float)):
|
31
|
+
raise FreeplayConfigurationError(f"Invalid value for key {key}: Value must be a string or number.")
|
32
|
+
|
33
|
+
|
34
|
+
def build_request_header(api_key: str) -> Dict[str, str]:
|
35
|
+
return {
|
36
|
+
'Authorization': f'Bearer {api_key}',
|
37
|
+
'User-Agent': get_user_agent()
|
38
|
+
}
|
39
|
+
|
40
|
+
|
41
|
+
def get_user_agent() -> str:
|
42
|
+
sdk_name = 'Freeplay'
|
43
|
+
sdk_version = importlib.metadata.version('Freeplay')
|
44
|
+
language = 'Python'
|
45
|
+
language_version = platform.python_version()
|
46
|
+
os_name = platform.system()
|
47
|
+
os_version = platform.release()
|
48
|
+
|
49
|
+
# Output format
|
50
|
+
# Freeplay/0.2.30 (Python/3.11.4; Darwin/23.2.0)
|
51
|
+
return f"{sdk_name}/{sdk_version} ({language}/{language_version}; {os_name}/{os_version})"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
freeplay/__init__.py,sha256=74A9S9hmLq9BNHsdx0-37yDxlSukudNl9bJ0TE60Z30,61
|
2
|
+
freeplay/api_support.py,sha256=E4Mxa3Lx31TEw_X6o4s9eAR1TSxs0PhFYYaWax6dH2I,2027
|
3
|
+
freeplay/completions.py,sha256=F1rMBtQaCtn0rBQqvCurkV25g8gLtwnEod5rRvf-txY,1176
|
4
|
+
freeplay/errors.py,sha256=bPqsw32YX-xSr7O-G49M0sSFF7mq-YF1WGq928UV47s,631
|
5
|
+
freeplay/flavors.py,sha256=XroBKT8Nf92VTsuC261Nceo9f9stkkpC5CXbi8y4NEs,17236
|
6
|
+
freeplay/freeplay.py,sha256=BLlr4YXh3a624xcM93KvZGsiIGSMrIMFM07lLyVCIao,17089
|
7
|
+
freeplay/freeplay_cli.py,sha256=nasbc_ckSr5-YtUKfg_w-6X1geQZ9s5u79VzRULGsbs,3868
|
8
|
+
freeplay/freeplay_thin.py,sha256=WHoVCkS30mDM7ghjDadgfj48BNL5EvaXktUsGfeXlIY,867
|
9
|
+
freeplay/llm_parameters.py,sha256=bQbfuC8EICF0XMZQa5pwI3FkQqxmCUVqHO3gYHy3Tg8,898
|
10
|
+
freeplay/model.py,sha256=kVARXUEJKbhOdWz7T8eR7npTPXlpaY9wWaEzJvbIvOU,534
|
11
|
+
freeplay/provider_config.py,sha256=hruf3Khusrwb76_-hv7ouuxmvJuaRyC1UxIw7XlJx8A,1416
|
12
|
+
freeplay/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
+
freeplay/record.py,sha256=_0uo0rUFZz8kwgWC0JhxFg13JyXgMfAVCkzZsuRLzBA,3354
|
14
|
+
freeplay/support.py,sha256=OOnUZOMYnLSEG_3toycWfHb2XZ8meF77uQRllYexXeo,12616
|
15
|
+
freeplay/utils.py,sha256=cRCCIzVqWNDKlTI-DDhXGyCkplbd-X4qzDs__aUpvww,1840
|
16
|
+
freeplay-0.2.32.dist-info/LICENSE,sha256=_jzIw45hB1XHGxiQ8leZ0GH_X7bR_a8qgxaqnHbCUOo,1064
|
17
|
+
freeplay-0.2.32.dist-info/METADATA,sha256=o9MiS7BrkV0M2Erp7bKomeRUBgveiqW6XQf7LLyVA4s,1633
|
18
|
+
freeplay-0.2.32.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
19
|
+
freeplay-0.2.32.dist-info/entry_points.txt,sha256=32s3rf2UUCqiJT4jnClEXZhdXlvl30uwpcxz-Gsy4UU,54
|
20
|
+
freeplay-0.2.32.dist-info/RECORD,,
|
freeplay-0.2.30.dist-info/RECORD
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
freeplay/__init__.py,sha256=74A9S9hmLq9BNHsdx0-37yDxlSukudNl9bJ0TE60Z30,61
|
2
|
-
freeplay/api_support.py,sha256=FJCm7yb1JhY0Z1Hn-JIVM7cCfBvWfCrqMQHRzzBzGLE,2012
|
3
|
-
freeplay/completions.py,sha256=JQtwe5THpkWqywUvOLyQFNa9t8kzNhIVkJni67U3HyI,1165
|
4
|
-
freeplay/errors.py,sha256=bPqsw32YX-xSr7O-G49M0sSFF7mq-YF1WGq928UV47s,631
|
5
|
-
freeplay/flavors.py,sha256=AUVAjZaP8VtK5F3NtQOa7_LD9YIs84gUafbUIqt6U84,18492
|
6
|
-
freeplay/freeplay.py,sha256=ObfW0QnSzuagfF5aMC44NPAZIokED3BUALuhqUY5-SA,28760
|
7
|
-
freeplay/freeplay_cli.py,sha256=nasbc_ckSr5-YtUKfg_w-6X1geQZ9s5u79VzRULGsbs,3868
|
8
|
-
freeplay/freeplay_thin.py,sha256=2YFfqFCYimUboRg_umasvHqi2-tzWTvpuf5b9-mQK3I,827
|
9
|
-
freeplay/llm_parameters.py,sha256=bQbfuC8EICF0XMZQa5pwI3FkQqxmCUVqHO3gYHy3Tg8,898
|
10
|
-
freeplay/provider_config.py,sha256=hruf3Khusrwb76_-hv7ouuxmvJuaRyC1UxIw7XlJx8A,1416
|
11
|
-
freeplay/record.py,sha256=pNLu5vPw6HyyPz5u-32pDfElY3hxeujaM1h7Xzah-VE,2961
|
12
|
-
freeplay/utils.py,sha256=SxZYKF5H6uotQa0m2B92CTk3ADr5N5SsUS_a6HQ0fnk,1026
|
13
|
-
freeplay-0.2.30.dist-info/LICENSE,sha256=_jzIw45hB1XHGxiQ8leZ0GH_X7bR_a8qgxaqnHbCUOo,1064
|
14
|
-
freeplay-0.2.30.dist-info/METADATA,sha256=XE8Y8IZibHed27Gi74EUrlfacpqVxWGxF7eyjE5mQZs,1633
|
15
|
-
freeplay-0.2.30.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
|
16
|
-
freeplay-0.2.30.dist-info/entry_points.txt,sha256=32s3rf2UUCqiJT4jnClEXZhdXlvl30uwpcxz-Gsy4UU,54
|
17
|
-
freeplay-0.2.30.dist-info/RECORD,,
|
File without changes
|
File without changes
|