Ankit93 commited on
Commit
9023ac5
·
1 Parent(s): 4ed2bb2
app.py CHANGED
@@ -1,31 +1,76 @@
 
 
1
  import gradio as gr
2
- from transformers import pipeline
3
-
4
- # Initialize the model pipeline only once
5
- text_generator = pipeline("text-generation", model="mistralai/Mixtral-8x7B-Instruct-v0.1", device_map="auto")
6
-
7
- class Inference:
8
- def __init__(self, pipe):
9
- self.pipe = pipe
10
-
11
- def get_results(self, prompt, max_new_tokens=256, temperature=0.7):
12
- output = self.pipe(prompt, max_new_tokens=max_new_tokens, temperature=temperature)
13
- return output[0]["generated_text"]
14
-
15
- inference = Inference(text_generator)
16
-
17
- def generate_text(prompt, max_tokens, temperature):
18
- return inference.get_results(prompt, max_tokens, temperature)
19
-
20
- # Create a simple Gradio interface
21
- gr.Interface(
22
- fn=generate_text,
23
- inputs=[
24
- gr.Textbox(lines=4, label="Prompt"),
25
- gr.Slider(minimum=10, maximum=1024, value=256, label="Max New Tokens"),
26
- gr.Slider(minimum=0.1, maximum=1.5, value=0.7, step=0.1, label="Temperature"),
27
- ],
28
- outputs=gr.Textbox(label="Generated Text"),
29
- title="Mixtral-8x7B Text Generator",
30
- description="Enter a prompt to generate text using Mixtral-8x7B-Instruct."
31
- ).launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re, uuid
2
+ import json, logging
3
  import gradio as gr
