harshith1411 commited on
Commit
1bf21c8
Β·
verified Β·
1 Parent(s): 8fd2f6f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -85
app.py CHANGED
@@ -1,105 +1,142 @@
1
  import streamlit as st
2
  import os
 
 
 
 
 
 
 
3
  import time
4
- from langchain_openai import ChatOpenAI
5
- from openai import RateLimitError
6
 
7
- # YOUR API KEY (with rate limit handling)
8
  os.environ["OPENAI_API_KEY"] = "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"
9
 
10
- KNOWLEDGE = """
11
- SR University is located in Warangal, Telangana, India.
12
- Computer Science program focuses on AI/ML, DSA, Java/Python, AWS/Azure, software engineering.
13
-
14
- B.Tech student preparing for AI/ML internships. Skills: LeetCode, AI projects (robotic arms, drones),
15
- cloud certifications, competitive programming.
16
-
17
- Internship tips:
18
- 1. 300+ LeetCode (Easy:100, Medium:150, Hard:50)
19
- 2. 3 portfolio projects: RAG chatbot, object detection, RL agent
20
- 3. Apply startups: AngelList, Y Combinator
21
- 4. Practice system design, behavioral interviews
22
- 5. Target: Google, Microsoft, Hyderabad/Bangalore startups
23
- """
24
-
25
- def get_chat_response(query, max_retries=3):
26
- """Handle rate limits with retry + fallback"""
27
- llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
28
-
29
- for attempt in range(max_retries):
30
- try:
31
- prompt = f"""Use ONLY this context to answer:
32
-
33
- {KNOWLEDGE}
34
-
35
- Question: {query}
36
-
37
- Answer:"""
38
-
39
- response = llm.invoke(prompt).content
40
- return response
41
-
42
- except RateLimitError:
43
- if attempt < max_retries - 1:
44
- st.warning(f"Rate limit hit. Retrying in 10s... (Attempt {attempt + 1}/{max_retries})")
45
- time.sleep(10)
46
- continue
47
- else:
48
- # FALLBACK: Local rule-based response
49
- return get_fallback_response(query)
50
 
51
- return "Sorry, service temporarily unavailable. Try again later."
52
-
53
- def get_fallback_response(query):
54
- """FREE fallback - no API needed"""
55
- query_lower = query.lower()
 
56
 
57
- if "university" in query_lower or "sr" in query_lower:
58
- return "SR University is in Warangal, Telangana. Excellent CS program with AI/ML, DSA, cloud computing focus."
 
59
 
60
- elif "internship" in query_lower or "job" in query_lower:
61
- return """AI/ML Internship Tips:
62
- 1. Solve 300+ LeetCode problems
63
- 2. Build RAG chatbot (this project!)
64
- 3. Apply via AngelList, LinkedIn
65
- 4. Target Hyderabad/Bangalore startups"""
66
 
67
- elif "project" in query_lower:
68
- return "Portfolio projects: 1) RAG Chatbot (live now), 2) Object Detection (robotic arm), 3) RL Drone Agent"
 
 
 
 
 
69
 
70
- elif "leetcode" in query_lower:
71
- return "LeetCode: Easy(100) + Medium(150) + Hard(50) = 300 problems total"
 
 
 
 
 
 
 
72
 
73
- else:
74
- return "Ask about SR University, internships, LeetCode, or AI projects! πŸ’‘"
 
 
 
 
 
75
 
76
- st.title("🧠 RAG Chatbot")
77
- st.info("πŸ’‘ Works even if OpenAI quota exhausted!")
 
78
 
79
- if "messages" not in st.session_state:
80
- st.session_state.messages = []
81
 
