langroid 0.49.0__py3-none-any.whl → 0.49.1__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.
@@ -1059,8 +1059,8 @@ class OpenAIGPT(LanguageModel):
1059
1059
  )
1060
1060
  if is_break:
1061
1061
  break
1062
- except Exception:
1063
- pass
1062
+ except Exception as e:
1063
+ logging.warning("Error while processing stream response: %s", str(e))
1064
1064
 
1065
1065
  print("")
1066
1066
  # TODO- get usage info in stream mode (?)
@@ -1121,8 +1121,8 @@ class OpenAIGPT(LanguageModel):
1121
1121
  )
1122
1122
  if is_break:
1123
1123
  break
1124
- except Exception:
1125
- pass
1124
+ except Exception as e:
1125
+ logging.warning("Error while processing stream response: %s", str(e))
1126
1126
 
1127
1127
  print("")
1128
1128
  # TODO- get usage info in stream mode (?)
@@ -1703,11 +1703,32 @@ class OpenAIGPT(LanguageModel):
1703
1703
  if self.config.litellm and settings.debug:
1704
1704
  kwargs["logger_fn"] = litellm_logging_fn
1705
1705
  result = completion_call(**kwargs)
1706
- if not self.get_stream():
1707
- # if streaming, cannot cache result
1706
+
1707
+ if self.get_stream():
1708
+ # If streaming, cannot cache result
1708
1709
  # since it is a generator. Instead,
1709
1710
  # we hold on to the hashed_key and
1710
1711
  # cache the result later
1712
+
1713
+ # Test if this is a stream with an exception by
1714
+ # trying to get first chunk: Some providers like LiteLLM
1715
+ # produce a valid stream object `result` instead of throwing a
1716
+ # rate-limit error, and if we don't catch it here,
1717
+ # we end up returning an empty response and not
1718
+ # using the retry mechanism in the decorator.
1719
+ try:
1720
+ # try to get the first chunk to check for errors
1721
+ test_iter = iter(result)
1722
+ first_chunk = next(test_iter)
1723
+ # If we get here without error, recreate the stream
1724
+ result = chain([first_chunk], test_iter)
1725
+ except StopIteration:
1726
+ # Empty stream is fine
1727
+ pass
1728
+ except Exception as e:
1729
+ # Propagate any errors in the stream
1730
+ raise e
1731
+ else:
1711
1732
  self._cache_store(hashed_key, result.model_dump())
1712
1733
  return cached, hashed_key, result
1713
1734
 
@@ -1734,7 +1755,35 @@ class OpenAIGPT(LanguageModel):
1734
1755
  kwargs["logger_fn"] = litellm_logging_fn
1735
1756
  # If it's not in the cache, call the API
1736
1757
  result = await acompletion_call(**kwargs)
1737
- if not self.get_stream():
1758
+ if self.get_stream():
1759
+ try:
1760
+ # Try to peek at the first chunk to immediately catch any errors
1761
+ # Store the original result (the stream)
1762
+ original_stream = result
1763
+
1764
+ # Manually create and advance the iterator to check for errors
1765
+ stream_iter = original_stream.__aiter__()
1766
+ try:
1767
+ # This will raise an exception if the stream is invalid
1768
+ first_chunk = await anext(stream_iter)
1769
+
1770
+ # If we reach here, the stream started successfully
1771
+ # Now recreate a fresh stream from the original API result
1772
+ # Otherwise, return a new stream that yields the first chunk
1773
+ # and remaining items
1774
+ async def combined_stream(): # type: ignore
1775
+ yield first_chunk
1776
+ async for chunk in stream_iter:
1777
+ yield chunk
1778
+
1779
+ result = combined_stream() # type: ignore
1780
+ except StopAsyncIteration:
1781
+ # Empty stream is normal - nothing to do
1782
+ pass
1783
+ except Exception as e:
1784
+ # Any exception here should be raised to trigger the retry mechanism
1785
+ raise e
1786
+ else:
1738
1787
  self._cache_store(hashed_key, result.model_dump())
1739
1788
  return cached, hashed_key, result
