Nagendravarma commited on
Commit Β·
bbbbe2c
1
Parent(s): c3938e0
Optimize latency: parallelize retrievals and reduce artificial stream delay
Browse files- backend/main.py +1 -1
- orchestration/orchestrator.py +44 -28
backend/main.py
CHANGED
|
@@ -253,7 +253,7 @@ async def chat_stream(session_id: str, query: str, plan_tier: str = "Unknown"):
|
|
| 253 |
# Emit individual sub-steps (each line from steps_log) with a small delay
|
| 254 |
for step in new_steps:
|
| 255 |
yield emit({"type": "substep", "node": node, "intent": intent, "step": step, "all_steps": current_steps})
|
| 256 |
-
await asyncio.sleep(0.
|
| 257 |
|
| 258 |
# Signal node completion
|
| 259 |
final_answer = state.get("answer", "")
|
|
|
|
| 253 |
# Emit individual sub-steps (each line from steps_log) with a small delay
|
| 254 |
for step in new_steps:
|
| 255 |
yield emit({"type": "substep", "node": node, "intent": intent, "step": step, "all_steps": current_steps})
|
| 256 |
+
await asyncio.sleep(0.05) # minimal pause for smooth UI without blocking stream
|
| 257 |
|
| 258 |
# Signal node completion
|
| 259 |
final_answer = state.get("answer", "")
|
orchestration/orchestrator.py
CHANGED
|
@@ -35,6 +35,8 @@ Architecture (5 nodes in a directed StateGraph):
|
|
| 35 |
import os
|
| 36 |
import sys
|
| 37 |
from typing import TypedDict, List
|
|
|
|
|
|
|
| 38 |
|
| 39 |
# Ensure project root is on sys.path so `config` and sibling packages resolve
|
| 40 |
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
@@ -202,17 +204,23 @@ def retrieve(state: AgentState) -> AgentState:
|
|
| 202 |
internal_logs = []
|
| 203 |
token = trace_log.set(internal_logs)
|
| 204 |
|
|
|
|
|
|
|
|
|
|
| 205 |
# ββ SIMPLE_LOOKUP ββββββββββββββββββββββββββββββββββββββββββββ
|
| 206 |
if intent == "SIMPLE_LOOKUP":
|
| 207 |
-
log.append("π [SIMPLE_LOOKUP]
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
|
|
|
|
|
|
|
|
|
| 216 |
|
| 217 |
# ββ POLICY_QUESTION ββββββββββββββββββββββββββββββββββββββββββ
|
| 218 |
elif intent == "POLICY_QUESTION":
|
|
@@ -223,28 +231,36 @@ def retrieve(state: AgentState) -> AgentState:
|
|
| 223 |
|
| 224 |
# ββ MULTI_HOP ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 225 |
elif intent == "MULTI_HOP":
|
| 226 |
-
log.append("π [MULTI_HOP]
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
|
|
|
|
|
|
|
|
|
| 240 |
|
| 241 |
# ββ COMPARISON βββββββββββββββββββββββββββββββββββββββββββββββ
|
| 242 |
elif intent == "COMPARISON":
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 248 |
|
| 249 |
separator = "\n\n" + "β" * 60 + "\n\n"
|
| 250 |
full_context = separator.join(parts) if parts else "No relevant context found."
|
|
|
|
| 35 |
import os
|
| 36 |
import sys
|
| 37 |
from typing import TypedDict, List
|
| 38 |
+
import concurrent.futures
|
| 39 |
+
import contextvars
|
| 40 |
|
| 41 |
# Ensure project root is on sys.path so `config` and sibling packages resolve
|
| 42 |
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
| 204 |
internal_logs = []
|
| 205 |
token = trace_log.set(internal_logs)
|
| 206 |
|
| 207 |
+
def _run_tool(tool_func, kwargs):
|
| 208 |
+
return contextvars.copy_context().run(tool_func, kwargs)
|
| 209 |
+
|
| 210 |
# ββ SIMPLE_LOOKUP ββββββββββββββββββββββββββββββββββββββββββββ
|
| 211 |
if intent == "SIMPLE_LOOKUP":
|
| 212 |
+
log.append("π [SIMPLE_LOOKUP] Executing Graph & Hybrid retrieval concurrently")
|
| 213 |
+
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
|
| 214 |
+
fut_g = executor.submit(_run_tool, relational_search.invoke, {"query": query})
|
| 215 |
+
fut_p = executor.submit(_run_tool, policy_search.invoke, {"query": query})
|
| 216 |
+
|
| 217 |
+
graph_ctx = fut_g.result()
|
| 218 |
+
if graph_ctx and "No structured" not in graph_ctx:
|
| 219 |
+
parts.append(f"[STRUCTURED GRAPH FACTS]\n{graph_ctx}")
|
| 220 |
+
|
| 221 |
+
policy_ctx = fut_p.result()
|
| 222 |
+
if policy_ctx and "No relevant" not in policy_ctx:
|
| 223 |
+
parts.append(f"[POLICY DOCUMENTS]\n{policy_ctx}")
|
| 224 |
|
| 225 |
# ββ POLICY_QUESTION ββββββββββββββββββββββββββββββββββββββββββ
|
| 226 |
elif intent == "POLICY_QUESTION":
|
|
|
|
| 231 |
|
| 232 |
# ββ MULTI_HOP ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 233 |
elif intent == "MULTI_HOP":
|
| 234 |
+
log.append("π [MULTI_HOP] Executing Graph, Policy, and Prior-Auth retrievals concurrently")
|
| 235 |
+
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
|
| 236 |
+
fut_g = executor.submit(_run_tool, relational_search.invoke, {"query": query})
|
| 237 |
+
fut_p = executor.submit(_run_tool, policy_search.invoke, {"query": query})
|
| 238 |
+
fut_a = executor.submit(_run_tool, prior_auth_search.invoke, {"query": query})
|
| 239 |
+
|
| 240 |
+
graph_ctx = fut_g.result()
|
| 241 |
+
if graph_ctx and "No structured" not in graph_ctx:
|
| 242 |
+
parts.append(f"[STRUCTURED GRAPH FACTS]\n{graph_ctx}")
|
| 243 |
+
|
| 244 |
+
policy_ctx = fut_p.result()
|
| 245 |
+
if policy_ctx and "No relevant" not in policy_ctx:
|
| 246 |
+
parts.append(f"[POLICY DOCUMENTS]\n{policy_ctx}")
|
| 247 |
+
|
| 248 |
+
auth_ctx = fut_a.result()
|
| 249 |
+
if auth_ctx and "No prior authorization" not in auth_ctx:
|
| 250 |
+
parts.append(f"[PRIOR AUTHORIZATION RULES]\n{auth_ctx}")
|
| 251 |
|
| 252 |
# ββ COMPARISON βββββββββββββββββββββββββββββββββββββββββββββββ
|
| 253 |
elif intent == "COMPARISON":
|
| 254 |
+
log.append(f"βοΈ [COMPARISON] Retrieving Bronze, Silver, and Gold plan contexts concurrently")
|
| 255 |
+
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
|
| 256 |
+
futures = {
|
| 257 |
+
tier: executor.submit(_run_tool, plan_comparison_search.invoke, {"query": query, "tier": tier})
|
| 258 |
+
for tier in ("Bronze", "Silver", "Gold")
|
| 259 |
+
}
|
| 260 |
+
for tier in ("Bronze", "Silver", "Gold"):
|
| 261 |
+
tier_ctx = futures[tier].result()
|
| 262 |
+
if tier_ctx and f"No {tier}" not in tier_ctx:
|
| 263 |
+
parts.append(f"[{tier.upper()} PLAN]\n{tier_ctx}")
|
| 264 |
|
| 265 |
separator = "\n\n" + "β" * 60 + "\n\n"
|
| 266 |
full_context = separator.join(parts) if parts else "No relevant context found."
|