Files changed (1) hide show
  1. app.py +161 -113
app.py CHANGED
@@ -1,113 +1,161 @@
1
- import gradio as gr
2
- import openai
3
- import os
4
- from langchain.embeddings import HuggingFaceEmbeddings
5
- from langchain_community.vectorstores import Chroma
6
- from langchain.schema import Document
7
-
8
- # Load the Sentence Transformer Embedding Model
9
- model_name = "intfloat/e5-small"
10
- embedding_model = HuggingFaceEmbeddings(model_name=model_name)
11
-
12
- # Set up OpenAI API Key (Replace with your own API key)
13
- openai.api_key = os.getenv("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") # Add in Hugging Face Secrets
14
-
15
- # Load ChromaDB with RunGalileo Dataset
16
- persist_directory = "./docs/chroma/"
17
- vectordb = Chroma(persist_directory=persist_directory, embedding_function=embedding_model)
18
-
19
- from langchain_community.vectorstores import Chroma
20
- from langchain.embeddings import HuggingFaceEmbeddings
21
- from langchain.schema import Document
22
-
23
- # Load the embedding model
24
- model_name = "intfloat/e5-small"
25
- embedding_model = HuggingFaceEmbeddings(model_name=model_name)
26
-
27
- # Define the ChromaDB persist directory
28
- persist_directory = "./docs/chroma/"
29
-
30
- # Load ChromaDB (or create if empty)
31
- vectordb = Chroma(persist_directory=persist_directory, embedding_function=embedding_model)
32
-
33
- # Check if documents exist
34
- if vectordb._collection.count() == 0:
35
- print("⚠️ No documents found in ChromaDB. Re-indexing dataset...")
36
-
37
- # Sample dataset (Replace with real RunGalileo dataset)
38
- documents = [
39
- Document(page_content="HVAC systems help regulate indoor temperature."),
40
- Document(page_content="Chiller plants are used in large buildings for cooling."),
41
- Document(page_content="BACnet is a common protocol for building automation."),
42
- Document(page_content="Heat pumps are essential in modern energy-efficient HVAC designs."),
43
- Document(page_content="Smart thermostats improve energy efficiency through AI-based control.")
44
- ]
45
-
46
- # Insert documents into ChromaDB
47
- vectordb.add_documents(documents)
48
-
49
- print(" Documents successfully indexed into ChromaDB.")
50
- else:
51
- print(f" ChromaDB contains {vectordb._collection.count()} documents.")
52
-
53
-
54
- # Function to Retrieve Top-K Relevant Documents
55
- def retrieve_documents(question, k=5):
56
- """Retrieve top K relevant documents from ChromaDB"""
57
- docs = vectordb.similarity_search(question, k=k)
58
-
59
- if not docs:
60
- return ["⚠️ No relevant documents found. Try a different query."]
61
-
62
- return [doc.page_content for doc in docs]
63
-
64
-
65
- # Function to Generate AI Response
66
- import openai
67
-
68
- def generate_response(question, context):
69
- """Generate AI response using OpenAI GPT-4"""
70
-
71
- if not context or "No relevant documents found." in context:
72
- return "No relevant context available. Try a different query."
73
-
74
- full_prompt = f"Context: {context}\n\nQuestion: {question}"
75
-
76
- try:
77
- client = openai.OpenAI() # New OpenAI client format
78
- response = client.chat.completions.create(
79
- model="gpt-4",
80
- messages=[
81
- {"role": "system", "content": "You are an AI assistant that answers user queries based on the given context."},
82
- {"role": "user", "content": full_prompt}
83
- ],
84
- max_tokens=300,
85
- temperature=0.7
86
- )
87
- return response.choices[0].message.content.strip()
88
- except Exception as e:
89
- return f"Error generating response: {str(e)}"
90
-
91
-
92
- # Full RAG Pipeline
93
- def rag_pipeline(question):
94
- retrieved_docs = retrieve_documents(question, k=5)
95
- context = " ".join(retrieved_docs)
96
- response = generate_response(question, context)
97
- return response, "\n\n".join(retrieved_docs)
98
-
99
- # Gradio UI Interface
100
- iface = gr.Interface(
101
- fn=rag_pipeline,
102
- inputs=gr.Textbox(label="Enter your question"),
103
- outputs=[
104
- gr.Textbox(label="Generated Response"),
105
- gr.Textbox(label="Retrieved Documents")
106
- ],
107
- title="RAG-Based Question Answering System ",
108
- description="Enter a question and retrieve relevant documents with AI-generated response."
109
- )
110
-
111
- # βœ… Launch the Gradio App
112
- if __name__ == "__main__":
113
- iface.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import openai
3
+ import os
4
+ import nltk
5
+ import shutil
6
+ import numpy as np
7
+ import torch
8
+ from datasets import load_dataset
9
+ from langchain.embeddings import HuggingFaceEmbeddings
10
+ from langchain_community.vectorstores import Chroma
11
+ from langchain.schema import Document
12
+ from sentence_transformers import SentenceTransformer
13
+ from sklearn.metrics import mean_squared_error, roc_auc_score
14
+ from sklearn.feature_extraction.text import TfidfVectorizer
15
+ from sklearn.metrics.pairwise import cosine_similarity
16
+
17
+ # βœ… Load Pretrained Model
18
+ model_name = "bert-base-uncased"
19
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
20
+ embedding_model = HuggingFaceEmbeddings(model_name=model_name)
21
+ embedding_model.client.to(device)
22
+
23
+ # βœ… Set OpenAI API Key (Replace with your own)
24
+ openai.api_key = os.getenv("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")
25
+
26
+ # βœ… Download NLTK Dependencies
27
+ nltk.download('punkt')
28
+
29
+ # βœ… Load RunGalileo Datasets
30
+ ragbench = {}
31
+ for dataset in ['covidqa', 'cuad', 'delucionqa', 'emanual', 'expertqa', 'finqa', 'hagrid', 'hotpotqa', 'msmarco', 'pubmedqa', 'tatqa', 'techqa']:
32
+ ragbench[dataset] = load_dataset("rungalileo/ragbench", dataset)
33
+ print("Datasets Loaded βœ…")
34
+
35
+ # βœ… Function to Chunk Documents
36
+ def chunk_documents_semantic(documents, max_chunk_size=500):
37
+ chunks = []
38
+ for doc in documents:
39
+ sentences = nltk.sent_tokenize(doc)
40
+ current_chunk = ""
41
+ for sentence in sentences:
42
+ if len(current_chunk) + len(sentence) <= max_chunk_size:
43
+ current_chunk += sentence + " "
44
+ else:
45
+ chunks.append(current_chunk.strip())
46
+ current_chunk = sentence + " "
47
+ if current_chunk:
48
+ chunks.append(current_chunk.strip())
49
+ return chunks
50
+
51
+ # βœ… Chunk the Entire Dataset
52
+ chunked_ragbench = {}
53
+ for dataset_name in ragbench.keys():
54
+ for split in ragbench[dataset_name].keys():
55
+ original_documents_full = ragbench[dataset_name][split]['documents']
56
+ chunked_documents_full = chunk_documents_semantic(original_documents_full)
57
+ chunked_ragbench[split] = chunked_documents_full
58
+ print("Chunking Completed βœ…")
59
+
60
+ # βœ… Setup ChromaDB
61
+ persist_directory = "chroma_db_directory"
62
+ if os.path.exists(persist_directory):
63
+ shutil.rmtree(persist_directory)
64
+
65
+ documents = [Document(page_content=chunk) for chunk in chunked_documents_full]
66
+ vectordb = Chroma.from_documents(
67
+ documents=documents,
68
+ embedding=embedding_model,
69
+ persist_directory=persist_directory
70
+ )
71
+ vectordb.persist()
72
+
73
+ # βœ… Retrieve Documents
74
+ def retrieve_documents(question, k=5):
75
+ docs = vectordb.similarity_search(question, k=k)
76
+ if not docs:
77
+ return ["⚠️ No relevant documents found. Try a different query."]
78
+ return [doc.page_content for doc in docs]
79
+
80
+ # βœ… Generate AI Response
81
+ def generate_response(question, context):
82
+ if not context or "No relevant documents found." in context:
83
+ return "No relevant context available. Try a different query."
84
+
85
+ full_prompt = f"Context: {context}\n\nQuestion: {question}"
86
+
87
+ try:
88
+ client = openai.OpenAI()
89
+ response = client.chat.completions.create(
90
+ model="gpt-4",
91
+ messages=[
92
+ {"role": "system", "content": "You are an AI assistant that answers user queries based on the given context."},
93
+ {"role": "user", "content": full_prompt}
94
+ ],
95
+ max_tokens=300,
96
+ temperature=0.7
97
+ )
98
+ return response.choices[0].message.content.strip()
99
+ except Exception as e:
100
+ return f"Error generating response: {str(e)}"
101
+
102
+ # βœ… Compute Context Relevance, Utilization, Completeness, Adherence
103
+ def compute_cosine_similarity(text1, text2):
104
+ vectorizer = TfidfVectorizer()
105
+ vectors = vectorizer.fit_transform([text1, text2])
106
+ return cosine_similarity(vectors[0], vectors[1])[0][0]
107
+
108
+ def context_relevance(question, relevant_documents):
109
+ combined_docs = " ".join(relevant_documents)
110
+ return compute_cosine_similarity(question, combined_docs)
111
+
112
+ def context_utilization(response, relevant_documents):
113
+ combined_docs = " ".join(relevant_documents)
114
+ return compute_cosine_similarity(response, combined_docs)
115
+
116
+ def completeness(response, ground_truth_answer):
117
+ return compute_cosine_similarity(response, ground_truth_answer)
118
+
119
+ def adherence(response, relevant_documents):
120
+ combined_docs = " ".join(relevant_documents)
121
+ response_tokens = set(response.split())
122
+ relevant_tokens = set(combined_docs.split())
123
+ supported_tokens = response_tokens.intersection(relevant_tokens)
124
+ return len(supported_tokens) / len(response_tokens)
125
+
126
+ def compute_rmse(predicted_values, ground_truth_values):
127
+ return np.sqrt(mean_squared_error(ground_truth_values, predicted_values))
128
+
129
+ # βœ… Full RAG Pipeline
130
+ def rag_pipeline(question):
131
+ retrieved_docs = retrieve_documents(question, k=5)
132
+ context = " ".join(retrieved_docs)
133
+ response = generate_response(question, context)
134
+
135
+ # Compute Evaluation Metrics
136
+ ground_truth_answer = "Sample ground truth answer from dataset"
137
+ predicted_metrics = {
138
+ "context_relevance": context_relevance(question, retrieved_docs),
139
+ "context_utilization": context_utilization(response, retrieved_docs),
140
+ "completeness": completeness(response, ground_truth_answer),
141
+ "adherence": adherence(response, retrieved_docs)
142
+ }
143
+
144
+ return response, "\n\n".join(retrieved_docs), predicted_metrics
145
+
146
+ # βœ… Gradio UI Interface
147
+ iface = gr.Interface(
148
+ fn=rag_pipeline,
149
+ inputs=gr.Textbox(label="Enter your question"),
150
+ outputs=[
151
+ gr.Textbox(label="Generated Response"),
152
+ gr.Textbox(label="Retrieved Documents"),
153
+ gr.JSON(label="Evaluation Metrics")
154
+ ],
155
+ title="RAG-Based QA System for RunGalileo",
156
+ description="Enter a question and retrieve relevant documents with AI-generated response & evaluation metrics."
157
+ )
158
+
159
+ # βœ… Launch the Gradio App
160
+ if __name__ == "__main__":
161
+ iface.launch()