Ventahana commited on
Commit
6120ef5
·
verified ·
1 Parent(s): 836c1c3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +151 -224
app.py CHANGED
@@ -1,266 +1,189 @@
1
  """
2
- Basic LlamaIndex Agent - Minimal working version
3
  """
4
  import os
5
- import sys
6
  from datetime import datetime
7
  from dotenv import load_dotenv
8
 
9
- # Load environment
10
  load_dotenv()
11
 
12
  print("=" * 60)
13
- print("🤖 Basic LlamaIndex Agent")
14
  print("=" * 60)
15
 
16
- # Try to import with fallbacks
 
 
 
 
 
 
 
 
 
17
  try:
18
- # Core imports that always exist
19
- from llama_index.core import Settings
20
  from llama_index.core.tools import FunctionTool
 
 
21
 
22
- # Try to import LLM
23
- try:
24
- from llama_index.llms.huggingface import HuggingFaceLLM
25
- HAS_HF_LLM = True
26
- except ImportError:
27
- print("⚠️ llama-index-llms-huggingface not installed")
28
- print("💡 Using dummy LLM for testing")
29
- HAS_HF_LLM = False
30
-
31
- # Try to import embeddings
32
- try:
33
- from llama_index.embeddings.huggingface import HuggingFaceEmbedding
34
- HAS_EMBEDDINGS = True
35
- except ImportError:
36
- print("⚠️ llama-index-embeddings-huggingface not installed")
37
- HAS_EMBEDDINGS = False
38
-
39
  print("✅ LlamaIndex imports successful")
40
 
41
  except ImportError as e:
42
- print(f"❌ Critical import error: {e}")
43
- print("\n💡 Install with: pip install llama-index-core transformers torch")
44
- sys.exit(1)
 
 
45
 
46
- # Setup LLM (with fallback)
47
- if HAS_HF_LLM:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  try:
49
- print("📦 Loading Hugging Face model...")
50
- Settings.llm = HuggingFaceLLM(
51
- model_name="distilbert/distilgpt2", # Smallest model
52
- tokenizer_name="distilbert/distilgpt2",
53
- max_new_tokens=50,
54
- generate_kwargs={"temperature": 0.1, "do_sample": True},
55
- device_map="cpu"
56
  )
57
- print("✅ LLM loaded successfully")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  except Exception as e:
59
- print(f"⚠️ Could not load HF model: {e}")
60
- HAS_HF_LLM = False
61
 
62
- if not HAS_HF_LLM:
63
- # Fallback to a mock LLM
64
- print("🔄 Using simple mock LLM")
65
- from llama_index.core.llms.mock import MockLLM
66
- Settings.llm = MockLLM()
67
 
68
- # Setup embeddings (optional)
69
- if HAS_EMBEDDINGS:
 
70
  try:
71
- Settings.embed_model = HuggingFaceEmbedding(
72
- model_name="sentence-transformers/all-MiniLM-L6-v2",
73
- device="cpu"
74
- )
75
  except:
76
- pass
77
 
78
- # ====== TOOLS DEFINITION ======
79
- # Define tools directly in app.py (no separate file needed)
 
80
 
81
- def calculate(expression: str) -> str:
82
- """Calculate mathematical expressions"""
83
  try:
84
- # Safe evaluation with only basic math
85
- allowed = set("0123456789+-*/(). ")
86
- if all(c in allowed for c in expression):
87
- result = eval(expression)
88
- return f"The answer is: {result}"
89
- return "Please use only numbers and + - * / ( )"
90
  except Exception as e:
91
- return f"Calculation error: {str(e)}"
92
 
