33Provides a RESTful Enterprise-Ready API to integrate the Neuro-Symbolic
44engine 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
79from pydantic import BaseModel
810from typing import List , Optional , Dict , Any
911from epistemic_forge .models import ProjectSpec
@@ -77,3 +79,47 @@ async def generate_claim_lattice(req: ForgeRequest):
7779@app .get ("/health" )
7880async 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 ())
0 commit comments