langroid 0.1.139__py3-none-any.whl → 0.1.219__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.
Files changed (97) hide show
  1. langroid/__init__.py +70 -0
  2. langroid/agent/__init__.py +22 -0
  3. langroid/agent/base.py +120 -33
  4. langroid/agent/batch.py +134 -35
  5. langroid/agent/callbacks/__init__.py +0 -0
  6. langroid/agent/callbacks/chainlit.py +608 -0
  7. langroid/agent/chat_agent.py +164 -100
  8. langroid/agent/chat_document.py +19 -2
  9. langroid/agent/openai_assistant.py +20 -10
  10. langroid/agent/special/__init__.py +33 -10
  11. langroid/agent/special/doc_chat_agent.py +521 -108
  12. langroid/agent/special/lance_doc_chat_agent.py +258 -0
  13. langroid/agent/special/lance_rag/__init__.py +9 -0
  14. langroid/agent/special/lance_rag/critic_agent.py +136 -0
  15. langroid/agent/special/lance_rag/lance_rag_task.py +80 -0
  16. langroid/agent/special/lance_rag/query_planner_agent.py +180 -0
  17. langroid/agent/special/lance_tools.py +44 -0
  18. langroid/agent/special/neo4j/__init__.py +0 -0
  19. langroid/agent/special/neo4j/csv_kg_chat.py +174 -0
  20. langroid/agent/special/neo4j/neo4j_chat_agent.py +370 -0
  21. langroid/agent/special/neo4j/utils/__init__.py +0 -0
  22. langroid/agent/special/neo4j/utils/system_message.py +46 -0
  23. langroid/agent/special/relevance_extractor_agent.py +23 -7
  24. langroid/agent/special/retriever_agent.py +29 -174
  25. langroid/agent/special/sql/__init__.py +7 -0
  26. langroid/agent/special/sql/sql_chat_agent.py +47 -23
  27. langroid/agent/special/sql/utils/__init__.py +11 -0
  28. langroid/agent/special/sql/utils/description_extractors.py +95 -46
  29. langroid/agent/special/sql/utils/populate_metadata.py +28 -21
  30. langroid/agent/special/table_chat_agent.py +43 -9
  31. langroid/agent/task.py +423 -114
  32. langroid/agent/tool_message.py +67 -10
  33. langroid/agent/tools/__init__.py +8 -0
  34. langroid/agent/tools/duckduckgo_search_tool.py +66 -0
  35. langroid/agent/tools/google_search_tool.py +11 -0
  36. langroid/agent/tools/metaphor_search_tool.py +67 -0
  37. langroid/agent/tools/recipient_tool.py +6 -24
  38. langroid/agent/tools/sciphi_search_rag_tool.py +79 -0
  39. langroid/cachedb/__init__.py +6 -0
  40. langroid/embedding_models/__init__.py +24 -0
  41. langroid/embedding_models/base.py +9 -1
  42. langroid/embedding_models/models.py +117 -17
  43. langroid/embedding_models/protoc/embeddings.proto +19 -0
  44. langroid/embedding_models/protoc/embeddings_pb2.py +33 -0
  45. langroid/embedding_models/protoc/embeddings_pb2.pyi +50 -0
  46. langroid/embedding_models/protoc/embeddings_pb2_grpc.py +79 -0
  47. langroid/embedding_models/remote_embeds.py +153 -0
  48. langroid/language_models/__init__.py +22 -0
  49. langroid/language_models/azure_openai.py +47 -4
  50. langroid/language_models/base.py +26 -10
  51. langroid/language_models/config.py +5 -0
  52. langroid/language_models/openai_gpt.py +407 -121
  53. langroid/language_models/prompt_formatter/__init__.py +9 -0
  54. langroid/language_models/prompt_formatter/base.py +4 -6
  55. langroid/language_models/prompt_formatter/hf_formatter.py +135 -0
  56. langroid/language_models/utils.py +10 -9
  57. langroid/mytypes.py +10 -4
  58. langroid/parsing/__init__.py +33 -1
  59. langroid/parsing/document_parser.py +259 -63
  60. langroid/parsing/image_text.py +32 -0
  61. langroid/parsing/parse_json.py +143 -0
  62. langroid/parsing/parser.py +20 -7
  63. langroid/parsing/repo_loader.py +108 -46
  64. langroid/parsing/search.py +8 -0
  65. langroid/parsing/table_loader.py +44 -0
  66. langroid/parsing/url_loader.py +59 -13
  67. langroid/parsing/urls.py +18 -9
  68. langroid/parsing/utils.py +130 -9
  69. langroid/parsing/web_search.py +73 -0
  70. langroid/prompts/__init__.py +7 -0
  71. langroid/prompts/chat-gpt4-system-prompt.md +68 -0
  72. langroid/prompts/prompts_config.py +1 -1
  73. langroid/utils/__init__.py +10 -0
  74. langroid/utils/algorithms/__init__.py +3 -0
  75. langroid/utils/configuration.py +0 -1
  76. langroid/utils/constants.py +4 -0
  77. langroid/utils/logging.py +2 -5
  78. langroid/utils/output/__init__.py +15 -2
  79. langroid/utils/output/status.py +33 -0
  80. langroid/utils/pandas_utils.py +30 -0
  81. langroid/utils/pydantic_utils.py +446 -4
  82. langroid/utils/system.py +36 -1
  83. langroid/vector_store/__init__.py +34 -2
  84. langroid/vector_store/base.py +33 -2
  85. langroid/vector_store/chromadb.py +42 -13
  86. langroid/vector_store/lancedb.py +226 -60
  87. langroid/vector_store/meilisearch.py +7 -6
  88. langroid/vector_store/momento.py +3 -2
  89. langroid/vector_store/qdrantdb.py +82 -11
  90. {langroid-0.1.139.dist-info → langroid-0.1.219.dist-info}/METADATA +190 -129
  91. langroid-0.1.219.dist-info/RECORD +127 -0
  92. langroid/agent/special/recipient_validator_agent.py +0 -157
  93. langroid/parsing/json.py +0 -64
  94. langroid/utils/web/selenium_login.py +0 -36
  95. langroid-0.1.139.dist-info/RECORD +0 -103
  96. {langroid-0.1.139.dist-info → langroid-0.1.219.dist-info}/LICENSE +0 -0
  97. {langroid-0.1.139.dist-info → langroid-0.1.219.dist-info}/WHEEL +0 -0
