jiarongqiu commited on
Commit
db15762
·
1 Parent(s): 45ed5ce

add pinecone service

Browse files
.gitignore ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.ipynb
2
+ script/
3
+
4
+ # Byte-compiled / optimized / DLL files
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+
9
+ # C extensions
10
+ *.so
11
+
12
+ # Distribution / packaging
13
+ .Python
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ share/python-wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+ MANIFEST
31
+
32
+ # PyInstaller
33
+ # Usually these files are written by a python script from a template
34
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+ cover/
56
+
57
+ # Translations
58
+ *.mo
59
+ *.pot
60
+
61
+ # Django stuff:
62
+ *.log
63
+ local_settings.py
64
+ db.sqlite3
65
+ db.sqlite3-journal
66
+
67
+ # Flask stuff:
68
+ instance/
69
+ .webassets-cache
70
+
71
+ # Scrapy stuff:
72
+ .scrapy
73
+
74
+ # Sphinx documentation
75
+ docs/_build/
76
+
77
+ # PyBuilder
78
+ .pybuilder/
79
+ target/
80
+
81
+ # Jupyter Notebook
82
+ .ipynb_checkpoints
83
+
84
+ # IPython
85
+ profile_default/
86
+ ipython_config.py
87
+
88
+ # pyenv
89
+ # For a library or package, you might want to ignore these files since the code is
90
+ # intended to run in multiple environments; otherwise, check them in:
91
+ # .python-version
92
+
93
+ # pipenv
94
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
96
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
97
+ # install all needed dependencies.
98
+ #Pipfile.lock
99
+
100
+ # poetry
101
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
102
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
103
+ # commonly ignored for libraries.
104
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
105
+ #poetry.lock
106
+
107
+ # pdm
108
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
109
+ #pdm.lock
110
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
111
+ # in version control.
112
+ # https://pdm.fming.dev/#use-with-ide
113
+ .pdm.toml
114
+
115
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
116
+ __pypackages__/
117
+
118
+ # Celery stuff
119
+ celerybeat-schedule
120
+ celerybeat.pid
121
+
122
+ # SageMath parsed files
123
+ *.sage.py
124
+
125
+ # Environments
126
+ .env
127
+ .venv
128
+ env/
129
+ venv/
130
+ ENV/
131
+ env.bak/
132
+ venv.bak/
133
+
134
+ # Spyder project settings
135
+ .spyderproject
136
+ .spyproject
137
+
138
+ # Rope project settings
139
+ .ropeproject
140
+
141
+ # mkdocs documentation
142
+ /site
143
+
144
+ # mypy
145
+ .mypy_cache/
146
+ .dmypy.json
147
+ dmypy.json
148
+
149
+ # Pyre type checker
150
+ .pyre/
151
+
152
+ # pytype static type analyzer
153
+ .pytype/
154
+
155
+ # Cython debug symbols
156
+ cython_debug/
157
+
158
+ # PyCharm
159
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
160
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
161
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
162
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
163
+ #.idea/
service/__init__.py CHANGED
@@ -0,0 +1 @@
 
 
1
+ from .vector_store import VectorStore
service/pinecone.py DELETED
@@ -1,23 +0,0 @@
1
- import os
2
- import pinecone
3
- from langchain.embeddings.openai import OpenAIEmbeddings
4
- from langchain.vectorstores import Pinecone
5
-
6
-
7
- class VectorStore(Pinecone):
8
-
9
- def __init__(self,index_name) -> None:
10
- pinecone.init(
11
- api_key=os.getenv("PINECONE_API_KEY"), # find at app.pinecone.io
12
- environment=os.getenv("PINECONE_ENV"), # next to api key in console
13
- )
14
- self.index_name = index_name
15
- self.embeddings = OpenAIEmbeddings()
16
- self.dims = 1536
17
- index = pinecone.Index(self.index_name)
18
- super().__init__(index, self.embeddings, "text")
19
-
20
- def add_docs(self,docs):
21
- if self.index_name not in pinecone.list_indexes():
22
- pinecone.create_index(name=self.index_name, metric="cosine", dimension=self.dims)
23
- Pinecone.from_documents(docs, self.embeddings, index_name=self.index_name)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
service/vector_store.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pinecone
3
+ from langchain.embeddings.openai import OpenAIEmbeddings
4
+ from langchain.vectorstores import Pinecone
5
+ from typing import TYPE_CHECKING, Any, Callable, Iterable, List, Optional, Tuple, Union
6
+ from langchain.docstore.document import Document
7
+ from langchain.schema.embeddings import Embeddings
8
+ from langchain.vectorstores.utils import DistanceStrategy, maximal_marginal_relevance
9
+ import numpy as np
10
+ import logging
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class VectorStore(Pinecone):
16
+
17
+ def __init__(self,index_name) -> None:
18
+ pinecone.init(
19
+ api_key=os.getenv("PINECONE_API_KEY"), # find at app.pinecone.io
20
+ environment=os.getenv("PINECONE_ENV"), # next to api key in console
21
+ )
22
+ self.index_name = index_name
23
+ self.dims = 1536
24
+ index = pinecone.Index(self.index_name)
25
+ super().__init__(index, OpenAIEmbeddings(), "text")
26
+
27
+ def add_docs(self,docs):
28
+ if self.index_name not in pinecone.list_indexes():
29
+ pinecone.create_index(name=self.index_name, metric="cosine", dimension=self.dims)
30
+ Pinecone.from_documents(docs, self.embeddings, index_name=self.index_name)
31
+
32
+ def similarity_search_by_vector_with_score(
33
+ self,
34
+ embedding: List[float],
35
+ *,
36
+ k: int = 4,
37
+ filter: Optional[dict] = None,
38
+ namespace: Optional[str] = None,
39
+ ) -> List[Tuple[Document, float]]:
40
+ """Return pinecone documents most similar to embedding, along with scores."""
41
+
42
+ if namespace is None:
43
+ namespace = self._namespace
44
+ docs = []
45
+ results = self._index.query(
46
+ [embedding],
47
+ top_k=k,
48
+ include_metadata=True,
49
+ namespace=namespace,
50
+ filter=filter,
51
+ )
52
+ for res in results["matches"]:
53
+ metadata = res["metadata"]
54
+ if self._text_key in metadata:
55
+ text = metadata.pop(self._text_key)
56
+ score = res["score"]
57
+ metadata['score'] = score
58
+ print(f"metadata {metadata}")
59
+ docs.append((Document(page_content=text, metadata=metadata), score))
60
+ else:
61
+ logger.warning(
62
+ f"Found document with no `{self._text_key}` key. Skipping."
63
+ )
64
+ return docs
65
+
66
+ def max_marginal_relevance_search_by_vector(
67
+ self,
68
+ embedding: List[float],
69
+ k: int = 4,
70
+ fetch_k: int = 20,
71
+ lambda_mult: float = 0.5,
72
+ filter: Optional[dict] = None,
73
+ namespace: Optional[str] = None,
74
+ **kwargs: Any,
75
+ ) -> List[Document]:
76
+ """Return docs selected using the maximal marginal relevance.
77
+
78
+ Maximal marginal relevance optimizes for similarity to query AND diversity
79
+ among selected documents.
80
+
81
+ Args:
82
+ embedding: Embedding to look up documents similar to.
83
+ k: Number of Documents to return. Defaults to 4.
84
+ fetch_k: Number of Documents to fetch to pass to MMR algorithm.
85
+ lambda_mult: Number between 0 and 1 that determines the degree
86
+ of diversity among the results with 0 corresponding
87
+ to maximum diversity and 1 to minimum diversity.
88
+ Defaults to 0.5.
89
+ Returns:
90
+ List of Documents selected by maximal marginal relevance.
91
+ """
92
+ if namespace is None:
93
+ namespace = self._namespace
94
+ results = self._index.query(
95
+ [embedding],
96
+ top_k=fetch_k,
97
+ include_values=True,
98
+ include_metadata=True,
99
+ namespace=namespace,
100
+ filter=filter,
101
+ )
102
+ mmr_selected = maximal_marginal_relevance(
103
+ np.array([embedding], dtype=np.float32),
104
+ [item["values"] for item in results["matches"]],
105
+ k=k,
106
+ lambda_mult=lambda_mult,
107
+ )
108
+ selected = []
109
+ for i in mmr_selected:
110
+ metadata = results["matches"][i]["metadata"]
111
+ score = results["matches"][i]["score"]
112
+ metadata['score'] = score
113
+ selected.append(metadata)
114
+ # selected = [results["matches"][i]["metadata"] for i in mmr_selected]
115
+ return [
116
+ Document(page_content=metadata.pop((self._text_key)), metadata=metadata)
117
+ for metadata in selected
118
+ ]
test/__init__.py ADDED
File without changes
test/vector_store.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from service import VectorStore
2
+
3
+ index_name = 'filecoin'
4
+ vector_store = VectorStore(index_name)
5
+ print(vector_store.similarity_search("what is filecoin"))
6
+
7
+ print(vector_store.max_marginal_relevance_search("what is filecoin"))