freeplay 0.4.1__py3-none-any.whl → 0.5.0a2__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.
@@ -8,7 +8,6 @@ from typing import (
8
8
  Any,
9
9
  Dict,
10
10
  List,
11
- Literal,
12
11
  Optional,
13
12
  Protocol,
14
13
  Sequence,
@@ -56,7 +55,12 @@ logger = logging.getLogger(__name__)
56
55
  class UnsupportedToolSchemaError(FreeplayConfigurationError):
57
56
  def __init__(self) -> None:
58
57
  super().__init__(
59
- f'Tool schema not supported for this model and provider.'
58
+ 'Tool schema not supported for this model and provider.'
59
+ )
60
+ class VertexAIToolSchemaError(FreeplayConfigurationError):
61
+ def __init__(self) -> None:
62
+ super().__init__(
63
+ 'Vertex AI SDK not found. Install google-cloud-aiplatform to get proper Tool objects.'
60
64
  )
61
65
 
62
66
 
@@ -100,8 +104,6 @@ class PromptInfo:
100
104
  provider: str
101
105
  model: str
102
106
  flavor_name: str
103
- project_id: str
104
-
105
107
 
106
108
  class FormattedPrompt:
107
109
  def __init__(
@@ -187,6 +189,21 @@ class BoundPrompt:
187
189
  for tool_schema in tool_schema
188
190
  ]
189
191
  }
192
+ elif flavor_name == "gemini_chat":
193
+ try:
194
+ from vertexai.generative_models import Tool, FunctionDeclaration # type: ignore[import-untyped]
195
+
196
+ function_declarations = [
197
+ FunctionDeclaration(
198
+ name=tool_schema.name,
199
+ description=tool_schema.description,
200
+ parameters=tool_schema.parameters
201
+ )
202
+ for tool_schema in tool_schema
203
+ ]
204
+ return [Tool(function_declarations=function_declarations)]
205
+ except ImportError:
206
+ raise VertexAIToolSchemaError()
190
207
 
191
208
  raise UnsupportedToolSchemaError()
192
209
 
@@ -540,7 +557,6 @@ class Prompts:
540
557
  model=model,
541
558
  flavor_name=prompt.metadata.flavor,
542
559
  provider_info=prompt.metadata.provider_info,
543
- project_id=prompt.project_id
544
560
  )
545
561
 
546
562
  return TemplatePrompt(prompt_info, prompt.content, prompt.tool_schema)
@@ -576,7 +592,6 @@ class Prompts:
576
592
  model=model,
577
593
  flavor_name=prompt.metadata.flavor,
578
594
  provider_info=prompt.metadata.provider_info,
579
- project_id=prompt.project_id
580
595
  )
581
596
 
582
597
  return TemplatePrompt(prompt_info, prompt.content, prompt.tool_schema)
@@ -1,8 +1,8 @@
1
1
  import json
2
2
  import logging
3
- from dataclasses import dataclass
3
+ from dataclasses import dataclass, field
4
4
  from typing import Any, Dict, List, Literal, Optional, Union
5
- from uuid import UUID
5
+ from uuid import UUID, uuid4
6
6
 
7
7
  from requests import HTTPError
8
8
 
@@ -22,6 +22,7 @@ from freeplay.resources.prompts import (
22
22
  )
23
23
  from freeplay.resources.sessions import SessionInfo, TraceInfo
24
24
  from freeplay.support import CallSupport
25
+ from freeplay.utils import convert_provider_message_to_dict
25
26
 
26
27
  logger = logging.getLogger(__name__)
27
28
 
@@ -37,11 +38,11 @@ ApiStyle = Union[Literal['batch'], Literal['default']]
37
38
 
38
39
  @dataclass
39
40
  class CallInfo:
40
- provider: str
41
- model: str
42
- start_time: float
43
- end_time: float
44
- model_parameters: LLMParameters
41
+ provider: Optional[str] = None
42
+ model: Optional[str] = None
43
+ start_time: Optional[float] = None
44
+ end_time: Optional[float] = None
45
+ model_parameters: Optional[LLMParameters] = None
45
46
  provider_info: Optional[Dict[str, Any]] = None
46
47
  usage: Optional[UsageTokens] = None
47
48
  api_style: Optional[ApiStyle] = None
