| """ |
| LangGraph Routing Logic for Healthcare RAG Pipeline. |
| |
| Defines conditional edge functions that determine the next node |
| based on current state. |
| """ |
| from typing import Literal |
| from langgraph.graph import END |
|
|
| from src.langgraph.langgraph_state import HealthcareRAGState |
| from src.langgraph.langgraph_nodes import MAX_RETRY_COUNT, MIN_RELEVANT_DOCS |
|
|
|
|
| def route_after_grading(state: HealthcareRAGState) -> Literal["generate", "refine", "unanswerable"]: |
| """ |
| Route after document grading. |
| |
| Decides whether to: |
| - "generate": Proceed with answer generation (enough relevant docs) |
| - "refine": Retry with refined query (not enough relevant docs, can retry) |
| - "unanswerable": Give up and return safe response (max retries reached) |
| """ |
| is_answerable = state.get("is_answerable", False) |
| retry_count = state.get("retry_count", 0) |
| documents = state.get("documents", []) |
| |
| |
| if not documents: |
| if retry_count < MAX_RETRY_COUNT: |
| return "refine" |
| return "unanswerable" |
| |
| |
| if is_answerable: |
| return "generate" |
| |
| |
| if retry_count < MAX_RETRY_COUNT: |
| return "refine" |
| |
| |
| |
| if len(documents) >= 1: |
| return "generate" |
| |
| return "unanswerable" |
|
|
|
|
| def route_after_verify(state: HealthcareRAGState) -> Literal["enrich_xai", "regenerate"]: |
| """ |
| Route after grounding verification. |
| |
| Decides whether to: |
| - "enrich_xai": Answer is grounded, proceed to XAI enrichment |
| - "regenerate": Answer not grounded, add warning and continue |
| """ |
| is_grounded = state.get("is_grounded", True) |
| |
| if is_grounded: |
| return "enrich_xai" |
| else: |
| |
| |
| return "enrich_xai" |
|
|
|
|
| def route_after_xai(state: HealthcareRAGState) -> Literal["end", "review"]: |
| """ |
| Route after XAI enrichment. |
| |
| Decides whether to: |
| - "end": Complete the response |
| - "review": Flag for human review (low confidence) |
| """ |
| needs_review = state.get("needs_review", False) |
| |
| if needs_review: |
| return "review" |
| return "end" |
|
|
|
|
| def should_continue_retrieval(state: HealthcareRAGState) -> bool: |
| """ |
| Check if we should continue retrieval loop. |
| |
| Returns True if: |
| - Not enough relevant documents |
| - Haven't exceeded retry count |
| """ |
| is_answerable = state.get("is_answerable", False) |
| retry_count = state.get("retry_count", 0) |
| |
| return not is_answerable and retry_count < MAX_RETRY_COUNT |
|
|