4
+ from typing import List, Dict
5
+
6
+ from data.css import custom_css
7
+ from src.controller.agent_cacher import AgentManager
8
+ # Configure logging
9
+ logging.basicConfig(level=logging.INFO, format="-->%(asctime)s [%(levelname)s] %(message)s")
10
+
11
+
12
+
13
+
14
+ def create_gradio_interface():
15
+ gr.HTML('<link href="https://fonts.googleapis.com/css2?family=Fira+Code&family=Roboto&display=swap" rel="stylesheet">')
16
+ gr.HTML(custom_css)
17
+ manager = AgentManager()
18
+
19
+ with gr.Blocks(title="AI Learning Assistant") as demo:
20
+ gr.Markdown("# 🧠 Learn with LlamaIndex Tools")
21
+ logging.info("Starting Learning Application")
22
+
23
+ with gr.Row():
24
+ session_id = gr.Textbox(label="Session ID", value=str(uuid.uuid4()), visible=True)
25
+ llm_selector = gr.Dropdown(
26
+ label="LLM Type",
27
+ choices=["Google", "OpenAI", "HuggingFace", "Mistral"],
28
+ value="Google",
29
+ interactive=True
30
+ )
31
+
32
+ with gr.Row():
33
+ with gr.Column(scale=3):
34
+ chatbot = gr.Chatbot(
35
+ label="Learning Dialog",
36
+ height=500,
37
+ type="messages"
38
+ )
39
+ query_input = gr.Textbox(label="Your Learning Query", placeholder="Ask about ML/DL algorithms...")
40
+ submit_btn = gr.Button("Submit")
41
+
42
+ with gr.Column(scale=1):
43
+ gr.Markdown("### Tools Preview")
44
+ tool_output = gr.Textbox(label="Selected Tools", interactive=False)
45
+ response_output = gr.Textbox(label="Full Response", interactive=False, lines=10)
46
+
47
+ def process_query(session_id_val, query, chat_history, llm_val):
48
+ print("Session:", session_id)
49
+ print("Query:", query)
50
+ #print("Chat History:", chat_history)
51
+ print("Option selected:", llm_val)
52
+ agent = manager.get_agent(session_id_val, llm_type=llm_val)
53
+ chat_history, tools_used, response = agent.process_query(query)
54
+ manager.save_agent(session_id_val, agent)
55
+ return chat_history, tools_used, response, ""
56
+
57
+ submit_btn.click(
58
+ process_query,
59
+ inputs=[session_id, query_input, chatbot, llm_selector], # ✅ 4 inputs
60
+ outputs=[chatbot, tool_output, response_output, query_input]
61
+ )
62
+
63
+ def load_history(session_id_val, llm_val):
64
+ agent = manager.get_agent(session_id_val, llm_val)
65
+ return agent.chat_history
66
+
67
+ session_id.change(
68
+ load_history,
69
+ inputs=[session_id, llm_selector], # ✅ Pass component objects, not .value
70
+ outputs=chatbot
71
+ )
72
+
73
+ return demo
74
+ if __name__ == "__main__":
75
+ interface = create_gradio_interface()
76
+ interface.launch()
app__.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # --- Gradio App ---
2
+ import uuid
3
+ import gradio as gr
4
+ from src.controller.agent import ChatBot
5
+
6
+
7
+ chatbot = ChatBot()
8
+ session_store = {}
9
+ session = ""
10
+
11
+ def build_request(user_input):
12
+ return {
13
+ "query": user_input,
14
+ "metadata": {
15
+ "user_id": "123",
16
+ "timestamp": "2025-04-20T12:00:00"
17
+ }
18
+ }
19
+
20
+ def chat(session_id, user_input, history):
21
+ if session_id not in session_store:
22
+ session_store[session_id] = []
23
+
24
+ if user_input.strip():
25
+ request = build_request(user_input)
26
+ agent = chatbot.agent_cacher.get_agent_for(session_id, request)
27
+ reply = agent.agentic_chat(user_input)
28
+
29
+ session_store[session_id].append(("You", user_input))
30
+ session_store[session_id].append(("Agent", reply))
31
+
32
+ updated_history = [(sender, message) for sender, message in session_store[session_id]]
33
+ return reply, ""
34
+
35
+ with gr.Blocks() as demo:
36
+ gr.Markdown("# 🧠 Chat with LlamaIndex Agent")
37
+
38
+ with gr.Row():
39
+ if not session:
40
+ session = uuid.uuid4()
41
+ session_id = gr.Textbox(label="Session ID", value=session)
42
+
43
+ with gr.Row():
44
+ chatbot_ui = gr.Chatbot(label="Chat History", height=400)
45
+
46
+ with gr.Row():
47
+ user_input = gr.Textbox(label="Your Query", placeholder="Enter your query here...")
48
+
49
+ with gr.Row():
50
+ send_btn = gr.Button("Send")
51
+
52
+ send_btn.click(
53
+ chat,
54
+ inputs=[session_id, user_input, chatbot_ui],
55
+ outputs=[chatbot_ui, user_input],
56
+ )
57
+
58
+ if __name__ == "__main__":
59
+ demo.launch()
data/__pycache__/css.cpython-312.pyc ADDED
Binary file (449 Bytes). View file
 
