| """Conditional edge functions for the RAG graph.""" |
|
|
| from src.chains import answer_grader, hallucination_grader, question_router, RouterQuery |
| from src.core import logger |
| from src.core.state import GraphState |
| from src.graph.constants import ( |
| GENERATE, |
| WEB_SEARCH, |
| DECISION_USEFUL, |
| DECISION_NOT_USEFUL, |
| DECISION_NOT_SUPPORTED, |
| DECISION_WEBSEARCH, |
| DECISION_VECTORSTORE, |
| ) |
|
|
|
|
| def route_question(state: GraphState) -> str: |
| """ |
| Route the initial question to vectorstore or web search. |
| |
| Args: |
| state: Current graph state with question. |
| |
| Returns: |
| Route decision: 'vectorstore' or 'websearch'. |
| """ |
| logger.debug("Routing question...") |
|
|
| question = state["question"] |
| source: RouterQuery = question_router.invoke({"question": question}) |
|
|
| if source.datasource == "websearch": |
| logger.info("Route β Web Search") |
| return DECISION_WEBSEARCH |
| else: |
| logger.info("Route β Vectorstore") |
| return DECISION_VECTORSTORE |
|
|
|
|
| def decide_to_generate(state: GraphState) -> str: |
| """ |
| Decide whether to generate or perform web search based on document relevance. |
| |
| Args: |
| state: Current graph state with web_search flag. |
| |
| Returns: |
| Next node: WEB_SEARCH or GENERATE. |
| """ |
| logger.debug("Assessing graded documents...") |
|
|
| if state["web_search"]: |
| logger.info("Documents insufficient β Web Search") |
| return WEB_SEARCH |
| else: |
| logger.info("Documents sufficient β Generate") |
| return GENERATE |
|
|
|
|
| def grade_generation(state: GraphState) -> str: |
| """ |
| Grade the generation for hallucination and answer quality. |
| |
| Args: |
| state: Current graph state with question, documents, and generation. |
| |
| Returns: |
| Decision: 'useful', 'not_useful', or 'not_supported'. |
| """ |
| logger.debug("Checking for hallucinations...") |
|
|
| question = state["question"] |
| documents = state["documents"] |
| generation = state["generation"] |
|
|
| |
| hallucination_score = hallucination_grader.invoke( |
| {"documents": documents, "generation": generation} |
| ) |
|
|
| if hallucination_score.binary_score: |
| logger.debug("Generation grounded in documents") |
|
|
| |
| answer_score = answer_grader.invoke( |
| {"question": question, "generation": generation} |
| ) |
|
|
| if answer_score.binary_score: |
| logger.info("Generation β Useful") |
| return DECISION_USEFUL |
| else: |
| logger.warning("Generation does not address question β Retry") |
| return DECISION_NOT_USEFUL |
| else: |
| logger.warning("Generation not grounded β Web Search") |
| return DECISION_NOT_SUPPORTED |
|
|