93
- def get_time(query: str = "") -> str:
94
- """Get current date and time"""
95
- now = datetime.now()
96
- return f"Current date and time: {now.strftime('%A, %B %d, %Y at %I:%M:%S %p')}"
97
-
98
- def list_files(query: str = "") -> str:
99
- """List files in the data directory"""
100
- data_dir = "data"
101
- if not os.path.exists(data_dir):
102
- return "No 'data' directory found. Create one to add documents."
103
-
104
- files = os.listdir(data_dir)
105
- if not files:
106
- return "No files in data directory."
107
-
108
- return f"Files in data directory:\n" + "\n".join([f"• {f}" for f in files])
109
-
110
- def simple_search(query: str) -> str:
111
- """Search for text in files"""
112
- if not query:
113
- return "Please provide a search query."
114
-
115
- data_dir = "data"
116
- if not os.path.exists(data_dir):
117
- return "No data directory found."
118
-
119
- results = []
120
- for filename in os.listdir(data_dir):
121
- filepath = os.path.join(data_dir, filename)
122
- if os.path.isfile(filepath) and filename.endswith(('.txt', '.md', '.py')):
123
- try:
124
- with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
125
- content = f.read()
126
- if query.lower() in content.lower():
127
- results.append(filename)
128
- except:
129
- continue
130
-
131
- if results:
132
- return f"Found '{query}' in: {', '.join(results)}"
133
- else:
134
- return f"No results found for '{query}'"
135
-
136
- # Create tool objects
137
  tools = [
 
 
 
 
 
138
  FunctionTool.from_defaults(
139
  calculate,
140
  name="calculator",
141
- description="Useful for mathematical calculations. Input should be a valid math expression like '2 + 2' or '5 * (3 + 4)'"
142
  ),
143
  FunctionTool.from_defaults(
144
  get_time,
145
- name="time",
146
- description="Get the current date and time. No input needed."
147
- ),
148
- FunctionTool.from_defaults(
149
- list_files,
150
- name="list_files",
151
- description="List all files available in the data directory."
152
- ),
153
- FunctionTool.from_defaults(
154
- simple_search,
155
- name="search",
156
- description="Search for text in files within the data directory."
157
  )
158
  ]
159
 
160
  print(f"🛠️ Created {len(tools)} tools")
161
 
162
- # ====== AGENT CREATION ======
163
- # Try different ways to create an agent based on version
164
-
165
- agent = None
166
- agent_type = "Unknown"
167
-
168
  try:
169
- # Try v0.10+ method
170
- from llama_index.core.agent import AgentRunner, ReActAgentWorker
171
- agent_worker = ReActAgentWorker.from_tools(
172
  tools=tools,
173
  llm=Settings.llm,
174
  verbose=True,
175
- max_iterations=3
176
  )
177
- agent = AgentRunner(agent_worker)
178
- agent_type = "ReActAgent (v0.10+)"
179
- print(f" Created {agent_type}")
180
- except:
181
- try:
182
- # Try v0.9 method
183
- from llama_index.core.agent import ReActAgent
184
- agent = ReActAgent.from_tools(
185
- tools=tools,
186
- llm=Settings.llm,
187
- verbose=True,
188
- max_iterations=3
189
- )
190
- agent_type = "ReActAgent (v0.9)"
191
- print(f"✅ Created {agent_type}")
192
- except:
193
- try:
194
- # Try simple agent
195
- from llama_index.core.agent import AgentRunner, FunctionCallingAgentWorker
196
- agent_worker = FunctionCallingAgentWorker.from_tools(
197
- tools=tools,
198
- llm=Settings.llm
199
- )
200
- agent = AgentRunner(agent_worker)
201
- agent_type = "FunctionCallingAgent"
202
- print(f"✅ Created {agent_type}")
203
- except:
204
- # Last resort: Use QueryEngine with tools
205
- from llama_index.core.query_engine import ToolRetrieverRouterQueryEngine
206
- from llama_index.core.objects import ObjectIndex
207
- from llama_index.core import VectorStoreIndex
208
- from llama_index.core.schema import TextNode
209
-
210
- # Create a simple router
211
- nodes = [TextNode(text=f"Tool: {tool.metadata.name} - {tool.metadata.description}")
212
- for tool in tools]
213
- index = VectorStoreIndex(nodes)
214
-
215
- class SimpleAgent:
216
- def __init__(self, tools, llm):
217
- self.tools = {tool.metadata.name: tool for tool in tools}
218
- self.llm = llm
219
-
220
- def chat(self, query):
221
- # Simple routing logic
222
- if "time" in query.lower():
223
- return get_time()
224
- elif any(op in query for op in ['+', '-', '*', '/', 'calc']):
225
- # Extract numbers for calculation
226
- import re
227
- nums = re.findall(r'\d+', query)
228
- if nums:
229
- return calculate("+".join(nums))
230
- elif "search" in query.lower():
231
- return simple_search(query.replace("search", "").strip())
232
- elif "file" in query.lower():
233
- return list_files()
234
-
235
- # Default response
236
- return f"I received: '{query}'. I can help with calculations, time, files, and search."
237
-
238
- agent = SimpleAgent(tools, Settings.llm)
239
- agent_type = "SimpleRouter"
240
- print(f"✅ Created {agent_type}")
241
-
242
- # ====== MAIN CHAT LOOP ======
243
- def main():
244
- # Create data directory if it doesn't exist
245
- os.makedirs("data", exist_ok=True)
246
 