data/coverage_doc.txt ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Plan Name: Elevate Health PPO 2025
2
+ Type: Preferred Provider Organization (PPO)
3
+
4
+ Summary:
5
+ The Elevate Health PPO Plan offers flexibility in choosing healthcare providers. Members can visit any doctor or specialist without a referral, but in-network providers offer lower out-of-pocket costs.
6
+
7
+ Key Benefits:
8
+ - Annual deductible: $1,500 individual / $3,000 family
9
+ - Out-of-pocket maximum: $6,000 individual / $12,000 family
10
+ - Primary care visits: $25 copay in-network
11
+ - Specialist visits: $50 copay in-network
12
+ - Emergency room: $250 copay
13
+ - Generic prescriptions: $10 copay
14
+ - Brand name prescriptions: $40 copay
15
+
16
+ Wellness Programs:
17
+ - Free annual physical exams
18
+ - Telehealth services with no copay
19
+ - Mental health counseling (up to 10 visits/year covered)
20
+
21
+ Covered Services:
22
+ - Preventive care (100% in-network)
23
+ - Maternity and newborn care
24
+ - Surgery and hospitalization
25
+ - Lab tests and X-rays
26
+
27
+ Exclusions:
28
+ - Cosmetic procedures
29
+ - Fertility treatments
30
+ - Long-term custodial care
31
+
32
+ Plan Name: CoreCare HMO 2025
33
+ Type: Health Maintenance Organization (HMO)
34
+
35
+ Summary:
36
+ CoreCare HMO Plan requires members to choose a Primary Care Physician (PCP) and get referrals for specialist care. This plan offers coordinated care at lower premiums.
37
+
38
+ Key Benefits:
39
+ - Annual deductible: $500 individual / $1,000 family
40
+ - Out-of-pocket maximum: $4,000 individual / $8,000 family
41
+ - Primary care visits: $15 copay
42
+ - Specialist visits: $30 copay (with referral)
43
+ - Emergency room: $200 copay
44
+ - Generic prescriptions: $5 copay
45
+ - Brand name prescriptions: $25 copay
46
+
47
+ Covered Services:
48
+ - Preventive and routine care
49
+ - Prenatal and maternity services
50
+ - Behavioral health support
51
+ - Diagnostic imaging and lab services
52
+
53
+ Exclusions:
54
+ - Out-of-network care (except emergencies)
55
+ - Cosmetic procedures
56
+ - Alternative therapies (e.g., acupuncture)
57
+
58
+ Contact Information:
59
+ For questions about coverage, contact Member Services at 1-800-555-1234.
data/css.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ custom_css = """
2
+ <style>
3
+ body, .gradio-container {
4
+ font-family: 'Roboto', sans-serif;
5
+ }
6
+
7
+ h1, h2, h3, label {
8
+ font-family: 'Fira Code', monospace;
9
+ color: #2c3e50;
10
+ }
11
+
12
+ textarea, input, select, button {
13
+ font-family: 'Courier New', monospace;
14
+ font-size: 15px;
15
+ }
16
+ </style>
17
+ """
requirements.txt CHANGED
Binary files a/requirements.txt and b/requirements.txt differ
 
src/agent/__pycache__/agenttools.cpython-312.pyc ADDED
Binary file (4.36 kB). View file
 
src/agent/__pycache__/custom_agent.cpython-312.pyc ADDED
Binary file (6.17 kB). View file
 
