Kal1510 commited on
Commit
d3a157d
·
verified ·
1 Parent(s): d6dc035

Update idea.txt

Browse files
Files changed (1) hide show
  1. idea.txt +242 -0
idea.txt CHANGED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ print("start1")
2
+ import os
3
+ import sys
4
+ import subprocess
5
+ import gradio as gr
6
+ from PyPDF2 import PdfReader
7
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
8
+ from langchain_community.vectorstores import FAISS
9
+ from langchain.prompts import PromptTemplate
10
+ from langchain.chains import LLMChain
11
+ from langchain_community.embeddings import HuggingFaceEmbeddings
12
+ from langchain.schema import Document
13
+ print("start2")
14
+
15
+
16
+ # Check if already installed to avoid reinstalling
17
+ try:
18
+ import llama_cpp
19
+ print("llama_cpp already installed.")
20
+ except ImportError:
21
+ print("Installing llama_cpp from wheel...")
22
+ subprocess.check_call([
23
+ sys.executable, "-m", "pip", "install",
24
+ "llama-cpp-python", "--no-binary", ":all:", "--force-reinstall"
25
+ ])
26
+
27
+
28
+ from llama_cpp import Llama
29
+ print("start3")
30
+ import warnings
31
+ warnings.filterwarnings("ignore")
32
+
33
+ print("Start")
34
+ import subprocess
35
+
36
+ subprocess.run([
37
+ "huggingface-cli", "download",
38
+ "TheBloke/Mistral-7B-Instruct-v0.1-GGUF",
39
+ "mistral-7b-instruct-v0.1.Q2_K.gguf",
40
+ "--local-dir", "./models",
41
+ "--local-dir-use-symlinks", "False"
42
+ ], check=True)
43
+
44
+ # ------------------------------
45
+ # Device and Embedding Setup (CPU optimized)
46
+ # ------------------------------
47
+ modelPath = "sentence-transformers/all-mpnet-base-v2"
48
+ model_kwargs = {"device": "cpu"} # Force CPU usage
49
+ encode_kwargs = {"normalize_embedding": False}
50
+
51
+ embeddings = HuggingFaceEmbeddings(
52
+ model_name=modelPath,
53
+ model_kwargs=model_kwargs,
54
+ encode_kwargs=encode_kwargs
55
+ )
56
+
57
+ # ------------------------------
58
+ # Load Mistral GGUF via llama.cpp (CPU optimized)
59
+ # ------------------------------
60
+ llm_cpp = Llama(
61
+ model_path="./models/mistral-7b-instruct-v0.1.Q2_K.gguf",
62
+ n_ctx=2048,
63
+ n_threads=4, # Adjust based on your CPU cores
64
+ n_gpu_layers=0, # Force CPU-only
65
+ temperature=0.7,
66
+ top_p=0.9,
67
+ repeat_penalty=1.1
68
+ )
69
+
70
+ # ------------------------------
71
+ # LangChain-compatible wrapper
72
+ # ------------------------------
73
+ def mistral_llm(prompt):
74
+ output = llm_cpp(
75
+ prompt,
76
+ max_tokens=512, # Reduced for CPU performance
77
+ stop=["</s>", "[INST]", "[/INST]"]
78
+ )
79
+ return output["choices"][0]["text"].strip()
80
+
81
+ # ------------------------------
82
+ # Prompt Template (unchanged)
83
+ # ------------------------------
84
+ def get_qa_prompt():
85
+ template = """<s>[INST] \
86
+ You are a helpful, knowledgeable AI assistant. Answer the user's question based on the provided context.
87
+
88
+ Guidelines:
89
+ - Respond in a natural, conversational tone
90
+ - Be detailed but concise
91
+ - Use paragraphs and bullet points when appropriate
92
+ - If you don't know, say so
93
+ - Maintain a friendly and professional demeanor
94
+
95
+ Conversation History:
96
+ {chat_history}
97
+
98
+ Relevant Context:
99
+ {context}
100
+
101
+ Current Question: {question}
102
+
103
+ Provide a helpful response: [/INST]"""
104
+ return PromptTemplate(
105
+ template=template,
106
+ input_variables=["context", "question", "chat_history"]
107
+ )
108
+
109
+ # ------------------------------
110
+ # PDF and Chat Logic (optimized for CPU)
111
+ # ------------------------------
112
+ def pdf_text(pdf_docs):
113
+ text = ""
114
+ for doc in pdf_docs:
115
+ reader = PdfReader(doc)
116
+ for page in reader.pages:
117
+ page_text = page.extract_text()
118
+ if page_text:
119
+ text += page_text + "\n"
120
+ return text
121
+
122
+ def get_chunks(text):
123
+ splitter = RecursiveCharacterTextSplitter(
124
+ chunk_size=800, # Smaller chunks for CPU
125
+ chunk_overlap=100,
126
+ length_function=len
127
+ )
128
+ chunks = splitter.split_text(text)
129
+ return [Document(page_content=chunk) for chunk in chunks]
130
+
131
+ def get_vectorstore(documents):
132
+ db = FAISS.from_documents(documents, embedding=embeddings)
133
+ db.save_local("faiss_index")
134
+
135
+ def format_chat_history(history):
136
+ return "\n".join([f"User: {q}\nAssistant: {a}" for q, a in history[-2:]]) # Shorter history
137
+
138
+ def handle_pdf_upload(pdf_files):
139
+ if not pdf_files:
140
+ return "⚠️ Upload at least one PDF"
141
+ try:
142
+ text = pdf_text(pdf_files)
143
+ if not text.strip():
144
+ return "⚠️ Could not extract text"
145
+ chunks = get_chunks(text)
146
+ get_vectorstore(chunks)
147
+ return f"✅ Processed {len(pdf_files)} PDF(s) with {len(chunks)} chunks"
148
+ except Exception as e:
149
+ return f"❌ Error: {str(e)}"
150
+
151
+ def user_query(msg, chat_history):
152
+ if not os.path.exists("faiss_index"):
153
+ chat_history.append((msg, "Please upload PDF documents first."))
154
+ return "", chat_history
155
+
156
+ try:
157
+ db = FAISS.load_local("faiss_index", embeddings, allow_dangerous_deserialization=True)
158
+ retriever = db.as_retriever(search_kwargs={"k": 2}) # Fewer documents for CPU
159
+ docs = retriever.get_relevant_documents(msg)
160
+ context = "\n\n".join([d.page_content for d in docs][:2]) # Limit context
161
+
162
+ prompt = get_qa_prompt()
163
+ final_prompt = prompt.format(
164
+ context=context[:1500], # Further limit context size
165
+ question=msg,
166
+ chat_history=format_chat_history(chat_history)
167
+ )
168
+
169
+ response = mistral_llm(final_prompt)
170
+ chat_history.append((msg, response))
171
+ return "", chat_history
172
+ except Exception as e:
173
+ error_msg = f"Sorry, I encountered an error: {str(e)}"
174
+ chat_history.append((msg, error_msg))
175
+ return "", chat_history
176
+
177
+ # ------------------------------
178
+ # Gradio Interface (your exact requested format)
179
+ # ------------------------------
180
+ with gr.Blocks(theme=gr.themes.Soft(), title="PDF Chat Assistant") as demo:
181
+ with gr.Row():
182
+ gr.Markdown("""
183
+ # 📚 PDF Chat Assistant
184
+ ### Have natural conversations with your documents ((Note: This Space runs on CPU, so responses may take a few mins.))
185
+ """)
186
+ with gr.Row():
187
+ with gr.Column(scale=1, min_width=300):
188
+ gr.Markdown("### Document Upload")
189
+ pdf_input = gr.File(
190
+ file_types=[".pdf"],
191
+ file_count="multiple",
192
+ label="Upload PDFs",
193
+ height=100
194
+ )
195
+ upload_btn = gr.Button("Process Documents", variant="primary")
196
+ status_box = gr.Textbox(label="Status", interactive=False)
197
+ gr.Markdown("""
198
+ **Instructions:**
199
+ 1. Upload PDF documents
200
+ 2. Click Process Documents
201
+ 3. Start chatting in the right panel
202
+ """)
203
+
204
+ with gr.Column(scale=2):
205
+ chatbot = gr.Chatbot(
206
+ height=600,
207
+ bubble_full_width=False,
208
+ avatar_images=(
209
+ "user.png",
210
+ "bot.png"
211
+ )
212
+ )
213
+
214
+ with gr.Row():
215
+ message = gr.Textbox(
216
+ placeholder="Type your question about the documents...",
217
+ show_label=False,
218
+ container=False,
219
+ scale=7,
220
+ autofocus=True
221
+ )
222
+ submit_btn = gr.Button("Send", variant="primary", scale=1)
223
+
224
+ with gr.Row():
225
+ clear_chat = gr.Button("🧹 Clear Conversation")
226
+ examples = gr.Examples(
227
+ examples=[
228
+ "Summarize the key points from the documents",
229
+ "What are the main findings?",
230
+ "Explain this in simpler terms"
231
+ ],
232
+ inputs=message,
233
+ label="Example Questions"
234
+ )
235
+
236
+ upload_btn.click(handle_pdf_upload, inputs=pdf_input, outputs=status_box)
237
+ submit_btn.click(user_query, inputs=[message, chatbot], outputs=[message, chatbot])
238
+ message.submit(user_query, inputs=[message, chatbot], outputs=[message, chatbot])
239
+ clear_chat.click(lambda: [], None, chatbot, queue=False)
240
+
241
+ if __name__ == "__main__":
242
+ demo.launch() # Disable sharing for local CPU use