flock-core 0.3.30__py3-none-any.whl → 0.3.32__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/__init__.py +23 -11
- flock/cli/constants.py +2 -4
- flock/cli/create_flock.py +220 -1
- flock/cli/execute_flock.py +200 -0
- flock/cli/load_flock.py +27 -7
- flock/cli/loaded_flock_cli.py +202 -0
- flock/cli/manage_agents.py +443 -0
- flock/cli/view_results.py +29 -0
- flock/cli/yaml_editor.py +283 -0
- flock/core/flock.py +44 -0
- flock/core/flock_registry.py +2 -84
- flock/core/mixin/dspy_integration.py +5 -2
- flock/core/serialization/serialization_utils.py +23 -8
- flock/evaluators/declarative/declarative_evaluator.py +2 -0
- flock/modules/memory/memory_module.py +17 -4
- flock/modules/output/output_module.py +9 -3
- {flock_core-0.3.30.dist-info → flock_core-0.3.32.dist-info}/METADATA +1 -1
- {flock_core-0.3.30.dist-info → flock_core-0.3.32.dist-info}/RECORD +21 -16
- {flock_core-0.3.30.dist-info → flock_core-0.3.32.dist-info}/WHEEL +0 -0
- {flock_core-0.3.30.dist-info → flock_core-0.3.32.dist-info}/entry_points.txt +0 -0
- {flock_core-0.3.30.dist-info → flock_core-0.3.32.dist-info}/licenses/LICENSE +0 -0
flock/cli/yaml_editor.py
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"""YAML Editor for Flock CLI.
|
|
2
|
+
|
|
3
|
+
This module provides functionality to view, edit, and validate YAML configurations
|
|
4
|
+
for Flock and FlockAgent instances.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import subprocess
|
|
9
|
+
import tempfile
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import questionary
|
|
13
|
+
import yaml
|
|
14
|
+
from rich.console import Console
|
|
15
|
+
from rich.panel import Panel
|
|
16
|
+
from rich.syntax import Syntax
|
|
17
|
+
from rich.table import Table
|
|
18
|
+
|
|
19
|
+
from flock.core.flock import Flock
|
|
20
|
+
from flock.core.flock_agent import FlockAgent
|
|
21
|
+
from flock.core.util.cli_helper import init_console
|
|
22
|
+
|
|
23
|
+
# Create console instance
|
|
24
|
+
console = Console()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def yaml_editor(flock_or_agent: Flock | FlockAgent | None = None):
|
|
28
|
+
"""YAML Editor main entry point.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
flock_or_agent: Optional Flock or FlockAgent instance to edit
|
|
32
|
+
"""
|
|
33
|
+
init_console()
|
|
34
|
+
console.print(Panel("[bold green]YAML Editor[/]"), justify="center")
|
|
35
|
+
|
|
36
|
+
if flock_or_agent is None:
|
|
37
|
+
# If no object provided, provide options to load from file
|
|
38
|
+
_yaml_file_browser()
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
while True:
|
|
42
|
+
init_console()
|
|
43
|
+
console.print(Panel("[bold green]YAML Editor[/]"), justify="center")
|
|
44
|
+
|
|
45
|
+
# Determine object type
|
|
46
|
+
if isinstance(flock_or_agent, Flock):
|
|
47
|
+
obj_type = "Flock"
|
|
48
|
+
console.print(
|
|
49
|
+
f"Editing [bold cyan]Flock[/] with {len(flock_or_agent._agents)} agents"
|
|
50
|
+
)
|
|
51
|
+
elif isinstance(flock_or_agent, FlockAgent):
|
|
52
|
+
obj_type = "FlockAgent"
|
|
53
|
+
console.print(
|
|
54
|
+
f"Editing [bold cyan]FlockAgent[/]: {flock_or_agent.name}"
|
|
55
|
+
)
|
|
56
|
+
else:
|
|
57
|
+
console.print("[bold red]Error: Unknown object type[/]")
|
|
58
|
+
input("\nPress Enter to continue...")
|
|
59
|
+
return
|
|
60
|
+
|
|
61
|
+
console.line()
|
|
62
|
+
|
|
63
|
+
choice = questionary.select(
|
|
64
|
+
"What would you like to do?",
|
|
65
|
+
choices=[
|
|
66
|
+
questionary.Separator(line=" "),
|
|
67
|
+
"View Current YAML",
|
|
68
|
+
"Edit YAML Directly",
|
|
69
|
+
"Abstract Editor (Visual)",
|
|
70
|
+
"Validate YAML",
|
|
71
|
+
"Save to File",
|
|
72
|
+
questionary.Separator(),
|
|
73
|
+
"Back to Main Menu",
|
|
74
|
+
],
|
|
75
|
+
).ask()
|
|
76
|
+
|
|
77
|
+
if choice == "View Current YAML":
|
|
78
|
+
_view_yaml(flock_or_agent)
|
|
79
|
+
elif choice == "Edit YAML Directly":
|
|
80
|
+
flock_or_agent = _edit_yaml_directly(flock_or_agent)
|
|
81
|
+
elif choice == "Abstract Editor (Visual)":
|
|
82
|
+
flock_or_agent = _abstract_editor(flock_or_agent)
|
|
83
|
+
elif choice == "Validate YAML":
|
|
84
|
+
_validate_yaml(flock_or_agent)
|
|
85
|
+
elif choice == "Save to File":
|
|
86
|
+
_save_to_file(flock_or_agent)
|
|
87
|
+
elif choice == "Back to Main Menu":
|
|
88
|
+
break
|
|
89
|
+
|
|
90
|
+
if choice != "Back to Main Menu":
|
|
91
|
+
input("\nPress Enter to continue...")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _yaml_file_browser():
|
|
95
|
+
"""Browser for YAML files to load."""
|
|
96
|
+
console.print("\n[bold]YAML File Browser[/]")
|
|
97
|
+
console.line()
|
|
98
|
+
|
|
99
|
+
current_dir = os.getcwd()
|
|
100
|
+
console.print(f"Current directory: [cyan]{current_dir}[/]")
|
|
101
|
+
|
|
102
|
+
# List .yaml/.yml files in current directory
|
|
103
|
+
yaml_files = list(Path(current_dir).glob("*.yaml")) + list(
|
|
104
|
+
Path(current_dir).glob("*.yml")
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
if not yaml_files:
|
|
108
|
+
console.print("[yellow]No YAML files found in current directory.[/]")
|
|
109
|
+
input("\nPress Enter to continue...")
|
|
110
|
+
return
|
|
111
|
+
|
|
112
|
+
# Display files
|
|
113
|
+
table = Table(title="YAML Files")
|
|
114
|
+
table.add_column("Filename", style="cyan")
|
|
115
|
+
table.add_column("Size", style="green")
|
|
116
|
+
table.add_column("Last Modified", style="yellow")
|
|
117
|
+
|
|
118
|
+
for file in yaml_files:
|
|
119
|
+
table.add_row(
|
|
120
|
+
file.name, f"{file.stat().st_size} bytes", f"{file.stat().st_mtime}"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
console.print(table)
|
|
124
|
+
|
|
125
|
+
# TODO: Add file selection and loading
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _view_yaml(obj: Flock | FlockAgent):
|
|
129
|
+
"""View the YAML representation of an object.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
obj: The object to view as YAML
|
|
133
|
+
"""
|
|
134
|
+
yaml_str = obj.to_yaml()
|
|
135
|
+
|
|
136
|
+
# Display with syntax highlighting
|
|
137
|
+
syntax = Syntax(
|
|
138
|
+
yaml_str,
|
|
139
|
+
"yaml",
|
|
140
|
+
theme="monokai",
|
|
141
|
+
line_numbers=True,
|
|
142
|
+
code_width=100,
|
|
143
|
+
word_wrap=True,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
init_console()
|
|
147
|
+
console.print(Panel("[bold green]YAML View[/]"), justify="center")
|
|
148
|
+
console.print(syntax)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _edit_yaml_directly(obj: Flock | FlockAgent) -> Flock | FlockAgent:
|
|
152
|
+
"""Edit the YAML representation directly using an external editor.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
obj: The object to edit
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
The updated object
|
|
159
|
+
"""
|
|
160
|
+
# Convert to YAML
|
|
161
|
+
yaml_str = obj.to_yaml()
|
|
162
|
+
|
|
163
|
+
# Create a temporary file
|
|
164
|
+
with tempfile.NamedTemporaryFile(
|
|
165
|
+
suffix=".yaml", mode="w+", delete=False
|
|
166
|
+
) as tmp:
|
|
167
|
+
tmp.write(yaml_str)
|
|
168
|
+
tmp_path = tmp.name
|
|
169
|
+
|
|
170
|
+
try:
|
|
171
|
+
# Determine which editor to use
|
|
172
|
+
editor = os.environ.get(
|
|
173
|
+
"EDITOR", "notepad" if os.name == "nt" else "nano"
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
# Open the editor
|
|
177
|
+
console.print(
|
|
178
|
+
f"\nOpening {editor} to edit YAML. Save and exit when done."
|
|
179
|
+
)
|
|
180
|
+
subprocess.call([editor, tmp_path])
|
|
181
|
+
|
|
182
|
+
# Read updated YAML
|
|
183
|
+
with open(tmp_path) as f:
|
|
184
|
+
updated_yaml = f.read()
|
|
185
|
+
|
|
186
|
+
# Parse back to object
|
|
187
|
+
try:
|
|
188
|
+
if isinstance(obj, Flock):
|
|
189
|
+
updated_obj = Flock.from_yaml(updated_yaml)
|
|
190
|
+
console.print("\n[green]✓[/] YAML parsed successfully!")
|
|
191
|
+
return updated_obj
|
|
192
|
+
elif isinstance(obj, FlockAgent):
|
|
193
|
+
updated_obj = FlockAgent.from_yaml(updated_yaml)
|
|
194
|
+
console.print("\n[green]✓[/] YAML parsed successfully!")
|
|
195
|
+
return updated_obj
|
|
196
|
+
except Exception as e:
|
|
197
|
+
console.print(f"\n[bold red]Error parsing YAML:[/] {e!s}")
|
|
198
|
+
console.print("\nKeeping original object.")
|
|
199
|
+
return obj
|
|
200
|
+
|
|
201
|
+
finally:
|
|
202
|
+
# Clean up the temporary file
|
|
203
|
+
try:
|
|
204
|
+
os.unlink(tmp_path)
|
|
205
|
+
except:
|
|
206
|
+
pass
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _abstract_editor(obj: Flock | FlockAgent) -> Flock | FlockAgent:
|
|
210
|
+
"""Edit object using an abstract form-based editor.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
obj: The object to edit
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
The updated object
|
|
217
|
+
"""
|
|
218
|
+
console.print("\n[yellow]Abstract visual editor not yet implemented.[/]")
|
|
219
|
+
console.print("Will provide a form-based editor for each field.")
|
|
220
|
+
|
|
221
|
+
# For now, just return the original object
|
|
222
|
+
return obj
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _validate_yaml(obj: Flock | FlockAgent):
|
|
226
|
+
"""Validate the YAML representation of an object.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
obj: The object to validate
|
|
230
|
+
"""
|
|
231
|
+
try:
|
|
232
|
+
yaml_str = obj.to_yaml()
|
|
233
|
+
|
|
234
|
+
# Attempt to parse with PyYAML
|
|
235
|
+
yaml.safe_load(yaml_str)
|
|
236
|
+
|
|
237
|
+
# Attempt to deserialize back to object
|
|
238
|
+
if isinstance(obj, Flock):
|
|
239
|
+
Flock.from_yaml(yaml_str)
|
|
240
|
+
elif isinstance(obj, FlockAgent):
|
|
241
|
+
FlockAgent.from_yaml(yaml_str)
|
|
242
|
+
|
|
243
|
+
console.print("\n[green]✓[/] YAML validation successful!")
|
|
244
|
+
except Exception as e:
|
|
245
|
+
console.print(f"\n[bold red]YAML validation failed:[/] {e!s}")
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def _save_to_file(obj: Flock | FlockAgent):
|
|
249
|
+
"""Save object to a YAML file.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
obj: The object to save
|
|
253
|
+
"""
|
|
254
|
+
# Determine default filename based on object type
|
|
255
|
+
if isinstance(obj, Flock):
|
|
256
|
+
default_name = "my_flock.flock.yaml"
|
|
257
|
+
elif isinstance(obj, FlockAgent):
|
|
258
|
+
default_name = f"{obj.name}.agent.yaml"
|
|
259
|
+
else:
|
|
260
|
+
default_name = "unknown.yaml"
|
|
261
|
+
|
|
262
|
+
# Get file path
|
|
263
|
+
file_path = questionary.text(
|
|
264
|
+
"Enter file path to save YAML:",
|
|
265
|
+
default=default_name,
|
|
266
|
+
).ask()
|
|
267
|
+
|
|
268
|
+
# Ensure the file has the correct extension
|
|
269
|
+
if not file_path.endswith((".yaml", ".yml")):
|
|
270
|
+
file_path += ".yaml"
|
|
271
|
+
|
|
272
|
+
# Create directory if it doesn't exist
|
|
273
|
+
save_path = Path(file_path)
|
|
274
|
+
save_path.parent.mkdir(parents=True, exist_ok=True)
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
# Save to file
|
|
278
|
+
with open(file_path, "w") as f:
|
|
279
|
+
f.write(obj.to_yaml())
|
|
280
|
+
|
|
281
|
+
console.print(f"\n[green]✓[/] Saved to {file_path}")
|
|
282
|
+
except Exception as e:
|
|
283
|
+
console.print(f"\n[bold red]Error saving file:[/] {e!s}")
|
flock/core/flock.py
CHANGED
|
@@ -73,6 +73,10 @@ class Flock(BaseModel, Serializable):
|
|
|
73
73
|
It is serializable to various formats like YAML and JSON.
|
|
74
74
|
"""
|
|
75
75
|
|
|
76
|
+
name: str = Field(
|
|
77
|
+
default_factory=lambda: f"flock_{uuid.uuid4().hex[:8]}",
|
|
78
|
+
description="A unique identifier for this Flock instance.",
|
|
79
|
+
)
|
|
76
80
|
model: str | None = Field(
|
|
77
81
|
default="openai/gpt-4o",
|
|
78
82
|
description="Default model identifier to be used for agents if not specified otherwise.",
|
|
@@ -104,6 +108,7 @@ class Flock(BaseModel, Serializable):
|
|
|
104
108
|
|
|
105
109
|
def __init__(
|
|
106
110
|
self,
|
|
111
|
+
name: str | None = None,
|
|
107
112
|
model: str | None = "openai/gpt-4o",
|
|
108
113
|
description: str | None = None,
|
|
109
114
|
enable_temporal: bool = False,
|
|
@@ -527,6 +532,45 @@ class Flock(BaseModel, Serializable):
|
|
|
527
532
|
host=host, port=port, server_name=server_name, create_ui=create_ui
|
|
528
533
|
)
|
|
529
534
|
|
|
535
|
+
# --- CLI Start Method ---
|
|
536
|
+
def start_cli(
|
|
537
|
+
self,
|
|
538
|
+
server_name: str = "Flock CLI",
|
|
539
|
+
show_results: bool = False,
|
|
540
|
+
edit_mode: bool = False,
|
|
541
|
+
) -> None:
|
|
542
|
+
"""Start a CLI interface for this Flock instance.
|
|
543
|
+
|
|
544
|
+
This method loads the CLI with the current Flock instance already available,
|
|
545
|
+
allowing users to execute, edit, or manage agents from the existing configuration.
|
|
546
|
+
|
|
547
|
+
Args:
|
|
548
|
+
server_name: Optional name for the CLI interface
|
|
549
|
+
show_results: Whether to initially show results of previous runs
|
|
550
|
+
edit_mode: Whether to open directly in edit mode
|
|
551
|
+
"""
|
|
552
|
+
# Import locally to avoid circular imports
|
|
553
|
+
try:
|
|
554
|
+
from flock.cli.loaded_flock_cli import start_loaded_flock_cli
|
|
555
|
+
except ImportError:
|
|
556
|
+
logger.error(
|
|
557
|
+
"CLI components not found. Cannot start CLI. "
|
|
558
|
+
"Ensure the CLI modules are properly installed."
|
|
559
|
+
)
|
|
560
|
+
return
|
|
561
|
+
|
|
562
|
+
logger.info(
|
|
563
|
+
f"Starting CLI interface with loaded Flock instance ({len(self._agents)} agents)"
|
|
564
|
+
)
|
|
565
|
+
|
|
566
|
+
# Pass the current Flock instance to the CLI
|
|
567
|
+
start_loaded_flock_cli(
|
|
568
|
+
flock=self,
|
|
569
|
+
server_name=server_name,
|
|
570
|
+
show_results=show_results,
|
|
571
|
+
edit_mode=edit_mode,
|
|
572
|
+
)
|
|
573
|
+
|
|
530
574
|
# --- Static Method Loaders (Keep for convenience) ---
|
|
531
575
|
@staticmethod
|
|
532
576
|
def load_from_file(file_path: str) -> Flock:
|
flock/core/flock_registry.py
CHANGED
|
@@ -528,87 +528,5 @@ def _auto_register_by_path():
|
|
|
528
528
|
)
|
|
529
529
|
|
|
530
530
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
# Register base classes themselves if needed by name (e.g., for type checks)
|
|
534
|
-
# _registry_instance.register_component(FlockEvaluator)
|
|
535
|
-
# _registry_instance.register_component(FlockModule)
|
|
536
|
-
# _registry_instance.register_component(FlockRouter)
|
|
537
|
-
|
|
538
|
-
# Import and register known implementations
|
|
539
|
-
try:
|
|
540
|
-
from flock.evaluators.declarative.declarative_evaluator import (
|
|
541
|
-
DeclarativeEvaluator,
|
|
542
|
-
)
|
|
543
|
-
|
|
544
|
-
_registry_instance.register_component(DeclarativeEvaluator)
|
|
545
|
-
except ImportError:
|
|
546
|
-
logger.warning("DeclarativeEvaluator not found for auto-registration.")
|
|
547
|
-
try:
|
|
548
|
-
from flock.evaluators.memory.memory_evaluator import MemoryEvaluator
|
|
549
|
-
|
|
550
|
-
_registry_instance.register_component(MemoryEvaluator)
|
|
551
|
-
except ImportError:
|
|
552
|
-
logger.warning("MemoryEvaluator not found for auto-registration.")
|
|
553
|
-
# Add other standard evaluators...
|
|
554
|
-
|
|
555
|
-
try:
|
|
556
|
-
from flock.modules.output.output_module import OutputModule
|
|
557
|
-
|
|
558
|
-
_registry_instance.register_component(OutputModule)
|
|
559
|
-
except ImportError:
|
|
560
|
-
logger.warning("OutputModule not found for auto-registration.")
|
|
561
|
-
try:
|
|
562
|
-
from flock.modules.performance.metrics_module import MetricsModule
|
|
563
|
-
|
|
564
|
-
_registry_instance.register_component(MetricsModule)
|
|
565
|
-
except ImportError:
|
|
566
|
-
logger.warning("MetricsModule not found for auto-registration.")
|
|
567
|
-
try:
|
|
568
|
-
from flock.modules.memory.memory_module import MemoryModule
|
|
569
|
-
|
|
570
|
-
_registry_instance.register_component(MemoryModule)
|
|
571
|
-
except ImportError:
|
|
572
|
-
logger.warning("MemoryModule not found for auto-registration.")
|
|
573
|
-
# Add other standard modules...
|
|
574
|
-
|
|
575
|
-
try:
|
|
576
|
-
from flock.routers.default.default_router import DefaultRouter
|
|
577
|
-
|
|
578
|
-
_registry_instance.register_component(DefaultRouter)
|
|
579
|
-
except ImportError:
|
|
580
|
-
logger.warning("DefaultRouter not found for auto-registration.")
|
|
581
|
-
try:
|
|
582
|
-
from flock.routers.llm.llm_router import LLMRouter
|
|
583
|
-
|
|
584
|
-
_registry_instance.register_component(LLMRouter)
|
|
585
|
-
except ImportError:
|
|
586
|
-
logger.warning("LLMRouter not found for auto-registration.")
|
|
587
|
-
try:
|
|
588
|
-
from flock.routers.agent.agent_router import AgentRouter
|
|
589
|
-
|
|
590
|
-
_registry_instance.register_component(AgentRouter)
|
|
591
|
-
except ImportError:
|
|
592
|
-
logger.warning("AgentRouter not found for auto-registration.")
|
|
593
|
-
# Add other standard routers...
|
|
594
|
-
|
|
595
|
-
# Auto-register standard tools
|
|
596
|
-
try:
|
|
597
|
-
from flock.core.tools import (
|
|
598
|
-
azure_tools,
|
|
599
|
-
basic_tools,
|
|
600
|
-
llm_tools,
|
|
601
|
-
markdown_tools,
|
|
602
|
-
)
|
|
603
|
-
from flock.core.tools.dev_tools import github
|
|
604
|
-
|
|
605
|
-
_registry_instance.register_module_components(basic_tools)
|
|
606
|
-
_registry_instance.register_module_components(azure_tools)
|
|
607
|
-
_registry_instance.register_module_components(github)
|
|
608
|
-
_registry_instance.register_module_components(llm_tools)
|
|
609
|
-
_registry_instance.register_module_components(markdown_tools)
|
|
610
|
-
except ImportError as e:
|
|
611
|
-
logger.warning(f"Could not auto-register standard tools: {e}")
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
_auto_register_core()
|
|
531
|
+
# Bootstrapping the registry
|
|
532
|
+
_auto_register_by_path()
|
|
@@ -5,7 +5,6 @@ import re # Import re for parsing
|
|
|
5
5
|
import typing
|
|
6
6
|
from typing import Any, Literal
|
|
7
7
|
|
|
8
|
-
from flock.core.flock_registry import get_registry # Use FlockRegistry
|
|
9
8
|
from flock.core.logging.logging import get_logger
|
|
10
9
|
|
|
11
10
|
# Import split_top_level (assuming it's moved or copied appropriately)
|
|
@@ -15,7 +14,6 @@ from flock.core.logging.logging import get_logger
|
|
|
15
14
|
# Define split_top_level here or ensure it's imported
|
|
16
15
|
|
|
17
16
|
logger = get_logger("mixin.dspy")
|
|
18
|
-
FlockRegistry = get_registry() # Get singleton instance
|
|
19
17
|
|
|
20
18
|
# Type definition for agent type override
|
|
21
19
|
AgentType = Literal["ReAct", "Completion", "ChainOfThought"] | None
|
|
@@ -69,6 +67,11 @@ def _resolve_type_string(type_str: str) -> type:
|
|
|
69
67
|
Handles built-ins, registered types, and common typing generics like
|
|
70
68
|
List, Dict, Optional, Union, Literal.
|
|
71
69
|
"""
|
|
70
|
+
# Import registry here to avoid circular imports
|
|
71
|
+
from flock.core.flock_registry import get_registry
|
|
72
|
+
|
|
73
|
+
FlockRegistry = get_registry()
|
|
74
|
+
|
|
72
75
|
type_str = type_str.strip()
|
|
73
76
|
logger.debug(f"Attempting to resolve type string: '{type_str}'")
|
|
74
77
|
|
|
@@ -3,20 +3,20 @@
|
|
|
3
3
|
|
|
4
4
|
import importlib
|
|
5
5
|
from collections.abc import Mapping, Sequence
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
7
|
|
|
8
8
|
from pydantic import BaseModel
|
|
9
9
|
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
get_registry, # New way
|
|
15
|
-
)
|
|
10
|
+
# Use TYPE_CHECKING to avoid circular imports
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
pass
|
|
13
|
+
|
|
16
14
|
from flock.core.logging.logging import get_logger
|
|
17
15
|
|
|
18
16
|
logger = get_logger("serialization.utils")
|
|
19
|
-
|
|
17
|
+
|
|
18
|
+
# Remove this line to avoid circular import at module level
|
|
19
|
+
# FlockRegistry = get_registry() # Get singleton instance
|
|
20
20
|
|
|
21
21
|
# --- Serialization Helper ---
|
|
22
22
|
|
|
@@ -26,6 +26,11 @@ def serialize_item(item: Any) -> Any:
|
|
|
26
26
|
Converts known callables to their path strings using FlockRegistry.
|
|
27
27
|
Converts Pydantic models using model_dump.
|
|
28
28
|
"""
|
|
29
|
+
# Import the registry lazily when needed
|
|
30
|
+
from flock.core.flock_registry import get_registry
|
|
31
|
+
|
|
32
|
+
FlockRegistry = get_registry()
|
|
33
|
+
|
|
29
34
|
if isinstance(item, BaseModel):
|
|
30
35
|
dumped = item.model_dump(mode="json", exclude_none=True)
|
|
31
36
|
return serialize_item(dumped)
|
|
@@ -74,6 +79,11 @@ def deserialize_item(item: Any) -> Any:
|
|
|
74
79
|
Converts reference dicts back to actual callables or types using FlockRegistry.
|
|
75
80
|
Handles nested lists and dicts.
|
|
76
81
|
"""
|
|
82
|
+
# Import the registry lazily when needed
|
|
83
|
+
from flock.core.flock_registry import get_registry
|
|
84
|
+
|
|
85
|
+
FlockRegistry = get_registry()
|
|
86
|
+
|
|
77
87
|
if isinstance(item, Mapping):
|
|
78
88
|
if "__callable_ref__" in item and len(item) == 1:
|
|
79
89
|
path_str = item["__callable_ref__"]
|
|
@@ -138,6 +148,11 @@ def deserialize_component(
|
|
|
138
148
|
"""Deserializes a component (Module, Evaluator, Router) from its dict representation.
|
|
139
149
|
Uses the 'type' field to find the correct class via FlockRegistry.
|
|
140
150
|
"""
|
|
151
|
+
# Import the registry and COMPONENT_BASE_TYPES lazily when needed
|
|
152
|
+
from flock.core.flock_registry import COMPONENT_BASE_TYPES, get_registry
|
|
153
|
+
|
|
154
|
+
FlockRegistry = get_registry()
|
|
155
|
+
|
|
141
156
|
if data is None:
|
|
142
157
|
return None
|
|
143
158
|
if not isinstance(data, dict):
|
|
@@ -9,6 +9,8 @@ from flock.core.mixin.prompt_parser import PromptParserMixin
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class DeclarativeEvaluatorConfig(FlockEvaluatorConfig):
|
|
12
|
+
"""Configuration for the DeclarativeEvaluator."""
|
|
13
|
+
|
|
12
14
|
agent_type_override: str | None = None
|
|
13
15
|
model: str | None = "openai/gpt-4o"
|
|
14
16
|
use_cache: bool = True
|
|
@@ -6,8 +6,12 @@ from typing import Any, Literal
|
|
|
6
6
|
from pydantic import Field
|
|
7
7
|
from tqdm import tqdm
|
|
8
8
|
|
|
9
|
-
from flock.core import FlockAgent, FlockModule, FlockModuleConfig
|
|
10
9
|
from flock.core.context.context import FlockContext
|
|
10
|
+
|
|
11
|
+
# if TYPE_CHECKING:
|
|
12
|
+
# from flock.core import FlockAgent
|
|
13
|
+
from flock.core.flock_agent import FlockAgent
|
|
14
|
+
from flock.core.flock_module import FlockModule, FlockModuleConfig
|
|
11
15
|
from flock.core.logging.logging import get_logger
|
|
12
16
|
from flock.modules.memory.memory_parser import MemoryMappingParser
|
|
13
17
|
from flock.modules.memory.memory_storage import FlockMemoryStore, MemoryEntry
|
|
@@ -282,7 +286,10 @@ class MemoryModule(FlockModule):
|
|
|
282
286
|
return set(concept_list)
|
|
283
287
|
|
|
284
288
|
async def _summarize_mode(
|
|
285
|
-
self,
|
|
289
|
+
self,
|
|
290
|
+
agent: FlockAgent,
|
|
291
|
+
inputs: dict[str, Any],
|
|
292
|
+
result: dict[str, Any],
|
|
286
293
|
) -> str:
|
|
287
294
|
"""Extract information chunks using summary mode."""
|
|
288
295
|
split_signature = agent.create_dspy_signature_class(
|
|
@@ -300,7 +307,10 @@ class MemoryModule(FlockModule):
|
|
|
300
307
|
return "\n".join(split_result.chunks)
|
|
301
308
|
|
|
302
309
|
async def _semantic_splitter_mode(
|
|
303
|
-
self,
|
|
310
|
+
self,
|
|
311
|
+
agent: FlockAgent,
|
|
312
|
+
inputs: dict[str, Any],
|
|
313
|
+
result: dict[str, Any],
|
|
304
314
|
) -> str | list[dict[str, str]]:
|
|
305
315
|
"""Extract information chunks using semantic mode."""
|
|
306
316
|
split_signature = agent.create_dspy_signature_class(
|
|
@@ -318,7 +328,10 @@ class MemoryModule(FlockModule):
|
|
|
318
328
|
return split_result.chunks
|
|
319
329
|
|
|
320
330
|
async def _character_splitter_mode(
|
|
321
|
-
self,
|
|
331
|
+
self,
|
|
332
|
+
agent: FlockAgent,
|
|
333
|
+
inputs: dict[str, Any],
|
|
334
|
+
result: dict[str, Any],
|
|
322
335
|
) -> list[str]:
|
|
323
336
|
"""Extract information chunks by splitting text into fixed character lengths."""
|
|
324
337
|
full_text = json.dumps(inputs) + (json.dumps(result) if result else "")
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
5
|
from datetime import datetime
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
7
|
|
|
8
8
|
from pydantic import Field
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from flock.core import FlockAgent
|
|
12
|
+
|
|
11
13
|
from flock.core.context.context import FlockContext
|
|
12
14
|
from flock.core.flock_module import FlockModule, FlockModuleConfig
|
|
13
15
|
from flock.core.logging.formatters.themed_formatter import (
|
|
@@ -17,6 +19,10 @@ from flock.core.logging.formatters.themes import OutputTheme
|
|
|
17
19
|
from flock.core.logging.logging import get_logger
|
|
18
20
|
from flock.core.serialization.json_encoder import FlockJSONEncoder
|
|
19
21
|
|
|
22
|
+
# from flock.core.logging.formatters.themes import OutputTheme
|
|
23
|
+
# from flock.core.logging.logging import get_logger
|
|
24
|
+
# from flock.core.serialization.json_encoder import FlockJSONEncoder
|
|
25
|
+
|
|
20
26
|
logger = get_logger("module.output")
|
|
21
27
|
|
|
22
28
|
|
|
@@ -168,7 +174,7 @@ class OutputModule(FlockModule):
|
|
|
168
174
|
|
|
169
175
|
async def post_evaluate(
|
|
170
176
|
self,
|
|
171
|
-
agent: FlockAgent,
|
|
177
|
+
agent: "FlockAgent",
|
|
172
178
|
inputs: dict[str, Any],
|
|
173
179
|
result: dict[str, Any],
|
|
174
180
|
context: FlockContext | None = None,
|