src/agent/agenttools.py ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from llama_index.core.tools import FunctionTool
2
+ from src.setup.utils import retry
3
+ from src.controller.customlogger import logging
4
+ from src.llm.source_llm import LLMCall
5
+
6
+
7
+ class ChatBotFunctionTools:
8
+ def __init__(self, llm_type="google"):
9
+ self.generator = LLMCall(llm_type).get_llm()
10
+
11
+ @retry(max_retries=5, delay=1)
12
+ def machine_learning_concept(self, query):
13
+ logging.info(f"Tool Call: machine_learning_concept('{query}')")
14
+ prompt = (
15
+ "You are a Machine Learning teacher.\n"
16
+ "Explain the following ML concept in:\n"
17
+ "The explaination should include geometrical or mathematical intuition"
18
+ "Try to keep answer crisp and compact"
19
+ f"User Query: {query}"
20
+ )
21
+ return self.generator.complete(prompt)
22
+
23
+ @retry(max_retries=5, delay=1)
24
+ def math_concept(self, query):
25
+ logging.info(f"Tool Call: math_concept('{query}')")
26
+ prompt = (
27
+ "You are a Math teacher.\n"
28
+ "Explain the following mathematics behind the Machine Learning algorithm in details with each step by step :\n"
29
+ "Try to keep answer crisp and compact"
30
+ f"User Query: {query}"
31
+ )
32
+ return self.generator.complete(prompt)
33
+
34
+ @retry(max_retries=5, delay=1)
35
+ def deep_learning_architecture(self, arch):
36
+ logging.info(f"Tool Call: deep_learning_architecture('{arch}')")
37
+ prompt = f"Explain the {arch} neural network architecture with diagram description"
38
+ return self.generator.complete(prompt)
39
+
40
+ @retry(max_retries=5, delay=1)
41
+ def visualize_algorithm(self, algo):
42
+ logging.info(f"Tool Call: visualize_algorithm('{algo}')")
43
+ prompt = f"Create visualization code that demonstrates how {algo} works"
44
+ return self.generator.complete(prompt)
45
+
46
+ @retry(max_retries=5, delay=1)
47
+ def concept_combiner(self, concepts):
48
+ logging.info(f"Tool Call: concept_combiner('{concepts}')")
49
+ prompt = f"Explain the relationship between these concepts: {', '.join(concepts)}"
50
+ return self.generator.complete(prompt)
51
+
52
+ @retry(max_retries=5, delay=1)
53
+ def llm_query(self, concepts):
54
+ logging.info(f"Tool Call: llm_query('{concepts}')")
55
+ prompt = f"You are an Expert to Answer the following question respond to the best of your knowledge: {', '.join(concepts)}"
56
+ return self.generator.complete(prompt)
57
+
58
+ @retry(max_retries=5, delay=1)
59
+ def get_tools(self):
60
+ return {
61
+ "ml_concept": FunctionTool.from_defaults(fn=self.machine_learning_concept),
62
+ "dl_architecture": FunctionTool.from_defaults(fn=self.deep_learning_architecture),
63
+ "algo_visualizer": FunctionTool.from_defaults(fn=self.visualize_algorithm),
64
+ "concept_combiner": FunctionTool.from_defaults(fn=self.concept_combiner),
65
+ "math_concept": FunctionTool.from_defaults(fn=self.math_concept),
66
+ "llm_query": FunctionTool.from_defaults(fn=self.llm_query)
67
+ }
68
+
69
+
70
+
71
+ # class LearningAgent:
72
+ # """Core agent that orchestrates tool usage for learning system"""
73
+ #
74
+ # def __init__(self, llm_value):
75
+ # self.llm = LLMCall(llm_type=llm_value).get_llm()
76
+ # self.tools = self._setup_tools()
77
+ # self.chat_history: List[Dict[str, str]] = [] # Stores properly formatted messages
78
+ # self.max_history = 20
79
+ #
80
+ # def _setup_tools(self) -> Dict[str, FunctionTool]:
81
+ # """Initialize all learning tools"""
82
+ # return {
83
+ # **self._setup_ml_tools(),
84
+ # **self._setup_dl_tools(),
85
+ # **self._setup_graph_tools(),
86
+ # **self._setup_utility_tools()
87
+ # }
88
+ #
89
+ # def _setup_ml_tools(self) -> Dict[str, FunctionTool]:
90
+ # """Machine Learning tools"""
91
+ #
92
+ # def ml_concept_explainer(query: str) -> str:
93
+ # prompt = f"Explain this ML concept in simple terms with examples: {query}"
94
+ # return self.llm.complete(prompt).text
95
+ #
96
+ # return {
97
+ # "ml_concept": FunctionTool.from_defaults(fn=ml_concept_explainer)
98
+ # }
99
+ #
100
+ # def _setup_dl_tools(self) -> Dict[str, FunctionTool]:
101
+ # """Deep Learning tools"""
102
+ #
103
+ # def dl_architecture(arch: str) -> str:
104
+ # prompt = f"Explain the {arch} neural network architecture with diagram description"
105
+ # return self.llm.complete(prompt).text
106
+ #
107
+ # return {
108
+ # "dl_architecture": FunctionTool.from_defaults(fn=dl_architecture)
109
+ # }
110
+ #
111
+ # def _setup_graph_tools(self) -> Dict[str, FunctionTool]:
112
+ # """Graph/Visualization tools"""
113
+ #
114
+ # def visualize_algorithm(algo: str) -> str:
115
+ # prompt = f"Create visualization code that demonstrates how {algo} works"
116
+ # return self.llm.complete(prompt).text
117
+ #
118
+ # return {
119
+ # "algo_visualizer": FunctionTool.from_defaults(fn=visualize_algorithm)
120
+ # }
121
+ #
122
+ # def _setup_utility_tools(self) -> Dict[str, FunctionTool]:
123
+ # """Utility tools"""
124
+ #
125
+ # def concept_combiner(concepts: List[str]) -> str:
126
+ # prompt = f"Explain the relationship between these concepts: {', '.join(concepts)}"
127
+ # return self.llm.complete(prompt).text
128
+ #
129
+ # return {
130
+ # "concept_combiner": FunctionTool.from_defaults(fn=concept_combiner)
131
+ # }
132
+ #
133
+ # def extract_json_from_markdown(self, markdown_text):
134
+ # """
135
+ # Extract and parse JSON content from a markdown-style code block.
136
+ # Handles formats like ```json ... ```
137
+ # """
138
+ # try:
139
+ # # Extract JSON block using regex
140
+ # match = re.search(r"```json\s*(\{.*?\})\s*```", markdown_text, re.DOTALL)
141
+ # if not match:
142
+ # raise ValueError("No JSON block found in markdown")
143
+ #
144
+ # json_str = match.group(1)
145
+ # return json.loads(json_str)
146
+ # except Exception as e:
147
+ # print(f"[ERROR] Could not parse JSON: {e}")
148
+ # return None
149
+ #
150
+ # def determine_tools(self, query: str):
151
+ # """Decide which tools to use based on query"""
152
+ # previous_questions = ""
153
+ # if self.chat_history:
154
+ # previous_questions = "\n".join([msg["content"] for msg in self.chat_history if msg["role"] == "user"][:-1]) \
155
+ # if self.chat_history else "No previous questions"
156
+ # prompt = f"""Analyze this learning query and select appropriate tools also form the condensed query based on
157
+ # previous_questions and Query:
158
+ # Query: {query}
159
+ # Previous Query: {previous_questions}
160
+ # Available Tools: {list(self.tools.keys())}
161
+ # Return dictionary of tool names and condensed query as dictionary in the below format:
162
+ # ```json
163
+ # {{
164
+ # "condensed_query": condensed query considering chat history and user query as string,
165
+ # "tool_names": tool names as comma-separated list
166
+ # }}
167
+ # ```
168
+ # Do Not add additional text"""
169
+ #
170
+ # response = self.llm.complete(prompt).text
171
+ # response = self.extract_json_from_markdown(response)
172
+ # return [t.strip() for t in response['tool_names'].split(",") if t.strip() in self.tools], response["condensed_query"]
173
+ #
174
+ # def execute_tools(self, tools: List[str], query: str) -> tuple[str, str]:
175
+ # """Execute multiple tools and combine results"""
176
+ # tool_results = []
177
+ # content_results = []
178
+ #
179
+ # for tool in tools:
180
+ # try:
181
+ # tool_output = self.tools[tool](query)
182
+ # content = tool_output.content if isinstance(tool_output, ToolOutput) else str(tool_output)
183
+ # tool_results.append(tool)
184
+ # content_results.append(content)
185
+ # except Exception as e:
186
+ # logging.error(f"Tool {tool} failed: {str(e)}")
187
+ # tool_results.append(tool)
188
+ # content_results.append(f"Error: {str(e)}")
189
+ #
190
+ # if len(tool_results) > 1:
191
+ # combined = "\n\n".join(f"**{t}**:\n{c}" for t, c in zip(tool_results, content_results))
192
+ # explanation = self.tools["concept_combiner"](content_results)
193
+ # return "multiple", f"{combined}\n\n**Combined Analysis**:\n{explanation}"
194
+ # return tool_results[0], content_results[0]
195
+ #
196
+ # def process_query(self, query: str) -> tuple[List[Dict[str, str]], str, str]:
197
+ # """Process query and return properly formatted messages"""
198
+ # tools, condensed_query = self.determine_tools(query)
199
+ # logging.info(f"Selected tools: {tools}")
200
+ #
201
+ # tool_used, response = self.execute_tools(tools, condensed_query)
202
+ #
203
+ # # Format messages for Gradio Chatbot
204
+ # user_msg = {"role": "user", "content": query.title()}
205
+ # assistant_msg = {"role": "assistant", "content": response}
206
+ #
207
+ # self.chat_history.extend([user_msg, assistant_msg])
208
+ # if len(self.chat_history) > self.max_history * 2: # *2 for user+assistant pairs
209
+ # self.chat_history = self.chat_history[-(self.max_history * 2):]
210
+ #
211
+ # return self.chat_history, tool_used, response
src/agent/custom_agent.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re, ast
2
+ import logging
3
+
4
+ import re
5
+ import json
6
+ import logging
7
+ from typing import List, Dict
8
+
9
+ from llama_index.core.tools.types import ToolOutput
10
+ from src.agent.agenttools import ChatBotFunctionTools
11
+
12
+
13
+ class LearningAgent:
14
+ def __init__(self, llm_value: str):
15
+ tool_builder = ChatBotFunctionTools(llm_type=llm_value)
16
+ self.llm = tool_builder.generator
17
+ self.tools = tool_builder.get_tools()
18
+ self.chat_history: List[Dict[str, str]] = []
19
+ self.max_history = 20
20
+
21
+ def extract_json_from_markdown(self, markdown_text: str):
22
+ try:
23
+ match = re.search(r"```json\s*(\{.*?\})\s*```", markdown_text, re.DOTALL)
24
+ if not match:
25
+ raise ValueError("No JSON block found in markdown")
26
+ return json.loads(match.group(1))
27
+ except Exception as e:
28
+ logging.error(f"Could not parse JSON: {e}")
29
+ return None
30
+
31
+ def determine_tools(self, query: str):
32
+ previous_questions = "\n".join(
33
+ [msg["content"] for msg in self.chat_history if msg["role"] == "user"]
34
+ ) if self.chat_history else "No previous questions"
35
+
36
+ prompt = f"""Analyze this learning query and select appropriate tools also form the condensed query based on
37
+ previous_questions and Query:
38
+ For Choosing tool properly analyze the condensed query and then decide. Choose multiple if its necessary based on condensed query
39
+ Its mandatory to select to atleast 1 tool
40
+ Query: {query}
41
+ Previous Query: {previous_questions}
42
+ Available Tools: {list(self.tools.keys())}
43
+ Return dictionary of tool names and condensed query as dictionary in the below format:
44
+ ```json
45
+ {{
46
+ "condensed_query": condensed query considering chat history and user query as string,
47
+ "tool_names": tool names as comma-separated list
48
+ }}
49
+ ```
50
+ Do Not add additional text"""
51
+ response = self.llm.complete(prompt)
52
+ try:
53
+ response = response.text
54
+ except:
55
+ response = response
56
+ parsed = self.extract_json_from_markdown(response)
57
+ condensed_query = parsed["condensed_query"]
58
+ tools = [t.strip() for t in parsed['tool_names'].split(",") if t.strip() in self.tools]
59
+ return tools if tools else ['llm_query'], condensed_query
60
+
61
+ def execute_tools(self, tools: List[str], query: str) -> tuple[str, str]:
62
+ tool_results, content_results = [], []
63
+ for tool in tools:
64
+ try:
65
+ tool_output = self.tools[tool](query)
66
+ content = tool_output.content if isinstance(tool_output, ToolOutput) else str(tool_output)
67
+ tool_results.append(tool)
68
+ content_results.append(content)
69
+ except Exception as e:
70
+ logging.error(f"Tool {tool} failed: {str(e)}")
71
+ tool_results.append(tool)
72
+ content_results.append(f"Error: {str(e)}")
73
+
74
+ if len(tool_results) > 1:
75
+ combined = "\n\n".join(f"**{t}**:\n{c}" for t, c in zip(tool_results, content_results))
76
+ explanation = self.tools["concept_combiner"](content_results)
77
+ return "multiple", f"{combined}\n\n**Combined Analysis**:\n{explanation}"
78
+ return tool_results[0], content_results[0]
79
+
80
+ def process_query(self, query: str) -> tuple[List[Dict[str, str]], str, str]:
81
+ tools, condensed_query = self.determine_tools(query)
82
+ tool_used, response = self.execute_tools(tools, condensed_query)
83
+ self.chat_history += [{"role": "user", "content": query}, {"role": "assistant", "content": response}]
84
+ self.chat_history = self.chat_history[-(self.max_history * 2):]
85
+ return self.chat_history, tool_used, response
86
+
src/controller/__init__.py ADDED
File without changes
src/controller/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (169 Bytes). View file
 
