asksql 2.1.0__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.
- asksql-2.1.0.dist-info/METADATA +517 -0
- asksql-2.1.0.dist-info/RECORD +291 -0
- asksql-2.1.0.dist-info/WHEEL +4 -0
- asksql-2.1.0.dist-info/entry_points.txt +4 -0
- asksql-2.1.0.dist-info/licenses/LICENSE +21 -0
- vanna/__init__.py +172 -0
- vanna/agents/__init__.py +7 -0
- vanna/capabilities/__init__.py +17 -0
- vanna/capabilities/agent_memory/__init__.py +21 -0
- vanna/capabilities/agent_memory/base.py +103 -0
- vanna/capabilities/agent_memory/models.py +53 -0
- vanna/capabilities/file_system/__init__.py +14 -0
- vanna/capabilities/file_system/base.py +71 -0
- vanna/capabilities/file_system/models.py +25 -0
- vanna/capabilities/sql_runner/__init__.py +13 -0
- vanna/capabilities/sql_runner/base.py +37 -0
- vanna/capabilities/sql_runner/models.py +13 -0
- vanna/components/__init__.py +92 -0
- vanna/components/base.py +11 -0
- vanna/components/rich/__init__.py +83 -0
- vanna/components/rich/containers/__init__.py +7 -0
- vanna/components/rich/containers/card.py +20 -0
- vanna/components/rich/data/__init__.py +9 -0
- vanna/components/rich/data/chart.py +17 -0
- vanna/components/rich/data/dataframe.py +93 -0
- vanna/components/rich/feedback/__init__.py +21 -0
- vanna/components/rich/feedback/badge.py +16 -0
- vanna/components/rich/feedback/icon_text.py +14 -0
- vanna/components/rich/feedback/log_viewer.py +41 -0
- vanna/components/rich/feedback/notification.py +19 -0
- vanna/components/rich/feedback/progress.py +37 -0
- vanna/components/rich/feedback/status_card.py +28 -0
- vanna/components/rich/feedback/status_indicator.py +14 -0
- vanna/components/rich/interactive/__init__.py +21 -0
- vanna/components/rich/interactive/button.py +95 -0
- vanna/components/rich/interactive/task_list.py +58 -0
- vanna/components/rich/interactive/ui_state.py +93 -0
- vanna/components/rich/specialized/__init__.py +7 -0
- vanna/components/rich/specialized/artifact.py +20 -0
- vanna/components/rich/text.py +16 -0
- vanna/components/simple/__init__.py +15 -0
- vanna/components/simple/image.py +15 -0
- vanna/components/simple/link.py +15 -0
- vanna/components/simple/text.py +11 -0
- vanna/core/__init__.py +193 -0
- vanna/core/_compat.py +19 -0
- vanna/core/agent/__init__.py +10 -0
- vanna/core/agent/agent.py +1407 -0
- vanna/core/agent/config.py +123 -0
- vanna/core/audit/__init__.py +28 -0
- vanna/core/audit/base.py +299 -0
- vanna/core/audit/models.py +131 -0
- vanna/core/component_manager.py +329 -0
- vanna/core/components.py +53 -0
- vanna/core/enhancer/__init__.py +11 -0
- vanna/core/enhancer/base.py +94 -0
- vanna/core/enhancer/default.py +118 -0
- vanna/core/enricher/__init__.py +10 -0
- vanna/core/enricher/base.py +59 -0
- vanna/core/errors.py +47 -0
- vanna/core/evaluation/__init__.py +81 -0
- vanna/core/evaluation/base.py +186 -0
- vanna/core/evaluation/dataset.py +254 -0
- vanna/core/evaluation/evaluators.py +376 -0
- vanna/core/evaluation/report.py +289 -0
- vanna/core/evaluation/runner.py +313 -0
- vanna/core/filter/__init__.py +10 -0
- vanna/core/filter/base.py +67 -0
- vanna/core/lifecycle/__init__.py +10 -0
- vanna/core/lifecycle/base.py +83 -0
- vanna/core/llm/__init__.py +16 -0
- vanna/core/llm/base.py +40 -0
- vanna/core/llm/models.py +61 -0
- vanna/core/middleware/__init__.py +10 -0
- vanna/core/middleware/base.py +69 -0
- vanna/core/observability/__init__.py +11 -0
- vanna/core/observability/base.py +88 -0
- vanna/core/observability/models.py +47 -0
- vanna/core/recovery/__init__.py +11 -0
- vanna/core/recovery/base.py +84 -0
- vanna/core/recovery/models.py +32 -0
- vanna/core/registry.py +278 -0
- vanna/core/rich_component.py +156 -0
- vanna/core/simple_component.py +27 -0
- vanna/core/storage/__init__.py +14 -0
- vanna/core/storage/base.py +46 -0
- vanna/core/storage/models.py +46 -0
- vanna/core/system_prompt/__init__.py +13 -0
- vanna/core/system_prompt/base.py +36 -0
- vanna/core/system_prompt/default.py +157 -0
- vanna/core/tool/__init__.py +18 -0
- vanna/core/tool/base.py +70 -0
- vanna/core/tool/models.py +84 -0
- vanna/core/user/__init__.py +17 -0
- vanna/core/user/base.py +29 -0
- vanna/core/user/models.py +25 -0
- vanna/core/user/request_context.py +70 -0
- vanna/core/user/resolver.py +42 -0
- vanna/core/validation.py +164 -0
- vanna/core/workflow/__init__.py +12 -0
- vanna/core/workflow/base.py +254 -0
- vanna/core/workflow/default.py +789 -0
- vanna/examples/__init__.py +1 -0
- vanna/examples/__main__.py +44 -0
- vanna/examples/anthropic_quickstart.py +80 -0
- vanna/examples/artifact_example.py +293 -0
- vanna/examples/claude_sqlite_example.py +236 -0
- vanna/examples/coding_agent_example.py +300 -0
- vanna/examples/custom_system_prompt_example.py +174 -0
- vanna/examples/default_workflow_handler_example.py +208 -0
- vanna/examples/email_auth_example.py +340 -0
- vanna/examples/evaluation_example.py +269 -0
- vanna/examples/extensibility_example.py +262 -0
- vanna/examples/minimal_example.py +67 -0
- vanna/examples/mock_auth_example.py +227 -0
- vanna/examples/mock_custom_tool.py +311 -0
- vanna/examples/mock_quickstart.py +79 -0
- vanna/examples/mock_quota_example.py +145 -0
- vanna/examples/mock_rich_components_demo.py +396 -0
- vanna/examples/mock_sqlite_example.py +223 -0
- vanna/examples/openai_quickstart.py +83 -0
- vanna/examples/primitive_components_demo.py +305 -0
- vanna/examples/quota_lifecycle_example.py +139 -0
- vanna/examples/visualization_example.py +251 -0
- vanna/integrations/__init__.py +17 -0
- vanna/integrations/anthropic/__init__.py +9 -0
- vanna/integrations/anthropic/llm.py +270 -0
- vanna/integrations/azureopenai/__init__.py +9 -0
- vanna/integrations/azureopenai/llm.py +329 -0
- vanna/integrations/azuresearch/__init__.py +7 -0
- vanna/integrations/azuresearch/agent_memory.py +413 -0
- vanna/integrations/bigquery/__init__.py +5 -0
- vanna/integrations/bigquery/sql_runner.py +81 -0
- vanna/integrations/chromadb/__init__.py +104 -0
- vanna/integrations/chromadb/agent_memory.py +488 -0
- vanna/integrations/clickhouse/__init__.py +5 -0
- vanna/integrations/clickhouse/sql_runner.py +82 -0
- vanna/integrations/duckdb/__init__.py +5 -0
- vanna/integrations/duckdb/sql_runner.py +65 -0
- vanna/integrations/faiss/__init__.py +7 -0
- vanna/integrations/faiss/agent_memory.py +435 -0
- vanna/integrations/google/__init__.py +9 -0
- vanna/integrations/google/gemini.py +370 -0
- vanna/integrations/hive/__init__.py +5 -0
- vanna/integrations/hive/sql_runner.py +87 -0
- vanna/integrations/local/__init__.py +17 -0
- vanna/integrations/local/agent_memory/__init__.py +7 -0
- vanna/integrations/local/agent_memory/in_memory.py +285 -0
- vanna/integrations/local/audit.py +59 -0
- vanna/integrations/local/file_system.py +242 -0
- vanna/integrations/local/file_system_conversation_store.py +255 -0
- vanna/integrations/local/storage.py +62 -0
- vanna/integrations/marqo/__init__.py +7 -0
- vanna/integrations/marqo/agent_memory.py +354 -0
- vanna/integrations/milvus/__init__.py +7 -0
- vanna/integrations/milvus/agent_memory.py +458 -0
- vanna/integrations/mock/__init__.py +9 -0
- vanna/integrations/mock/llm.py +65 -0
- vanna/integrations/mssql/__init__.py +5 -0
- vanna/integrations/mssql/sql_runner.py +66 -0
- vanna/integrations/mysql/__init__.py +5 -0
- vanna/integrations/mysql/sql_runner.py +92 -0
- vanna/integrations/ollama/__init__.py +7 -0
- vanna/integrations/ollama/llm.py +252 -0
- vanna/integrations/openai/__init__.py +10 -0
- vanna/integrations/openai/llm.py +267 -0
- vanna/integrations/openai/responses.py +163 -0
- vanna/integrations/opensearch/__init__.py +7 -0
- vanna/integrations/opensearch/agent_memory.py +411 -0
- vanna/integrations/oracle/__init__.py +5 -0
- vanna/integrations/oracle/sql_runner.py +75 -0
- vanna/integrations/pinecone/__init__.py +7 -0
- vanna/integrations/pinecone/agent_memory.py +329 -0
- vanna/integrations/plotly/__init__.py +5 -0
- vanna/integrations/plotly/chart_generator.py +313 -0
- vanna/integrations/postgres/__init__.py +9 -0
- vanna/integrations/postgres/sql_runner.py +112 -0
- vanna/integrations/premium/agent_memory/__init__.py +7 -0
- vanna/integrations/premium/agent_memory/premium.py +186 -0
- vanna/integrations/presto/__init__.py +5 -0
- vanna/integrations/presto/sql_runner.py +107 -0
- vanna/integrations/qdrant/__init__.py +7 -0
- vanna/integrations/qdrant/agent_memory.py +466 -0
- vanna/integrations/snowflake/__init__.py +5 -0
- vanna/integrations/snowflake/sql_runner.py +147 -0
- vanna/integrations/sqlite/__init__.py +9 -0
- vanna/integrations/sqlite/sql_runner.py +65 -0
- vanna/integrations/weaviate/__init__.py +7 -0
- vanna/integrations/weaviate/agent_memory.py +428 -0
- vanna/legacy/ZhipuAI/ZhipuAI_Chat.py +233 -0
- vanna/legacy/ZhipuAI/ZhipuAI_embeddings.py +79 -0
- vanna/legacy/ZhipuAI/__init__.py +2 -0
- vanna/legacy/__init__.py +403 -0
- vanna/legacy/adapter.py +468 -0
- vanna/legacy/advanced/__init__.py +28 -0
- vanna/legacy/anthropic/__init__.py +1 -0
- vanna/legacy/anthropic/anthropic_chat.py +80 -0
- vanna/legacy/azuresearch/__init__.py +1 -0
- vanna/legacy/azuresearch/azuresearch_vector.py +274 -0
- vanna/legacy/base/__init__.py +1 -0
- vanna/legacy/base/base.py +2133 -0
- vanna/legacy/base/safe_exec.py +190 -0
- vanna/legacy/bedrock/__init__.py +1 -0
- vanna/legacy/bedrock/bedrock_converse.py +86 -0
- vanna/legacy/chromadb/__init__.py +1 -0
- vanna/legacy/chromadb/chromadb_vector.py +259 -0
- vanna/legacy/cohere/__init__.py +2 -0
- vanna/legacy/cohere/cohere_chat.py +99 -0
- vanna/legacy/cohere/cohere_embeddings.py +77 -0
- vanna/legacy/deepseek/__init__.py +1 -0
- vanna/legacy/deepseek/deepseek_chat.py +59 -0
- vanna/legacy/exceptions/__init__.py +46 -0
- vanna/legacy/faiss/__init__.py +1 -0
- vanna/legacy/faiss/faiss.py +230 -0
- vanna/legacy/flask/__init__.py +1355 -0
- vanna/legacy/flask/assets.py +58 -0
- vanna/legacy/flask/auth.py +56 -0
- vanna/legacy/google/__init__.py +2 -0
- vanna/legacy/google/bigquery_vector.py +293 -0
- vanna/legacy/google/gemini_chat.py +78 -0
- vanna/legacy/hf/__init__.py +1 -0
- vanna/legacy/hf/hf.py +80 -0
- vanna/legacy/local.py +8 -0
- vanna/legacy/marqo/__init__.py +1 -0
- vanna/legacy/marqo/marqo.py +168 -0
- vanna/legacy/milvus/__init__.py +1 -0
- vanna/legacy/milvus/milvus_vector.py +328 -0
- vanna/legacy/mistral/__init__.py +1 -0
- vanna/legacy/mistral/mistral.py +51 -0
- vanna/legacy/mock/__init__.py +3 -0
- vanna/legacy/mock/embedding.py +11 -0
- vanna/legacy/mock/llm.py +18 -0
- vanna/legacy/mock/vectordb.py +67 -0
- vanna/legacy/ollama/__init__.py +1 -0
- vanna/legacy/ollama/ollama.py +110 -0
- vanna/legacy/openai/__init__.py +2 -0
- vanna/legacy/openai/openai_chat.py +124 -0
- vanna/legacy/openai/openai_embeddings.py +46 -0
- vanna/legacy/opensearch/__init__.py +2 -0
- vanna/legacy/opensearch/opensearch_vector.py +369 -0
- vanna/legacy/opensearch/opensearch_vector_semantic.py +200 -0
- vanna/legacy/oracle/__init__.py +1 -0
- vanna/legacy/oracle/oracle_vector.py +584 -0
- vanna/legacy/pgvector/__init__.py +1 -0
- vanna/legacy/pgvector/pgvector.py +282 -0
- vanna/legacy/pinecone/__init__.py +3 -0
- vanna/legacy/pinecone/pinecone_vector.py +275 -0
- vanna/legacy/qdrant/__init__.py +3 -0
- vanna/legacy/qdrant/qdrant.py +329 -0
- vanna/legacy/qianfan/Qianfan_Chat.py +170 -0
- vanna/legacy/qianfan/Qianfan_embeddings.py +36 -0
- vanna/legacy/qianfan/__init__.py +2 -0
- vanna/legacy/qianwen/QianwenAI_chat.py +132 -0
- vanna/legacy/qianwen/QianwenAI_embeddings.py +46 -0
- vanna/legacy/qianwen/__init__.py +2 -0
- vanna/legacy/remote.py +79 -0
- vanna/legacy/types/__init__.py +292 -0
- vanna/legacy/utils.py +72 -0
- vanna/legacy/vannadb/__init__.py +1 -0
- vanna/legacy/vannadb/vannadb_vector.py +468 -0
- vanna/legacy/vllm/__init__.py +1 -0
- vanna/legacy/vllm/vllm.py +97 -0
- vanna/legacy/weaviate/__init__.py +1 -0
- vanna/legacy/weaviate/weaviate_vector.py +194 -0
- vanna/legacy/xinference/__init__.py +1 -0
- vanna/legacy/xinference/xinference.py +53 -0
- vanna/py.typed +0 -0
- vanna/servers/__init__.py +16 -0
- vanna/servers/__main__.py +8 -0
- vanna/servers/base/__init__.py +18 -0
- vanna/servers/base/chat_handler.py +65 -0
- vanna/servers/base/models.py +111 -0
- vanna/servers/base/rich_chat_handler.py +141 -0
- vanna/servers/base/templates.py +331 -0
- vanna/servers/cli/__init__.py +7 -0
- vanna/servers/cli/server_runner.py +204 -0
- vanna/servers/fastapi/__init__.py +7 -0
- vanna/servers/fastapi/app.py +163 -0
- vanna/servers/fastapi/routes.py +183 -0
- vanna/servers/flask/__init__.py +7 -0
- vanna/servers/flask/app.py +132 -0
- vanna/servers/flask/routes.py +137 -0
- vanna/tools/__init__.py +41 -0
- vanna/tools/agent_memory.py +322 -0
- vanna/tools/file_system.py +879 -0
- vanna/tools/python.py +222 -0
- vanna/tools/run_sql.py +173 -0
- vanna/tools/visualize_data.py +195 -0
- vanna/utils/__init__.py +0 -0
- vanna/utils/sql_safety.py +84 -0
- vanna/web_components/__init__.py +44 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from openai import OpenAI
|
|
4
|
+
|
|
5
|
+
from ..base import VannaBase
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Cohere_Embeddings(VannaBase):
|
|
9
|
+
def __init__(self, client=None, config=None):
|
|
10
|
+
VannaBase.__init__(self, config=config)
|
|
11
|
+
|
|
12
|
+
# Default embedding model
|
|
13
|
+
self.model = "embed-multilingual-v3.0"
|
|
14
|
+
|
|
15
|
+
if config is not None and "model" in config:
|
|
16
|
+
self.model = config["model"]
|
|
17
|
+
|
|
18
|
+
if client is not None:
|
|
19
|
+
self.client = client
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
# Check for API key in environment variable
|
|
23
|
+
api_key = os.getenv("COHERE_API_KEY")
|
|
24
|
+
|
|
25
|
+
# Check for API key in config
|
|
26
|
+
if config is not None and "api_key" in config:
|
|
27
|
+
api_key = config["api_key"]
|
|
28
|
+
|
|
29
|
+
# Validate API key
|
|
30
|
+
if not api_key:
|
|
31
|
+
raise ValueError(
|
|
32
|
+
"Cohere API key is required. Please provide it via config or set the COHERE_API_KEY environment variable."
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Initialize client with validated API key
|
|
36
|
+
self.client = OpenAI(
|
|
37
|
+
base_url="https://api.cohere.ai/compatibility/v1",
|
|
38
|
+
api_key=api_key,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def generate_embedding(self, data: str, **kwargs) -> list[float]:
|
|
42
|
+
if not data:
|
|
43
|
+
raise ValueError("Cannot generate embedding for empty input data")
|
|
44
|
+
|
|
45
|
+
# Use model from kwargs, config, or default
|
|
46
|
+
model = kwargs.get("model", self.model)
|
|
47
|
+
if self.config is not None and "model" in self.config and model == self.model:
|
|
48
|
+
model = self.config["model"]
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
embedding = self.client.embeddings.create(
|
|
52
|
+
model=model,
|
|
53
|
+
input=data,
|
|
54
|
+
encoding_format="float", # Ensure we get float values
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Check if response has expected structure
|
|
58
|
+
if not embedding or not hasattr(embedding, "data") or not embedding.data:
|
|
59
|
+
raise ValueError(
|
|
60
|
+
"Received empty or malformed embedding response from API"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
if not embedding.data[0] or not hasattr(embedding.data[0], "embedding"):
|
|
64
|
+
raise ValueError(
|
|
65
|
+
"Embedding response is missing expected 'embedding' field"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if not embedding.data[0].embedding:
|
|
69
|
+
raise ValueError("Received empty embedding vector")
|
|
70
|
+
|
|
71
|
+
return embedding.data[0].embedding
|
|
72
|
+
|
|
73
|
+
except Exception as e:
|
|
74
|
+
# Log the error and raise a more informative exception
|
|
75
|
+
error_msg = f"Error generating embedding with Cohere: {str(e)}"
|
|
76
|
+
print(error_msg)
|
|
77
|
+
raise Exception(error_msg)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .deepseek_chat import DeepSeekChat
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from openai import OpenAI
|
|
4
|
+
|
|
5
|
+
from ..base import VannaBase
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# from vanna.chromadb import ChromaDB_VectorStore
|
|
9
|
+
|
|
10
|
+
# class DeepSeekVanna(ChromaDB_VectorStore, DeepSeekChat):
|
|
11
|
+
# def __init__(self, config=None):
|
|
12
|
+
# ChromaDB_VectorStore.__init__(self, config=config)
|
|
13
|
+
# DeepSeekChat.__init__(self, config=config)
|
|
14
|
+
|
|
15
|
+
# vn = DeepSeekVanna(config={"api_key": "sk-************", "model": "deepseek-chat"})
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class DeepSeekChat(VannaBase):
|
|
19
|
+
def __init__(self, config=None):
|
|
20
|
+
if config is None:
|
|
21
|
+
raise ValueError(
|
|
22
|
+
"For DeepSeek, config must be provided with an api_key and model"
|
|
23
|
+
)
|
|
24
|
+
if "api_key" not in config:
|
|
25
|
+
raise ValueError("config must contain a DeepSeek api_key")
|
|
26
|
+
|
|
27
|
+
if "model" not in config:
|
|
28
|
+
raise ValueError("config must contain a DeepSeek model")
|
|
29
|
+
|
|
30
|
+
api_key = config["api_key"]
|
|
31
|
+
model = config["model"]
|
|
32
|
+
self.model = model
|
|
33
|
+
self.client = OpenAI(api_key=api_key, base_url="https://api.deepseek.com/v1")
|
|
34
|
+
|
|
35
|
+
def system_message(self, message: str) -> any:
|
|
36
|
+
return {"role": "system", "content": message}
|
|
37
|
+
|
|
38
|
+
def user_message(self, message: str) -> any:
|
|
39
|
+
return {"role": "user", "content": message}
|
|
40
|
+
|
|
41
|
+
def assistant_message(self, message: str) -> any:
|
|
42
|
+
return {"role": "assistant", "content": message}
|
|
43
|
+
|
|
44
|
+
def generate_sql(self, question: str, **kwargs) -> str:
|
|
45
|
+
# 使用父类的 generate_sql
|
|
46
|
+
sql = super().generate_sql(question, **kwargs)
|
|
47
|
+
|
|
48
|
+
# 替换 "\_" 为 "_"
|
|
49
|
+
sql = sql.replace("\\_", "_")
|
|
50
|
+
|
|
51
|
+
return sql
|
|
52
|
+
|
|
53
|
+
def submit_prompt(self, prompt, **kwargs) -> str:
|
|
54
|
+
chat_response = self.client.chat.completions.create(
|
|
55
|
+
model=self.model,
|
|
56
|
+
messages=prompt,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
return chat_response.choices[0].message.content
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class ImproperlyConfigured(Exception):
|
|
2
|
+
"""Raise for incorrect configuration."""
|
|
3
|
+
|
|
4
|
+
pass
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DependencyError(Exception):
|
|
8
|
+
"""Raise for missing dependencies."""
|
|
9
|
+
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ConnectionError(Exception):
|
|
14
|
+
"""Raise for connection"""
|
|
15
|
+
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class OTPCodeError(Exception):
|
|
20
|
+
"""Raise for invalid otp or not able to send it"""
|
|
21
|
+
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SQLRemoveError(Exception):
|
|
26
|
+
"""Raise when not able to remove SQL"""
|
|
27
|
+
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ExecutionError(Exception):
|
|
32
|
+
"""Raise when not able to execute Code"""
|
|
33
|
+
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ValidationError(Exception):
|
|
38
|
+
"""Raise for validations"""
|
|
39
|
+
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class APIError(Exception):
|
|
44
|
+
"""Raise for API errors"""
|
|
45
|
+
|
|
46
|
+
pass
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .faiss import FAISS
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import uuid
|
|
4
|
+
from typing import List, Dict, Any
|
|
5
|
+
|
|
6
|
+
import faiss
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pandas as pd
|
|
9
|
+
|
|
10
|
+
from ..base import VannaBase
|
|
11
|
+
from ..exceptions import DependencyError
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class FAISS(VannaBase):
|
|
15
|
+
def __init__(self, config=None):
|
|
16
|
+
if config is None:
|
|
17
|
+
config = {}
|
|
18
|
+
|
|
19
|
+
VannaBase.__init__(self, config=config)
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
import faiss
|
|
23
|
+
except ImportError:
|
|
24
|
+
raise DependencyError(
|
|
25
|
+
"FAISS is not installed. Please install it with 'pip install faiss-cpu' or 'pip install faiss-gpu'"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
from sentence_transformers import SentenceTransformer
|
|
30
|
+
except ImportError:
|
|
31
|
+
raise DependencyError(
|
|
32
|
+
"SentenceTransformer is not installed. Please install it with 'pip install sentence-transformers'."
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
self.path = config.get("path", ".")
|
|
36
|
+
self.embedding_dim = config.get("embedding_dim", 384)
|
|
37
|
+
self.n_results_sql = config.get("n_results_sql", config.get("n_results", 10))
|
|
38
|
+
self.n_results_ddl = config.get("n_results_ddl", config.get("n_results", 10))
|
|
39
|
+
self.n_results_documentation = config.get(
|
|
40
|
+
"n_results_documentation", config.get("n_results", 10)
|
|
41
|
+
)
|
|
42
|
+
self.curr_client = config.get("client", "persistent")
|
|
43
|
+
|
|
44
|
+
if self.curr_client == "persistent":
|
|
45
|
+
self.sql_index = self._load_or_create_index("sql_index.faiss")
|
|
46
|
+
self.ddl_index = self._load_or_create_index("ddl_index.faiss")
|
|
47
|
+
self.doc_index = self._load_or_create_index("doc_index.faiss")
|
|
48
|
+
elif self.curr_client == "in-memory":
|
|
49
|
+
self.sql_index = faiss.IndexFlatL2(self.embedding_dim)
|
|
50
|
+
self.ddl_index = faiss.IndexFlatL2(self.embedding_dim)
|
|
51
|
+
self.doc_index = faiss.IndexFlatL2(self.embedding_dim)
|
|
52
|
+
elif (
|
|
53
|
+
isinstance(self.curr_client, list)
|
|
54
|
+
and len(self.curr_client) == 3
|
|
55
|
+
and all(isinstance(idx, faiss.Index) for idx in self.curr_client)
|
|
56
|
+
):
|
|
57
|
+
self.sql_index = self.curr_client[0]
|
|
58
|
+
self.ddl_index = self.curr_client[1]
|
|
59
|
+
self.doc_index = self.curr_client[2]
|
|
60
|
+
else:
|
|
61
|
+
raise ValueError(
|
|
62
|
+
f"Unsupported storage type was set in config: {self.curr_client}"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
self.sql_metadata: List[Dict[str, Any]] = self._load_or_create_metadata(
|
|
66
|
+
"sql_metadata.json"
|
|
67
|
+
)
|
|
68
|
+
self.ddl_metadata: List[Dict[str, str]] = self._load_or_create_metadata(
|
|
69
|
+
"ddl_metadata.json"
|
|
70
|
+
)
|
|
71
|
+
self.doc_metadata: List[Dict[str, str]] = self._load_or_create_metadata(
|
|
72
|
+
"doc_metadata.json"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
model_name = config.get("embedding_model", "all-MiniLM-L6-v2")
|
|
76
|
+
self.embedding_model = SentenceTransformer(model_name)
|
|
77
|
+
|
|
78
|
+
def _load_or_create_index(self, filename):
|
|
79
|
+
filepath = os.path.join(self.path, filename)
|
|
80
|
+
if os.path.exists(filepath):
|
|
81
|
+
return faiss.read_index(filepath)
|
|
82
|
+
return faiss.IndexFlatL2(self.embedding_dim)
|
|
83
|
+
|
|
84
|
+
def _load_or_create_metadata(self, filename):
|
|
85
|
+
filepath = os.path.join(self.path, filename)
|
|
86
|
+
if os.path.exists(filepath):
|
|
87
|
+
with open(filepath, "r") as f:
|
|
88
|
+
return json.load(f)
|
|
89
|
+
return []
|
|
90
|
+
|
|
91
|
+
def _save_index(self, index, filename):
|
|
92
|
+
if self.curr_client == "persistent":
|
|
93
|
+
filepath = os.path.join(self.path, filename)
|
|
94
|
+
faiss.write_index(index, filepath)
|
|
95
|
+
|
|
96
|
+
def _save_metadata(self, metadata, filename):
|
|
97
|
+
if self.curr_client == "persistent":
|
|
98
|
+
filepath = os.path.join(self.path, filename)
|
|
99
|
+
with open(filepath, "w") as f:
|
|
100
|
+
json.dump(metadata, f)
|
|
101
|
+
|
|
102
|
+
def generate_embedding(self, data: str, **kwargs) -> List[float]:
|
|
103
|
+
embedding = self.embedding_model.encode(data)
|
|
104
|
+
assert embedding.shape[0] == self.embedding_dim, (
|
|
105
|
+
f"Embedding dimension mismatch: expected {self.embedding_dim}, got {embedding.shape[0]}"
|
|
106
|
+
)
|
|
107
|
+
return embedding.tolist()
|
|
108
|
+
|
|
109
|
+
def _add_to_index(self, index, metadata_list, text, extra_metadata=None) -> str:
|
|
110
|
+
embedding = self.generate_embedding(text)
|
|
111
|
+
index.add(np.array([embedding], dtype=np.float32))
|
|
112
|
+
entry_id = str(uuid.uuid4())
|
|
113
|
+
metadata_list.append({"id": entry_id, **(extra_metadata or {})})
|
|
114
|
+
return entry_id
|
|
115
|
+
|
|
116
|
+
def add_question_sql(self, question: str, sql: str, **kwargs) -> str:
|
|
117
|
+
entry_id = self._add_to_index(
|
|
118
|
+
self.sql_index,
|
|
119
|
+
self.sql_metadata,
|
|
120
|
+
question + " " + sql,
|
|
121
|
+
{"question": question, "sql": sql},
|
|
122
|
+
)
|
|
123
|
+
self._save_index(self.sql_index, "sql_index.faiss")
|
|
124
|
+
self._save_metadata(self.sql_metadata, "sql_metadata.json")
|
|
125
|
+
return entry_id
|
|
126
|
+
|
|
127
|
+
def add_ddl(self, ddl: str, **kwargs) -> str:
|
|
128
|
+
entry_id = self._add_to_index(
|
|
129
|
+
self.ddl_index, self.ddl_metadata, ddl, {"ddl": ddl}
|
|
130
|
+
)
|
|
131
|
+
self._save_index(self.ddl_index, "ddl_index.faiss")
|
|
132
|
+
self._save_metadata(self.ddl_metadata, "ddl_metadata.json")
|
|
133
|
+
return entry_id
|
|
134
|
+
|
|
135
|
+
def add_documentation(self, documentation: str, **kwargs) -> str:
|
|
136
|
+
entry_id = self._add_to_index(
|
|
137
|
+
self.doc_index,
|
|
138
|
+
self.doc_metadata,
|
|
139
|
+
documentation,
|
|
140
|
+
{"documentation": documentation},
|
|
141
|
+
)
|
|
142
|
+
self._save_index(self.doc_index, "doc_index.faiss")
|
|
143
|
+
self._save_metadata(self.doc_metadata, "doc_metadata.json")
|
|
144
|
+
return entry_id
|
|
145
|
+
|
|
146
|
+
def _get_similar(self, index, metadata_list, text, n_results) -> list:
|
|
147
|
+
embedding = self.generate_embedding(text)
|
|
148
|
+
D, I = index.search(np.array([embedding], dtype=np.float32), k=n_results)
|
|
149
|
+
return (
|
|
150
|
+
[] if len(I[0]) == 0 or I[0][0] == -1 else [metadata_list[i] for i in I[0]]
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
def get_similar_question_sql(self, question: str, **kwargs) -> list:
|
|
154
|
+
return self._get_similar(
|
|
155
|
+
self.sql_index, self.sql_metadata, question, self.n_results_sql
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
def get_related_ddl(self, question: str, **kwargs) -> list:
|
|
159
|
+
return [
|
|
160
|
+
metadata["ddl"]
|
|
161
|
+
for metadata in self._get_similar(
|
|
162
|
+
self.ddl_index, self.ddl_metadata, question, self.n_results_ddl
|
|
163
|
+
)
|
|
164
|
+
]
|
|
165
|
+
|
|
166
|
+
def get_related_documentation(self, question: str, **kwargs) -> list:
|
|
167
|
+
return [
|
|
168
|
+
metadata["documentation"]
|
|
169
|
+
for metadata in self._get_similar(
|
|
170
|
+
self.doc_index,
|
|
171
|
+
self.doc_metadata,
|
|
172
|
+
question,
|
|
173
|
+
self.n_results_documentation,
|
|
174
|
+
)
|
|
175
|
+
]
|
|
176
|
+
|
|
177
|
+
def get_training_data(self, **kwargs) -> pd.DataFrame:
|
|
178
|
+
sql_data = pd.DataFrame(self.sql_metadata)
|
|
179
|
+
sql_data["training_data_type"] = "sql"
|
|
180
|
+
|
|
181
|
+
ddl_data = pd.DataFrame(self.ddl_metadata)
|
|
182
|
+
ddl_data["training_data_type"] = "ddl"
|
|
183
|
+
|
|
184
|
+
doc_data = pd.DataFrame(self.doc_metadata)
|
|
185
|
+
doc_data["training_data_type"] = "documentation"
|
|
186
|
+
|
|
187
|
+
return pd.concat([sql_data, ddl_data, doc_data], ignore_index=True)
|
|
188
|
+
|
|
189
|
+
def remove_training_data(self, id: str, **kwargs) -> bool:
|
|
190
|
+
for metadata_list, index, index_name in [
|
|
191
|
+
(self.sql_metadata, self.sql_index, "sql_index.faiss"),
|
|
192
|
+
(self.ddl_metadata, self.ddl_index, "ddl_index.faiss"),
|
|
193
|
+
(self.doc_metadata, self.doc_index, "doc_index.faiss"),
|
|
194
|
+
]:
|
|
195
|
+
for i, item in enumerate(metadata_list):
|
|
196
|
+
if item["id"] == id:
|
|
197
|
+
del metadata_list[i]
|
|
198
|
+
new_index = faiss.IndexFlatL2(self.embedding_dim)
|
|
199
|
+
embeddings = [
|
|
200
|
+
self.generate_embedding(json.dumps(m)) for m in metadata_list
|
|
201
|
+
]
|
|
202
|
+
if embeddings:
|
|
203
|
+
new_index.add(np.array(embeddings, dtype=np.float32))
|
|
204
|
+
setattr(self, index_name.split(".")[0], new_index)
|
|
205
|
+
|
|
206
|
+
if self.curr_client == "persistent":
|
|
207
|
+
self._save_index(new_index, index_name)
|
|
208
|
+
self._save_metadata(
|
|
209
|
+
metadata_list, f"{index_name.split('.')[0]}_metadata.json"
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
return True
|
|
213
|
+
return False
|
|
214
|
+
|
|
215
|
+
def remove_collection(self, collection_name: str) -> bool:
|
|
216
|
+
if collection_name in ["sql", "ddl", "documentation"]:
|
|
217
|
+
setattr(
|
|
218
|
+
self, f"{collection_name}_index", faiss.IndexFlatL2(self.embedding_dim)
|
|
219
|
+
)
|
|
220
|
+
setattr(self, f"{collection_name}_metadata", [])
|
|
221
|
+
|
|
222
|
+
if self.curr_client == "persistent":
|
|
223
|
+
self._save_index(
|
|
224
|
+
getattr(self, f"{collection_name}_index"),
|
|
225
|
+
f"{collection_name}_index.faiss",
|
|
226
|
+
)
|
|
227
|
+
self._save_metadata([], f"{collection_name}_metadata.json")
|
|
228
|
+
|
|
229
|
+
return True
|
|
230
|
+
return False
|