247
- # Create a sample file
248
- sample_file = os.path.join("data", "sample.txt")
249
- if not os.path.exists(sample_file):
250
- with open(sample_file, "w") as f:
251
- f.write("Welcome to the LlamaIndex agent.\n")
252
- f.write("This is a sample document for testing.\n")
253
- f.write("You can search for words like 'LlamaIndex', 'agent', or 'sample'.\n")
254
- print(f"📄 Created sample file: {sample_file}")
 
255
 
 
 
 
 
 
 
 
 
 
 
 
256
  print("\n" + "=" * 60)
257
- print(f"Agent Type: {agent_type}")
258
- print("Available tools: calculator, time, list_files, search")
259
- print("\n💡 Examples:")
260
  print("• 'What is 15 * 3?'")
261
  print("• 'What time is it?'")
262
- print("• 'List my files'")
263
- print("• 'Search for LlamaIndex'")
264
  print("• 'exit' to quit")
265
  print("=" * 60)
266
 
@@ -268,31 +191,35 @@ def main():
268
  try:
269
  user_input = input("\nYou: ").strip()
270
 
271
- if user_input.lower() in ['exit', 'quit', 'bye']:
272
  print("\n👋 Goodbye!")
273
  break
274
- elif user_input.lower() in ['help', '?']:
275
  print("\n📋 Help:")
276
- print("• I can do calculations: '2 + 2', '5 * 10'")
277
- print("• I can tell time: 'what time is it?'")
278
- print("• I can list files: 'list files'")
279
- print("• I can search: 'search for sample'")
280
- print("• Type 'exit' to quit")
281
  continue
282
- elif not user_input:
 
 
 
 
 
283
  continue
284
 
285
- # Get response
286
- print("🤔 Thinking...", end="", flush=True)
287
  response = agent.chat(user_input)
288
- print(f"\r🤖 Agent: {response}\n")
289
 
290
  except KeyboardInterrupt:
291
  print("\n\n👋 Goodbye!")
292
  break
293
  except Exception as e:
294
- print(f"\r❌ Error: {str(e)}")
295
- print("💡 Try a simpler query or type 'help'")
296
 
297
  if __name__ == "__main__":
298
  main()
 
1
  """
2
+ LlamaIndex Agent with HuggingFace Inference API
3
  """
4
  import os
 
5
  from datetime import datetime
6
  from dotenv import load_dotenv
7
 
8
+ # Load environment variables
9
  load_dotenv()
10
 
11
  print("=" * 60)
12
+ print("🤖 LlamaIndex Agent - HuggingFace API")
13
  print("=" * 60)
14
 
15
+ # Get token from environment (your secret)
16
+ HF_TOKEN = os.getenv("HUGGINGFACE_TOKEN")
17
+ if not HF_TOKEN:
18
+ print("❌ HUGGINGFACE_TOKEN not found in environment")
19
+ print("💡 Make sure your token is set in secrets")
20
+ exit(1)
21
+
22
+ print("✅ Found HuggingFace token")
23
+
24
+ # Import LlamaIndex
25
  try:
26
+ from llama_index.core import SimpleDirectoryReader, VectorStoreIndex, Settings
 
27
  from llama_index.core.tools import FunctionTool
28
+ from llama_index.core.agent import ReActAgent
29
+ from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  print("✅ LlamaIndex imports successful")
32
 
33
  except ImportError as e:
34
+ print(f"❌ Import error: {e}")
35
+ exit(1)
36
+
37
+ # Initialize HuggingFace API LLM
38
+ print("\n📡 Connecting to HuggingFace API...")
39
 
40
+ try:
41
+ # Initialize the LLM with HuggingFace API
42
+ llm = HuggingFaceInferenceAPI(
43
+ model_name="Qwen/Qwen2.5-Coder-32B-Instruct", # Use your preferred model
44
+ token=HF_TOKEN,
45
+ context_window=8192,
46
+ max_new_tokens=512,
47
+ generate_kwargs={"temperature": 0.1}
48
+ )
49
+
50
+ Settings.llm = llm
51
+ print(f"✅ Connected to: Qwen/Qwen2.5-Coder-32B-Instruct")
52
+
53
+ except Exception as e:
54
+ print(f"❌ API connection failed: {e}")
55
+ print("🔄 Trying alternative model...")
56
+
57
+ # Fallback to Mistral if Qwen fails
58
  try:
59
+ llm = HuggingFaceInferenceAPI(
60
+ model_name="mistralai/Mistral-7B-Instruct-v0.2",
61
+ token=HF_TOKEN,
62
+ context_window=4096,
63
+ max_new_tokens=256
 
 
64
  )
65
+ Settings.llm = llm
66
+ print(f"✅ Connected to: Mistral-7B-Instruct")
67
+ except Exception as e2:
68
+ print(f"❌ All connections failed: {e2}")
69
+ exit(1)
70
+
71
+ # ====== DOCUMENT SETUP ======
72
+ def setup_documents():
73
+ """Setup document index"""
74
+ data_dir = "./data"
75
+ os.makedirs(data_dir, exist_ok=True)
76
+
77
+ # Create sample file if empty
78
+ sample_file = f"{data_dir}/sample.txt"
79
+ if not os.path.exists(sample_file):
80
+ with open(sample_file, "w") as f:
81
+ f.write("LlamaIndex is a framework for building LLM applications.\n")
82
+ f.write("It helps you connect your data to large language models.\n")
83
+ f.write("HuggingFace provides access to thousands of models.\n")
84
+ f.write("The answer to life, the universe, and everything is 42.\n")
85
+ print(f"📄 Created {sample_file}")
86
+
87
+ # Load documents
88
+ try:
89
+ documents = SimpleDirectoryReader(data_dir).load_data()
90
+ index = VectorStoreIndex.from_documents(documents)
91
+ print(f"✅ Loaded {len(documents)} documents")
92
+ return index
93
  except Exception as e:
94
+ print(f"⚠️ Document error: {e}")
95
+ return VectorStoreIndex([])
96
 
97
+ # Create document index
98
+ index = setup_documents()
 
 
 
99
 
100
+ # ====== TOOLS ======
101
+ def calculate(expr: str) -> str:
102
+ """Calculate math expressions"""
103
  try:
104
+ allowed = set("0123456789+-*/(). ")
105
+ if all(c in allowed for c in expr):
106
+ return f"Result: {eval(expr)}"
107
+ return "Invalid characters"
108
  except:
109
+ return "Math error"
110
 
