langroid 0.13.0__tar.gz → 0.15.0__tar.gz

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.
Files changed (143) hide show
  1. {langroid-0.13.0 → langroid-0.15.0}/PKG-INFO +4 -1
  2. {langroid-0.13.0 → langroid-0.15.0}/README.md +2 -0
  3. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/doc_chat_agent.py +99 -17
  4. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/openai_gpt.py +18 -6
  5. {langroid-0.13.0 → langroid-0.15.0}/pyproject.toml +2 -1
  6. {langroid-0.13.0 → langroid-0.15.0}/LICENSE +0 -0
  7. {langroid-0.13.0 → langroid-0.15.0}/langroid/__init__.py +0 -0
  8. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/__init__.py +0 -0
  9. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/base.py +0 -0
  10. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/batch.py +0 -0
  11. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/callbacks/__init__.py +0 -0
  12. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/callbacks/chainlit.py +0 -0
  13. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/chat_agent.py +0 -0
  14. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/chat_document.py +0 -0
  15. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/helpers.py +0 -0
  16. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/junk +0 -0
  17. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/openai_assistant.py +0 -0
  18. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/__init__.py +0 -0
  19. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/lance_doc_chat_agent.py +0 -0
  20. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/lance_rag/__init__.py +0 -0
  21. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/lance_rag/critic_agent.py +0 -0
  22. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/lance_rag/lance_rag_task.py +0 -0
  23. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/lance_rag/query_planner_agent.py +0 -0
  24. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/lance_tools.py +0 -0
  25. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/neo4j/__init__.py +0 -0
  26. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/neo4j/csv_kg_chat.py +0 -0
  27. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/neo4j/neo4j_chat_agent.py +0 -0
  28. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/neo4j/utils/__init__.py +0 -0
  29. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/neo4j/utils/system_message.py +0 -0
  30. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/relevance_extractor_agent.py +0 -0
  31. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/retriever_agent.py +0 -0
  32. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/sql/__init__.py +0 -0
  33. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/sql/sql_chat_agent.py +0 -0
  34. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/sql/utils/__init__.py +0 -0
  35. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/sql/utils/description_extractors.py +0 -0
  36. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/sql/utils/populate_metadata.py +0 -0
  37. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/sql/utils/system_message.py +0 -0
  38. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/sql/utils/tools.py +0 -0
  39. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/special/table_chat_agent.py +0 -0
  40. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/structured_message.py +0 -0
  41. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/task.py +0 -0
  42. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tool_message.py +0 -0
  43. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/__init__.py +0 -0
  44. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/duckduckgo_search_tool.py +0 -0
  45. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/extract_tool.py +0 -0
  46. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/generator_tool.py +0 -0
  47. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/google_search_tool.py +0 -0
  48. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/metaphor_search_tool.py +0 -0
  49. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/note_tool.py +0 -0
  50. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/orchestration.py +0 -0
  51. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/recipient_tool.py +0 -0
  52. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/retrieval_tool.py +0 -0
  53. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/rewind_tool.py +0 -0
  54. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/run_python_code.py +0 -0
  55. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/tools/segment_extract_tool.py +0 -0
  56. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent/typed_task.py +0 -0
  57. {langroid-0.13.0 → langroid-0.15.0}/langroid/agent_config.py +0 -0
  58. {langroid-0.13.0 → langroid-0.15.0}/langroid/cachedb/__init__.py +0 -0
  59. {langroid-0.13.0 → langroid-0.15.0}/langroid/cachedb/base.py +0 -0
  60. {langroid-0.13.0 → langroid-0.15.0}/langroid/cachedb/momento_cachedb.py +0 -0
  61. {langroid-0.13.0 → langroid-0.15.0}/langroid/cachedb/redis_cachedb.py +0 -0
  62. {langroid-0.13.0 → langroid-0.15.0}/langroid/embedding_models/__init__.py +0 -0
  63. {langroid-0.13.0 → langroid-0.15.0}/langroid/embedding_models/base.py +0 -0
  64. {langroid-0.13.0 → langroid-0.15.0}/langroid/embedding_models/clustering.py +0 -0
  65. {langroid-0.13.0 → langroid-0.15.0}/langroid/embedding_models/models.py +0 -0
  66. {langroid-0.13.0 → langroid-0.15.0}/langroid/embedding_models/protoc/__init__.py +0 -0
  67. {langroid-0.13.0 → langroid-0.15.0}/langroid/embedding_models/protoc/embeddings.proto +0 -0
  68. {langroid-0.13.0 → langroid-0.15.0}/langroid/embedding_models/protoc/embeddings_pb2.py +0 -0
  69. {langroid-0.13.0 → langroid-0.15.0}/langroid/embedding_models/protoc/embeddings_pb2.pyi +0 -0
  70. {langroid-0.13.0 → langroid-0.15.0}/langroid/embedding_models/protoc/embeddings_pb2_grpc.py +0 -0
  71. {langroid-0.13.0 → langroid-0.15.0}/langroid/embedding_models/remote_embeds.py +0 -0
  72. {langroid-0.13.0 → langroid-0.15.0}/langroid/exceptions.py +0 -0
  73. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/.chainlit/config.toml +0 -0
  74. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/.chainlit/translations/en-US.json +0 -0
  75. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/__init__.py +0 -0
  76. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/azure_openai.py +0 -0
  77. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/base.py +0 -0
  78. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/config.py +0 -0
  79. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/mock_lm.py +0 -0
  80. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/prompt_formatter/__init__.py +0 -0
  81. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/prompt_formatter/base.py +0 -0
  82. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/prompt_formatter/hf_formatter.py +0 -0
  83. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/prompt_formatter/llama2_formatter.py +0 -0
  84. {langroid-0.13.0 → langroid-0.15.0}/langroid/language_models/utils.py +0 -0
  85. {langroid-0.13.0 → langroid-0.15.0}/langroid/mytypes.py +0 -0
  86. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/__init__.py +0 -0
  87. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/agent_chats.py +0 -0
  88. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/code-parsing.md +0 -0
  89. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/code_parser.py +0 -0
  90. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/config.py +0 -0
  91. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/document_parser.py +0 -0
  92. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/image_text.py +0 -0
  93. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/para_sentence_split.py +0 -0
  94. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/parse_json.py +0 -0
  95. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/parser.py +0 -0
  96. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/repo_loader.py +0 -0
  97. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/routing.py +0 -0
  98. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/search.py +0 -0
  99. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/spider.py +0 -0
  100. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/table_loader.py +0 -0
  101. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/url_loader.py +0 -0
  102. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/url_loader_cookies.py +0 -0
  103. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/urls.py +0 -0
  104. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/utils.py +0 -0
  105. {langroid-0.13.0 → langroid-0.15.0}/langroid/parsing/web_search.py +0 -0
  106. {langroid-0.13.0 → langroid-0.15.0}/langroid/prompts/__init__.py +0 -0
  107. {langroid-0.13.0 → langroid-0.15.0}/langroid/prompts/chat-gpt4-system-prompt.md +0 -0
  108. {langroid-0.13.0 → langroid-0.15.0}/langroid/prompts/dialog.py +0 -0
  109. {langroid-0.13.0 → langroid-0.15.0}/langroid/prompts/prompts_config.py +0 -0
  110. {langroid-0.13.0 → langroid-0.15.0}/langroid/prompts/templates.py +0 -0
  111. {langroid-0.13.0 → langroid-0.15.0}/langroid/pydantic_v1/__init__.py +0 -0
  112. {langroid-0.13.0 → langroid-0.15.0}/langroid/pydantic_v1/main.py +0 -0
  113. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/.chainlit/config.toml +0 -0
  114. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/.chainlit/translations/en-US.json +0 -0
  115. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/__init__.py +0 -0
  116. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/algorithms/__init__.py +0 -0
  117. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/algorithms/graph.py +0 -0
  118. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/configuration.py +0 -0
  119. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/constants.py +0 -0
  120. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/docker.py +0 -0
  121. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/globals.py +0 -0
  122. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/llms/__init__.py +0 -0
  123. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/llms/strings.py +0 -0
  124. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/logging.py +0 -0
  125. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/object_registry.py +0 -0
  126. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/output/__init__.py +0 -0
  127. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/output/citations.py +0 -0
  128. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/output/printing.py +0 -0
  129. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/output/status.py +0 -0
  130. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/pandas_utils.py +0 -0
  131. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/pydantic_utils.py +0 -0
  132. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/system.py +0 -0
  133. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/types.py +0 -0
  134. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/web/__init__.py +0 -0
  135. {langroid-0.13.0 → langroid-0.15.0}/langroid/utils/web/login.py +0 -0
  136. {langroid-0.13.0 → langroid-0.15.0}/langroid/vector_store/__init__.py +0 -0
  137. {langroid-0.13.0 → langroid-0.15.0}/langroid/vector_store/base.py +0 -0
  138. {langroid-0.13.0 → langroid-0.15.0}/langroid/vector_store/chromadb.py +0 -0
  139. {langroid-0.13.0 → langroid-0.15.0}/langroid/vector_store/lancedb.py +0 -0
  140. {langroid-0.13.0 → langroid-0.15.0}/langroid/vector_store/meilisearch.py +0 -0
  141. {langroid-0.13.0 → langroid-0.15.0}/langroid/vector_store/momento.py +0 -0
  142. {langroid-0.13.0 → langroid-0.15.0}/langroid/vector_store/qdrant_cloud.py +0 -0
  143. {langroid-0.13.0 → langroid-0.15.0}/langroid/vector_store/qdrantdb.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langroid
