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.
- {fairo-25.7.1 → fairo-25.7.2}/PKG-INFO +1 -1
- fairo-25.7.2/fairo/__init__.py +1 -0
- fairo-25.7.2/fairo/core/chat/chat.py +227 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/workflow/utils.py +2 -15
- {fairo-25.7.1 → fairo-25.7.2}/fairo.egg-info/PKG-INFO +1 -1
- fairo-25.7.1/fairo/__init__.py +0 -1
- fairo-25.7.1/fairo/core/chat/chat.py +0 -54
- {fairo-25.7.1 → fairo-25.7.2}/README.md +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/__init__.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/__init__.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/base_agent.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/code_analysis_agent.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/output/__init__.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/output/base_output.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/output/google_drive.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/tools/__init__.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/tools/base_tools.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/tools/code_analysis.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/tools/utils.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/agent/utils.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/chat/__init__.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/client/__init__.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/client/client.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/exceptions.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/execution/__init__.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/execution/agent_serializer.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/execution/env_finder.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/execution/executor.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/execution/model_log_helper.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/models/__init__.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/models/custom_field_value.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/models/resources.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/runnable/__init__.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/runnable/runnable.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/workflow/__init__.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/workflow/base_workflow.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/core/workflow/dependency.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/metrics/__init__.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/metrics/fairness_object.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/metrics/metrics.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/settings.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/tests/__init__.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo/tests/test_metrics.py +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo.egg-info/SOURCES.txt +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo.egg-info/dependency_links.txt +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo.egg-info/requires.txt +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/fairo.egg-info/top_level.txt +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/pyproject.toml +0 -0
- {fairo-25.7.1 → fairo-25.7.2}/setup.cfg +0 -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)
|
fairo-25.7.1/fairo/__init__.py
DELETED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|