flock-core 0.4.0b11__py3-none-any.whl → 0.4.0b13__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.

@@ -37,6 +37,7 @@ class FlockFactory:
37
37
  no_output: bool = False,
38
38
  print_context: bool = False,
39
39
  write_to_file: bool = False,
40
+ stream: bool = False,
40
41
  ) -> FlockAgent:
41
42
  """Creates a default FlockAgent.
42
43
 
@@ -50,6 +51,7 @@ class FlockFactory:
50
51
  use_cache=use_cache,
51
52
  max_tokens=max_tokens,
52
53
  temperature=temperature,
54
+ stream=stream,
53
55
  )
54
56
 
55
57
  evaluator = DeclarativeEvaluator(name="default", config=eval_config)
@@ -145,6 +145,66 @@ class FlockSerializer:
145
145
  )
146
146
  )
147
147
 
148
+ # Description (Callables)
149
+ if agent_data.get("description_callable"):
150
+ logger.debug(
151
+ f"Adding description callable '{agent_data['description_callable']}' from agent '{name}'"
152
+ )
153
+ description_callable_name = agent_data[
154
+ "description_callable"
155
+ ]
156
+ description_callable = agent_instance.description
157
+ path_str = FlockRegistry.get_callable_path_string(
158
+ description_callable
159
+ )
160
+ if path_str:
161
+ logger.debug(
162
+ f"Adding description callable '{description_callable_name}' (from path '{path_str}') to components"
163
+ )
164
+ components[description_callable_name] = (
165
+ FlockSerializer._get_callable_definition(
166
+ path_str, description_callable_name, path_type
167
+ )
168
+ )
169
+
170
+ if agent_data.get("input_callable"):
171
+ logger.debug(
172
+ f"Adding input callable '{agent_data['input_callable']}' from agent '{name}'"
173
+ )
174
+ input_callable_name = agent_data["input_callable"]
175
+ input_callable = agent_instance.input
176
+ path_str = FlockRegistry.get_callable_path_string(
177
+ input_callable
178
+ )
179
+ if path_str:
180
+ logger.debug(
181
+ f"Adding input callable '{input_callable_name}' (from path '{path_str}') to components"
182
+ )
183
+ components[input_callable_name] = (
184
+ FlockSerializer._get_callable_definition(
185
+ path_str, input_callable_name, path_type
186
+ )
187
+ )
188
+
189
+ if agent_data.get("output_callable"):
190
+ logger.debug(
191
+ f"Adding output callable '{agent_data['output_callable']}' from agent '{name}'"
192
+ )
193
+ output_callable_name = agent_data["output_callable"]
194
+ output_callable = agent_instance.output
195
+ path_str = FlockRegistry.get_callable_path_string(
196
+ output_callable
197
+ )
198
+ if path_str:
199
+ logger.debug(
200
+ f"Adding output callable '{output_callable_name}' (from path '{path_str}') to components"
201
+ )
202
+ components[output_callable_name] = (
203
+ FlockSerializer._get_callable_definition(
204
+ path_str, output_callable_name, path_type
205
+ )
206
+ )
207
+
148
208
  # Tools (Callables)
149
209
  if agent_data.get("tools"):
150
210
  logger.debug(
@@ -1,12 +1,20 @@
1
+ from collections.abc import Generator
1
2
  from typing import Any
2
3
 
4
+ import dspy
3
5
  from pydantic import Field
6
+ from rich.console import Console
4
7
 
5
8
  from flock.core.flock_agent import FlockAgent
6
9
  from flock.core.flock_evaluator import FlockEvaluator, FlockEvaluatorConfig
10
+ from flock.core.logging.logging import get_logger
7
11
  from flock.core.mixin.dspy_integration import DSPyIntegrationMixin
8
12
  from flock.core.mixin.prompt_parser import PromptParserMixin
9
13
 
14
+ console = Console()
15
+
16
+ logger = get_logger("evaluators.declarative")
17
+
10
18
 
11
19
  class DeclarativeEvaluatorConfig(FlockEvaluatorConfig):
12
20
  """Configuration for the DeclarativeEvaluator."""
@@ -16,6 +24,10 @@ class DeclarativeEvaluatorConfig(FlockEvaluatorConfig):
16
24
  use_cache: bool = True
17
25
  temperature: float = 0.0
18
26
  max_tokens: int = 4096
27
+ stream: bool = Field(
28
+ default=False,
29
+ description="Enable streaming output from the underlying DSPy program.",
30
+ )
19
31
 
20
32
 
21
33
  class DeclarativeEvaluator(
@@ -31,24 +43,86 @@ class DeclarativeEvaluator(
31
43
  async def evaluate(
32
44
  self, agent: FlockAgent, inputs: dict[str, Any], tools: list[Any]
33
45
  ) -> dict[str, Any]:
34
- """Evaluate using DSPy."""
35
- _dspy_signature = self.create_dspy_signature_class(
36
- agent.name,
37
- agent.description,
38
- f"{agent.input} -> {agent.output}",
39
- )
40
- self._configure_language_model(
41
- model=self.config.model,
42
- use_cache=self.config.use_cache,
43
- temperature=self.config.temperature,
44
- max_tokens=self.config.max_tokens,
45
- )
46
- agent_task = self._select_task(
47
- _dspy_signature,
48
- agent_type_override=self.config.agent_type_override,
49
- tools=tools,
50
- )
51
- # Execute the task.
52
- result = agent_task(**inputs)
53
- result = self._process_result(result, inputs)
54
- return result
46
+ """Evaluate using DSPy, with optional asynchronous streaming."""
47
+ # --- Setup Signature and LM ---
48
+ try:
49
+ _dspy_signature = self.create_dspy_signature_class(
50
+ agent.name,
51
+ agent.description,
52
+ f"{agent.input} -> {agent.output}",
53
+ )
54
+ # --- Get output field names ---
55
+ # dspy.Signature holds fields in .output_fields attribute
56
+ output_field_names = list(_dspy_signature.output_fields.keys())
57
+ if not output_field_names:
58
+ logger.warning(
59
+ f"DSPy signature for agent '{agent.name}' has no defined output fields. Streaming might not produce text."
60
+ )
61
+ # -----------------------------
62
+
63
+ self._configure_language_model(
64
+ model=self.config.model or agent.model,
65
+ use_cache=self.config.use_cache,
66
+ temperature=self.config.temperature,
67
+ max_tokens=self.config.max_tokens,
68
+ )
69
+ agent_task = self._select_task(
70
+ _dspy_signature,
71
+ agent_type_override=self.config.agent_type_override,
72
+ tools=tools,
73
+ )
74
+ except Exception as setup_error:
75
+ logger.error(
76
+ f"Error setting up DSPy task for agent '{agent.name}': {setup_error}",
77
+ exc_info=True,
78
+ )
79
+ raise RuntimeError(
80
+ f"DSPy task setup failed: {setup_error}"
81
+ ) from setup_error
82
+
83
+ # --- Conditional Evaluation (Stream vs No Stream) ---
84
+ if self.config.stream:
85
+ logger.info(
86
+ f"Evaluating agent '{agent.name}' with async streaming."
87
+ )
88
+ if not callable(agent_task):
89
+ logger.error("agent_task is not callable, cannot stream.")
90
+ raise TypeError(
91
+ "DSPy task could not be created or is not callable."
92
+ )
93
+
94
+ streaming_task = dspy.streamify(agent_task)
95
+ stream_generator: Generator = streaming_task(**inputs)
96
+
97
+ console.print("\n")
98
+ async for chunk in stream_generator:
99
+ if (
100
+ hasattr(chunk, "choices")
101
+ and chunk.choices
102
+ and hasattr(chunk.choices[0], "delta")
103
+ and chunk.choices[0].delta
104
+ and hasattr(chunk.choices[0].delta, "content")
105
+ ):
106
+ delta_content = chunk.choices[0].delta.content
107
+
108
+ if delta_content:
109
+ console.print(delta_content, end="")
110
+
111
+ result_dict = self._process_result(chunk, inputs)
112
+
113
+ console.print("\n")
114
+ return result_dict
115
+
116
+ else: # Non-streaming path
117
+ logger.info(f"Evaluating agent '{agent.name}' without streaming.")
118
+ try:
119
+ # Ensure the call is awaited if the underlying task is async
120
+ result_obj = await agent_task(**inputs)
121
+ result_dict = self._process_result(result_obj, inputs)
122
+ return result_dict
123
+ except Exception as e:
124
+ logger.error(
125
+ f"Error during non-streaming evaluation for agent '{agent.name}': {e}",
126
+ exc_info=True,
127
+ )
128
+ raise RuntimeError(f"Evaluation failed: {e}") from e
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flock-core
3
- Version: 0.4.0b11
3
+ Version: 0.4.0b13
4
4
  Summary: Declarative LLM Orchestration at Scale
5
5
  Author-email: Andre Ratzenberger <andre.ratzenberger@whiteduck.de>
6
6
  License-File: LICENSE
@@ -21,7 +21,7 @@ flock/core/__init__.py,sha256=p7lmQULRu9ejIAELfanZiyMhW0CougIPvyFHW2nqBFQ,847
21
21
  flock/core/flock.py,sha256=zQUpITLx_CMhJRnft4AWQDfYj85FhUlT-Ank5c-fSko,25146
22
22
  flock/core/flock_agent.py,sha256=uFVr8eVWZ4uowH659fdOvVuBD4fx695Zm9UB9pOQKDU,32223
23
23
  flock/core/flock_evaluator.py,sha256=dOXZeDOGZcAmJ9ahqq_2bdGUU1VOXY4skmwTVpAjiVw,1685
24
- flock/core/flock_factory.py,sha256=MGTkJCP1WGpV614f87r1vwe0tqAvBCoH9PlqtqDyJDk,2828
24
+ flock/core/flock_factory.py,sha256=ym2ZIdDXzV_Ym5JdRUvFJRIkLIVCj017M6-AXQ7VkW8,2885
25
25
  flock/core/flock_module.py,sha256=96aFVYAgwpKN53xGbivQDUpikOYGFCxK5mqhclOcxY0,3003
26
26
  flock/core/flock_registry.py,sha256=ekYpQgSkZVnbyPbl8gA7nf54brt94rYZZBe2RwEGtUc,20828
27
27
  flock/core/flock_router.py,sha256=A5GaxcGvtiFlRLHBTW7okh5RDm3BdKam2uXvRHRaj7k,2187
@@ -59,7 +59,7 @@ flock/core/mixin/dspy_integration.py,sha256=vlf6rJnR9EsfZi5KyFLEXIbUvhpBhodctn-m
59
59
  flock/core/mixin/prompt_parser.py,sha256=eOqI-FK3y17gVqpc_y5GF-WmK1Jv8mFlkZxTcgweoxI,5121
60
60
  flock/core/serialization/__init__.py,sha256=CML7fPgG6p4c0CDBlJ_uwV1aZZhJKK9uy3IoIHfO87w,431
61
61
  flock/core/serialization/callable_registry.py,sha256=sUZECTZWsM3fJ8FDRQ-FgLNW9hF26nY17AD6fJKADMc,1419
62
- flock/core/serialization/flock_serializer.py,sha256=EcDpw-OdkDied80UMXnWYOU0A8PrTQlZ7JRNK2YQ9Tg,30041
62
+ flock/core/serialization/flock_serializer.py,sha256=TEePKaJqU-_XWHTMWyMHloDNwmkKyOUSfXoJ7ZVki8k,33048
63
63
  flock/core/serialization/json_encoder.py,sha256=gAKj2zU_8wQiNvdkby2hksSA4fbPNwTjup_yz1Le1Vw,1229
64
64
  flock/core/serialization/secure_serializer.py,sha256=n5-zRvvXddgJv1FFHsaQ2wuYdL3WUSGPvG_LGaffEJo,6144
65
65
  flock/core/serialization/serializable.py,sha256=qlv8TsTqRuklXiNuCMrvro5VKz764xC2i3FlgLJSkdk,12129
@@ -75,7 +75,7 @@ flock/core/util/file_path_utils.py,sha256=Odf7uU32C-x1KNighbNERSiMtkzW4h8laABIoF
75
75
  flock/core/util/hydrator.py,sha256=6qNwOwCZB7r6y25BZ--0PGofrAlfMaXbDKFQeP5NLts,11196
76
76
  flock/core/util/input_resolver.py,sha256=g9vDPdY4OH-G7qjas5ksGEHueokHGFPMoLOvC-ngeLo,5984
77
77
  flock/core/util/loader.py,sha256=j3q2qem5bFMP2SmMuYjb-ISxsNGNZd1baQmpvAnRUUk,2244
78
- flock/evaluators/declarative/declarative_evaluator.py,sha256=WZ74LG81JcuApG2KcTk8plh0fFqDhJjtl6ubW1K-fqc,1750
78
+ flock/evaluators/declarative/declarative_evaluator.py,sha256=kGhxkFJx8T0JXsr27rdqmB4nwq28yMDCOwPRJ-C2DOA,4778
79
79
  flock/evaluators/memory/azure_search_evaluator.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
80
  flock/evaluators/memory/memory_evaluator.py,sha256=SmerXyNaqm8DTV0yw-WqWkn9DXIf6x-nPG1eyTV6NY8,3452
81
81
  flock/evaluators/natural_language/natural_language_evaluator.py,sha256=6nVEeh8_uwv_h-d3FWlA0GbzDzRtdhvxCGKirHtyvOU,2012
@@ -439,8 +439,8 @@ flock/workflow/activities.py,sha256=eVZDnxGJl_quNO-UTV3YgvTV8LrRaHN3QDAA1ANKzac,
439
439
  flock/workflow/agent_activities.py,sha256=NhBZscflEf2IMfSRa_pBM_TRP7uVEF_O0ROvWZ33eDc,963
440
440
  flock/workflow/temporal_setup.py,sha256=VWBgmBgfTBjwM5ruS_dVpA5AVxx6EZ7oFPGw4j3m0l0,1091
441
441
  flock/workflow/workflow.py,sha256=I9MryXW_bqYVTHx-nl2epbTqeRy27CAWHHA7ZZA0nAk,1696
442
- flock_core-0.4.0b11.dist-info/METADATA,sha256=SBfnjjaedd-MZ5XRQCxC0Mgmm0k1uhVRWjZGGE-UDnY,21101
443
- flock_core-0.4.0b11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
444
- flock_core-0.4.0b11.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
445
- flock_core-0.4.0b11.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
446
- flock_core-0.4.0b11.dist-info/RECORD,,
442
+ flock_core-0.4.0b13.dist-info/METADATA,sha256=-oZxxLDqjStFoVTtT5Ss9sk-EFpgsyINBBBJYYq7i6I,21101
443
+ flock_core-0.4.0b13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
444
+ flock_core-0.4.0b13.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
445
+ flock_core-0.4.0b13.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
446
+ flock_core-0.4.0b13.dist-info/RECORD,,