lionagi 0.2.4__py3-none-any.whl → 0.2.6__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.
- lionagi/core/collections/model.py +32 -0
- lionagi/core/engine/branch_engine.py +4 -1
- lionagi/core/generic/graph.py +4 -2
- lionagi/core/generic/node.py +2 -2
- lionagi/core/session/directive_mixin.py +29 -5
- lionagi/core/unit/unit.py +18 -2
- lionagi/core/unit/unit_mixin.py +10 -12
- lionagi/core/validator/validator.py +17 -4
- lionagi/core/work/work_edge.py +8 -6
- lionagi/core/work/work_function.py +13 -6
- lionagi/core/work/work_function_node.py +19 -8
- lionagi/core/work/work_queue.py +4 -4
- lionagi/core/work/work_task.py +14 -24
- lionagi/core/work/worker.py +66 -39
- lionagi/core/work/worker_engine.py +38 -13
- lionagi/integrations/config/oai_configs.py +1 -1
- lionagi/integrations/provider/litellm.py +3 -4
- lionagi/libs/ln_parse.py +2 -2
- lionagi/tests/api/aws/conftest.py +17 -20
- lionagi/tests/api/aws/test_aws_s3.py +4 -5
- lionagi/tests/test_core/generic/test_structure.py +2 -2
- lionagi/tests/test_core/graph/test_graph.py +1 -1
- lionagi/tests/test_core/graph/test_tree.py +1 -1
- lionagi/tests/test_core/mail/test_mail.py +4 -5
- lionagi/tests/test_core/test_structure/test_base_structure.py +1 -1
- lionagi/tests/test_core/test_structure/test_graph.py +1 -1
- lionagi/tests/test_core/test_structure/test_tree.py +1 -1
- lionagi/version.py +1 -1
- {lionagi-0.2.4.dist-info → lionagi-0.2.6.dist-info}/METADATA +2 -2
- {lionagi-0.2.4.dist-info → lionagi-0.2.6.dist-info}/RECORD +33 -33
- {lionagi-0.2.4.dist-info → lionagi-0.2.6.dist-info}/WHEEL +1 -1
- {lionagi-0.2.4.dist-info → lionagi-0.2.6.dist-info}/LICENSE +0 -0
- {lionagi-0.2.4.dist-info → lionagi-0.2.6.dist-info}/top_level.txt +0 -0
| @@ -322,6 +322,38 @@ class iModel: | |
| 322 322 | 
             
                    node.add_field("embedding", embed["data"][0]["embedding"])
         | 
| 323 323 | 
             
                    node._meta_insert("embedding_meta", payload)
         | 
| 324 324 |  | 
| 325 | 
            +
                async def format_structure(
         | 
| 326 | 
            +
                    self,
         | 
| 327 | 
            +
                    data: str | dict,
         | 
| 328 | 
            +
                    json_schema: dict | str = None,
         | 
| 329 | 
            +
                    request_fields: dict | list = None,
         | 
| 330 | 
            +
                    **kwargs,
         | 
| 331 | 
            +
                ) -> dict:
         | 
| 332 | 
            +
                    if json_schema:
         | 
| 333 | 
            +
                        kwargs["response_format"] = {
         | 
| 334 | 
            +
                            "type": "json_schema",
         | 
| 335 | 
            +
                            "json_schema": json_schema,
         | 
| 336 | 
            +
                        }
         | 
| 337 | 
            +
                        kwargs["model"] = kwargs.pop("model", "gpt-4o-mini")
         | 
| 338 | 
            +
                    if not request_fields and not json_schema:
         | 
| 339 | 
            +
                        raise ValueError("Either request_fields or json_schema must be provided")
         | 
| 340 | 
            +
                    request_fields = request_fields or json_schema["properties"]
         | 
| 341 | 
            +
             | 
| 342 | 
            +
                    messages = [
         | 
| 343 | 
            +
                        {
         | 
| 344 | 
            +
                            "role": "system",
         | 
| 345 | 
            +
                            "content": "You are a helpful json formatting assistant.",
         | 
| 346 | 
            +
                        },
         | 
| 347 | 
            +
                        {
         | 
| 348 | 
            +
                            "role": "user",
         | 
| 349 | 
            +
                            "content": f"can you please format the given data into given json schema?"
         | 
| 350 | 
            +
                            f"--- data --- {data} |||| ----json fields required --- {request_fields}",
         | 
| 351 | 
            +
                        },
         | 
| 352 | 
            +
                    ]
         | 
| 353 | 
            +
             | 
| 354 | 
            +
                    result = await self.call_chat_completion(messages, **kwargs)
         | 
| 355 | 
            +
                    return result["choices"][0]["message"]["content"]
         | 
| 356 | 
            +
             | 
| 325 357 | 
             
                def to_dict(self):
         | 
| 326 358 | 
             
                    """
         | 
| 327 359 | 
             
                    Converts the model instance to a dictionary representation.
         | 
| @@ -57,7 +57,10 @@ class BranchExecutor(Branch, BaseExecutor): | |
| 57 57 | 
             
                                await self._process_condition(mail)
         | 
| 58 58 | 
             
                            elif mail.category == "end":
         | 
| 59 59 | 
             
                                self._process_end(mail)
         | 
| 60 | 
            -
                        if  | 
| 60 | 
            +
                        if (
         | 
| 61 | 
            +
                            key in self.mailbox.pending_ins
         | 
| 62 | 
            +
                            and self.mailbox.pending_ins.get(key, Pile()).size() == 0
         | 
| 63 | 
            +
                        ):
         | 
| 61 64 | 
             
                            self.mailbox.pending_ins.pop(key)
         | 
| 62 65 |  | 
| 63 66 | 
             
                async def execute(self, refresh_time=1) -> None:
         | 
    
        lionagi/core/generic/graph.py
    CHANGED
    
    | @@ -202,7 +202,9 @@ class Graph(Node): | |
| 202 202 |  | 
| 203 203 | 
             
                    return g
         | 
| 204 204 |  | 
| 205 | 
            -
                def display( | 
| 205 | 
            +
                def display(
         | 
| 206 | 
            +
                    self, node_label="class_name", edge_label="label", draw_kwargs={}, **kwargs
         | 
| 207 | 
            +
                ):
         | 
| 206 208 | 
             
                    """Display the graph using NetworkX and Matplotlib."""
         | 
| 207 209 | 
             
                    from lionagi.libs import SysUtil
         | 
| 208 210 |  | 
| @@ -224,7 +226,7 @@ class Graph(Node): | |
| 224 226 | 
             
                        node_color="orange",
         | 
| 225 227 | 
             
                        alpha=0.9,
         | 
| 226 228 | 
             
                        labels=nx.get_node_attributes(g, node_label),
         | 
| 227 | 
            -
                        **draw_kwargs
         | 
| 229 | 
            +
                        **draw_kwargs,
         | 
| 228 230 | 
             
                    )
         | 
| 229 231 |  | 
| 230 232 | 
             
                    labels = nx.get_edge_attributes(g, edge_label)
         | 
    
        lionagi/core/generic/node.py
    CHANGED
    
    | @@ -124,7 +124,7 @@ class Node(Component, Relatable): | |
| 124 124 | 
             
                    label: str | None = None,
         | 
| 125 125 | 
             
                    bundle: bool = False,
         | 
| 126 126 | 
             
                    edge_class: Callable = Edge,
         | 
| 127 | 
            -
                    **kwargs
         | 
| 127 | 
            +
                    **kwargs,
         | 
| 128 128 | 
             
                ) -> None:
         | 
| 129 129 | 
             
                    """
         | 
| 130 130 | 
             
                    Establish directed relationship from this node to another.
         | 
| @@ -150,7 +150,7 @@ class Node(Component, Relatable): | |
| 150 150 | 
             
                        condition=condition,
         | 
| 151 151 | 
             
                        bundle=bundle,
         | 
| 152 152 | 
             
                        label=label,
         | 
| 153 | 
            -
                        **kwargs
         | 
| 153 | 
            +
                        **kwargs,
         | 
| 154 154 | 
             
                    )
         | 
| 155 155 |  | 
| 156 156 | 
             
                    self.relations[direction].include(edge)
         | 
| @@ -51,6 +51,10 @@ class DirectiveMixin: | |
| 51 51 | 
             
                    return_branch=False,
         | 
| 52 52 | 
             
                    images=None,
         | 
| 53 53 | 
             
                    image_path=None,
         | 
| 54 | 
            +
                    template=None,
         | 
| 55 | 
            +
                    verbose=True,
         | 
| 56 | 
            +
                    formatter=None,
         | 
| 57 | 
            +
                    format_kwargs=None,
         | 
| 54 58 | 
             
                    **kwargs,
         | 
| 55 59 | 
             
                ):
         | 
| 56 60 | 
             
                    """
         | 
| @@ -114,7 +118,15 @@ class DirectiveMixin: | |
| 114 118 | 
             
                        >>> print(result)
         | 
| 115 119 | 
             
                    """
         | 
| 116 120 |  | 
| 117 | 
            -
                    directive = Unit( | 
| 121 | 
            +
                    directive = Unit(
         | 
| 122 | 
            +
                        self,
         | 
| 123 | 
            +
                        imodel=imodel,
         | 
| 124 | 
            +
                        rulebook=rulebook,
         | 
| 125 | 
            +
                        template=template,
         | 
| 126 | 
            +
                        verbose=verbose,
         | 
| 127 | 
            +
                        formatter=formatter,
         | 
| 128 | 
            +
                        format_kwargs=format_kwargs,
         | 
| 129 | 
            +
                    )
         | 
| 118 130 | 
             
                    if system:
         | 
| 119 131 | 
             
                        self.add_message(system=system)
         | 
| 120 132 |  | 
| @@ -174,7 +186,10 @@ class DirectiveMixin: | |
| 174 186 | 
             
                    directive=None,
         | 
| 175 187 | 
             
                    images=None,
         | 
| 176 188 | 
             
                    image_path=None,
         | 
| 177 | 
            -
                     | 
| 189 | 
            +
                    template=None,
         | 
| 190 | 
            +
                    verbose=True,
         | 
| 191 | 
            +
                    formatter=None,
         | 
| 192 | 
            +
                    format_kwargs=None,
         | 
| 178 193 | 
             
                    **kwargs,
         | 
| 179 194 | 
             
                ):
         | 
| 180 195 | 
             
                    """
         | 
| @@ -220,7 +235,14 @@ class DirectiveMixin: | |
| 220 235 |  | 
| 221 236 | 
             
                        images = ImageUtil.read_image_to_base64(image_path)
         | 
| 222 237 |  | 
| 223 | 
            -
                    _directive = Unit( | 
| 238 | 
            +
                    _directive = Unit(
         | 
| 239 | 
            +
                        self,
         | 
| 240 | 
            +
                        imodel=imodel,
         | 
| 241 | 
            +
                        rulebook=rulebook,
         | 
| 242 | 
            +
                        verbose=verbose,
         | 
| 243 | 
            +
                        formatter=formatter,
         | 
| 244 | 
            +
                        format_kwargs=format_kwargs,
         | 
| 245 | 
            +
                    )
         | 
| 224 246 |  | 
| 225 247 | 
             
                    idx = len(self.progress)
         | 
| 226 248 | 
             
                    if directive and isinstance(directive, str):
         | 
| @@ -232,6 +254,7 @@ class DirectiveMixin: | |
| 232 254 | 
             
                            reason=reason,
         | 
| 233 255 | 
             
                            confidence=confidence,
         | 
| 234 256 | 
             
                            images=images,
         | 
| 257 | 
            +
                            template=template,
         | 
| 235 258 | 
             
                            **kwargs,
         | 
| 236 259 | 
             
                        )
         | 
| 237 260 |  | 
| @@ -248,7 +271,7 @@ class DirectiveMixin: | |
| 248 271 | 
             
                            form.action_response.update(_dict)
         | 
| 249 272 |  | 
| 250 273 | 
             
                        return form
         | 
| 251 | 
            -
             | 
| 274 | 
            +
             | 
| 252 275 | 
             
                    form = await _directive.direct(
         | 
| 253 276 | 
             
                        instruction=instruction,
         | 
| 254 277 | 
             
                        context=context,
         | 
| @@ -269,6 +292,7 @@ class DirectiveMixin: | |
| 269 292 | 
             
                        plan_num_step=plan_num_step,
         | 
| 270 293 | 
             
                        predict_num_sentences=predict_num_sentences,
         | 
| 271 294 | 
             
                        images=images,
         | 
| 295 | 
            +
                        template=template,
         | 
| 272 296 | 
             
                        **kwargs,
         | 
| 273 297 | 
             
                    )
         | 
| 274 298 |  | 
| @@ -283,5 +307,5 @@ class DirectiveMixin: | |
| 283 307 | 
             
                        if not hasattr(form, "action_response"):
         | 
| 284 308 | 
             
                            form.append_to_request("action_response", {})
         | 
| 285 309 | 
             
                        form.action_response.update(_dict)
         | 
| 286 | 
            -
             | 
| 310 | 
            +
             | 
| 287 311 | 
             
                    return form
         | 
    
        lionagi/core/unit/unit.py
    CHANGED
    
    | @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and | |
| 14 14 | 
             
            limitations under the License.
         | 
| 15 15 | 
             
            """
         | 
| 16 16 |  | 
| 17 | 
            +
            from typing import Callable
         | 
| 17 18 | 
             
            from lionagi.libs.ln_convert import strip_lower
         | 
| 18 19 | 
             
            from lionagi.libs.ln_func_call import rcall
         | 
| 19 20 | 
             
            from lionagi.core.collections.abc import Directive
         | 
| @@ -40,7 +41,14 @@ class Unit(Directive, DirectiveMixin): | |
| 40 41 | 
             
                default_template = UnitForm
         | 
| 41 42 |  | 
| 42 43 | 
             
                def __init__(
         | 
| 43 | 
            -
                    self, | 
| 44 | 
            +
                    self,
         | 
| 45 | 
            +
                    branch,
         | 
| 46 | 
            +
                    imodel: iModel = None,
         | 
| 47 | 
            +
                    template=None,
         | 
| 48 | 
            +
                    rulebook=None,
         | 
| 49 | 
            +
                    verbose=False,
         | 
| 50 | 
            +
                    formatter: Callable = None,
         | 
| 51 | 
            +
                    format_kwargs: dict = {},
         | 
| 44 52 | 
             
                ) -> None:
         | 
| 45 53 | 
             
                    self.branch = branch
         | 
| 46 54 | 
             
                    if imodel and isinstance(imodel, iModel):
         | 
| @@ -49,7 +57,11 @@ class Unit(Directive, DirectiveMixin): | |
| 49 57 | 
             
                    else:
         | 
| 50 58 | 
             
                        self.imodel = branch.imodel
         | 
| 51 59 | 
             
                    self.form_template = template or self.default_template
         | 
| 52 | 
            -
                     | 
| 60 | 
            +
                    rule_config = {"formatter": formatter, "format_kwargs": format_kwargs}
         | 
| 61 | 
            +
                    if rulebook:
         | 
| 62 | 
            +
                        rule_config["rulebook"] = rulebook
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    self.validator = Validator(**rule_config)
         | 
| 53 65 | 
             
                    self.verbose = verbose
         | 
| 54 66 |  | 
| 55 67 | 
             
                async def chat(
         | 
| @@ -71,6 +83,8 @@ class Unit(Directive, DirectiveMixin): | |
| 71 83 | 
             
                    clear_messages=False,
         | 
| 72 84 | 
             
                    use_annotation=True,
         | 
| 73 85 | 
             
                    return_branch=False,
         | 
| 86 | 
            +
                    formatter=None,
         | 
| 87 | 
            +
                    format_kwargs={},
         | 
| 74 88 | 
             
                    **kwargs,
         | 
| 75 89 | 
             
                ):
         | 
| 76 90 | 
             
                    """
         | 
| @@ -119,6 +133,8 @@ class Unit(Directive, DirectiveMixin): | |
| 119 133 | 
             
                        clear_messages=clear_messages,
         | 
| 120 134 | 
             
                        use_annotation=use_annotation,
         | 
| 121 135 | 
             
                        return_branch=return_branch,
         | 
| 136 | 
            +
                        formatter=formatter,
         | 
| 137 | 
            +
                        format_kwargs=format_kwargs,
         | 
| 122 138 | 
             
                        **kwargs,
         | 
| 123 139 | 
             
                    )
         | 
| 124 140 |  | 
    
        lionagi/core/unit/unit_mixin.py
    CHANGED
    
    | @@ -257,7 +257,6 @@ class DirectiveMixin(ABC): | |
| 257 257 | 
             
                    form: Form = None,
         | 
| 258 258 | 
             
                    return_form: bool = True,
         | 
| 259 259 | 
             
                    strict: bool = False,
         | 
| 260 | 
            -
                    rulebook: Any = None,
         | 
| 261 260 | 
             
                    use_annotation: bool = True,
         | 
| 262 261 | 
             
                    template_name: str = None,
         | 
| 263 262 | 
             
                    costs=None,
         | 
| @@ -274,7 +273,6 @@ class DirectiveMixin(ABC): | |
| 274 273 | 
             
                        form: Form data.
         | 
| 275 274 | 
             
                        return_form: Flag indicating if form should be returned.
         | 
| 276 275 | 
             
                        strict: Flag indicating if strict validation should be applied.
         | 
| 277 | 
            -
                        rulebook: Rulebook instance for validation.
         | 
| 278 276 | 
             
                        use_annotation: Flag indicating if annotations should be used.
         | 
| 279 277 | 
             
                        template_name: Template name for form.
         | 
| 280 278 |  | 
| @@ -295,8 +293,7 @@ class DirectiveMixin(ABC): | |
| 295 293 | 
             
                    response_ = self._process_model_response(_msg, requested_fields)
         | 
| 296 294 |  | 
| 297 295 | 
             
                    if form:
         | 
| 298 | 
            -
                         | 
| 299 | 
            -
                        form = await validator.validate_response(
         | 
| 296 | 
            +
                        form = await self.validator.validate_response(
         | 
| 300 297 | 
             
                            form=form,
         | 
| 301 298 | 
             
                            response=response_,
         | 
| 302 299 | 
             
                            strict=strict,
         | 
| @@ -332,7 +329,6 @@ class DirectiveMixin(ABC): | |
| 332 329 | 
             
                    invoke_tool: bool = True,
         | 
| 333 330 | 
             
                    return_form: bool = True,
         | 
| 334 331 | 
             
                    strict: bool = False,
         | 
| 335 | 
            -
                    rulebook: Any = None,
         | 
| 336 332 | 
             
                    imodel: Any = None,
         | 
| 337 333 | 
             
                    use_annotation: bool = True,
         | 
| 338 334 | 
             
                    branch: Any = None,
         | 
| @@ -356,7 +352,6 @@ class DirectiveMixin(ABC): | |
| 356 352 | 
             
                        invoke_tool: Flag indicating if tools should be invoked.
         | 
| 357 353 | 
             
                        return_form: Flag indicating if form should be returned.
         | 
| 358 354 | 
             
                        strict: Flag indicating if strict validation should be applied.
         | 
| 359 | 
            -
                        rulebook: Rulebook instance for validation.
         | 
| 360 355 | 
             
                        imodel: Model instance.
         | 
| 361 356 | 
             
                        use_annotation: Flag indicating if annotations should be used.
         | 
| 362 357 | 
             
                        branch: Branch instance.
         | 
| @@ -400,9 +395,8 @@ class DirectiveMixin(ABC): | |
| 400 395 | 
             
                        form=form,
         | 
| 401 396 | 
             
                        return_form=return_form,
         | 
| 402 397 | 
             
                        strict=strict,
         | 
| 403 | 
            -
                        rulebook=rulebook,
         | 
| 404 398 | 
             
                        use_annotation=use_annotation,
         | 
| 405 | 
            -
                        costs=imodel.costs,
         | 
| 399 | 
            +
                        costs=imodel.costs or (0, 0),
         | 
| 406 400 | 
             
                    )
         | 
| 407 401 |  | 
| 408 402 | 
             
                    return out_, branch if return_branch else out_
         | 
| @@ -421,13 +415,14 @@ class DirectiveMixin(ABC): | |
| 421 415 | 
             
                    invoke_tool=True,
         | 
| 422 416 | 
             
                    return_form=True,
         | 
| 423 417 | 
             
                    strict=False,
         | 
| 424 | 
            -
                    rulebook=None,
         | 
| 425 418 | 
             
                    imodel=None,
         | 
| 426 419 | 
             
                    images: Optional[str] = None,
         | 
| 427 420 | 
             
                    clear_messages=False,
         | 
| 428 421 | 
             
                    use_annotation=True,
         | 
| 429 422 | 
             
                    timeout: float = None,
         | 
| 430 423 | 
             
                    return_branch=False,
         | 
| 424 | 
            +
                    formatter=None,
         | 
| 425 | 
            +
                    format_kwargs={},
         | 
| 431 426 | 
             
                    **kwargs,
         | 
| 432 427 | 
             
                ):
         | 
| 433 428 | 
             
                    """
         | 
| @@ -470,13 +465,14 @@ class DirectiveMixin(ABC): | |
| 470 465 | 
             
                        invoke_tool=invoke_tool,
         | 
| 471 466 | 
             
                        return_form=return_form,
         | 
| 472 467 | 
             
                        strict=strict,
         | 
| 473 | 
            -
                        rulebook=rulebook,
         | 
| 474 468 | 
             
                        imodel=imodel,
         | 
| 475 469 | 
             
                        use_annotation=use_annotation,
         | 
| 476 470 | 
             
                        timeout=timeout,
         | 
| 477 471 | 
             
                        branch=branch,
         | 
| 478 472 | 
             
                        clear_messages=clear_messages,
         | 
| 479 473 | 
             
                        return_branch=return_branch,
         | 
| 474 | 
            +
                        formatter=formatter,
         | 
| 475 | 
            +
                        format_kwargs=format_kwargs,
         | 
| 480 476 | 
             
                        **kwargs,
         | 
| 481 477 | 
             
                    )
         | 
| 482 478 |  | 
| @@ -609,7 +605,9 @@ class DirectiveMixin(ABC): | |
| 609 605 | 
             
                    clear_messages=False,
         | 
| 610 606 | 
             
                    return_branch=False,
         | 
| 611 607 | 
             
                    images: Optional[str] = None,
         | 
| 612 | 
            -
                    verbose= | 
| 608 | 
            +
                    verbose=True,
         | 
| 609 | 
            +
                    formatter=None,
         | 
| 610 | 
            +
                    format_kwargs=None,
         | 
| 613 611 | 
             
                    **kwargs,
         | 
| 614 612 | 
             
                ):
         | 
| 615 613 | 
             
                    """
         | 
| @@ -658,7 +656,7 @@ class DirectiveMixin(ABC): | |
| 658 656 | 
             
                    if allow_action and not tools:
         | 
| 659 657 | 
             
                        tools = True
         | 
| 660 658 |  | 
| 661 | 
            -
                    tool_schema=None
         | 
| 659 | 
            +
                    tool_schema = None
         | 
| 662 660 | 
             
                    if tools:
         | 
| 663 661 | 
             
                        tool_schema = branch.tool_manager.get_tool_schema(tools)
         | 
| 664 662 |  | 
| @@ -14,10 +14,12 @@ See the License for the specific language governing permissions and | |
| 14 14 | 
             
            limitations under the License.
         | 
| 15 15 | 
             
            """
         | 
| 16 16 |  | 
| 17 | 
            -
             | 
| 17 | 
            +
            import asyncio
         | 
| 18 | 
            +
            from typing import Any, Dict, List, Union, Callable
         | 
| 18 19 | 
             
            from lionagi.libs import SysUtil
         | 
| 19 20 | 
             
            from lionagi.libs.ln_func_call import lcall
         | 
| 20 21 | 
             
            from lionagi.core.collections.abc import FieldError
         | 
| 22 | 
            +
            from lionagi.core.collections.model import iModel
         | 
| 21 23 | 
             
            from ..rule.base import Rule
         | 
| 22 24 | 
             
            from ..rule._default import DEFAULT_RULES
         | 
| 23 25 | 
             
            from ..rule.rulebook import RuleBook
         | 
| @@ -56,6 +58,8 @@ class Validator: | |
| 56 58 | 
             
                    order: List[str] = None,
         | 
| 57 59 | 
             
                    init_config: Dict[str, Dict] = None,
         | 
| 58 60 | 
             
                    active_rules: Dict[str, Rule] = None,
         | 
| 61 | 
            +
                    formatter: Callable = None,
         | 
| 62 | 
            +
                    format_kwargs: dict = {},
         | 
| 59 63 | 
             
                ):
         | 
| 60 64 | 
             
                    """
         | 
| 61 65 | 
             
                    Initialize the Validator.
         | 
| @@ -75,6 +79,8 @@ class Validator: | |
| 75 79 | 
             
                    )
         | 
| 76 80 | 
             
                    self.active_rules: Dict[str, Rule] = active_rules or self._initiate_rules()
         | 
| 77 81 | 
             
                    self.validation_log = []
         | 
| 82 | 
            +
                    self.formatter = formatter
         | 
| 83 | 
            +
                    self.format_kwargs = format_kwargs
         | 
| 78 84 |  | 
| 79 85 | 
             
                def _initiate_rules(self) -> Dict[str, Rule]:
         | 
| 80 86 | 
             
                    """
         | 
| @@ -207,9 +213,16 @@ class Validator: | |
| 207 213 | 
             
                        if len(form.requested_fields) == 1:
         | 
| 208 214 | 
             
                            response = {form.requested_fields[0]: response}
         | 
| 209 215 | 
             
                        else:
         | 
| 210 | 
            -
                             | 
| 211 | 
            -
                                 | 
| 212 | 
            -
             | 
| 216 | 
            +
                            if self.formatter:
         | 
| 217 | 
            +
                                if asyncio.iscoroutinefunction(self.formatter):
         | 
| 218 | 
            +
                                    response = await self.formatter(response, **self.format_kwargs)
         | 
| 219 | 
            +
                                    print("formatter used")
         | 
| 220 | 
            +
                                else:
         | 
| 221 | 
            +
                                    response = self.formatter(response, **self.format_kwargs)
         | 
| 222 | 
            +
                                    print("formatter used")
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                    if not isinstance(response, dict):
         | 
| 225 | 
            +
                        raise ValueError(f"The form response format is invalid for filling.")
         | 
| 213 226 |  | 
| 214 227 | 
             
                    dict_ = {}
         | 
| 215 228 | 
             
                    for k, v in response.items():
         | 
    
        lionagi/core/work/work_edge.py
    CHANGED
    
    | @@ -21,19 +21,19 @@ class WorkEdge(Edge, Progressable): | |
| 21 21 | 
             
                        other than "from_work" and "from_result".
         | 
| 22 22 | 
             
                    associated_worker (Worker): The worker to which this WorkEdge belongs.
         | 
| 23 23 | 
             
                """
         | 
| 24 | 
            +
             | 
| 24 25 | 
             
                convert_function: Callable = Field(
         | 
| 25 26 | 
             
                    ...,
         | 
| 26 | 
            -
                    description="Function to transform the result of the previous work into parameters for the next work."
         | 
| 27 | 
            +
                    description="Function to transform the result of the previous work into parameters for the next work.",
         | 
| 27 28 | 
             
                )
         | 
| 28 29 |  | 
| 29 30 | 
             
                convert_function_kwargs: dict = Field(
         | 
| 30 31 | 
             
                    {},
         | 
| 31 | 
            -
                    description= | 
| 32 | 
            +
                    description='parameters for the worklink function other than "from_work" and "from_result"',
         | 
| 32 33 | 
             
                )
         | 
| 33 34 |  | 
| 34 35 | 
             
                associated_worker: Worker = Field(
         | 
| 35 | 
            -
                    ...,
         | 
| 36 | 
            -
                    description="The worker to which this WorkEdge belongs."
         | 
| 36 | 
            +
                    ..., description="The worker to which this WorkEdge belongs."
         | 
| 37 37 | 
             
                )
         | 
| 38 38 |  | 
| 39 39 | 
             
                @field_validator("convert_function", mode="before")
         | 
| @@ -81,8 +81,10 @@ class WorkEdge(Edge, Progressable): | |
| 81 81 | 
             
                        StopIteration: If the task has no available steps left to proceed.
         | 
| 82 82 | 
             
                    """
         | 
| 83 83 | 
             
                    if task.available_steps == 0:
         | 
| 84 | 
            -
                        task.status_note = ( | 
| 85 | 
            -
             | 
| 84 | 
            +
                        task.status_note = (
         | 
| 85 | 
            +
                            "Task stopped proceeding further as all available steps have been used up, "
         | 
| 86 | 
            +
                            "but the task has not yet reached completion."
         | 
| 87 | 
            +
                        )
         | 
| 86 88 | 
             
                        return
         | 
| 87 89 | 
             
                    func_signature = inspect.signature(self.convert_function)
         | 
| 88 90 | 
             
                    kwargs = self.convert_function_kwargs.copy()
         | 
| @@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 13 13 | 
             
            See the License for the specific language governing permissions and
         | 
| 14 14 | 
             
            limitations under the License.
         | 
| 15 15 | 
             
            """
         | 
| 16 | 
            +
             | 
| 16 17 | 
             
            import asyncio
         | 
| 17 18 | 
             
            import logging
         | 
| 18 19 |  | 
| @@ -33,7 +34,13 @@ class WorkFunction: | |
| 33 34 | 
             
                """
         | 
| 34 35 |  | 
| 35 36 | 
             
                def __init__(
         | 
| 36 | 
            -
                    self, | 
| 37 | 
            +
                    self,
         | 
| 38 | 
            +
                    assignment,
         | 
| 39 | 
            +
                    function,
         | 
| 40 | 
            +
                    retry_kwargs=None,
         | 
| 41 | 
            +
                    guidance=None,
         | 
| 42 | 
            +
                    capacity=10,
         | 
| 43 | 
            +
                    refresh_time=1,
         | 
| 37 44 | 
             
                ):
         | 
| 38 45 | 
             
                    """
         | 
| 39 46 | 
             
                    Initializes a WorkFunction instance.
         | 
| @@ -69,11 +76,11 @@ class WorkFunction: | |
| 69 76 | 
             
                @property
         | 
| 70 77 | 
             
                def execution_mode(self):
         | 
| 71 78 | 
             
                    """
         | 
| 72 | 
            -
             | 
| 79 | 
            +
                    Gets the execution mode of the work function's queue.
         | 
| 73 80 |  | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 81 | 
            +
                    Returns:
         | 
| 82 | 
            +
                        bool: The execution mode of the work function's queue.
         | 
| 83 | 
            +
                    """
         | 
| 77 84 | 
             
                    return self.worklog.queue.execution_mode
         | 
| 78 85 |  | 
| 79 86 | 
             
                def is_progressable(self):
         | 
| @@ -121,4 +128,4 @@ class WorkFunction: | |
| 121 128 | 
             
                    """
         | 
| 122 129 | 
             
                    Stops the execution of the work function's queue.
         | 
| 123 130 | 
             
                    """
         | 
| 124 | 
            -
                    await self.worklog.stop()
         | 
| 131 | 
            +
                    await self.worklog.stop()
         | 
| @@ -21,7 +21,16 @@ class WorkFunctionNode(WorkFunction, Node): | |
| 21 21 | 
             
                    refresh_time (int): The time interval to refresh the work log queue.
         | 
| 22 22 | 
             
                """
         | 
| 23 23 |  | 
| 24 | 
            -
                def __init__( | 
| 24 | 
            +
                def __init__(
         | 
| 25 | 
            +
                    self,
         | 
| 26 | 
            +
                    assignment,
         | 
| 27 | 
            +
                    function,
         | 
| 28 | 
            +
                    retry_kwargs=None,
         | 
| 29 | 
            +
                    guidance=None,
         | 
| 30 | 
            +
                    capacity=10,
         | 
| 31 | 
            +
                    refresh_time=1,
         | 
| 32 | 
            +
                    **kwargs,
         | 
| 33 | 
            +
                ):
         | 
| 25 34 | 
             
                    """
         | 
| 26 35 | 
             
                    Initializes a WorkFunctionNode instance.
         | 
| 27 36 |  | 
| @@ -35,10 +44,12 @@ class WorkFunctionNode(WorkFunction, Node): | |
| 35 44 | 
             
                        **kwargs: Additional keyword arguments for the Node initialization.
         | 
| 36 45 | 
             
                    """
         | 
| 37 46 | 
             
                    Node.__init__(self, **kwargs)
         | 
| 38 | 
            -
                    WorkFunction.__init__( | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 47 | 
            +
                    WorkFunction.__init__(
         | 
| 48 | 
            +
                        self,
         | 
| 49 | 
            +
                        assignment=assignment,
         | 
| 50 | 
            +
                        function=function,
         | 
| 51 | 
            +
                        retry_kwargs=retry_kwargs,
         | 
| 52 | 
            +
                        guidance=guidance,
         | 
| 53 | 
            +
                        capacity=capacity,
         | 
| 54 | 
            +
                        refresh_time=refresh_time,
         | 
| 55 | 
            +
                    )
         | 
    
        lionagi/core/work/work_queue.py
    CHANGED
    
    | @@ -90,11 +90,11 @@ class WorkQueue: | |
| 90 90 |  | 
| 91 91 | 
             
                async def execute(self):
         | 
| 92 92 | 
             
                    """
         | 
| 93 | 
            -
             | 
| 93 | 
            +
                    Continuously executes the process method at a specified refresh interval.
         | 
| 94 94 |  | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 95 | 
            +
                    Args:
         | 
| 96 | 
            +
                        refresh_time (int, optional): The time in seconds to wait between
         | 
| 97 | 
            +
                            successive calls to `process`. Defaults to 1.
         | 
| 98 98 | 
             
                    """
         | 
| 99 99 | 
             
                    self.execution_mode = True
         | 
| 100 100 | 
             
                    self._stop_event.clear()
         | 
    
        lionagi/core/work/work_task.py
    CHANGED
    
    | @@ -20,39 +20,24 @@ class WorkTask(Component): | |
| 20 20 | 
             
                    current_work (Work | None): The current work in progress.
         | 
| 21 21 | 
             
                    post_processing (Callable | None): The post-processing function to be executed after the entire task is successfully completed.
         | 
| 22 22 | 
             
                """
         | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
                    description="Name of the task"
         | 
| 26 | 
            -
                )
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                name: str | None = Field(None, description="Name of the task")
         | 
| 27 25 |  | 
| 28 26 | 
             
                status: WorkStatus = Field(
         | 
| 29 | 
            -
                    WorkStatus.PENDING,
         | 
| 30 | 
            -
                    description="The current status of the task"
         | 
| 27 | 
            +
                    WorkStatus.PENDING, description="The current status of the task"
         | 
| 31 28 | 
             
                )
         | 
| 32 29 |  | 
| 33 | 
            -
                status_note: str = Field(
         | 
| 34 | 
            -
                    None,
         | 
| 35 | 
            -
                    description="Note for tasks current status"
         | 
| 36 | 
            -
                )
         | 
| 30 | 
            +
                status_note: str = Field(None, description="Note for tasks current status")
         | 
| 37 31 |  | 
| 38 | 
            -
                work_history: list[Work] = Field(
         | 
| 39 | 
            -
                    [],
         | 
| 40 | 
            -
                    description="List of works processed"
         | 
| 41 | 
            -
                )
         | 
| 32 | 
            +
                work_history: list[Work] = Field([], description="List of works processed")
         | 
| 42 33 |  | 
| 43 | 
            -
                max_steps: int | None = Field(
         | 
| 44 | 
            -
                    10,
         | 
| 45 | 
            -
                    description="Maximum number of works allowed"
         | 
| 46 | 
            -
                )
         | 
| 34 | 
            +
                max_steps: int | None = Field(10, description="Maximum number of works allowed")
         | 
| 47 35 |  | 
| 48 | 
            -
                current_work: Work | None = Field(
         | 
| 49 | 
            -
                    None,
         | 
| 50 | 
            -
                    description="The current work in progress"
         | 
| 51 | 
            -
                )
         | 
| 36 | 
            +
                current_work: Work | None = Field(None, description="The current work in progress")
         | 
| 52 37 |  | 
| 53 38 | 
             
                post_processing: Callable | None = Field(
         | 
| 54 39 | 
             
                    None,
         | 
| 55 | 
            -
                    description="The post-processing function to be executed after the entire task has been successfully completed."
         | 
| 40 | 
            +
                    description="The post-processing function to be executed after the entire task has been successfully completed.",
         | 
| 56 41 | 
             
                )
         | 
| 57 42 |  | 
| 58 43 | 
             
                @field_validator("max_steps", mode="before")
         | 
| @@ -108,7 +93,12 @@ class WorkTask(Component): | |
| 108 93 | 
             
                    Returns:
         | 
| 109 94 | 
             
                        WorkTask: A new instance of WorkTask with the same attributes.
         | 
| 110 95 | 
             
                    """
         | 
| 111 | 
            -
                    new_worktask = WorkTask( | 
| 96 | 
            +
                    new_worktask = WorkTask(
         | 
| 97 | 
            +
                        name=self.name,
         | 
| 98 | 
            +
                        status=self.status,
         | 
| 99 | 
            +
                        max_steps=self.max_steps,
         | 
| 100 | 
            +
                        current_work=self.current_work,
         | 
| 101 | 
            +
                    )
         | 
| 112 102 | 
             
                    for work in self.work_history:
         | 
| 113 103 | 
             
                        new_worktask.work_history.append(work)
         | 
| 114 104 | 
             
                    return new_worktask
         |