langroid 0.39.2__py3-none-any.whl → 0.39.4__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.
@@ -58,7 +58,7 @@ from langroid.utils.object_registry import ObjectRegistry
58
58
  from langroid.utils.output import show_if_debug, status
59
59
  from langroid.utils.output.citations import (
60
60
  extract_markdown_references,
61
- format_footnote_text,
61
+ format_cited_references,
62
62
  )
63
63
  from langroid.utils.pydantic_utils import dataframe_to_documents, extract_fields
64
64
  from langroid.vector_store.base import VectorStore, VectorStoreConfig
@@ -859,18 +859,10 @@ class DocChatAgent(ChatAgent):
859
859
  final_answer = answer_doc.content.strip()
860
860
  show_if_debug(final_answer, "SUMMARIZE_RESPONSE= ")
861
861
 
862
+ # extract references like [^2], [^3], etc. from the final answer
862
863
  citations = extract_markdown_references(final_answer)
863
-
864
- citations_str = ""
865
- if len(citations) > 0:
866
- # append [i] source, content for each citation
867
- citations_str = "\n".join(
868
- [
869
- f"[^{c}] {passages[c-1].metadata.source}"
870
- f"\n{format_footnote_text(passages[c-1].content)}"
871
- for c in citations
872
- ]
873
- )
864
+ # format the cited references as a string suitable for markdown footnote
865
+ citations_str = format_cited_references(citations, passages)
874
866
 
