ai-pipeline-core 0.4.3__py3-none-any.whl → 0.4.4__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.
- ai_pipeline_core/__init__.py +1 -1
- ai_pipeline_core/deployment/base.py +35 -8
- ai_pipeline_core/deployment/progress.py +46 -18
- ai_pipeline_core/llm/client.py +2 -2
- {ai_pipeline_core-0.4.3.dist-info → ai_pipeline_core-0.4.4.dist-info}/METADATA +1 -1
- {ai_pipeline_core-0.4.3.dist-info → ai_pipeline_core-0.4.4.dist-info}/RECORD +8 -8
- {ai_pipeline_core-0.4.3.dist-info → ai_pipeline_core-0.4.4.dist-info}/WHEEL +0 -0
- {ai_pipeline_core-0.4.3.dist-info → ai_pipeline_core-0.4.4.dist-info}/licenses/LICENSE +0 -0
ai_pipeline_core/__init__.py
CHANGED
|
@@ -821,7 +821,31 @@ class PipelineDeployment(Generic[TOptions, TResult]):
|
|
|
821
821
|
else:
|
|
822
822
|
current_docs = initial_documents or []
|
|
823
823
|
|
|
824
|
-
|
|
824
|
+
# Set up intra-flow progress context so progress_update() works inside flows
|
|
825
|
+
flow_minutes = tuple(getattr(f, "estimated_minutes", 1) for f in self.flows)
|
|
826
|
+
completed_mins = sum(flow_minutes[: max(step - 1, 0)])
|
|
827
|
+
progress_queue: asyncio.Queue[ProgressRun | None] = asyncio.Queue()
|
|
828
|
+
wh_url = context.progress_webhook_url or ""
|
|
829
|
+
worker = asyncio.create_task(webhook_worker(progress_queue, wh_url)) if wh_url else None
|
|
830
|
+
|
|
831
|
+
with flow_context(
|
|
832
|
+
webhook_url=wh_url,
|
|
833
|
+
project_name=project_name,
|
|
834
|
+
run_id=str(run_uuid) if run_uuid else "",
|
|
835
|
+
flow_run_id=str(run_uuid) if run_uuid else "",
|
|
836
|
+
flow_name=flow_name,
|
|
837
|
+
step=step,
|
|
838
|
+
total_steps=total_steps,
|
|
839
|
+
flow_minutes=flow_minutes,
|
|
840
|
+
completed_minutes=completed_mins,
|
|
841
|
+
queue=progress_queue,
|
|
842
|
+
):
|
|
843
|
+
try:
|
|
844
|
+
await flow_fn(project_name, current_docs, options)
|
|
845
|
+
finally:
|
|
846
|
+
progress_queue.put_nowait(None)
|
|
847
|
+
if worker:
|
|
848
|
+
await worker
|
|
825
849
|
|
|
826
850
|
# Build result from all documents in store
|
|
827
851
|
if store:
|
|
@@ -852,12 +876,6 @@ class PipelineDeployment(Generic[TOptions, TResult]):
|
|
|
852
876
|
"""
|
|
853
877
|
deployment = self
|
|
854
878
|
|
|
855
|
-
@flow(
|
|
856
|
-
name=self.name,
|
|
857
|
-
flow_run_name=f"{self.name}-{{project_name}}",
|
|
858
|
-
persist_result=True,
|
|
859
|
-
result_serializer="json",
|
|
860
|
-
)
|
|
861
879
|
async def _deployment_flow(
|
|
862
880
|
project_name: str,
|
|
863
881
|
documents: list[Document],
|
|
@@ -875,7 +893,16 @@ class PipelineDeployment(Generic[TOptions, TResult]):
|
|
|
875
893
|
store.shutdown()
|
|
876
894
|
set_document_store(None)
|
|
877
895
|
|
|
878
|
-
|
|
896
|
+
# Patch annotations so Prefect generates the parameter schema from the concrete types
|
|
897
|
+
_deployment_flow.__annotations__["options"] = self.options_type
|
|
898
|
+
_deployment_flow.__annotations__["return"] = self.result_type
|
|
899
|
+
|
|
900
|
+
return flow(
|
|
901
|
+
name=self.name,
|
|
902
|
+
flow_run_name=f"{self.name}-{{project_name}}",
|
|
903
|
+
persist_result=True,
|
|
904
|
+
result_serializer="json",
|
|
905
|
+
)(_deployment_flow)
|
|
879
906
|
|
|
880
907
|
|
|
881
908
|
__all__ = [
|
|
@@ -9,6 +9,8 @@ from dataclasses import dataclass
|
|
|
9
9
|
from datetime import UTC, datetime
|
|
10
10
|
from uuid import UUID
|
|
11
11
|
|
|
12
|
+
from prefect import get_client
|
|
13
|
+
|
|
12
14
|
from ai_pipeline_core.logging import get_pipeline_logger
|
|
13
15
|
|
|
14
16
|
from .contract import ProgressRun
|
|
@@ -38,9 +40,14 @@ _context: ContextVar[ProgressContext | None] = ContextVar("progress_context", de
|
|
|
38
40
|
|
|
39
41
|
|
|
40
42
|
async def update(fraction: float, message: str = "") -> None:
|
|
41
|
-
"""Report intra-flow progress (0.0-1.0). No-op without context.
|
|
43
|
+
"""Report intra-flow progress (0.0-1.0). No-op without context.
|
|
44
|
+
|
|
45
|
+
Sends webhook payload (if webhook_url configured) AND updates Prefect
|
|
46
|
+
flow run labels (if flow_run_id available) so both push and poll consumers
|
|
47
|
+
see progress, and staleness detection stays current.
|
|
48
|
+
"""
|
|
42
49
|
ctx = _context.get()
|
|
43
|
-
if ctx is None
|
|
50
|
+
if ctx is None:
|
|
44
51
|
return
|
|
45
52
|
|
|
46
53
|
fraction = max(0.0, min(1.0, fraction))
|
|
@@ -50,22 +57,43 @@ async def update(fraction: float, message: str = "") -> None:
|
|
|
50
57
|
else:
|
|
51
58
|
overall = fraction
|
|
52
59
|
overall = round(max(0.0, min(1.0, overall)), 4)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
step_progress = round(fraction, 4)
|
|
61
|
+
|
|
62
|
+
# Enqueue webhook payload for async delivery
|
|
63
|
+
if ctx.webhook_url:
|
|
64
|
+
payload = ProgressRun(
|
|
65
|
+
flow_run_id=UUID(ctx.flow_run_id) if ctx.flow_run_id else UUID(int=0),
|
|
66
|
+
project_name=ctx.project_name,
|
|
67
|
+
state="RUNNING",
|
|
68
|
+
timestamp=datetime.now(UTC),
|
|
69
|
+
step=ctx.step,
|
|
70
|
+
total_steps=ctx.total_steps,
|
|
71
|
+
flow_name=ctx.flow_name,
|
|
72
|
+
status="progress",
|
|
73
|
+
progress=overall,
|
|
74
|
+
step_progress=step_progress,
|
|
75
|
+
message=message,
|
|
76
|
+
)
|
|
77
|
+
ctx.queue.put_nowait(payload)
|
|
78
|
+
|
|
79
|
+
# Update Prefect labels so polling consumers and staleness detection stay current
|
|
80
|
+
if ctx.flow_run_id:
|
|
81
|
+
try:
|
|
82
|
+
async with get_client() as client:
|
|
83
|
+
await client.update_flow_run_labels(
|
|
84
|
+
flow_run_id=UUID(ctx.flow_run_id),
|
|
85
|
+
labels={
|
|
86
|
+
"progress.step": ctx.step,
|
|
87
|
+
"progress.total_steps": ctx.total_steps,
|
|
88
|
+
"progress.flow_name": ctx.flow_name,
|
|
89
|
+
"progress.status": "progress",
|
|
90
|
+
"progress.progress": overall,
|
|
91
|
+
"progress.step_progress": step_progress,
|
|
92
|
+
"progress.message": message,
|
|
93
|
+
},
|
|
94
|
+
)
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.warning(f"Progress label update failed: {e}")
|
|
69
97
|
|
|
70
98
|
|
|
71
99
|
async def webhook_worker(
|
ai_pipeline_core/llm/client.py
CHANGED
|
@@ -258,10 +258,10 @@ def _model_name_to_openrouter_model(model: ModelName) -> str:
|
|
|
258
258
|
Returns:
|
|
259
259
|
OpenRouter model name.
|
|
260
260
|
"""
|
|
261
|
-
if model == "gemini-3-flash-search":
|
|
262
|
-
return "google/gemini-3-flash:online"
|
|
263
261
|
if model == "sonar-pro-search":
|
|
264
262
|
return "perplexity/sonar-pro-search"
|
|
263
|
+
if model.endswith("-search"):
|
|
264
|
+
model = model.replace("-search", ":online")
|
|
265
265
|
if model.startswith("gemini"):
|
|
266
266
|
return f"google/{model}"
|
|
267
267
|
elif model.startswith("gpt"):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ai-pipeline-core
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.4
|
|
4
4
|
Summary: Core utilities for AI-powered processing pipelines using prefect
|
|
5
5
|
Project-URL: Homepage, https://github.com/bbarwik/ai-pipeline-core
|
|
6
6
|
Project-URL: Repository, https://github.com/bbarwik/ai-pipeline-core
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
ai_pipeline_core/__init__.py,sha256=
|
|
1
|
+
ai_pipeline_core/__init__.py,sha256=VcU67cNpAB6EJf2V_FxUx4ZFosbpb6IzFFwpJauHJzk,3270
|
|
2
2
|
ai_pipeline_core/exceptions.py,sha256=csAl7vq6xjSFBF8-UM9WZODCbhsOdOG5zH6IbA8iteM,1280
|
|
3
3
|
ai_pipeline_core/prompt_manager.py,sha256=3wFkL5rrjtUT1cLInkgyhS8hKnO4MeD1cdXAEuLhgoE,9459
|
|
4
4
|
ai_pipeline_core/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
ai_pipeline_core/settings.py,sha256=BUz8JEFfJQrdE4rNOhQWwxnTrfekLjWkoy-3wDZQ7PY,5142
|
|
6
6
|
ai_pipeline_core/testing.py,sha256=jIRrLxNvTwdamucfJoHET2qMeRhhMZV9uEJXO5vAfis,279
|
|
7
7
|
ai_pipeline_core/deployment/__init__.py,sha256=wTkVK6gcEQvqBajFMTAuodRONpN25yHbR1jtcumf0WQ,900
|
|
8
|
-
ai_pipeline_core/deployment/base.py,sha256=
|
|
8
|
+
ai_pipeline_core/deployment/base.py,sha256=bGSnDdrw6cLM_TItAiwptnwApbw5wkoIGY9pnwDvOTQ,37485
|
|
9
9
|
ai_pipeline_core/deployment/contract.py,sha256=a1qbHhneTGB27oSOUy79CUIhOIzOoq37M63XoIMzA4Y,1952
|
|
10
10
|
ai_pipeline_core/deployment/deploy.py,sha256=TCF4fH5f-K1ADODZHEyf-x7PJzDbv4qtWxlpoCe_mTs,22909
|
|
11
11
|
ai_pipeline_core/deployment/helpers.py,sha256=yVtGFUs4AFXkpLkiQ_ale0nXXt5btfWSb5PAbikQHNs,3312
|
|
12
|
-
ai_pipeline_core/deployment/progress.py,sha256=
|
|
12
|
+
ai_pipeline_core/deployment/progress.py,sha256=rO2g8VIh7EpzxzGGAroXEpveWoWZkk66jkDW22BY4j8,4827
|
|
13
13
|
ai_pipeline_core/deployment/remote.py,sha256=tOexisKEeeBoHLGYZWqcjr2H-nqqYc6kvoDL72AW78w,4661
|
|
14
14
|
ai_pipeline_core/docs_generator/__init__.py,sha256=JbWbk-Lw5GgWrCMRuw8zvKNTZY2jXv7XqoMiBYudvRI,1255
|
|
15
15
|
ai_pipeline_core/docs_generator/__main__.py,sha256=CH4agiM2suFJ63MhTg5m0GuXdc40z-6o4ojR72JQWVA,145
|
|
@@ -38,7 +38,7 @@ ai_pipeline_core/images/__init__.py,sha256=Hc2QKR27Q2Q-h5nH-EbzfxdE3dHArBm-st5_x
|
|
|
38
38
|
ai_pipeline_core/images/_processing.py,sha256=MrCuPGsyyEl9UlXYIPhZs0wN8CPTMZmejV2Lo2wyCZk,4362
|
|
39
39
|
ai_pipeline_core/llm/__init__.py,sha256=oyRvYD5DLDl7JIRTBUaiVz6jUC5dLLujkMNFpfRp2zc,795
|
|
40
40
|
ai_pipeline_core/llm/ai_messages.py,sha256=Ycmntk5d6NUFqVVsnNR_IDwJUFuHYEH7CPvmmDfYaJI,17424
|
|
41
|
-
ai_pipeline_core/llm/client.py,sha256=
|
|
41
|
+
ai_pipeline_core/llm/client.py,sha256=N8eH9bY2rF28U5kGK0HQ3ibKvphcipSMLVVxtxtut8Y,30275
|
|
42
42
|
ai_pipeline_core/llm/model_options.py,sha256=hg8xR0RJdJKp8QJNA4EbLnfFsnkE4HnxD85aYxc--hM,9164
|
|
43
43
|
ai_pipeline_core/llm/model_response.py,sha256=Ml9wcssSssqibReJxCc9EQu488pz69Cmq_XNBs_xmak,12219
|
|
44
44
|
ai_pipeline_core/llm/model_types.py,sha256=qHoUPPEkHu9B4kJ5xcIC09fk72v667ZxvzigxtgLpVo,2174
|
|
@@ -70,7 +70,7 @@ ai_pipeline_core/observability/_tracking/_writer.py,sha256=xZjwYyIxDzzzPxqkKjYAY
|
|
|
70
70
|
ai_pipeline_core/pipeline/__init__.py,sha256=uMv1jwSyq8Ym8Hbn5097twBJLdwN1iMeqnVM4EWyrhA,282
|
|
71
71
|
ai_pipeline_core/pipeline/decorators.py,sha256=CDJAeOjGLt5Ewc0Jc9zEuwLZwKyutOv89LSRS9dcXmI,37456
|
|
72
72
|
ai_pipeline_core/pipeline/options.py,sha256=KF4FcT085-IwX8r649v0a9ua5xnApM0qG2wJHWbq39A,438
|
|
73
|
-
ai_pipeline_core-0.4.
|
|
74
|
-
ai_pipeline_core-0.4.
|
|
75
|
-
ai_pipeline_core-0.4.
|
|
76
|
-
ai_pipeline_core-0.4.
|
|
73
|
+
ai_pipeline_core-0.4.4.dist-info/METADATA,sha256=DWL9spC2_pILAtrr6BARsTIjqWk3-VJO6WNyTqdEqyQ,29947
|
|
74
|
+
ai_pipeline_core-0.4.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
75
|
+
ai_pipeline_core-0.4.4.dist-info/licenses/LICENSE,sha256=kKj8mfbdWwkyG3U6n7ztB3bAZlEwShTkAsvaY657i3I,1074
|
|
76
|
+
ai_pipeline_core-0.4.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|