2023-07-11 17:50:08 -04:00
|
|
|
import os
|
2023-09-15 23:11:16 -04:00
|
|
|
|
2023-07-24 10:28:12 -04:00
|
|
|
import numpy as np
|
2023-11-18 18:24:29 -05:00
|
|
|
from transformers import AutoModel
|
2023-11-16 21:03:06 -05:00
|
|
|
|
2023-09-15 23:11:16 -04:00
|
|
|
from extensions.openai.errors import ServiceUnavailableError
|
|
|
|
from extensions.openai.utils import debug_msg, float_list_to_base64
|
2023-11-10 10:34:27 -05:00
|
|
|
from modules.logging_colors import logger
|
2023-07-11 17:50:08 -04:00
|
|
|
|
2023-09-17 21:39:29 -04:00
|
|
|
embeddings_params_initialized = False
|
2023-11-06 00:38:29 -05:00
|
|
|
|
|
|
|
|
2023-09-17 21:39:29 -04:00
|
|
|
def initialize_embedding_params():
|
2023-11-06 00:38:29 -05:00
|
|
|
'''
|
|
|
|
using 'lazy loading' to avoid circular import
|
|
|
|
so this function will be executed only once
|
|
|
|
'''
|
2023-09-17 21:39:29 -04:00
|
|
|
global embeddings_params_initialized
|
|
|
|
if not embeddings_params_initialized:
|
|
|
|
from extensions.openai.script import params
|
2023-11-10 10:34:27 -05:00
|
|
|
|
|
|
|
global st_model, embeddings_model, embeddings_device
|
|
|
|
|
2023-09-17 21:39:29 -04:00
|
|
|
st_model = os.environ.get("OPENEDAI_EMBEDDING_MODEL", params.get('embedding_model', 'all-mpnet-base-v2'))
|
|
|
|
embeddings_model = None
|
|
|
|
# OPENEDAI_EMBEDDING_DEVICE: auto (best or cpu), cpu, cuda, ipu, xpu, mkldnn, opengl, opencl, ideep, hip, ve, fpga, ort, xla, lazy, vulkan, mps, meta, hpu, mtia, privateuseone
|
|
|
|
embeddings_device = os.environ.get("OPENEDAI_EMBEDDING_DEVICE", params.get('embedding_device', 'cpu'))
|
|
|
|
if embeddings_device.lower() == 'auto':
|
|
|
|
embeddings_device = None
|
2023-11-10 10:34:27 -05:00
|
|
|
|
2023-09-17 21:39:29 -04:00
|
|
|
embeddings_params_initialized = True
|
2023-07-11 17:50:08 -04:00
|
|
|
|
2023-09-15 23:11:16 -04:00
|
|
|
|
2023-11-08 09:25:43 -05:00
|
|
|
def load_embedding_model(model: str):
|
2023-11-10 10:34:27 -05:00
|
|
|
try:
|
|
|
|
from sentence_transformers import SentenceTransformer
|
|
|
|
except ModuleNotFoundError:
|
|
|
|
logger.error("The sentence_transformers module has not been found. Please install it manually with pip install -U sentence-transformers.")
|
|
|
|
raise ModuleNotFoundError
|
|
|
|
|
2023-09-17 21:39:29 -04:00
|
|
|
initialize_embedding_params()
|
2023-07-24 10:28:12 -04:00
|
|
|
global embeddings_device, embeddings_model
|
2023-07-11 17:50:08 -04:00
|
|
|
try:
|
2023-11-06 00:38:29 -05:00
|
|
|
print(f"Try embedding model: {model} on {embeddings_device}")
|
2023-11-18 18:24:29 -05:00
|
|
|
if 'jina-embeddings' in model:
|
|
|
|
embeddings_model = AutoModel.from_pretrained(model, trust_remote_code=True) # trust_remote_code is needed to use the encode method
|
|
|
|
embeddings_model = embeddings_model.to(embeddings_device)
|
|
|
|
else:
|
|
|
|
embeddings_model = SentenceTransformer(model, device=embeddings_device)
|
|
|
|
|
2023-11-10 10:34:27 -05:00
|
|
|
print(f"Loaded embedding model: {model}")
|
2023-07-11 17:50:08 -04:00
|
|
|
except Exception as e:
|
2023-07-24 10:28:12 -04:00
|
|
|
embeddings_model = None
|
2023-07-12 14:33:25 -04:00
|
|
|
raise ServiceUnavailableError(f"Error: Failed to load embedding model: {model}", internal_message=repr(e))
|
|
|
|
|
|
|
|
|
2023-11-10 10:34:27 -05:00
|
|
|
def get_embeddings_model():
|
2023-09-17 21:39:29 -04:00
|
|
|
initialize_embedding_params()
|
2023-07-11 17:50:08 -04:00
|
|
|
global embeddings_model, st_model
|
|
|
|
if st_model and not embeddings_model:
|
2023-11-05 18:42:45 -05:00
|
|
|
load_embedding_model(st_model) # lazy load the model
|
2023-11-10 10:34:27 -05:00
|
|
|
|
2023-07-11 17:50:08 -04:00
|
|
|
return embeddings_model
|
|
|
|
|
2023-07-12 14:33:25 -04:00
|
|
|
|
2023-07-24 10:28:12 -04:00
|
|
|
def get_embeddings_model_name() -> str:
|
2023-09-17 21:39:29 -04:00
|
|
|
initialize_embedding_params()
|
2023-07-11 17:50:08 -04:00
|
|
|
global st_model
|
|
|
|
return st_model
|
|
|
|
|
2023-07-12 14:33:25 -04:00
|
|
|
|
2023-07-24 10:28:12 -04:00
|
|
|
def get_embeddings(input: list) -> np.ndarray:
|
2023-11-05 18:42:45 -05:00
|
|
|
model = get_embeddings_model()
|
|
|
|
debug_msg(f"embedding model : {model}")
|
|
|
|
embedding = model.encode(input, convert_to_numpy=True, normalize_embeddings=True, convert_to_tensor=False)
|
2023-11-06 00:38:29 -05:00
|
|
|
debug_msg(f"embedding result : {embedding}") # might be too long even for debug, use at you own will
|
2023-11-05 18:42:45 -05:00
|
|
|
return embedding
|
2023-07-24 10:28:12 -04:00
|
|
|
|
2023-09-15 23:11:16 -04:00
|
|
|
|
2023-07-24 10:28:12 -04:00
|
|
|
def embeddings(input: list, encoding_format: str) -> dict:
|
|
|
|
embeddings = get_embeddings(input)
|
2023-07-11 17:50:08 -04:00
|
|
|
if encoding_format == "base64":
|
|
|
|
data = [{"object": "embedding", "embedding": float_list_to_base64(emb), "index": n} for n, emb in enumerate(embeddings)]
|
|
|
|
else:
|
2023-07-24 10:28:12 -04:00
|
|
|
data = [{"object": "embedding", "embedding": emb.tolist(), "index": n} for n, emb in enumerate(embeddings)]
|
2023-07-11 17:50:08 -04:00
|
|
|
|
|
|
|
response = {
|
|
|
|
"object": "list",
|
|
|
|
"data": data,
|
|
|
|
"model": st_model, # return the real model
|
|
|
|
"usage": {
|
|
|
|
"prompt_tokens": 0,
|
|
|
|
"total_tokens": 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
debug_msg(f"Embeddings return size: {len(embeddings[0])}, number: {len(embeddings)}")
|
2023-07-12 14:33:25 -04:00
|
|
|
return response
|