freeplay 0.3.8__tar.gz → 0.3.9__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: freeplay
3
- Version: 0.3.8
3
+ Version: 0.3.9
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.3.8"
3
+ version = "0.3.9"
4
4
  description = ""
5
5
  authors = ["FreePlay Engineering <engineering@freeplay.ai>"]
6
6
  license = "MIT"
@@ -4,9 +4,7 @@ from abc import ABC, abstractmethod
4
4
  from dataclasses import asdict, dataclass
5
5
  import logging
6
6
  from pathlib import Path
7
- from typing import Dict, Optional, List, cast, Any, Union, overload
8
- from anthropic.types.message import Message as AnthropicMessage
9
- from openai.types.chat import ChatCompletionMessage as OpenAIMessage
7
+ from typing import Dict, Optional, List, Protocol, cast, Any, Union, runtime_checkable
10
8
 
11
9
  from freeplay.errors import FreeplayConfigurationError, FreeplayClientError, log_freeplay_client_warning
12
10
  from freeplay.llm_parameters import LLMParameters
@@ -44,6 +42,13 @@ class PromptInfo:
44
42
  flavor_name: str
45
43
  project_id: str
46
44
 
45
+ # Client SDKs (Anthropic and OpenAI) have pydantic types for messages that require strict structures.
46
+ # We want to avoid taking a dependency on the client SDKs, so we instead just ensure they can be converted to a dict,
47
+ # this will ultimately be validated at runtime by the server for any incompatibility.
48
+ @runtime_checkable
49
+ class GenericProviderMessage(Protocol):
50
+ def to_dict(self) -> Dict[str, Any]:
51
+ pass
47
52
 
48
53
  class FormattedPrompt:
49
54
  def __init__(
@@ -54,9 +59,11 @@ class FormattedPrompt:
54
59
  formatted_prompt_text: Optional[str] = None,
55
60
  tool_schema: Optional[List[Dict[str, Any]]] = None
56
61
  ):
62
+ # These two definitions allow us to operate on typed fields unitl we expose them as Any for client use.
63
+ self._llm_prompt = formatted_prompt
64
+ self._tool_schema = tool_schema
65
+
57
66
  self.prompt_info = prompt_info
58
- self.llm_prompt = formatted_prompt
59
- self.tool_schema = tool_schema
60
67
  if formatted_prompt_text:
61
68
  self.llm_prompt_text = formatted_prompt_text
62
69
 
@@ -67,11 +74,21 @@ class FormattedPrompt:
67
74
  # Note: messages are **not formatted** for the provider.
68
75
  self.messages = messages
69
76
 
77
+ @property
78
+ # We know this is a list of dict[str,str], but we use Any to avoid typing issues with client SDK libraries, which require strict TypedDict.
79
+ def llm_prompt(self) -> Any:
80
+ return self._llm_prompt
81
+
82
+ @property
83
+ def tool_schema(self) -> Any:
84
+ return self._tool_schema
85
+
70
86
  def all_messages(
71
87
  self,
72
- new_message: Union[Dict[str, str], AnthropicMessage, OpenAIMessage]
88
+ new_message: Union[Dict[str, str], GenericProviderMessage]
73
89
  ) -> List[Dict[str, Any]]:
74
- if isinstance(new_message, AnthropicMessage) or isinstance(new_message, OpenAIMessage):
90
+ # Check if it's a OpenAI or Anthropic message: if it's a provider message object (has to_dict method)
91
+ if isinstance(new_message, GenericProviderMessage):
75
92
  return self.messages + [new_message.to_dict()]
76
93
  elif isinstance(new_message, dict):
77
94
  return self.messages + [new_message]
File without changes
File without changes
File without changes
File without changes
File without changes