codewithharsha commited on
Commit
bea2229
·
verified ·
1 Parent(s): 40e16e4

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +164 -164
main.py CHANGED
@@ -1,164 +1,164 @@
1
- import os
2
- import time
3
- import json # Import JSON for parsing
4
- from flask import Flask, request, jsonify, render_template
5
- from flask_cors import CORS
6
- from langchain_groq import ChatGroq
7
- from langchain_text_splitters import RecursiveCharacterTextSplitter
8
- from langchain.chains.combine_documents import create_stuff_documents_chain
9
- from langchain_core.prompts import ChatPromptTemplate
10
- from langchain.chains import create_retrieval_chain
11
- from langchain_community.vectorstores import FAISS
12
- from langchain_community.document_loaders import PyPDFDirectoryLoader
13
- from langchain_huggingface import HuggingFaceEmbeddings
14
- from dotenv import load_dotenv
15
-
16
- # Load environment variables
17
- load_dotenv()
18
-
19
- # --- LLM and API Key Setup ---
20
- groq_api_key = os.getenv("GROQ_API_KEY")
21
-
22
- if not groq_api_key:
23
- raise ValueError("GROQ_API_KEY not found. Please set it in your .env file or as an environment variable.")
24
-
25
- llm = ChatGroq(groq_api_key=groq_api_key, model_name="llama-3.1-8b-instant")
26
-
27
-
28
- def load_retrieval_chain():
29
- """
30
- Loads the vector database and creates the retrieval chain.
31
- This function runs once when the server starts.
32
- """
33
- print("Loading vector database... This may take a moment.")
34
-
35
- # --- PROMPT TEMPLATE - Reverted to simple stateless version ---
36
- prompt_template = """
37
- You are a friendly and helpful hotel assistant.
38
- Your role is to provide clear, welcoming, and professional responses to guest questions.
39
- You MUST respond in a valid JSON format.
40
-
41
- The JSON object must have two keys:
42
- 1. "intent": (string) This will always be "qa" for this version.
43
- 2. "response": (string) Your natural language, conversational response to the user.
44
-
45
- RULES:
46
- - Base your answers ONLY on the provided context. If the information is not in the context,
47
- politely say "I'm sorry, I don't have that information, but I can connect you with our front desk for assistance."
48
- - Do not make up information.
49
-
50
- <context>
51
- {context}
52
- <context>
53
-
54
- Question: {input}
55
-
56
- Your JSON Response:
57
- """
58
- prompt = ChatPromptTemplate.from_template(prompt_template)
59
-
60
- embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
61
- loader = PyPDFDirectoryLoader("data")
62
- docs = loader.load()
63
-
64
- text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
65
- final_documents = text_splitter.split_documents(docs[:50])
66
-
67
- vectors = FAISS.from_documents(final_documents, embeddings)
68
-
69
- print("Vector database loaded successfully.")
70
-
71
- document_chain = create_stuff_documents_chain(llm, prompt)
72
-
73
- # 1. Create the retriever from the vector store
74
- retriever = vectors.as_retriever()
75
- # 2. Create the retrieval chain
76
- retrieval_chain = create_retrieval_chain(retriever, document_chain)
77
-
78
- return retrieval_chain
79
-
80
- # --- Flask App Initialization ---
81
- app = Flask(__name__)
82
- CORS(app) # Enable CORS for all routes in your app
83
-
84
- # Load the retrieval chain ONCE when the app starts
85
- try:
86
- retrieval_chain = load_retrieval_chain()
87
- except Exception as e:
88
- print(f"Failed to load vector database on startup: {e}")
89
- retrieval_chain = None
90
-
91
- # --- NEW ROUTE TO SERVE YOUR WEBPAGE ---
92
- @app.route("/")
93
- def index():
94
- """
95
- Serves the index.html file from the 'templates' folder.
96
- """
97
- return render_template('index.html')
98
-
99
- @app.route("/chat", methods=["POST"])
100
- def chat():
101
- """
102
- The main chat endpoint.
103
- Receives a JSON with "query" and returns a JSON with "intent" and "response".
104
- """
105
- if retrieval_chain is None:
106
- return jsonify({"error": "Vector database is not initialized. Check server logs."}), 500
107
-
108
- try:
109
- data = request.json
110
- user_query = data.get("query")
111
-
112
- if not user_query:
113
- return jsonify({"error": "No query provided"}), 400
114
-
115
- print(f"Received query: {user_query}")
116
-
117
- start = time.process_time()
118
-
119
- # Invoke the chain with the user's query
120
- response = retrieval_chain.invoke({'input': user_query})
121
-
122
- response_time = time.process_time() - start
123
- print(f"Response time: {response_time:.4f} seconds")
124
-
125
- # --- Parse the JSON response from the LLM ---
126
- try:
127
- # The LLM's answer is in the 'answer' field
128
- llm_output_str = response['answer']
129
- # The LLM output itself is a JSON string, so we parse it.
130
- parsed_response = json.loads(llm_output_str)
131
-
132
- # We can also add the RAG context for debugging
133
- parsed_response["context"] = [doc.page_content for doc in response['context']]
134
-
135
- print(f"LLM Response: {parsed_response}")
136
-
137
- return jsonify(parsed_response)
138
-
139
- except json.JSONDecodeError:
140
- print(f"Error: LLM did not return valid JSON. Response was: {llm_output_str}")
141
- return jsonify({"intent": "qa", "response": "I'm sorry, I had a small glitch. Could you rephrase that?"})
142
- except Exception as e:
143
- print(f"Error parsing LLM response: {e}")
144
- return jsonify({"intent": "qa", "response": "I'm sorry, I'm having trouble processing that request."})
145
-
146
- except Exception as e:
147
- print(f"Error processing request: {e}")
148
- return jsonify({"error": str(e)}), 500
149
-
150
- # --- /book ENDPOINT REMOVED ---
151
-
152
- # --- Run the Flask Server ---
153
- if __name__ == "__main__":
154
- # Ensure a 'data' directory exists
155
- if not os.path.exists("data"):
156
- os.makedirs("data")
157
- print("Created 'data' directory. Please add your PDF files here and restart the server.")
158
-
159
- # init_db() call removed
160
-
161
- print("Starting Flask server...")
162
- # Running on 0.0.0.0 makes it accessible on your network, ready for EC2
163
- app.run(debug=True, host="0.0.0.0", port=5000)
164
-
 
