freeplay 0.3.19__py3-none-any.whl → 0.3.20__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/resources/adapters.py +50 -17
- freeplay/resources/prompts.py +5 -7
- freeplay/support.py +4 -1
- {freeplay-0.3.19.dist-info → freeplay-0.3.20.dist-info}/METADATA +1 -1
- {freeplay-0.3.19.dist-info → freeplay-0.3.20.dist-info}/RECORD +8 -8
- {freeplay-0.3.19.dist-info → freeplay-0.3.20.dist-info}/LICENSE +0 -0
- {freeplay-0.3.19.dist-info → freeplay-0.3.20.dist-info}/WHEEL +0 -0
- {freeplay-0.3.19.dist-info → freeplay-0.3.20.dist-info}/entry_points.txt +0 -0
freeplay/resources/adapters.py
CHANGED
@@ -3,6 +3,7 @@ from dataclasses import dataclass
|
|
3
3
|
from typing import Protocol, Dict, List, Union, Any
|
4
4
|
|
5
5
|
from freeplay.errors import FreeplayConfigurationError
|
6
|
+
from freeplay.support import MediaType
|
6
7
|
|
7
8
|
|
8
9
|
@dataclass
|
@@ -11,12 +12,16 @@ class TextContent:
|
|
11
12
|
|
12
13
|
|
13
14
|
@dataclass
|
14
|
-
class
|
15
|
+
class MediaContentUrl:
|
16
|
+
slot_name: str
|
17
|
+
type: MediaType
|
15
18
|
url: str
|
16
19
|
|
17
20
|
|
18
21
|
@dataclass
|
19
|
-
class
|
22
|
+
class MediaContentBase64:
|
23
|
+
slot_name: str
|
24
|
+
type: MediaType
|
20
25
|
content_type: str
|
21
26
|
data: str
|
22
27
|
|
@@ -58,24 +63,28 @@ class AnthropicAdapter(LLMAdapter):
|
|
58
63
|
return anthropic_messages
|
59
64
|
|
60
65
|
@staticmethod
|
61
|
-
def __map_content(content: Union[TextContent,
|
66
|
+
def __map_content(content: Union[TextContent, MediaContentBase64, MediaContentUrl]) -> Dict[str, Any]:
|
62
67
|
if isinstance(content, TextContent):
|
63
68
|
return {
|
64
69
|
"type": "text",
|
65
70
|
"text": content.text
|
66
71
|
}
|
67
|
-
|
72
|
+
if content.type == "audio" or content.type == "video":
|
73
|
+
raise ValueError("Anthropic does not support audio or video content")
|
74
|
+
|
75
|
+
media_type = "image" if content.type == "image" else "document"
|
76
|
+
if isinstance(content, MediaContentBase64):
|
68
77
|
return {
|
69
|
-
"type":
|
78
|
+
"type": media_type,
|
70
79
|
"source": {
|
71
80
|
"type": "base64",
|
72
81
|
"media_type": content.content_type,
|
73
82
|
"data": content.data,
|
74
83
|
}
|
75
84
|
}
|
76
|
-
elif isinstance(content,
|
85
|
+
elif isinstance(content, MediaContentUrl):
|
77
86
|
return {
|
78
|
-
"type":
|
87
|
+
"type": media_type,
|
79
88
|
"source": {
|
80
89
|
"type": "url",
|
81
90
|
"url": content.url,
|
@@ -101,28 +110,52 @@ class OpenAIAdapter(LLMAdapter):
|
|
101
110
|
return openai_messages
|
102
111
|
|
103
112
|
@staticmethod
|
104
|
-
def __map_content(content: Union[TextContent,
|
113
|
+
def __map_content(content: Union[TextContent, MediaContentBase64, MediaContentUrl]) -> Dict[str, Any]:
|
105
114
|
if isinstance(content, TextContent):
|
106
115
|
return {
|
107
116
|
"type": "text",
|
108
117
|
"text": content.text
|
109
118
|
}
|
110
|
-
elif isinstance(content,
|
119
|
+
elif isinstance(content, MediaContentBase64):
|
120
|
+
return OpenAIAdapter.__format_base64_content(content)
|
121
|
+
elif isinstance(content, MediaContentUrl):
|
122
|
+
if content.type != "image":
|
123
|
+
raise ValueError("Message contains a non-image URL, but OpenAI only supports image URLs.")
|
124
|
+
|
111
125
|
return {
|
112
126
|
"type": "image_url",
|
113
127
|
"image_url": {
|
114
|
-
"url":
|
128
|
+
"url": content.url
|
129
|
+
}
|
130
|
+
}
|
131
|
+
else:
|
132
|
+
raise ValueError(f"Unexpected content type {type(content)}")
|
133
|
+
|
134
|
+
@staticmethod
|
135
|
+
def __format_base64_content(content: MediaContentBase64) -> Dict[str, Any]:
|
136
|
+
if content.type == "audio":
|
137
|
+
return {
|
138
|
+
"type": "input_audio",
|
139
|
+
"input_audio": {
|
140
|
+
"data": content.data,
|
141
|
+
"format": content.content_type.split("/")[-1].replace("mpeg", "mp3")
|
142
|
+
}
|
143
|
+
}
|
144
|
+
elif content.type == "file":
|
145
|
+
return {
|
146
|
+
"type": "file",
|
147
|
+
"file": {
|
148
|
+
"filename": f"{content.slot_name}.{content.content_type.split('/')[-1]}",
|
149
|
+
"file_data": f"data:{content.content_type};base64,{content.data}"
|
115
150
|
}
|
116
151
|
}
|
117
|
-
|
152
|
+
else:
|
118
153
|
return {
|
119
154
|
"type": "image_url",
|
120
155
|
"image_url": {
|
121
|
-
"url": content.
|
156
|
+
"url": f"data:{content.content_type};base64,{content.data}"
|
122
157
|
}
|
123
158
|
}
|
124
|
-
else:
|
125
|
-
raise ValueError(f"Unexpected content type {type(content)}")
|
126
159
|
|
127
160
|
|
128
161
|
class Llama3Adapter(LLMAdapter):
|
@@ -163,17 +196,17 @@ class GeminiAdapter(LLMAdapter):
|
|
163
196
|
return gemini_messages
|
164
197
|
|
165
198
|
@staticmethod
|
166
|
-
def __map_content(content: Union[TextContent,
|
199
|
+
def __map_content(content: Union[TextContent, MediaContentBase64, MediaContentUrl]) -> Dict[str, Any]:
|
167
200
|
if isinstance(content, TextContent):
|
168
201
|
return {"text": content.text}
|
169
|
-
elif isinstance(content,
|
202
|
+
elif isinstance(content, MediaContentBase64):
|
170
203
|
return {
|
171
204
|
"inline_data": {
|
172
205
|
"data": content.data,
|
173
206
|
"mime_type": content.content_type,
|
174
207
|
}
|
175
208
|
}
|
176
|
-
elif isinstance(content,
|
209
|
+
elif isinstance(content, MediaContentUrl):
|
177
210
|
raise ValueError("Message contains an image URL, but image URLs are not supported by Gemini")
|
178
211
|
else:
|
179
212
|
raise ValueError(f"Unexpected content type {type(content)}")
|
freeplay/resources/prompts.py
CHANGED
@@ -25,7 +25,7 @@ from freeplay.errors import (
|
|
25
25
|
)
|
26
26
|
from freeplay.llm_parameters import LLMParameters
|
27
27
|
from freeplay.model import InputVariables
|
28
|
-
from freeplay.resources.adapters import MissingFlavorError, adaptor_for_flavor,
|
28
|
+
from freeplay.resources.adapters import MissingFlavorError, adaptor_for_flavor, MediaContentBase64, MediaContentUrl, \
|
29
29
|
TextContent
|
30
30
|
from freeplay.support import (
|
31
31
|
CallSupport,
|
@@ -212,18 +212,16 @@ MediaInputMap = Dict[str, MediaInput]
|
|
212
212
|
|
213
213
|
|
214
214
|
def extract_media_content(media_inputs: MediaInputMap, media_slots: List[MediaSlot]) -> List[
|
215
|
-
Union[
|
216
|
-
media_content: List[Union[
|
215
|
+
Union[MediaContentBase64, MediaContentUrl]]:
|
216
|
+
media_content: List[Union[MediaContentBase64, MediaContentUrl]] = []
|
217
217
|
for slot in media_slots:
|
218
|
-
if slot.type != "image":
|
219
|
-
continue
|
220
218
|
file = media_inputs.get(slot.placeholder_name, None)
|
221
219
|
if file is None:
|
222
220
|
continue
|
223
221
|
if isinstance(file, MediaInputUrl):
|
224
|
-
media_content.append(
|
222
|
+
media_content.append(MediaContentUrl(type=slot.type, url=file.url, slot_name=slot.placeholder_name))
|
225
223
|
else:
|
226
|
-
media_content.append(
|
224
|
+
media_content.append(MediaContentBase64(type=slot.type, content_type=file.content_type, data=file.data, slot_name=slot.placeholder_name))
|
227
225
|
|
228
226
|
return media_content
|
229
227
|
|
freeplay/support.py
CHANGED
@@ -29,9 +29,12 @@ class ToolSchema:
|
|
29
29
|
Role = Literal['system', 'user', 'assistant']
|
30
30
|
|
31
31
|
|
32
|
+
MediaType = Literal["image", "audio", "video", "file"]
|
33
|
+
|
34
|
+
|
32
35
|
@dataclass
|
33
36
|
class MediaSlot:
|
34
|
-
type:
|
37
|
+
type: MediaType
|
35
38
|
placeholder_name: str
|
36
39
|
|
37
40
|
|
@@ -7,17 +7,17 @@ freeplay/llm_parameters.py,sha256=bQbfuC8EICF0XMZQa5pwI3FkQqxmCUVqHO3gYHy3Tg8,89
|
|
7
7
|
freeplay/model.py,sha256=o0de_RZ2WTJ4m5OJw1ZVfC2xG6zBq_XShBrRt1laEjc,1405
|
8
8
|
freeplay/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
9
|
freeplay/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
|
-
freeplay/resources/adapters.py,sha256=
|
10
|
+
freeplay/resources/adapters.py,sha256=BFqzLoJhLJeXfUyPOKDnllN_3jlbbBH0z32tXv20R20,8188
|
11
11
|
freeplay/resources/customer_feedback.py,sha256=bw8MfEOKbGgn4FOyvcADrcs9GhcpNXNTgxKjBjIzywE,899
|
12
|
-
freeplay/resources/prompts.py,sha256=
|
12
|
+
freeplay/resources/prompts.py,sha256=poLt48UG_3q6qDMvMqk0x6Y4QM66Mt6LyASpfcG0jwo,22843
|
13
13
|
freeplay/resources/recordings.py,sha256=z2ARII1jCnmNh1GU3hGnXZUz5IF_KhyayQum71k-h9c,9213
|
14
14
|
freeplay/resources/sessions.py,sha256=J5A3CjiV2MFqQyxN3TWTvJaa9jmMza58mRFRq2v9iAk,3746
|
15
15
|
freeplay/resources/test_cases.py,sha256=nXL_976RwSJDT6OWDM4GEzbcOzcGkJ9ulvb0XOzCRDM,2240
|
16
16
|
freeplay/resources/test_runs.py,sha256=Tp2N-odInT5XEEWrEsVhdgfnsclOE8n92_C8gTwO2MI,2623
|
17
|
-
freeplay/support.py,sha256=
|
17
|
+
freeplay/support.py,sha256=kQMItnMGZT5TOdPQsSiKOlBbBqO4AyR91vito6wt4JM,12275
|
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.20.dist-info/LICENSE,sha256=_jzIw45hB1XHGxiQ8leZ0GH_X7bR_a8qgxaqnHbCUOo,1064
|
20
|
+
freeplay-0.3.20.dist-info/METADATA,sha256=3mkuwNZ5k_CGH3wtcIOCrI5lDPL2meBLE4_fqQW7vOc,1654
|
21
|
+
freeplay-0.3.20.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
22
|
+
freeplay-0.3.20.dist-info/entry_points.txt,sha256=32s3rf2UUCqiJT4jnClEXZhdXlvl30uwpcxz-Gsy4UU,54
|
23
|
+
freeplay-0.3.20.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|