File size: 9,756 Bytes
90eaf96
c608440
90eaf96
 
 
c608440
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f0fb393
c608440
90eaf96
69b6831
90eaf96
 
c608440
90eaf96
c948f7b
 
 
 
 
 
 
 
c608440
90eaf96
f0fb393
 
 
c608440
90eaf96
 
c608440
90eaf96
 
 
 
 
dea87eb
90eaf96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c608440
90eaf96
 
987ec40
90eaf96
987ec40
02227a8
 
 
 
 
 
 
 
 
 
 
 
 
90eaf96
 
 
 
 
 
 
 
987ec40
90eaf96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c608440
90eaf96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f0fb393
90eaf96
 
f0fb393
 
 
90eaf96
 
 
 
 
 
 
f0fb393
90eaf96
 
 
 
 
 
02227a8
90eaf96
 
 
 
 
 
02227a8
90eaf96
 
 
 
f0fb393
90eaf96
8417629
90eaf96
 
 
 
 
 
 
 
 
 
 
2cb95cb
90eaf96
 
 
 
 
 
 
 
 
 
02227a8
c608440
90eaf96
 
f0fb393
e85789d
90eaf96
c608440
02227a8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c608440
90eaf96
 
 
 
 
 
 
a142f83
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

import os
import time
import traceback
from dotenv import load_dotenv
from langchain_core.messages import convert_to_messages
from langchain_core.tools import tool
from langchain_groq import ChatGroq
from langchain_tavily import TavilySearch
from langgraph.prebuilt import create_react_agent
from langgraph_supervisor import create_supervisor
from langchain_google_genai import ChatGoogleGenerativeAI
from langsmith import traceable
from e2b_code_interpreter import Sandbox
from langchain_chroma import Chroma
from langchain_community.graphs import Neo4jGraph
from langchain_cohere import ChatCohere, CohereEmbeddings
from langchain_community.chains.graph_qa.cypher import GraphCypherQAChain
from langchain_core.prompts import PromptTemplate
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_experimental.graph_transformers import LLMGraphTransformer
from langchain_mistralai import ChatMistralAI