src/controller/__pycache__/agent_cacher.cpython-312.pyc ADDED
Binary file (1.62 kB). View file
 
src/controller/__pycache__/customlogger.cpython-312.pyc ADDED
Binary file (355 Bytes). View file
 
src/controller/agent_cacher.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from src.setup.cache import RedisDataSource
3
+ from src.agent.custom_agent import LearningAgent
4
+
5
+
6
+ class AgentManager:
7
+ def __init__(self):
8
+ self.cache = RedisDataSource()
9
+
10
+ def get_agent(self, session_id, llm_type):
11
+ cached = self.cache.read(f"agent:{session_id}")
12
+ agent = LearningAgent(llm_type)
13
+ if cached and "chat_history" in cached:
14
+ agent.chat_history = [
15
+ msg for msg in cached["chat_history"]
16
+ if isinstance(msg, dict) and "role" in msg and "content" in msg
17
+ ]
18
+ return agent
19
+
20
+ def save_agent(self, session_id, agent):
21
+ self.cache.write(f"agent:{session_id}", {
22
+ "chat_history": [
23
+ {"role": msg["role"], "content": msg["content"]}
24
+ for msg in agent.chat_history
25
+ ]
26
+ })
src/controller/customlogger.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import logging
2
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
src/controller/utils.py ADDED
@@ -0,0 +1 @@
 
 
1
+ SYSTEM_PROMPT = "You are helpful, intelligent, and reroute queries efficiently."
src/llm/__pycache__/source_llm.cpython-312.pyc ADDED
Binary file (4.72 kB). View file
 