3
- Version: 0.13.0
3
+ Version: 0.15.0
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  License: MIT
6
6
  Author: Prasad Chalasani
@@ -38,6 +38,7 @@ Provides-Extra: vecdbs
38
38
  Requires-Dist: aiohttp (>=3.9.1,<4.0.0)
39
39
  Requires-Dist: async-generator (>=1.10,<2.0)
40
40
  Requires-Dist: bs4 (>=0.0.1,<0.0.2)
41
+ Requires-Dist: cerebras-cloud-sdk (>=1.1.0,<2.0.0)
41
42
  Requires-Dist: chainlit (==1.1.202) ; extra == "all" or extra == "chainlit"
42
43
  Requires-Dist: chromadb (>=0.4.21,<=0.4.23) ; extra == "vecdbs" or extra == "all" or extra == "chromadb"
43
44
  Requires-Dist: colorlog (>=6.7.0,<7.0.0)
@@ -153,6 +154,8 @@ This Multi-Agent paradigm is inspired by the
153
154
  `Langroid` is a fresh take on LLM app-development, where considerable thought has gone
154
155
  into simplifying the developer experience; it does not use `Langchain`.
155
156
 
157
+ :fire: Read the (WIP) [overview of the langroid architecture](https://langroid.github.io/langroid/blog/2024/08/15/overview-of-langroids-multi-agent-architecture-prelim/)
158
+
156
159
  📢 Companies are using/adapting Langroid in **production**. Here is a quote:
157
160
 
158
161
  >[Nullify](https://www.nullify.ai) uses AI Agents for secure software development.
@@ -46,6 +46,8 @@ This Multi-Agent paradigm is inspired by the
46
46
  `Langroid` is a fresh take on LLM app-development, where considerable thought has gone
47
47
  into simplifying the developer experience; it does not use `Langchain`.
48
48
 
49
+ :fire: Read the (WIP) [overview of the langroid architecture](https://langroid.github.io/langroid/blog/2024/08/15/overview-of-langroids-multi-agent-architecture-prelim/)
50
+
49
51
  📢 Companies are using/adapting Langroid in **production**. Here is a quote:
50
52
 
51
53
  >[Nullify](https://www.nullify.ai) uses AI Agents for secure software development.
@@ -14,6 +14,7 @@ pip install "langroid[hf-embeddings]"
14
14
  """
15
15
 
16
16
  import logging
17
+ from collections import OrderedDict
17
18
  from functools import cache
18
19
  from typing import Any, Dict, List, Optional, Set, Tuple, no_type_check
19
20
 
@@ -130,12 +131,16 @@ class DocChatAgentConfig(ChatAgentConfig):
130
131
  n_fuzzy_neighbor_words: int = 100 # num neighbor words to retrieve for fuzzy match
131
132
  use_fuzzy_match: bool = True
132
133
  use_bm25_search: bool = True
134
+ use_reciprocal_rank_fusion: bool = True # ignored if using cross-encoder reranking
133
135
  cross_encoder_reranking_model: str = (
134
136
  "cross-encoder/ms-marco-MiniLM-L-6-v2" if has_sentence_transformers else ""
135
137
  )
136
138
  rerank_diversity: bool = True # rerank to maximize diversity?
137
139
  rerank_periphery: bool = True # rerank to avoid Lost In the Middle effect?
138
140
  rerank_after_adding_context: bool = True # rerank after adding context window?
141
+ # RRF (Reciprocal Rank Fusion) score = 1/(rank + reciprocal_rank_fusion_constant)
142
+ # see https://learn.microsoft.com/en-us/azure/search/hybrid-search-ranking#how-rrf-ranking-works
143
+ reciprocal_rank_fusion_constant: float = 60.0
139
144
  cache: bool = True # cache results
140
145
  debug: bool = False
141
146
  stream: bool = True # allow streaming where needed
@@ -1105,10 +1110,17 @@ class DocChatAgent(ChatAgent):
1105
1110
  Returns:
1106
1111
 
1107
1112
  """
1108
- # if we are using cross-encoder reranking, we can retrieve more docs
1109
- # during retrieval, and leave it to the cross-encoder re-ranking
1110
- # to whittle down to self.config.parsing.n_similar_docs
1111
- retrieval_multiple = 1 if self.config.cross_encoder_reranking_model == "" else 3
1113
+ # if we are using cross-encoder reranking or reciprocal rank fusion (RRF),
1114
+ # we can retrieve more docs during retrieval, and leave it to the cross-encoder
1115
+ # or RRF reranking to whittle down to self.config.parsing.n_similar_docs
1116
+ retrieval_multiple = (
1117
+ 1
1118
+ if (
1119
+ self.config.cross_encoder_reranking_model == ""
1120
+ and not self.config.use_reciprocal_rank_fusion
1121
+ )
1122
+ else 3
1123
+ )
1112
1124
 
1113
1125
  if self.vecdb is None:
1114
1126
  raise ValueError("VecDB not set")
@@ -1120,28 +1132,98 @@ class DocChatAgent(ChatAgent):
1120
1132
  q,
1121
1133
  k=self.config.parsing.n_similar_docs * retrieval_multiple,
1122
1134
  )
1135
+ # sort by score descending
1136
+ docs_and_scores = sorted(
1137
+ docs_and_scores, key=lambda x: x[1], reverse=True
1138
+ )
1139
+
1123
1140
  # keep only docs with unique d.id()
1124
- id2doc_score = {d.id(): (d, s) for d, s in docs_and_scores}
1125
- docs_and_scores = list(id2doc_score.values())
1126
- passages = [d for (d, _) in docs_and_scores]
1127
- # passages = [
1128
- # Document(content=d.content, metadata=d.metadata)
1129
- # for (d, _) in docs_and_scores
1130
- # ]
1141
+ id2_rank_semantic = {d.id(): i for i, (d, _) in enumerate(docs_and_scores)}
1142
+ id2doc = {d.id(): d for d, _ in docs_and_scores}
1143
+ # make sure we get unique docs
1144
+ passages = [id2doc[id] for id, _ in id2_rank_semantic.items()]
1131
1145
 
1146
+ id2_rank_bm25 = {}
1132
1147
  if self.config.use_bm25_search:
1133
1148
  # TODO: Add score threshold in config
1134
1149
  docs_scores = self.get_similar_chunks_bm25(query, retrieval_multiple)
1135
- passages += [d for (d, _) in docs_scores]
1150
+ if self.config.cross_encoder_reranking_model == "":
1151
+ # only if we're not re-ranking with a cross-encoder,
1152
+ # we collect these ranks for Reciprocal Rank Fusion down below.
1153
+ docs_scores = sorted(docs_scores, key=lambda x: x[1], reverse=True)
1154
+ id2_rank_bm25 = {d.id(): i for i, (d, _) in enumerate(docs_scores)}
1155
+ id2doc.update({d.id(): d for d, _ in docs_scores})
1156
+ else:
1157
+ passages += [d for (d, _) in docs_scores]
1136
1158
 
1159
+ id2_rank_fuzzy = {}
1137
1160
  if self.config.use_fuzzy_match:
1138
1161
  # TODO: Add score threshold in config
1139
1162
  fuzzy_match_doc_scores = self.get_fuzzy_matches(query, retrieval_multiple)
1140
- passages += [d for (d, _) in fuzzy_match_doc_scores]
1163
+ if self.config.cross_encoder_reranking_model == "":
1164
+ # only if we're not re-ranking with a cross-encoder,
1165
+ # we collect these ranks for Reciprocal Rank Fusion down below.
1166
+ fuzzy_match_doc_scores = sorted(
1167
+ fuzzy_match_doc_scores, key=lambda x: x[1], reverse=True
1168
+ )
1169
+ id2_rank_fuzzy = {
1170
+ d.id(): i for i, (d, _) in enumerate(fuzzy_match_doc_scores)
1171
+ }
1172
+ id2doc.update({d.id(): d for d, _ in fuzzy_match_doc_scores})
1173
+ else:
1174
+ passages += [d for (d, _) in fuzzy_match_doc_scores]
1141
1175
 
1142
- # keep unique passages
1143
- id2passage = {p.id(): p for p in passages}
1144
- passages = list(id2passage.values())
1176
+ if (
1177
+ self.config.cross_encoder_reranking_model == ""
1178
+ and self.config.use_reciprocal_rank_fusion
1179
+ and (self.config.use_bm25_search or self.config.use_fuzzy_match)
1180
+ ):
1181
+ # Since we're not using cross-enocder re-ranking,
1182
+ # we need to re-order the retrieved chunks from potentially three
1183
+ # different retrieval methods (semantic, bm25, fuzzy), where the
1184
+ # similarity scores are on different scales.
1185
+ # We order the retrieved chunks using Reciprocal Rank Fusion (RRF) score.
1186
+ # Combine the ranks from each id2doc_rank_* dict into a single dict,
1187
+ # where the reciprocal rank score is the sum of
1188
+ # 1/(rank + self.config.reciprocal_rank_fusion_constant).
1189
+ # See https://learn.microsoft.com/en-us/azure/search/hybrid-search-ranking
1190
+ #
1191
+ # Note: diversity/periphery-reranking below may modify the final ranking.
1192
+ id2_reciprocal_score = {}
1193
+ for id_ in (
1194
+ set(id2_rank_semantic.keys())
1195
+ | set(id2_rank_bm25.keys())
1196
+ | set(id2_rank_fuzzy.keys())
1197
+ ):
1198
+ rank_semantic = id2_rank_semantic.get(id_, float("inf"))
1199
+ rank_bm25 = id2_rank_bm25.get(id_, float("inf"))
1200
+ rank_fuzzy = id2_rank_fuzzy.get(id_, float("inf"))
1201
+ c = self.config.reciprocal_rank_fusion_constant
1202
+ reciprocal_fusion_score = (
1203
+ 1 / (rank_semantic + c) + 1 / (rank_bm25 + c) + 1 / (rank_fuzzy + c)
1204
+ )
1205
+ id2_reciprocal_score[id_] = reciprocal_fusion_score
1206
+
1207
+ # sort the docs by the reciprocal score, in descending order
1208
+ id2_reciprocal_score = OrderedDict(
1209
+ sorted(
1210
+ id2_reciprocal_score.items(),
1211
+ key=lambda x: x[1],
1212
+ reverse=True,
1213
+ )
1214
+ )
1215
+ # each method retrieved up to retrieval_multiple * n_similar_docs,
1216
+ # so we need to take the top n_similar_docs from the combined list
1217
+ passages = [
1218
+ id2doc[id]
1219
+ for i, (id, _) in enumerate(id2_reciprocal_score.items())
1220
+ if i < self.config.parsing.n_similar_docs
1221
+ ]
1222
+ # passages must have distinct ids
1223
+ assert len(passages) == len(set([d.id() for d in passages])), (
1224
+ f"Duplicate passages in retrieved docs: {len(passages)} != "
1225
+ f"{len(set([d.id() for d in passages]))}"
1226
+ )
1145
1227
 
1146
1228
  if len(passages) == 0:
1147
1229
  return []
@@ -1171,7 +1253,7 @@ class DocChatAgent(ChatAgent):
1171
1253
  passages_scores = self.add_context_window(passages_scores)
1172
1254
  passages = [p for p, _ in passages_scores]
1173
1255
 
1174
- return passages
1256
+ return passages[: self.config.parsing.n_similar_docs]
1175
1257
 
1176
1258
  @no_type_check
1177
1259
  def get_relevant_extracts(self, query: str) -> Tuple[str, List[Document]]:
@@ -21,6 +21,7 @@ from typing import (
21
21
  )
22
22
 
23
23
  import openai
24
+ from cerebras.cloud.sdk import AsyncCerebras, Cerebras
24
25
  from groq import AsyncGroq, Groq
25
26
  from httpx import Timeout
26
27
  from openai import AsyncOpenAI, OpenAI
@@ -371,8 +372,8 @@ class OpenAIGPT(LanguageModel):
371
372
  Class for OpenAI LLMs
372
373
  """
373
374
 
374
- client: OpenAI | Groq
375
- async_client: AsyncOpenAI | AsyncGroq
375
+ client: OpenAI | Groq | Cerebras
376
+ async_client: AsyncOpenAI | AsyncGroq | AsyncCerebras
376
377
 
377
378
  def __init__(self, config: OpenAIGPTConfig = OpenAIGPTConfig()):
378
379
  """
@@ -479,6 +480,7 @@ class OpenAIGPT(LanguageModel):
479
480
  self.api_key = DUMMY_API_KEY
480
481
 
481
482
  self.is_groq = self.config.chat_model.startswith("groq/")
483
+ self.is_cerebras = self.config.chat_model.startswith("cerebras/")
482
484
 
483
485
  if self.is_groq:
484
486
  self.config.chat_model = self.config.chat_model.replace("groq/", "")
@@ -489,6 +491,16 @@ class OpenAIGPT(LanguageModel):
489
491
  self.async_client = AsyncGroq(
490
492
  api_key=self.api_key,
491
493
  )
494
+ elif self.is_cerebras:
495
+ self.config.chat_model = self.config.chat_model.replace("cerebras/", "")
496
+ self.api_key = os.getenv("CEREBRAS_API_KEY", DUMMY_API_KEY)
497
+ self.client = Cerebras(
498
+ api_key=self.api_key,
499
+ )
500
+ # TODO there is not async client, so should we do anything here?
501
+ self.async_client = AsyncCerebras(
502
+ api_key=self.api_key,
503
+ )
492
504
  else:
493
505
  self.client = OpenAI(
494
506
  api_key=self.api_key,
@@ -1096,8 +1108,8 @@ class OpenAIGPT(LanguageModel):
1096
1108
  if self.config.use_chat_for_completion:
1097
1109
  return self.chat(messages=prompt, max_tokens=max_tokens)
1098
1110
 
1099
- if self.is_groq:
1100
- raise ValueError("Groq does not support pure completions")
1111
+ if self.is_groq or self.is_cerebras:
1112
+ raise ValueError("Groq, Cerebras do not support pure completions")
1101
1113
 
1102
1114
  if settings.debug:
1103
1115
  print(f"[grey37]PROMPT: {escape(prompt)}[/grey37]")
@@ -1174,8 +1186,8 @@ class OpenAIGPT(LanguageModel):
1174
1186
  if self.config.use_chat_for_completion:
1175
1187
  return await self.achat(messages=prompt, max_tokens=max_tokens)
1176
1188
 
1177
- if self.is_groq:
1178
- raise ValueError("Groq does not support pure completions")
1189
+ if self.is_groq or self.is_cerebras:
1190
+ raise ValueError("Groq, Cerebras do not support pure completions")
1179
1191
 
1180
1192
  if settings.debug:
1181
1193
  print(f"[grey37]PROMPT: {escape(prompt)}[/grey37]")
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "langroid"
3
- version = "0.13.0"
3
+ version = "0.15.0"
4
4
  description = "Harness LLMs with Multi-Agent Programming"
5
5
  authors = ["Prasad Chalasani <pchalasani@gmail.com>"]
6
6
  readme = "README.md"
@@ -89,6 +89,7 @@ async-generator = "^1.10"
89
89
 
90
90
  python-magic = "^0.4.27"
91
91
  json-repair = "^0.27.0"
92
+ cerebras-cloud-sdk = "^1.1.0"
92
93
 
93
94
 
94
95
  [tool.poetry.extras]
File without changes
File without changes
File without changes