freeplay 0.5.0a1__tar.gz → 0.5.0a3__tar.gz

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.
Files changed (22) hide show
  1. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/PKG-INFO +1 -1
  2. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/pyproject.toml +4 -3
  3. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/resources/prompts.py +21 -2
  4. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/resources/recordings.py +4 -0
  5. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/utils.py +42 -1
  6. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/LICENSE +0 -0
  7. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/README.md +0 -0
  8. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/__init__.py +0 -0
  9. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/api_support.py +0 -0
  10. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/errors.py +0 -0
  11. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/freeplay.py +0 -0
  12. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/freeplay_cli.py +0 -0
  13. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/llm_parameters.py +0 -0
  14. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/model.py +0 -0
  15. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/py.typed +0 -0
  16. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/resources/__init__.py +0 -0
  17. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/resources/adapters.py +0 -0
  18. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/resources/customer_feedback.py +0 -0
  19. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/resources/sessions.py +0 -0
  20. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/resources/test_cases.py +0 -0
  21. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/resources/test_runs.py +0 -0
  22. {freeplay-0.5.0a1 → freeplay-0.5.0a3}/src/freeplay/support.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: freeplay
3
- Version: 0.5.0a1
3
+ Version: 0.5.0a3
4
4
  Summary:
5
5
  License: MIT
6
6
  Author: FreePlay Engineering
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "freeplay"
3
- version = "0.5.0a1"
3
+ version = "0.5.0a3"
4
4
  description = ""
5
5
  authors = ["FreePlay Engineering <engineering@freeplay.ai>"]
6
6
  license = "MIT"
@@ -17,9 +17,10 @@ pystache = "^0.6.5"
17
17
  mypy = "^1"
18
18
  types-requests = "^2.31"
19
19
  anthropic = { extras = ["bedrock"], version = "^0.39.0" }
20
- openai = "^1"
20
+ openai = "1.98.0"
21
21
  boto3 = "^1.34.97"
22
- google-cloud-aiplatform = "1.51.0"
22
+ google-cloud-aiplatform = "^1.71.0"
23
+ vertexai = "^1.71.1"
23
24
  httpx = "0.27.2"
24
25
 
25
26
  [tool.poetry.group.test.dependencies]
@@ -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
 
@@ -185,6 +189,21 @@ class BoundPrompt:
185
189
  for tool_schema in tool_schema
186
190
  ]
187
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()
188
207
 
189
208
  raise UnsupportedToolSchemaError()
190
209
 
@@ -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
 
@@ -129,6 +130,9 @@ class Recordings:
129
130
  if len(record_payload.all_messages) < 1:
130
131
  raise FreeplayClientError("Messages list must have at least one message. "
131
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]
132
136
 
133
137
  record_api_payload: Dict[str, Any] = {
134
138
  "messages": record_payload.all_messages,
@@ -75,14 +75,55 @@ 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
+ """
79
+ Convert provider message objects to dictionaries.
80
+ For Vertex AI objects, automatically converts to camelCase.
81
+ """
82
+ # List of possible raw attribute names in Vertex AI objects
83
+ vertex_raw_attrs = [
84
+ '_raw_content', # For Content objects
85
+ '_raw_tool', # For Tool objects
86
+ '_raw_message', # For message objects
87
+ '_raw_candidate', # For Candidate objects
88
+ '_raw_response', # For response objects
89
+ '_raw_function_declaration', # For FunctionDeclaration
90
+ '_raw_generation_config', # For GenerationConfig
91
+ '_pb', # Generic protobuf attribute
92
+ ]
93
+
94
+ # Check for Vertex AI objects with raw protobuf attributes
95
+ for attr_name in vertex_raw_attrs:
96
+ if hasattr(obj, attr_name):
97
+ raw_obj = getattr(obj, attr_name)
98
+ if raw_obj is not None:
99
+ try:
100
+ # Use the metaclass to_dict with camelCase conversion
101
+ return type(raw_obj).to_dict(
102
+ raw_obj,
103
+ preserving_proto_field_name=False, # camelCase
104
+ use_integers_for_enums=False, # Keep as strings (we'll lowercase them)
105
+ including_default_value_fields=False # Exclude defaults
106
+ )
107
+ except: # noqa: E722
108
+ # If we can't convert, continue to the next attribute
109
+ pass
110
+
111
+ # For non-Vertex AI objects, use their standard to_dict methods
112
+ if hasattr(obj, 'to_dict') and callable(getattr(obj, 'to_dict')):
113
+ # Regular to_dict (for Vertex AI wrappers without _raw_* attributes)
114
+ return obj.to_dict()
115
+ elif hasattr(obj, 'model_dump'):
79
116
  # Pydantic v2
80
117
  return obj.model_dump(mode='json')
81
118
  elif hasattr(obj, 'dict'):
82
119
  # Pydantic v1
83
120
  return obj.dict(encode_json=True)
84
121
  elif isinstance(obj, dict):
122
+ # Handle dictionaries recursively
85
123
  return {k: convert_provider_message_to_dict(v) for k, v in obj.items()}
86
124
  elif isinstance(obj, list):
125
+ # Handle lists recursively
87
126
  return [convert_provider_message_to_dict(item) for item in obj]
127
+
128
+ # Return as-is for primitive types
88
129
  return obj
File without changes
File without changes