src/llm/source_llm.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from src.controller.customlogger import logging
3
+ from llama_index.llms.google_genai import GoogleGenAI
4
+ from llama_index.llms.openai import OpenAI
5
+ from llama_index.llms.huggingface import HuggingFaceLLM
6
+ from mistralai import Mistral
7
+ from llama_index.core.llms import ChatMessage
8
+ from dotenv import load_dotenv
9
+ load_dotenv()
10
+
11
+
12
+ class MistralWrapper:
13
+ def __init__(self):
14
+ self.client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
15
+ self.model = "mistral-large-latest"
16
+
17
+ def complete(self, messages, **kwargs):
18
+ chat_response = self.client.chat.complete(
19
+ model= self.model,
20
+ messages = [{"role":"user", "content":messages}])
21
+ return chat_response.choices[0].message.content
22
+
23
+ ## --- LLMCall ---
24
+ class LLMCall:
25
+ def __init__(self, llm_type="OpenAi", config=None):
26
+ self.llm_type = llm_type
27
+ self.config = config or {}
28
+ self.api_key_google = os.getenv("GOOGLE_API_KEY")
29
+ self.client = self.get_llm()
30
+
31
+ def get_llm(self):
32
+ if self.llm_type == "OpenAi":
33
+ logging.info("Initializing OpenAI LLM")
34
+ return self._get_openai_llm()
35
+ elif self.llm_type == "Google":
36
+ logging.info("Initializing Google Gemini LLM")
37
+ return self._get_google_llm()
38
+ elif self.llm_type == "HuggingFace":
39
+ logging.info("Initializing HuggingFace LLM")
40
+ return self._get_huggingface_llm()
41
+ elif self.llm_type == "Mistral":
42
+ logging.info("Initializing HuggingFace LLM")
43
+ return self._get_mistral()
44
+ else:
45
+ raise ValueError(f"Unsupported LLM type: {self.llm_type}")
46
+
47
+ def _get_openai_llm(self):
48
+ return OpenAI(
49
+ model=self.config.get("model", "gpt-3.5-turbo-0613"),
50
+ api_key=self.config.get("api_key"),
51
+ temperature=self.config.get("temperature", 0.7),
52
+ max_tokens=self.config.get("max_tokens", 1024)
53
+ )
54
+
55
+ def _get_google_llm(self):
56
+ return GoogleGenAI(
57
+ model="models/gemini-1.5-flash",
58
+ )
59
+
60
+ def _get_mistral(self):
61
+ return MistralWrapper()
62
+
63
+
64
+ def _get_huggingface_llm(self):
65
+ return HuggingFaceLLM(
66
+ model_name="HuggingFaceH4/zephyr-7b-beta",
67
+ tokenizer_name="HuggingFaceH4/zephyr-7b-beta",
68
+ context_window=self.config.get("context_window", 2048),
69
+ max_new_tokens=self.config.get("max_new_tokens", 256)
70
+ )
71
+
72
+
73
+ def get_client(self):
74
+ return self.client
src/setup/__pycache__/cache.cpython-312.pyc ADDED
Binary file (2.49 kB). View file
 
