operonx 0.6.2__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.
- operonx/__init__.py +131 -0
- operonx/core/__init__.py +100 -0
- operonx/core/configs/__init__.py +15 -0
- operonx/core/configs/edge_config.py +25 -0
- operonx/core/configs/op_config.py +34 -0
- operonx/core/engine.py +627 -0
- operonx/core/exceptions.py +387 -0
- operonx/core/loggings/__init__.py +224 -0
- operonx/core/loggings/config.py +83 -0
- operonx/core/loggings/events.py +165 -0
- operonx/core/loggings/formatters.py +114 -0
- operonx/core/loggings/handlers/__init__.py +28 -0
- operonx/core/loggings/handlers/console.py +180 -0
- operonx/core/loggings/handlers/file.py +101 -0
- operonx/core/loggings/log_templates.json +10 -0
- operonx/core/loggings/theme.py +27 -0
- operonx/core/media.py +197 -0
- operonx/core/middleware.py +74 -0
- operonx/core/ops/__init__.py +72 -0
- operonx/core/ops/_edges.py +167 -0
- operonx/core/ops/_params.py +174 -0
- operonx/core/ops/_shortcuts.py +93 -0
- operonx/core/ops/_utils.py +42 -0
- operonx/core/ops/base.py +886 -0
- operonx/core/ops/flow/__init__.py +14 -0
- operonx/core/ops/flow/branch_op.py +286 -0
- operonx/core/ops/graph/__init__.py +12 -0
- operonx/core/ops/graph/_decorators.py +215 -0
- operonx/core/ops/graph/graph_op.py +593 -0
- operonx/core/ops/graph/task_scheduler.py +436 -0
- operonx/core/ops/graph/validation.py +316 -0
- operonx/core/ops/transform/__init__.py +15 -0
- operonx/core/ops/transform/func_op.py +441 -0
- operonx/core/ops/transform/parser_op.py +309 -0
- operonx/core/registry/__init__.py +65 -0
- operonx/core/registry/config_registry.py +146 -0
- operonx/core/registry/errors.py +35 -0
- operonx/core/registry/resource_hub.py +558 -0
- operonx/core/registry/shortcuts/__init__.py +7 -0
- operonx/core/registry/shortcuts/health.py +38 -0
- operonx/core/registry/storage/__init__.py +11 -0
- operonx/core/registry/storage/base.py +73 -0
- operonx/core/registry/storage/json.py +114 -0
- operonx/core/registry/storage/yaml.py +305 -0
- operonx/core/states/__init__.py +35 -0
- operonx/core/states/cell.py +86 -0
- operonx/core/states/ref.py +628 -0
- operonx/core/states/schema.py +388 -0
- operonx/core/states/state.py +341 -0
- operonx/core/tracing/__init__.py +34 -0
- operonx/core/tracing/base.py +64 -0
- operonx/core/tracing/collector.py +707 -0
- operonx/core/tracing/flush_worker.py +202 -0
- operonx/core/tracing/labels.py +122 -0
- operonx/core/tracing/local.py +62 -0
- operonx/core/tracing/models.py +66 -0
- operonx/core/tracing/trace_filter.py +274 -0
- operonx/core/utils/__init__.py +36 -0
- operonx/core/utils/algo.py +290 -0
- operonx/core/utils/auto_name.py +204 -0
- operonx/core/utils/bimap.py +72 -0
- operonx/core/utils/common.py +137 -0
- operonx/core/utils/context.py +18 -0
- operonx/core/utils/yaml_model.py +85 -0
- operonx/providers/__init__.py +155 -0
- operonx/providers/_utils/__init__.py +1 -0
- operonx/providers/_utils/huggingface.py +50 -0
- operonx/providers/_utils/onnx.py +69 -0
- operonx/providers/auth/__init__.py +14 -0
- operonx/providers/auth/config.py +41 -0
- operonx/providers/auth/factory.py +16 -0
- operonx/providers/auth/keycloak.py +254 -0
- operonx/providers/embeddings/__init__.py +50 -0
- operonx/providers/embeddings/base.py +66 -0
- operonx/providers/embeddings/config.py +60 -0
- operonx/providers/embeddings/factory.py +61 -0
- operonx/providers/embeddings/huggingface.py +272 -0
- operonx/providers/embeddings/onnx.py +306 -0
- operonx/providers/embeddings/tei.py +184 -0
- operonx/providers/embeddings/vllm.py +183 -0
- operonx/providers/llms/__init__.py +64 -0
- operonx/providers/llms/anthropic.py +412 -0
- operonx/providers/llms/azure.py +234 -0
- operonx/providers/llms/base.py +446 -0
- operonx/providers/llms/batch_coordinator.py +280 -0
- operonx/providers/llms/config.py +212 -0
- operonx/providers/llms/factory.py +61 -0
- operonx/providers/llms/gemini.py +456 -0
- operonx/providers/llms/openai.py +677 -0
- operonx/providers/llms/response.py +203 -0
- operonx/providers/onnx/__init__.py +33 -0
- operonx/providers/onnx/backend.py +108 -0
- operonx/providers/onnx/config.py +25 -0
- operonx/providers/onnx/factory.py +21 -0
- operonx/providers/ops/__init__.py +43 -0
- operonx/providers/ops/_utils.py +12 -0
- operonx/providers/ops/chain.py +130 -0
- operonx/providers/ops/embedding.py +127 -0
- operonx/providers/ops/llm.py +648 -0
- operonx/providers/ops/onnx.py +114 -0
- operonx/providers/ops/prompt.py +289 -0
- operonx/providers/ops/rerank.py +190 -0
- operonx/providers/ops/triton.py +311 -0
- operonx/providers/registry/__init__.py +17 -0
- operonx/providers/registry/auth_plugin.py +29 -0
- operonx/providers/registry/embedding_plugin.py +29 -0
- operonx/providers/registry/llm_plugin.py +29 -0
- operonx/providers/registry/onnx_plugin.py +29 -0
- operonx/providers/registry/rerank_plugin.py +29 -0
- operonx/providers/rerankers/__init__.py +42 -0
- operonx/providers/rerankers/base.py +26 -0
- operonx/providers/rerankers/config.py +69 -0
- operonx/providers/rerankers/factory.py +67 -0
- operonx/providers/rerankers/huggingface.py +207 -0
- operonx/providers/rerankers/onnx.py +226 -0
- operonx/providers/rerankers/pinecone.py +247 -0
- operonx/providers/rerankers/tei.py +120 -0
- operonx/providers/rerankers/vllm.py +183 -0
- operonx/telemetry/__init__.py +53 -0
- operonx/telemetry/backends/__init__.py +27 -0
- operonx/telemetry/backends/langfuse/__init__.py +17 -0
- operonx/telemetry/backends/langfuse/client.py +243 -0
- operonx/telemetry/backends/langfuse/config.py +64 -0
- operonx/telemetry/backends/langfuse/prompt_manager.py +94 -0
- operonx/telemetry/backends/otel/__init__.py +29 -0
- operonx/telemetry/backends/otel/client.py +203 -0
- operonx/telemetry/backends/otel/config.py +139 -0
- operonx/telemetry/plugin.py +72 -0
- operonx/telemetry/tracers/__init__.py +20 -0
- operonx/telemetry/tracers/_base.py +106 -0
- operonx/telemetry/tracers/langfuse.py +369 -0
- operonx/telemetry/tracers/operon_eyes.py +87 -0
- operonx/telemetry/tracers/otel.py +271 -0
- operonx-0.6.2.dist-info/METADATA +258 -0
- operonx-0.6.2.dist-info/RECORD +138 -0
- operonx-0.6.2.dist-info/WHEEL +4 -0
- operonx-0.6.2.dist-info/entry_points.txt +2 -0
- operonx-0.6.2.dist-info/licenses/LICENSE +201 -0
operonx/__init__.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""Operon — high-performance workflow engine for AI applications.
|
|
2
|
+
|
|
3
|
+
Operon runs anything as a workflow — from IO-bound tasks like LLMs and
|
|
4
|
+
agents to CPU-bound workloads. Inspired by Airflow operators, it enforces
|
|
5
|
+
clear, consistent conventions for building scalable async workflows.
|
|
6
|
+
|
|
7
|
+
Example::
|
|
8
|
+
|
|
9
|
+
from operonx import Operon, GraphOp, START, END, PARENT, op
|
|
10
|
+
|
|
11
|
+
@op
|
|
12
|
+
def double(x: int):
|
|
13
|
+
return {"result": x * 2}
|
|
14
|
+
|
|
15
|
+
with GraphOp(name="workflow") as graph:
|
|
16
|
+
step = double(x=PARENT["input"])
|
|
17
|
+
START >> step >> END
|
|
18
|
+
|
|
19
|
+
engine = Operon(graph)
|
|
20
|
+
result = await engine.run(inputs={"input": 5})
|
|
21
|
+
|
|
22
|
+
Sub-namespaces:
|
|
23
|
+
- ``operonx.core`` — engine, ops, state, tracing, registry
|
|
24
|
+
- ``operonx.providers`` — LLM, embedding, reranker, ONNX backends
|
|
25
|
+
- ``operonx.telemetry`` — Langfuse, OTEL, local tracers
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import Optional, Union
|
|
30
|
+
|
|
31
|
+
from operonx.core import (
|
|
32
|
+
END,
|
|
33
|
+
LOGGER,
|
|
34
|
+
PARENT,
|
|
35
|
+
PENDING,
|
|
36
|
+
START,
|
|
37
|
+
BranchOp,
|
|
38
|
+
FuncOp,
|
|
39
|
+
GraphOp,
|
|
40
|
+
Middleware,
|
|
41
|
+
Operon,
|
|
42
|
+
ParserOp,
|
|
43
|
+
graph,
|
|
44
|
+
op,
|
|
45
|
+
)
|
|
46
|
+
from operonx.core.registry import (
|
|
47
|
+
BOOTSTRAP_ENV_PATHS,
|
|
48
|
+
ResourceHub,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
__version__ = "0.6.1"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def bootstrap(
|
|
55
|
+
*,
|
|
56
|
+
resources: Optional[Union[str, Path]] = None,
|
|
57
|
+
env: bool = True,
|
|
58
|
+
) -> Optional[ResourceHub]:
|
|
59
|
+
"""One-line setup for ``.env`` and :class:`ResourceHub`.
|
|
60
|
+
|
|
61
|
+
- When ``env`` is ``True`` (default), load ``./.env`` from CWD using
|
|
62
|
+
``python-dotenv`` (non-override; existing env wins). The path is
|
|
63
|
+
recorded in ``BOOTSTRAP_ENV_PATHS`` for later diagnostic messages.
|
|
64
|
+
- When ``resources`` is a path, install the hub via
|
|
65
|
+
:meth:`ResourceHub.from_yaml`.
|
|
66
|
+
- When ``resources`` is ``None``, call :meth:`ResourceHub.auto` —
|
|
67
|
+
which checks ``./resources.yaml`` and warns on miss.
|
|
68
|
+
- Idempotent: if a hub is already installed, return it unchanged.
|
|
69
|
+
|
|
70
|
+
Returns the installed hub, or ``None`` if no ``resources.yaml`` was
|
|
71
|
+
found and none was provided. Pure-compute graphs that don't need a
|
|
72
|
+
hub can ignore the return value.
|
|
73
|
+
"""
|
|
74
|
+
if env:
|
|
75
|
+
_load_env_into_bootstrap()
|
|
76
|
+
|
|
77
|
+
if ResourceHub._instance is not None:
|
|
78
|
+
return ResourceHub._instance
|
|
79
|
+
|
|
80
|
+
if resources is not None:
|
|
81
|
+
hub = ResourceHub.from_yaml(resources)
|
|
82
|
+
ResourceHub.set_instance(hub)
|
|
83
|
+
return hub
|
|
84
|
+
|
|
85
|
+
return ResourceHub.auto()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _load_env_into_bootstrap() -> None:
|
|
89
|
+
"""Load ``./.env`` from CWD if it exists; record the path.
|
|
90
|
+
|
|
91
|
+
Records the absolute path in ``BOOTSTRAP_ENV_PATHS`` regardless of
|
|
92
|
+
whether the file existed — this is what the env-var error message
|
|
93
|
+
surfaces, so users see exactly where ``.env`` was searched.
|
|
94
|
+
"""
|
|
95
|
+
env_path = (Path.cwd() / ".env").resolve()
|
|
96
|
+
if env_path not in BOOTSTRAP_ENV_PATHS:
|
|
97
|
+
BOOTSTRAP_ENV_PATHS.append(env_path)
|
|
98
|
+
if not env_path.exists():
|
|
99
|
+
return
|
|
100
|
+
try:
|
|
101
|
+
from dotenv import load_dotenv
|
|
102
|
+
except ImportError:
|
|
103
|
+
return
|
|
104
|
+
load_dotenv(env_path, override=False)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
__all__ = [
|
|
108
|
+
# Engine
|
|
109
|
+
"Operon",
|
|
110
|
+
"Middleware",
|
|
111
|
+
# Core op types
|
|
112
|
+
"GraphOp",
|
|
113
|
+
"BranchOp",
|
|
114
|
+
"FuncOp",
|
|
115
|
+
"ParserOp",
|
|
116
|
+
# Decorators
|
|
117
|
+
"op",
|
|
118
|
+
"graph",
|
|
119
|
+
# Markers
|
|
120
|
+
"START",
|
|
121
|
+
"END",
|
|
122
|
+
"PARENT",
|
|
123
|
+
"PENDING",
|
|
124
|
+
# Logging
|
|
125
|
+
"LOGGER",
|
|
126
|
+
# Setup
|
|
127
|
+
"bootstrap",
|
|
128
|
+
"ResourceHub",
|
|
129
|
+
# Version
|
|
130
|
+
"__version__",
|
|
131
|
+
]
|
operonx/core/__init__.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Operon core — workflow engine, ops, state, tracing, registry.
|
|
2
|
+
|
|
3
|
+
Public surface re-exported from the submodules below. For top-level
|
|
4
|
+
convenience imports (``from operonx import Operon``), see
|
|
5
|
+
:mod:`operonx.__init__`.
|
|
6
|
+
|
|
7
|
+
Example::
|
|
8
|
+
|
|
9
|
+
from operonx.core import Operon, GraphOp, START, END, PARENT
|
|
10
|
+
from operonx.core.ops import FuncOp
|
|
11
|
+
|
|
12
|
+
with GraphOp(name="workflow") as graph:
|
|
13
|
+
node = FuncOp(name="processor", ...)
|
|
14
|
+
START >> node >> END
|
|
15
|
+
|
|
16
|
+
engine = Operon(graph)
|
|
17
|
+
result = await engine.run(inputs={"key": "value"})
|
|
18
|
+
print(result["output"]) # workflow output
|
|
19
|
+
print(result["$state"]) # MemoryState for debugging
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from operonx.core.configs import EdgeConfig, EdgeType
|
|
23
|
+
from operonx.core.engine import ExecutionHandle, Operon
|
|
24
|
+
from operonx.core.loggings import LOGGER
|
|
25
|
+
from operonx.core.media import Media
|
|
26
|
+
from operonx.core.middleware import Middleware
|
|
27
|
+
from operonx.core.ops import (
|
|
28
|
+
END,
|
|
29
|
+
PARENT,
|
|
30
|
+
PENDING,
|
|
31
|
+
START,
|
|
32
|
+
BaseOp,
|
|
33
|
+
BranchOp,
|
|
34
|
+
DummyOp,
|
|
35
|
+
FuncOp,
|
|
36
|
+
GraphOp,
|
|
37
|
+
ParserOp,
|
|
38
|
+
ParserType,
|
|
39
|
+
graph,
|
|
40
|
+
op,
|
|
41
|
+
)
|
|
42
|
+
from operonx.core.registry import (
|
|
43
|
+
REGISTRY,
|
|
44
|
+
CacheEntry,
|
|
45
|
+
ConfigEntry,
|
|
46
|
+
ConfigRegistry,
|
|
47
|
+
ConfigStorage,
|
|
48
|
+
HealthCheckResult,
|
|
49
|
+
JsonConfigStorage,
|
|
50
|
+
ResourceHub,
|
|
51
|
+
YamlConfigStorage,
|
|
52
|
+
)
|
|
53
|
+
from operonx.core.states import Cell, MemoryState, Ref, StateSchema
|
|
54
|
+
from operonx.core.utils import Param
|
|
55
|
+
|
|
56
|
+
__all__ = [
|
|
57
|
+
# Engine
|
|
58
|
+
"Operon",
|
|
59
|
+
"ExecutionHandle",
|
|
60
|
+
"Middleware",
|
|
61
|
+
# Op base / markers
|
|
62
|
+
"BaseOp",
|
|
63
|
+
"DummyOp",
|
|
64
|
+
"START",
|
|
65
|
+
"END",
|
|
66
|
+
"PARENT",
|
|
67
|
+
"PENDING",
|
|
68
|
+
# Op types
|
|
69
|
+
"GraphOp",
|
|
70
|
+
"BranchOp",
|
|
71
|
+
"FuncOp",
|
|
72
|
+
"ParserOp",
|
|
73
|
+
"ParserType",
|
|
74
|
+
# Decorators
|
|
75
|
+
"op",
|
|
76
|
+
"graph",
|
|
77
|
+
# State
|
|
78
|
+
"StateSchema",
|
|
79
|
+
"MemoryState",
|
|
80
|
+
"Ref",
|
|
81
|
+
"Cell",
|
|
82
|
+
# Configs / params
|
|
83
|
+
"EdgeConfig",
|
|
84
|
+
"EdgeType",
|
|
85
|
+
"Param",
|
|
86
|
+
# Multimodal
|
|
87
|
+
"Media",
|
|
88
|
+
# Logging
|
|
89
|
+
"LOGGER",
|
|
90
|
+
# Registry
|
|
91
|
+
"ResourceHub",
|
|
92
|
+
"ConfigRegistry",
|
|
93
|
+
"ConfigEntry",
|
|
94
|
+
"CacheEntry",
|
|
95
|
+
"REGISTRY",
|
|
96
|
+
"HealthCheckResult",
|
|
97
|
+
"ConfigStorage",
|
|
98
|
+
"YamlConfigStorage",
|
|
99
|
+
"JsonConfigStorage",
|
|
100
|
+
]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Config types for the workflow graph.
|
|
2
|
+
|
|
3
|
+
- ``OpType`` — enum of op categories (func, branch, graph, llm, ...)
|
|
4
|
+
- ``EdgeConfig`` — config for edges between ops
|
|
5
|
+
- ``EdgeType`` — edge kinds (normal, lookback, condition)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .edge_config import EdgeConfig, EdgeType
|
|
9
|
+
from .op_config import OpType
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"OpType",
|
|
13
|
+
"EdgeConfig",
|
|
14
|
+
"EdgeType",
|
|
15
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Các kiểu config edge cho operonx."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
EdgeType = Literal["normal", "lookback", "condition"]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class EdgeConfig(BaseModel):
|
|
11
|
+
"""Config cho các edge giữa các node trong workflow graph.
|
|
12
|
+
|
|
13
|
+
Attributes:
|
|
14
|
+
from_node: Tên node nguồn
|
|
15
|
+
to_node: Tên node đích
|
|
16
|
+
type: Loại edge (normal, lookback, condition)
|
|
17
|
+
soft: Nếu True, edge này không được tính vào ready_count.
|
|
18
|
+
Dùng cho các đầu ra nhánh khi chỉ một nhánh được thực thi.
|
|
19
|
+
Được tạo bằng toán tử > thay vì >>
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from_node: str
|
|
23
|
+
to_node: str
|
|
24
|
+
type: EdgeType = "normal"
|
|
25
|
+
soft: bool = False
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Các kiểu và class config node cho operonx."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
OpType = Literal[
|
|
6
|
+
# Node dữ liệu
|
|
7
|
+
"data",
|
|
8
|
+
# Node AI/ML
|
|
9
|
+
"llm",
|
|
10
|
+
"embedding",
|
|
11
|
+
"rerank",
|
|
12
|
+
# Node điều khiển luồng
|
|
13
|
+
"branch",
|
|
14
|
+
"for",
|
|
15
|
+
"while",
|
|
16
|
+
"stream",
|
|
17
|
+
# Node xử lý
|
|
18
|
+
"code",
|
|
19
|
+
"lambda",
|
|
20
|
+
"parser",
|
|
21
|
+
"prompt",
|
|
22
|
+
"doc-processor",
|
|
23
|
+
# Node database/storage
|
|
24
|
+
"milvus",
|
|
25
|
+
"mongo",
|
|
26
|
+
"s3",
|
|
27
|
+
# Node đặc biệt
|
|
28
|
+
"graph",
|
|
29
|
+
"default",
|
|
30
|
+
"dummy",
|
|
31
|
+
"tool-executor",
|
|
32
|
+
"mcp",
|
|
33
|
+
]
|
|
34
|
+
"""Các loại node được hỗ trợ trong workflow graph."""
|