| """LangGraph agent using retriever fallback with LLM + tools.""" |
| import os |
| from langgraph.graph import StateGraph, MessagesState |
| from langgraph.prebuilt import ToolNode, tools_condition |
| from langchain_core.messages import HumanMessage, AIMessage |
| from langchain_google_genai import ChatGoogleGenerativeAI |
| from langchain_core.runnables import Runnable |
| |
| from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI |
| from tools import TOOLS |
| import pandas as pd |
|
|
| |
| QA_PATH = "metadata.jsonl" |
| qa_pairs = pd.read_json(QA_PATH, lines=True) |
| qa_dict = {row["Question"].strip(): row["Final answer"].strip() for _, row in qa_pairs.iterrows()} |
|
|
| def build_graph(): |
| """Construct a LangGraph agent with a QA retriever and fallback LLM+tools.""" |
| |
| |
| |
| |
| llm = HuggingFaceInferenceAPI(model_name="Qwen/Qwen2.5-Coder-32B-Instruct") |
| llm_with_tools = llm.bind_tools(TOOLS) |
|
|
| |
| def retriever_node(state: MessagesState): |
| query = state["messages"][-1].content.strip() |
| if query in qa_dict: |
| print(f"✅ Exact match found in retriever.") |
| return {"messages": [AIMessage(content=qa_dict[query])]} |
| print(f"🔍 No match found. Falling back to LLM.") |
| return {"messages": state["messages"]} |
|
|
| |
| def assistant_node(state: MessagesState): |
| return {"messages": [llm_with_tools.invoke(state["messages"])]} |
|
|
| |
| builder = StateGraph(MessagesState) |
| builder.add_node("retriever", retriever_node) |
| builder.add_node("assistant", assistant_node) |
| builder.add_node("tools", ToolNode(TOOLS)) |
|
|
| |
| builder.set_entry_point("retriever") |
| builder.add_edge("retriever", "assistant") |
| builder.add_conditional_edges("assistant", tools_condition) |
| builder.add_edge("tools", "assistant") |
| builder.set_finish_point("assistant") |
|
|
| return builder.compile() |
|
|
| |
| class BasicAgent: |
| def __init__(self): |
| print("BasicAgent initialized with retriever + LLM.") |
| self.graph = build_graph() |
|
|
| def __call__(self, question: str) -> str: |
| print(f"Agent received question: {question[:80]}") |
| result = self.graph.invoke({"messages": [HumanMessage(content=question)]}) |
| return result['messages'][-1].content.strip() |
|
|