langroid 0.33.6__py3-none-any.whl → 0.33.8__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 +106 -0
- langroid/agent/__init__.py +41 -0
- langroid/agent/base.py +1983 -0
- langroid/agent/batch.py +398 -0
- langroid/agent/callbacks/__init__.py +0 -0
- langroid/agent/callbacks/chainlit.py +598 -0
- langroid/agent/chat_agent.py +1899 -0
- langroid/agent/chat_document.py +454 -0
- langroid/agent/openai_assistant.py +882 -0
- langroid/agent/special/__init__.py +59 -0
- langroid/agent/special/arangodb/__init__.py +0 -0
- langroid/agent/special/arangodb/arangodb_agent.py +656 -0
- langroid/agent/special/arangodb/system_messages.py +186 -0
- langroid/agent/special/arangodb/tools.py +107 -0
- langroid/agent/special/arangodb/utils.py +36 -0
- langroid/agent/special/doc_chat_agent.py +1466 -0
- langroid/agent/special/lance_doc_chat_agent.py +262 -0
- langroid/agent/special/lance_rag/__init__.py +9 -0
- langroid/agent/special/lance_rag/critic_agent.py +198 -0
- langroid/agent/special/lance_rag/lance_rag_task.py +82 -0
- langroid/agent/special/lance_rag/query_planner_agent.py +260 -0
- langroid/agent/special/lance_tools.py +61 -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 +433 -0
- langroid/agent/special/neo4j/system_messages.py +120 -0
- langroid/agent/special/neo4j/tools.py +32 -0
- langroid/agent/special/relevance_extractor_agent.py +127 -0
- langroid/agent/special/retriever_agent.py +56 -0
- langroid/agent/special/sql/__init__.py +17 -0
- langroid/agent/special/sql/sql_chat_agent.py +654 -0
- langroid/agent/special/sql/utils/__init__.py +21 -0
- langroid/agent/special/sql/utils/description_extractors.py +190 -0
- langroid/agent/special/sql/utils/populate_metadata.py +85 -0
- langroid/agent/special/sql/utils/system_message.py +35 -0
- langroid/agent/special/sql/utils/tools.py +64 -0
- langroid/agent/special/table_chat_agent.py +263 -0
- langroid/agent/task.py +2099 -0
- langroid/agent/tool_message.py +393 -0
- langroid/agent/tools/__init__.py +38 -0
- langroid/agent/tools/duckduckgo_search_tool.py +50 -0
- langroid/agent/tools/file_tools.py +234 -0
- langroid/agent/tools/google_search_tool.py +39 -0
- langroid/agent/tools/metaphor_search_tool.py +68 -0
- langroid/agent/tools/orchestration.py +303 -0
- langroid/agent/tools/recipient_tool.py +235 -0
- langroid/agent/tools/retrieval_tool.py +32 -0
- langroid/agent/tools/rewind_tool.py +137 -0
- langroid/agent/tools/segment_extract_tool.py +41 -0
- langroid/agent/xml_tool_message.py +382 -0
- langroid/cachedb/__init__.py +17 -0
- langroid/cachedb/base.py +58 -0
- langroid/cachedb/momento_cachedb.py +108 -0
- langroid/cachedb/redis_cachedb.py +153 -0
- langroid/embedding_models/__init__.py +39 -0
- langroid/embedding_models/base.py +74 -0
- langroid/embedding_models/models.py +461 -0
- langroid/embedding_models/protoc/__init__.py +0 -0
- 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/exceptions.py +71 -0
- langroid/language_models/__init__.py +53 -0
- langroid/language_models/azure_openai.py +153 -0
- langroid/language_models/base.py +678 -0
- langroid/language_models/config.py +18 -0
- langroid/language_models/mock_lm.py +124 -0
- langroid/language_models/openai_gpt.py +1964 -0
- langroid/language_models/prompt_formatter/__init__.py +16 -0
- langroid/language_models/prompt_formatter/base.py +40 -0
- langroid/language_models/prompt_formatter/hf_formatter.py +132 -0
- langroid/language_models/prompt_formatter/llama2_formatter.py +75 -0
- langroid/language_models/utils.py +151 -0
- langroid/mytypes.py +84 -0
- langroid/parsing/__init__.py +52 -0
- langroid/parsing/agent_chats.py +38 -0
- langroid/parsing/code_parser.py +121 -0
- langroid/parsing/document_parser.py +718 -0
- langroid/parsing/para_sentence_split.py +62 -0
- langroid/parsing/parse_json.py +155 -0
- langroid/parsing/parser.py +313 -0
- langroid/parsing/repo_loader.py +790 -0
- langroid/parsing/routing.py +36 -0
- langroid/parsing/search.py +275 -0
- langroid/parsing/spider.py +102 -0
- langroid/parsing/table_loader.py +94 -0
- langroid/parsing/url_loader.py +115 -0
- langroid/parsing/urls.py +273 -0
- langroid/parsing/utils.py +373 -0
- langroid/parsing/web_search.py +156 -0
- langroid/prompts/__init__.py +9 -0
- langroid/prompts/dialog.py +17 -0
- langroid/prompts/prompts_config.py +5 -0
- langroid/prompts/templates.py +141 -0
- langroid/pydantic_v1/__init__.py +10 -0
- langroid/pydantic_v1/main.py +4 -0
- langroid/utils/__init__.py +19 -0
- langroid/utils/algorithms/__init__.py +3 -0
- langroid/utils/algorithms/graph.py +103 -0
- langroid/utils/configuration.py +98 -0
- langroid/utils/constants.py +30 -0
- langroid/utils/git_utils.py +252 -0
- langroid/utils/globals.py +49 -0
- langroid/utils/logging.py +135 -0
- langroid/utils/object_registry.py +66 -0
- langroid/utils/output/__init__.py +20 -0
- langroid/utils/output/citations.py +41 -0
- langroid/utils/output/printing.py +99 -0
- langroid/utils/output/status.py +40 -0
- langroid/utils/pandas_utils.py +30 -0
- langroid/utils/pydantic_utils.py +602 -0
- langroid/utils/system.py +286 -0
- langroid/utils/types.py +93 -0
- langroid/vector_store/__init__.py +50 -0
- langroid/vector_store/base.py +359 -0
- langroid/vector_store/chromadb.py +214 -0
- langroid/vector_store/lancedb.py +406 -0
- langroid/vector_store/meilisearch.py +299 -0
- langroid/vector_store/momento.py +278 -0
- langroid/vector_store/qdrantdb.py +468 -0
- {langroid-0.33.6.dist-info → langroid-0.33.8.dist-info}/METADATA +95 -94
- langroid-0.33.8.dist-info/RECORD +127 -0
- {langroid-0.33.6.dist-info → langroid-0.33.8.dist-info}/WHEEL +1 -1
- langroid-0.33.6.dist-info/RECORD +0 -7
- langroid-0.33.6.dist-info/entry_points.txt +0 -4
- pyproject.toml +0 -356
- {langroid-0.33.6.dist-info → langroid-0.33.8.dist-info}/licenses/LICENSE +0 -0
langroid/utils/system.py
ADDED
@@ -0,0 +1,286 @@
|
|
1
|
+
import difflib
|
2
|
+
import getpass
|
3
|
+
import hashlib
|
4
|
+
import importlib
|
5
|
+
import importlib.metadata
|
6
|
+
import inspect
|
7
|
+
import logging
|
8
|
+
import shutil
|
9
|
+
import socket
|
10
|
+
import traceback
|
11
|
+
import uuid
|
12
|
+
from pathlib import Path
|
13
|
+
from typing import Any, Literal
|
14
|
+
|
15
|
+
logger = logging.getLogger(__name__)
|
16
|
+
|
17
|
+
DELETION_ALLOWED_PATHS = [
|
18
|
+
".qdrant",
|
19
|
+
".chroma",
|
20
|
+
".lancedb",
|
21
|
+
]
|
22
|
+
|
23
|
+
|
24
|
+
def pydantic_major_version() -> int:
|
25
|
+
try:
|
26
|
+
pydantic_version = importlib.metadata.version("pydantic")
|
27
|
+
major_version = int(pydantic_version.split(".")[0])
|
28
|
+
return major_version
|
29
|
+
except importlib.metadata.PackageNotFoundError:
|
30
|
+
return -1
|
31
|
+
|
32
|
+
|
33
|
+
class LazyLoad:
|
34
|
+
"""Lazy loading of modules or classes."""
|
35
|
+
|
36
|
+
def __init__(self, import_path: str) -> None:
|
37
|
+
self.import_path = import_path
|
38
|
+
self._target = None
|
39
|
+
self._is_target_loaded = False
|
40
|
+
|
41
|
+
def _load_target(self) -> None:
|
42
|
+
if not self._is_target_loaded:
|
43
|
+
try:
|
44
|
+
# Attempt to import as a module
|
45
|
+
self._target = importlib.import_module(self.import_path) # type: ignore
|
46
|
+
except ImportError:
|
47
|
+
# If module import fails, attempt to import as a
|
48
|
+
# class or function from a module
|
49
|
+
module_path, attr_name = self.import_path.rsplit(".", 1)
|
50
|
+
module = importlib.import_module(module_path)
|
51
|
+
self._target = getattr(module, attr_name)
|
52
|
+
self._is_target_loaded = True
|
53
|
+
|
54
|
+
def __getattr__(self, name: str) -> Any:
|
55
|
+
self._load_target()
|
56
|
+
return getattr(self._target, name)
|
57
|
+
|
58
|
+
def __call__(self, *args: Any, **kwargs: Any) -> Any:
|
59
|
+
self._load_target()
|
60
|
+
if callable(self._target):
|
61
|
+
return self._target(*args, **kwargs)
|
62
|
+
else:
|
63
|
+
raise TypeError(f"{self.import_path!r} object is not callable")
|
64
|
+
|
65
|
+
|
66
|
+
def rmdir(path: str) -> bool:
|
67
|
+
"""
|
68
|
+
Remove a directory recursively.
|
69
|
+
Args:
|
70
|
+
path (str): path to directory to remove
|
71
|
+
Returns:
|
72
|
+
True if a dir was removed, false otherwise. Raises error if failed to remove.
|
73
|
+
"""
|
74
|
+
if not any([path.startswith(p) for p in DELETION_ALLOWED_PATHS]):
|
75
|
+
raise ValueError(
|
76
|
+
f"""
|
77
|
+
Removing Dir '{path}' not allowed.
|
78
|
+
Must start with one of {DELETION_ALLOWED_PATHS}
|
79
|
+
This is a safety measure to prevent accidental deletion of files.
|
80
|
+
If you are sure you want to delete this directory, please add it
|
81
|
+
to the `DELETION_ALLOWED_PATHS` list in langroid/utils/system.py and
|
82
|
+
re-run the command.
|
83
|
+
"""
|
84
|
+
)
|
85
|
+
|
86
|
+
try:
|
87
|
+
shutil.rmtree(path)
|
88
|
+
except FileNotFoundError:
|
89
|
+
logger.warning(f"Directory '{path}' does not exist. No action taken.")
|
90
|
+
return False
|
91
|
+
except Exception as e:
|
92
|
+
logger.error(f"Error while removing directory '{path}': {e}")
|
93
|
+
return True
|
94
|
+
|
95
|
+
|
96
|
+
def caller_name() -> str:
|
97
|
+
"""
|
98
|
+
Who called the function?
|
99
|
+
"""
|
100
|
+
frame = inspect.currentframe()
|
101
|
+
if frame is None:
|
102
|
+
return ""
|
103
|
+
|
104
|
+
caller_frame = frame.f_back
|
105
|
+
|
106
|
+
# If there's no caller frame, the function was called from the global scope
|
107
|
+
if caller_frame is None:
|
108
|
+
return ""
|
109
|
+
|
110
|
+
return caller_frame.f_code.co_name
|
111
|
+
|
112
|
+
|
113
|
+
def friendly_error(e: Exception, msg: str = "An error occurred.") -> str:
|
114
|
+
tb = traceback.format_exc()
|
115
|
+
original_error_message: str = str(e)
|
116
|
+
full_error_message: str = (
|
117
|
+
f"{msg}\nOriginal error: {original_error_message}\nTraceback:\n{tb}"
|
118
|
+
)
|
119
|
+
return full_error_message
|
120
|
+
|
121
|
+
|
122
|
+
def generate_user_id(org: str = "") -> str:
|
123
|
+
"""
|
124
|
+
Generate a unique user ID based on the username and machine name.
|
125
|
+
Returns:
|
126
|
+
"""
|
127
|
+
# Get the username
|
128
|
+
username = getpass.getuser()
|
129
|
+
|
130
|
+
# Get the machine's name
|
131
|
+
machine_name = socket.gethostname()
|
132
|
+
|
133
|
+
org_pfx = f"{org}_" if org else ""
|
134
|
+
|
135
|
+
# Create a consistent unique ID based on the username and machine name
|
136
|
+
unique_string = f"{org_pfx}{username}@{machine_name}"
|
137
|
+
|
138
|
+
# Generate a SHA-256 hash of the unique string
|
139
|
+
user_id = hashlib.sha256(unique_string.encode()).hexdigest()
|
140
|
+
|
141
|
+
return user_id
|
142
|
+
|
143
|
+
|
144
|
+
def update_hash(hash: str | None = None, s: str = "") -> str:
|
145
|
+
"""
|
146
|
+
Takes a SHA256 hash string and a new string, updates the hash with the new string,
|
147
|
+
and returns the updated hash string.
|
148
|
+
|
149
|
+
Args:
|
150
|
+
hash (str): A SHA256 hash string.
|
151
|
+
s (str): A new string to update the hash with.
|
152
|
+
|
153
|
+
Returns:
|
154
|
+
The updated hash in hexadecimal format.
|
155
|
+
"""
|
156
|
+
# Create a new hash object if no hash is provided
|
157
|
+
if hash is None:
|
158
|
+
hash_obj = hashlib.sha256()
|
159
|
+
else:
|
160
|
+
# Convert the hexadecimal hash string to a byte object
|
161
|
+
hash_bytes = bytes.fromhex(hash)
|
162
|
+
hash_obj = hashlib.sha256(hash_bytes)
|
163
|
+
|
164
|
+
# Update the hash with the new string
|
165
|
+
hash_obj.update(s.encode("utf-8"))
|
166
|
+
|
167
|
+
# Return the updated hash in hexadecimal format and the original string
|
168
|
+
return hash_obj.hexdigest()
|
169
|
+
|
170
|
+
|
171
|
+
def hash(s: str) -> str:
|
172
|
+
"""
|
173
|
+
Generate a SHA256 hash of a string.
|
174
|
+
|
175
|
+
Args:
|
176
|
+
s (str): The string to hash.
|
177
|
+
|
178
|
+
Returns:
|
179
|
+
str: The SHA256 hash of the string.
|
180
|
+
"""
|
181
|
+
return update_hash(s=s)
|
182
|
+
|
183
|
+
|
184
|
+
def generate_unique_id() -> str:
|
185
|
+
"""Generate a unique ID using UUID4."""
|
186
|
+
return str(uuid.uuid4())
|
187
|
+
|
188
|
+
|
189
|
+
def create_file(
|
190
|
+
filepath: str | Path,
|
191
|
+
content: str = "",
|
192
|
+
if_exists: Literal["overwrite", "skip", "error", "append"] = "overwrite",
|
193
|
+
) -> None:
|
194
|
+
"""
|
195
|
+
Create, overwrite or append to a file, with the given content
|
196
|
+
at the specified filepath.
|
197
|
+
If content is empty, it will simply touch to create an empty file.
|
198
|
+
|
199
|
+
Args:
|
200
|
+
filepath (str|Path): The relative path of the file to be created
|
201
|
+
content (str): The content to be written to the file
|
202
|
+
if_exists (Literal["overwrite", "skip", "error", "append"]):
|
203
|
+
Action to take if file exists
|
204
|
+
"""
|
205
|
+
filepath = Path(filepath)
|
206
|
+
filepath.parent.mkdir(parents=True, exist_ok=True)
|
207
|
+
|
208
|
+
if filepath.exists():
|
209
|
+
if if_exists == "skip":
|
210
|
+
logger.warning(f"File already exists, skipping: {filepath}")
|
211
|
+
return
|
212
|
+
elif if_exists == "error":
|
213
|
+
raise FileExistsError(f"File already exists: {filepath}")
|
214
|
+
elif if_exists == "append":
|
215
|
+
mode = "a"
|
216
|
+
else: # overwrite
|
217
|
+
mode = "w"
|
218
|
+
else:
|
219
|
+
mode = "w"
|
220
|
+
|
221
|
+
if content == "" and mode in ["a", "w"]:
|
222
|
+
filepath.touch()
|
223
|
+
logger.warning(f"Empty file created: {filepath}")
|
224
|
+
else:
|
225
|
+
# the newline = '\n` argument is used to ensure that
|
226
|
+
# newlines in the content are written as actual line breaks
|
227
|
+
with open(filepath, mode, newline="\n") as f:
|
228
|
+
f.write(content)
|
229
|
+
action = "appended to" if mode == "a" else "created/updated in"
|
230
|
+
logger.warning(f"Content {action}: {filepath}")
|
231
|
+
|
232
|
+
|
233
|
+
def read_file(path: str, line_numbers: bool = False) -> str:
|
234
|
+
"""
|
235
|
+
Read the contents of a file.
|
236
|
+
|
237
|
+
Args:
|
238
|
+
path (str): The path to the file to be read.
|
239
|
+
line_numbers (bool, optional): If True, prepend line numbers to each line.
|
240
|
+
Defaults to False.
|
241
|
+
|
242
|
+
Returns:
|
243
|
+
str: The contents of the file, optionally with line numbers.
|
244
|
+
|
245
|
+
Raises:
|
246
|
+
FileNotFoundError: If the specified file does not exist.
|
247
|
+
"""
|
248
|
+
# raise an error if the file does not exist
|
249
|
+
if not Path(path).exists():
|
250
|
+
raise FileNotFoundError(f"File not found: {path}")
|
251
|
+
file = Path(path).expanduser()
|
252
|
+
content = file.read_text()
|
253
|
+
if line_numbers:
|
254
|
+
lines = content.splitlines()
|
255
|
+
numbered_lines = [f"{i+1}: {line}" for i, line in enumerate(lines)]
|
256
|
+
return "\n".join(numbered_lines)
|
257
|
+
return content
|
258
|
+
|
259
|
+
|
260
|
+
def diff_files(file1: str, file2: str) -> str:
|
261
|
+
"""
|
262
|
+
Find the diffs between two files, in unified diff format.
|
263
|
+
"""
|
264
|
+
with open(file1, "r") as f1, open(file2, "r") as f2:
|
265
|
+
lines1 = f1.readlines()
|
266
|
+
lines2 = f2.readlines()
|
267
|
+
|
268
|
+
differ = difflib.unified_diff(lines1, lines2, fromfile=file1, tofile=file2)
|
269
|
+
diff_result = "".join(differ)
|
270
|
+
return diff_result
|
271
|
+
|
272
|
+
|
273
|
+
def list_dir(path: str | Path) -> list[str]:
|
274
|
+
"""
|
275
|
+
List the contents of a directory.
|
276
|
+
|
277
|
+
Args:
|
278
|
+
path (str): The path to the directory.
|
279
|
+
|
280
|
+
Returns:
|
281
|
+
list[str]: A list of the files and directories in the specified directory.
|
282
|
+
"""
|
283
|
+
dir_path = Path(path)
|
284
|
+
if not dir_path.is_dir():
|
285
|
+
raise NotADirectoryError(f"Path is not a directory: {dir_path}")
|
286
|
+
return [str(p) for p in dir_path.iterdir()]
|
langroid/utils/types.py
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
import json
|
2
|
+
import logging
|
3
|
+
from typing import Any, Optional, Type, TypeVar, Union, get_args, get_origin
|
4
|
+
|
5
|
+
from langroid.pydantic_v1 import BaseModel
|
6
|
+
|
7
|
+
logger = logging.getLogger(__name__)
|
8
|
+
PrimitiveType = Union[int, float, bool, str]
|
9
|
+
T = TypeVar("T")
|
10
|
+
|
11
|
+
|
12
|
+
def is_instance_of(obj: Any, type_hint: Type[T] | Any) -> bool:
|
13
|
+
"""
|
14
|
+
Check if an object is an instance of a type hint, e.g.
|
15
|
+
to check whether x is of type `List[ToolMessage]` or type `int`
|
16
|
+
"""
|
17
|
+
if type_hint == Any:
|
18
|
+
return True
|
19
|
+
|
20
|
+
if type_hint is type(obj):
|
21
|
+
return True
|
22
|
+
|
23
|
+
origin = get_origin(type_hint)
|
24
|
+
args = get_args(type_hint)
|
25
|
+
|
26
|
+
if origin is Union:
|
27
|
+
return any(is_instance_of(obj, arg) for arg in args)
|
28
|
+
|
29
|
+
if origin: # e.g. List, Dict, Tuple, Set
|
30
|
+
if isinstance(obj, origin):
|
31
|
+
# check if all items in obj are of the required types
|
32
|
+
if args:
|
33
|
+
if isinstance(obj, (list, tuple, set)):
|
34
|
+
return all(is_instance_of(item, args[0]) for item in obj)
|
35
|
+
if isinstance(obj, dict):
|
36
|
+
return all(
|
37
|
+
is_instance_of(k, args[0]) and is_instance_of(v, args[1])
|
38
|
+
for k, v in obj.items()
|
39
|
+
)
|
40
|
+
return True
|
41
|
+
else:
|
42
|
+
return False
|
43
|
+
|
44
|
+
return isinstance(obj, type_hint)
|
45
|
+
|
46
|
+
|
47
|
+
def to_string(msg: Any) -> str:
|
48
|
+
"""
|
49
|
+
Best-effort conversion of arbitrary msg to str.
|
50
|
+
Return empty string if conversion fails.
|
51
|
+
"""
|
52
|
+
if msg is None:
|
53
|
+
return ""
|
54
|
+
if isinstance(msg, str):
|
55
|
+
return msg
|
56
|
+
if isinstance(msg, BaseModel):
|
57
|
+
return msg.json()
|
58
|
+
# last resort: use json.dumps() or str() to make it a str
|
59
|
+
try:
|
60
|
+
return json.dumps(msg)
|
61
|
+
except Exception:
|
62
|
+
try:
|
63
|
+
return str(msg)
|
64
|
+
except Exception as e:
|
65
|
+
logger.error(
|
66
|
+
f"""
|
67
|
+
Error converting msg to str: {e}",
|
68
|
+
""",
|
69
|
+
exc_info=True,
|
70
|
+
)
|
71
|
+
return ""
|
72
|
+
|
73
|
+
|
74
|
+
def from_string(
|
75
|
+
s: str,
|
76
|
+
output_type: Type[PrimitiveType],
|
77
|
+
) -> Optional[PrimitiveType]:
|
78
|
+
if output_type is int:
|
79
|
+
try:
|
80
|
+
return int(s)
|
81
|
+
except ValueError:
|
82
|
+
return None
|
83
|
+
elif output_type is float:
|
84
|
+
try:
|
85
|
+
return float(s)
|
86
|
+
except ValueError:
|
87
|
+
return None
|
88
|
+
elif output_type is bool:
|
89
|
+
return s.lower() in ("true", "yes", "1")
|
90
|
+
elif output_type is str:
|
91
|
+
return s
|
92
|
+
else:
|
93
|
+
return None
|
@@ -0,0 +1,50 @@
|
|
1
|
+
from . import base
|
2
|
+
|
3
|
+
from . import qdrantdb
|
4
|
+
|
5
|
+
from .base import VectorStoreConfig, VectorStore
|
6
|
+
from .qdrantdb import QdrantDBConfig, QdrantDB
|
7
|
+
|
8
|
+
__all__ = [
|
9
|
+
"base",
|
10
|
+
"VectorStore",
|
11
|
+
"VectorStoreConfig",
|
12
|
+
"qdrantdb",
|
13
|
+
"QdrantDBConfig",
|
14
|
+
"QdrantDB",
|
15
|
+
]
|
16
|
+
|
17
|
+
|
18
|
+
try:
|
19
|
+
from . import meilisearch
|
20
|
+
from .meilisearch import MeiliSearch, MeiliSearchConfig
|
21
|
+
|
22
|
+
meilisearch
|
23
|
+
MeiliSearch
|
24
|
+
MeiliSearchConfig
|
25
|
+
__all__.extend(["meilisearch", "MeiliSearch", "MeiliSearchConfig"])
|
26
|
+
except ImportError:
|
27
|
+
pass
|
28
|
+
|
29
|
+
|
30
|
+
try:
|
31
|
+
from . import lancedb
|
32
|
+
from .lancedb import LanceDB, LanceDBConfig
|
33
|
+
|
34
|
+
lancedb
|
35
|
+
LanceDB
|
36
|
+
LanceDBConfig
|
37
|
+
__all__.extend(["lancedb", "LanceDB", "LanceDBConfig"])
|
38
|
+
except ImportError:
|
39
|
+
pass
|
40
|
+
|
41
|
+
try:
|
42
|
+
from . import chromadb
|
43
|
+
from .chromadb import ChromaDBConfig, ChromaDB
|
44
|
+
|
45
|
+
chromadb # silence linters
|
46
|
+
ChromaDB
|
47
|
+
ChromaDBConfig
|
48
|
+
__all__.extend(["chromadb", "ChromaDBConfig", "ChromaDB"])
|
49
|
+
except ImportError:
|
50
|
+
pass
|