flock-core 0.4.0b20__py3-none-any.whl → 0.4.0b22__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.
Potentially problematic release.
This version of flock-core might be problematic. Click here for more details.
- flock/core/flock.py +7 -20
- flock/core/logging/logging.py +6 -17
- flock/core/mixin/dspy_integration.py +15 -43
- flock/core/serialization/serialization_utils.py +10 -30
- flock/core/util/cli_helper.py +3 -3
- flock/core/util/hydrator.py +8 -24
- flock/evaluators/declarative/declarative_evaluator.py +4 -10
- {flock_core-0.4.0b20.dist-info → flock_core-0.4.0b22.dist-info}/METADATA +1 -1
- {flock_core-0.4.0b20.dist-info → flock_core-0.4.0b22.dist-info}/RECORD +12 -12
- {flock_core-0.4.0b20.dist-info → flock_core-0.4.0b22.dist-info}/WHEEL +0 -0
- {flock_core-0.4.0b20.dist-info → flock_core-0.4.0b22.dist-info}/entry_points.txt +0 -0
- {flock_core-0.4.0b20.dist-info → flock_core-0.4.0b22.dist-info}/licenses/LICENSE +0 -0
flock/core/flock.py
CHANGED
|
@@ -350,13 +350,9 @@ class Flock(BaseModel, Serializable):
|
|
|
350
350
|
try:
|
|
351
351
|
resolved_start_agent = self._agents.get(start_agent_name)
|
|
352
352
|
if not resolved_start_agent:
|
|
353
|
-
resolved_start_agent = FlockRegistry.get_agent(
|
|
354
|
-
start_agent_name
|
|
355
|
-
)
|
|
353
|
+
resolved_start_agent = FlockRegistry.get_agent(start_agent_name)
|
|
356
354
|
if not resolved_start_agent:
|
|
357
|
-
raise ValueError(
|
|
358
|
-
f"Start agent '{start_agent_name}' not found."
|
|
359
|
-
)
|
|
355
|
+
raise ValueError(f"Start agent '{start_agent_name}' not found.")
|
|
360
356
|
self.add_agent(resolved_start_agent)
|
|
361
357
|
|
|
362
358
|
run_context = context if context else FlockContext()
|
|
@@ -388,20 +384,15 @@ class Flock(BaseModel, Serializable):
|
|
|
388
384
|
|
|
389
385
|
# Execute workflow
|
|
390
386
|
if not self.enable_temporal:
|
|
391
|
-
result = await run_local_workflow(
|
|
392
|
-
run_context, box_result=False
|
|
393
|
-
)
|
|
387
|
+
result = await run_local_workflow(run_context, box_result=False)
|
|
394
388
|
else:
|
|
395
|
-
result = await run_temporal_workflow(
|
|
396
|
-
run_context, box_result=False
|
|
397
|
-
)
|
|
389
|
+
result = await run_temporal_workflow(run_context, box_result=False)
|
|
398
390
|
|
|
399
391
|
span.set_attribute("result.type", str(type(result)))
|
|
400
392
|
result_str = str(result)
|
|
401
393
|
span.set_attribute(
|
|
402
394
|
"result.preview",
|
|
403
|
-
result_str[:1000]
|
|
404
|
-
+ ("..." if len(result_str) > 1000 else ""),
|
|
395
|
+
result_str[:1000] + ("..." if len(result_str) > 1000 else ""),
|
|
405
396
|
)
|
|
406
397
|
|
|
407
398
|
if box_result:
|
|
@@ -409,17 +400,13 @@ class Flock(BaseModel, Serializable):
|
|
|
409
400
|
logger.debug("Boxing final result.")
|
|
410
401
|
return Box(result)
|
|
411
402
|
except ImportError:
|
|
412
|
-
logger.warning(
|
|
413
|
-
"Box library not installed, returning raw dict."
|
|
414
|
-
)
|
|
403
|
+
logger.warning("Box library not installed, returning raw dict.")
|
|
415
404
|
return result
|
|
416
405
|
else:
|
|
417
406
|
return result
|
|
418
407
|
|
|
419
408
|
except Exception as e:
|
|
420
|
-
logger.error(
|
|
421
|
-
f"Flock run '{self.name}' failed: {e}", exc_info=True
|
|
422
|
-
)
|
|
409
|
+
logger.error(f"Flock run '{self.name}' failed: {e}", exc_info=True)
|
|
423
410
|
span.record_exception(e)
|
|
424
411
|
span.set_status(trace.Status(trace.StatusCode.ERROR, str(e)))
|
|
425
412
|
return {
|
flock/core/logging/logging.py
CHANGED
|
@@ -144,9 +144,7 @@ def custom_format(record):
|
|
|
144
144
|
level_name = record["level"].name
|
|
145
145
|
category = record["extra"].get("category", "unknown")
|
|
146
146
|
trace_id = record["extra"].get("trace_id", "no-trace")
|
|
147
|
-
color_tag = color_for_category(
|
|
148
|
-
category
|
|
149
|
-
) # Get the color tag name (e.g., "yellow")
|
|
147
|
+
color_tag = color_for_category(category) # Get the color tag name (e.g., "yellow")
|
|
150
148
|
|
|
151
149
|
message = record["message"]
|
|
152
150
|
message = message.replace("{", "{{").replace("}", "}}")
|
|
@@ -155,8 +153,7 @@ def custom_format(record):
|
|
|
155
153
|
if len(message) > MAX_LENGTH:
|
|
156
154
|
truncated_chars = len(message) - MAX_LENGTH
|
|
157
155
|
message = (
|
|
158
|
-
message[:MAX_LENGTH]
|
|
159
|
-
+ f"<yellow>...+({truncated_chars} chars)</yellow>"
|
|
156
|
+
message[:MAX_LENGTH] + f"<yellow>...+({truncated_chars} chars)</yellow>"
|
|
160
157
|
)
|
|
161
158
|
|
|
162
159
|
# Determine if category needs bolding (can refine this logic)
|
|
@@ -164,13 +161,9 @@ def custom_format(record):
|
|
|
164
161
|
|
|
165
162
|
# Apply tags sequentially
|
|
166
163
|
category_styled = f"[{category}]" # Start with the plain category name
|
|
167
|
-
category_styled =
|
|
168
|
-
f"<{color_tag}>{category_styled}</{color_tag}>" # Wrap with color
|
|
169
|
-
)
|
|
164
|
+
category_styled = f"<{color_tag}>{category_styled}</{color_tag}>" # Wrap with color
|
|
170
165
|
if needs_bold:
|
|
171
|
-
category_styled =
|
|
172
|
-
f"<bold>{category_styled}</bold>" # Wrap with bold if needed
|
|
173
|
-
)
|
|
166
|
+
category_styled = f"<bold>{category_styled}</bold>" # Wrap with bold if needed
|
|
174
167
|
|
|
175
168
|
# Final format string using sequential tags for category
|
|
176
169
|
return (
|
|
@@ -311,8 +304,7 @@ class FlockLogger:
|
|
|
311
304
|
if len(message) > max_length:
|
|
312
305
|
truncated_chars = len(message) - max_length
|
|
313
306
|
return (
|
|
314
|
-
message[:max_length]
|
|
315
|
-
+ f"...<yellow>+({truncated_chars} chars)</yellow>"
|
|
307
|
+
message[:max_length] + f"...<yellow>+({truncated_chars} chars)</yellow>"
|
|
316
308
|
)
|
|
317
309
|
return message
|
|
318
310
|
|
|
@@ -454,10 +446,7 @@ def get_module_loggers() -> list[FlockLogger]:
|
|
|
454
446
|
def truncate_for_logging(obj, max_item_length=100, max_items=10):
|
|
455
447
|
"""Truncate large data structures for logging purposes."""
|
|
456
448
|
if isinstance(obj, str) and len(obj) > max_item_length:
|
|
457
|
-
return (
|
|
458
|
-
obj[:max_item_length]
|
|
459
|
-
+ f"... ({len(obj) - max_item_length} more chars)"
|
|
460
|
-
)
|
|
449
|
+
return obj[:max_item_length] + f"... ({len(obj) - max_item_length} more chars)"
|
|
461
450
|
elif isinstance(obj, dict):
|
|
462
451
|
if len(obj) > max_items:
|
|
463
452
|
return {
|
|
@@ -93,26 +93,20 @@ def _resolve_type_string(type_str: str) -> type:
|
|
|
93
93
|
if generic_match:
|
|
94
94
|
base_name = generic_match.group(1).strip()
|
|
95
95
|
args_str = generic_match.group(2).strip()
|
|
96
|
-
logger.debug(
|
|
97
|
-
f"Detected generic pattern: Base='{base_name}', Args='{args_str}'"
|
|
98
|
-
)
|
|
96
|
+
logger.debug(f"Detected generic pattern: Base='{base_name}', Args='{args_str}'")
|
|
99
97
|
|
|
100
98
|
try:
|
|
101
99
|
# Get the base generic type (e.g., list, dict, Optional) from registry/builtins
|
|
102
100
|
BaseType = FlockRegistry.get_type(
|
|
103
101
|
base_name
|
|
104
102
|
) # Expects List, Dict etc. to be registered
|
|
105
|
-
logger.debug(
|
|
106
|
-
f"Resolved base generic type '{base_name}' to: {BaseType}"
|
|
107
|
-
)
|
|
103
|
+
logger.debug(f"Resolved base generic type '{base_name}' to: {BaseType}")
|
|
108
104
|
|
|
109
105
|
# Special handling for Literal
|
|
110
106
|
if BaseType is typing.Literal:
|
|
111
107
|
# Split literal values, remove quotes, strip whitespace
|
|
112
108
|
literal_args_raw = split_top_level(args_str)
|
|
113
|
-
literal_args = tuple(
|
|
114
|
-
s.strip().strip("'\"") for s in literal_args_raw
|
|
115
|
-
)
|
|
109
|
+
literal_args = tuple(s.strip().strip("'\"") for s in literal_args_raw)
|
|
116
110
|
logger.debug(
|
|
117
111
|
f"Parsing Literal arguments: {literal_args_raw} -> {literal_args}"
|
|
118
112
|
)
|
|
@@ -127,9 +121,7 @@ def _resolve_type_string(type_str: str) -> type:
|
|
|
127
121
|
if not arg_strs:
|
|
128
122
|
raise ValueError("Generic type has no arguments.")
|
|
129
123
|
|
|
130
|
-
resolved_arg_types = tuple(
|
|
131
|
-
_resolve_type_string(arg) for arg in arg_strs
|
|
132
|
-
)
|
|
124
|
+
resolved_arg_types = tuple(_resolve_type_string(arg) for arg in arg_strs)
|
|
133
125
|
logger.debug(f"Resolved generic arguments: {resolved_arg_types}")
|
|
134
126
|
|
|
135
127
|
# Construct the generic type hint
|
|
@@ -137,9 +129,7 @@ def _resolve_type_string(type_str: str) -> type:
|
|
|
137
129
|
if len(resolved_arg_types) != 1:
|
|
138
130
|
raise ValueError("Optional requires exactly one argument.")
|
|
139
131
|
resolved_type = typing.Union[resolved_arg_types[0], type(None)] # type: ignore
|
|
140
|
-
logger.debug(
|
|
141
|
-
f"Constructed Optional type as Union: {resolved_type}"
|
|
142
|
-
)
|
|
132
|
+
logger.debug(f"Constructed Optional type as Union: {resolved_type}")
|
|
143
133
|
return resolved_type
|
|
144
134
|
elif BaseType is typing.Union:
|
|
145
135
|
if not resolved_arg_types:
|
|
@@ -151,9 +141,7 @@ def _resolve_type_string(type_str: str) -> type:
|
|
|
151
141
|
BaseType, "__getitem__"
|
|
152
142
|
): # Check if subscriptable (like list, dict, List, Dict)
|
|
153
143
|
resolved_type = BaseType[resolved_arg_types] # type: ignore
|
|
154
|
-
logger.debug(
|
|
155
|
-
f"Constructed subscripted generic type: {resolved_type}"
|
|
156
|
-
)
|
|
144
|
+
logger.debug(f"Constructed subscripted generic type: {resolved_type}")
|
|
157
145
|
return resolved_type
|
|
158
146
|
else:
|
|
159
147
|
# Base type found but cannot be subscripted
|
|
@@ -244,15 +232,11 @@ class DSPyIntegrationMixin:
|
|
|
244
232
|
)
|
|
245
233
|
|
|
246
234
|
FieldClass = (
|
|
247
|
-
dspy.InputField
|
|
248
|
-
if field_kind == "input"
|
|
249
|
-
else dspy.OutputField
|
|
235
|
+
dspy.InputField if field_kind == "input" else dspy.OutputField
|
|
250
236
|
)
|
|
251
237
|
# DSPy Fields use 'desc' for description
|
|
252
238
|
class_dict[name] = (
|
|
253
|
-
FieldClass(desc=desc)
|
|
254
|
-
if desc is not None
|
|
255
|
-
else FieldClass()
|
|
239
|
+
FieldClass(desc=desc) if desc is not None else FieldClass()
|
|
256
240
|
)
|
|
257
241
|
|
|
258
242
|
try:
|
|
@@ -263,15 +247,11 @@ class DSPyIntegrationMixin:
|
|
|
263
247
|
f"Error processing fields for DSPy signature '{agent_name}': {e}",
|
|
264
248
|
exc_info=True,
|
|
265
249
|
)
|
|
266
|
-
raise ValueError(
|
|
267
|
-
f"Could not process fields for signature: {e}"
|
|
268
|
-
) from e
|
|
250
|
+
raise ValueError(f"Could not process fields for signature: {e}") from e
|
|
269
251
|
|
|
270
252
|
# Create and return the dynamic class
|
|
271
253
|
try:
|
|
272
|
-
DynamicSignature = type(
|
|
273
|
-
"dspy_" + agent_name, (base_class,), class_dict
|
|
274
|
-
)
|
|
254
|
+
DynamicSignature = type("dspy_" + agent_name, (base_class,), class_dict)
|
|
275
255
|
logger.info(
|
|
276
256
|
f"Successfully created DSPy Signature: {DynamicSignature.__name__} "
|
|
277
257
|
f"with fields: {DynamicSignature.__annotations__}"
|
|
@@ -344,9 +324,7 @@ class DSPyIntegrationMixin:
|
|
|
344
324
|
try:
|
|
345
325
|
import dspy
|
|
346
326
|
except ImportError:
|
|
347
|
-
logger.error(
|
|
348
|
-
"DSPy library is not installed. Cannot select DSPy task."
|
|
349
|
-
)
|
|
327
|
+
logger.error("DSPy library is not installed. Cannot select DSPy task.")
|
|
350
328
|
raise ImportError("DSPy is required for this functionality.")
|
|
351
329
|
|
|
352
330
|
processed_tools = []
|
|
@@ -365,9 +343,7 @@ class DSPyIntegrationMixin:
|
|
|
365
343
|
|
|
366
344
|
# Determine type if not overridden
|
|
367
345
|
if not selected_type:
|
|
368
|
-
selected_type =
|
|
369
|
-
"ReAct" if processed_tools else "Predict"
|
|
370
|
-
) # Default logic
|
|
346
|
+
selected_type = "ReAct" if processed_tools else "Predict" # Default logic
|
|
371
347
|
|
|
372
348
|
logger.debug(
|
|
373
349
|
f"Selecting DSPy program type: {selected_type} (Tools provided: {bool(processed_tools)})"
|
|
@@ -390,9 +366,7 @@ class DSPyIntegrationMixin:
|
|
|
390
366
|
)
|
|
391
367
|
dspy_program = dspy.Predict(signature)
|
|
392
368
|
|
|
393
|
-
logger.info(
|
|
394
|
-
f"Instantiated DSPy program: {type(dspy_program).__name__}"
|
|
395
|
-
)
|
|
369
|
+
logger.info(f"Instantiated DSPy program: {type(dspy_program).__name__}")
|
|
396
370
|
return dspy_program
|
|
397
371
|
except Exception as e:
|
|
398
372
|
logger.error(
|
|
@@ -416,9 +390,7 @@ class DSPyIntegrationMixin:
|
|
|
416
390
|
output_dict = dict(result.items())
|
|
417
391
|
elif hasattr(result, "__dict__"): # Fallback for other object types
|
|
418
392
|
output_dict = {
|
|
419
|
-
k: v
|
|
420
|
-
for k, v in result.__dict__.items()
|
|
421
|
-
if not k.startswith("_")
|
|
393
|
+
k: v for k, v in result.__dict__.items() if not k.startswith("_")
|
|
422
394
|
}
|
|
423
395
|
else:
|
|
424
396
|
# If it's already a dict (less common for DSPy results directly)
|
|
@@ -436,7 +408,7 @@ class DSPyIntegrationMixin:
|
|
|
436
408
|
|
|
437
409
|
lm = dspy.settings.get("lm")
|
|
438
410
|
cost = sum([x["cost"] for x in lm.history if x["cost"] is not None])
|
|
439
|
-
lm_history = lm.
|
|
411
|
+
lm_history = lm.history
|
|
440
412
|
|
|
441
413
|
return final_result, cost, lm_history
|
|
442
414
|
|
|
@@ -57,9 +57,7 @@ def _format_type_to_string(type_hint: type) -> str:
|
|
|
57
57
|
inner_type = next(t for t in args if t is not type(None))
|
|
58
58
|
return _format_type_to_string(inner_type)
|
|
59
59
|
# return f"Optional[{_format_type_to_string(inner_type)}]"
|
|
60
|
-
return (
|
|
61
|
-
f"Union[{', '.join(_format_type_to_string(arg) for arg in args)}]"
|
|
62
|
-
)
|
|
60
|
+
return f"Union[{', '.join(_format_type_to_string(arg) for arg in args)}]"
|
|
63
61
|
elif origin is Literal:
|
|
64
62
|
formatted_args = []
|
|
65
63
|
for arg in args:
|
|
@@ -68,9 +66,7 @@ def _format_type_to_string(type_hint: type) -> str:
|
|
|
68
66
|
else:
|
|
69
67
|
formatted_args.append(str(arg))
|
|
70
68
|
return f"Literal[{', '.join(formatted_args)}]"
|
|
71
|
-
elif hasattr(
|
|
72
|
-
type_hint, "__forward_arg__"
|
|
73
|
-
): # Handle ForwardRefs if necessary
|
|
69
|
+
elif hasattr(type_hint, "__forward_arg__"): # Handle ForwardRefs if necessary
|
|
74
70
|
return type_hint.__forward_arg__
|
|
75
71
|
elif hasattr(type_hint, "__name__"):
|
|
76
72
|
# Handle custom types registered in registry (get preferred name)
|
|
@@ -87,9 +83,7 @@ def _format_type_to_string(type_hint: type) -> str:
|
|
|
87
83
|
type_repr = str(type_hint).replace("typing.", "") # Basic cleanup
|
|
88
84
|
type_repr = str(type_hint).replace("| None", "")
|
|
89
85
|
type_repr = type_repr.strip()
|
|
90
|
-
logger.debug(
|
|
91
|
-
f"Using fallback string representation for type: {type_repr}"
|
|
92
|
-
)
|
|
86
|
+
logger.debug(f"Using fallback string representation for type: {type_repr}")
|
|
93
87
|
return type_repr
|
|
94
88
|
|
|
95
89
|
|
|
@@ -199,9 +193,7 @@ def serialize_item(item: Any) -> Any:
|
|
|
199
193
|
dumped = item.model_dump(mode="json", exclude_none=True)
|
|
200
194
|
return serialize_item(dumped)
|
|
201
195
|
elif callable(item) and not isinstance(item, type):
|
|
202
|
-
path_str = FlockRegistry.get_callable_path_string(
|
|
203
|
-
item
|
|
204
|
-
) # Use registry helper
|
|
196
|
+
path_str = FlockRegistry.get_callable_path_string(item) # Use registry helper
|
|
205
197
|
if path_str:
|
|
206
198
|
return {"__callable_ref__": path_str}
|
|
207
199
|
else:
|
|
@@ -226,9 +218,7 @@ def serialize_item(item: Any) -> Any:
|
|
|
226
218
|
) # Check regular types/classes by path
|
|
227
219
|
if type_name:
|
|
228
220
|
return {"__type_ref__": type_name}
|
|
229
|
-
logger.warning(
|
|
230
|
-
f"Could not serialize type object {item}, storing as string."
|
|
231
|
-
)
|
|
221
|
+
logger.warning(f"Could not serialize type object {item}, storing as string.")
|
|
232
222
|
return str(item)
|
|
233
223
|
else:
|
|
234
224
|
# Return basic types as is
|
|
@@ -283,9 +273,7 @@ def deserialize_item(item: Any) -> Any:
|
|
|
283
273
|
mod = importlib.import_module(module_name)
|
|
284
274
|
type_obj = getattr(mod, class_name)
|
|
285
275
|
if isinstance(type_obj, type):
|
|
286
|
-
FlockRegistry.register_type(
|
|
287
|
-
type_obj, type_name
|
|
288
|
-
) # Cache it
|
|
276
|
+
FlockRegistry.register_type(type_obj, type_name) # Cache it
|
|
289
277
|
return type_obj
|
|
290
278
|
else:
|
|
291
279
|
raise TypeError()
|
|
@@ -306,9 +294,7 @@ def deserialize_item(item: Any) -> Any:
|
|
|
306
294
|
|
|
307
295
|
|
|
308
296
|
# --- Component Deserialization Helper ---
|
|
309
|
-
def deserialize_component(
|
|
310
|
-
data: dict | None, expected_base_type: type
|
|
311
|
-
) -> Any | None:
|
|
297
|
+
def deserialize_component(data: dict | None, expected_base_type: type) -> Any | None:
|
|
312
298
|
"""Deserializes a component (Module, Evaluator, Router) from its dict representation.
|
|
313
299
|
Uses the 'type' field to find the correct class via FlockRegistry.
|
|
314
300
|
"""
|
|
@@ -320,14 +306,10 @@ def deserialize_component(
|
|
|
320
306
|
if data is None:
|
|
321
307
|
return None
|
|
322
308
|
if not isinstance(data, dict):
|
|
323
|
-
logger.error(
|
|
324
|
-
f"Expected dict for component deserialization, got {type(data)}"
|
|
325
|
-
)
|
|
309
|
+
logger.error(f"Expected dict for component deserialization, got {type(data)}")
|
|
326
310
|
return None
|
|
327
311
|
|
|
328
|
-
type_name = data.get(
|
|
329
|
-
"type"
|
|
330
|
-
) # Assuming 'type' key holds the class name string
|
|
312
|
+
type_name = data.get("type") # Assuming 'type' key holds the class name string
|
|
331
313
|
if not type_name:
|
|
332
314
|
logger.error(f"Component data missing 'type' field: {data}")
|
|
333
315
|
return None
|
|
@@ -335,9 +317,7 @@ def deserialize_component(
|
|
|
335
317
|
try:
|
|
336
318
|
ComponentClass = FlockRegistry.get_component(type_name) # Use registry
|
|
337
319
|
# Optional: Keep the base type check
|
|
338
|
-
if COMPONENT_BASE_TYPES and not issubclass(
|
|
339
|
-
ComponentClass, expected_base_type
|
|
340
|
-
):
|
|
320
|
+
if COMPONENT_BASE_TYPES and not issubclass(ComponentClass, expected_base_type):
|
|
341
321
|
raise TypeError(
|
|
342
322
|
f"Deserialized class {type_name} is not a subclass of {expected_base_type.__name__}"
|
|
343
323
|
)
|
flock/core/util/cli_helper.py
CHANGED
|
@@ -64,14 +64,14 @@ def init_console(clear_screen: bool = True, show_banner: bool = True):
|
|
|
64
64
|
if show_banner:
|
|
65
65
|
console.print(banner_text)
|
|
66
66
|
console.print(
|
|
67
|
-
|
|
67
|
+
"[italic]'Magpie'[/] milestone - [bold]white duck GmbH[/] - [cyan]https://whiteduck.de[/]\n"
|
|
68
68
|
)
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
def display_banner_no_version():
|
|
72
72
|
"""Display the Flock banner."""
|
|
73
73
|
banner_text = Text(
|
|
74
|
-
|
|
74
|
+
"""
|
|
75
75
|
🦆 🐓 🐤 🐧
|
|
76
76
|
╭━━━━━━━━━━━━━━━━━━━━━━━━╮
|
|
77
77
|
│ ▒█▀▀▀ █░░ █▀▀█ █▀▀ █░█ │
|
|
@@ -84,4 +84,4 @@ def display_banner_no_version():
|
|
|
84
84
|
style="bold orange3",
|
|
85
85
|
)
|
|
86
86
|
console.print(banner_text)
|
|
87
|
-
console.print(
|
|
87
|
+
console.print("[bold]white duck GmbH[/] - [cyan]https://whiteduck.de[/]\n")
|
flock/core/util/hydrator.py
CHANGED
|
@@ -21,9 +21,7 @@ logger = get_logger("hydrator")
|
|
|
21
21
|
T = TypeVar("T", bound=BaseModel)
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def flockclass(
|
|
25
|
-
model: str = "openai/gpt-4o", agent_description: str | None = None
|
|
26
|
-
):
|
|
24
|
+
def flockclass(model: str = "openai/gpt-4o", agent_description: str | None = None):
|
|
27
25
|
"""Decorator to add a .hydrate() method to a Pydantic class.
|
|
28
26
|
Leverages a dynamic Flock agent to fill missing (None) fields.
|
|
29
27
|
|
|
@@ -90,9 +88,7 @@ def flockclass(
|
|
|
90
88
|
return self # Return early if agent run failed
|
|
91
89
|
|
|
92
90
|
# Update object fields with results
|
|
93
|
-
_update_fields_with_results(
|
|
94
|
-
self, result, missing_fields, class_name
|
|
95
|
-
)
|
|
91
|
+
_update_fields_with_results(self, result, missing_fields, class_name)
|
|
96
92
|
|
|
97
93
|
return self
|
|
98
94
|
|
|
@@ -109,9 +105,7 @@ def flockclass(
|
|
|
109
105
|
import concurrent.futures
|
|
110
106
|
|
|
111
107
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
112
|
-
future = executor.submit(
|
|
113
|
-
asyncio.run, hydrate_async(self)
|
|
114
|
-
)
|
|
108
|
+
future = executor.submit(asyncio.run, hydrate_async(self))
|
|
115
109
|
return future.result()
|
|
116
110
|
else:
|
|
117
111
|
# There's a loop but it's not running
|
|
@@ -124,9 +118,7 @@ def flockclass(
|
|
|
124
118
|
# Attach the methods to the class
|
|
125
119
|
setattr(cls, "hydrate_async", hydrate_async)
|
|
126
120
|
setattr(cls, "hydrate", hydrate)
|
|
127
|
-
setattr(
|
|
128
|
-
cls, "hydrate_sync", hydrate
|
|
129
|
-
) # Alias for backward compatibility
|
|
121
|
+
setattr(cls, "hydrate_sync", hydrate) # Alias for backward compatibility
|
|
130
122
|
|
|
131
123
|
logger.debug(f"Attached hydrate methods to class {cls.__name__}")
|
|
132
124
|
return cls
|
|
@@ -141,14 +133,10 @@ def _get_model_fields(
|
|
|
141
133
|
try:
|
|
142
134
|
if hasattr(obj, "model_fields"): # Pydantic v2
|
|
143
135
|
all_fields = obj.model_fields
|
|
144
|
-
type_hints = {
|
|
145
|
-
name: field.annotation for name, field in all_fields.items()
|
|
146
|
-
}
|
|
136
|
+
type_hints = {name: field.annotation for name, field in all_fields.items()}
|
|
147
137
|
else: # Pydantic v1 fallback
|
|
148
138
|
type_hints = get_type_hints(obj.__class__)
|
|
149
|
-
all_fields = getattr(
|
|
150
|
-
obj, "__fields__", {name: None for name in type_hints}
|
|
151
|
-
)
|
|
139
|
+
all_fields = getattr(obj, "__fields__", {name: None for name in type_hints})
|
|
152
140
|
return all_fields, type_hints
|
|
153
141
|
except Exception as e:
|
|
154
142
|
logger.error(
|
|
@@ -268,9 +256,7 @@ async def _run_hydration_agent(
|
|
|
268
256
|
else {"context_info": {"object_type": class_name}}
|
|
269
257
|
)
|
|
270
258
|
|
|
271
|
-
logger.info(
|
|
272
|
-
f"Running hydration agent '{agent_name}' for {class_name}..."
|
|
273
|
-
)
|
|
259
|
+
logger.info(f"Running hydration agent '{agent_name}' for {class_name}...")
|
|
274
260
|
|
|
275
261
|
# Run agent
|
|
276
262
|
result = await temp_flock.run_async(
|
|
@@ -278,9 +264,7 @@ async def _run_hydration_agent(
|
|
|
278
264
|
input=agent_input_data,
|
|
279
265
|
box_result=False,
|
|
280
266
|
)
|
|
281
|
-
logger.info(
|
|
282
|
-
f"Hydration agent returned for {class_name}: {list(result.keys())}"
|
|
283
|
-
)
|
|
267
|
+
logger.info(f"Hydration agent returned for {class_name}: {list(result.keys())}")
|
|
284
268
|
|
|
285
269
|
return result
|
|
286
270
|
|
|
@@ -35,9 +35,7 @@ class DeclarativeEvaluatorConfig(FlockEvaluatorConfig):
|
|
|
35
35
|
kwargs: dict[str, Any] = Field(default_factory=dict)
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
class DeclarativeEvaluator(
|
|
39
|
-
FlockEvaluator, DSPyIntegrationMixin, PromptParserMixin
|
|
40
|
-
):
|
|
38
|
+
class DeclarativeEvaluator(FlockEvaluator, DSPyIntegrationMixin, PromptParserMixin):
|
|
41
39
|
"""Evaluator that uses DSPy for generation."""
|
|
42
40
|
|
|
43
41
|
config: DeclarativeEvaluatorConfig = Field(
|
|
@@ -91,14 +89,10 @@ class DeclarativeEvaluator(
|
|
|
91
89
|
|
|
92
90
|
# --- Conditional Evaluation (Stream vs No Stream) ---
|
|
93
91
|
if self.config.stream:
|
|
94
|
-
logger.info(
|
|
95
|
-
f"Evaluating agent '{agent.name}' with async streaming."
|
|
96
|
-
)
|
|
92
|
+
logger.info(f"Evaluating agent '{agent.name}' with async streaming.")
|
|
97
93
|
if not callable(agent_task):
|
|
98
94
|
logger.error("agent_task is not callable, cannot stream.")
|
|
99
|
-
raise TypeError(
|
|
100
|
-
"DSPy task could not be created or is not callable."
|
|
101
|
-
)
|
|
95
|
+
raise TypeError("DSPy task could not be created or is not callable.")
|
|
102
96
|
|
|
103
97
|
streaming_task = dspy.streamify(agent_task)
|
|
104
98
|
stream_generator: Generator = streaming_task(**inputs)
|
|
@@ -150,7 +144,7 @@ class DeclarativeEvaluator(
|
|
|
150
144
|
raise RuntimeError(f"Evaluation failed: {e}") from e
|
|
151
145
|
|
|
152
146
|
def filter_thought_process(
|
|
153
|
-
result_dict: dict[str, Any], include_thought_process: bool
|
|
147
|
+
self, result_dict: dict[str, Any], include_thought_process: bool
|
|
154
148
|
) -> dict[str, Any]:
|
|
155
149
|
"""Filter out thought process from the result dictionary."""
|
|
156
150
|
if include_thought_process:
|
|
@@ -19,7 +19,7 @@ flock/cli/view_results.py,sha256=dOzK0O1FHSIDERnx48y-2Xke9BkOHS7pcOhs64AyIg0,781
|
|
|
19
19
|
flock/cli/yaml_editor.py,sha256=K3N0bh61G1TSDAZDnurqW9e_-hO6CtSQKXQqlDhCjVo,12527
|
|
20
20
|
flock/cli/assets/release_notes.md,sha256=bqnk50jxM3w5uY44Dc7MkdT8XmRREFxrVBAG9XCOSSU,4896
|
|
21
21
|
flock/core/__init__.py,sha256=p7lmQULRu9ejIAELfanZiyMhW0CougIPvyFHW2nqBFQ,847
|
|
22
|
-
flock/core/flock.py,sha256=
|
|
22
|
+
flock/core/flock.py,sha256=RcDUc__ukjUy9aSA_n0t8SxXCex4BV_nagTcg22peJ0,25116
|
|
23
23
|
flock/core/flock_agent.py,sha256=ZmkiHd2oLao_263b7nmf26TQfyevX9_HNlhHPIkd3UM,33497
|
|
24
24
|
flock/core/flock_evaluator.py,sha256=dOXZeDOGZcAmJ9ahqq_2bdGUU1VOXY4skmwTVpAjiVw,1685
|
|
25
25
|
flock/core/flock_factory.py,sha256=vLkCASLh7Vrb5NFjb4ZQT5xN3zsUDud51hAQxb82oTk,2993
|
|
@@ -45,7 +45,7 @@ flock/core/execution/local_executor.py,sha256=rnIQvaJOs6zZORUcR3vvyS6LPREDJTjayg
|
|
|
45
45
|
flock/core/execution/temporal_executor.py,sha256=OF_uXgQsoUGp6U1ZkcuaidAEKyH7XDtbfrtdF10XQ_4,1675
|
|
46
46
|
flock/core/interpreter/python_interpreter.py,sha256=RaUMZuufsKBNQ4FAeSaOgUuxzs8VYu5TgUUs-xwaxxM,26376
|
|
47
47
|
flock/core/logging/__init__.py,sha256=Q8hp9-1ilPIUIV0jLgJ3_cP7COrea32cVwL7dicPnlM,82
|
|
48
|
-
flock/core/logging/logging.py,sha256
|
|
48
|
+
flock/core/logging/logging.py,sha256=JcgABQ8QJU1hhzhfF93eqnE0jhyXGZ2oObZst68sKR8,15409
|
|
49
49
|
flock/core/logging/telemetry.py,sha256=3E9Tyj6AUR6A5RlIufcdCdWm5BAA7tbOsCa7lHoUQaU,5404
|
|
50
50
|
flock/core/logging/trace_and_logged.py,sha256=5vNrK1kxuPMoPJ0-QjQg-EDJL1oiEzvU6UNi6X8FiMs,2117
|
|
51
51
|
flock/core/logging/formatters/enum_builder.py,sha256=LgEYXUv84wK5vwHflZ5h8HBGgvLH3sByvUQe8tZiyY0,981
|
|
@@ -56,7 +56,7 @@ flock/core/logging/span_middleware/baggage_span_processor.py,sha256=gJfRl8FeB6jd
|
|
|
56
56
|
flock/core/logging/telemetry_exporter/base_exporter.py,sha256=rQJJzS6q9n2aojoSqwCnl7ZtHrh5LZZ-gkxUuI5WfrQ,1124
|
|
57
57
|
flock/core/logging/telemetry_exporter/file_exporter.py,sha256=nKAjJSZtA7FqHSTuTiFtYYepaxOq7l1rDvs8U8rSBlA,3023
|
|
58
58
|
flock/core/logging/telemetry_exporter/sqlite_exporter.py,sha256=CDsiMb9QcqeXelZ6ZqPSS56ovMPGqOu6whzBZRK__Vg,3498
|
|
59
|
-
flock/core/mixin/dspy_integration.py,sha256=
|
|
59
|
+
flock/core/mixin/dspy_integration.py,sha256=JlGtakuy_lXXEEXBycd7ygmdUBKS-4qPWNqx3Wqfy78,17187
|
|
60
60
|
flock/core/mixin/prompt_parser.py,sha256=eOqI-FK3y17gVqpc_y5GF-WmK1Jv8mFlkZxTcgweoxI,5121
|
|
61
61
|
flock/core/serialization/__init__.py,sha256=CML7fPgG6p4c0CDBlJ_uwV1aZZhJKK9uy3IoIHfO87w,431
|
|
62
62
|
flock/core/serialization/callable_registry.py,sha256=sUZECTZWsM3fJ8FDRQ-FgLNW9hF26nY17AD6fJKADMc,1419
|
|
@@ -64,19 +64,19 @@ flock/core/serialization/flock_serializer.py,sha256=TEePKaJqU-_XWHTMWyMHloDNwmkK
|
|
|
64
64
|
flock/core/serialization/json_encoder.py,sha256=gAKj2zU_8wQiNvdkby2hksSA4fbPNwTjup_yz1Le1Vw,1229
|
|
65
65
|
flock/core/serialization/secure_serializer.py,sha256=n5-zRvvXddgJv1FFHsaQ2wuYdL3WUSGPvG_LGaffEJo,6144
|
|
66
66
|
flock/core/serialization/serializable.py,sha256=qlv8TsTqRuklXiNuCMrvro5VKz764xC2i3FlgLJSkdk,12129
|
|
67
|
-
flock/core/serialization/serialization_utils.py,sha256=
|
|
67
|
+
flock/core/serialization/serialization_utils.py,sha256=63CV41Jba29EEqS85h_6ADgbeYvVmfILmbXv742LiXQ,12702
|
|
68
68
|
flock/core/tools/azure_tools.py,sha256=hwLnI2gsEq6QzUoWj5eCGDKTdXY1XUf6K-H5Uwva2MY,17093
|
|
69
69
|
flock/core/tools/basic_tools.py,sha256=Ye7nlI4RRkqWRy8nH9CKuItBmh_ZXxUpouGnCOfx0s0,9050
|
|
70
70
|
flock/core/tools/llm_tools.py,sha256=Bdt4Dpur5dGpxd2KFEQyxjfZazvW1HCDKY6ydMj6UgQ,21811
|
|
71
71
|
flock/core/tools/markdown_tools.py,sha256=W6fGM48yGHbifVlaOk1jOtVcybfRbRmf20VbDOZv8S4,6031
|
|
72
72
|
flock/core/tools/zendesk_tools.py,sha256=deZAyUi9j-_yZaTayLQVJaFXIqIct-P6C8IGN5UU_tM,3528
|
|
73
73
|
flock/core/tools/dev_tools/github.py,sha256=a2OTPXS7kWOVA4zrZHynQDcsmEi4Pac5MfSjQOLePzA,5308
|
|
74
|
-
flock/core/util/cli_helper.py,sha256=
|
|
74
|
+
flock/core/util/cli_helper.py,sha256=EnK4X-FgaO71JsSXLdy0R-cxE3UctlFZtzldursw-Bw,49845
|
|
75
75
|
flock/core/util/file_path_utils.py,sha256=Odf7uU32C-x1KNighbNERSiMtkzW4h8laABIoFK7A5M,6246
|
|
76
|
-
flock/core/util/hydrator.py,sha256=
|
|
76
|
+
flock/core/util/hydrator.py,sha256=QJvCA8F4nkSP5akp3yg0cT6oaajOr1n7sldW5dCs6Lo,10733
|
|
77
77
|
flock/core/util/input_resolver.py,sha256=g9vDPdY4OH-G7qjas5ksGEHueokHGFPMoLOvC-ngeLo,5984
|
|
78
78
|
flock/core/util/loader.py,sha256=j3q2qem5bFMP2SmMuYjb-ISxsNGNZd1baQmpvAnRUUk,2244
|
|
79
|
-
flock/evaluators/declarative/declarative_evaluator.py,sha256=
|
|
79
|
+
flock/evaluators/declarative/declarative_evaluator.py,sha256=6FCUPf0ArckwYzNXcYAd4NcR0254e24jJadSxbStMx0,5987
|
|
80
80
|
flock/evaluators/memory/azure_search_evaluator.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
81
81
|
flock/evaluators/memory/memory_evaluator.py,sha256=SmerXyNaqm8DTV0yw-WqWkn9DXIf6x-nPG1eyTV6NY8,3452
|
|
82
82
|
flock/evaluators/natural_language/natural_language_evaluator.py,sha256=6nVEeh8_uwv_h-d3FWlA0GbzDzRtdhvxCGKirHtyvOU,2012
|
|
@@ -441,8 +441,8 @@ flock/workflow/activities.py,sha256=eVZDnxGJl_quNO-UTV3YgvTV8LrRaHN3QDAA1ANKzac,
|
|
|
441
441
|
flock/workflow/agent_activities.py,sha256=NhBZscflEf2IMfSRa_pBM_TRP7uVEF_O0ROvWZ33eDc,963
|
|
442
442
|
flock/workflow/temporal_setup.py,sha256=VWBgmBgfTBjwM5ruS_dVpA5AVxx6EZ7oFPGw4j3m0l0,1091
|
|
443
443
|
flock/workflow/workflow.py,sha256=I9MryXW_bqYVTHx-nl2epbTqeRy27CAWHHA7ZZA0nAk,1696
|
|
444
|
-
flock_core-0.4.
|
|
445
|
-
flock_core-0.4.
|
|
446
|
-
flock_core-0.4.
|
|
447
|
-
flock_core-0.4.
|
|
448
|
-
flock_core-0.4.
|
|
444
|
+
flock_core-0.4.0b22.dist-info/METADATA,sha256=oV2HF6qAqxnneQoXA-vPHC1kDVw2FVb71g49Ru-IsxY,12970
|
|
445
|
+
flock_core-0.4.0b22.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
446
|
+
flock_core-0.4.0b22.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
|
|
447
|
+
flock_core-0.4.0b22.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
|
|
448
|
+
flock_core-0.4.0b22.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|