111
+ def get_time() -> str:
112
+ """Get current time"""
113
+ return f"Current time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
114
 
115
+ def search_docs(query: str) -> str:
116
+ """Search documents using direct query engine"""
117
  try:
118
+ query_engine = index.as_query_engine(
119
+ llm=Settings.llm,
120
+ response_mode="tree_summarize"
121
+ )
122
+ response = query_engine.query(query)
123
+ return str(response)
124
  except Exception as e:
125
+ return f"Search error: {e}"
126
 
127
+ # Create tools
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  tools = [
129
+ FunctionTool.from_defaults(
130
+ search_docs,
131
+ name="search_documents",
132
+ description="Search through your indexed documents for information"
133
+ ),
134
  FunctionTool.from_defaults(
135
  calculate,
136
  name="calculator",
137
+ description="Calculate mathematical expressions"
138
  ),
139
  FunctionTool.from_defaults(
140
  get_time,
141
+ name="get_time",
142
+ description="Get current date and time"
 
 
 
 
 
 
 
 
 
 
143
  )
144
  ]
145
 
146
  print(f"🛠️ Created {len(tools)} tools")
147
 
148
+ # ====== AGENT ======
 
 
 
 
 
149
  try:
150
+ agent = ReActAgent.from_tools(
 
 
151
  tools=tools,
152
  llm=Settings.llm,
153
  verbose=True,
154
+ max_iterations=5
155
  )
156
+ print("✅ Agent created successfully")
157
+ except Exception as e:
158
+ print(f"⚠️ Agent creation error: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
+ # Create simple fallback
161
+ class SimpleAgent:
162
+ def chat(self, query):
163
+ if any(op in query for op in ['+', '-', '*', '/']):
164
+ return calculate(query)
165
+ elif "time" in query.lower():
166
+ return get_time()
167
+ else:
168
+ return search_docs(query)
169
 
170
+ agent = SimpleAgent()
171
+ print("✅ Created simple agent")
172
+
173
+ # ====== DIRECT QUERY ENGINE (like your example) ======
174
+ direct_engine = index.as_query_engine(
175
+ llm=Settings.llm,
176
+ response_mode="tree_summarize"
177
+ )
178
+
179
+ # ====== MAIN ======
180
+ def main():
181
  print("\n" + "=" * 60)
182
+ print("🎯 Ready! Try these commands:")
183
+ print(" 'search What is LlamaIndex?'")
 
184
  print("• 'What is 15 * 3?'")
185
  print("• 'What time is it?'")
186
+ print("• 'direct What is the meaning of life?'")
 
187
  print("• 'exit' to quit")
188
  print("=" * 60)
189
 
 
191
  try:
192
  user_input = input("\nYou: ").strip()
193
 
194
+ if user_input.lower() == 'exit':
195
  print("\n👋 Goodbye!")
196
  break
197
+ elif user_input.lower() == 'help':
198
  print("\n📋 Help:")
199
+ print("• Ask questions - I'll search your documents")
200
+ print("• Do math: '2 + 2', '5 * 10'")
201
+ print("• Ask for time")
202
+ print("• Start with 'direct ' for direct query")
203
+ print("• 'exit' to quit")
204
  continue
205
+ elif user_input.lower().startswith('direct '):
206
+ # Direct query like your example
207
+ question = user_input[7:].strip()
208
+ print(f"�� Direct query: {question}")
209
+ response = direct_engine.query(question)
210
+ print(f"\n🤖 Answer: {response}")
211
  continue
212
 
213
+ # Use agent
214
+ print("🤔 Thinking...")
215
  response = agent.chat(user_input)
216
+ print(f"\n🤖 Agent: {response}")
217
 
218
  except KeyboardInterrupt:
219
  print("\n\n👋 Goodbye!")
220
  break
221
  except Exception as e:
222
+ print(f"\n❌ Error: {str(e)}")
 
223
 
224
  if __name__ == "__main__":
225
  main()