freeplay 0.2.35__py3-none-any.whl → 0.2.37__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/flavors.py +1 -1
- freeplay/model.py +1 -1
- freeplay/support.py +1 -1
- freeplay/thin/freeplay_thin.py +12 -3
- freeplay/thin/resources/prompts.py +83 -15
- freeplay/thin/resources/recordings.py +2 -2
- {freeplay-0.2.35.dist-info → freeplay-0.2.37.dist-info}/METADATA +2 -1
- {freeplay-0.2.35.dist-info → freeplay-0.2.37.dist-info}/RECORD +11 -11
- {freeplay-0.2.35.dist-info → freeplay-0.2.37.dist-info}/WHEEL +1 -1
- {freeplay-0.2.35.dist-info → freeplay-0.2.37.dist-info}/LICENSE +0 -0
- {freeplay-0.2.35.dist-info → freeplay-0.2.37.dist-info}/entry_points.txt +0 -0
freeplay/flavors.py
CHANGED
@@ -50,7 +50,7 @@ class Flavor(ABC):
|
|
50
50
|
pass
|
51
51
|
|
52
52
|
@abstractmethod
|
53
|
-
def to_llm_syntax(self, messages: List[ChatMessage]) -> str
|
53
|
+
def to_llm_syntax(self, messages: List[ChatMessage]) -> Union[str, List[ChatMessage]]:
|
54
54
|
raise NotImplementedError()
|
55
55
|
|
56
56
|
@abstractmethod
|
freeplay/model.py
CHANGED
@@ -3,7 +3,7 @@ from typing import List, Union, Any, Dict, Mapping
|
|
3
3
|
|
4
4
|
from pydantic import RootModel
|
5
5
|
|
6
|
-
InputValue = Union[str, int, bool,
|
6
|
+
InputValue = Union[str, int, bool, Dict[str, Any], List[Any]]
|
7
7
|
InputVariable = RootModel[Union[Dict[str, "InputVariable"], List["InputVariable"], str, int, bool, float]]
|
8
8
|
InputVariable.model_rebuild()
|
9
9
|
|
freeplay/support.py
CHANGED
freeplay/thin/freeplay_thin.py
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
1
3
|
from freeplay.errors import FreeplayConfigurationError
|
2
4
|
from freeplay.record import DefaultRecordProcessor
|
3
5
|
from freeplay.support import CallSupport
|
4
6
|
from freeplay.thin.resources.customer_feedback import CustomerFeedback
|
5
|
-
from freeplay.thin.resources.prompts import Prompts
|
7
|
+
from freeplay.thin.resources.prompts import Prompts, APITemplateResolver, TemplateResolver
|
6
8
|
from freeplay.thin.resources.recordings import Recordings
|
7
9
|
from freeplay.thin.resources.sessions import Sessions
|
8
10
|
from freeplay.thin.resources.test_runs import TestRuns
|
@@ -12,7 +14,8 @@ class Freeplay:
|
|
12
14
|
def __init__(
|
13
15
|
self,
|
14
16
|
freeplay_api_key: str,
|
15
|
-
api_base: str
|
17
|
+
api_base: str,
|
18
|
+
template_resolver: Optional[TemplateResolver] = None
|
16
19
|
) -> None:
|
17
20
|
if not freeplay_api_key or not freeplay_api_key.strip():
|
18
21
|
raise FreeplayConfigurationError("Freeplay API key not set. It must be set to the Freeplay API.")
|
@@ -22,9 +25,15 @@ class Freeplay:
|
|
22
25
|
self.freeplay_api_key = freeplay_api_key
|
23
26
|
self.api_base = api_base
|
24
27
|
|
28
|
+
resolver: TemplateResolver
|
29
|
+
if template_resolver is None:
|
30
|
+
resolver = APITemplateResolver(self.call_support)
|
31
|
+
else:
|
32
|
+
resolver = template_resolver
|
33
|
+
|
25
34
|
# Resources ========
|
26
35
|
self.customer_feedback = CustomerFeedback(self.call_support)
|
27
|
-
self.prompts = Prompts(self.call_support)
|
36
|
+
self.prompts = Prompts(self.call_support, resolver)
|
28
37
|
self.recordings = Recordings(self.call_support)
|
29
38
|
self.sessions = Sessions()
|
30
39
|
self.test_runs = TestRuns(self.call_support)
|
@@ -1,8 +1,10 @@
|
|
1
1
|
import json
|
2
|
+
from abc import ABC, abstractmethod
|
2
3
|
from dataclasses import dataclass
|
3
|
-
from
|
4
|
+
from pathlib import Path
|
5
|
+
from typing import Dict, Optional, List, Union, cast
|
4
6
|
|
5
|
-
from freeplay.completions import PromptTemplates, ChatMessage
|
7
|
+
from freeplay.completions import PromptTemplates, ChatMessage, PromptTemplateWithMetadata
|
6
8
|
from freeplay.errors import FreeplayConfigurationError
|
7
9
|
from freeplay.flavors import Flavor
|
8
10
|
from freeplay.llm_parameters import LLMParameters
|
@@ -27,8 +29,8 @@ class FormattedPrompt:
|
|
27
29
|
def __init__(
|
28
30
|
self,
|
29
31
|
prompt_info: PromptInfo,
|
30
|
-
messages: List[
|
31
|
-
formatted_prompt: Union[str, List[
|
32
|
+
messages: List[Dict[str, str]],
|
33
|
+
formatted_prompt: Union[str, List[Dict[str, str]]]
|
32
34
|
):
|
33
35
|
self.prompt_info = prompt_info
|
34
36
|
self.messages = messages
|
@@ -36,8 +38,8 @@ class FormattedPrompt:
|
|
36
38
|
|
37
39
|
def all_messages(
|
38
40
|
self,
|
39
|
-
new_message:
|
40
|
-
) -> List[
|
41
|
+
new_message: Dict[str, str]
|
42
|
+
) -> List[Dict[str, str]]:
|
41
43
|
return self.messages + [new_message]
|
42
44
|
|
43
45
|
|
@@ -45,7 +47,7 @@ class BoundPrompt:
|
|
45
47
|
def __init__(
|
46
48
|
self,
|
47
49
|
prompt_info: PromptInfo,
|
48
|
-
messages: List[
|
50
|
+
messages: List[Dict[str, str]]
|
49
51
|
):
|
50
52
|
self.prompt_info = prompt_info
|
51
53
|
self.messages = messages
|
@@ -61,7 +63,7 @@ class BoundPrompt:
|
|
61
63
|
return FormattedPrompt(
|
62
64
|
self.prompt_info,
|
63
65
|
self.messages,
|
64
|
-
cast(Union[str, List[
|
66
|
+
cast(Union[str, List[Dict[str, str]]], llm_format)
|
65
67
|
)
|
66
68
|
|
67
69
|
|
@@ -69,7 +71,7 @@ class TemplatePrompt:
|
|
69
71
|
def __init__(
|
70
72
|
self,
|
71
73
|
prompt_info: PromptInfo,
|
72
|
-
messages: List[
|
74
|
+
messages: List[Dict[str, str]]
|
73
75
|
):
|
74
76
|
self.prompt_info = prompt_info
|
75
77
|
self.messages = messages
|
@@ -82,19 +84,85 @@ class TemplatePrompt:
|
|
82
84
|
return BoundPrompt(self.prompt_info, bound_messages)
|
83
85
|
|
84
86
|
|
87
|
+
class TemplateResolver(ABC):
|
88
|
+
@abstractmethod
|
89
|
+
def get_prompts(self, project_id: str, environment: str) -> PromptTemplates:
|
90
|
+
pass
|
91
|
+
|
92
|
+
|
93
|
+
class FilesystemTemplateResolver(TemplateResolver):
|
94
|
+
|
95
|
+
def __init__(self, freeplay_directory: Path):
|
96
|
+
FilesystemTemplateResolver.__validate_freeplay_directory(freeplay_directory)
|
97
|
+
self.prompts_directory = freeplay_directory / "freeplay" / "prompts"
|
98
|
+
|
99
|
+
def get_prompts(self, project_id: str, environment: str) -> PromptTemplates:
|
100
|
+
self.__validate_prompt_directory(project_id, environment)
|
101
|
+
|
102
|
+
directory = self.prompts_directory / project_id / environment
|
103
|
+
prompt_file_paths = directory.glob("*.json")
|
104
|
+
|
105
|
+
prompt_list = []
|
106
|
+
for prompt_file_path in prompt_file_paths:
|
107
|
+
json_dom = json.loads(prompt_file_path.read_text())
|
108
|
+
|
109
|
+
prompt_list.append(PromptTemplateWithMetadata(
|
110
|
+
prompt_template_id=json_dom.get('prompt_template_id'),
|
111
|
+
prompt_template_version_id=json_dom.get('prompt_template_version_id'),
|
112
|
+
name=json_dom.get('name'),
|
113
|
+
content=json_dom.get('content'),
|
114
|
+
flavor_name=json_dom.get('metadata').get('flavor_name'),
|
115
|
+
params=json_dom.get('metadata').get('params')
|
116
|
+
))
|
117
|
+
|
118
|
+
return PromptTemplates(prompt_list)
|
119
|
+
|
120
|
+
@staticmethod
|
121
|
+
def __validate_freeplay_directory(freeplay_directory: Path) -> None:
|
122
|
+
if not freeplay_directory.is_dir():
|
123
|
+
raise FreeplayConfigurationError(
|
124
|
+
"Path for prompt templates is not a valid directory (%s)" % freeplay_directory
|
125
|
+
)
|
126
|
+
|
127
|
+
prompts_directory = freeplay_directory / "freeplay" / "prompts"
|
128
|
+
if not prompts_directory.is_dir():
|
129
|
+
raise FreeplayConfigurationError(
|
130
|
+
"Invalid path for prompt templates (%s). "
|
131
|
+
"Did not find a freeplay/prompts directory underneath." % freeplay_directory
|
132
|
+
)
|
133
|
+
|
134
|
+
def __validate_prompt_directory(self, project_id: str, environment: str) -> None:
|
135
|
+
maybe_prompt_dir = self.prompts_directory / project_id / environment
|
136
|
+
if not maybe_prompt_dir.is_dir():
|
137
|
+
raise FreeplayConfigurationError(
|
138
|
+
"Could not find prompt template directory for project ID %s and environment %s." %
|
139
|
+
(project_id, environment)
|
140
|
+
)
|
141
|
+
|
142
|
+
|
143
|
+
class APITemplateResolver(TemplateResolver):
|
144
|
+
|
145
|
+
def __init__(self, call_support: CallSupport):
|
146
|
+
self.call_support = call_support
|
147
|
+
|
148
|
+
def get_prompts(self, project_id: str, environment: str) -> PromptTemplates:
|
149
|
+
return self.call_support.get_prompts(
|
150
|
+
project_id=project_id,
|
151
|
+
tag=environment
|
152
|
+
)
|
153
|
+
|
154
|
+
|
85
155
|
class Prompts:
|
86
|
-
def __init__(self, call_support: CallSupport) -> None:
|
156
|
+
def __init__(self, call_support: CallSupport, template_resolver: TemplateResolver) -> None:
|
87
157
|
self.call_support = call_support
|
158
|
+
self.template_resolver = template_resolver
|
88
159
|
|
89
160
|
def get_all(self, project_id: str, environment: str) -> PromptTemplates:
|
90
161
|
return self.call_support.get_prompts(project_id=project_id, tag=environment)
|
91
162
|
|
92
163
|
def get(self, project_id: str, template_name: str, environment: str) -> TemplatePrompt:
|
93
|
-
|
94
|
-
|
95
|
-
template_name=template_name,
|
96
|
-
environment=environment
|
97
|
-
)
|
164
|
+
prompt_templates = self.template_resolver.get_prompts(project_id, environment)
|
165
|
+
prompt_template = self.call_support.find_template_by_name(prompt_templates, template_name)
|
98
166
|
|
99
167
|
messages = json.loads(prompt_template.content)
|
100
168
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import json
|
2
2
|
import logging
|
3
3
|
from dataclasses import dataclass
|
4
|
-
from typing import Optional, List
|
4
|
+
from typing import Dict, Optional, List
|
5
5
|
|
6
6
|
from freeplay import api_support
|
7
7
|
from freeplay.completions import PromptTemplateWithMetadata, OpenAIFunctionCall
|
@@ -50,7 +50,7 @@ class TestRunInfo:
|
|
50
50
|
|
51
51
|
@dataclass
|
52
52
|
class RecordPayload:
|
53
|
-
all_messages: List[
|
53
|
+
all_messages: List[Dict[str, str]]
|
54
54
|
inputs: InputVariables
|
55
55
|
|
56
56
|
session_info: SessionInfo
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: freeplay
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.37
|
4
4
|
Summary:
|
5
5
|
License: MIT
|
6
6
|
Author: FreePlay Engineering
|
@@ -12,6 +12,7 @@ Classifier: Programming Language :: Python :: 3.8
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.9
|
13
13
|
Classifier: Programming Language :: Python :: 3.10
|
14
14
|
Classifier: Programming Language :: Python :: 3.11
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
15
16
|
Requires-Dist: anthropic (>=0.7.7,<0.8.0)
|
16
17
|
Requires-Dist: click (==8.1.7)
|
17
18
|
Requires-Dist: dacite (>=1.8.0,<2.0.0)
|
@@ -2,26 +2,26 @@ freeplay/__init__.py,sha256=74A9S9hmLq9BNHsdx0-37yDxlSukudNl9bJ0TE60Z30,61
|
|
2
2
|
freeplay/api_support.py,sha256=u8b1e9prlR4_qOcqmFduU7U35ubQt1tWJ6bXhUdsv0c,2240
|
3
3
|
freeplay/completions.py,sha256=F1rMBtQaCtn0rBQqvCurkV25g8gLtwnEod5rRvf-txY,1176
|
4
4
|
freeplay/errors.py,sha256=bPqsw32YX-xSr7O-G49M0sSFF7mq-YF1WGq928UV47s,631
|
5
|
-
freeplay/flavors.py,sha256=
|
5
|
+
freeplay/flavors.py,sha256=IytHc1C1q0ZTJn9T6Mt6oJn6eeTqQBc-9habH7p-T80,17242
|
6
6
|
freeplay/freeplay.py,sha256=BLlr4YXh3a624xcM93KvZGsiIGSMrIMFM07lLyVCIao,17089
|
7
7
|
freeplay/freeplay_cli.py,sha256=k9QPBedcFqpy9Ec9k7DT_y-NpVxHqRF5jKPTaQBBs1Q,3863
|
8
8
|
freeplay/llm_parameters.py,sha256=bQbfuC8EICF0XMZQa5pwI3FkQqxmCUVqHO3gYHy3Tg8,898
|
9
|
-
freeplay/model.py,sha256=
|
9
|
+
freeplay/model.py,sha256=7BRAuyxsLl8X-ue8wXPmAiKYp4OaYI-HkaGc3t5qtMU,534
|
10
10
|
freeplay/provider_config.py,sha256=hruf3Khusrwb76_-hv7ouuxmvJuaRyC1UxIw7XlJx8A,1416
|
11
11
|
freeplay/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
12
|
freeplay/record.py,sha256=69vO9vYGFL8gLrvRqLzlvodVNo05GOzKDJnCyhUha08,3615
|
13
|
-
freeplay/support.py,sha256=
|
13
|
+
freeplay/support.py,sha256=KP_rRgn0gh6n5BOGGExHO9pip9Pj22_WSvF6v106kX8,13083
|
14
14
|
freeplay/thin/__init__.py,sha256=XgU_eMmTpOPCa9w5mVOyxPgwAgRFfVdRWDazYGYZtQ0,351
|
15
|
-
freeplay/thin/freeplay_thin.py,sha256=
|
15
|
+
freeplay/thin/freeplay_thin.py,sha256=raVESB8VWoCSeCsGPDr-DOx37WXi8D27odKnOeDWwV0,1613
|
16
16
|
freeplay/thin/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
17
|
freeplay/thin/resources/customer_feedback.py,sha256=aTM7Eez7iYmjXSpRqkHxf4pi6xBrzVnMiQCEJVfPGvg,527
|
18
|
-
freeplay/thin/resources/prompts.py,sha256=
|
19
|
-
freeplay/thin/resources/recordings.py,sha256=
|
18
|
+
freeplay/thin/resources/prompts.py,sha256=CRsvrIIe59WHTAA1PFvfNOK2x9S-C9zCz_z8XzsIg4w,7142
|
19
|
+
freeplay/thin/resources/recordings.py,sha256=utrGTjPPiNt1btI0Hiti9s7VvCYFWqitAx35zrXrOfg,5047
|
20
20
|
freeplay/thin/resources/sessions.py,sha256=ioWdeTM9BSrEWKrFH66ysQIw5kCTlCVopJDmWtFgHz0,868
|
21
21
|
freeplay/thin/resources/test_runs.py,sha256=L8A1tQHzYg9UmLgbNFtFa8pGXqyrcoyTtSE0sSnd9UE,1267
|
22
22
|
freeplay/utils.py,sha256=cRCCIzVqWNDKlTI-DDhXGyCkplbd-X4qzDs__aUpvww,1840
|
23
|
-
freeplay-0.2.
|
24
|
-
freeplay-0.2.
|
25
|
-
freeplay-0.2.
|
26
|
-
freeplay-0.2.
|
27
|
-
freeplay-0.2.
|
23
|
+
freeplay-0.2.37.dist-info/LICENSE,sha256=_jzIw45hB1XHGxiQ8leZ0GH_X7bR_a8qgxaqnHbCUOo,1064
|
24
|
+
freeplay-0.2.37.dist-info/METADATA,sha256=0QabpMND4wK9yg-3bGxZZJzMKVTikH0v1iLf0HOgyiE,1676
|
25
|
+
freeplay-0.2.37.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
26
|
+
freeplay-0.2.37.dist-info/entry_points.txt,sha256=32s3rf2UUCqiJT4jnClEXZhdXlvl30uwpcxz-Gsy4UU,54
|
27
|
+
freeplay-0.2.37.dist-info/RECORD,,
|
File without changes
|
File without changes
|