@@ -1,10 +1,11 @@
1
- from typing import Dict, Union
1
+ from typing import Dict, List, Union
2
2
 
3
3
  from sqlalchemy import MetaData
4
4
 
5
5
 
6
6
  def populate_metadata_with_schema_tools(
7
- metadata: MetaData, info: Dict[str, Dict[str, Union[str, Dict[str, str]]]]
7
+ metadata: MetaData | List[MetaData],
8
+ info: Dict[str, Dict[str, Union[str, Dict[str, str]]]],
8
9
  ) -> Dict[str, Dict[str, Union[str, Dict[str, str]]]]:
9
10
  """
10
11
  Extracts information from an SQLAlchemy database's metadata and combines it
@@ -18,28 +19,35 @@ def populate_metadata_with_schema_tools(
18
19
  Returns:
19
20
  Dict[str, Dict[str, Any]]: A dictionary with table and context information.
20
21
  """
21
-
22
22
  db_info: Dict[str, Dict[str, Union[str, Dict[str, str]]]] = {}
23
23
 
24
- # Create empty metadata dictionary with column datatypes
25
- for table_name, table in metadata.tables.items():
26
- # Populate tables with empty descriptions
27
- db_info[str(table_name)] = {
28
- "description": info[table_name]["description"] or "",
29
- "columns": {},
30
- }
31
-
32
- for column in table.columns:
33
- # Populate columns with datatype
34
- db_info[str(table_name)]["columns"][str(column.name)] = ( # type: ignore
35
- str(column.type)
36
- )
24
+ def populate_metadata(md: MetaData) -> None:
25
+ # Create empty metadata dictionary with column datatypes
26
+ for table_name, table in md.tables.items():
27
+ # Populate tables with empty descriptions
28
+ db_info[table_name] = {
29
+ "description": info[table_name]["description"] or "",
30
+ "columns": {},
31
+ }
32
+
33
+ for column in table.columns:
34
+ # Populate columns with datatype
35
+ db_info[table_name]["columns"][str(column.name)] = ( # type: ignore
36
+ str(column.type)
37
+ )
38
+
39
+ if isinstance(metadata, list):
40
+ for md in metadata:
41
+ populate_metadata(md)
42
+ else:
43
+ populate_metadata(metadata)
37
44
 