1740
1789
 
langroid/mytypes.py CHANGED
@@ -65,6 +65,30 @@ class DocMetaData(BaseModel):
65
65
 
66
66
  return original_dict
67
67
 
68
+ def __str__(self) -> str:
69
+ title_str = (
70
+ ""
71
+ if "unknown" in self.title.lower() or self.title.strip() == ""
72
+ else f"Title: {self.title}"
73
+ )
74
+ date_str = ""
75
+ if (
76
+ "unknown" not in self.published_date.lower()
77
+ and self.published_date.strip() != ""
78
+ ):
79
+ try:
80
+ from dateutil import parser
81
+
82
+ # Try to parse the date string
83
+ date_obj = parser.parse(self.published_date)
84
+ # Format to include only the date part (year-month-day)
85
+ date_only = date_obj.strftime("%Y-%m-%d")
86
+ date_str = f"Date: {date_only}"
87
+ except (ValueError, ImportError, TypeError):
88
+ # If parsing fails, just use the original date
89
+ date_str = f"Date: {self.published_date}"
90
+ return f"{self.source} {title_str} {date_str}".strip()
91
+
68
92
  class Config:
69
93
  extra = Extra.allow
70
94
 
@@ -93,7 +117,7 @@ class Document(BaseModel):
93
117
  return dedent(
94
118
  f"""
95
119
  CONTENT: {self.content}
96
- SOURCE:{self.metadata.source}
120
+ SOURCE:{str(self.metadata)}
97
121
  """
98
122
  )
99
123
 
