File size: 7,689 Bytes
78549c1 2e5073c 78549c1 1660a60 2e5073c 78549c1 2e5073c 78549c1 2e5073c 78549c1 2e5073c 78549c1 2e5073c 78549c1 2e5073c 78549c1 2e5073c 78549c1 2e5073c 78549c1 2e5073c 78549c1 2e5073c 78549c1 |
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 |
import os
import gradio as gr
from groq import Groq
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np
import PyPDF2
import re
from collections import Counter
from sklearn.metrics.pairwise import cosine_similarity
import logging
# Setup logging
logging.basicConfig(filename='query_logs.log', level=logging.INFO, format='%(asctime)s:%(levelname)s:%(message)s')
# Grog API key (Use environment variable or replace it with your actual API key)
grog_api_key = "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"
# Initialize groq API client
client = Groq(api_key=grog_api_key)
# Path to the already uploaded book
book_path = 'Generative_AI_Foundations_in_Python_Discover_key_techniques_and.pdf'
# Cache system to store previous responses
cache = {}
# Check if the file exists
if os.path.exists(book_path):
print(f"Book found at: {book_path}")
else:
print("Book not found!")
# Function to read the PDF file
def read_pdf(file_path):
with open(file_path, 'rb') as file:
reader = PyPDF2.PdfReader(file)
number_of_pages = len(reader.pages)
text = ""
for page_num in range(number_of_pages):
page = reader.pages[page_num]
text += page.extract_text()
return text
# Read the PDF content
book_text = read_pdf(book_path)
print(book_text[:1000]) # Print first 1000 characters of the book for verification
# Vectorization of the extracted PDF content
def vectorize_text(text):
try:
# Use Sentence Transformer to create embeddings
model = SentenceTransformer('all-MiniLM-L6-v2')
sentences = text.split('\n') # Split text into sentences for vectorization
embeddings = model.encode(sentences, show_progress_bar=True)
# Create FAISS index for similarity search
index = faiss.IndexFlatL2(embeddings.shape[1]) # L2 distance index
index.add(np.array(embeddings)) # Add embeddings to the index
print(f"Added {len(sentences)} sentences to the vector store.")
return index, sentences
except Exception as e:
print(f"Error during vectorization: {str(e)}")
return None, None
# Vectorize the extracted PDF text
vector_index, sentences = vectorize_text(book_text)
# Check if the vectorization was successful
if vector_index:
print("Vectorization complete.")
else:
print("Vectorization failed.")
# Function to generate embeddings for the query using the SentenceTransformer
def generate_query_embedding(query, sentence_transformer_model):
return sentence_transformer_model.encode([query])
# Function to check relevancy and handle out-of-bounds queries
def check_relevancy(D, threshold=0.4):
if D[0][0] > threshold:
return False
return True
# Function to generate diverse responses from the LLM with varied parameters
def generate_diverse_responses(client, prompt, n=3):
responses = []
for i in range(n):
temperature = 0.5 + (i * 0.2) # Vary temperature from 0.5 to 0.9
top_p = 0.9 - (i * 0.2) # Vary top-p from 0.9 to 0.7
try:
chat_completion = client.chat.completions.create(
messages=[{
"role": "user",
"content": prompt,
}],
model="llama3-8b-8192",
temperature=temperature,
top_p=top_p
)
responses.append(chat_completion.choices[0].message.content)
except Exception as e:
logging.error(f"Error generating response: {str(e)}")
responses.append("Sorry, an error occurred while generating this response.")
return responses
# Function to aggregate responses based on similarity and voting mechanism
def aggregate_responses(responses):
# Use a simple voting mechanism to select the most common response
response_counter = Counter(responses)
most_common_response = response_counter.most_common(1)[0][0]
# Rank responses by semantic similarity to the first response
model = SentenceTransformer('all-MiniLM-L6-v2')
embeddings = model.encode(responses)
first_embedding = embeddings[0].reshape(1, -1)
similarities = cosine_similarity(first_embedding, embeddings)[0]
top_response_index = np.argmax(similarities)
# Return the most similar response to the first response
return responses[top_response_index]
# Function to generate answers using the groq API with Llama model
def generate_answer_with_grog(query, vector_index, sentences, sentence_transformer_model):
# Check cache for previous queries
if query in cache:
logging.info(f"Cache hit for query: {query}")
return cache[query]
try:
# Get the query embedding using the sentence transformer
query_embedding = generate_query_embedding(query, sentence_transformer_model)
# Perform similarity search on the vector store (vector index)
D, I = vector_index.search(np.array(query_embedding), k=5) # Find top 5 similar sentences
# If no relevant content found, generate a fallback response
if len(I[0]) == 0 or D[0][0] > 1.0:
fallback_response = f"I couldn't find anything relevant in the document, but here's a general answer to your query: {query}"
chat_completion = client.chat.completions.create(
messages=[{
"role": "user",
"content": fallback_response,
}],
model="llama3-8b-8192",
)
cache[query] = chat_completion.choices[0].message.content
return cache[query]
# Retrieve the most relevant sentences
relevant_sentences = [sentences[i] for i in I[0]]
# Combine the relevant sentences for the final query
combined_text = " ".join(relevant_sentences)
# Create a prompt with the relevant content
final_prompt = f"**Relevant Information:**\n\n '{combined_text}'\n\n **Answer:** {query}"
# Generate diverse responses using the groq API
responses = generate_diverse_responses(client, final_prompt)
# Aggregate the responses to ensure stability and variety
final_response = aggregate_responses(responses)
# Cache the response for future queries
cache[query] = final_response
return final_response
except Exception as e:
logging.error(f"Error during answer generation with groq API: {str(e)}")
return f"Error during answer generation: {str(e)}"
# Gradio app function
def gradio_interface(query):
global vector_index, sentences
# Initialize the sentence transformer model
sentence_transformer_model = SentenceTransformer('all-MiniLM-L6-v2')
if vector_index is None or sentences is None:
return "Vector index or sentences not initialized properly."
# Generate the answer using the groq API and Llama model with varied responses
answer = generate_answer_with_grog(query, vector_index, sentences, sentence_transformer_model)
# Log the query and answer for monitoring
logging.info(f"Query: {query}, Answer: {answer}")
return f"### Here's your response:\n\n{answer}"
# Create the Gradio interface
iface = gr.Interface(
fn=gradio_interface,
inputs=gr.Textbox(label="Enter your query"),
outputs="markdown", # Use markdown output for better formatting
title="Generative_AI_Foundations_in_Python PDF-based Query Answering",
description="Ask any question about the content in the uploaded PDF and receive diverse, reliable answers."
)
# Launch the Gradio app
if __name__ == "__main__":
iface.launch()
|