38
45
  return db_info
39
46
 
40
47
 
41
48
  def populate_metadata(
42
- metadata: MetaData, info: Dict[str, Dict[str, Union[str, Dict[str, str]]]]
49
+ metadata: MetaData | List[MetaData],
50
+ info: Dict[str, Dict[str, Union[str, Dict[str, str]]]],
43
51
  ) -> Dict[str, Dict[str, Union[str, Dict[str, str]]]]:
44
52
  """
45
53
  Populate metadata based on the provided database metadata and additional info.
@@ -51,11 +59,10 @@ def populate_metadata(
51
59
  Returns:
52
60
  Dict: A dictionary containing populated metadata information.
53
61
  """
54
-
55
62
  # Fetch basic metadata info using available tools
56
- db_info: Dict[
57
- str, Dict[str, Union[str, Dict[str, str]]]
58
- ] = populate_metadata_with_schema_tools(metadata=metadata, info=info)
63
+ db_info: Dict[str, Dict[str, Union[str, Dict[str, str]]]] = (
64
+ populate_metadata_with_schema_tools(metadata=metadata, info=info)
65
+ )
59
66
 
60
67
  # Iterate over tables to update column metadata
61
68
  for table_name in db_info.keys():
@@ -7,33 +7,37 @@ code to answer the query. The code is passed via the `run_code` tool/function-ca
7
7
  which is handled by the Agent's `run_code` method. This method executes/evaluates
8
8
  the code and returns the result as a string.
9
9
  """
10
+
10
11
  import io
11
12
  import logging
12
13
  import sys
13
- from typing import List, no_type_check
14
+ from typing import List, Optional, no_type_check
14
15
 
15
16
  import numpy as np
16
17
  import pandas as pd
17
18
  from rich.console import Console
18
19
 
20
+ import langroid as lr
21
+ from langroid.agent import ChatDocument
19
22
  from langroid.agent.chat_agent import ChatAgent, ChatAgentConfig
20
23
  from langroid.agent.tool_message import ToolMessage
21
24
  from langroid.language_models.openai_gpt import OpenAIChatModel, OpenAIGPTConfig
22
25
  from langroid.parsing.table_loader import read_tabular_data
23
26
  from langroid.prompts.prompts_config import PromptsConfig
27
+ from langroid.utils.constants import DONE
24
28
  from langroid.vector_store.base import VectorStoreConfig
25
29
 
26
30
  logger = logging.getLogger(__name__)
27
31
 
28
32
  console = Console()
29
33
 
30
- DEFAULT_TABLE_CHAT_SYSTEM_MESSAGE = """
34
+ DEFAULT_TABLE_CHAT_SYSTEM_MESSAGE = f"""
31
35
  You are a savvy data scientist, with expertise in analyzing tabular datasets,
32
36
  using Python and the Pandas library for dataframe manipulation.
33
37
  Since you do not have access to the dataframe 'df', you
34
- will need to use the `run_code` tool/function-call to answer the question.
38
+ will need to use the `run_code` tool/function-call to answer my questions.
35
39
  Here is a summary of the dataframe:
36
- {summary}
40
+ {{summary}}
37
41
  Do not assume any columns other than those shown.
38
42
  In the code you submit to the `run_code` tool/function,
39
43
  do not forget to include any necessary imports, such as `import pandas as pd`.
@@ -45,10 +49,12 @@ If you receive a null or other unexpected result, see if you have made an assump
45
49
  in your code, and try another way, or use `run_code` to explore the dataframe
46
50
  before submitting your final code.
47
51
 
48
- Once you have the answer to the question, say DONE and show me the answer.
49
- If you receive an error message, try using the `run_code` tool/function
50
- again with the corrected code.
52
+ Once you have the answer to the question, possibly after a few steps,
53
+ say {DONE} and show me the answer. If you receive an error message,
54
+ try using the `run_code` tool/function again with the corrected code.
51
55
 
56
+ VERY IMPORTANT: When using the `run_code` tool/function, DO NOT EXPLAIN ANYTHING,
57
+ SIMPLY USE THE TOOL, with the CODE.
52
58
  Start by asking me what I want to know about the data.
53
59
  """