@@ -97,7 +97,7 @@ def format_cited_references(
97
97
  # source and content for each citation
98
98
  full_citations_str = "\n".join(
99
99
  [
100
- f"[^{c}] {passages[c-1].metadata.source}"
100
+ f"[^{c}] {str(passages[c-1].metadata)}"
101
101
  f"\n{format_footnote_text(passages[c-1].content)}"
102
102
  for c in good_citations
103
103
  ]
@@ -105,6 +105,6 @@ def format_cited_references(
105
105
 
106
106
  # source for each citation
107
107
  citations_str = "\n".join(
108
- [f"[^{c}] {passages[c-1].metadata.source}" for c in good_citations]
108
+ [f"[^{c}] {str(passages[c-1].metadata)}" for c in good_citations]
109
109
  )
110
110
  return full_citations_str, citations_str
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langroid
3
- Version: 0.49.0
3
+ Version: 0.49.1
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  Author-email: Prasad Chalasani <pchalasani@gmail.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  langroid/__init__.py,sha256=z_fCOLQJPOw3LLRPBlFB5-2HyCjpPgQa4m4iY5Fvb8Y,1800
2
2
  langroid/exceptions.py,sha256=OPjece_8cwg94DLPcOGA1ddzy5bGh65pxzcHMnssTz8,2995
3
- langroid/mytypes.py,sha256=1mt21xiczAu1WgfZIptBKN9WpqYgpVeo8cAXvs6drKA,2986
3
+ langroid/mytypes.py,sha256=ezj_6FFDkJZiVx1SS9eJvh23dH76Ti7mJbePi8ldkAI,3919
4
4
  langroid/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  langroid/agent/__init__.py,sha256=ll0Cubd2DZ-fsCMl7e10hf9ZjFGKzphfBco396IKITY,786
6
6
  langroid/agent/base.py,sha256=U-UjdpxIFqkzRIB5-LYwHrhMSNI3sDbfnNRqIhrtsyI,79568
@@ -72,7 +72,7 @@ langroid/language_models/base.py,sha256=mDYmFCBCLdq8_Uvws4MiewwEgcOCP8Qb0e5yUXr3
72
72
  langroid/language_models/config.py,sha256=9Q8wk5a7RQr8LGMT_0WkpjY8S4ywK06SalVRjXlfCiI,378
73
73
  langroid/language_models/mock_lm.py,sha256=5BgHKDVRWFbUwDT_PFgTZXz9-k8wJSA2e3PZmyDgQ1k,4022
74
74
  langroid/language_models/model_info.py,sha256=tfBBxL0iUf2mVN6CjcvqflzFUVg2oZqOJZexZ8jHTYA,12216
75
- langroid/language_models/openai_gpt.py,sha256=Vcs2g2N3dT6Oc8WfbIXckuzmYWUCrN8TPYw0yyyTWNM,80378
75
+ langroid/language_models/openai_gpt.py,sha256=M_jp97Ksp5r3U-d0jCLPLjVmn7IK1mC8Ry4t7k6A5tc,82906
76
76
  langroid/language_models/utils.py,sha256=L4_CbihDMTGcsg0TOG1Yd5JFEto46--h7CX_14m89sQ,5016
77
77
  langroid/language_models/prompt_formatter/__init__.py,sha256=2-5cdE24XoFDhifOLl8yiscohil1ogbP1ECkYdBlBsk,372
78
78
  langroid/language_models/prompt_formatter/base.py,sha256=eDS1sgRNZVnoajwV_ZIha6cba5Dt8xjgzdRbPITwx3Q,1221
@@ -115,7 +115,7 @@ langroid/utils/types.py,sha256=-BvyIf_LmAJ5jR9NC7S4CSVNEr3XayAaxJ5o0TiIej0,2992
115
115
  langroid/utils/algorithms/__init__.py,sha256=WylYoZymA0fnzpB4vrsH_0n7WsoLhmuZq8qxsOCjUpM,41
116
116
  langroid/utils/algorithms/graph.py,sha256=JbdpPnUOhw4-D6O7ou101JLA3xPCD0Lr3qaPoFCaRfo,2866
117
117
  langroid/utils/output/__init__.py,sha256=7P0f--4IZneNsTxXY5fd6d6iW-CeVe-KSsl-87sbBPc,340
118
- langroid/utils/output/citations.py,sha256=5mhg2-kpBF7qgV82gJbIiUHfoJcpJiK1sAWdDF0o0Wc,3866
118
+ langroid/utils/output/citations.py,sha256=cEiqSH7DJ5q4M2z_6eFjCj9Ohnf68i6sivjeRFuFAtk,3862
119
119
  langroid/utils/output/printing.py,sha256=yzPJZN-8_jyOJmI9N_oLwEDfjMwVgk3IDiwnZ4eK_AE,2962
120
120
  langroid/utils/output/status.py,sha256=rzbE7mDJcgNNvdtylCseQcPGCGghtJvVq3lB-OPJ49E,1049
121
121
  langroid/vector_store/__init__.py,sha256=8ktJUVsVUoc7FMmkUFpFBZu7VMWUqQY9zpm4kEJ8yTs,1537
@@ -127,7 +127,7 @@ langroid/vector_store/pineconedb.py,sha256=otxXZNaBKb9f_H75HTaU3lMHiaR2NUp5MqwLZ
127
127
  langroid/vector_store/postgres.py,sha256=wHPtIi2qM4fhO4pMQr95pz1ZCe7dTb2hxl4VYspGZoA,16104
128
128
  langroid/vector_store/qdrantdb.py,sha256=O6dSBoDZ0jzfeVBd7LLvsXu083xs2fxXtPa9gGX3JX4,18443
129
129
  langroid/vector_store/weaviatedb.py,sha256=Yn8pg139gOy3zkaPfoTbMXEEBCiLiYa1MU5d_3UA1K4,11847
130
- langroid-0.49.0.dist-info/METADATA,sha256=hheI5QVNzEyGlA-p2gJVGsgOuN1jP8piUAxXnv05CTg,63606
131
- langroid-0.49.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
132
- langroid-0.49.0.dist-info/licenses/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
133
- langroid-0.49.0.dist-info/RECORD,,
130
+ langroid-0.49.1.dist-info/METADATA,sha256=a2cArSN5YfRq4GRH37MkO6h-fvXbXEFkoo-qDMyVTzA,63606
131
+ langroid-0.49.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
132
+ langroid-0.49.1.dist-info/licenses/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
133
+ langroid-0.49.1.dist-info/RECORD,,