|
22 | 22 | import numpy as np |
23 | 23 | from langchain_core.documents import Document |
24 | 24 | from langchain_core.embeddings import Embeddings |
25 | | -from langchain_core.vectorstores import VectorStore |
| 25 | +from langchain_core.vectorstores import VectorStore, utils |
26 | 26 | from sqlalchemy.engine.row import RowMapping |
27 | 27 |
|
28 | 28 | from .engine import PostgresEngine |
@@ -788,7 +788,7 @@ async def amax_marginal_relevance_search_with_score_by_vector( |
788 | 788 | fetch_k = fetch_k if fetch_k else self.fetch_k |
789 | 789 | lambda_mult = lambda_mult if lambda_mult else self.lambda_mult |
790 | 790 | embedding_list = [json.loads(row[self.embedding_column]) for row in results] |
791 | | - mmr_selected = maximal_marginal_relevance( |
| 791 | + mmr_selected = utils.maximal_marginal_relevance( |
792 | 792 | np.array(embedding, dtype=np.float32), |
793 | 793 | embedding_list, |
794 | 794 | k=k, |
@@ -963,76 +963,3 @@ async def is_valid_index( |
963 | 963 | """ |
964 | 964 | results = await self.engine._afetch(query) |
965 | 965 | return bool(len(results) == 1) |
966 | | - |
967 | | - |
968 | | -### The following is copied from langchain-community until it's moved into core |
969 | | - |
970 | | -Matrix = Union[List[List[float]], List[np.ndarray], np.ndarray] |
971 | | - |
972 | | - |
973 | | -def maximal_marginal_relevance( |
974 | | - query_embedding: np.ndarray, |
975 | | - embedding_list: list, |
976 | | - lambda_mult: float = 0.5, |
977 | | - k: int = 4, |
978 | | -) -> List[int]: |
979 | | - """Calculate maximal marginal relevance.""" |
980 | | - if min(k, len(embedding_list)) <= 0: |
981 | | - return [] |
982 | | - if query_embedding.ndim == 1: |
983 | | - query_embedding = np.expand_dims(query_embedding, axis=0) |
984 | | - similarity_to_query = cosine_similarity(query_embedding, embedding_list)[0] |
985 | | - most_similar = int(np.argmax(similarity_to_query)) |
986 | | - idxs = [most_similar] |
987 | | - selected = np.array([embedding_list[most_similar]]) |
988 | | - while len(idxs) < min(k, len(embedding_list)): |
989 | | - best_score = -np.inf |
990 | | - idx_to_add = -1 |
991 | | - similarity_to_selected = cosine_similarity(embedding_list, selected) |
992 | | - for i, query_score in enumerate(similarity_to_query): |
993 | | - if i in idxs: |
994 | | - continue |
995 | | - redundant_score = max(similarity_to_selected[i]) |
996 | | - equation_score = ( |
997 | | - lambda_mult * query_score - (1 - lambda_mult) * redundant_score |
998 | | - ) |
999 | | - if equation_score > best_score: |
1000 | | - best_score = equation_score |
1001 | | - idx_to_add = i |
1002 | | - idxs.append(idx_to_add) |
1003 | | - selected = np.append(selected, [embedding_list[idx_to_add]], axis=0) |
1004 | | - return idxs |
1005 | | - |
1006 | | - |
1007 | | -def cosine_similarity(X: Matrix, Y: Matrix) -> np.ndarray: |
1008 | | - """Row-wise cosine similarity between two equal-width matrices.""" |
1009 | | - if len(X) == 0 or len(Y) == 0: |
1010 | | - return np.array([]) |
1011 | | - |
1012 | | - X = np.array(X) |
1013 | | - Y = np.array(Y) |
1014 | | - if X.shape[1] != Y.shape[1]: |
1015 | | - raise ValueError( |
1016 | | - f"Number of columns in X and Y must be the same. X has shape {X.shape} " |
1017 | | - f"and Y has shape {Y.shape}." |
1018 | | - ) |
1019 | | - try: |
1020 | | - import simsimd as simd # type: ignore |
1021 | | - |
1022 | | - X = np.array(X, dtype=np.float32) |
1023 | | - Y = np.array(Y, dtype=np.float32) |
1024 | | - Z = 1 - simd.cdist(X, Y, metric="cosine") |
1025 | | - if isinstance(Z, float): |
1026 | | - return np.array([Z]) |
1027 | | - return Z |
1028 | | - except ImportError: |
1029 | | - X_norm = np.linalg.norm(X, axis=1) |
1030 | | - Y_norm = np.linalg.norm(Y, axis=1) |
1031 | | - # Ignore divide by zero errors run time warnings as those are handled below. |
1032 | | - with np.errstate(divide="ignore", invalid="ignore"): |
1033 | | - similarity = np.dot(X, Y.T) / np.outer(X_norm, Y_norm) |
1034 | | - similarity[np.isnan(similarity) | np.isinf(similarity)] = 0.0 |
1035 | | - return similarity |
1036 | | - |
1037 | | - |
1038 | | -### End code from langchain-community |
0 commit comments