1
+ import os
2
+ import time
3
+ import json # Import JSON for parsing
4
+ from flask import Flask, request, jsonify, render_template
5
+ from flask_cors import CORS
6
+ from langchain_groq import ChatGroq
7
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
8
+ from langchain.chains.combine_documents import create_stuff_documents_chain
9
+ from langchain_core.prompts import ChatPromptTemplate
10
+ from langchain.chains import create_retrieval_chain
11
+ from langchain_community.vectorstores import FAISS
12
+ from langchain_community.document_loaders import PyPDFDirectoryLoader
13
+ from langchain_huggingface import HuggingFaceEmbeddings
14
+ from dotenv import load_dotenv
15
+
16
+ # Load environment variables
17
+ load_dotenv()
18
+
19
+ # --- LLM and API Key Setup ---
20
+ groq_api_key = os.getenv("GROQ_API_KEY")
21
+
22
+ if not groq_api_key:
23
+ raise ValueError("GROQ_API_KEY not found. Please set it in your .env file or as an environment variable.")
24
+
25
+ llm = ChatGroq(groq_api_key=groq_api_key, model_name="llama-3.1-8b-instant")
26
+
27
+
28
+ def load_retrieval_chain():
29
+ """
30
+ Loads the vector database and creates the retrieval chain.
31
+ This function runs once when the server starts.
32
+ """
33
+ print("Loading vector database... This may take a moment.")
34
+
35
+ # --- PROMPT TEMPLATE - Reverted to simple stateless version ---
36
+ prompt_template = """
37
+ You are a friendly and helpful hotel assistant.
38
+ Your role is to provide clear, welcoming, and professional responses to guest questions.
39
+ You MUST respond in a valid JSON format.
40
+
41
+ The JSON object must have two keys:
42
+ 1. "intent": (string) This will always be "qa" for this version.
43
+ 2. "response": (string) Your natural language, conversational response to the user.
44
+
45
+ RULES:
46
+ - Base your answers ONLY on the provided context. If the information is not in the context,
47
+ politely say "I'm sorry, I don't have that information, but I can connect you with our front desk for assistance."
48
+ - Do not make up information.
49
+
50
+ <context>
51
+ {context}
52
+ <context>
53
+
54
+ Question: {input}
55
+
56
+ Your JSON Response:
57
+ """
58
+ prompt = ChatPromptTemplate.from_template(prompt_template)
59
+
60
+ embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
61
+ loader = PyPDFDirectoryLoader("data")
62
+ docs = loader.load()
63
+
64
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
65
+ final_documents = text_splitter.split_documents(docs[:50])
66
+
67
+ vectors = FAISS.from_documents(final_documents, embeddings)
68
+
69
+ print("Vector database loaded successfully.")
70
+
71
+ document_chain = create_stuff_documents_chain(llm, prompt)
72
+
73
+ # 1. Create the retriever from the vector store
74
+ retriever = vectors.as_retriever()
75
+ # 2. Create the retrieval chain
76
+ retrieval_chain = create_retrieval_chain(retriever, document_chain)
77
+
78
+ return retrieval_chain
79
+
80
+ # --- Flask App Initialization ---
81
+ app = Flask(__name__)
82
+ CORS(app) # Enable CORS for all routes in your app
83
+
84
+ # Load the retrieval chain ONCE when the app starts
85
+ try:
86
+ retrieval_chain = load_retrieval_chain()
87
+ except Exception as e:
88
+ print(f"Failed to load vector database on startup: {e}")
89
+ retrieval_chain = None
90
+
91
+ # --- NEW ROUTE TO SERVE YOUR WEBPAGE ---
92
+ @app.route("/")
93
+ def index():
94
+ """
95
+ Serves the index.html file from the 'templates' folder.
96
+ """
97
+ return render_template('index.html')
98
+
99
+ @app.route("/chat", methods=["POST"])
100
+ def chat():
101
+ """
102
+ The main chat endpoint.
103
+ Receives a JSON with "query" and returns a JSON with "intent" and "response".
104
+ """
105
+ if retrieval_chain is None:
106
+ return jsonify({"error": "Vector database is not initialized. Check server logs."}), 500
107
+
108
+ try:
109
+ data = request.json
110
+ user_query = data.get("query")
111
+
112
+ if not user_query:
113
+ return jsonify({"error": "No query provided"}), 400
114
+
115
+ print(f"Received query: {user_query}")
116
+
117
+ start = time.process_time()
118
+
119
+ # Invoke the chain with the user's query
120
+ response = retrieval_chain.invoke({'input': user_query})
121
+
122
+ response_time = time.process_time() - start
123
+ print(f"Response time: {response_time:.4f} seconds")
124
+
125
+ # --- Parse the JSON response from the LLM ---
126
+ try:
127
+ # The LLM's answer is in the 'answer' field
128
+ llm_output_str = response['answer']
129
+ # The LLM output itself is a JSON string, so we parse it.
130
+ parsed_response = json.loads(llm_output_str)
131
+
132
+ # We can also add the RAG context for debugging
133
+ parsed_response["context"] = [doc.page_content for doc in response['context']]
134
+
135
+ print(f"LLM Response: {parsed_response}")
136
+
137
+ return jsonify(parsed_response)
138
+
139
+ except json.JSONDecodeError:
140
+ print(f"Error: LLM did not return valid JSON. Response was: {llm_output_str}")
141
+ return jsonify({"intent": "qa", "response": "I'm sorry, I had a small glitch. Could you rephrase that?"})
142
+ except Exception as e:
143
+ print(f"Error parsing LLM response: {e}")
144
+ return jsonify({"intent": "qa", "response": "I'm sorry, I'm having trouble processing that request."})
145
+
146
+ except Exception as e:
147
+ print(f"Error processing request: {e}")
148
+ return jsonify({"error": str(e)}), 500
149
+
150
+ # --- /book ENDPOINT REMOVED ---
151
+
152
+ # --- Run the Flask Server ---
153
+ if __name__ == "__main__":
154
+ # Ensure a 'data' directory exists
155
+ if not os.path.exists("data"):
156
+ os.makedirs("data")
157
+ print("Created 'data' directory. Please add your PDF files here and restart the server.")
158
+
159
+ # init_db() call removed
160
+
161
+ print("Starting Flask server...")
162
+ # Running on 0.0.0.0 makes it accessible on your network, ready for EC2
163
+ app.run(debug=True, host="0.0.0.0", port=7860)
164
+