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,56 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
import flask
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AuthInterface(ABC):
|
|
7
|
+
@abstractmethod
|
|
8
|
+
def get_user(self, flask_request) -> any:
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def is_logged_in(self, user: any) -> bool:
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
@abstractmethod
|
|
16
|
+
def override_config_for_user(self, user: any, config: dict) -> dict:
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def login_form(self) -> str:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def login_handler(self, flask_request) -> str:
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def callback_handler(self, flask_request) -> str:
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def logout_handler(self, flask_request) -> str:
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class NoAuth(AuthInterface):
|
|
37
|
+
def get_user(self, flask_request) -> any:
|
|
38
|
+
return {}
|
|
39
|
+
|
|
40
|
+
def is_logged_in(self, user: any) -> bool:
|
|
41
|
+
return True
|
|
42
|
+
|
|
43
|
+
def override_config_for_user(self, user: any, config: dict) -> dict:
|
|
44
|
+
return config
|
|
45
|
+
|
|
46
|
+
def login_form(self) -> str:
|
|
47
|
+
return ""
|
|
48
|
+
|
|
49
|
+
def login_handler(self, flask_request) -> str:
|
|
50
|
+
return "No login required"
|
|
51
|
+
|
|
52
|
+
def callback_handler(self, flask_request) -> str:
|
|
53
|
+
return "No login required"
|
|
54
|
+
|
|
55
|
+
def logout_handler(self, flask_request) -> str:
|
|
56
|
+
return "No login required"
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import os
|
|
3
|
+
import uuid
|
|
4
|
+
from typing import List, Optional
|
|
5
|
+
from vertexai.language_models import TextEmbeddingInput, TextEmbeddingModel
|
|
6
|
+
|
|
7
|
+
import pandas as pd
|
|
8
|
+
from google.cloud import bigquery
|
|
9
|
+
|
|
10
|
+
from ..base import VannaBase
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BigQuery_VectorStore(VannaBase):
|
|
14
|
+
def __init__(self, config: dict, **kwargs):
|
|
15
|
+
self.config = config
|
|
16
|
+
|
|
17
|
+
self.n_results_sql = config.get("n_results_sql", config.get("n_results", 10))
|
|
18
|
+
self.n_results_documentation = config.get(
|
|
19
|
+
"n_results_documentation", config.get("n_results", 10)
|
|
20
|
+
)
|
|
21
|
+
self.n_results_ddl = config.get("n_results_ddl", config.get("n_results", 10))
|
|
22
|
+
|
|
23
|
+
if "api_key" in config or os.getenv("GOOGLE_API_KEY"):
|
|
24
|
+
"""
|
|
25
|
+
If Google api_key is provided through config
|
|
26
|
+
or set as an environment variable, assign it.
|
|
27
|
+
"""
|
|
28
|
+
print("Configuring genai")
|
|
29
|
+
self.type = "GEMINI"
|
|
30
|
+
import google.generativeai as genai
|
|
31
|
+
|
|
32
|
+
genai.configure(api_key=config["api_key"])
|
|
33
|
+
|
|
34
|
+
self.genai = genai
|
|
35
|
+
else:
|
|
36
|
+
self.type = "VERTEX_AI"
|
|
37
|
+
# Authenticate using VertexAI
|
|
38
|
+
|
|
39
|
+
if self.config.get("project_id"):
|
|
40
|
+
self.project_id = self.config.get("project_id")
|
|
41
|
+
else:
|
|
42
|
+
self.project_id = os.getenv("GOOGLE_CLOUD_PROJECT")
|
|
43
|
+
|
|
44
|
+
if self.project_id is None:
|
|
45
|
+
raise ValueError("Project ID is not set")
|
|
46
|
+
|
|
47
|
+
self.conn = bigquery.Client(project=self.project_id)
|
|
48
|
+
|
|
49
|
+
dataset_name = self.config.get("bigquery_dataset_name", "vanna_managed")
|
|
50
|
+
self.dataset_id = f"{self.project_id}.{dataset_name}"
|
|
51
|
+
dataset = bigquery.Dataset(self.dataset_id)
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
self.conn.get_dataset(self.dataset_id) # Make an API request.
|
|
55
|
+
print(f"Dataset {self.dataset_id} already exists")
|
|
56
|
+
except Exception:
|
|
57
|
+
# Dataset does not exist, create it
|
|
58
|
+
dataset.location = "US"
|
|
59
|
+
self.conn.create_dataset(dataset, timeout=30) # Make an API request.
|
|
60
|
+
print(f"Created dataset {self.dataset_id}")
|
|
61
|
+
|
|
62
|
+
# Create a table called training_data in the dataset that contains the columns:
|
|
63
|
+
# id, training_data_type, question, content, embedding, created_at
|
|
64
|
+
|
|
65
|
+
self.table_id = f"{self.dataset_id}.training_data"
|
|
66
|
+
schema = [
|
|
67
|
+
bigquery.SchemaField("id", "STRING", mode="REQUIRED"),
|
|
68
|
+
bigquery.SchemaField("training_data_type", "STRING", mode="REQUIRED"),
|
|
69
|
+
bigquery.SchemaField("question", "STRING", mode="REQUIRED"),
|
|
70
|
+
bigquery.SchemaField("content", "STRING", mode="REQUIRED"),
|
|
71
|
+
bigquery.SchemaField("embedding", "FLOAT64", mode="REPEATED"),
|
|
72
|
+
bigquery.SchemaField("created_at", "TIMESTAMP", mode="REQUIRED"),
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
table = bigquery.Table(self.table_id, schema=schema)
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
self.conn.get_table(self.table_id) # Make an API request.
|
|
79
|
+
print(f"Table {self.table_id} already exists")
|
|
80
|
+
except Exception:
|
|
81
|
+
# Table does not exist, create it
|
|
82
|
+
self.conn.create_table(table, timeout=30) # Make an API request.
|
|
83
|
+
print(f"Created table {self.table_id}")
|
|
84
|
+
|
|
85
|
+
# Create VECTOR INDEX IF NOT EXISTS
|
|
86
|
+
# TODO: This requires 5000 rows before it can be created
|
|
87
|
+
# vector_index_query = f"""
|
|
88
|
+
# CREATE VECTOR INDEX IF NOT EXISTS my_index
|
|
89
|
+
# ON `{self.table_id}`(embedding)
|
|
90
|
+
# OPTIONS(
|
|
91
|
+
# distance_type='COSINE',
|
|
92
|
+
# index_type='IVF',
|
|
93
|
+
# ivf_options='{{"num_lists": 1000}}'
|
|
94
|
+
# )
|
|
95
|
+
# """
|
|
96
|
+
|
|
97
|
+
# try:
|
|
98
|
+
# self.conn.query(vector_index_query).result() # Make an API request.
|
|
99
|
+
# print(f"Vector index on {self.table_id} created or already exists")
|
|
100
|
+
# except Exception as e:
|
|
101
|
+
# print(f"Failed to create vector index: {e}")
|
|
102
|
+
|
|
103
|
+
def store_training_data(
|
|
104
|
+
self,
|
|
105
|
+
training_data_type: str,
|
|
106
|
+
question: str,
|
|
107
|
+
content: str,
|
|
108
|
+
embedding: List[float],
|
|
109
|
+
**kwargs,
|
|
110
|
+
) -> str:
|
|
111
|
+
id = str(uuid.uuid4())
|
|
112
|
+
created_at = datetime.datetime.now()
|
|
113
|
+
self.conn.insert_rows_json(
|
|
114
|
+
self.table_id,
|
|
115
|
+
[
|
|
116
|
+
{
|
|
117
|
+
"id": id,
|
|
118
|
+
"training_data_type": training_data_type,
|
|
119
|
+
"question": question,
|
|
120
|
+
"content": content,
|
|
121
|
+
"embedding": embedding,
|
|
122
|
+
"created_at": created_at.isoformat(),
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
return id
|
|
128
|
+
|
|
129
|
+
def fetch_similar_training_data(
|
|
130
|
+
self, training_data_type: str, question: str, n_results, **kwargs
|
|
131
|
+
) -> pd.DataFrame:
|
|
132
|
+
question_embedding = self.generate_question_embedding(question)
|
|
133
|
+
|
|
134
|
+
query = f"""
|
|
135
|
+
SELECT
|
|
136
|
+
base.id as id,
|
|
137
|
+
base.question as question,
|
|
138
|
+
base.training_data_type as training_data_type,
|
|
139
|
+
base.content as content,
|
|
140
|
+
distance
|
|
141
|
+
FROM
|
|
142
|
+
VECTOR_SEARCH(
|
|
143
|
+
TABLE `{self.table_id}`,
|
|
144
|
+
'embedding',
|
|
145
|
+
(SELECT * FROM UNNEST([STRUCT({question_embedding})])),
|
|
146
|
+
top_k => 5,
|
|
147
|
+
distance_type => 'COSINE',
|
|
148
|
+
options => '{{"use_brute_force":true}}'
|
|
149
|
+
)
|
|
150
|
+
WHERE
|
|
151
|
+
base.training_data_type = @training_data_type
|
|
152
|
+
"""
|
|
153
|
+
job_config = bigquery.QueryJobConfig(
|
|
154
|
+
query_parameters=[
|
|
155
|
+
bigquery.ScalarQueryParameter(
|
|
156
|
+
"training_data_type", "STRING", training_data_type
|
|
157
|
+
)
|
|
158
|
+
]
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
results = self.conn.query(query, job_config=job_config).result().to_dataframe()
|
|
162
|
+
return results
|
|
163
|
+
|
|
164
|
+
def get_embeddings(self, data: str, task: str) -> List[float]:
|
|
165
|
+
embeddings = None
|
|
166
|
+
|
|
167
|
+
if self.type == "VERTEX_AI":
|
|
168
|
+
input = [TextEmbeddingInput(data, task)]
|
|
169
|
+
model = TextEmbeddingModel.from_pretrained("text-embedding-004")
|
|
170
|
+
|
|
171
|
+
result = model.get_embeddings(input)
|
|
172
|
+
|
|
173
|
+
if len(result) > 0:
|
|
174
|
+
embeddings = result[0].values
|
|
175
|
+
else:
|
|
176
|
+
# Use Gemini Consumer API
|
|
177
|
+
result = self.genai.embed_content(
|
|
178
|
+
model="models/text-embedding-004", content=data, task_type=task
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
if "embedding" in result:
|
|
182
|
+
embeddings = result["embedding"]
|
|
183
|
+
|
|
184
|
+
return embeddings
|
|
185
|
+
|
|
186
|
+
def generate_question_embedding(self, data: str, **kwargs) -> List[float]:
|
|
187
|
+
result = self.get_embeddings(data, "RETRIEVAL_QUERY")
|
|
188
|
+
|
|
189
|
+
if result is not None:
|
|
190
|
+
return result
|
|
191
|
+
else:
|
|
192
|
+
raise ValueError("No embeddings returned")
|
|
193
|
+
|
|
194
|
+
def generate_storage_embedding(self, data: str, **kwargs) -> List[float]:
|
|
195
|
+
result = self.get_embeddings(data, "RETRIEVAL_DOCUMENT")
|
|
196
|
+
|
|
197
|
+
if result is not None:
|
|
198
|
+
return result
|
|
199
|
+
else:
|
|
200
|
+
raise ValueError("No embeddings returned")
|
|
201
|
+
|
|
202
|
+
# task = "RETRIEVAL_DOCUMENT"
|
|
203
|
+
# inputs = [TextEmbeddingInput(data, task)]
|
|
204
|
+
# embeddings = self.vertex_embedding_model.get_embeddings(inputs)
|
|
205
|
+
|
|
206
|
+
# if len(embeddings) == 0:
|
|
207
|
+
# raise ValueError("No embeddings returned")
|
|
208
|
+
|
|
209
|
+
# return embeddings[0].values
|
|
210
|
+
|
|
211
|
+
return result
|
|
212
|
+
|
|
213
|
+
def generate_embedding(self, data: str, **kwargs) -> List[float]:
|
|
214
|
+
return self.generate_storage_embedding(data, **kwargs)
|
|
215
|
+
|
|
216
|
+
def get_similar_question_sql(self, question: str, **kwargs) -> list:
|
|
217
|
+
df = self.fetch_similar_training_data(
|
|
218
|
+
training_data_type="sql", question=question, n_results=self.n_results_sql
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
# Return a list of dictionaries with only question, sql fields. The content field needs to be renamed to sql
|
|
222
|
+
return df.rename(columns={"content": "sql"})[["question", "sql"]].to_dict(
|
|
223
|
+
orient="records"
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
def get_related_ddl(self, question: str, **kwargs) -> list:
|
|
227
|
+
df = self.fetch_similar_training_data(
|
|
228
|
+
training_data_type="ddl", question=question, n_results=self.n_results_ddl
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
# Return a list of strings of the content
|
|
232
|
+
return df["content"].tolist()
|
|
233
|
+
|
|
234
|
+
def get_related_documentation(self, question: str, **kwargs) -> list:
|
|
235
|
+
df = self.fetch_similar_training_data(
|
|
236
|
+
training_data_type="documentation",
|
|
237
|
+
question=question,
|
|
238
|
+
n_results=self.n_results_documentation,
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
# Return a list of strings of the content
|
|
242
|
+
return df["content"].tolist()
|
|
243
|
+
|
|
244
|
+
def add_question_sql(self, question: str, sql: str, **kwargs) -> str:
|
|
245
|
+
doc = {"question": question, "sql": sql}
|
|
246
|
+
|
|
247
|
+
embedding = self.generate_embedding(str(doc))
|
|
248
|
+
|
|
249
|
+
return self.store_training_data(
|
|
250
|
+
training_data_type="sql",
|
|
251
|
+
question=question,
|
|
252
|
+
content=sql,
|
|
253
|
+
embedding=embedding,
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
def add_ddl(self, ddl: str, **kwargs) -> str:
|
|
257
|
+
embedding = self.generate_embedding(ddl)
|
|
258
|
+
|
|
259
|
+
return self.store_training_data(
|
|
260
|
+
training_data_type="ddl", question="", content=ddl, embedding=embedding
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
def add_documentation(self, documentation: str, **kwargs) -> str:
|
|
264
|
+
embedding = self.generate_embedding(documentation)
|
|
265
|
+
|
|
266
|
+
return self.store_training_data(
|
|
267
|
+
training_data_type="documentation",
|
|
268
|
+
question="",
|
|
269
|
+
content=documentation,
|
|
270
|
+
embedding=embedding,
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
def get_training_data(self, **kwargs) -> pd.DataFrame:
|
|
274
|
+
query = (
|
|
275
|
+
f"SELECT id, training_data_type, question, content FROM `{self.table_id}`"
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
return self.conn.query(query).result().to_dataframe()
|
|
279
|
+
|
|
280
|
+
def remove_training_data(self, id: str, **kwargs) -> bool:
|
|
281
|
+
# Pass id as a query parameter, never inside the SQL string (CVE-2026-4229)
|
|
282
|
+
query = f"DELETE FROM `{self.table_id}` WHERE id = @id"
|
|
283
|
+
job_config = bigquery.QueryJobConfig(
|
|
284
|
+
query_parameters=[bigquery.ScalarQueryParameter("id", "STRING", id)]
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
try:
|
|
288
|
+
self.conn.query(query, job_config=job_config).result()
|
|
289
|
+
return True
|
|
290
|
+
|
|
291
|
+
except Exception as e:
|
|
292
|
+
print(f"Failed to remove training data: {e}")
|
|
293
|
+
return False
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from ..base import VannaBase
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class GoogleGeminiChat(VannaBase):
|
|
7
|
+
def __init__(self, config=None):
|
|
8
|
+
VannaBase.__init__(self, config=config)
|
|
9
|
+
|
|
10
|
+
# default temperature - can be overrided using config
|
|
11
|
+
self.temperature = 0.7
|
|
12
|
+
|
|
13
|
+
if "temperature" in config:
|
|
14
|
+
self.temperature = config["temperature"]
|
|
15
|
+
|
|
16
|
+
if "model_name" in config:
|
|
17
|
+
model_name = config["model_name"]
|
|
18
|
+
else:
|
|
19
|
+
model_name = "gemini-1.5-pro"
|
|
20
|
+
|
|
21
|
+
self.google_api_key = None
|
|
22
|
+
|
|
23
|
+
if "api_key" in config or os.getenv("GOOGLE_API_KEY"):
|
|
24
|
+
"""
|
|
25
|
+
If Google api_key is provided through config
|
|
26
|
+
or set as an environment variable, assign it.
|
|
27
|
+
"""
|
|
28
|
+
import google.generativeai as genai
|
|
29
|
+
|
|
30
|
+
genai.configure(api_key=config["api_key"])
|
|
31
|
+
self.chat_model = genai.GenerativeModel(model_name)
|
|
32
|
+
else:
|
|
33
|
+
# Authenticate using VertexAI
|
|
34
|
+
import google.auth
|
|
35
|
+
import vertexai
|
|
36
|
+
from vertexai.generative_models import GenerativeModel
|
|
37
|
+
|
|
38
|
+
json_file_path = config.get(
|
|
39
|
+
"google_credentials"
|
|
40
|
+
) # Assuming the JSON file path is provided in the config
|
|
41
|
+
|
|
42
|
+
if not json_file_path or not os.path.exists(json_file_path):
|
|
43
|
+
raise FileNotFoundError(
|
|
44
|
+
f"JSON credentials file not found at: {json_file_path}"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
# Validate and set the JSON file path for GOOGLE_APPLICATION_CREDENTIALS
|
|
49
|
+
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = json_file_path
|
|
50
|
+
|
|
51
|
+
# Initialize VertexAI with the credentials
|
|
52
|
+
credentials, _ = google.auth.default()
|
|
53
|
+
vertexai.init(credentials=credentials)
|
|
54
|
+
self.chat_model = GenerativeModel(model_name)
|
|
55
|
+
except google.auth.exceptions.DefaultCredentialsError as e:
|
|
56
|
+
raise RuntimeError(f"Default credentials error: {e}")
|
|
57
|
+
except google.auth.exceptions.TransportError as e:
|
|
58
|
+
raise RuntimeError(f"Transport error during authentication: {e}")
|
|
59
|
+
except Exception as e:
|
|
60
|
+
raise RuntimeError(f"Failed to authenticate using JSON file: {e}")
|
|
61
|
+
|
|
62
|
+
def system_message(self, message: str) -> any:
|
|
63
|
+
return message
|
|
64
|
+
|
|
65
|
+
def user_message(self, message: str) -> any:
|
|
66
|
+
return message
|
|
67
|
+
|
|
68
|
+
def assistant_message(self, message: str) -> any:
|
|
69
|
+
return message
|
|
70
|
+
|
|
71
|
+
def submit_prompt(self, prompt, **kwargs) -> str:
|
|
72
|
+
response = self.chat_model.generate_content(
|
|
73
|
+
prompt,
|
|
74
|
+
generation_config={
|
|
75
|
+
"temperature": self.temperature,
|
|
76
|
+
},
|
|
77
|
+
)
|
|
78
|
+
return response.text
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .hf import Hf
|
vanna/legacy/hf/hf.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
|
3
|
+
|
|
4
|
+
from ..base import VannaBase
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Hf(VannaBase):
|
|
8
|
+
def __init__(self, config=None):
|
|
9
|
+
model_name_or_path = self.config.get(
|
|
10
|
+
"model_name_or_path", None
|
|
11
|
+
) # e.g. meta-llama/Meta-Llama-3-8B-Instruct or local path to the model checkpoint files
|
|
12
|
+
# list of quantization methods supported by transformers package: https://huggingface.co/docs/transformers/main/en/quantization/overview
|
|
13
|
+
quantization_config = self.config.get("quantization_config", None)
|
|
14
|
+
self.tokenizer = AutoTokenizer.from_pretrained(model_name_or_path)
|
|
15
|
+
self.model = AutoModelForCausalLM.from_pretrained(
|
|
16
|
+
model_name_or_path,
|
|
17
|
+
quantization_config=quantization_config,
|
|
18
|
+
device_map="auto",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
def system_message(self, message: str) -> any:
|
|
22
|
+
return {"role": "system", "content": message}
|
|
23
|
+
|
|
24
|
+
def user_message(self, message: str) -> any:
|
|
25
|
+
return {"role": "user", "content": message}
|
|
26
|
+
|
|
27
|
+
def assistant_message(self, message: str) -> any:
|
|
28
|
+
return {"role": "assistant", "content": message}
|
|
29
|
+
|
|
30
|
+
def extract_sql_query(self, text):
|
|
31
|
+
"""
|
|
32
|
+
Extracts the first SQL statement after the word 'select', ignoring case,
|
|
33
|
+
matches until the first semicolon, three backticks, or the end of the string,
|
|
34
|
+
and removes three backticks if they exist in the extracted string.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
- text (str): The string to search within for an SQL statement.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
- str: The first SQL statement found, with three backticks removed, or an empty string if no match is found.
|
|
41
|
+
"""
|
|
42
|
+
# Regular expression to find 'select' (ignoring case) and capture until ';', '```', or end of string
|
|
43
|
+
pattern = re.compile(r"select.*?(?:;|```|$)", re.IGNORECASE | re.DOTALL)
|
|
44
|
+
|
|
45
|
+
match = pattern.search(text)
|
|
46
|
+
if match:
|
|
47
|
+
# Remove three backticks from the matched string if they exist
|
|
48
|
+
return match.group(0).replace("```", "")
|
|
49
|
+
else:
|
|
50
|
+
return text
|
|
51
|
+
|
|
52
|
+
def generate_sql(self, question: str, **kwargs) -> str:
|
|
53
|
+
# Use the super generate_sql
|
|
54
|
+
sql = super().generate_sql(question, **kwargs)
|
|
55
|
+
|
|
56
|
+
# Replace "\_" with "_"
|
|
57
|
+
sql = sql.replace("\\_", "_")
|
|
58
|
+
|
|
59
|
+
sql = sql.replace("\\", "")
|
|
60
|
+
|
|
61
|
+
return self.extract_sql_query(sql)
|
|
62
|
+
|
|
63
|
+
def submit_prompt(self, prompt, **kwargs) -> str:
|
|
64
|
+
input_ids = self.tokenizer.apply_chat_template(
|
|
65
|
+
prompt, add_generation_prompt=True, return_tensors="pt"
|
|
66
|
+
).to(self.model.device)
|
|
67
|
+
|
|
68
|
+
outputs = self.model.generate(
|
|
69
|
+
input_ids,
|
|
70
|
+
max_new_tokens=512,
|
|
71
|
+
eos_token_id=self.tokenizer.eos_token_id,
|
|
72
|
+
do_sample=True,
|
|
73
|
+
temperature=1,
|
|
74
|
+
top_p=0.9,
|
|
75
|
+
)
|
|
76
|
+
response = outputs[0][input_ids.shape[-1] :]
|
|
77
|
+
response = self.tokenizer.decode(response, skip_special_tokens=True)
|
|
78
|
+
self.log(response)
|
|
79
|
+
|
|
80
|
+
return response
|
vanna/legacy/local.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from .chromadb.chromadb_vector import ChromaDB_VectorStore
|
|
2
|
+
from .openai.openai_chat import OpenAI_Chat
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class LocalContext_OpenAI(ChromaDB_VectorStore, OpenAI_Chat):
|
|
6
|
+
def __init__(self, config=None):
|
|
7
|
+
ChromaDB_VectorStore.__init__(self, config=config)
|
|
8
|
+
OpenAI_Chat.__init__(self, config=config)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .marqo import Marqo_VectorStore
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
import marqo
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
from ..base import VannaBase
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Marqo_VectorStore(VannaBase):
|
|
10
|
+
def __init__(self, config=None):
|
|
11
|
+
VannaBase.__init__(self, config=config)
|
|
12
|
+
|
|
13
|
+
if config is not None and "marqo_url" in config:
|
|
14
|
+
marqo_url = config["marqo_url"]
|
|
15
|
+
else:
|
|
16
|
+
marqo_url = "http://localhost:8882"
|
|
17
|
+
|
|
18
|
+
if config is not None and "marqo_model" in config:
|
|
19
|
+
marqo_model = config["marqo_model"]
|
|
20
|
+
else:
|
|
21
|
+
marqo_model = "hf/all_datasets_v4_MiniLM-L6"
|
|
22
|
+
|
|
23
|
+
self.mq = marqo.Client(url=marqo_url)
|
|
24
|
+
|
|
25
|
+
for index in ["vanna-sql", "vanna-ddl", "vanna-doc"]:
|
|
26
|
+
try:
|
|
27
|
+
self.mq.create_index(index, model=marqo_model)
|
|
28
|
+
except Exception as e:
|
|
29
|
+
print(e)
|
|
30
|
+
print(f"Marqo index {index} already exists")
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
def generate_embedding(self, data: str, **kwargs) -> list[float]:
|
|
34
|
+
# Marqo doesn't need to generate embeddings
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
def add_question_sql(self, question: str, sql: str, **kwargs) -> str:
|
|
38
|
+
id = str(uuid.uuid4()) + "-sql"
|
|
39
|
+
question_sql_dict = {
|
|
40
|
+
"question": question,
|
|
41
|
+
"sql": sql,
|
|
42
|
+
"_id": id,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
self.mq.index("vanna-sql").add_documents(
|
|
46
|
+
[question_sql_dict],
|
|
47
|
+
tensor_fields=["question", "sql"],
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
return id
|
|
51
|
+
|
|
52
|
+
def add_ddl(self, ddl: str, **kwargs) -> str:
|
|
53
|
+
id = str(uuid.uuid4()) + "-ddl"
|
|
54
|
+
ddl_dict = {
|
|
55
|
+
"ddl": ddl,
|
|
56
|
+
"_id": id,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
self.mq.index("vanna-ddl").add_documents(
|
|
60
|
+
[ddl_dict],
|
|
61
|
+
tensor_fields=["ddl"],
|
|
62
|
+
)
|
|
63
|
+
return id
|
|
64
|
+
|
|
65
|
+
def add_documentation(self, documentation: str, **kwargs) -> str:
|
|
66
|
+
id = str(uuid.uuid4()) + "-doc"
|
|
67
|
+
doc_dict = {
|
|
68
|
+
"doc": documentation,
|
|
69
|
+
"_id": id,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
self.mq.index("vanna-doc").add_documents(
|
|
73
|
+
[doc_dict],
|
|
74
|
+
tensor_fields=["doc"],
|
|
75
|
+
)
|
|
76
|
+
return id
|
|
77
|
+
|
|
78
|
+
def get_training_data(self, **kwargs) -> pd.DataFrame:
|
|
79
|
+
data = []
|
|
80
|
+
|
|
81
|
+
for hit in self.mq.index("vanna-doc").search("", limit=1000)["hits"]:
|
|
82
|
+
data.append(
|
|
83
|
+
{
|
|
84
|
+
"id": hit["_id"],
|
|
85
|
+
"training_data_type": "documentation",
|
|
86
|
+
"question": "",
|
|
87
|
+
"content": hit["doc"],
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
for hit in self.mq.index("vanna-ddl").search("", limit=1000)["hits"]:
|
|
92
|
+
data.append(
|
|
93
|
+
{
|
|
94
|
+
"id": hit["_id"],
|
|
95
|
+
"training_data_type": "ddl",
|
|
96
|
+
"question": "",
|
|
97
|
+
"content": hit["ddl"],
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
for hit in self.mq.index("vanna-sql").search("", limit=1000)["hits"]:
|
|
102
|
+
data.append(
|
|
103
|
+
{
|
|
104
|
+
"id": hit["_id"],
|
|
105
|
+
"training_data_type": "sql",
|
|
106
|
+
"question": hit["question"],
|
|
107
|
+
"content": hit["sql"],
|
|
108
|
+
}
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
df = pd.DataFrame(data)
|
|
112
|
+
|
|
113
|
+
return df
|
|
114
|
+
|
|
115
|
+
def remove_training_data(self, id: str, **kwargs) -> bool:
|
|
116
|
+
if id.endswith("-sql"):
|
|
117
|
+
self.mq.index("vanna-sql").delete_documents(ids=[id])
|
|
118
|
+
return True
|
|
119
|
+
elif id.endswith("-ddl"):
|
|
120
|
+
self.mq.index("vanna-ddl").delete_documents(ids=[id])
|
|
121
|
+
return True
|
|
122
|
+
elif id.endswith("-doc"):
|
|
123
|
+
self.mq.index("vanna-doc").delete_documents(ids=[id])
|
|
124
|
+
return True
|
|
125
|
+
else:
|
|
126
|
+
return False
|
|
127
|
+
|
|
128
|
+
# Static method to extract the documents from the results of a query
|
|
129
|
+
@staticmethod
|
|
130
|
+
def _extract_documents(data) -> list:
|
|
131
|
+
# Check if 'hits' key is in the dictionary and if it's a list
|
|
132
|
+
if "hits" in data and isinstance(data["hits"], list):
|
|
133
|
+
# Iterate over each item in 'hits'
|
|
134
|
+
|
|
135
|
+
if len(data["hits"]) == 0:
|
|
136
|
+
return []
|
|
137
|
+
|
|
138
|
+
# If there is a "doc" key, return the value of that key
|
|
139
|
+
if "doc" in data["hits"][0]:
|
|
140
|
+
return [hit["doc"] for hit in data["hits"]]
|
|
141
|
+
|
|
142
|
+
# If there is a "ddl" key, return the value of that key
|
|
143
|
+
if "ddl" in data["hits"][0]:
|
|
144
|
+
return [hit["ddl"] for hit in data["hits"]]
|
|
145
|
+
|
|
146
|
+
# Otherwise return the entire hit
|
|
147
|
+
return [
|
|
148
|
+
{key: value for key, value in hit.items() if not key.startswith("_")}
|
|
149
|
+
for hit in data["hits"]
|
|
150
|
+
]
|
|
151
|
+
else:
|
|
152
|
+
# Return an empty list if 'hits' is not found or not a list
|
|
153
|
+
return []
|
|
154
|
+
|
|
155
|
+
def get_similar_question_sql(self, question: str, **kwargs) -> list:
|
|
156
|
+
return Marqo_VectorStore._extract_documents(
|
|
157
|
+
self.mq.index("vanna-sql").search(question)
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
def get_related_ddl(self, question: str, **kwargs) -> list:
|
|
161
|
+
return Marqo_VectorStore._extract_documents(
|
|
162
|
+
self.mq.index("vanna-ddl").search(question)
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
def get_related_documentation(self, question: str, **kwargs) -> list:
|
|
166
|
+
return Marqo_VectorStore._extract_documents(
|
|
167
|
+
self.mq.index("vanna-doc").search(question)
|
|
168
|
+
)
|