Spaces:
Running
Running
File size: 12,499 Bytes
4003576 57fce4e 35a5f1c a9cc6a5 f5c686f 35a5f1c 4003576 2788b1e 35a5f1c 4003576 35a5f1c b600e93 a9cc6a5 b600e93 35a5f1c 88b1a0d b600e93 f5c686f 4003576 b600e93 35a5f1c 4003576 35a5f1c 4003576 35a5f1c 2740235 35a5f1c 4003576 35a5f1c 4003576 35a5f1c 4003576 35a5f1c 4003576 2788b1e 35a5f1c 4003576 35a5f1c 4003576 35a5f1c 2788b1e 4003576 35a5f1c b600e93 4003576 35a5f1c 4003576 35a5f1c 4003576 35a5f1c 4003576 35a5f1c d18fcb7 cd9a3d3 d18fcb7 35a5f1c 3fc7131 cd9a3d3 35a5f1c ec99e1c 35a5f1c d18fcb7 3fc7131 d18fcb7 195a6ed 35a5f1c d18fcb7 35a5f1c 2740235 35a5f1c 2740235 35a5f1c 2740235 35a5f1c 2740235 35a5f1c 738595c 35a5f1c 8102a2e 35a5f1c 2740235 35a5f1c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
import os
import time
import json
import logging
from groq import Groq
from langchain.memory import ConversationBufferMemory
from langchain_openai import ChatOpenAI
from langchain_community.document_loaders import CSVLoader
from langchain_community.vectorstores import FAISS
from deep_translator import GoogleTranslator
# Set up logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class Comsatsbot:
def __init__(self, hf, llm, api_keys, chats_collection, paths, index_path='faiss_kb'):
logger.info("Initializing Comsatsbot...")
self.llm = llm
self.api_keys = api_keys
self.client = None
self.models = [
# "llama3-groq-70b-8192-tool-use-preview",
"llama-3.3-70b-versatile",
"llama3-70b-8192"
]
self.memory = ConversationBufferMemory(llm=self.llm, max_token_limit=3000)
self.chats_collection = chats_collection
self.index_path = index_path
self.hf = hf
self.faiss_index = None
self.faiss_retriever = None
self.paths = paths
self.initialize_faiss_index()
def load_data(self, paths):
logger.info(f"Loading data from paths: {paths}")
documents = []
for path in paths:
loader = CSVLoader(file_path=path)
data = loader.load()
documents.extend(data)
logger.debug(f"Loaded {len(documents)} documents.")
return documents
def initialize_faiss_index(self):
logger.info("Initializing FAISS index...")
if os.path.exists(self.index_path):
logger.info(f"FAISS index found at {self.index_path}. Loading...")
self.faiss_index = FAISS.load_local(self.index_path, self.hf, allow_dangerous_deserialization=True)
else:
logger.info(f"FAISS index not found. Creating a new one...")
documents = self.load_data(self.paths)
self.faiss_index = FAISS.from_documents(documents, self.hf)
self.faiss_index.save_local(self.index_path)
self.faiss_retriever = self.faiss_index.as_retriever(search_kwargs={"k": 5})
logger.info("FAISS index initialized successfully.")
def retrieve_answer(self, query):
logger.info(f"Retrieving answer for query: {query}")
if self.faiss_retriever:
result = self.faiss_retriever.invoke(query)
logger.debug(f"Retrieved answer: {result}")
return result
logger.warning("FAISS retriever is not initialized.")
return None
def create_chat_record(self, chat_id):
logger.info(f"Creating new chat record for chat_id: {chat_id}")
self.chats_collection.insert_one({
"_id": chat_id,
"history": []
})
def update_chat(self, chat_id, question, answer):
logger.info(f"Updating chat history for chat_id: {chat_id}")
self.chats_collection.update_one(
{"_id": chat_id},
{"$push": {"history": {"question": question, "answer": answer}}}
)
def load_chat(self, chat_id):
logger.info(f"Loading chat history for chat_id: {chat_id}")
chat_record = self.chats_collection.find_one({"_id": chat_id})
if not chat_record:
logger.error(f"Chat ID {chat_id} does not exist.")
raise KeyError(f"Chat ID {chat_id} does not exist.")
return chat_record.get('history', [])
def new_chat(self, chat_id):
logger.info(f"Creating new chat with ID: {chat_id}")
if self.chats_collection.find_one({"_id": chat_id}):
logger.error(f"Chat ID {chat_id} already exists.")
raise KeyError(f"Chat ID {chat_id} exists already.")
self.create_chat_record(chat_id)
return "success"
def delete_chat(self, chat_id):
logger.info(f"Deleting chat record for chat_id: {chat_id}")
if not self.chats_collection.find_one({"_id": chat_id}):
logger.error(f"Chat ID {chat_id} does not exist.")
raise KeyError(f"Chat ID {chat_id} does not exist.")
self.chats_collection.delete_one({"_id": chat_id})
return "success"
def get_system_prompt(self):
return """
You are a comsats assistant to help the user with comsats university-related queries. Your response should be concise, direct, and to the point. Avoid any unnecessary explanations. Always consider the provided context and chat history to generate the answer.
Use emojis only when required based on the user's tone and emotions. Do not overuse them in every answer. provide emojis only when it is context based required. Here's when you should use emojis:
- **Happy emotions**: Use π or π when the user expresses satisfaction or asks for something positive.
- **Sad emotions**: Use π when the user is asking about something disappointing or negative.
- **Surprise**: Use π― when the user expresses surprise.
- **Anger or frustration**: Use π‘ when the user expresses frustration or dissatisfaction.
If the user asks the same question repeatedly or asks an illogical question, feel free to use emojis to subtly convey frustration, confusion, or amusement.
you have to answer the all questions asked from you in relevant context. Do not answer out of the context.
If the user writes question in urdu, give answer in urdu.
If the user writes question in English, give answer in English .
please provide the personalized answer and provide answer quickly
please answer from the dataset i provided to you in csv files. And donot write in every answer that i donot know the exact answer.and refer website only where it is necessary.
Do not include the phrase "According to the provided context" or "Based on the chat history". Simply generate the answer like a human would, without referencing where the information comes from.
If the question requires a URL, format it like this:
[Click here to visit COMSATS](https://comsats.edu.pk).
Your task is to help students at COMSATS University, Attock campus, with their university-related queries. The following are key details about the university:
- Departments: CS, AI, SE, Math, BBA, EE, CE, English.
- Facilities: Cricket ground, football ground, two canteens (near CS and Math/EE), mosque near CS department, LT rooms in CS, classrooms in Math, and labs in EE.
- Admission: Accepts NTS test, CGPA requirements: 85% for CGPA 4.0, 79-84% for CGPA 3.66.
- Available degrees: BS Computer Science, BS Software Engineering, BS Artificial Intelligence, BS English, BS Math, BS Electrical Engineering, BS Computer Engineering, BS BBA.
Consider the following chat history for additional context to answer the question:
{history}
When answering:
- Answer in a conversational and friendly tone.
- Be concise and to the point, while still being helpful.
- If you donβt know the answer from the context or chat history, simply write the generalized answer from the model..
Context ends here. Now, answer the following question:
{question}
"""
def generate_response(self, question, history, context):
logger.info(f"Generating response for question: {question}")
prompt = self.get_system_prompt().format(question=question, history=history, context=context)
while True:
for api_key in self.api_keys:
self.client = Groq(api_key=api_key)
for model in self.models:
try:
logger.info(f"Calling model {model} for response...")
chat_completion = self.client.chat.completions.create(
messages=[
{"role": "system", "content": prompt},
{"role": "user", "content": f"Answer the following question: {question}"}
],
model=model,
max_tokens=1024,
)
response = chat_completion.choices[0].message.content
logger.debug(f"Received response: {response}")
return response
except Exception as e:
logger.error(f"Error with model {model}: {e}")
time.sleep(2)
continue
logger.warning("Unable to generate a response.")
return "Sorry, unable to provide an answer at this time."
def detect_language(self, question):
logger.info(f"Detecting language for question: {question}")
for api_key in self.api_keys:
self.client = Groq(api_key=api_key)
for model in self.models:
try:
chat_completion = self.client.chat.completions.create(
messages=[
{
"role": "system",
"content": """
You are an expert agent, and your task is to detect the language.
Return a JSON: {'detected_language': 'urdu' or 'english'}
"""
},
{
"role": "user",
"content": f"Detect the language for: {question}"
}
],
model=model,
max_tokens=256,
response_format={"type": "json_object"},
)
response = json.loads(chat_completion.choices[0].message.content)
detected_language = response['detected_language'].lower()
logger.debug(f"Detected language: {detected_language}")
return detected_language
except Exception as e:
logger.error(f"Error detecting language: {e}")
time.sleep(2)
continue
logger.warning("Unable to detect language.")
return "english"
def translate_urdu(self, text):
logger.info(f"Translating text to Urdu: {text}")
for api_key in self.api_keys:
self.client = Groq(api_key=api_key)
for model in self.models:
try:
chat_completion = self.client.chat.completions.create(
messages=[
{
"role": "system",
"content": """
Translate the following text into proper Urdu. Return a JSON:
{'text': 'translated urdu text'}
"""
},
{
"role": "user",
"content": f"Translate this: {text}"
}
],
model=model,
max_tokens=512,
response_format={"type": "json_object"},
)
response = json.loads(chat_completion.choices[0].message.content)
translated_text = response['text']
logger.debug(f"Translated text: {translated_text}")
return translated_text
except Exception as e:
logger.error(f"Error translating text: {e}")
time.sleep(2)
continue
return text
def response(self, question, chat_id):
logger.info(f"Processing response for question: {question} (chat_id: {chat_id})")
chat_history = self.load_chat(chat_id)
for entry in chat_history:
self.memory.save_context({"input": entry["question"]}, {"output": entry["answer"]})
language = self.detect_language(question)
if language == 'urdu':
question_translation = GoogleTranslator(source='ur', target='en').translate(question)
context = self.faiss_retriever.invoke(question_translation)
else:
context = self.faiss_retriever.invoke(question)
answer = self.generate_response(question, chat_history, context)
self.update_chat(chat_id, question, answer)
return answer |