flock-core 0.4.506__py3-none-any.whl → 0.4.508__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/evaluation/utils.py +85 -2
- flock/core/flock.py +102 -56
- flock/core/flock_agent.py +2 -2
- flock/core/flock_evaluator.py +8 -1
- flock/core/flock_factory.py +4 -0
- flock/core/mixin/dspy_integration.py +7 -6
- flock/evaluators/declarative/declarative_evaluator.py +112 -88
- {flock_core-0.4.506.dist-info → flock_core-0.4.508.dist-info}/METADATA +28 -10
- {flock_core-0.4.506.dist-info → flock_core-0.4.508.dist-info}/RECORD +12 -15
- flock/core/api/ui/__init__.py +0 -0
- flock/core/api/ui/routes.py +0 -271
- flock/core/api/ui/utils.py +0 -119
- {flock_core-0.4.506.dist-info → flock_core-0.4.508.dist-info}/WHEEL +0 -0
- {flock_core-0.4.506.dist-info → flock_core-0.4.508.dist-info}/entry_points.txt +0 -0
- {flock_core-0.4.506.dist-info → flock_core-0.4.508.dist-info}/licenses/LICENSE +0 -0
|
@@ -26,6 +26,8 @@ class DeclarativeEvaluatorConfig(FlockEvaluatorConfig):
|
|
|
26
26
|
use_cache: bool = True
|
|
27
27
|
temperature: float = 0.0
|
|
28
28
|
max_tokens: int = 4096
|
|
29
|
+
max_retries: int = 3
|
|
30
|
+
max_tool_calls: int = 10
|
|
29
31
|
stream: bool = Field(
|
|
30
32
|
default=False,
|
|
31
33
|
description="Enable streaming output from the underlying DSPy program.",
|
|
@@ -51,110 +53,132 @@ class DeclarativeEvaluator(
|
|
|
51
53
|
_cost: float = PrivateAttr(default=0.0)
|
|
52
54
|
_lm_history: list = PrivateAttr(default_factory=list)
|
|
53
55
|
|
|
56
|
+
# def __init__(self, name: str, config: DeclarativeEvaluatorConfig) -> None:
|
|
57
|
+
# super().__init__(name=name, config=config)
|
|
58
|
+
# self._configure_language_model(
|
|
59
|
+
# model=config.model,
|
|
60
|
+
# use_cache=config.use_cache,
|
|
61
|
+
# temperature=config.temperature,
|
|
62
|
+
# max_tokens=config.max_tokens,
|
|
63
|
+
# )
|
|
64
|
+
|
|
54
65
|
async def evaluate(
|
|
55
|
-
self,
|
|
66
|
+
self,
|
|
67
|
+
agent: FlockAgent,
|
|
68
|
+
inputs: dict[str, Any],
|
|
69
|
+
tools: list[Any],
|
|
70
|
+
mcp_tools: list[Any] | None = None,
|
|
56
71
|
) -> dict[str, Any]:
|
|
57
72
|
"""Evaluate using DSPy, with optional asynchronous streaming."""
|
|
58
73
|
# --- Setup Signature and LM ---
|
|
59
|
-
try:
|
|
60
|
-
from rich.console import Console
|
|
61
|
-
|
|
62
|
-
console = Console()
|
|
63
|
-
_dspy_signature = self.create_dspy_signature_class(
|
|
64
|
-
agent.name,
|
|
65
|
-
agent.description,
|
|
66
|
-
f"{agent.input} -> {agent.output}",
|
|
67
|
-
)
|
|
68
|
-
# --- Get output field names ---
|
|
69
|
-
# dspy.Signature holds fields in .output_fields attribute
|
|
70
|
-
output_field_names = list(_dspy_signature.output_fields.keys())
|
|
71
|
-
if not output_field_names:
|
|
72
|
-
logger.warning(
|
|
73
|
-
f"DSPy signature for agent '{agent.name}' has no defined output fields. Streaming might not produce text."
|
|
74
|
-
)
|
|
75
|
-
# -----------------------------
|
|
76
74
|
|
|
77
|
-
|
|
75
|
+
with dspy.context(
|
|
76
|
+
lm=dspy.LM(
|
|
78
77
|
model=self.config.model or agent.model,
|
|
79
|
-
|
|
78
|
+
cache=self.config.use_cache,
|
|
80
79
|
temperature=self.config.temperature,
|
|
81
80
|
max_tokens=self.config.max_tokens,
|
|
81
|
+
num_retries=self.config.max_retries,
|
|
82
82
|
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
tools=tools,
|
|
87
|
-
mcp_tools=mcp_tools,
|
|
88
|
-
kwargs=self.config.kwargs,
|
|
89
|
-
)
|
|
90
|
-
except Exception as setup_error:
|
|
91
|
-
logger.error(
|
|
92
|
-
f"Error setting up DSPy task for agent '{agent.name}': {setup_error}",
|
|
93
|
-
exc_info=True,
|
|
94
|
-
)
|
|
95
|
-
raise RuntimeError(
|
|
96
|
-
f"DSPy task setup failed: {setup_error}"
|
|
97
|
-
) from setup_error
|
|
98
|
-
|
|
99
|
-
# --- Conditional Evaluation (Stream vs No Stream) ---
|
|
100
|
-
if self.config.stream:
|
|
101
|
-
logger.info(
|
|
102
|
-
f"Evaluating agent '{agent.name}' with async streaming."
|
|
103
|
-
)
|
|
104
|
-
if not callable(agent_task):
|
|
105
|
-
logger.error("agent_task is not callable, cannot stream.")
|
|
106
|
-
raise TypeError(
|
|
107
|
-
"DSPy task could not be created or is not callable."
|
|
108
|
-
)
|
|
83
|
+
):
|
|
84
|
+
try:
|
|
85
|
+
from rich.console import Console
|
|
109
86
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
async for chunk in stream_generator:
|
|
116
|
-
if (
|
|
117
|
-
hasattr(chunk, "choices")
|
|
118
|
-
and chunk.choices
|
|
119
|
-
and hasattr(chunk.choices[0], "delta")
|
|
120
|
-
and chunk.choices[0].delta
|
|
121
|
-
and hasattr(chunk.choices[0].delta, "content")
|
|
122
|
-
):
|
|
123
|
-
delta_content = chunk.choices[0].delta.content
|
|
124
|
-
|
|
125
|
-
if delta_content:
|
|
126
|
-
console.print(delta_content, end="")
|
|
127
|
-
|
|
128
|
-
result_dict, cost, lm_history = self._process_result(
|
|
129
|
-
chunk, inputs
|
|
87
|
+
console = Console()
|
|
88
|
+
_dspy_signature = self.create_dspy_signature_class(
|
|
89
|
+
agent.name,
|
|
90
|
+
agent.description,
|
|
91
|
+
f"{agent.input} -> {agent.output}",
|
|
130
92
|
)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
93
|
+
# --- Get output field names ---
|
|
94
|
+
# dspy.Signature holds fields in .output_fields attribute
|
|
95
|
+
output_field_names = list(_dspy_signature.output_fields.keys())
|
|
96
|
+
if not output_field_names:
|
|
97
|
+
logger.warning(
|
|
98
|
+
f"DSPy signature for agent '{agent.name}' has no defined output fields. Streaming might not produce text."
|
|
99
|
+
)
|
|
100
|
+
# -----------------------------
|
|
101
|
+
|
|
102
|
+
agent_task = self._select_task(
|
|
103
|
+
_dspy_signature,
|
|
104
|
+
override_evaluator_type=self.config.override_evaluator_type,
|
|
105
|
+
tools=tools,
|
|
106
|
+
max_tool_calls=self.config.max_tool_calls,
|
|
107
|
+
mcp_tools=mcp_tools,
|
|
108
|
+
kwargs=self.config.kwargs,
|
|
109
|
+
)
|
|
110
|
+
except Exception as setup_error:
|
|
111
|
+
logger.error(
|
|
112
|
+
f"Error setting up DSPy task for agent '{agent.name}': {setup_error}",
|
|
113
|
+
exc_info=True,
|
|
146
114
|
)
|
|
147
|
-
|
|
148
|
-
|
|
115
|
+
raise RuntimeError(
|
|
116
|
+
f"DSPy task setup failed: {setup_error}"
|
|
117
|
+
) from setup_error
|
|
118
|
+
|
|
119
|
+
# --- Conditional Evaluation (Stream vs No Stream) ---
|
|
120
|
+
if self.config.stream:
|
|
121
|
+
logger.info(
|
|
122
|
+
f"Evaluating agent '{agent.name}' with async streaming."
|
|
123
|
+
)
|
|
124
|
+
if not callable(agent_task):
|
|
125
|
+
logger.error("agent_task is not callable, cannot stream.")
|
|
126
|
+
raise TypeError(
|
|
127
|
+
"DSPy task could not be created or is not callable."
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
streaming_task = dspy.streamify(
|
|
131
|
+
agent_task, is_async_program=True
|
|
132
|
+
)
|
|
133
|
+
stream_generator: Generator = streaming_task(**inputs)
|
|
134
|
+
delta_content = ""
|
|
135
|
+
|
|
136
|
+
console.print("\n")
|
|
137
|
+
async for chunk in stream_generator:
|
|
138
|
+
if (
|
|
139
|
+
hasattr(chunk, "choices")
|
|
140
|
+
and chunk.choices
|
|
141
|
+
and hasattr(chunk.choices[0], "delta")
|
|
142
|
+
and chunk.choices[0].delta
|
|
143
|
+
and hasattr(chunk.choices[0].delta, "content")
|
|
144
|
+
):
|
|
145
|
+
delta_content = chunk.choices[0].delta.content
|
|
146
|
+
|
|
147
|
+
if delta_content:
|
|
148
|
+
console.print(delta_content, end="")
|
|
149
|
+
|
|
150
|
+
result_dict, cost, lm_history = self._process_result(
|
|
151
|
+
chunk, inputs
|
|
152
|
+
)
|
|
153
|
+
self._cost = cost
|
|
154
|
+
self._lm_history = lm_history
|
|
155
|
+
|
|
156
|
+
console.print("\n")
|
|
149
157
|
return self.filter_thought_process(
|
|
150
158
|
result_dict, self.config.include_thought_process
|
|
151
159
|
)
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
160
|
+
|
|
161
|
+
else: # Non-streaming path
|
|
162
|
+
logger.info(
|
|
163
|
+
f"Evaluating agent '{agent.name}' without streaming."
|
|
156
164
|
)
|
|
157
|
-
|
|
165
|
+
try:
|
|
166
|
+
# Ensure the call is awaited if the underlying task is async
|
|
167
|
+
result_obj = await agent_task.acall(**inputs)
|
|
168
|
+
result_dict, cost, lm_history = self._process_result(
|
|
169
|
+
result_obj, inputs
|
|
170
|
+
)
|
|
171
|
+
self._cost = cost
|
|
172
|
+
self._lm_history = lm_history
|
|
173
|
+
return self.filter_thought_process(
|
|
174
|
+
result_dict, self.config.include_thought_process
|
|
175
|
+
)
|
|
176
|
+
except Exception as e:
|
|
177
|
+
logger.error(
|
|
178
|
+
f"Error during non-streaming evaluation for agent '{agent.name}': {e}",
|
|
179
|
+
exc_info=True,
|
|
180
|
+
)
|
|
181
|
+
raise RuntimeError(f"Evaluation failed: {e}") from e
|
|
158
182
|
|
|
159
183
|
def filter_thought_process(
|
|
160
184
|
self, result_dict: dict[str, Any], include_thought_process: bool
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flock-core
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.508
|
|
4
4
|
Summary: Declarative LLM Orchestration at Scale
|
|
5
5
|
Author-email: Andre Ratzenberger <andre.ratzenberger@whiteduck.de>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -9,20 +9,15 @@ Classifier: Operating System :: OS Independent
|
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Requires-Python: >=3.10
|
|
11
11
|
Requires-Dist: aiosqlite>=0.21.0
|
|
12
|
-
Requires-Dist: chromadb>=0.6.3
|
|
13
12
|
Requires-Dist: cloudpickle>=3.1.1
|
|
14
|
-
Requires-Dist: datasets>=3.2.0
|
|
15
13
|
Requires-Dist: devtools>=0.12.2
|
|
16
14
|
Requires-Dist: dspy==2.6.23
|
|
17
15
|
Requires-Dist: fastapi>=0.115.8
|
|
18
16
|
Requires-Dist: httpx>=0.28.1
|
|
19
|
-
Requires-Dist: inspect-ai>=0.3.88
|
|
20
17
|
Requires-Dist: litellm==1.69.3
|
|
21
18
|
Requires-Dist: loguru>=0.7.3
|
|
22
19
|
Requires-Dist: markdown2>=2.5.3
|
|
23
|
-
Requires-Dist: matplotlib>=3.10.0
|
|
24
20
|
Requires-Dist: mcp>=1.7.1
|
|
25
|
-
Requires-Dist: mem0ai[graph]>=0.1.101
|
|
26
21
|
Requires-Dist: msgpack>=1.1.0
|
|
27
22
|
Requires-Dist: openai==1.75.0
|
|
28
23
|
Requires-Dist: opentelemetry-api>=1.30.0
|
|
@@ -31,6 +26,7 @@ Requires-Dist: opentelemetry-exporter-jaeger>=1.21.0
|
|
|
31
26
|
Requires-Dist: opentelemetry-exporter-otlp>=1.30.0
|
|
32
27
|
Requires-Dist: opentelemetry-instrumentation-logging>=0.51b0
|
|
33
28
|
Requires-Dist: opentelemetry-sdk>=1.30.0
|
|
29
|
+
Requires-Dist: opik>=1.7.26
|
|
34
30
|
Requires-Dist: pandas>=2.2.3
|
|
35
31
|
Requires-Dist: pillow>=10.4.0
|
|
36
32
|
Requires-Dist: prometheus-client>=0.21.1
|
|
@@ -40,12 +36,9 @@ Requires-Dist: pydantic==2.10.5
|
|
|
40
36
|
Requires-Dist: python-box>=7.3.2
|
|
41
37
|
Requires-Dist: python-decouple>=3.8
|
|
42
38
|
Requires-Dist: python-dotenv>=1.0.1
|
|
43
|
-
Requires-Dist: python-fasthtml>=0.12.6
|
|
44
39
|
Requires-Dist: pyyaml>=6.0
|
|
45
40
|
Requires-Dist: questionary>=2.1.0
|
|
46
41
|
Requires-Dist: rich>=13.9.4
|
|
47
|
-
Requires-Dist: rouge-score>=0.1.2
|
|
48
|
-
Requires-Dist: sentence-transformers>=3.4.1
|
|
49
42
|
Requires-Dist: temporalio>=1.9.0
|
|
50
43
|
Requires-Dist: thefuzz>=0.22.1
|
|
51
44
|
Requires-Dist: tiktoken>=0.8.0
|
|
@@ -53,7 +46,23 @@ Requires-Dist: toml>=0.10.2
|
|
|
53
46
|
Requires-Dist: tqdm>=4.67.1
|
|
54
47
|
Requires-Dist: uvicorn>=0.34.0
|
|
55
48
|
Requires-Dist: wd-di>=0.2.14
|
|
56
|
-
Requires-Dist:
|
|
49
|
+
Requires-Dist: websockets>=15.0.1
|
|
50
|
+
Provides-Extra: all
|
|
51
|
+
Requires-Dist: azure-identity>=1.23.0; extra == 'all'
|
|
52
|
+
Requires-Dist: azure-search-documents>=11.5.2; extra == 'all'
|
|
53
|
+
Requires-Dist: azure-storage-blob>=12.25.1; extra == 'all'
|
|
54
|
+
Requires-Dist: chromadb>=0.6.3; extra == 'all'
|
|
55
|
+
Requires-Dist: datasets>=3.2.0; extra == 'all'
|
|
56
|
+
Requires-Dist: docling>=2.18.0; extra == 'all'
|
|
57
|
+
Requires-Dist: duckduckgo-search>=7.3.2; extra == 'all'
|
|
58
|
+
Requires-Dist: markdownify>=0.14.1; extra == 'all'
|
|
59
|
+
Requires-Dist: matplotlib>=3.10.0; extra == 'all'
|
|
60
|
+
Requires-Dist: mem0ai[graph]>=0.1.101; extra == 'all'
|
|
61
|
+
Requires-Dist: nltk>=3.9.1; extra == 'all'
|
|
62
|
+
Requires-Dist: rouge-score>=0.1.2; extra == 'all'
|
|
63
|
+
Requires-Dist: sentence-transformers>=3.4.1; extra == 'all'
|
|
64
|
+
Requires-Dist: tavily-python>=0.5.0; extra == 'all'
|
|
65
|
+
Requires-Dist: zep-python>=2.0.2; extra == 'all'
|
|
57
66
|
Provides-Extra: all-tools
|
|
58
67
|
Requires-Dist: azure-identity>=1.23.0; extra == 'all-tools'
|
|
59
68
|
Requires-Dist: azure-search-documents>=11.5.2; extra == 'all-tools'
|
|
@@ -72,8 +81,17 @@ Requires-Dist: docling>=2.18.0; extra == 'basic-tools'
|
|
|
72
81
|
Requires-Dist: duckduckgo-search>=7.3.2; extra == 'basic-tools'
|
|
73
82
|
Requires-Dist: markdownify>=0.14.1; extra == 'basic-tools'
|
|
74
83
|
Requires-Dist: tavily-python>=0.5.0; extra == 'basic-tools'
|
|
84
|
+
Provides-Extra: evaluation
|
|
85
|
+
Requires-Dist: datasets>=3.2.0; extra == 'evaluation'
|
|
86
|
+
Requires-Dist: rouge-score>=0.1.2; extra == 'evaluation'
|
|
87
|
+
Requires-Dist: sentence-transformers>=3.4.1; extra == 'evaluation'
|
|
75
88
|
Provides-Extra: llm-tools
|
|
76
89
|
Requires-Dist: nltk>=3.9.1; extra == 'llm-tools'
|
|
90
|
+
Provides-Extra: memory
|
|
91
|
+
Requires-Dist: chromadb>=0.6.3; extra == 'memory'
|
|
92
|
+
Requires-Dist: matplotlib>=3.10.0; extra == 'memory'
|
|
93
|
+
Requires-Dist: mem0ai[graph]>=0.1.101; extra == 'memory'
|
|
94
|
+
Requires-Dist: zep-python>=2.0.2; extra == 'memory'
|
|
77
95
|
Description-Content-Type: text/markdown
|
|
78
96
|
|
|
79
97
|
<p align="center">
|
|
@@ -26,10 +26,10 @@ flock/cli/view_results.py,sha256=dOzK0O1FHSIDERnx48y-2Xke9BkOHS7pcOhs64AyIg0,781
|
|
|
26
26
|
flock/cli/yaml_editor.py,sha256=K3N0bh61G1TSDAZDnurqW9e_-hO6CtSQKXQqlDhCjVo,12527
|
|
27
27
|
flock/cli/assets/release_notes.md,sha256=bqnk50jxM3w5uY44Dc7MkdT8XmRREFxrVBAG9XCOSSU,4896
|
|
28
28
|
flock/core/__init__.py,sha256=juwyNr3QqKXUS5-E3hlMYRhgqHgQBqgtP12OF3tUCAI,1249
|
|
29
|
-
flock/core/flock.py,sha256=
|
|
30
|
-
flock/core/flock_agent.py,sha256=
|
|
31
|
-
flock/core/flock_evaluator.py,sha256=
|
|
32
|
-
flock/core/flock_factory.py,sha256=
|
|
29
|
+
flock/core/flock.py,sha256=iR4i0_z0w2ns_iHbP7FqN--7wlsPIWch1H-BVecPs_I,38205
|
|
30
|
+
flock/core/flock_agent.py,sha256=EHI0p3axr8X364wfHMB2js16MQT7H1Awe6SzJQR7bhw,48573
|
|
31
|
+
flock/core/flock_evaluator.py,sha256=TPy6u6XX3cqkY1r9NW1w2lTwCMNW7pxhFYKLefnEbXg,1820
|
|
32
|
+
flock/core/flock_factory.py,sha256=36eOtha-XG67_kK_VadG7UQ8cMgAcd7y1k5yFkT-pR0,14017
|
|
33
33
|
flock/core/flock_module.py,sha256=ObILimpVaPnaaqYvcBYJJ20lQzfrjgTdADplaNRjHU0,7448
|
|
34
34
|
flock/core/flock_registry.py,sha256=KzdFfc3QC-Dk42G24hdf6Prp3HvGj9ymXR3TTBe-T-A,27161
|
|
35
35
|
flock/core/flock_router.py,sha256=1OAXDsdaIIFApEfo6SRfFEDoTuGt3Si7n2MXiySEfis,2644
|
|
@@ -42,13 +42,10 @@ flock/core/api/models.py,sha256=seqKuzhbN37nCNO7KrcJjI2mWuwiOKCLFcJcTPvTtag,3422
|
|
|
42
42
|
flock/core/api/run_store.py,sha256=bFodJvVyWogzoezVy0cOoWWU3MdEBXf_6_5sBqCRWps,9227
|
|
43
43
|
flock/core/api/runner.py,sha256=3izg6cVk1RoR1hDIDwMAO1gi3lnLcp8DPv7AnJBYx6A,1443
|
|
44
44
|
flock/core/api/service.py,sha256=HRHs4xt-bGeSm5hdN92H1vWQtLzqZalhZxIh6iwww8Y,11381
|
|
45
|
-
flock/core/api/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
|
-
flock/core/api/ui/routes.py,sha256=nS-wWO94mshE5ozWfOQZ-HOvtes_1qxDVcqpMZtU5JQ,8885
|
|
47
|
-
flock/core/api/ui/utils.py,sha256=V7PqYHNK519hFJ8jvvwf7bGpbBXCRz_HQG3BDCCqlNA,4802
|
|
48
45
|
flock/core/context/context.py,sha256=zdQuB1YWPJmQVv_2_sm1HK7FSnusa3Jl-83PcTuaLUk,7791
|
|
49
46
|
flock/core/context/context_manager.py,sha256=FANSWa6DEhdhtZ7t_9Gza0v80UdpoDOhHbfVOccmjkA,1181
|
|
50
47
|
flock/core/context/context_vars.py,sha256=ASPA29hpENWub4mgRoG62FtTVakCHQZfn6IhJQKe3C8,347
|
|
51
|
-
flock/core/evaluation/utils.py,sha256=
|
|
48
|
+
flock/core/evaluation/utils.py,sha256=S5M0uTFcClphZsR5EylEzrRNK-1434yImiGYL4pR_5o,15380
|
|
52
49
|
flock/core/execution/batch_executor.py,sha256=mHwCI-DHqApCv_EVCN0ZOUd-LCQLjREpxKbAUPC0pcY,15266
|
|
53
50
|
flock/core/execution/evaluation_executor.py,sha256=D9EO0sU-2qWj3vomjmUUi-DOtHNJNFRf30kGDHuzREE,17702
|
|
54
51
|
flock/core/execution/local_executor.py,sha256=rnIQvaJOs6zZORUcR3vvyS6LPREDJTjaygl_Db0M8ao,952
|
|
@@ -79,7 +76,7 @@ flock/core/mcp/types/handlers.py,sha256=mhAoSS6vA3K7YP_mF9Sb2Zn2RvFM8fXxtbwC4zgU
|
|
|
79
76
|
flock/core/mcp/types/types.py,sha256=NFVFv0BXy4P79SGe8rKBO4VH41xkpF6Y-yvU3Fmzx6w,4872
|
|
80
77
|
flock/core/mcp/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
81
78
|
flock/core/mcp/util/helpers.py,sha256=Xlf4iKW_lZxsVMTRoOnV29JsJfAppfmEJrb6sIcoCH4,636
|
|
82
|
-
flock/core/mixin/dspy_integration.py,sha256=
|
|
79
|
+
flock/core/mixin/dspy_integration.py,sha256=LQN4cfcG6Myi6kX0-2bKCuK1K_k_lu3SNaTdHHk3lEU,17745
|
|
83
80
|
flock/core/mixin/prompt_parser.py,sha256=eOqI-FK3y17gVqpc_y5GF-WmK1Jv8mFlkZxTcgweoxI,5121
|
|
84
81
|
flock/core/serialization/__init__.py,sha256=CML7fPgG6p4c0CDBlJ_uwV1aZZhJKK9uy3IoIHfO87w,431
|
|
85
82
|
flock/core/serialization/callable_registry.py,sha256=sUZECTZWsM3fJ8FDRQ-FgLNW9hF26nY17AD6fJKADMc,1419
|
|
@@ -96,7 +93,7 @@ flock/core/util/loader.py,sha256=j3q2qem5bFMP2SmMuYjb-ISxsNGNZd1baQmpvAnRUUk,224
|
|
|
96
93
|
flock/core/util/spliter.py,sha256=rDLnZX158PWkmW8vi2UfMLAMRXcHQFUIydAABd-lDGw,7154
|
|
97
94
|
flock/evaluators/__init__.py,sha256=Y0cEkx0dujRmy--TDpKoTqFSLzbyFz8BwEOv8kdSUhg,22
|
|
98
95
|
flock/evaluators/declarative/__init__.py,sha256=Y0cEkx0dujRmy--TDpKoTqFSLzbyFz8BwEOv8kdSUhg,22
|
|
99
|
-
flock/evaluators/declarative/declarative_evaluator.py,sha256=
|
|
96
|
+
flock/evaluators/declarative/declarative_evaluator.py,sha256=tulTpUOXhF-wMe5a9ULpsCiS1o2Z-DOXOUTqOSzVYqI,7397
|
|
100
97
|
flock/evaluators/memory/memory_evaluator.py,sha256=ySwz7kcc8suXMJ7gKNSWThW8iOMlE8lUcUzEAHvv8rw,3559
|
|
101
98
|
flock/evaluators/test/test_case_evaluator.py,sha256=3Emcoty0LOLLBIuPGxSpKphuZC9Fu1DTr1vbGg-hd0Q,1233
|
|
102
99
|
flock/evaluators/zep/zep_evaluator.py,sha256=6_5vTdU0yJAH8I8w3-MPXiAZx6iUPhAVCsHjrHzkPLM,2058
|
|
@@ -557,8 +554,8 @@ flock/workflow/agent_execution_activity.py,sha256=Gy6FtuVAjf0NiUXmC3syS2eJpNQF4R
|
|
|
557
554
|
flock/workflow/flock_workflow.py,sha256=iSUF_soFvWar0ffpkzE4irkDZRx0p4HnwmEBi_Ne2sY,9666
|
|
558
555
|
flock/workflow/temporal_config.py,sha256=3_8O7SDEjMsSMXsWJBfnb6XTp0TFaz39uyzSlMTSF_I,3988
|
|
559
556
|
flock/workflow/temporal_setup.py,sha256=YIHnSBntzOchHfMSh8hoLeNXrz3B1UbR14YrR6soM7A,1606
|
|
560
|
-
flock_core-0.4.
|
|
561
|
-
flock_core-0.4.
|
|
562
|
-
flock_core-0.4.
|
|
563
|
-
flock_core-0.4.
|
|
564
|
-
flock_core-0.4.
|
|
557
|
+
flock_core-0.4.508.dist-info/METADATA,sha256=_THooyyskEuH1CU8OfPv_CcHecZ1lEtSTFjeoOS5Q24,22584
|
|
558
|
+
flock_core-0.4.508.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
559
|
+
flock_core-0.4.508.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
|
|
560
|
+
flock_core-0.4.508.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
|
|
561
|
+
flock_core-0.4.508.dist-info/RECORD,,
|
flock/core/api/ui/__init__.py
DELETED
|
File without changes
|
flock/core/api/ui/routes.py
DELETED
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
# src/flock/core/api/ui/routes.py
|
|
2
|
-
"""FastHTML UI routes for the Flock API."""
|
|
3
|
-
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
5
|
-
|
|
6
|
-
# --- Conditional FastHTML Imports ---
|
|
7
|
-
try:
|
|
8
|
-
import httpx
|
|
9
|
-
from fasthtml.common import *
|
|
10
|
-
|
|
11
|
-
# Import Form explicitly with an alias to avoid collisions
|
|
12
|
-
from fasthtml.common import Form as FHForm
|
|
13
|
-
|
|
14
|
-
FASTHTML_AVAILABLE = True
|
|
15
|
-
except ImportError:
|
|
16
|
-
FASTHTML_AVAILABLE = False
|
|
17
|
-
|
|
18
|
-
# Define necessary dummies if not available
|
|
19
|
-
class Request:
|
|
20
|
-
pass
|
|
21
|
-
|
|
22
|
-
class Titled:
|
|
23
|
-
pass
|
|
24
|
-
|
|
25
|
-
class Div:
|
|
26
|
-
pass
|
|
27
|
-
|
|
28
|
-
class H1:
|
|
29
|
-
pass
|
|
30
|
-
|
|
31
|
-
class P:
|
|
32
|
-
pass
|
|
33
|
-
|
|
34
|
-
class H2:
|
|
35
|
-
pass
|
|
36
|
-
|
|
37
|
-
class Pre:
|
|
38
|
-
pass
|
|
39
|
-
|
|
40
|
-
class Code:
|
|
41
|
-
pass
|
|
42
|
-
|
|
43
|
-
class Label:
|
|
44
|
-
pass
|
|
45
|
-
|
|
46
|
-
class Select:
|
|
47
|
-
pass
|
|
48
|
-
|
|
49
|
-
class Option:
|
|
50
|
-
pass
|
|
51
|
-
|
|
52
|
-
class FHForm:
|
|
53
|
-
pass # Dummy alias if not available
|
|
54
|
-
|
|
55
|
-
class Button:
|
|
56
|
-
pass
|
|
57
|
-
|
|
58
|
-
class Span:
|
|
59
|
-
pass
|
|
60
|
-
|
|
61
|
-
class Script:
|
|
62
|
-
pass
|
|
63
|
-
|
|
64
|
-
class Style:
|
|
65
|
-
pass
|
|
66
|
-
|
|
67
|
-
class Hidden:
|
|
68
|
-
pass
|
|
69
|
-
|
|
70
|
-
class Textarea:
|
|
71
|
-
pass
|
|
72
|
-
|
|
73
|
-
class Input:
|
|
74
|
-
pass
|
|
75
|
-
|
|
76
|
-
def fast_app():
|
|
77
|
-
return None, None
|
|
78
|
-
|
|
79
|
-
def picolink():
|
|
80
|
-
return None
|
|
81
|
-
# ------------------------------------
|
|
82
|
-
|
|
83
|
-
# Use TYPE_CHECKING to avoid circular import errors for type hints
|
|
84
|
-
if TYPE_CHECKING:
|
|
85
|
-
from flock.core.api.main import FlockAPI
|
|
86
|
-
|
|
87
|
-
# Import logger and utils needed by UI routes
|
|
88
|
-
from flock.core.logging.logging import get_logger
|
|
89
|
-
|
|
90
|
-
logger = get_logger("api.ui")
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def create_ui_app(
|
|
94
|
-
flock_api_instance: "FlockAPI",
|
|
95
|
-
api_host: str,
|
|
96
|
-
api_port: int,
|
|
97
|
-
server_name: str,
|
|
98
|
-
) -> Any:
|
|
99
|
-
"""Creates and configures the FastHTML application and its routes."""
|
|
100
|
-
if not FASTHTML_AVAILABLE:
|
|
101
|
-
raise ImportError("FastHTML is not installed. Cannot create UI.")
|
|
102
|
-
logger.debug("Creating FastHTML application instance for UI")
|
|
103
|
-
|
|
104
|
-
# Use the passed FlockAPI instance to access necessary data/methods
|
|
105
|
-
flock_instance = flock_api_instance.flock
|
|
106
|
-
parse_input_spec_func = (
|
|
107
|
-
flock_api_instance._parse_input_spec
|
|
108
|
-
) # Get reference to parser
|
|
109
|
-
|
|
110
|
-
fh_app, fh_rt = fast_app(
|
|
111
|
-
hdrs=(
|
|
112
|
-
Script(src="https://unpkg.com/htmx.org@1.9.10/dist/htmx.min.js"),
|
|
113
|
-
picolink, # Pass directly
|
|
114
|
-
Style("""
|
|
115
|
-
body { padding: 20px; max-width: 800px; margin: auto; font-family: sans-serif; }
|
|
116
|
-
label { display: block; margin-top: 1rem; font-weight: bold;}
|
|
117
|
-
input, select, textarea { width: 100%; margin-top: 0.25rem; padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }
|
|
118
|
-
input[type=checkbox] { width: auto; margin-right: 0.5rem; vertical-align: middle; }
|
|
119
|
-
label[for^=input_] { font-weight: normal; display: inline; margin-top: 0;} /* Style for checkbox labels */
|
|
120
|
-
button[type=submit] { margin-top: 1.5rem; padding: 0.75rem 1.5rem; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 1rem;}
|
|
121
|
-
button[type=submit]:hover { background-color: #0056b3; }
|
|
122
|
-
#result-area { margin-top: 2rem; background-color: #f8f9fa; padding: 15px; border: 1px solid #dee2e6; border-radius: 5px; white-space: pre-wrap; word-wrap: break-word; font-family: monospace; }
|
|
123
|
-
.htmx-indicator { display: none; margin-left: 10px; font-style: italic; color: #6c757d; }
|
|
124
|
-
.htmx-request .htmx-indicator { display: inline; }
|
|
125
|
-
.htmx-request.htmx-indicator { display: inline; }
|
|
126
|
-
.error-message { color: #721c24; margin-top: 10px; font-weight: bold; background-color: #f8d7da; border: 1px solid #f5c6cb; padding: 10px; border-radius: 5px;}
|
|
127
|
-
"""),
|
|
128
|
-
)
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
@fh_rt("/get-agent-inputs")
|
|
132
|
-
def get_agent_inputs(request: Request):
|
|
133
|
-
"""Endpoint called by HTMX to get agent input fields."""
|
|
134
|
-
agent_name = request.query_params.get("agent_name")
|
|
135
|
-
logger.debug(f"UI requesting inputs for agent: {agent_name}")
|
|
136
|
-
if not agent_name:
|
|
137
|
-
return Div("Please select an agent.", cls="error-message")
|
|
138
|
-
|
|
139
|
-
# Access agents via the passed FlockAPI instance
|
|
140
|
-
agent_def = flock_instance.agents.get(agent_name)
|
|
141
|
-
if not agent_def:
|
|
142
|
-
logger.warning(f"Agent '{agent_name}' not found for UI.")
|
|
143
|
-
return Div(f"Agent '{agent_name}' not found.", cls="error-message")
|
|
144
|
-
|
|
145
|
-
# Use the parsing function from the FlockAPI instance
|
|
146
|
-
input_fields = parse_input_spec_func(agent_def.input or "")
|
|
147
|
-
logger.debug(f"Parsed input fields for {agent_name}: {input_fields}")
|
|
148
|
-
|
|
149
|
-
inputs_html = []
|
|
150
|
-
for field in input_fields:
|
|
151
|
-
field_id = f"input_{field['name']}"
|
|
152
|
-
label_text = f"{field['name']}"
|
|
153
|
-
if field["type"] != "bool":
|
|
154
|
-
label_text += f" ({field['type']})"
|
|
155
|
-
label = Label(label_text, fr=field_id)
|
|
156
|
-
input_attrs = dict(
|
|
157
|
-
id=field_id,
|
|
158
|
-
name=f"inputs.{field['name']}",
|
|
159
|
-
type=field["html_type"],
|
|
160
|
-
)
|
|
161
|
-
if field.get("step"):
|
|
162
|
-
input_attrs["step"] = field["step"]
|
|
163
|
-
if field.get("desc"):
|
|
164
|
-
input_attrs["placeholder"] = field["desc"]
|
|
165
|
-
if field.get("rows"):
|
|
166
|
-
input_attrs["rows"] = field["rows"]
|
|
167
|
-
|
|
168
|
-
if field["html_type"] == "textarea":
|
|
169
|
-
input_el = Textarea(**input_attrs)
|
|
170
|
-
elif field["html_type"] == "checkbox":
|
|
171
|
-
input_el = Div(
|
|
172
|
-
Input(**input_attrs, value="true"),
|
|
173
|
-
Label(f" Enable?", fr=field_id),
|
|
174
|
-
)
|
|
175
|
-
else:
|
|
176
|
-
input_el = Input(**input_attrs)
|
|
177
|
-
|
|
178
|
-
inputs_html.append(
|
|
179
|
-
Div(label, input_el, style="margin-bottom: 1rem;")
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
inputs_html.append(
|
|
183
|
-
Hidden(
|
|
184
|
-
id="selected_agent_name", name="agent_name", value=agent_name
|
|
185
|
-
)
|
|
186
|
-
)
|
|
187
|
-
return (
|
|
188
|
-
Div(*inputs_html)
|
|
189
|
-
if inputs_html
|
|
190
|
-
else P("This agent requires no input.")
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
@fh_rt("/")
|
|
194
|
-
async def ui_root(request: Request):
|
|
195
|
-
"""Serves the main UI page."""
|
|
196
|
-
logger.info("Serving main UI page /ui/")
|
|
197
|
-
agents_list = []
|
|
198
|
-
error_msg = None
|
|
199
|
-
api_url = f"http://{api_host}:{api_port}/agents"
|
|
200
|
-
try:
|
|
201
|
-
async with httpx.AsyncClient() as client:
|
|
202
|
-
logger.debug(f"UI fetching agents from {api_url}")
|
|
203
|
-
response = await client.get(api_url)
|
|
204
|
-
response.raise_for_status()
|
|
205
|
-
agent_data = response.json()
|
|
206
|
-
agents_list = agent_data.get("agents", [])
|
|
207
|
-
logger.debug(f"Fetched {len(agents_list)} agents for UI")
|
|
208
|
-
except Exception as e:
|
|
209
|
-
error_msg = f"UI Error: Could not fetch agent list from API at {api_url}. Details: {e}"
|
|
210
|
-
logger.error(error_msg, exc_info=True)
|
|
211
|
-
|
|
212
|
-
options = [
|
|
213
|
-
Option("-- Select Agent --", value="", selected=True, disabled=True)
|
|
214
|
-
] + [
|
|
215
|
-
Option(
|
|
216
|
-
f"{agent['name']}: {agent['description']}", value=agent["name"]
|
|
217
|
-
)
|
|
218
|
-
for agent in agents_list
|
|
219
|
-
]
|
|
220
|
-
|
|
221
|
-
# Use FHForm alias here
|
|
222
|
-
content = Div(
|
|
223
|
-
H2(f"Agent Runner"),
|
|
224
|
-
P(
|
|
225
|
-
"Select an agent, provide the required inputs, and click 'Run Flock'."
|
|
226
|
-
),
|
|
227
|
-
Label("Select Starting Agent:", fr="agent_select"),
|
|
228
|
-
Select(
|
|
229
|
-
*options,
|
|
230
|
-
id="agent_select",
|
|
231
|
-
name="agent_name",
|
|
232
|
-
hx_get="/ui/get-agent-inputs",
|
|
233
|
-
hx_trigger="change",
|
|
234
|
-
hx_target="#agent-inputs-container",
|
|
235
|
-
hx_indicator="#loading-indicator",
|
|
236
|
-
),
|
|
237
|
-
FHForm(
|
|
238
|
-
Div(id="agent-inputs-container", style="margin-top: 1rem;"),
|
|
239
|
-
Button("Run Flock", type="submit"),
|
|
240
|
-
Span(
|
|
241
|
-
" Processing...",
|
|
242
|
-
id="loading-indicator",
|
|
243
|
-
cls="htmx-indicator",
|
|
244
|
-
),
|
|
245
|
-
hx_post="/ui/run-agent-form", # Target the dedicated form endpoint
|
|
246
|
-
hx_target="#result-area",
|
|
247
|
-
hx_swap="innerHTML",
|
|
248
|
-
hx_indicator="#loading-indicator",
|
|
249
|
-
),
|
|
250
|
-
H2("Result"),
|
|
251
|
-
Div(
|
|
252
|
-
Pre(
|
|
253
|
-
Code(
|
|
254
|
-
"Result will appear here...",
|
|
255
|
-
id="result-content",
|
|
256
|
-
class_="language-json",
|
|
257
|
-
)
|
|
258
|
-
),
|
|
259
|
-
id="result-area",
|
|
260
|
-
style="min-height: 100px;",
|
|
261
|
-
),
|
|
262
|
-
)
|
|
263
|
-
|
|
264
|
-
if error_msg:
|
|
265
|
-
content = Div(
|
|
266
|
-
H1("Flock UI - Error"), P(error_msg, cls="error-message")
|
|
267
|
-
)
|
|
268
|
-
|
|
269
|
-
return Titled(f"{server_name}", content)
|
|
270
|
-
|
|
271
|
-
return fh_app
|