freeplay 0.3.24a0__py3-none-any.whl → 0.3.25__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/freeplay_cli.py +49 -4
- freeplay/resources/prompts.py +3 -0
- freeplay/resources/test_runs.py +24 -10
- freeplay/support.py +33 -0
- {freeplay-0.3.24a0.dist-info → freeplay-0.3.25.dist-info}/METADATA +1 -1
- {freeplay-0.3.24a0.dist-info → freeplay-0.3.25.dist-info}/RECORD +9 -9
- {freeplay-0.3.24a0.dist-info → freeplay-0.3.25.dist-info}/LICENSE +0 -0
- {freeplay-0.3.24a0.dist-info → freeplay-0.3.25.dist-info}/WHEEL +0 -0
- {freeplay-0.3.24a0.dist-info → freeplay-0.3.25.dist-info}/entry_points.txt +0 -0
freeplay/freeplay_cli.py
CHANGED
@@ -50,7 +50,53 @@ def download(project_id: str, environment: str, output_dir: str) -> None:
|
|
50
50
|
click.echo(f"Found {len(prompts.prompt_templates)} prompt templates")
|
51
51
|
|
52
52
|
for prompt in prompts.prompt_templates:
|
53
|
-
__write_single_file(environment, output_dir,
|
53
|
+
__write_single_file(environment, output_dir, prompt)
|
54
|
+
except FreeplayClientError as e:
|
55
|
+
print(f"Error downloading templates: {e}.\nIs your project ID correct?", file=sys.stderr)
|
56
|
+
exit(1)
|
57
|
+
except FreeplayServerError as e:
|
58
|
+
print(f"Error on Freeplay's servers downloading templates: {e}.\nTry again after a short wait.",
|
59
|
+
file=sys.stderr)
|
60
|
+
exit(2)
|
61
|
+
except Exception as e:
|
62
|
+
print(f"Error downloading templates: {e}", file=sys.stderr)
|
63
|
+
exit(3)
|
64
|
+
|
65
|
+
|
66
|
+
@cli.command()
|
67
|
+
@click.option("--environment", required=True, help="The environment from which the prompts will be pulled.", default="latest")
|
68
|
+
@click.option("--output-dir", required=True, help="The directory where the prompts will be saved.")
|
69
|
+
def download_all(environment: str, output_dir: str) -> None:
|
70
|
+
if "FREEPLAY_API_KEY" not in os.environ:
|
71
|
+
print("FREEPLAY_API_KEY is not set. It is required to run the freeplay command.", file=sys.stderr)
|
72
|
+
exit(4)
|
73
|
+
|
74
|
+
if "FREEPLAY_SUBDOMAIN" not in os.environ:
|
75
|
+
print("FREEPLAY_SUBDOMAIN is not set. It is required to run the freeplay command.", file=sys.stderr)
|
76
|
+
exit(4)
|
77
|
+
|
78
|
+
FREEPLAY_API_KEY = os.environ["FREEPLAY_API_KEY"]
|
79
|
+
freeplay_api_url = f'https://{os.environ["FREEPLAY_SUBDOMAIN"]}.freeplay.ai/api'
|
80
|
+
|
81
|
+
if "FREEPLAY_API_URL" in os.environ:
|
82
|
+
freeplay_api_url = f'{os.environ["FREEPLAY_API_URL"]}/api'
|
83
|
+
click.echo("Using URL override for Freeplay specified in the FREEPLAY_API_URL environment variable")
|
84
|
+
|
85
|
+
click.echo(
|
86
|
+
f"Downloading prompts for environment {environment}, "
|
87
|
+
f"to directory {output_dir} from {freeplay_api_url}")
|
88
|
+
|
89
|
+
fp_client = Freeplay(
|
90
|
+
freeplay_api_key=FREEPLAY_API_KEY,
|
91
|
+
api_base=freeplay_api_url
|
92
|
+
)
|
93
|
+
|
94
|
+
try:
|
95
|
+
prompts: PromptTemplates = fp_client.prompts.get_all_for_environment(environment=environment)
|
96
|
+
click.echo(f"Found {len(prompts.prompt_templates)} prompt templates")
|
97
|
+
|
98
|
+
for prompt in prompts.prompt_templates:
|
99
|
+
__write_single_file(environment, output_dir, prompt)
|
54
100
|
except FreeplayClientError as e:
|
55
101
|
print(f"Error downloading templates: {e}.\nIs your project ID correct?", file=sys.stderr)
|
56
102
|
exit(1)
|
@@ -66,10 +112,9 @@ def download(project_id: str, environment: str, output_dir: str) -> None:
|
|
66
112
|
def __write_single_file(
|
67
113
|
environment: str,
|
68
114
|
output_dir: str,
|
69
|
-
project_id: str,
|
70
115
|
prompt: PromptTemplate
|
71
116
|
) -> None:
|
72
|
-
directory = __root_dir(environment, output_dir, project_id)
|
117
|
+
directory = __root_dir(environment, output_dir, prompt.project_id)
|
73
118
|
basename = f'{prompt.prompt_template_name}'
|
74
119
|
prompt_path = directory / f'{basename}.json'
|
75
120
|
click.echo("Writing prompt file: %s" % prompt_path)
|
@@ -87,6 +132,6 @@ def __write_single_file(
|
|
87
132
|
|
88
133
|
|
89
134
|
def __root_dir(environment: str, output_dir: str, project_id: str) -> Path:
|
90
|
-
directory = Path(output_dir) / "freeplay" / "prompts" / project_id / environment
|
135
|
+
directory = Path(output_dir).resolve() / "freeplay" / "prompts" / project_id / environment
|
91
136
|
os.makedirs(directory, exist_ok=True)
|
92
137
|
return directory
|
freeplay/resources/prompts.py
CHANGED
@@ -557,6 +557,9 @@ class Prompts:
|
|
557
557
|
|
558
558
|
return TemplatePrompt(prompt_info, prompt.content, prompt.tool_schema)
|
559
559
|
|
560
|
+
def get_all_for_environment(self, environment: str) -> PromptTemplates:
|
561
|
+
return self.call_support.get_prompts_for_environment(environment=environment)
|
562
|
+
|
560
563
|
def get_by_version_id(self, project_id: str, template_id: str, version_id: str) -> TemplatePrompt:
|
561
564
|
prompt = self.template_resolver.get_prompt_version_id(project_id, template_id, version_id)
|
562
565
|
|
freeplay/resources/test_runs.py
CHANGED
@@ -1,23 +1,34 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
|
-
from typing import List, Optional, Dict
|
2
|
+
from typing import List, Optional, Dict, Any
|
3
|
+
import warnings
|
3
4
|
|
4
5
|
from freeplay.model import InputVariables, TestRunInfo
|
5
6
|
from freeplay.support import CallSupport, SummaryStatistics
|
6
7
|
|
7
|
-
|
8
8
|
@dataclass
|
9
|
-
class
|
9
|
+
class CompletionTestCase:
|
10
10
|
def __init__(
|
11
11
|
self,
|
12
12
|
test_case_id: str,
|
13
13
|
variables: InputVariables,
|
14
14
|
output: Optional[str],
|
15
|
-
history: Optional[List[Dict[str, str]]]
|
15
|
+
history: Optional[List[Dict[str, str]]],
|
16
|
+
custom_metadata: Optional[Dict[str, str]]
|
16
17
|
):
|
17
18
|
self.id = test_case_id
|
18
19
|
self.variables = variables
|
19
20
|
self.output = output
|
20
21
|
self.history = history
|
22
|
+
self.custom_metadata = custom_metadata
|
23
|
+
|
24
|
+
class TestCase(CompletionTestCase):
|
25
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
26
|
+
warnings.warn(
|
27
|
+
"'TestCase' is deprecated; use 'CompletionTestCase' instead.",
|
28
|
+
DeprecationWarning,
|
29
|
+
stacklevel=2,
|
30
|
+
)
|
31
|
+
super().__init__(*args, **kwargs)
|
21
32
|
|
22
33
|
class TraceTestCase:
|
23
34
|
def __init__(
|
@@ -25,17 +36,18 @@ class TraceTestCase:
|
|
25
36
|
test_case_id: str,
|
26
37
|
input: str,
|
27
38
|
output: Optional[str],
|
39
|
+
custom_metadata: Optional[Dict[str, str]]
|
28
40
|
):
|
29
41
|
self.id = test_case_id
|
30
42
|
self.input = input
|
31
43
|
self.output = output
|
32
|
-
|
44
|
+
self.custom_metadata = custom_metadata
|
33
45
|
@dataclass
|
34
46
|
class TestRun:
|
35
47
|
def __init__(
|
36
48
|
self,
|
37
49
|
test_run_id: str,
|
38
|
-
test_cases: List[
|
50
|
+
test_cases: List[CompletionTestCase] = [],
|
39
51
|
trace_test_cases: List[TraceTestCase] = []
|
40
52
|
):
|
41
53
|
self.test_run_id = test_run_id
|
@@ -46,7 +58,7 @@ class TestRun:
|
|
46
58
|
if self.test_cases and len(self.test_cases) > 0 and self.trace_test_cases and len(self.trace_test_cases) > 0:
|
47
59
|
raise ValueError("Test case and trace test case cannot both be present")
|
48
60
|
|
49
|
-
def get_test_cases(self) -> List[
|
61
|
+
def get_test_cases(self) -> List[CompletionTestCase]:
|
50
62
|
self.__must_not_be_both_trace_and_completion()
|
51
63
|
if len(self.trace_test_cases) > 0:
|
52
64
|
raise ValueError("Completion test cases are not present. Please use get_trace_test_cases() instead.")
|
@@ -93,16 +105,18 @@ class TestRuns:
|
|
93
105
|
test_run = self.call_support.create_test_run(
|
94
106
|
project_id, testlist, include_outputs, name, description, flavor_name)
|
95
107
|
test_cases = [
|
96
|
-
|
108
|
+
CompletionTestCase(test_case_id=test_case.id,
|
97
109
|
variables=test_case.variables,
|
98
110
|
output=test_case.output,
|
99
|
-
history=test_case.history
|
111
|
+
history=test_case.history,
|
112
|
+
custom_metadata=test_case.custom_metadata)
|
100
113
|
for test_case in test_run.test_cases
|
101
114
|
]
|
102
115
|
trace_test_cases = [
|
103
116
|
TraceTestCase(test_case_id=test_case.id,
|
104
117
|
input=test_case.input,
|
105
|
-
output=test_case.output
|
118
|
+
output=test_case.output,
|
119
|
+
custom_metadata=test_case.custom_metadata)
|
106
120
|
for test_case in test_run.trace_test_cases
|
107
121
|
]
|
108
122
|
|
freeplay/support.py
CHANGED
@@ -76,6 +76,17 @@ class SummaryStatistics:
|
|
76
76
|
human_evaluation: Dict[str, Any]
|
77
77
|
|
78
78
|
|
79
|
+
@dataclass
|
80
|
+
class ProjectInfo:
|
81
|
+
id: str
|
82
|
+
name: str
|
83
|
+
|
84
|
+
|
85
|
+
@dataclass
|
86
|
+
class ProjectInfos:
|
87
|
+
projects: List[ProjectInfo]
|
88
|
+
|
89
|
+
|
79
90
|
class PromptTemplateEncoder(JSONEncoder):
|
80
91
|
def default(self, prompt_template: PromptTemplate) -> Dict[str, Any]:
|
81
92
|
return prompt_template.__dict__
|
@@ -89,6 +100,7 @@ class TestCaseTestRunResponse:
|
|
89
100
|
self.history: Optional[List[Dict[str, Any]]] = test_case.get('history')
|
90
101
|
self.custom_metadata: Optional[Dict[str, str]] = test_case.get('custom_metadata')
|
91
102
|
|
103
|
+
|
92
104
|
class TraceTestCaseTestRunResponse:
|
93
105
|
def __init__(self, test_case: Dict[str, Any]):
|
94
106
|
self.id: str = test_case['test_case_id']
|
@@ -96,6 +108,7 @@ class TraceTestCaseTestRunResponse:
|
|
96
108
|
self.output: Optional[str] = test_case.get('output')
|
97
109
|
self.custom_metadata: Optional[Dict[str, str]] = test_case.get('custom_metadata')
|
98
110
|
|
111
|
+
|
99
112
|
class TestRunResponse:
|
100
113
|
def __init__(
|
101
114
|
self,
|
@@ -185,6 +198,26 @@ class CallSupport:
|
|
185
198
|
|
186
199
|
return maybe_prompts
|
187
200
|
|
201
|
+
def get_prompts_for_environment(self, environment: str) -> PromptTemplates:
|
202
|
+
projects_response = api_support.get_raw(
|
203
|
+
api_key=self.freeplay_api_key,
|
204
|
+
url=f'{self.api_base}/v2/projects/all'
|
205
|
+
)
|
206
|
+
if projects_response.status_code != 200:
|
207
|
+
raise freeplay_response_error("Error getting prompt templates", projects_response)
|
208
|
+
|
209
|
+
maybe_projects: Optional[ProjectInfos] = try_decode(ProjectInfos, projects_response.content)
|
210
|
+
if maybe_projects is None:
|
211
|
+
raise FreeplayServerError('Failed to parse list of projects from server')
|
212
|
+
|
213
|
+
prompt_templates = PromptTemplates([])
|
214
|
+
for project in maybe_projects.projects:
|
215
|
+
prompt_templates.prompt_templates.extend(
|
216
|
+
self.get_prompts(project.id, environment).prompt_templates
|
217
|
+
)
|
218
|
+
|
219
|
+
return prompt_templates
|
220
|
+
|
188
221
|
def get_prompt(self, project_id: str, template_name: str, environment: str) -> PromptTemplate:
|
189
222
|
response = api_support.get_raw(
|
190
223
|
api_key=self.freeplay_api_key,
|
@@ -2,22 +2,22 @@ freeplay/__init__.py,sha256=ljXF0vHC3oGgk-vLyJFawr7MZKOj_ExYJJsVdrpqZoM,482
|
|
2
2
|
freeplay/api_support.py,sha256=Kn2x3g6yloHQl3NwFRjbZE9BnIh7d1sgwGwC0mHuvw4,2483
|
3
3
|
freeplay/errors.py,sha256=vwotUBldxDzREZOmLUeoiDoZjcvDwgH1AMwKBLhLooE,807
|
4
4
|
freeplay/freeplay.py,sha256=J04-erDD6rI2SAje_Nsf3x5Qx-Z6p8gQvGrMRHFWoD4,1602
|
5
|
-
freeplay/freeplay_cli.py,sha256=
|
5
|
+
freeplay/freeplay_cli.py,sha256=TFkMt4_gjV9BLmxA9iBaPgdl4QK4qYdN-HLxHm1A1-A,5451
|
6
6
|
freeplay/llm_parameters.py,sha256=bQbfuC8EICF0XMZQa5pwI3FkQqxmCUVqHO3gYHy3Tg8,898
|
7
7
|
freeplay/model.py,sha256=GI3qPRouwdrBFOPBrcQFt5O0chtlSNvl8jAstePuYlA,1480
|
8
8
|
freeplay/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
9
|
freeplay/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
10
|
freeplay/resources/adapters.py,sha256=6ZAPpoLeOkUkV1s9VNQNsYrnupV0-sy11zFfKfctM1Y,9296
|
11
11
|
freeplay/resources/customer_feedback.py,sha256=bw8MfEOKbGgn4FOyvcADrcs9GhcpNXNTgxKjBjIzywE,899
|
12
|
-
freeplay/resources/prompts.py,sha256=
|
12
|
+
freeplay/resources/prompts.py,sha256=7hQU0f6GW3qNqEytsiFOnHY6M5c1O6B0w9QDmNk91n0,23516
|
13
13
|
freeplay/resources/recordings.py,sha256=V8KAPWnYAQ2-gqwyAJveD8a_AaBPYT32N_xbPU4S27M,9153
|
14
14
|
freeplay/resources/sessions.py,sha256=dZtd9nq2nH8pmXxQOJitBnN5Jl3kjggDItDcjC69TYo,3883
|
15
15
|
freeplay/resources/test_cases.py,sha256=nXL_976RwSJDT6OWDM4GEzbcOzcGkJ9ulvb0XOzCRDM,2240
|
16
|
-
freeplay/resources/test_runs.py,sha256=
|
17
|
-
freeplay/support.py,sha256=
|
16
|
+
freeplay/resources/test_runs.py,sha256=u7bBfJ3Ro5DJZQdjCAXj4Xj-3fYmtQIGhy8vJeluJvQ,4668
|
17
|
+
freeplay/support.py,sha256=NYk0IBUZtyYJ4h4dyNA4dVG-QT5zsO9MHQ8PuXNFP_4,14297
|
18
18
|
freeplay/utils.py,sha256=Xvt4mNLXLL7E6MI2hTuDLV5cl5Y83DgdjCZSyDGMjR0,3187
|
19
|
-
freeplay-0.3.
|
20
|
-
freeplay-0.3.
|
21
|
-
freeplay-0.3.
|
22
|
-
freeplay-0.3.
|
23
|
-
freeplay-0.3.
|
19
|
+
freeplay-0.3.25.dist-info/LICENSE,sha256=_jzIw45hB1XHGxiQ8leZ0GH_X7bR_a8qgxaqnHbCUOo,1064
|
20
|
+
freeplay-0.3.25.dist-info/METADATA,sha256=bmBW4iPCJsJYyFpgQ0Q4LbsUE9_Df494gUgtpEg0DC8,1661
|
21
|
+
freeplay-0.3.25.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
22
|
+
freeplay-0.3.25.dist-info/entry_points.txt,sha256=32s3rf2UUCqiJT4jnClEXZhdXlvl30uwpcxz-Gsy4UU,54
|
23
|
+
freeplay-0.3.25.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|