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.
- langroid/__init__.py +70 -0
- langroid/agent/__init__.py +22 -0
- langroid/agent/base.py +120 -33
- langroid/agent/batch.py +134 -35
- langroid/agent/callbacks/__init__.py +0 -0
- langroid/agent/callbacks/chainlit.py +608 -0
- langroid/agent/chat_agent.py +164 -100
- langroid/agent/chat_document.py +19 -2
- langroid/agent/openai_assistant.py +20 -10
- langroid/agent/special/__init__.py +33 -10
- langroid/agent/special/doc_chat_agent.py +521 -108
- langroid/agent/special/lance_doc_chat_agent.py +258 -0
- langroid/agent/special/lance_rag/__init__.py +9 -0
- langroid/agent/special/lance_rag/critic_agent.py +136 -0
- langroid/agent/special/lance_rag/lance_rag_task.py +80 -0
- langroid/agent/special/lance_rag/query_planner_agent.py +180 -0
- langroid/agent/special/lance_tools.py +44 -0
- langroid/agent/special/neo4j/__init__.py +0 -0
- langroid/agent/special/neo4j/csv_kg_chat.py +174 -0
- langroid/agent/special/neo4j/neo4j_chat_agent.py +370 -0
- langroid/agent/special/neo4j/utils/__init__.py +0 -0
- langroid/agent/special/neo4j/utils/system_message.py +46 -0
- langroid/agent/special/relevance_extractor_agent.py +23 -7
- langroid/agent/special/retriever_agent.py +29 -174
- langroid/agent/special/sql/__init__.py +7 -0
- langroid/agent/special/sql/sql_chat_agent.py +47 -23
- langroid/agent/special/sql/utils/__init__.py +11 -0
- langroid/agent/special/sql/utils/description_extractors.py +95 -46
- langroid/agent/special/sql/utils/populate_metadata.py +28 -21
- langroid/agent/special/table_chat_agent.py +43 -9
- langroid/agent/task.py +423 -114
- langroid/agent/tool_message.py +67 -10
- langroid/agent/tools/__init__.py +8 -0
- langroid/agent/tools/duckduckgo_search_tool.py +66 -0
- langroid/agent/tools/google_search_tool.py +11 -0
- langroid/agent/tools/metaphor_search_tool.py +67 -0
- langroid/agent/tools/recipient_tool.py +6 -24
- langroid/agent/tools/sciphi_search_rag_tool.py +79 -0
- langroid/cachedb/__init__.py +6 -0
- langroid/embedding_models/__init__.py +24 -0
- langroid/embedding_models/base.py +9 -1
- langroid/embedding_models/models.py +117 -17
- langroid/embedding_models/protoc/embeddings.proto +19 -0
- langroid/embedding_models/protoc/embeddings_pb2.py +33 -0
- langroid/embedding_models/protoc/embeddings_pb2.pyi +50 -0
- langroid/embedding_models/protoc/embeddings_pb2_grpc.py +79 -0
- langroid/embedding_models/remote_embeds.py +153 -0
- langroid/language_models/__init__.py +22 -0
- langroid/language_models/azure_openai.py +47 -4
- langroid/language_models/base.py +26 -10
- langroid/language_models/config.py +5 -0
- langroid/language_models/openai_gpt.py +407 -121
- langroid/language_models/prompt_formatter/__init__.py +9 -0
- langroid/language_models/prompt_formatter/base.py +4 -6
- langroid/language_models/prompt_formatter/hf_formatter.py +135 -0
- langroid/language_models/utils.py +10 -9
- langroid/mytypes.py +10 -4
- langroid/parsing/__init__.py +33 -1
- langroid/parsing/document_parser.py +259 -63
- langroid/parsing/image_text.py +32 -0
- langroid/parsing/parse_json.py +143 -0
- langroid/parsing/parser.py +20 -7
- langroid/parsing/repo_loader.py +108 -46
- langroid/parsing/search.py +8 -0
- langroid/parsing/table_loader.py +44 -0
- langroid/parsing/url_loader.py +59 -13
- langroid/parsing/urls.py +18 -9
- langroid/parsing/utils.py +130 -9
- langroid/parsing/web_search.py +73 -0
- langroid/prompts/__init__.py +7 -0
- langroid/prompts/chat-gpt4-system-prompt.md +68 -0
- langroid/prompts/prompts_config.py +1 -1
- langroid/utils/__init__.py +10 -0
- langroid/utils/algorithms/__init__.py +3 -0
- langroid/utils/configuration.py +0 -1
- langroid/utils/constants.py +4 -0
- langroid/utils/logging.py +2 -5
- langroid/utils/output/__init__.py +15 -2
- langroid/utils/output/status.py +33 -0
- langroid/utils/pandas_utils.py +30 -0
- langroid/utils/pydantic_utils.py +446 -4
- langroid/utils/system.py +36 -1
- langroid/vector_store/__init__.py +34 -2
- langroid/vector_store/base.py +33 -2
- langroid/vector_store/chromadb.py +42 -13
- langroid/vector_store/lancedb.py +226 -60
- langroid/vector_store/meilisearch.py +7 -6
- langroid/vector_store/momento.py +3 -2
- langroid/vector_store/qdrantdb.py +82 -11
- {langroid-0.1.139.dist-info → langroid-0.1.219.dist-info}/METADATA +190 -129
- langroid-0.1.219.dist-info/RECORD +127 -0
- langroid/agent/special/recipient_validator_agent.py +0 -157
- langroid/parsing/json.py +0 -64
- langroid/utils/web/selenium_login.py +0 -36
- langroid-0.1.139.dist-info/RECORD +0 -103
- {langroid-0.1.139.dist-info → langroid-0.1.219.dist-info}/LICENSE +0 -0
- {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
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
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
|
-
|
58
|
-
|
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
|
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,
|
49
|
-
If you receive an error message,
|
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().
|
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
|