54
60
 
@@ -72,7 +78,7 @@ def dataframe_summary(df: pd.DataFrame) -> str:
72
78
  )
73
79
 
74
80
  # Numerical data summary
75
- num_summary = df.describe().applymap(lambda x: "{:.2f}".format(x))
81
+ num_summary = df.describe().map(lambda x: "{:.2f}".format(x))
76
82
  num_str = "Numerical Column Summary:\n" + num_summary.to_string() + "\n\n"
77
83
 
78
84
  # Categorical data summary
@@ -101,7 +107,6 @@ def dataframe_summary(df: pd.DataFrame) -> str:
101
107
  class TableChatAgentConfig(ChatAgentConfig):
102
108
  system_message: str = DEFAULT_TABLE_CHAT_SYSTEM_MESSAGE
103
109
  user_message: None | str = None
104
- max_context_tokens: int = 1000
105
110
  cache: bool = True # cache results
106
111
  debug: bool = False
107
112
  stream: bool = True # allow streaming where needed
@@ -125,6 +130,7 @@ class RunCodeTool(ToolMessage):
125
130
  purpose: str = """
126
131
  To run <code> on the dataframe 'df' and
127
132
  return the results to answer a question.
133
+ IMPORTANT: ALL the code should be in the <code> field.
128
134
  """
129
135
  code: str
130
136
 
@@ -141,6 +147,8 @@ class TableChatAgent(ChatAgent):
141
147
  Agent for chatting with a collection of documents.
142
148
  """
143
149
 
150
+ sent_code: bool = False
151
+
144
152
  def __init__(self, config: TableChatAgentConfig):
145
153
  if isinstance(config.data, pd.DataFrame):
146
154
  df = config.data
@@ -165,6 +173,15 @@ class TableChatAgent(ChatAgent):
165
173
  # enable the agent to use and handle the RunCodeTool
166
174
  self.enable_message(RunCodeTool)
167
175
 
176
+ def user_response(
177
+ self,
178
+ msg: Optional[str | ChatDocument] = None,
179
+ ) -> Optional[ChatDocument]:
180
+ response = super().user_response(msg)
181
+ if response is not None and response.content != "":
182
+ self.sent_code = False
183
+ return response
184
+
168
185
  def run_code(self, msg: RunCodeTool) -> str:
169
186
  """
170
187
  Handle a RunCodeTool message by running the code and returning the result.
@@ -174,6 +191,7 @@ class TableChatAgent(ChatAgent):
174
191
  Returns:
175
192
  str: The result of running the code along with any print output.
176
193
  """
194
+ self.sent_code = True
177
195
  code = msg.code
178
196
  # Create a dictionary that maps 'df' to the actual DataFrame
179
197
  local_vars = {"df": self.df}
@@ -220,3 +238,19 @@ class TableChatAgent(ChatAgent):
220
238
  result = "No result"
221
239
  # Return the result
222
240
  return result
241
+
242
+ def handle_message_fallback(
243
+ self, msg: str | ChatDocument
244
+ ) -> str | ChatDocument | None:
245
+ """Handle scenario where LLM forgets to say DONE or forgets to use run_code"""
246
+ if isinstance(msg, ChatDocument) and msg.metadata.sender == lr.Entity.LLM:
247
+ if self.sent_code:
248
+ return DONE
249
+ else:
250
+ return """
251
+ You forgot to use the `run_code` tool/function to find the answer.
252
+ Try again using the `run_code` tool/function.
253
+ Remember that ALL your code, including imports,
254
+ should be in the `code` field.
255
+ """
256
+ return None