Spaces:
Sleeping
Sleeping
| import os | |
| import sys | |
| import numpy as np | |
| import pandas as pd | |
| from tqdm import tqdm | |
| import torch | |
| from sentence_transformers import SentenceTransformer | |
| import streamlit as st | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| def load_and_parse_data(data_path, emb_path): | |
| # FIX: Removed memory_map=True to prevent file locking | |
| docs = pd.read_parquet(data_path) | |
| chunks = list(docs["data"]) | |
| vecs = pd.read_parquet(emb_path) | |
| embs = vecs = np.stack(vecs['embedding'].values) | |
| return chunks, embs | |
| def get_model(): | |
| # 1. Determine where we are (Local vs Frozen/Exe) | |
| if getattr(sys, 'frozen', False): | |
| base_dir = sys._MEIPASS | |
| else: | |
| base_dir = os.path.dirname(os.path.abspath(__file__)) | |
| # 2. Check for the local folder | |
| local_model_path = os.path.join(base_dir, "models", "multilingual-e5-large") | |
| # 3. Decision Logic: Use Local if it exists, otherwise use Cloud | |
| if os.path.exists(local_model_path): | |
| print(f"π [System] Found local model at: {local_model_path}") | |
| model_source = local_model_path | |
| else: | |
| print(f"βοΈ [System] Local model not found. Downloading from Hugging Face...") | |
| model_source = "intfloat/multilingual-e5-large" | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| print(f"π [System] Loading Embedding Model ({model_source}) on {device}...") | |
| try: | |
| model = SentenceTransformer(model_source, device=device) | |
| print("β [System] Model loaded.") | |
| return model | |
| except Exception as e: | |
| print(f"β [System] Failed to load model: {e}") | |
| raise e | |
| def bge_embed(texts, batch_size=256): | |
| """ | |
| Standardizes text for E5 models. | |
| E5 requires 'query: ' prefix for search and 'passage: ' for storage. | |
| """ | |
| model = get_model() | |
| embeddings = [] | |
| if isinstance(texts, str): | |
| texts = [texts] | |
| # --- E5 SPECIFIC UPDATE --- | |
| # If the input is a single string (a query), we add the 'query: ' prefix. | |
| # If you are using this function to embed your database (passages), | |
| # you should change this prefix to 'passage: '. | |
| processed_texts = [] | |
| for t in texts: | |
| if not t.startswith("query: ") and not t.startswith("passage: "): | |
| # Defaulting to query prefix for the search function | |
| processed_texts.append(f"query: {t}") | |
| else: | |
| processed_texts.append(t) | |
| # --------------------------- | |
| for i in range(0, len(processed_texts), batch_size): | |
| batch = processed_texts[i:i + batch_size] | |
| batch_emb = model.encode( | |
| batch, | |
| batch_size=len(batch), | |
| show_progress_bar=False, | |
| normalize_embeddings=True | |
| ) | |
| embeddings.extend(batch_emb) | |
| return embeddings |