# --- WRAPPER FUNCTION START ---
def get_agent_app():
    # --- Load Environment ---
    load_dotenv()

    # --- Environment Keys (Inside function to capture runtime env) ---
     # --- Environment Keys ---
    tavily_api_key = os.environ.get("TAVILY_API_KEY")
    groq_api_key = os.environ.get("GROQ_API_KEY")
    # FIX 1: os.environ() galat tha, os.getenv() sahi hai
    google_api_key = os.getenv("GOOGLE_API_KEY")
    e2b_api_key = os.environ.get("E2B_API_KEY")
    cohere_api_key = os.environ.get("COHERE_API_KEY")
    mistralai_api_key = os.environ.get("MISTRALAI_API_KEY")

    # Graph Keys
    os.environ["NEO4J_URI"] = os.environ.get("NEO4J_URI")
    os.environ["NEO4J_USERNAME"] = os.environ.get("NEO4J_USERNAME")
    os.environ["NEO4J_PASSWORD"] = os.environ.get("NEO4J_PASSWORD")

    # --- Tools Setup ---
    web_search = TavilySearch(api_key=tavily_api_key, max_results=3)

    # 1. Setup Connection
    embeddings = CohereEmbeddings(model="embed-english-v3.0", cohere_api_key=os.environ["COHERE_API_KEY"])
    
    # Path './' kar diya hai taaki hosting par chale
    vector_store = Chroma(
        persist_directory="./chroma_db_groq_v1", 
        embedding_function=embeddings, 
        collection_name="rag_groq_final"
    )

    @tool
    def vector_tool(query: str) -> str:
        """
        Use this tool to find Context, from internal documents.
        Input: A search query (e.g., 'AutoDev project architecture').
        """
        print(f"   ⚑ [Vector Tool]: Searching Docs for '{query}'...")
        try:
            results = vector_store.similarity_search(query, k=4)
            if not results:
                return "VECTOR_FAILURE: No info found in docs."
            return "\n\n".join([doc.page_content for doc in results])
        except Exception as e:
            return f"Vector Error: {e}"


    # 1. Setup Graph & Smart Prompt
    try:
        graph = Neo4jGraph()

      # --- πŸ”₯ UPDATED STRONG PROMPT ---
        cypher_template = """
        You are a Neo4j Expert.
    Schema: {schema}
    Goal: Generate a Cypher query to retrieve ALL connections (Skills, Projects, Education) for the user.
    
    ⚠️ CRITICAL RULES:
    1. **Case-Insensitive:** ALWAYS use `WHERE toLower(p.name) CONTAINS toLower('avneesh')`.
    2. **Relationship Syntax:** When matching multiple relationships, DO NOT repeat the colon.
       - ❌ WRONG: `[:HAS_SKILL|:WORKED_ON|:HAS_DEGREE]`
       - βœ… CORRECT: `[:HAS_SKILL|WORKED_ON|HAS_DEGREE]`
    3. **Pattern:** `MATCH (p:Person)-[r]->(related) WHERE toLower(p.name) CONTAINS toLower('{question_keyword}') RETURN p, r, related LIMIT 50`
    
    Question: {question}
    Cypher Query:
       """

        cypher_prompt = PromptTemplate(
            template=cypher_template,
            input_variables=["schema", "question"]
        )

        # Graph logic ke liye GPT-4o best hai (Syntax errors kam karta hai)
        cypher_chain = GraphCypherQAChain.from_llm(
            llm=ChatGoogleGenerativeAI(model="gemini-2.5-pro",api_key=google_api_key),
            graph=graph,
            verbose=True,
            cypher_prompt=cypher_prompt,
            allow_dangerous_requests=True
        )

        @tool
        def graph_tool(query: str) -> str:
            """
            Use this tool to find Skills, Relationships, Connections, or Tech Stacks.
            """
            print(f"   πŸ”— [Graph Tool]: Reasoning for '{query}'...")
            try:
                result = cypher_chain.invoke(query)
                data = result['result']

                # Agar Graph khali hai, to Supervisor ko signal do
                if not data or "I don't know" in data or data == "[]":
                    return "GRAPH_FAILURE: No direct match. SUGGESTION: Ask Vector_Specialist."

                return str(data)
            except Exception as e:
                return f"Graph Error: {e}"
    except:
        # Fallback if graph fails
        @tool
        def graph_tool(query: str) -> str: return "Graph Connection Failed"




    # --- Models ---
    @traceable
    def create_groq_supervisor_model():
        return ChatGroq(model="qwen/qwen3-32b", api_key=groq_api_key )# Powerful model for reasoning

    @traceable
    def create_groq_coding_model():
        return ChatGroq(model="llama-3.3-70b-versatile", api_key=groq_api_key) # Powerful model for coding

    @traceable
    def create_google_coding2_model():
        return ChatGoogleGenerativeAI(model="gemini-2.5-flash",api_key=google_api_key) # Powerful model for coding

    @traceable
    def create_groq_coding3_model():
        return ChatGroq(model="openai/gpt-oss-20b", api_key=groq_api_key) # Powerful model for coding

    @traceable
    def create_mistralai_coding4_model():
        return ChatMistralAI(api_key=mistralai_api_key,
        model="ministral-3b-latest", # Using the stable and powerful model
        max_retries=3,
        temperature=0.7) # max_token removed to avoid errors

    sup_model = create_groq_supervisor_model()
    coding_model = create_groq_coding_model()
    coding_model2 = create_google_coding2_model()
    coding_model3 = create_groq_coding3_model()
    coding_model4 = create_mistralai_coding4_model()


    graph_agent = create_react_agent(
        model=coding_model3,
        tools=[graph_tool],
        prompt=(
            """tool` to query the Knowledge Graph.

    **Instructions:**
    1. Analyze the user's question and extract key entities (Names, Technologies).
    2. Use the tool to query the database.
    3. **If Data Found:** Return the exact facts found (e.g., "Avneesh knows Python, Java").
    4. **If No Data/Empty:** Return exactly: "GRAPH_FAILURE: No relevant data found in the knowledge graph."
    5. pass answer to supervisor but do not call any tool  respond with the exact message: "graph_info passed successfully to supervisor."""
        ),
        name="graph_agent",
    )

    #_-- vector Agent ---
    vector_agent = create_react_agent(
        model=coding_model,
        tools=[vector_tool],
        prompt=(
        """
            "You are a vector expert. Use `vector_tool` to find document context."
            "When you get the information, just output the answer directly as text."
            "pass answer to supervisor but do not call any tool  respond with the exact message: "vector passed successfully to supervisor."""
        ),
        name="vector_agent",
    )

    web_agent = create_react_agent(
        model=sup_model,
        tools=[web_search],
        prompt=(
        """
            "You are a web expert. Use `web_search_tool` to find real-time context."
            "When you get the information, just output the answer directly as text."
            "pass answer to supervisor but do not call any tool  respond with the exact message: "web_info passed successfully to supervisor."""
        ),
        name="web_agent",
    )

  

    # --- Supervisor ---
    supervisor = create_supervisor(
        model=coding_model2,
        agents=[vector_agent,graph_agent, web_agent],
        prompt=(
    """
   You are a Senior Technical Project Manager (Supervisor).
    Your goal is to answer user queries by orchestrating a team of agents in a SPECIFIC ORDER.
    
    ⚠️ **INTELLIGENT WORKFLOW (FOLLOW STRICTLY):**
    
    **STEP 1: IDENTIFY (Graph_Agent)**
    - ALWAYS call `Graph_Agent` FIRST.
    - Ask it to find the *relationships* and *facts* about the entities in the user's query.
    - *Goal:* Figure out "What is this?" (e.g., Is 'AutoDev' a person, a project, or a skill?).
    
    **STEP 2: STRATEGIZE (Internal Thought)**
    - Analyze the Graph_Agent's output.
    - IF Graph says "X is a Project" -> You know you need architecture/code details.
    - IF Graph says "X is a Person" -> You might need their resume/bio.
    
    **STEP 3: DEEP DIVE (Vector_Agent)**
    - Based on Step 2, formulate a *Specific Query* for the `Vector_Agent`.
    - ❌ DO NOT just pass the user's raw question.
    - βœ… PASS A TARGETED QUERY. 
      - *Bad:* "Tell me about AutoDev."
      - *Good:* "Search documents for 'AutoDev' architecture diagrams, tech stack, and deployment steps."
    
    **STEP 4: EXECUTE/REFINE (Coder_Agent / Web_Agent)**
    - If you need to calculate something or run code, use `Coder_Agent` with the data gathered from Step 1 & 3.
    - Use `Web_Agent` ONLY if the data is missing from both Graph and Docs (e.g., live stock prices).
    
    **FINAL OUTPUT:**
    - Synthesize all info into a clear, professional answer.
    """
        ),
        sanitize_names=True,
        add_handoff_back_messages=True,
        output_mode="full_history",
    ).compile()

    # --- Return Statement (Ab ye indented hai, isliye error nahi aayega) ---
    return supervisor