82
- # Chat history
83
- for message in st.session_state.messages:
84
- with st.chat_message(message["role"]):
85
- st.markdown(message["content"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
 
87
- # Chat input
88
- if query := st.chat_input("Ask about university, internships, projects..."):
89
- st.session_state.messages.append({"role": "user", "content": query})
90
- with st.chat_message("user"):
91
- st.markdown(query)
92
 
93
- with st.chat_message("assistant"):
94
- with st.spinner('Thinking...'):
95
- response = get_chat_response(query)
96
- st.markdown(response)
97
 
98
- st.session_state.messages.append({"role": "assistant", "content": response})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
- # Clear chat
101
- if st.sidebar.button("πŸ—‘οΈ Clear Chat"):
102
- st.session_state.messages = []
103
- st.rerun()
 
 
 
 
 
 
104
 
105
- st.sidebar.success("βœ… Works with/without OpenAI quota!")
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
  import os
3
+ from langchain_openai import ChatOpenAI, OpenAIEmbeddings
4
+ from langchain_community.document_loaders import TextLoader, PyPDFLoader
5
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
6
+ from langchain.vectorstores import FAISS
7
+ from langchain.prompts import ChatPromptTemplate
8
+ from langchain_core.output_parsers import StrOutputParser
9
+ import tempfile
10
  import time
 
 
11
 
12
+ # YOUR API KEY
13
  os.environ["OPENAI_API_KEY"] = "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"
14
 
15
+ @st.cache_resource
16
+ def load_vectorstore(_file_path):
17
+ """Load or create vectorstore from uploaded file"""
18
+ if os.path.exists("faiss_index"):
19
+ embeddings = OpenAIEmbeddings()
20
+ vectorstore = FAISS.load_local("faiss_index", embeddings, allow_dangerous_deserialization=True)
21
+ return vectorstore
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ # Process uploaded file
24
+ file_ext = _file_path.split('.')[-1].lower()
25
+ if file_ext == 'pdf':
26
+ loader = PyPDFLoader(_file_path)
27
+ else:
28
+ loader = TextLoader(_file_path)
29
 
30
+ docs = loader.load()
31
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
32
+ splits = text_splitter.split_documents(docs)
33
 
34
+ embeddings = OpenAIEmbeddings()
35
+ vectorstore = FAISS.from_documents(splits, embeddings)
36
+ vectorstore.save_local("faiss_index")
 
 
 
37
 
38
+ st.sidebar.success("βœ… Vector index created from your document!")
39
+ return vectorstore
40
+
41
+ def get_rag_chain(vectorstore):
42
+ """Create RAG chain"""
43
+ retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
44
+ llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
45
 
46
+ prompt = ChatPromptTemplate.from_template(
47
+ """You are a helpful assistant. Answer using ONLY the following context:
48
+
49
+ {context}
50
+
51
+ Question: {question}
52
+
53
+ Answer concisely and accurately. If answer not in context, say "I don't have that information.""""
54
+ )
55
 
56
+ chain = (
57
+ {"context": retriever, "question": lambda x: x}
58
+ | prompt
59
+ | llm
60
+ | StrOutputParser()
61
+ )
62
+ return chain
63
 
64
+ # === MAIN UI ===
65
+ st.title("🧠 Dynamic RAG Chatbot")
66
+ st.markdown("**Upload ANY document β†’ Ask ANY question β†’ Get accurate answers!**")
67
 
68
+ # File upload
69
+ uploaded_file = st.file_uploader("πŸ“€ Upload PDF or TXT", type=['pdf', 'txt'])
70
 
71
+ if uploaded_file is not None:
72
+ # Save uploaded file
73
+ with tempfile.NamedTemporaryFile(delete=False, suffix=f".{uploaded_file.name.split('.')[-1]}") as tmp_file:
74
+ tmp_file.write(uploaded_file.getvalue())
75
+ file_path = tmp_file.name
76
+
77
+ st.success(f"βœ… Loaded: {uploaded_file.name}")
78
+
79
+ # Load vectorstore
80
+ with st.spinner("πŸ”„ Indexing your document..."):
81
+ try:
82
+ vectorstore = load_vectorstore(file_path)
83
+ chain = get_rag_chain(vectorstore)
84
+ st.session_state.chain = chain
85
+ st.session_state.ready = True
86
+ except Exception as e:
87
+ st.error(f"Error: {str(e)}")
88
+ st.session_state.ready = False
89
 
90
+ # Chat interface (only if ready)
91
+ if 'ready' in st.session_state and st.session_state.ready:
92
+ st.success("πŸš€ Chatbot ready! Ask questions about your document.")
 
 
93
 
94
+ if "messages" not in st.session_state:
95
+ st.session_state.messages = []
 
 
96
 
97
+ # Chat history
98
+ for message in st.session_state.messages:
99
+ with st.chat_message(message["role"]):
100
+ st.markdown(message["content"])
101
+
102
+ # Chat input
103
+ if query := st.chat_input("πŸ’¬ Ask ANY question about your document..."):
104
+ st.session_state.messages.append({"role": "user", "content": query})
105
+ with st.chat_message("user"):
106
+ st.markdown(query)
107
+
108
+ with st.chat_message("assistant"):
109
+ with st.spinner("Searching document..."):
110
+ try:
111
+ response = st.session_state.chain.invoke(query)
112
+ st.markdown(response)
113
+ except Exception as e:
114
+ st.error(f"Error: {str(e)}")
115
+ st.markdown("Try re-uploading your document.")
116
+
117
+ st.session_state.messages.append({"role": "assistant", "content": response})
118
+
119
+ # Clear chat
120
+ if st.button("πŸ—‘οΈ Clear Chat"):
121
+ st.session_state.messages = []
122
+ st.rerun()
123
 
124
+ else:
125
+ st.info("πŸ‘† **Upload a PDF or TXT file to start chatting!**")
126
+ st.markdown("""
127
+ **Works with:**
128
+ β€’ Resumes/CVs (.pdf, .txt)
129
+ β€’ Research papers
130
+ β€’ Notes/lecture slides
131
+ β€’ Company docs
132
+ β€’ ANY text content!
133
+ """)
134
 
135
+ # Sidebar
136
+ with st.sidebar:
137
+ st.markdown("### 🎯 Features")
138
+ st.markdown("- Dynamic document upload")
139
+ st.markdown("- True RAG (vector search)")
140
+ st.markdown("- Handles PDF/TXT")
141
+ st.markdown("- Production UI")
142
+ st.markdown("- Portfolio ready!")