@@ -77,12 +78,15 @@ class ResponseInfo:
77
78
 
78
79
  @dataclass
79
80
  class RecordPayload:
81
+ project_id: str
80
82
  all_messages: List[Dict[str, Any]]
81
- inputs: InputVariables
82
83
 
83
- session_info: SessionInfo
84
- prompt_info: PromptInfo
85
- call_info: CallInfo
84
+ session_info: SessionInfo = field(
85
+ default_factory=lambda: SessionInfo(session_id=str(uuid4()), custom_metadata=None)
86
+ )
87
+ inputs: Optional[InputVariables] = None
88
+ prompt_info: Optional[PromptInfo] = None
89
+ call_info: Optional[CallInfo] = None
86
90
  media_inputs: Optional[MediaInputMap] = None
87
91
  tool_schema: Optional[List[Dict[str, Any]]] = None
88
92
  response_info: Optional[ResponseInfo] = None
@@ -126,25 +130,34 @@ class Recordings:
126
130
  if len(record_payload.all_messages) < 1:
127
131
  raise FreeplayClientError("Messages list must have at least one message. "
128
132
  "The last message should be the current response.")
133
+
134
+ if record_payload.tool_schema is not None:
135
+ record_payload.tool_schema = [convert_provider_message_to_dict(tool) for tool in record_payload.tool_schema]
129
136
 
130
137
  record_api_payload: Dict[str, Any] = {
131
138
  "messages": record_payload.all_messages,
132
139
  "inputs": record_payload.inputs,
133
140
  "tool_schema": record_payload.tool_schema,
134
141
  "session_info": {"custom_metadata": record_payload.session_info.custom_metadata},
135
- "prompt_info": {
142
+
143
+ }
144
+
145
+ if record_payload.prompt_info is not None:
146
+ record_api_payload["prompt_info"] = {
136
147
  "environment": record_payload.prompt_info.environment,
137
148
  "prompt_template_version_id": record_payload.prompt_info.prompt_template_version_id,
138
- },
139
- "call_info": {
149
+ }
150
+
151
+ if record_payload.call_info is not None:
152
+ record_api_payload["call_info"] = {
140
153
  "start_time": record_payload.call_info.start_time,
141
154
  "end_time": record_payload.call_info.end_time,
142
155
  "model": record_payload.call_info.model,
143
156
  "provider": record_payload.call_info.provider,
144
157
  "provider_info": record_payload.call_info.provider_info,
145
158
  "llm_parameters": record_payload.call_info.model_parameters,
159
+ "api_style": record_payload.call_info.api_style,
146
160
  }
147
- }
148
161
 
149
162
  if record_payload.completion_id is not None:
150
163
  record_api_payload['completion_id'] = str(record_payload.completion_id)
@@ -175,15 +188,12 @@ class Recordings:
175
188
  "trace_id": record_payload.trace_info.trace_id
176
189
  }
177
190
 
178
- if record_payload.call_info.usage is not None:
191
+ if record_payload.call_info is not None and record_payload.call_info.usage is not None:
179
192
  record_api_payload['call_info']['usage'] = {
180
193
  "prompt_tokens": record_payload.call_info.usage.prompt_tokens,
181
194
  "completion_tokens": record_payload.call_info.usage.completion_tokens,
182
195
  }
183
196
 
184
- if record_payload.call_info.api_style is not None:
185
- record_api_payload['call_info']['api_style'] = record_payload.call_info.api_style
186
-
187
197
  if record_payload.media_inputs is not None:
188
198
  record_api_payload['media_inputs'] = {
189
199
  name: media_inputs_to_json(media_input)
@@ -193,7 +203,7 @@ class Recordings:
193
203
  try:
194
204
  recorded_response = api_support.post_raw(
195
205
  api_key=self.call_support.freeplay_api_key,
196
- url=f'{self.call_support.api_base}/v2/projects/{record_payload.prompt_info.project_id}/sessions/{record_payload.session_info.session_id}/completions',
206
+ url=f'{self.call_support.api_base}/v2/projects/{record_payload.project_id}/sessions/{record_payload.session_info.session_id}/completions',
197
207
  payload=record_api_payload
198
208
  )
199
209
  recorded_response.raise_for_status()
freeplay/utils.py CHANGED
@@ -75,7 +75,10 @@ def get_user_agent() -> str:
75
75
  # Recursively convert Pydantic models, lists, and dicts to dict compatible format -- used to allow us to accept
76
76
  # provider message shapes (usually generated types) or the default {'content': ..., 'role': ...} shape.
77
77
  def convert_provider_message_to_dict(obj: Any) -> Any:
78
- if hasattr(obj, 'model_dump'):
78
+ if hasattr(obj, 'to_dict') and callable(getattr(obj, 'to_dict')):
79
+ # Vertex AI has a to_dict method
80
+ return obj.to_dict()
81
+ elif hasattr(obj, 'model_dump'):
79
82
  # Pydantic v2
80
83
  return obj.model_dump(mode='json')
81
84
  elif hasattr(obj, 'dict'):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: freeplay
3
- Version: 0.4.1
3
+ Version: 0.5.0a2
4
4
  Summary:
5
5
  License: MIT
6
6
  Author: FreePlay Engineering
@@ -9,15 +9,15 @@ 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=6AUgHyOcXIpHvrxGAhsQgmDERvRHKutB6J-GkhkGH6s,928
12
- freeplay/resources/prompts.py,sha256=83OPxdyCodxLSIhxL8MVEjlKsT6eHwnn_2DErMXyi5A,23299
13
- freeplay/resources/recordings.py,sha256=pzX7SeEipAMSeiC8RoNekTpMep4APBaoveAh8OCmUlU,9190
12
+ freeplay/resources/prompts.py,sha256=pkZa_b3HSrZoPqhcKCXsb26w2In-ETKydclbkXU_hus,24093
13
+ freeplay/resources/recordings.py,sha256=OOSgSkQO7CVnOA2y7eSl5B2eMHZv5E3_-3J2XILwKUo,9811
14
14
  freeplay/resources/sessions.py,sha256=dZtd9nq2nH8pmXxQOJitBnN5Jl3kjggDItDcjC69TYo,3883
15
15
  freeplay/resources/test_cases.py,sha256=nXL_976RwSJDT6OWDM4GEzbcOzcGkJ9ulvb0XOzCRDM,2240
16
16
  freeplay/resources/test_runs.py,sha256=IkqW2LrVrLzFcGtalwP4FV-DeQKKb6Nekvy02FfoH8k,5007
17
17
  freeplay/support.py,sha256=9X-utKyM9BkhCLJbPT184ud26Dc69f3DiHjyN8qq0vQ,15266
18
- freeplay/utils.py,sha256=Xvt4mNLXLL7E6MI2hTuDLV5cl5Y83DgdjCZSyDGMjR0,3187
19
- freeplay-0.4.1.dist-info/LICENSE,sha256=_jzIw45hB1XHGxiQ8leZ0GH_X7bR_a8qgxaqnHbCUOo,1064
20
- freeplay-0.4.1.dist-info/METADATA,sha256=BqYvmeKI3Ae6rXuOqvx1Y2GNqOI3JV38BdyR4pG2U-8,1660
21
- freeplay-0.4.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
22
- freeplay-0.4.1.dist-info/entry_points.txt,sha256=32s3rf2UUCqiJT4jnClEXZhdXlvl30uwpcxz-Gsy4UU,54
23
- freeplay-0.4.1.dist-info/RECORD,,
18
+ freeplay/utils.py,sha256=5mNC3NTHDlzltyUDF8q2wNddgGy6-MhI8ldnRvtAl7U,3329
19
+ freeplay-0.5.0a2.dist-info/LICENSE,sha256=_jzIw45hB1XHGxiQ8leZ0GH_X7bR_a8qgxaqnHbCUOo,1064
20
+ freeplay-0.5.0a2.dist-info/METADATA,sha256=pzFZ1UFoEM-rCaL11UHjH_pMjYg20tRGog0zptc5cnQ,1662
21
+ freeplay-0.5.0a2.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
22
+ freeplay-0.5.0a2.dist-info/entry_points.txt,sha256=32s3rf2UUCqiJT4jnClEXZhdXlvl30uwpcxz-Gsy4UU,54
23
+ freeplay-0.5.0a2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.3
2
+ Generator: poetry-core 2.1.2
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any