llama-index-tools-database 0.0.1__tar.gz

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.
@@ -0,0 +1,53 @@
1
+ Metadata-Version: 2.1
2
+ Name: llama-index-tools-database
3
+ Version: 0.0.1
4
+ Summary: llama-index tools database integration
5
+ License: MIT
6
+ Author: Your Name
7
+ Author-email: you@example.com
8
+ Requires-Python: >=3.8.1,<3.12
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Requires-Dist: llama-index-core (>=0.9.32,<0.10.0)
15
+ Description-Content-Type: text/markdown
16
+
17
+ # Database Tool
18
+
19
+ This tool connects to a database (using SQLAlchemy under the hood) and allows an Agent to query the database and get information about the tables.
20
+
21
+ ## Usage
22
+
23
+ This tool has more extensive example usage documented in a Jupyter notebook [here](https://github.com/emptycrown/llama-hub/tree/main/llama_hub/tools/notebooks/database.ipynb) and [here](https://github.com/emptycrown/llama-hub/tree/main/llama_hub/tools/notebooks/intro_to_tools.ipynb)
24
+
25
+ Here's an example usage of the DatabaseToolSpec.
26
+
27
+ ```python
28
+ from llama_index.tools.database import DatabaseToolSpec
29
+ from llama_index.agent import OpenAIAgent
30
+
31
+ db_tools = DatabaseToolSpec(
32
+ scheme="postgresql", # Database Scheme
33
+ host="localhost", # Database Host
34
+ port="5432", # Database Port
35
+ user="postgres", # Database User
36
+ password="FakeExamplePassword", # Database Password
37
+ dbname="postgres", # Database Name
38
+ )
39
+ agent = OpenAIAgent.from_tools(db_tools.to_tool_list())
40
+
41
+ agent.chat("What tables does this database contain")
42
+ agent.chat("Describe the first table")
43
+ agent.chat("Retrieve the first row of that table")
44
+ ```
45
+
46
+ The tools available are:
47
+
48
+ `list_tables`: A tool to list the tables in the database schema
49
+ `describe_tables`: A tool to describe the schema of a table
50
+ `load_data`: A tool that accepts an SQL query and returns the result
51
+
52
+ This loader is designed to be used as a way to load data as a Tool in a Agent. See [here](https://github.com/emptycrown/llama-hub/tree/main) for examples.
53
+
@@ -0,0 +1,36 @@
1
+ # Database Tool
2
+
3
+ This tool connects to a database (using SQLAlchemy under the hood) and allows an Agent to query the database and get information about the tables.
4
+
5
+ ## Usage
6
+
7
+ This tool has more extensive example usage documented in a Jupyter notebook [here](https://github.com/emptycrown/llama-hub/tree/main/llama_hub/tools/notebooks/database.ipynb) and [here](https://github.com/emptycrown/llama-hub/tree/main/llama_hub/tools/notebooks/intro_to_tools.ipynb)
8
+
9
+ Here's an example usage of the DatabaseToolSpec.
10
+
11
+ ```python
12
+ from llama_index.tools.database import DatabaseToolSpec
13
+ from llama_index.agent import OpenAIAgent
14
+
15
+ db_tools = DatabaseToolSpec(
16
+ scheme="postgresql", # Database Scheme
17
+ host="localhost", # Database Host
18
+ port="5432", # Database Port
19
+ user="postgres", # Database User
20
+ password="FakeExamplePassword", # Database Password
21
+ dbname="postgres", # Database Name
22
+ )
23
+ agent = OpenAIAgent.from_tools(db_tools.to_tool_list())
24
+
25
+ agent.chat("What tables does this database contain")
26
+ agent.chat("Describe the first table")
27
+ agent.chat("Retrieve the first row of that table")
28
+ ```
29
+
30
+ The tools available are:
31
+
32
+ `list_tables`: A tool to list the tables in the database schema
33
+ `describe_tables`: A tool to describe the schema of a table
34
+ `load_data`: A tool that accepts an SQL query and returns the result
35
+
36
+ This loader is designed to be used as a way to load data as a Tool in a Agent. See [here](https://github.com/emptycrown/llama-hub/tree/main) for examples.
@@ -0,0 +1,6 @@
1
+ # __init__.py
2
+ from llama_index.tools.database.base import (
3
+ DatabaseToolSpec,
4
+ )
5
+
6
+ __all__ = ["DatabaseToolSpec"]
@@ -0,0 +1,135 @@
1
+ """Database Tool."""
2
+
3
+ from typing import Any, List, Optional
4
+
5
+ from llama_index.core.utilities.sql_wrapper import SQLDatabase
6
+ from llama_index.core.readers.base import BaseReader
7
+ from llama_index.core.schema import Document
8
+ from llama_index.core.tools.tool_spec.base import BaseToolSpec
9
+ from sqlalchemy import MetaData, text
10
+ from sqlalchemy.engine import Engine
11
+ from sqlalchemy.exc import NoSuchTableError
12
+ from sqlalchemy.schema import CreateTable
13
+
14
+
15
+ class DatabaseToolSpec(BaseToolSpec, BaseReader):
16
+ """Simple Database tool.
17
+
18
+ Concatenates each row into Document used by LlamaIndex.
19
+
20
+ Args:
21
+ sql_database (Optional[SQLDatabase]): SQL database to use,
22
+ including table names to specify.
23
+ See :ref:`Ref-Struct-Store` for more details.
24
+
25
+ OR
26
+
27
+ engine (Optional[Engine]): SQLAlchemy Engine object of the database connection.
28
+
29
+ OR
30
+
31
+ uri (Optional[str]): uri of the database connection.
32
+
33
+ OR
34
+
35
+ scheme (Optional[str]): scheme of the database connection.
36
+ host (Optional[str]): host of the database connection.
37
+ port (Optional[int]): port of the database connection.
38
+ user (Optional[str]): user of the database connection.
39
+ password (Optional[str]): password of the database connection.
40
+ dbname (Optional[str]): dbname of the database connection.
41
+
42
+ """
43
+
44
+ spec_functions = ["load_data", "describe_tables", "list_tables"]
45
+
46
+ def __init__(
47
+ self,
48
+ sql_database: Optional[SQLDatabase] = None,
49
+ engine: Optional[Engine] = None,
50
+ uri: Optional[str] = None,
51
+ scheme: Optional[str] = None,
52
+ host: Optional[str] = None,
53
+ port: Optional[str] = None,
54
+ user: Optional[str] = None,
55
+ password: Optional[str] = None,
56
+ dbname: Optional[str] = None,
57
+ *args: Optional[Any],
58
+ **kwargs: Optional[Any],
59
+ ) -> None:
60
+ """Initialize with parameters."""
61
+ if sql_database:
62
+ self.sql_database = sql_database
63
+ elif engine:
64
+ self.sql_database = SQLDatabase(engine, *args, **kwargs)
65
+ elif uri:
66
+ self.uri = uri
67
+ self.sql_database = SQLDatabase.from_uri(uri, *args, **kwargs)
68
+ elif scheme and host and port and user and password and dbname:
69
+ uri = f"{scheme}://{user}:{password}@{host}:{port}/{dbname}"
70
+ self.uri = uri
71
+ self.sql_database = SQLDatabase.from_uri(uri, *args, **kwargs)
72
+ else:
73
+ raise ValueError(
74
+ "You must provide either a SQLDatabase, "
75
+ "a SQL Alchemy Engine, a valid connection URI, or a valid "
76
+ "set of credentials."
77
+ )
78
+ self._metadata = MetaData()
79
+ self._metadata.reflect(bind=self.sql_database.engine)
80
+
81
+ def load_data(self, query: str) -> List[Document]:
82
+ """Query and load data from the Database, returning a list of Documents.
83
+
84
+ Args:
85
+ query (str): an SQL query to filter tables and rows.
86
+
87
+ Returns:
88
+ List[Document]: A list of Document objects.
89
+ """
90
+ documents = []
91
+ with self.sql_database.engine.connect() as connection:
92
+ if query is None:
93
+ raise ValueError("A query parameter is necessary to filter the data")
94
+ else:
95
+ result = connection.execute(text(query))
96
+
97
+ for item in result.fetchall():
98
+ # fetch each item
99
+ doc_str = ", ".join([str(entry) for entry in item])
100
+ documents.append(Document(text=doc_str))
101
+ return documents
102
+
103
+ def list_tables(self) -> List[str]:
104
+ """
105
+ Returns a list of available tables in the database.
106
+ To retrieve details about the columns of specfic tables, use
107
+ the describe_tables endpoint
108
+ """
109
+ return list(map(lambda x: x.name, self._metadata.sorted_tables))
110
+
111
+ def describe_tables(self, tables: Optional[List[str]] = None) -> str:
112
+ """
113
+ Describes the specifed tables in the database
114
+
115
+ Args:
116
+ tables (List[str]): A list of table names to retrieve details about
117
+ """
118
+ table_names = tables or [table.name for table in self._metadata.sorted_tables]
119
+ table_schemas = []
120
+
121
+ for table_name in table_names:
122
+ table = next(
123
+ (
124
+ table
125
+ for table in self._metadata.sorted_tables
126
+ if table.name == table_name
127
+ ),
128
+ None,
129
+ )
130
+ if table is None:
131
+ raise NoSuchTableError(f"Table '{table_name}' does not exist.")
132
+ schema = str(CreateTable(table).compile(self.sql_database._engine))
133
+ table_schemas.append(f"{schema}\n")
134
+
135
+ return "\n".join(table_schemas)
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["poetry-core"]
3
+ build-backend = "poetry.core.masonry.api"
4
+
5
+ [tool.codespell]
6
+ check-filenames = true
7
+ check-hidden = true
8
+ # Feel free to un-skip examples, and experimental, you will just need to
9
+ # work through many typos (--write-changes and --interactive will help)
10
+ skip = "*.csv,*.html,*.json,*.jsonl,*.pdf,*.txt,*.ipynb"
11
+
12
+ [tool.mypy]
13
+ disallow_untyped_defs = true
14
+ # Remove venv skip when integrated with pre-commit
15
+ exclude = ["_static", "build", "examples", "notebooks", "venv"]
16
+ ignore_missing_imports = true
17
+ python_version = "3.8"
18
+
19
+ [tool.poetry]
20
+ name = "llama-index-tools-database"
21
+ version = "0.0.1"
22
+ description = "llama-index tools database integration"
23
+ authors = ["Your Name <you@example.com>"]
24
+ license = "MIT"
25
+ readme = "README.md"
26
+ packages = [{include = "llama_index/"}]
27
+
28
+ [tool.poetry.dependencies]
29
+ python = ">=3.8.1,<3.12"
30
+ llama-index-core = "^0.9.32"
31
+
32
+ [tool.poetry.group.dev.dependencies]
33
+ black = {extras = ["jupyter"], version = "<=23.9.1,>=23.7.0"}
34
+ codespell = {extras = ["toml"], version = ">=v2.2.6"}
35
+ ipython = "8.10.0"
36
+ jupyter = "^1.0.0"
37
+ mypy = "0.991"
38
+ pre-commit = "3.2.0"
39
+ pylint = "2.15.10"
40
+ pytest = "7.2.1"
41
+ pytest-mock = "3.11.1"
42
+ ruff = "0.0.292"
43
+ tree-sitter-languages = "^1.8.0"
44
+ types-Deprecated = ">=0.1.0"
45
+ types-PyYAML = "^6.0.12.12"
46
+ types-protobuf = "^4.24.0.4"
47
+ types-redis = "4.5.5.0"
48
+ types-requests = "2.28.11.8" # TODO: unpin when mypy>0.991
49
+ types-setuptools = "67.1.0.0"