excel_analysis / utils.py
Ashish1722's picture
Upload 11 files
eb4b18c verified
Raw
History Blame Contribute Delete
4.6 kB
import logging
from pathlib import Path
from PyPDF2 import PdfReader
from sentence_transformers import SentenceTransformer
import faiss
import json
import concurrent.futures
import numpy as np
from typing import List, Tuple
from datetime import datetime
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('script_analysis.log'),
logging.StreamHandler()
]
)
class EmbeddingManager:
def __init__(self, output_dir: Path, max_workers: int = 6):
self.model = SentenceTransformer('all-MiniLM-L6-v2')
self.chunk_size = 512
self.output_dir = output_dir
(self.output_dir / 'embeddings').mkdir(exist_ok=True)
self.max_workers = max_workers
def extract_text(self, pdf_path: str) -> str:
with open(pdf_path, 'rb') as file:
reader = PdfReader(file)
text = ''
for page in reader.pages:
text += page.extract_text() + '\n'
return text
def create_chunks(self, text: str) -> list:
words = text.split()
chunks = []
current_chunk = []
current_size = 0
for word in words:
current_size += len(word) + 1
if current_size > self.chunk_size:
chunks.append(' '.join(current_chunk))
current_chunk = [word]
current_size = len(word)
else:
current_chunk.append(word)
if current_chunk:
chunks.append(' '.join(current_chunk))
return chunks
def process_chunk_batch(self, chunks: List[str]) -> np.ndarray:
"""Process a batch of chunks and return their embeddings."""
try:
return self.model.encode(chunks)
except Exception as e:
logging.error(f"Error encoding chunk batch: {e}")
raise
def save_embeddings(self, chunks: list,file_name:str):
try:
embeddings_dir = self.output_dir / 'embeddings' / file_name
embeddings_dir.mkdir(parents=True, exist_ok=True)
# Split chunks into batches for parallel processing
batch_size = len(chunks) // self.max_workers
batches = [chunks[i:i + batch_size] for i in range(0, len(chunks), batch_size)]
# Process batches in parallel
embeddings_list = []
with concurrent.futures.ProcessPoolExecutor(max_workers=self.max_workers) as executor:
future_to_batch = {executor.submit(self.process_chunk_batch, batch): batch
for batch in batches}
for future in concurrent.futures.as_completed(future_to_batch):
batch_embeddings = future.result()
embeddings_list.append(batch_embeddings)
# Combine all embeddings
embeddings = np.vstack(embeddings_list)
# Create and save FAISS index
index = faiss.IndexFlatL2(embeddings.shape[1])
index.add(embeddings.astype('float32'))
faiss.write_index(index, str(embeddings_dir / 'script.index'))
# Save metadata and chunks
metadata = {
'file_name': file_name,
'timestamp': datetime.now().isoformat(),
'num_chunks': len(chunks),
'chunk_size': self.chunk_size,
'model': 'all-MiniLM-L6-v2',
'embedding_dimension': embeddings.shape[1],
'num_workers': self.max_workers
}
with open(embeddings_dir / 'metadata.json', 'w') as f:
json.dump(metadata, f, indent=4)
with open(embeddings_dir / 'chunks.json', 'w') as f:
json.dump(chunks, f, indent=4)
logging.info(f"Saved embeddings and metadata to {embeddings_dir}")
return embeddings_dir
except Exception as e:
logging.error(f"Error saving embeddings: {e}")
raise
def process_script(self, data: str,filename):
chunks = self.create_chunks(data)
logging.info(f"Created {len(chunks)} chunks from script")
embeddings_dir = self.save_embeddings(chunks,file_name=filename)
return chunks, embeddings_dir