langroid 0.1.239__py3-none-any.whl → 0.1.241__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- langroid/language_models/openai_gpt.py +40 -34
- langroid/vector_store/qdrantdb.py +109 -18
- {langroid-0.1.239.dist-info → langroid-0.1.241.dist-info}/METADATA +4 -2
- {langroid-0.1.239.dist-info → langroid-0.1.241.dist-info}/RECORD +6 -6
- {langroid-0.1.239.dist-info → langroid-0.1.241.dist-info}/LICENSE +0 -0
- {langroid-0.1.239.dist-info → langroid-0.1.241.dist-info}/WHEEL +0 -0
@@ -670,23 +670,26 @@ class OpenAIGPT(LanguageModel):
|
|
670
670
|
sys.stdout.write(Colors().GREEN)
|
671
671
|
sys.stdout.flush()
|
672
672
|
has_function = False
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
673
|
+
try:
|
674
|
+
for event in response:
|
675
|
+
(
|
676
|
+
is_break,
|
677
|
+
has_function,
|
678
|
+
function_name,
|
679
|
+
function_args,
|
680
|
+
completion,
|
681
|
+
) = self._process_stream_event(
|
682
|
+
event,
|
683
|
+
chat=chat,
|
684
|
+
has_function=has_function,
|
685
|
+
completion=completion,
|
686
|
+
function_args=function_args,
|
687
|
+
function_name=function_name,
|
688
|
+
)
|
689
|
+
if is_break:
|
690
|
+
break
|
691
|
+
except Exception:
|
692
|
+
pass
|
690
693
|
|
691
694
|
print("")
|
692
695
|
# TODO- get usage info in stream mode (?)
|
@@ -722,23 +725,26 @@ class OpenAIGPT(LanguageModel):
|
|
722
725
|
sys.stdout.write(Colors().GREEN)
|
723
726
|
sys.stdout.flush()
|
724
727
|
has_function = False
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
728
|
+
try:
|
729
|
+
async for event in response:
|
730
|
+
(
|
731
|
+
is_break,
|
732
|
+
has_function,
|
733
|
+
function_name,
|
734
|
+
function_args,
|
735
|
+
completion,
|
736
|
+
) = self._process_stream_event(
|
737
|
+
event,
|
738
|
+
chat=chat,
|
739
|
+
has_function=has_function,
|
740
|
+
completion=completion,
|
741
|
+
function_args=function_args,
|
742
|
+
function_name=function_name,
|
743
|
+
)
|
744
|
+
if is_break:
|
745
|
+
break
|
746
|
+
except Exception:
|
747
|
+
pass
|
742
748
|
|
743
749
|
print("")
|
744
750
|
# TODO- get usage info in stream mode (?)
|
@@ -3,7 +3,7 @@ import json
|
|
3
3
|
import logging
|
4
4
|
import os
|
5
5
|
import uuid
|
6
|
-
from typing import List, Optional, Sequence, Tuple, TypeVar
|
6
|
+
from typing import Dict, List, Optional, Sequence, Tuple, TypeVar
|
7
7
|
|
8
8
|
from dotenv import load_dotenv
|
9
9
|
from qdrant_client import QdrantClient
|
@@ -13,7 +13,12 @@ from qdrant_client.http.models import (
|
|
13
13
|
CollectionStatus,
|
14
14
|
Distance,
|
15
15
|
Filter,
|
16
|
-
|
16
|
+
NamedSparseVector,
|
17
|
+
NamedVector,
|
18
|
+
SearchRequest,
|
19
|
+
SparseIndexParams,
|
20
|
+
SparseVector,
|
21
|
+
SparseVectorParams,
|
17
22
|
VectorParams,
|
18
23
|
)
|
19
24
|
|
@@ -22,7 +27,7 @@ from langroid.embedding_models.base import (
|
|
22
27
|
EmbeddingModelsConfig,
|
23
28
|
)
|
24
29
|
from langroid.embedding_models.models import OpenAIEmbeddingsConfig
|
25
|
-
from langroid.mytypes import Document, EmbeddingFunction
|
30
|
+
from langroid.mytypes import Document, EmbeddingFunction, Embeddings
|
26
31
|
from langroid.utils.configuration import settings
|
27
32
|
from langroid.vector_store.base import VectorStore, VectorStoreConfig
|
28
33
|
|
@@ -62,15 +67,36 @@ class QdrantDBConfig(VectorStoreConfig):
|
|
62
67
|
storage_path: str = ".qdrant/data"
|
63
68
|
embedding: EmbeddingModelsConfig = OpenAIEmbeddingsConfig()
|
64
69
|
distance: str = Distance.COSINE
|
70
|
+
use_sparse_embeddings: bool = False
|
71
|
+
sparse_embedding_model: str = ""
|
72
|
+
sparse_limit: int = 3
|
65
73
|
|
66
74
|
|
67
75
|
class QdrantDB(VectorStore):
|
68
76
|
def __init__(self, config: QdrantDBConfig = QdrantDBConfig()):
|
69
77
|
super().__init__(config)
|
70
|
-
self.config = config
|
78
|
+
self.config: QdrantDBConfig = config
|
71
79
|
emb_model = EmbeddingModel.create(config.embedding)
|
72
80
|
self.embedding_fn: EmbeddingFunction = emb_model.embedding_fn()
|
73
81
|
self.embedding_dim = emb_model.embedding_dims
|
82
|
+
if self.config.use_sparse_embeddings:
|
83
|
+
try:
|
84
|
+
from transformers import AutoModelForMaskedLM, AutoTokenizer
|
85
|
+
except ImportError:
|
86
|
+
raise ImportError(
|
87
|
+
"""
|
88
|
+
To use sparse embeddings,
|
89
|
+
you must install langroid with the [transformers] extra, e.g.:
|
90
|
+
pip install "langroid[transformers]"
|
91
|
+
"""
|
92
|
+
)
|
93
|
+
|
94
|
+
self.sparse_tokenizer = AutoTokenizer.from_pretrained(
|
95
|
+
self.config.sparse_embedding_model
|
96
|
+
)
|
97
|
+
self.sparse_model = AutoModelForMaskedLM.from_pretrained(
|
98
|
+
self.config.sparse_embedding_model
|
99
|
+
)
|
74
100
|
self.host = config.host
|
75
101
|
self.port = config.port
|
76
102
|
load_dotenv()
|
@@ -205,12 +231,22 @@ class QdrantDB(VectorStore):
|
|
205
231
|
else:
|
206
232
|
logger.warning("Recreating fresh collection")
|
207
233
|
self.client.delete_collection(collection_name=collection_name)
|
208
|
-
|
209
|
-
|
210
|
-
|
234
|
+
|
235
|
+
vectors_config = {
|
236
|
+
"": VectorParams(
|
211
237
|
size=self.embedding_dim,
|
212
238
|
distance=Distance.COSINE,
|
213
|
-
)
|
239
|
+
)
|
240
|
+
}
|
241
|
+
sparse_vectors_config = None
|
242
|
+
if self.config.use_sparse_embeddings:
|
243
|
+
sparse_vectors_config = {
|
244
|
+
"text-sparse": SparseVectorParams(index=SparseIndexParams())
|
245
|
+
}
|
246
|
+
self.client.create_collection(
|
247
|
+
collection_name=collection_name,
|
248
|
+
vectors_config=vectors_config,
|
249
|
+
sparse_vectors_config=sparse_vectors_config,
|
214
250
|
)
|
215
251
|
collection_info = self.client.get_collection(collection_name=collection_name)
|
216
252
|
assert collection_info.status == CollectionStatus.GREEN
|
@@ -221,6 +257,32 @@ class QdrantDB(VectorStore):
|
|
221
257
|
logger.info(collection_info)
|
222
258
|
logger.setLevel(level)
|
223
259
|
|
260
|
+
def get_sparse_embeddings(self, inputs: List[str]) -> List[SparseVector]:
|
261
|
+
if not self.config.use_sparse_embeddings:
|
262
|
+
return []
|
263
|
+
import torch
|
264
|
+
|
265
|
+
tokens = self.sparse_tokenizer(
|
266
|
+
inputs, return_tensors="pt", truncation=True, padding=True
|
267
|
+
)
|
268
|
+
output = self.sparse_model(**tokens)
|
269
|
+
vectors = torch.max(
|
270
|
+
torch.log(torch.relu(output.logits) + torch.tensor(1.0))
|
271
|
+
* tokens.attention_mask.unsqueeze(-1),
|
272
|
+
dim=1,
|
273
|
+
)[0].squeeze(dim=1)
|
274
|
+
sparse_embeddings = []
|
275
|
+
for vec in vectors:
|
276
|
+
cols = vec.nonzero().squeeze().cpu().tolist()
|
277
|
+
weights = vec[cols].cpu().tolist()
|
278
|
+
sparse_embeddings.append(
|
279
|
+
SparseVector(
|
280
|
+
indices=cols,
|
281
|
+
values=weights,
|
282
|
+
)
|
283
|
+
)
|
284
|
+
return sparse_embeddings
|
285
|
+
|
224
286
|
def add_documents(self, documents: Sequence[Document]) -> None:
|
225
287
|
# Add id to metadata if not already present
|
226
288
|
super().maybe_add_ids(documents)
|
@@ -232,6 +294,9 @@ class QdrantDB(VectorStore):
|
|
232
294
|
return
|
233
295
|
document_dicts = [doc.dict() for doc in documents]
|
234
296
|
embedding_vecs = self.embedding_fn([doc.content for doc in documents])
|
297
|
+
sparse_embedding_vecs = self.get_sparse_embeddings(
|
298
|
+
[doc.content for doc in documents]
|
299
|
+
)
|
235
300
|
if self.config.collection_name is None:
|
236
301
|
raise ValueError("No collection name set, cannot ingest docs")
|
237
302
|
if self.config.collection_name not in colls:
|
@@ -241,11 +306,16 @@ class QdrantDB(VectorStore):
|
|
241
306
|
# else we get an API error
|
242
307
|
b = self.config.batch_size
|
243
308
|
for i in range(0, len(ids), b):
|
309
|
+
vectors: Dict[str, Embeddings | List[SparseVector]] = {
|
310
|
+
"": embedding_vecs[i : i + b]
|
311
|
+
}
|
312
|
+
if self.config.use_sparse_embeddings:
|
313
|
+
vectors["text-sparse"] = sparse_embedding_vecs[i : i + b]
|
244
314
|
self.client.upsert(
|
245
315
|
collection_name=self.config.collection_name,
|
246
316
|
points=Batch(
|
247
317
|
ids=ids[i : i + b],
|
248
|
-
vectors=
|
318
|
+
vectors=vectors,
|
249
319
|
payloads=document_dicts[i : i + b],
|
250
320
|
),
|
251
321
|
)
|
@@ -332,18 +402,39 @@ class QdrantDB(VectorStore):
|
|
332
402
|
filter = Filter()
|
333
403
|
else:
|
334
404
|
filter = Filter.parse_obj(json.loads(where))
|
405
|
+
requests = [
|
406
|
+
SearchRequest(
|
407
|
+
vector=NamedVector(
|
408
|
+
name="",
|
409
|
+
vector=embedding,
|
410
|
+
),
|
411
|
+
limit=k,
|
412
|
+
with_payload=True,
|
413
|
+
filter=filter,
|
414
|
+
)
|
415
|
+
]
|
416
|
+
if self.config.use_sparse_embeddings:
|
417
|
+
sparse_embedding = self.get_sparse_embeddings([text])[0]
|
418
|
+
requests.append(
|
419
|
+
SearchRequest(
|
420
|
+
vector=NamedSparseVector(
|
421
|
+
name="text-sparse",
|
422
|
+
vector=sparse_embedding,
|
423
|
+
),
|
424
|
+
limit=self.config.sparse_limit,
|
425
|
+
with_payload=True,
|
426
|
+
filter=filter,
|
427
|
+
)
|
428
|
+
)
|
335
429
|
if self.config.collection_name is None:
|
336
430
|
raise ValueError("No collection name set, cannot search")
|
337
|
-
|
338
|
-
collection_name=self.config.collection_name,
|
339
|
-
query_vector=embedding,
|
340
|
-
query_filter=filter,
|
341
|
-
limit=k,
|
342
|
-
search_params=SearchParams(
|
343
|
-
hnsw_ef=128,
|
344
|
-
exact=False, # use Apx NN, not exact NN
|
345
|
-
),
|
431
|
+
search_result_lists: List[List[ScoredPoint]] = self.client.search_batch(
|
432
|
+
collection_name=self.config.collection_name, requests=requests
|
346
433
|
)
|
434
|
+
|
435
|
+
search_result = [
|
436
|
+
match for result in search_result_lists for match in result
|
437
|
+
] # 2D list -> 1D list
|
347
438
|
scores = [match.score for match in search_result if match is not None]
|
348
439
|
docs = [
|
349
440
|
Document(**(match.payload)) # type: ignore
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: langroid
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.241
|
4
4
|
Summary: Harness LLMs with Multi-Agent Programming
|
5
5
|
License: MIT
|
6
6
|
Author: Prasad Chalasani
|
@@ -36,6 +36,7 @@ Requires-Dist: fakeredis (>=2.12.1,<3.0.0)
|
|
36
36
|
Requires-Dist: fire (>=0.5.0,<0.6.0)
|
37
37
|
Requires-Dist: flake8 (>=6.0.0,<7.0.0)
|
38
38
|
Requires-Dist: google-api-python-client (>=2.95.0,<3.0.0)
|
39
|
+
Requires-Dist: google-generativeai (>=0.5.2,<0.6.0)
|
39
40
|
Requires-Dist: groq (>=0.5.0,<0.6.0)
|
40
41
|
Requires-Dist: grpcio (>=1.62.1,<2.0.0)
|
41
42
|
Requires-Dist: halo (>=0.0.31,<0.0.32)
|
@@ -99,8 +100,9 @@ Requires-Dist: sqlalchemy (>=2.0.19,<3.0.0)
|
|
99
100
|
Requires-Dist: tantivy (>=0.21.0,<0.22.0)
|
100
101
|
Requires-Dist: thefuzz (>=0.20.0,<0.21.0)
|
101
102
|
Requires-Dist: tiktoken (>=0.5.1,<0.6.0)
|
102
|
-
Requires-Dist: torch (==2.0.0) ; extra == "hf-embeddings"
|
103
|
+
Requires-Dist: torch (==2.0.0) ; extra == "hf-embeddings" or extra == "transformers"
|
103
104
|
Requires-Dist: trafilatura (>=1.5.0,<2.0.0)
|
105
|
+
Requires-Dist: transformers (>=4.40.1,<5.0.0) ; extra == "transformers"
|
104
106
|
Requires-Dist: typer (>=0.9.0,<0.10.0)
|
105
107
|
Requires-Dist: types-pillow (>=10.2.0.20240406,<11.0.0.0)
|
106
108
|
Requires-Dist: types-pyyaml (>=6.0.12.20240311,<7.0.0.0)
|
@@ -63,7 +63,7 @@ langroid/language_models/azure_openai.py,sha256=ncRCbKooqLVOY-PWQUIo9C3yTuKEFbAw
|
|
63
63
|
langroid/language_models/base.py,sha256=B6dX43ZR65mIvjD95W4RcfpT-WpmiuEcstR3eMrr56Y,21029
|
64
64
|
langroid/language_models/config.py,sha256=5UF3DzO1a-Dfsc3vghE0XGq7g9t_xDsRCsuRiU4dgBg,366
|
65
65
|
langroid/language_models/openai_assistants.py,sha256=9K-DEAL2aSWHeXj2hwCo2RAlK9_1oCPtqX2u1wISCj8,36
|
66
|
-
langroid/language_models/openai_gpt.py,sha256=
|
66
|
+
langroid/language_models/openai_gpt.py,sha256=ueB9MJzxGBIjN_i22v2ZqoWo_twnQan_s4p0dzf4zzI,50505
|
67
67
|
langroid/language_models/prompt_formatter/__init__.py,sha256=9JXFF22QNMmbQV1q4nrIeQVTtA3Tx8tEZABLtLBdFyc,352
|
68
68
|
langroid/language_models/prompt_formatter/base.py,sha256=eDS1sgRNZVnoajwV_ZIha6cba5Dt8xjgzdRbPITwx3Q,1221
|
69
69
|
langroid/language_models/prompt_formatter/hf_formatter.py,sha256=TFL6ppmeQWnzr6CKQzRZFYY810zE1mr8DZnhw6i85ok,5217
|
@@ -120,8 +120,8 @@ langroid/vector_store/lancedb.py,sha256=lbl8wZuV6GNw0LnIwOSriSNwoMEba90umQTcQHtM
|
|
120
120
|
langroid/vector_store/meilisearch.py,sha256=d2huA9P-NoYRuAQ9ZeXJmMKr7ry8u90RUSR28k2ecQg,11340
|
121
121
|
langroid/vector_store/momento.py,sha256=9cui31TTrILid2KIzUpBkN2Ey3g_CZWOQVdaFsA4Ors,10045
|
122
122
|
langroid/vector_store/qdrant_cloud.py,sha256=3im4Mip0QXLkR6wiqVsjV1QvhSElfxdFSuDKddBDQ-4,188
|
123
|
-
langroid/vector_store/qdrantdb.py,sha256=
|
124
|
-
langroid-0.1.
|
125
|
-
langroid-0.1.
|
126
|
-
langroid-0.1.
|
127
|
-
langroid-0.1.
|
123
|
+
langroid/vector_store/qdrantdb.py,sha256=sk5Qb2ZNbooi0rorsMuqIMokF7WADw6PJ0D6goM2XBw,16802
|
124
|
+
langroid-0.1.241.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
|
125
|
+
langroid-0.1.241.dist-info/METADATA,sha256=3-gQbFV94rqEec_esydP028p-Ol3w2J9mbrcupeq0Xg,49163
|
126
|
+
langroid-0.1.241.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
127
|
+
langroid-0.1.241.dist-info/RECORD,,
|
File without changes
|
File without changes
|