codewithharsha commited on
Commit
2c955fe
·
verified ·
1 Parent(s): f4d2810

Upload 2 files

Browse files
Files changed (2) hide show
  1. main.py +164 -0
  2. requirements.txt +12 -0
main.py ADDED
@@ -0,0 +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
+
requirements.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ flask
2
+ flask-cors
3
+ langchain
4
+ langchain_groq
5
+ langchain_text_splitters
6
+ langchain_community
7
+ langchain_huggingface
8
+ sentence-transformers
9
+ faiss-cpu
10
+ pypdf
11
+ python-dotenv
12
+ gunicorn