src/setup/cache.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, redis
2
+ from dotenv import load_dotenv
3
+ from src.controller.customlogger import logging
4
+
5
+ load_dotenv()
6
+
7
+
8
+ class RedisDataSource:
9
+ def __init__(self, host='localhost', port=6379, db=0):
10
+ self.host = os.environ.get("REDIS_HOST")
11
+ self.username = os.environ.get("REDIS_USERNAME")
12
+ self.password = os.environ.get("REDIS_PASSWORD")
13
+ self.port = os.environ.get("REDIS_PORT")
14
+ self.client = redis.Redis(host=self.host,
15
+ username=self.username,
16
+ password=self.password,
17
+ port=self.port,
18
+ decode_responses=True)
19
+
20
+ def read(self, session_id):
21
+ cache_data = self.client.get(session_id)
22
+ logging.info(f"Redis Read: session_id={session_id}, found={bool(cache_data)}")
23
+ return eval(cache_data) if cache_data else {}
24
+
25
+ def write(self, session_id, data):
26
+ try:
27
+ self.client.set(session_id, str(data))
28
+ logging.info(f"Redis Write: session_id={session_id}, data_keys={list(data.keys())}")
29
+ except Exception as e:
30
+ logging.error(f"Redis Write Error: {e}")
31
+ print(data)
32
+
src/setup/utils.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+
4
+ import time
5
+ import functools
6
+
7
+ def retry(max_retries=3, delay=1, exceptions=(Exception,)):
8
+ def decorator(func):
9
+ @functools.wraps(func)
10
+ def wrapper(*args, **kwargs):
11
+ retries = 0
12
+ while True:
13
+ try:
14
+ return func(*args, **kwargs)
15
+ except exceptions as e:
16
+ retries += 1
17
+ if retries > max_retries:
18
+ raise
19
+ print(f"Retrying {func.__name__} due to {e} (attempt {retries}/{max_retries})...")
20
+ time.sleep(delay)
21
+ return wrapper
22
+ return decorator