langroid 0.56.4__py3-none-any.whl → 0.56.6__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/agent/base.py +0 -4
- langroid/agent/special/doc_chat_agent.py +87 -21
- langroid/agent/special/lance_doc_chat_agent.py +1 -1
- langroid/parsing/parser.py +1 -1
- {langroid-0.56.4.dist-info → langroid-0.56.6.dist-info}/METADATA +1 -1
- {langroid-0.56.4.dist-info → langroid-0.56.6.dist-info}/RECORD +8 -8
- {langroid-0.56.4.dist-info → langroid-0.56.6.dist-info}/WHEEL +0 -0
- {langroid-0.56.4.dist-info → langroid-0.56.6.dist-info}/licenses/LICENSE +0 -0
langroid/agent/base.py
CHANGED
@@ -279,9 +279,6 @@ class Agent(ABC):
|
|
279
279
|
if param.annotation != inspect.Parameter.empty:
|
280
280
|
ann_str = str(param.annotation)
|
281
281
|
# Check for Agent-like types
|
282
|
-
print(param, inspect.isclass(param.annotation))
|
283
|
-
print(param, issubclass(param.annotation, Agent))
|
284
|
-
print(param, param.annotation is ChatDocument)
|
285
282
|
if (
|
286
283
|
inspect.isclass(param.annotation)
|
287
284
|
and issubclass(param.annotation, Agent)
|
@@ -312,7 +309,6 @@ class Agent(ABC):
|
|
312
309
|
elif param.name == "chat_doc":
|
313
310
|
chat_doc_param = param.name
|
314
311
|
|
315
|
-
print(has_annotations, agent_param, chat_doc_param)
|
316
312
|
return has_annotations, agent_param, chat_doc_param
|
317
313
|
|
318
314
|
@no_type_check
|
@@ -142,6 +142,8 @@ class DocChatAgentConfig(ChatAgentConfig):
|
|
142
142
|
# improve retrieval.
|
143
143
|
chunk_enrichment_config: Optional[ChunkEnrichmentAgentConfig] = None
|
144
144
|
|
145
|
+
n_relevant_chunks: int = 3 # how many relevant chunks to retrieve finally
|
146
|
+
n_similar_chunks: int = 3 # how many similar chunks to retrieve, by each method
|
145
147
|
n_query_rephrases: int = 0
|
146
148
|
n_neighbor_chunks: int = 0 # how many neighbors on either side of match to retrieve
|
147
149
|
n_fuzzy_neighbor_words: int = 100 # num neighbor words to retrieve for fuzzy match
|
@@ -185,7 +187,8 @@ class DocChatAgentConfig(ChatAgentConfig):
|
|
185
187
|
# truncating due to punctuation
|
186
188
|
min_chunk_chars=200,
|
187
189
|
discard_chunk_chars=5, # discard chunks with fewer than this many chars
|
188
|
-
n_similar_docs
|
190
|
+
# set deprecated n_similar_docs to None; use n_similar_chunks above instead
|
191
|
+
n_similar_docs=None,
|
189
192
|
n_neighbor_ids=0, # num chunk IDs to store on either side of each chunk
|
190
193
|
pdf=PdfParsingConfig(
|
191
194
|
# NOTE: PDF parsing is extremely challenging, and each library
|
@@ -240,6 +243,60 @@ class DocChatAgent(ChatAgent):
|
|
240
243
|
self.chunked_docs: List[Document] = []
|
241
244
|
self.chunked_docs_clean: List[Document] = []
|
242
245
|
self.response: None | Document = None
|
246
|
+
if (
|
247
|
+
self.config.cross_encoder_reranking_model != ""
|
248
|
+
and self.config.use_reciprocal_rank_fusion
|
249
|
+
):
|
250
|
+
logger.warning(
|
251
|
+
"""
|
252
|
+
You have set `use_reciprocal_rank_fusion` to True,
|
253
|
+
but it will be ignored since you have also set
|
254
|
+
`cross_encoder_reranking_model` to a non-empty value.
|
255
|
+
To use RRF (Reciprocal Rank Fusion), set
|
256
|
+
`cross_encoder_reranking_model` to an empty string.
|
257
|
+
"""
|
258
|
+
)
|
259
|
+
|
260
|
+
if (
|
261
|
+
self.config.cross_encoder_reranking_model == ""
|
262
|
+
and not self.config.use_reciprocal_rank_fusion
|
263
|
+
and (self.config.use_fuzzy_match or self.config.use_bm25_search)
|
264
|
+
and (
|
265
|
+
self.config.n_relevant_chunks
|
266
|
+
< self.config.n_similar_chunks
|
267
|
+
* (self.config.use_bm25_search + self.config.use_fuzzy_match)
|
268
|
+
)
|
269
|
+
):
|
270
|
+
logger.warning(
|
271
|
+
"""
|
272
|
+
DocChatAgent has been configured to have no cross encoder reranking,
|
273
|
+
AND `use_reciprocal_rank_fusion` is set to False,
|
274
|
+
AND `use_fuzzy_match` or `use_bm25_search` is True,
|
275
|
+
AND `n_relevant_chunks` is less than `n_similar_chunks` * (
|
276
|
+
`use_bm25_search` + `use_fuzzy_match`
|
277
|
+
),
|
278
|
+
BUT there is no way to rerank the chunks retrieved by multiple methods,
|
279
|
+
so we will set `use_reciprocal_rank_fusion` to True.
|
280
|
+
"""
|
281
|
+
)
|
282
|
+
self.config.use_reciprocal_rank_fusion = True
|
283
|
+
|
284
|
+
# Handle backward compatibility for deprecated n_similar_docs
|
285
|
+
if self.config.parsing.n_similar_docs is not None:
|
286
|
+
logger.warning(
|
287
|
+
"""
|
288
|
+
The parameter `parsing.n_similar_docs` is deprecated and will be
|
289
|
+
removed in a future version. Please use `n_similar_chunks` and
|
290
|
+
`n_relevant_chunks` instead, which provide more fine-grained
|
291
|
+
control over retrieval.
|
292
|
+
- n_similar_chunks: number of chunks to retrieve by each method
|
293
|
+
- n_relevant_chunks: final number of chunks to return after reranking
|
294
|
+
"""
|
295
|
+
)
|
296
|
+
# Use the deprecated value for both parameters
|
297
|
+
self.config.n_similar_chunks = self.config.parsing.n_similar_docs
|
298
|
+
self.config.n_relevant_chunks = self.config.parsing.n_similar_docs
|
299
|
+
|
243
300
|
self.ingest()
|
244
301
|
|
245
302
|
def clear(self) -> None:
|
@@ -486,7 +543,7 @@ class DocChatAgent(ChatAgent):
|
|
486
543
|
def retrieval_tool(self, msg: RetrievalTool) -> str:
|
487
544
|
"""Handle the RetrievalTool message"""
|
488
545
|
self.config.retrieve_only = True
|
489
|
-
self.config.
|
546
|
+
self.config.n_relevant_chunks = msg.num_results
|
490
547
|
content_doc = self.answer_from_docs(msg.query)
|
491
548
|
return content_doc.content
|
492
549
|
|
@@ -1005,7 +1062,7 @@ class DocChatAgent(ChatAgent):
|
|
1005
1062
|
self.chunked_docs,
|
1006
1063
|
self.chunked_docs_clean, # already pre-processed!
|
1007
1064
|
query,
|
1008
|
-
k=self.config.
|
1065
|
+
k=self.config.n_similar_chunks * multiple,
|
1009
1066
|
)
|
1010
1067
|
return docs_scores
|
1011
1068
|
|
@@ -1025,7 +1082,7 @@ class DocChatAgent(ChatAgent):
|
|
1025
1082
|
query,
|
1026
1083
|
self.chunked_docs,
|
1027
1084
|
self.chunked_docs_clean,
|
1028
|
-
k=self.config.
|
1085
|
+
k=self.config.n_similar_chunks * multiple,
|
1029
1086
|
words_before=self.config.n_fuzzy_neighbor_words or None,
|
1030
1087
|
words_after=self.config.n_fuzzy_neighbor_words or None,
|
1031
1088
|
)
|
@@ -1056,9 +1113,7 @@ class DocChatAgent(ChatAgent):
|
|
1056
1113
|
key=lambda x: x[0],
|
1057
1114
|
reverse=True,
|
1058
1115
|
)
|
1059
|
-
passages = [
|
1060
|
-
d for _, d in sorted_pairs[: self.config.parsing.n_similar_docs]
|
1061
|
-
]
|
1116
|
+
passages = [d for _, d in sorted_pairs[: self.config.n_similar_chunks]]
|
1062
1117
|
return passages
|
1063
1118
|
|
1064
1119
|
def rerank_with_diversity(self, passages: List[Document]) -> List[Document]:
|
@@ -1229,7 +1284,7 @@ class DocChatAgent(ChatAgent):
|
|
1229
1284
|
|
1230
1285
|
# if we are using cross-encoder reranking or reciprocal rank fusion (RRF),
|
1231
1286
|
# we can retrieve more docs during retrieval, and leave it to the cross-encoder
|
1232
|
-
# or RRF reranking to whittle down to self.config.
|
1287
|
+
# or RRF reranking to whittle down to self.config.n_similar_chunks
|
1233
1288
|
retrieval_multiple = (
|
1234
1289
|
1
|
1235
1290
|
if (
|
@@ -1247,7 +1302,7 @@ class DocChatAgent(ChatAgent):
|
|
1247
1302
|
for q in [query] + query_proxies:
|
1248
1303
|
docs_and_scores += self.get_semantic_search_results(
|
1249
1304
|
q,
|
1250
|
-
k=self.config.
|
1305
|
+
k=self.config.n_similar_chunks * retrieval_multiple,
|
1251
1306
|
)
|
1252
1307
|
# sort by score descending
|
1253
1308
|
docs_and_scores = sorted(
|
@@ -1265,8 +1320,12 @@ class DocChatAgent(ChatAgent):
|
|
1265
1320
|
# TODO: Add score threshold in config
|
1266
1321
|
docs_scores = self.get_similar_chunks_bm25(query, retrieval_multiple)
|
1267
1322
|
id2doc.update({d.id(): d for d, _ in docs_scores})
|
1268
|
-
if
|
1269
|
-
|
1323
|
+
if (
|
1324
|
+
self.config.cross_encoder_reranking_model == ""
|
1325
|
+
and self.config.use_reciprocal_rank_fusion
|
1326
|
+
):
|
1327
|
+
# if we're not re-ranking with a cross-encoder, and have RRF enabled,
|
1328
|
+
# instead of accumulating the bm25 results into passages,
|
1270
1329
|
# we collect these ranks for Reciprocal Rank Fusion down below.
|
1271
1330
|
docs_scores = sorted(docs_scores, key=lambda x: x[1], reverse=True)
|
1272
1331
|
id2_rank_bm25 = {d.id(): i for i, (d, _) in enumerate(docs_scores)}
|
@@ -1279,8 +1338,12 @@ class DocChatAgent(ChatAgent):
|
|
1279
1338
|
if self.config.use_fuzzy_match:
|
1280
1339
|
# TODO: Add score threshold in config
|
1281
1340
|
fuzzy_match_doc_scores = self.get_fuzzy_matches(query, retrieval_multiple)
|
1282
|
-
if
|
1283
|
-
|
1341
|
+
if (
|
1342
|
+
self.config.cross_encoder_reranking_model == ""
|
1343
|
+
and self.config.use_reciprocal_rank_fusion
|
1344
|
+
):
|
1345
|
+
# if we're not re-ranking with a cross-encoder,
|
1346
|
+
# instead of accumulating the fuzzy match results into passages,
|
1284
1347
|
# we collect these ranks for Reciprocal Rank Fusion down below.
|
1285
1348
|
fuzzy_match_doc_scores = sorted(
|
1286
1349
|
fuzzy_match_doc_scores, key=lambda x: x[1], reverse=True
|
@@ -1316,9 +1379,12 @@ class DocChatAgent(ChatAgent):
|
|
1316
1379
|
| set(id2_rank_bm25.keys())
|
1317
1380
|
| set(id2_rank_fuzzy.keys())
|
1318
1381
|
):
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1382
|
+
# Use max_rank instead of infinity to avoid bias against
|
1383
|
+
# single-method docs
|
1384
|
+
max_rank = self.config.n_similar_chunks * retrieval_multiple
|
1385
|
+
rank_semantic = id2_rank_semantic.get(id_, max_rank)
|
1386
|
+
rank_bm25 = id2_rank_bm25.get(id_, max_rank)
|
1387
|
+
rank_fuzzy = id2_rank_fuzzy.get(id_, max_rank)
|
1322
1388
|
c = self.config.reciprocal_rank_fusion_constant
|
1323
1389
|
reciprocal_fusion_score = (
|
1324
1390
|
1 / (rank_semantic + c) + 1 / (rank_bm25 + c) + 1 / (rank_fuzzy + c)
|
@@ -1333,12 +1399,12 @@ class DocChatAgent(ChatAgent):
|
|
1333
1399
|
reverse=True,
|
1334
1400
|
)
|
1335
1401
|
)
|
1336
|
-
# each method retrieved up to retrieval_multiple *
|
1337
|
-
# so we need to take the top
|
1402
|
+
# each method retrieved up to retrieval_multiple * n_similar_chunks,
|
1403
|
+
# so we need to take the top n_similar_chunks from the combined list
|
1338
1404
|
passages = [
|
1339
1405
|
id2doc[id]
|
1340
1406
|
for i, (id, _) in enumerate(id2_reciprocal_score.items())
|
1341
|
-
if i < self.config.
|
1407
|
+
if i < self.config.n_similar_chunks
|
1342
1408
|
]
|
1343
1409
|
# passages must have distinct ids
|
1344
1410
|
assert len(passages) == len(set([d.id() for d in passages])), (
|
@@ -1355,7 +1421,7 @@ class DocChatAgent(ChatAgent):
|
|
1355
1421
|
passages = [p for p, _ in passages_scores]
|
1356
1422
|
# now passages can potentially have a lot of doc chunks,
|
1357
1423
|
# so we re-rank them using a cross-encoder scoring model,
|
1358
|
-
# and pick top k where k = config
|
1424
|
+
# and pick top k where k = config..n_similar_chunks
|
1359
1425
|
# https://www.sbert.net/examples/applications/retrieve_rerank
|
1360
1426
|
if self.config.cross_encoder_reranking_model != "":
|
1361
1427
|
passages = self.rerank_with_cross_encoder(query, passages)
|
@@ -1374,7 +1440,7 @@ class DocChatAgent(ChatAgent):
|
|
1374
1440
|
passages_scores = self.add_context_window(passages_scores)
|
1375
1441
|
passages = [p for p, _ in passages_scores]
|
1376
1442
|
|
1377
|
-
return passages[: self.config.
|
1443
|
+
return passages[: self.config.n_relevant_chunks]
|
1378
1444
|
|
1379
1445
|
@no_type_check
|
1380
1446
|
def get_relevant_extracts(self, query: str) -> Tuple[str, List[Document]]:
|
@@ -255,7 +255,7 @@ class LanceDocChatAgent(DocChatAgent):
|
|
255
255
|
result = (
|
256
256
|
tbl.search(query_clean)
|
257
257
|
.where(self.config.filter or None)
|
258
|
-
.limit(self.config.
|
258
|
+
.limit(self.config.n_similar_chunks * multiple)
|
259
259
|
)
|
260
260
|
docs = self.vecdb._lance_result_to_docs(result)
|
261
261
|
scores = [r["score"] for r in result.to_list()]
|
langroid/parsing/parser.py
CHANGED
@@ -120,7 +120,7 @@ class ParsingConfig(BaseSettings):
|
|
120
120
|
# aim to have at least this many chars per chunk when truncating due to punctuation
|
121
121
|
min_chunk_chars: int = 350
|
122
122
|
discard_chunk_chars: int = 5 # discard chunks with fewer than this many chars
|
123
|
-
n_similar_docs: int = 4
|
123
|
+
n_similar_docs: Optional[int] = 4 # deprecated
|
124
124
|
n_neighbor_ids: int = 5 # window size to store around each chunk
|
125
125
|
separators: List[str] = ["\n\n", "\n", " ", ""]
|
126
126
|
token_encoding_model: str = "text-embedding-3-small"
|
@@ -3,7 +3,7 @@ langroid/exceptions.py,sha256=OPjece_8cwg94DLPcOGA1ddzy5bGh65pxzcHMnssTz8,2995
|
|
3
3
|
langroid/mytypes.py,sha256=HIcYAqGeA9OK0Hlscym2FI5Oax9QFljDZoVgRlomhRk,4014
|
4
4
|
langroid/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
langroid/agent/__init__.py,sha256=ll0Cubd2DZ-fsCMl7e10hf9ZjFGKzphfBco396IKITY,786
|
6
|
-
langroid/agent/base.py,sha256=
|
6
|
+
langroid/agent/base.py,sha256=GVE_vdtDUJpldACH4LQwjqbQ11UDn9thr2-uBXk0RjU,86009
|
7
7
|
langroid/agent/batch.py,sha256=wpE9RqCNDVDhAXkCB7wEqfCIEAi6qKcrhaZ-Zr9T4C0,21375
|
8
8
|
langroid/agent/chat_agent.py,sha256=2HIYzYxkrGkRIS97ioKfIqjaW3RbX89M39LjzBobBEY,88381
|
9
9
|
langroid/agent/chat_document.py,sha256=0e6zYkqIorMIVbCsxOul9ziwAPPOWDsBsRV9E8ux-WI,18055
|
@@ -15,9 +15,9 @@ langroid/agent/xml_tool_message.py,sha256=oeBKnJNoGaKdtz39XoWGMTNlVyXew2MWH5lgtY
|
|
15
15
|
langroid/agent/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
16
|
langroid/agent/callbacks/chainlit.py,sha256=4rJw07NIIVTIVvksVY08h5PdLE_kRoJItjbQM0UjRn0,20962
|
17
17
|
langroid/agent/special/__init__.py,sha256=gik_Xtm_zV7U9s30Mn8UX3Gyuy4jTjQe9zjiE3HWmEo,1273
|
18
|
-
langroid/agent/special/doc_chat_agent.py,sha256=
|
18
|
+
langroid/agent/special/doc_chat_agent.py,sha256=q-W4fDM-kdv_keBQjIsSZEUcmUvDAK1Cb2GcfJ9KhmY,68852
|
19
19
|
langroid/agent/special/doc_chat_task.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
-
langroid/agent/special/lance_doc_chat_agent.py,sha256=
|
20
|
+
langroid/agent/special/lance_doc_chat_agent.py,sha256=6pIqi2DF-MvYYN3-blsdUgulYnOBTl7I21T7wPAt1zM,10413
|
21
21
|
langroid/agent/special/lance_tools.py,sha256=qS8x4wi8mrqfbYV2ztFzrcxyhHQ0ZWOc-zkYiH7awj0,2105
|
22
22
|
langroid/agent/special/relevance_extractor_agent.py,sha256=zIx8GUdVo1aGW6ASla0NPQjYYIpmriK_TYMijqAx3F8,4796
|
23
23
|
langroid/agent/special/retriever_agent.py,sha256=o2UfqiCGME0t85SZ6qjK041_WZYqXSuV1SeH_3KtVuc,1931
|
@@ -94,7 +94,7 @@ langroid/parsing/file_attachment.py,sha256=ryJVhVFOhINrfkf9Z0vWTTwCnm80z2qzXgp20
|
|
94
94
|
langroid/parsing/md_parser.py,sha256=JUgsUpCaeAuBndmtDaJR9HMZaje1gmtXtaLXJHst3i8,21340
|
95
95
|
langroid/parsing/para_sentence_split.py,sha256=AJBzZojP3zpB-_IMiiHismhqcvkrVBQ3ZINoQyx_bE4,2000
|
96
96
|
langroid/parsing/parse_json.py,sha256=aADo38bAHQhC8on4aWZZzVzSDy-dK35vRLZsFI2ewh8,4756
|
97
|
-
langroid/parsing/parser.py,sha256=
|
97
|
+
langroid/parsing/parser.py,sha256=pFolKsWxr2uQ5zoAqby9eunZ0baBlzCs9LfJ6NPV_8I,15623
|
98
98
|
langroid/parsing/pdf_utils.py,sha256=QogxU_B1N3WSLyZ9PEcJDaJoZShKs7CPQRVyF1V2DiE,3143
|
99
99
|
langroid/parsing/repo_loader.py,sha256=NpysuyzRHvgL3F4BB_wGo5sCUnZ3FOlVCJmZ7CaUdbs,30202
|
100
100
|
langroid/parsing/routing.py,sha256=-FcnlqldzL4ZoxuDwXjQPNHgBe9F9-F4R6q7b_z9CvI,1232
|
@@ -137,7 +137,7 @@ langroid/vector_store/pineconedb.py,sha256=otxXZNaBKb9f_H75HTaU3lMHiaR2NUp5MqwLZ
|
|
137
137
|
langroid/vector_store/postgres.py,sha256=wHPtIi2qM4fhO4pMQr95pz1ZCe7dTb2hxl4VYspGZoA,16104
|
138
138
|
langroid/vector_store/qdrantdb.py,sha256=O6dSBoDZ0jzfeVBd7LLvsXu083xs2fxXtPa9gGX3JX4,18443
|
139
139
|
langroid/vector_store/weaviatedb.py,sha256=Yn8pg139gOy3zkaPfoTbMXEEBCiLiYa1MU5d_3UA1K4,11847
|
140
|
-
langroid-0.56.
|
141
|
-
langroid-0.56.
|
142
|
-
langroid-0.56.
|
143
|
-
langroid-0.56.
|
140
|
+
langroid-0.56.6.dist-info/METADATA,sha256=Obrt0l7fxia2D7Fd9M9SQFCulOxfAJwqo9DxorPzgfA,65744
|
141
|
+
langroid-0.56.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
142
|
+
langroid-0.56.6.dist-info/licenses/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
|
143
|
+
langroid-0.56.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|