fairo 25.7.1__tar.gz → 25.7.2__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 (49) hide show
  1. {fairo-25.7.1 → fairo-25.7.2}/PKG-INFO +1 -1
  2. fairo-25.7.2/fairo/__init__.py +1 -0
  3. fairo-25.7.2/fairo/core/chat/chat.py +227 -0
  4. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/workflow/utils.py +2 -15
  5. {fairo-25.7.1 → fairo-25.7.2}/fairo.egg-info/PKG-INFO +1 -1
  6. fairo-25.7.1/fairo/__init__.py +0 -1
  7. fairo-25.7.1/fairo/core/chat/chat.py +0 -54
  8. {fairo-25.7.1 → fairo-25.7.2}/README.md +0 -0
  9. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/__init__.py +0 -0
  10. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/__init__.py +0 -0
  11. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/base_agent.py +0 -0
  12. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/code_analysis_agent.py +0 -0
  13. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/output/__init__.py +0 -0
  14. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/output/base_output.py +0 -0
  15. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/output/google_drive.py +0 -0
  16. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/tools/__init__.py +0 -0
  17. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/tools/base_tools.py +0 -0
  18. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/tools/code_analysis.py +0 -0
  19. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/tools/utils.py +0 -0
  20. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/utils.py +0 -0
  21. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/chat/__init__.py +0 -0
  22. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/client/__init__.py +0 -0
  23. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/client/client.py +0 -0
  24. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/exceptions.py +0 -0
  25. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/execution/__init__.py +0 -0
  26. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/execution/agent_serializer.py +0 -0
  27. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/execution/env_finder.py +0 -0
  28. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/execution/executor.py +0 -0
  29. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/execution/model_log_helper.py +0 -0
  30. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/models/__init__.py +0 -0
  31. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/models/custom_field_value.py +0 -0
  32. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/models/resources.py +0 -0
  33. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/runnable/__init__.py +0 -0
  34. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/runnable/runnable.py +0 -0
  35. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/workflow/__init__.py +0 -0
  36. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/workflow/base_workflow.py +0 -0
  37. {fairo-25.7.1 → fairo-25.7.2}/fairo/core/workflow/dependency.py +0 -0
  38. {fairo-25.7.1 → fairo-25.7.2}/fairo/metrics/__init__.py +0 -0
  39. {fairo-25.7.1 → fairo-25.7.2}/fairo/metrics/fairness_object.py +0 -0
  40. {fairo-25.7.1 → fairo-25.7.2}/fairo/metrics/metrics.py +0 -0
  41. {fairo-25.7.1 → fairo-25.7.2}/fairo/settings.py +0 -0
  42. {fairo-25.7.1 → fairo-25.7.2}/fairo/tests/__init__.py +0 -0
  43. {fairo-25.7.1 → fairo-25.7.2}/fairo/tests/test_metrics.py +0 -0
  44. {fairo-25.7.1 → fairo-25.7.2}/fairo.egg-info/SOURCES.txt +0 -0
  45. {fairo-25.7.1 → fairo-25.7.2}/fairo.egg-info/dependency_links.txt +0 -0
  46. {fairo-25.7.1 → fairo-25.7.2}/fairo.egg-info/requires.txt +0 -0
  47. {fairo-25.7.1 → fairo-25.7.2}/fairo.egg-info/top_level.txt +0 -0
  48. {fairo-25.7.1 → fairo-25.7.2}/pyproject.toml +0 -0
  49. {fairo-25.7.1 → fairo-25.7.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fairo
3
- Version: 25.7.1
3
+ Version: 25.7.2
4
4
  Summary: SDK for interfacing with Fairo SaaS platform.
5
5
  Author-email: "Fairo Systems, Inc." <support@fairo.ai>
6
6
  License: Apache-2.0
@@ -0,0 +1 @@
1
+ __version__ = "25.7.2"
@@ -0,0 +1,227 @@
1
+
2
+ from langchain_community.chat_models.mlflow import ChatMlflow
3
+ from mlflow.deployments import get_deploy_client
4
+ from mlflow.deployments.base import BaseDeploymentClient
5
+ from fairo.settings import get_mlflow_gateway_chat_route, get_mlflow_gateway_uri, get_mlflow_user, get_mlflow_password
6
+ import requests
7
+ from requests.auth import HTTPBasicAuth
8
+ import json
9
+ import os
10
+
11
+ class FairoDeploymentClient(BaseDeploymentClient):
12
+ """Custom deployment client that implements predict_stream for Fairo endpoints."""
13
+
14
+ def __init__(self, target_uri: str, endpoint: str):
15
+ self.target_uri = target_uri
16
+ self.endpoint = endpoint
17
+
18
+ def predict_stream(self, deployment_name=None, inputs=None, endpoint=None):
19
+ """
20
+ Implement streaming predictions by making HTTP requests to the Fairo gateway.
21
+ """
22
+ endpoint = endpoint or self.endpoint
23
+
24
+ # Use the gateway URL to make streaming requests
25
+ gateway_url = f"{self.target_uri.rstrip('/')}/gateway/{endpoint}/invocations"
26
+
27
+ headers = {
28
+ 'Content-Type': 'application/json',
29
+ 'Accept': 'text/event-stream'
30
+ }
31
+
32
+ # Add authentication if needed
33
+ auth = None
34
+ if os.environ.get('MLFLOW_TRACKING_USERNAME') and os.environ.get('MLFLOW_TRACKING_PASSWORD'):
35
+ auth = HTTPBasicAuth(
36
+ os.environ.get('MLFLOW_TRACKING_USERNAME'),
37
+ os.environ.get('MLFLOW_TRACKING_PASSWORD')
38
+ )
39
+
40
+ # Make streaming request
41
+ try:
42
+ response = requests.post(
43
+ gateway_url,
44
+ json={**inputs, "stream": True},
45
+ headers=headers,
46
+ auth=auth,
47
+ )
48
+
49
+ if response.status_code != 200:
50
+ error_text = response.text
51
+ raise Exception(f"HTTP {response.status_code}: {error_text}")
52
+
53
+ # Check if response is actually streaming
54
+ content_type = response.headers.get('content-type', '')
55
+
56
+ chunk_count = 0
57
+
58
+ # Parse streaming response
59
+ for line in response.iter_lines():
60
+ if line:
61
+ line = line.decode('utf-8')
62
+
63
+ # Handle different streaming formats
64
+ if line.startswith('data: '):
65
+ try:
66
+ data_str = line[6:] # Remove 'data: ' prefix
67
+ if data_str.strip() == '[DONE]':
68
+ break
69
+ data = json.loads(data_str)
70
+ chunk_count += 1
71
+ yield data
72
+ except json.JSONDecodeError as e:
73
+ continue
74
+ else:
75
+ # Try parsing as direct JSON
76
+ try:
77
+ data = json.loads(line)
78
+ chunk_count += 1
79
+ yield data
80
+ except json.JSONDecodeError:
81
+ continue
82
+
83
+
84
+ # If no chunks were yielded, fall back to non-streaming
85
+ if chunk_count == 0:
86
+ # Try to get the full response as JSON
87
+ try:
88
+ if hasattr(response, 'json'):
89
+ result = response.json()
90
+ yield result
91
+ except:
92
+ # Create a minimal response to avoid the error
93
+ yield {
94
+ "choices": [{
95
+ "delta": {"content": "", "role": "assistant"},
96
+ "finish_reason": "stop"
97
+ }]
98
+ }
99
+
100
+ except requests.exceptions.RequestException as e:
101
+ raise Exception(f"Request failed: {e}")
102
+
103
+ def predict(self, deployment_name=None, inputs=None, endpoint=None):
104
+ """
105
+ Implement synchronous predictions by making HTTP requests to the Fairo gateway.
106
+ """
107
+ endpoint = endpoint or self.endpoint
108
+
109
+ # Use the gateway URL to make requests
110
+ gateway_url = f"{self.target_uri.rstrip('/')}/gateway/{endpoint}/invocations"
111
+
112
+ headers = {
113
+ 'Content-Type': 'application/json',
114
+ 'Accept': 'application/json'
115
+ }
116
+
117
+ # Add authentication if needed
118
+ auth = None
119
+ if os.environ.get('MLFLOW_TRACKING_USERNAME') and os.environ.get('MLFLOW_TRACKING_PASSWORD'):
120
+ auth = HTTPBasicAuth(
121
+ os.environ.get('MLFLOW_TRACKING_USERNAME'),
122
+ os.environ.get('MLFLOW_TRACKING_PASSWORD')
123
+ )
124
+
125
+ # Make request
126
+ response = requests.post(
127
+ gateway_url,
128
+ json=inputs,
129
+ headers=headers,
130
+ auth=auth
131
+ )
132
+
133
+ if response.status_code != 200:
134
+ raise Exception(f"HTTP {response.status_code}: {response.text}")
135
+
136
+ return response.json()
137
+
138
+ def get_deployment(self, name, endpoint=None):
139
+ """Get deployment information."""
140
+ raise NotImplementedError("get_deployment not implemented")
141
+
142
+ def list_deployments(self, endpoint=None):
143
+ """List available deployments."""
144
+ raise NotImplementedError("list_deployments not implemented")
145
+
146
+ def get_endpoint(self, endpoint):
147
+ """Get endpoint information."""
148
+ raise NotImplementedError("get_endpoint not implemented")
149
+
150
+ def list_endpoints(self):
151
+ """List available endpoints."""
152
+ raise NotImplementedError("list_endpoints not implemented")
153
+
154
+ def create_deployment(self, name, config, endpoint=None):
155
+ """Create a new deployment."""
156
+ raise NotImplementedError("create_deployment not implemented")
157
+
158
+ def update_deployment(self, name, config, endpoint=None):
159
+ """Update an existing deployment."""
160
+ raise NotImplementedError("update_deployment not implemented")
161
+
162
+ def delete_deployment(self, name, endpoint=None):
163
+ """Delete a deployment."""
164
+ raise NotImplementedError("delete_deployment not implemented")
165
+
166
+ def create_endpoint(self, name, config):
167
+ """Create a new endpoint."""
168
+ raise NotImplementedError("create_endpoint not implemented")
169
+
170
+ def update_endpoint(self, name, config):
171
+ """Update an existing endpoint."""
172
+ raise NotImplementedError("update_endpoint not implemented")
173
+
174
+ def delete_endpoint(self, name):
175
+ """Delete an endpoint."""
176
+ raise NotImplementedError("delete_endpoint not implemented")
177
+
178
+
179
+ class ChatFairo(ChatMlflow):
180
+
181
+ def __init__(self, **kwargs):
182
+
183
+ # # TODO <- see if this can be improved
184
+ # os.environ["MLFLOW_TRACKING_USERNAME"] = get_mlflow_user()
185
+ # os.environ["MLFLOW_TRACKING_PASSWORD"] = get_mlflow_password()
186
+
187
+ super().__init__(
188
+ target_uri=os.environ.get('MLFLOW_GATEWAY_URI', get_mlflow_gateway_uri()),
189
+ endpoint=os.environ.get('MLFLOW_GATEWAY_ROUTE', get_mlflow_gateway_chat_route()),
190
+ **kwargs
191
+ )
192
+
193
+ self._client = FairoDeploymentClient(self.target_uri, self.endpoint)
194
+
195
+ @property
196
+ def _target_uri(self):
197
+ return os.environ.get("MLFLOW_GATEWAY_URI", None)
198
+
199
+ @property
200
+ def _endpoint(self):
201
+ return os.environ.get("MLFLOW_GATEWAY_ROUTE", None)
202
+
203
+ def invoke(self, *args, **kwargs):
204
+ # Override invoke to use dynamic target_uri
205
+ self.target_uri = self._target_uri
206
+ self._client = FairoDeploymentClient(self.target_uri, self.endpoint)
207
+ return super().invoke(*args, **kwargs)
208
+
209
+
210
+ class FairoChat(ChatMlflow):
211
+ def __init__(self, endpoint, **kwargs):
212
+ super().__init__(
213
+ target_uri=os.environ.get('MLFLOW_GATEWAY_URI', None),
214
+ endpoint=endpoint,
215
+ # extra_params={"workflow_run_id": workflow_run_id},
216
+ **kwargs
217
+ )
218
+
219
+ @property
220
+ def _target_uri(self):
221
+ return os.environ.get("MLFLOW_GATEWAY_URI", None)
222
+
223
+ def invoke(self, *args, **kwargs):
224
+ # Override invoke to use dynamic target_uri
225
+ self.target_uri = self._target_uri
226
+ self._client = get_deploy_client(self.target_uri)
227
+ return super().invoke(*args, **kwargs)
@@ -1,7 +1,6 @@
1
1
 
2
2
  from typing import List
3
3
  from fairo.core.agent.base_agent import SimpleAgent
4
- from fairo.core.workflow.dependency import FairoVectorStore, PostgresVectorStore
5
4
 
6
5
 
7
6
  def output_workflow_tools(agents):
@@ -230,13 +229,7 @@ def output_langchain_process_graph(agents):
230
229
  if fn and fn.__closure__:
231
230
  for cell in fn.__closure__:
232
231
  val = cell.cell_contents
233
- if (
234
- (
235
- FairoVectorStore and isinstance(val, FairoVectorStore)
236
- ) or (
237
- PostgresVectorStore and isinstance(val, PostgresVectorStore)
238
- )
239
- ) and val.collection_name not in seen_collections:
232
+ if type(val).__name__ in ("FairoVectorStore", "PostgresVectorStore") and val.collection_name not in seen_collections:
240
233
  vector_stores.append(val)
241
234
  seen_collections.add(val.collection_name)
242
235
 
@@ -266,13 +259,7 @@ def output_langchain_process_graph(agents):
266
259
  if fn and fn.__closure__:
267
260
  for cell in fn.__closure__:
268
261
  val = cell.cell_contents
269
- if (
270
- (
271
- FairoVectorStore and isinstance(val, FairoVectorStore)
272
- ) or (
273
- PostgresVectorStore and isinstance(val, PostgresVectorStore)
274
- )
275
- ) and val.collection_name in dependency_map:
262
+ if type(val).__name__ in ("FairoVectorStore", "PostgresVectorStore") and val.collection_name in dependency_map:
276
263
  num = dependency_map[val.collection_name]
277
264
  if num not in agent_deps:
278
265
  agent_deps.append(num)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fairo
3
- Version: 25.7.1
3
+ Version: 25.7.2
4
4
  Summary: SDK for interfacing with Fairo SaaS platform.
5
5
  Author-email: "Fairo Systems, Inc." <support@fairo.ai>
6
6
  License: Apache-2.0
@@ -1 +0,0 @@
1
- __version__ = "25.7.1"
@@ -1,54 +0,0 @@
1
-
2
- from langchain_community.chat_models.mlflow import ChatMlflow
3
- from mlflow.deployments import get_deploy_client
4
- from fairo.settings import get_mlflow_gateway_chat_route, get_mlflow_gateway_uri, get_mlflow_user, get_mlflow_password
5
- import os
6
-
7
-
8
- class ChatFairo(ChatMlflow):
9
-
10
- def __init__(self, **kwargs):
11
-
12
- # # TODO <- see if this can be improved
13
- # os.environ["MLFLOW_TRACKING_USERNAME"] = get_mlflow_user()
14
- # os.environ["MLFLOW_TRACKING_PASSWORD"] = get_mlflow_password()
15
-
16
- super().__init__(
17
- target_uri=os.environ.get('MLFLOW_GATEWAY_URI', get_mlflow_gateway_uri()),
18
- endpoint=os.environ.get('MLFLOW_GATEWAY_ROUTE', get_mlflow_gateway_chat_route()),
19
- **kwargs
20
- )
21
-
22
- @property
23
- def _target_uri(self):
24
- return os.environ.get("MLFLOW_GATEWAY_URI", None)
25
-
26
- @property
27
- def _endpoint(self):
28
- return os.environ.get("MLFLOW_GATEWAY_ROUTE", None)
29
-
30
- def invoke(self, *args, **kwargs):
31
- # Override invoke to use dynamic target_uri
32
- self.target_uri = self._target_uri
33
- self._client = get_deploy_client(self.target_uri)
34
- return super().invoke(*args, **kwargs)
35
-
36
-
37
- class FairoChat(ChatMlflow):
38
- def __init__(self, endpoint, **kwargs):
39
- super().__init__(
40
- target_uri=os.environ.get('MLFLOW_GATEWAY_URI', None),
41
- endpoint=endpoint,
42
- # extra_params={"workflow_run_id": workflow_run_id},
43
- **kwargs
44
- )
45
-
46
- @property
47
- def _target_uri(self):
48
- return os.environ.get("MLFLOW_GATEWAY_URI", None)
49
-
50
- def invoke(self, *args, **kwargs):
51
- # Override invoke to use dynamic target_uri
52
- self.target_uri = self._target_uri
53
- self._client = get_deploy_client(self.target_uri)
54
- return super().invoke(*args, **kwargs)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes