Skip to content

Commit 7c3cd93

Browse files
author
Arena AI Agent
committed
feat(api): 🌊 implement Server-Sent Events (SSE) Streaming in FastAPI to push real-time cognitive execution traces (L0-L6) to the client, preventing timeouts on deep reasoning tasks
1 parent 6cbc74c commit 7c3cd93

3 files changed

Lines changed: 51 additions & 4 deletions

File tree

‎epistemic_forge/pipeline/arsenal_run.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def run(self, spec: ProjectSpec, out_dir: Optional[str] = None) -> ForgeResult:
8585
)
8686

8787

88-
def run_pipeline(
88+
async def run_pipeline(
8989
title: str,
9090
question: str,
9191
domain: str = "hybrid",
@@ -110,7 +110,8 @@ def run_pipeline(
110110
)
111111
try:
112112
logger.info(f"Starting Epistemic Forge Pipeline for: '{title}'")
113-
result = ArsenalRun.create().run(spec)
113+
async for event in ArsenalRun.create().run(spec):
114+
yield event
114115
logger.success("Pipeline execution completed successfully.")
115116
return result
116117
except Exception as e:

‎epistemic_forge/ui/api.py‎

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
Provides a RESTful Enterprise-Ready API to integrate the Neuro-Symbolic
44
engine into any larger MLOps or business workflow.
55
"""
6-
from fastapi import FastAPI, HTTPException, BackgroundTasks
6+
from fastapi import FastAPI, HTTPException, Request
7+
from sse_starlette.sse import EventSourceResponse
8+
import json
79
from pydantic import BaseModel
810
from typing import List, Optional, Dict, Any
911
from epistemic_forge.models import ProjectSpec
@@ -77,3 +79,47 @@ async def generate_claim_lattice(req: ForgeRequest):
7779
@app.get("/health")
7880
async def health_check():
7981
return {"status": "operational", "engine": "neuro-symbolic-v1"}
82+
83+
84+
@app.post("/api/v1/forge/stream")
85+
async def generate_claim_lattice_stream(req: ForgeRequest, request: Request):
86+
"""Executes the L0-L6 pipeline and streams execution states via SSE."""
87+
async def event_generator():
88+
spec = ProjectSpec(
89+
title=req.title,
90+
question=req.question,
91+
domain=req.domain,
92+
target_model=req.target_model,
93+
keywords=req.keywords,
94+
api_key=req.api_key,
95+
api_base=req.api_base,
96+
budget_tokens=req.budget_tokens
97+
)
98+
99+
try:
100+
async for event in run_pipeline(title=spec.title, question=spec.question, domain=spec.domain.value):
101+
# If client disconnected
102+
if await request.is_disconnected():
103+
break
104+
105+
# If we have the final result, format it
106+
if event["status"] == "completed":
107+
result = event["result"]
108+
final_memo = next((art.content for art in getattr(result, "artifacts", []) if art.name == "Final Synthesis Memo"), "")
109+
raw_claims = getattr(result, "claims", [])
110+
claims_list = [c.model_dump() if hasattr(c, "model_dump") else c for c in raw_claims]
111+
112+
final_data = {
113+
"score": getattr(result, "final_score", 0.0),
114+
"claims": claims_list,
115+
"final_memo": final_memo,
116+
"peer_review": getattr(result, "peer_review", {})
117+
}
118+
yield {"event": "completed", "data": json.dumps(final_data)}
119+
else:
120+
yield {"event": "update", "data": json.dumps({"status": event["status"], "message": event["message"]})}
121+
122+
except Exception as e:
123+
yield {"event": "error", "data": json.dumps({"detail": str(e)})}
124+
125+
return EventSourceResponse(event_generator())

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ classifiers = [
3131
"Topic :: Scientific/Engineering :: Artificial Intelligence",
3232
"Topic :: Text Processing :: Linguistic",
3333
]
34-
dependencies = ["litellm>=1.40.0", "duckduckgo-search>=5.0.0", "chromadb>=0.4.0", "nbformat>=5.0.0", "fastapi>=0.100.0", "uvicorn>=0.20.0", "pydantic>=2.0.0", "loguru>=0.7.0", "tenacity>=8.0.0", "instructor>=1.3.0", "rich>=13.0.0", "streamlit>=1.35.0"]
34+
dependencies = ["litellm>=1.40.0", "duckduckgo-search>=5.0.0", "chromadb>=0.4.0", "nbformat>=5.0.0", "fastapi>=0.100.0", "uvicorn>=0.20.0", "sse-starlette>=2.0.0", "pydantic>=2.0.0", "loguru>=0.7.0", "tenacity>=8.0.0", "instructor>=1.3.0", "rich>=13.0.0", "streamlit>=1.35.0"]
3535

3636
[project.optional-dependencies]
3737
dev = ["pytest>=7.0", "pytest-mock"]

0 commit comments

Comments
 (0)