875
867
  return ChatDocument(
876
868
  content=final_answer, # does not contain citations
@@ -54,6 +54,7 @@ class DeepSeekModel(ModelName):
54
54
 
55
55
  DEEPSEEK = "deepseek/deepseek-chat"
56
56
  DEEPSEEK_R1 = "deepseek/deepseek-reasoner"
57
+ OPENROUTER_DEEPSEEK_R1 = "openrouter/deepseek/deepseek-r1"
57
58
 
58
59
 
59
60
  class GeminiModel(ModelName):
@@ -66,6 +67,23 @@ class GeminiModel(ModelName):
66
67
  GEMINI_2_FLASH_THINKING = "gemini/gemini-2.0-flash-thinking-exp"
67
68
 
68
69
 
70
+ class OpenAI_API_ParamInfo(BaseModel):
71
+ """
72
+ Parameters exclusive to some models, when using OpenAI API
73
+ """
74
+
75
+ params: Dict[str, List[str]] = dict(
76
+ reasoning_effort=[
77
+ OpenAIChatModel.O3_MINI.value,
78
+ ],
79
+ )
80
+ extra_parameters: Dict[str, List[str]] = dict(
81
+ include_reasoning=[
82
+ DeepSeekModel.OPENROUTER_DEEPSEEK_R1.value,
83
+ ]
84
+ )
85
+
86
+
69
87
  class ModelInfo(BaseModel):
70
88
  """
71
89
  Consolidated information about LLM, related to capacity, cost and API
@@ -49,6 +49,7 @@ from langroid.language_models.config import HFPromptFormatterConfig
49
49
  from langroid.language_models.model_info import (
50
50
  DeepSeekModel,
51
51
  GeminiModel,
52
+ OpenAI_API_ParamInfo,
52
53
  get_model_info,
53
54
  )
54
55
  from langroid.language_models.model_info import (
@@ -203,6 +204,7 @@ class OpenAICallParams(BaseModel):
203
204
  stop: str | List[str] | None = None # (list of) stop sequence(s)
204
205
  seed: int | None = 42
205
206
  user: str | None = None # user id for tracking
207
+ extra_body: Dict[str, Any] | None = None # additional params for API request body
206
208
 
207
209
  def to_dict_exclude_none(self) -> Dict[str, Any]:
208
210
  return {k: v for k, v in self.dict().items() if v is not None}
@@ -642,7 +644,15 @@ class OpenAIGPT(LanguageModel):
642
644
  """
643
645
  List of params that are not supported by the current model
644
646
  """
645
- return get_model_info(self.config.chat_model).unsupported_params
647
+ model_info = get_model_info(self.config.chat_model)
648
+ unsupported = set(model_info.unsupported_params)
649
+ for param, model_list in OpenAI_API_ParamInfo().params.items():
650
+ if (
651
+ self.config.chat_model not in model_list
652
+ and self.chat_model_orig not in model_list
653
+ ):
654
+ unsupported.add(param)
655
+ return list(unsupported)
646
656
 
647
657
  def rename_params(self) -> Dict[str, str]:
648
658
  """
@@ -739,7 +749,10 @@ class OpenAIGPT(LanguageModel):
739
749
  delta = choices[0].get("delta", {})
740
750
  # capture both content and reasoning_content
741
751
  event_text = delta.get("content", "")
742
- event_reasoning = delta.get("reasoning_content", "")
752
+ event_reasoning = delta.get(
753
+ "reasoning_content",
754
+ delta.get("reasoning", ""),
755
+ )
743
756
  if "function_call" in delta and delta["function_call"] is not None:
744
757
  if "name" in delta["function_call"]:
745
758
  event_fn_name = delta["function_call"]["name"]
@@ -861,7 +874,10 @@ class OpenAIGPT(LanguageModel):
861
874
  if chat:
862
875
  delta = choices[0].get("delta", {})
863
876
  event_text = delta.get("content", "")
864
- event_reasoning = delta.get("reasoning_content", "")
877
+ event_reasoning = delta.get(
878
+ "reasoning_content",
879
+ delta.get("reasoning", ""),
880
+ )
865
881
  if "function_call" in delta and delta["function_call"] is not None:
866
882
  if "name" in delta["function_call"]:
867
883
  event_fn_name = delta["function_call"]["name"]
@@ -1757,6 +1773,18 @@ class OpenAIGPT(LanguageModel):
1757
1773
  for old_param, new_param in param_rename_map.items():
1758
1774
  if old_param in args:
1759
1775
  args[new_param] = args.pop(old_param)
1776
+
1777
+ # finally, get rid of extra_body params exclusive to certain models
1778
+ extra_params = args.get("extra_body", {})
1779
+ if extra_params:
1780
+ for param, model_list in OpenAI_API_ParamInfo().extra_parameters.items():
1781
+ if (
1782
+ self.config.chat_model not in model_list
1783
+ and self.chat_model_orig not in model_list
1784
+ ):
1785
+ extra_params.pop(param, None)
1786
+ if extra_params:
1787
+ args["extra_body"] = extra_params
1760
1788
  return args
1761
1789
 
1762
1790
  def _process_chat_completion_response(
langroid/parsing/urls.py CHANGED
@@ -221,10 +221,15 @@ def find_urls(
221
221
  response = requests.get(url, timeout=5)
222
222
  response.raise_for_status()
223
223
  soup = BeautifulSoup(response.text, "html.parser")
224
- links = [urljoin(url, a["href"]) for a in soup.find_all("a", href=True)]
224
+ links = [
225
+ urljoin(url, a["href"]) # type: ignore
226
+ for a in soup.find_all("a", href=True)
227
+ ]
225
228
 
226
229
  # Defrag links: discard links that are to portions of same page
227
- defragged_links = list(set(urldefrag(link).url for link in links))
230
+ defragged_links = list(
231
+ set(urldefrag(link).url for link in links) # type: ignore
232
+ )
228
233
 
229
234
  # Filter links based on domain matching requirement
230
235
  domain_matching_links = [
@@ -1,4 +1,9 @@
1
- def extract_markdown_references(md_string: str) -> list[int]:
1
+ from typing import List
2
+
3
+ from langroid.mytypes import Document
4
+
5
+
6
+ def extract_markdown_references(md_string: str) -> List[int]:
2
7
  """
3
8
  Extracts markdown references (e.g., [^1], [^2]) from a string and returns
4
9
  them as a sorted list of integers.
@@ -59,3 +64,28 @@ def format_footnote_text(content: str, width: int = 0) -> str:
59
64
 
60
65
  # Join them with newline so we preserve the paragraph/blank line structure
61
66
  return "\n".join(output_lines)
67
+
68
+
69
+ def format_cited_references(citations: List[int], passages: list[Document]) -> str:
70
+ """
71
+ Given a list of (integer) citations, and a list of passages, return a string
72
+ that can be added as a footer to the main text, to show sources cited.
73
+
74
+ Args:
75
+ citations (list[int]): list of citations, presumably from main text
76
+ passages (list[Document]): list of passages (Document objects)
77
+
78
+ Returns:
79
+ str: formatted string of citations for footnote in markdown
80
+ """
81
+ citations_str = ""
82
+ if len(citations) > 0:
83
+ # append [i] source, content for each citation
84
+ citations_str = "\n".join(
85
+ [
86
+ f"[^{c}] {passages[c-1].metadata.source}"
87
+ f"\n{format_footnote_text(passages[c-1].content)}"
88
+ for c in citations
89
+ ]
90
+ )
91
+ return citations_str
langroid/utils/system.py CHANGED
@@ -14,11 +14,7 @@ from typing import Any, Literal
14
14
 
15
15
  logger = logging.getLogger(__name__)
16
16
 
17
- DELETION_ALLOWED_PATHS = [
18
- ".qdrant",
19
- ".chroma",
20
- ".lancedb",
21
- ]
17
+ DELETION_ALLOWED_PATHS = [".qdrant", ".chroma", ".lancedb", ".weaviate"]
22
18
 
23
19
 
24
20
  def pydantic_major_version() -> int:
@@ -32,6 +32,8 @@ class WeaviateDBConfig(VectorStoreConfig):
32
32
  collection_name: str | None = "temp"
33
33
  embedding: EmbeddingModelsConfig = OpenAIEmbeddingsConfig()
34
34
  distance: str = VectorDistances.COSINE
35
+ cloud: bool = False
36
+ storage_path: str = ".weaviate_embedded/data"
35
37
 
36
38
 
37
39
  class WeaviateDB(VectorStore):
@@ -39,19 +41,25 @@ class WeaviateDB(VectorStore):
39
41
  super().__init__(config)
40
42
  self.config: WeaviateDBConfig = config
41
43
  load_dotenv()
42
- key = os.getenv("WEAVIATE_API_KEY")
43
- url = os.getenv("WEAVIATE_API_URL")
44
- if url is None or key is None:
45
- raise ValueError(
46
- """WEAVIATE_API_KEY, WEAVIATE_API_URL env variable must be set to use
47
- WeaviateDB in cloud mode. Please set these values
48
- in your .env file.
49
- """
44
+ if not self.config.cloud:
45
+ self.client = weaviate.connect_to_embedded(
46
+ version="latest", persistence_data_path=self.config.storage_path
50
47
  )
51
- self.client = weaviate.connect_to_weaviate_cloud(
52
- cluster_url=url,
53
- auth_credentials=Auth.api_key(key),
54
- )
48
+ else: # Cloud mode
49
+ key = os.getenv("WEAVIATE_API_KEY")
50
+ url = os.getenv("WEAVIATE_API_URL")
51
+ if url is None or key is None:
52
+ raise ValueError(
53
+ """WEAVIATE_API_KEY, WEAVIATE_API_URL env variables must be set to
54
+ use WeaviateDB in cloud mode. Please set these values
55
+ in your .env file.
56
+ """
57
+ )
58
+ self.client = weaviate.connect_to_weaviate_cloud(
59
+ cluster_url=url,
60
+ auth_credentials=Auth.api_key(key),
61
+ )
62
+
55
63
  if config.collection_name is not None:
56
64
  WeaviateDB.validate_and_format_collection_name(config.collection_name)
57
65
 
@@ -267,3 +275,8 @@ class WeaviateDB(VectorStore):
267
275
  )
268
276
 
269
277
  return formatted_name
278
+
279
+ def __del__(self) -> None:
280
+ # Gracefully close the connection with local client
281
+ if not self.config.cloud:
282
+ self.client.close()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langroid
3
- Version: 0.39.2
3
+ Version: 0.39.4
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  Author-email: Prasad Chalasani <pchalasani@gmail.com>
6
6
  License: MIT
@@ -30,7 +30,7 @@ Requires-Dist: lxml<5.0.0,>=4.9.3
30
30
  Requires-Dist: nest-asyncio<2.0.0,>=1.6.0
31
31
  Requires-Dist: nltk<4.0.0,>=3.8.2
32
32
  Requires-Dist: onnxruntime<2.0.0,>=1.16.1
33
- Requires-Dist: openai<2.0.0,>=1.45.0
33
+ Requires-Dist: openai<2.0.0,>=1.61.1
34
34
  Requires-Dist: pandas<3.0.0,>=2.0.3
35
35
  Requires-Dist: prettytable<4.0.0,>=3.8.0
36
36
  Requires-Dist: pydantic<3.0.0,>=1
@@ -14,7 +14,7 @@ langroid/agent/xml_tool_message.py,sha256=6SshYZJKIfi4mkE-gIoSwjkEYekQ8GwcSiCv7a
14
14
  langroid/agent/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  langroid/agent/callbacks/chainlit.py,sha256=RH8qUXaZE5o2WQz3WJQ1SdFtASGlxWCA6_HYz_3meDQ,20822
16
16
  langroid/agent/special/__init__.py,sha256=gik_Xtm_zV7U9s30Mn8UX3Gyuy4jTjQe9zjiE3HWmEo,1273
17
- langroid/agent/special/doc_chat_agent.py,sha256=tMx-3cBEIHJM14P20cYvIzAc9z-skSnHOPVJ0eegxzc,64692
17
+ langroid/agent/special/doc_chat_agent.py,sha256=Q16HOg6MXa26szTO29OOIv1kv8QfuUjxLlLOP3eqZvA,64539
18
18
  langroid/agent/special/lance_doc_chat_agent.py,sha256=s8xoRs0gGaFtDYFUSIRchsgDVbS5Q3C2b2mr3V1Fd-Q,10419
19
19
  langroid/agent/special/lance_tools.py,sha256=qS8x4wi8mrqfbYV2ztFzrcxyhHQ0ZWOc-zkYiH7awj0,2105
20
20
  langroid/agent/special/relevance_extractor_agent.py,sha256=zIx8GUdVo1aGW6ASla0NPQjYYIpmriK_TYMijqAx3F8,4796
@@ -69,8 +69,8 @@ langroid/language_models/azure_openai.py,sha256=zNQzzsERxNestq-hFfQZbvTzK43G2vjR
69
69
  langroid/language_models/base.py,sha256=mN6HAjLgF2xpHObz5uPZ3JDID7jdTiRLEkoGgGrqLM8,25177
70
70
  langroid/language_models/config.py,sha256=9Q8wk5a7RQr8LGMT_0WkpjY8S4ywK06SalVRjXlfCiI,378
71
71
  langroid/language_models/mock_lm.py,sha256=5BgHKDVRWFbUwDT_PFgTZXz9-k8wJSA2e3PZmyDgQ1k,4022
72
- langroid/language_models/model_info.py,sha256=n60j5DrAlxCsHa8pl7PWNBPP7pSAEVMi2mUQ4JOqo7Q,10648
73
- langroid/language_models/openai_gpt.py,sha256=Vuxz3tZThUN_9MF16KW0HJe0k0qk1tv58PZ0qqwpGdg,76754
72
+ langroid/language_models/model_info.py,sha256=6B8Cey0eX8vR6wAc8-Cb1Gj7pazN01A-FjWTYpG0QFg,11111
73
+ langroid/language_models/openai_gpt.py,sha256=3_kC1o4eY-VnCPAgP8JoIm-fOUnCzHEATymV8WG_ecw,77876
74
74
  langroid/language_models/utils.py,sha256=L4_CbihDMTGcsg0TOG1Yd5JFEto46--h7CX_14m89sQ,5016
75
75
  langroid/language_models/prompt_formatter/__init__.py,sha256=2-5cdE24XoFDhifOLl8yiscohil1ogbP1ECkYdBlBsk,372
76
76
  langroid/language_models/prompt_formatter/base.py,sha256=eDS1sgRNZVnoajwV_ZIha6cba5Dt8xjgzdRbPITwx3Q,1221
@@ -90,7 +90,7 @@ langroid/parsing/search.py,sha256=M1swZfZEMEsalmTwVCkql3DzBNBemky7pWt0PrcwGdQ,97
90
90
  langroid/parsing/spider.py,sha256=hAVM6wxh1pQ0EN4tI5wMBtAjIk0T-xnpi-ZUzWybhos,3258
91
91
  langroid/parsing/table_loader.py,sha256=qNM4obT_0Y4tjrxNBCNUYjKQ9oETCZ7FbolKBTcz-GM,3410
92
92
  langroid/parsing/url_loader.py,sha256=JK48KktLRDBfjrt4nsUfy92M6yGdEeicAqOum2MdULM,4656
93
- langroid/parsing/urls.py,sha256=XjpaV5onG7gKQ5iQeFTzHSw5P08Aqw0g-rMUu61lR6s,7988
93
+ langroid/parsing/urls.py,sha256=86omykgxo4hg2jyF10Ef-FJa9n6MgXdSXy2mImqgo5c,8076
94
94
  langroid/parsing/utils.py,sha256=YrV2GNL4EOBGknA4AClPGdJ4S5B31radrt-Ou8OAKoU,12749
95
95
  langroid/parsing/web_search.py,sha256=8rW8EI3tyHITaB2l9MT_6yLMeQfo8y-Ih-8N2v2uMpk,4931
96
96
  langroid/prompts/__init__.py,sha256=RW11vK6jiLPuaUh4GpeFvstti73gkm8_rDMtrbo2YsU,142
@@ -108,12 +108,12 @@ langroid/utils/logging.py,sha256=mwxHimq1wtVQ64PvDyfJJ7Upj-rjHLNHgx8EC2wClvo,402
108
108
  langroid/utils/object_registry.py,sha256=iPz9GHzvmCeVoidB3JdAMEKcxJEqTdUr0otQEexDZ5s,2100
109
109
  langroid/utils/pandas_utils.py,sha256=UctS986Jtl_MvU5rA7-GfrjEHXP7MNu8ePhepv0bTn0,755
110
110
  langroid/utils/pydantic_utils.py,sha256=R7Ps8VP56-eSo-LYHWllFo-SJ2zDmdItuuYpUq2gGJ8,20854
111
- langroid/utils/system.py,sha256=AiEehQy0K9c9qHdKsZRCscRrazDzuh5Tv3GRQsA0Cxg,8455
111
+ langroid/utils/system.py,sha256=cJqDgOf9mM82l1GyUeQQdEYAwepYXQwtpJU8Xrz0-MA,8453
112
112
  langroid/utils/types.py,sha256=4GrOnU3HLWh-UwaUPp7LlB3V413q3K5OSzc0ggDoQ6A,2510
113
113
  langroid/utils/algorithms/__init__.py,sha256=WylYoZymA0fnzpB4vrsH_0n7WsoLhmuZq8qxsOCjUpM,41
114
114
  langroid/utils/algorithms/graph.py,sha256=JbdpPnUOhw4-D6O7ou101JLA3xPCD0Lr3qaPoFCaRfo,2866
115
115
  langroid/utils/output/__init__.py,sha256=7P0f--4IZneNsTxXY5fd6d6iW-CeVe-KSsl-87sbBPc,340
116
- langroid/utils/output/citations.py,sha256=mQhRXVN-uhmKd2z32UZQBE0adZGEaQJ7cVXLfkrcZJI,2221
116
+ langroid/utils/output/citations.py,sha256=9T69O_N6mxPQjQ-qC1vKS8_kyg1z5hDQXMhBsA45xkk,3147
117
117
  langroid/utils/output/printing.py,sha256=yzPJZN-8_jyOJmI9N_oLwEDfjMwVgk3IDiwnZ4eK_AE,2962
118
118
  langroid/utils/output/status.py,sha256=rzbE7mDJcgNNvdtylCseQcPGCGghtJvVq3lB-OPJ49E,1049
119
119
  langroid/vector_store/__init__.py,sha256=BcoOm1tG3y0EqjkIGmMOHkY9iTUhDHgyruknWDKgqIg,1214
@@ -123,8 +123,8 @@ langroid/vector_store/lancedb.py,sha256=Qd20gKjWozPWfW5-D66J6U8dSrJo1yl-maj6s1lb
123
123
  langroid/vector_store/meilisearch.py,sha256=6frB7GFWeWmeKzRfLZIvzRjllniZ1cYj3HmhHQICXLs,11663
124
124
  langroid/vector_store/momento.py,sha256=xOaU7Hlyyn_5ihb0ARS5JHtmrKrTCt2IdRA-ioMM5ek,10307
125
125
  langroid/vector_store/qdrantdb.py,sha256=v7TAsIoj_vxeKDYS9tpwJLBZA8fuTweTYxHo0X_uawM,17949
126
- langroid/vector_store/weaviatedb.py,sha256=FOzgvqLqvdN5jJebVtJ-8tu2CeBzBfSP3ih4_ODEOOw,10605
127
- langroid-0.39.2.dist-info/METADATA,sha256=wFY32Hc5yDfZqfFRrz9AKIM17w42GxzYY13pBQX2shg,60634
128
- langroid-0.39.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
129
- langroid-0.39.2.dist-info/licenses/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
130
- langroid-0.39.2.dist-info/RECORD,,
126
+ langroid/vector_store/weaviatedb.py,sha256=cMg9kqJXlD1WURs6QivHvwausCyLYGr4mOK2v9uYkhw,11105
127
+ langroid-0.39.4.dist-info/METADATA,sha256=kmZh0J5DvAdv2oNUiCAa3e1SfQ7Le0-egld9zjhVMAw,60634
128
+ langroid-0.39.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
129
+ langroid-0.39.4.dist-info/licenses/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
130
+ langroid-0.39.4.dist-info/RECORD,,