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.
Files changed (291) hide show
  1. asksql-2.1.0.dist-info/METADATA +517 -0
  2. asksql-2.1.0.dist-info/RECORD +291 -0
  3. asksql-2.1.0.dist-info/WHEEL +4 -0
  4. asksql-2.1.0.dist-info/entry_points.txt +4 -0
  5. asksql-2.1.0.dist-info/licenses/LICENSE +21 -0
  6. vanna/__init__.py +172 -0
  7. vanna/agents/__init__.py +7 -0
  8. vanna/capabilities/__init__.py +17 -0
  9. vanna/capabilities/agent_memory/__init__.py +21 -0
  10. vanna/capabilities/agent_memory/base.py +103 -0
  11. vanna/capabilities/agent_memory/models.py +53 -0
  12. vanna/capabilities/file_system/__init__.py +14 -0
  13. vanna/capabilities/file_system/base.py +71 -0
  14. vanna/capabilities/file_system/models.py +25 -0
  15. vanna/capabilities/sql_runner/__init__.py +13 -0
  16. vanna/capabilities/sql_runner/base.py +37 -0
  17. vanna/capabilities/sql_runner/models.py +13 -0
  18. vanna/components/__init__.py +92 -0
  19. vanna/components/base.py +11 -0
  20. vanna/components/rich/__init__.py +83 -0
  21. vanna/components/rich/containers/__init__.py +7 -0
  22. vanna/components/rich/containers/card.py +20 -0
  23. vanna/components/rich/data/__init__.py +9 -0
  24. vanna/components/rich/data/chart.py +17 -0
  25. vanna/components/rich/data/dataframe.py +93 -0
  26. vanna/components/rich/feedback/__init__.py +21 -0
  27. vanna/components/rich/feedback/badge.py +16 -0
  28. vanna/components/rich/feedback/icon_text.py +14 -0
  29. vanna/components/rich/feedback/log_viewer.py +41 -0
  30. vanna/components/rich/feedback/notification.py +19 -0
  31. vanna/components/rich/feedback/progress.py +37 -0
  32. vanna/components/rich/feedback/status_card.py +28 -0
  33. vanna/components/rich/feedback/status_indicator.py +14 -0
  34. vanna/components/rich/interactive/__init__.py +21 -0
  35. vanna/components/rich/interactive/button.py +95 -0
  36. vanna/components/rich/interactive/task_list.py +58 -0
  37. vanna/components/rich/interactive/ui_state.py +93 -0
  38. vanna/components/rich/specialized/__init__.py +7 -0
  39. vanna/components/rich/specialized/artifact.py +20 -0
  40. vanna/components/rich/text.py +16 -0
  41. vanna/components/simple/__init__.py +15 -0
  42. vanna/components/simple/image.py +15 -0
  43. vanna/components/simple/link.py +15 -0
  44. vanna/components/simple/text.py +11 -0
  45. vanna/core/__init__.py +193 -0
  46. vanna/core/_compat.py +19 -0
  47. vanna/core/agent/__init__.py +10 -0
  48. vanna/core/agent/agent.py +1407 -0
  49. vanna/core/agent/config.py +123 -0
  50. vanna/core/audit/__init__.py +28 -0
  51. vanna/core/audit/base.py +299 -0
  52. vanna/core/audit/models.py +131 -0
  53. vanna/core/component_manager.py +329 -0
  54. vanna/core/components.py +53 -0
  55. vanna/core/enhancer/__init__.py +11 -0
  56. vanna/core/enhancer/base.py +94 -0
  57. vanna/core/enhancer/default.py +118 -0
  58. vanna/core/enricher/__init__.py +10 -0
  59. vanna/core/enricher/base.py +59 -0
  60. vanna/core/errors.py +47 -0
  61. vanna/core/evaluation/__init__.py +81 -0
  62. vanna/core/evaluation/base.py +186 -0
  63. vanna/core/evaluation/dataset.py +254 -0
  64. vanna/core/evaluation/evaluators.py +376 -0
  65. vanna/core/evaluation/report.py +289 -0
  66. vanna/core/evaluation/runner.py +313 -0
  67. vanna/core/filter/__init__.py +10 -0
  68. vanna/core/filter/base.py +67 -0
  69. vanna/core/lifecycle/__init__.py +10 -0
  70. vanna/core/lifecycle/base.py +83 -0
  71. vanna/core/llm/__init__.py +16 -0
  72. vanna/core/llm/base.py +40 -0
  73. vanna/core/llm/models.py +61 -0
  74. vanna/core/middleware/__init__.py +10 -0
  75. vanna/core/middleware/base.py +69 -0
  76. vanna/core/observability/__init__.py +11 -0
  77. vanna/core/observability/base.py +88 -0
  78. vanna/core/observability/models.py +47 -0
  79. vanna/core/recovery/__init__.py +11 -0
  80. vanna/core/recovery/base.py +84 -0
  81. vanna/core/recovery/models.py +32 -0
  82. vanna/core/registry.py +278 -0
  83. vanna/core/rich_component.py +156 -0
  84. vanna/core/simple_component.py +27 -0
  85. vanna/core/storage/__init__.py +14 -0
  86. vanna/core/storage/base.py +46 -0
  87. vanna/core/storage/models.py +46 -0
  88. vanna/core/system_prompt/__init__.py +13 -0
  89. vanna/core/system_prompt/base.py +36 -0
  90. vanna/core/system_prompt/default.py +157 -0
  91. vanna/core/tool/__init__.py +18 -0
  92. vanna/core/tool/base.py +70 -0
  93. vanna/core/tool/models.py +84 -0
  94. vanna/core/user/__init__.py +17 -0
  95. vanna/core/user/base.py +29 -0
  96. vanna/core/user/models.py +25 -0
  97. vanna/core/user/request_context.py +70 -0
  98. vanna/core/user/resolver.py +42 -0
  99. vanna/core/validation.py +164 -0
  100. vanna/core/workflow/__init__.py +12 -0
  101. vanna/core/workflow/base.py +254 -0
  102. vanna/core/workflow/default.py +789 -0
  103. vanna/examples/__init__.py +1 -0
  104. vanna/examples/__main__.py +44 -0
  105. vanna/examples/anthropic_quickstart.py +80 -0
  106. vanna/examples/artifact_example.py +293 -0
  107. vanna/examples/claude_sqlite_example.py +236 -0
  108. vanna/examples/coding_agent_example.py +300 -0
  109. vanna/examples/custom_system_prompt_example.py +174 -0
  110. vanna/examples/default_workflow_handler_example.py +208 -0
  111. vanna/examples/email_auth_example.py +340 -0
  112. vanna/examples/evaluation_example.py +269 -0
  113. vanna/examples/extensibility_example.py +262 -0
  114. vanna/examples/minimal_example.py +67 -0
  115. vanna/examples/mock_auth_example.py +227 -0
  116. vanna/examples/mock_custom_tool.py +311 -0
  117. vanna/examples/mock_quickstart.py +79 -0
  118. vanna/examples/mock_quota_example.py +145 -0
  119. vanna/examples/mock_rich_components_demo.py +396 -0
  120. vanna/examples/mock_sqlite_example.py +223 -0
  121. vanna/examples/openai_quickstart.py +83 -0
  122. vanna/examples/primitive_components_demo.py +305 -0
  123. vanna/examples/quota_lifecycle_example.py +139 -0
  124. vanna/examples/visualization_example.py +251 -0
  125. vanna/integrations/__init__.py +17 -0
  126. vanna/integrations/anthropic/__init__.py +9 -0
  127. vanna/integrations/anthropic/llm.py +270 -0
  128. vanna/integrations/azureopenai/__init__.py +9 -0
  129. vanna/integrations/azureopenai/llm.py +329 -0
  130. vanna/integrations/azuresearch/__init__.py +7 -0
  131. vanna/integrations/azuresearch/agent_memory.py +413 -0
  132. vanna/integrations/bigquery/__init__.py +5 -0
  133. vanna/integrations/bigquery/sql_runner.py +81 -0
  134. vanna/integrations/chromadb/__init__.py +104 -0
  135. vanna/integrations/chromadb/agent_memory.py +488 -0
  136. vanna/integrations/clickhouse/__init__.py +5 -0
  137. vanna/integrations/clickhouse/sql_runner.py +82 -0
  138. vanna/integrations/duckdb/__init__.py +5 -0
  139. vanna/integrations/duckdb/sql_runner.py +65 -0
  140. vanna/integrations/faiss/__init__.py +7 -0
  141. vanna/integrations/faiss/agent_memory.py +435 -0
  142. vanna/integrations/google/__init__.py +9 -0
  143. vanna/integrations/google/gemini.py +370 -0
  144. vanna/integrations/hive/__init__.py +5 -0
  145. vanna/integrations/hive/sql_runner.py +87 -0
  146. vanna/integrations/local/__init__.py +17 -0
  147. vanna/integrations/local/agent_memory/__init__.py +7 -0
  148. vanna/integrations/local/agent_memory/in_memory.py +285 -0
  149. vanna/integrations/local/audit.py +59 -0
  150. vanna/integrations/local/file_system.py +242 -0
  151. vanna/integrations/local/file_system_conversation_store.py +255 -0
  152. vanna/integrations/local/storage.py +62 -0
  153. vanna/integrations/marqo/__init__.py +7 -0
  154. vanna/integrations/marqo/agent_memory.py +354 -0
  155. vanna/integrations/milvus/__init__.py +7 -0
  156. vanna/integrations/milvus/agent_memory.py +458 -0
  157. vanna/integrations/mock/__init__.py +9 -0
  158. vanna/integrations/mock/llm.py +65 -0
  159. vanna/integrations/mssql/__init__.py +5 -0
  160. vanna/integrations/mssql/sql_runner.py +66 -0
  161. vanna/integrations/mysql/__init__.py +5 -0
  162. vanna/integrations/mysql/sql_runner.py +92 -0
  163. vanna/integrations/ollama/__init__.py +7 -0
  164. vanna/integrations/ollama/llm.py +252 -0
  165. vanna/integrations/openai/__init__.py +10 -0
  166. vanna/integrations/openai/llm.py +267 -0
  167. vanna/integrations/openai/responses.py +163 -0
  168. vanna/integrations/opensearch/__init__.py +7 -0
  169. vanna/integrations/opensearch/agent_memory.py +411 -0
  170. vanna/integrations/oracle/__init__.py +5 -0
  171. vanna/integrations/oracle/sql_runner.py +75 -0
  172. vanna/integrations/pinecone/__init__.py +7 -0
  173. vanna/integrations/pinecone/agent_memory.py +329 -0
  174. vanna/integrations/plotly/__init__.py +5 -0
  175. vanna/integrations/plotly/chart_generator.py +313 -0
  176. vanna/integrations/postgres/__init__.py +9 -0
  177. vanna/integrations/postgres/sql_runner.py +112 -0
  178. vanna/integrations/premium/agent_memory/__init__.py +7 -0
  179. vanna/integrations/premium/agent_memory/premium.py +186 -0
  180. vanna/integrations/presto/__init__.py +5 -0
  181. vanna/integrations/presto/sql_runner.py +107 -0
  182. vanna/integrations/qdrant/__init__.py +7 -0
  183. vanna/integrations/qdrant/agent_memory.py +466 -0
  184. vanna/integrations/snowflake/__init__.py +5 -0
  185. vanna/integrations/snowflake/sql_runner.py +147 -0
  186. vanna/integrations/sqlite/__init__.py +9 -0
  187. vanna/integrations/sqlite/sql_runner.py +65 -0
  188. vanna/integrations/weaviate/__init__.py +7 -0
  189. vanna/integrations/weaviate/agent_memory.py +428 -0
  190. vanna/legacy/ZhipuAI/ZhipuAI_Chat.py +233 -0
  191. vanna/legacy/ZhipuAI/ZhipuAI_embeddings.py +79 -0
  192. vanna/legacy/ZhipuAI/__init__.py +2 -0
  193. vanna/legacy/__init__.py +403 -0
  194. vanna/legacy/adapter.py +468 -0
  195. vanna/legacy/advanced/__init__.py +28 -0
  196. vanna/legacy/anthropic/__init__.py +1 -0
  197. vanna/legacy/anthropic/anthropic_chat.py +80 -0
  198. vanna/legacy/azuresearch/__init__.py +1 -0
  199. vanna/legacy/azuresearch/azuresearch_vector.py +274 -0
  200. vanna/legacy/base/__init__.py +1 -0
  201. vanna/legacy/base/base.py +2133 -0
  202. vanna/legacy/base/safe_exec.py +190 -0
  203. vanna/legacy/bedrock/__init__.py +1 -0
  204. vanna/legacy/bedrock/bedrock_converse.py +86 -0
  205. vanna/legacy/chromadb/__init__.py +1 -0
  206. vanna/legacy/chromadb/chromadb_vector.py +259 -0
  207. vanna/legacy/cohere/__init__.py +2 -0
  208. vanna/legacy/cohere/cohere_chat.py +99 -0
  209. vanna/legacy/cohere/cohere_embeddings.py +77 -0
  210. vanna/legacy/deepseek/__init__.py +1 -0
  211. vanna/legacy/deepseek/deepseek_chat.py +59 -0
  212. vanna/legacy/exceptions/__init__.py +46 -0
  213. vanna/legacy/faiss/__init__.py +1 -0
  214. vanna/legacy/faiss/faiss.py +230 -0
  215. vanna/legacy/flask/__init__.py +1355 -0
  216. vanna/legacy/flask/assets.py +58 -0
  217. vanna/legacy/flask/auth.py +56 -0
  218. vanna/legacy/google/__init__.py +2 -0
  219. vanna/legacy/google/bigquery_vector.py +293 -0
  220. vanna/legacy/google/gemini_chat.py +78 -0
  221. vanna/legacy/hf/__init__.py +1 -0
  222. vanna/legacy/hf/hf.py +80 -0
  223. vanna/legacy/local.py +8 -0
  224. vanna/legacy/marqo/__init__.py +1 -0
  225. vanna/legacy/marqo/marqo.py +168 -0
  226. vanna/legacy/milvus/__init__.py +1 -0
  227. vanna/legacy/milvus/milvus_vector.py +328 -0
  228. vanna/legacy/mistral/__init__.py +1 -0
  229. vanna/legacy/mistral/mistral.py +51 -0
  230. vanna/legacy/mock/__init__.py +3 -0
  231. vanna/legacy/mock/embedding.py +11 -0
  232. vanna/legacy/mock/llm.py +18 -0
  233. vanna/legacy/mock/vectordb.py +67 -0
  234. vanna/legacy/ollama/__init__.py +1 -0
  235. vanna/legacy/ollama/ollama.py +110 -0
  236. vanna/legacy/openai/__init__.py +2 -0
  237. vanna/legacy/openai/openai_chat.py +124 -0
  238. vanna/legacy/openai/openai_embeddings.py +46 -0
  239. vanna/legacy/opensearch/__init__.py +2 -0
  240. vanna/legacy/opensearch/opensearch_vector.py +369 -0
  241. vanna/legacy/opensearch/opensearch_vector_semantic.py +200 -0
  242. vanna/legacy/oracle/__init__.py +1 -0
  243. vanna/legacy/oracle/oracle_vector.py +584 -0
  244. vanna/legacy/pgvector/__init__.py +1 -0
  245. vanna/legacy/pgvector/pgvector.py +282 -0
  246. vanna/legacy/pinecone/__init__.py +3 -0
  247. vanna/legacy/pinecone/pinecone_vector.py +275 -0
  248. vanna/legacy/qdrant/__init__.py +3 -0
  249. vanna/legacy/qdrant/qdrant.py +329 -0
  250. vanna/legacy/qianfan/Qianfan_Chat.py +170 -0
  251. vanna/legacy/qianfan/Qianfan_embeddings.py +36 -0
  252. vanna/legacy/qianfan/__init__.py +2 -0
  253. vanna/legacy/qianwen/QianwenAI_chat.py +132 -0
  254. vanna/legacy/qianwen/QianwenAI_embeddings.py +46 -0
  255. vanna/legacy/qianwen/__init__.py +2 -0
  256. vanna/legacy/remote.py +79 -0
  257. vanna/legacy/types/__init__.py +292 -0
  258. vanna/legacy/utils.py +72 -0
  259. vanna/legacy/vannadb/__init__.py +1 -0
  260. vanna/legacy/vannadb/vannadb_vector.py +468 -0
  261. vanna/legacy/vllm/__init__.py +1 -0
  262. vanna/legacy/vllm/vllm.py +97 -0
  263. vanna/legacy/weaviate/__init__.py +1 -0
  264. vanna/legacy/weaviate/weaviate_vector.py +194 -0
  265. vanna/legacy/xinference/__init__.py +1 -0
  266. vanna/legacy/xinference/xinference.py +53 -0
  267. vanna/py.typed +0 -0
  268. vanna/servers/__init__.py +16 -0
  269. vanna/servers/__main__.py +8 -0
  270. vanna/servers/base/__init__.py +18 -0
  271. vanna/servers/base/chat_handler.py +65 -0
  272. vanna/servers/base/models.py +111 -0
  273. vanna/servers/base/rich_chat_handler.py +141 -0
  274. vanna/servers/base/templates.py +331 -0
  275. vanna/servers/cli/__init__.py +7 -0
  276. vanna/servers/cli/server_runner.py +204 -0
  277. vanna/servers/fastapi/__init__.py +7 -0
  278. vanna/servers/fastapi/app.py +163 -0
  279. vanna/servers/fastapi/routes.py +183 -0
  280. vanna/servers/flask/__init__.py +7 -0
  281. vanna/servers/flask/app.py +132 -0
  282. vanna/servers/flask/routes.py +137 -0
  283. vanna/tools/__init__.py +41 -0
  284. vanna/tools/agent_memory.py +322 -0
  285. vanna/tools/file_system.py +879 -0
  286. vanna/tools/python.py +222 -0
  287. vanna/tools/run_sql.py +173 -0
  288. vanna/tools/visualize_data.py +195 -0
  289. vanna/utils/__init__.py +0 -0
  290. vanna/utils/sql_safety.py +84 -0
  291. 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