كتابة SQL باستخدام Vanna و Milvus
Vanna هو إطار عمل مفتوح المصدر من Python RAG (التوليد المعزز للاسترجاع) لتوليد SQL والوظائف ذات الصلة. Milvus هي قاعدة البيانات المتجهة مفتوحة المصدر الأكثر تقدمًا في العالم، وهي مصممة لتشغيل تطبيقات البحث عن التشابه المضمنة وتطبيقات الذكاء الاصطناعي.
يعمل Vanna في خطوتين سهلتين - تدريب "نموذج" RAG على بياناتك، ثم طرح الأسئلة التي ستُعيد استعلامات SQL التي يمكن إعدادها للتشغيل على قاعدة بياناتك. يوضح هذا الدليل كيفية استخدام Vanna لإنشاء استعلامات SQL وتنفيذها استنادًا إلى بياناتك المخزنة في قاعدة البيانات.
المتطلبات الأساسية
قبل تشغيل هذا الدليل، تأكد من تثبيت التبعيات التالية:
$ pip install "vanna[milvus,openai]"
إذا كنت تستخدم Google Colab، لتمكين التبعيات المثبتة للتو، قد تحتاج إلى إعادة تشغيل وقت التشغيل (انقر على قائمة "وقت التشغيل" في أعلى الشاشة، وحدد "إعادة تشغيل الجلسة" من القائمة المنسدلة).
وتحتاج إلى تعيين OPENAI_API_KEY
في متغيرات البيئة الخاصة بك. يمكنك الحصول على مفتاح API من OpenAI.
import os
os.environ["OPENAI_API_KEY"] = "sk-***********"
إعداد البيانات
أولاً، نحن بحاجة إلى أن نرث من فئتي Milvus_VectorStore
و OpenAI_Chat
من فانا وتعريف فئة جديدة VannaMilvus
تجمع بين القدرات من كليهما.
from pymilvus import MilvusClient, model
from vanna.milvus import Milvus_VectorStore
from vanna.openai import OpenAI_Chat
class VannaMilvus(Milvus_VectorStore, OpenAI_Chat):
def __init__(self, config=None):
Milvus_VectorStore.__init__(self, config=config)
OpenAI_Chat.__init__(self, config=config)
نقوم بتهيئة فئة VannaMilvus
بمعلمات التكوين اللازمة. نستخدم مثيل milvus_client
لتخزين التضمينات و model.DefaultEmbeddingFunction()
التي تمت تهيئتها من نموذج ميلفوس لتوليد التضمينات.C
أما بالنسبة لحجة MilvusClient
:
- يعد تعيين
uri
كملف محلي، على سبيل المثال./milvus.db
، هو الطريقة الأكثر ملاءمة، حيث يستخدم تلقائيًا ميلفوس لايت لتخزين جميع البيانات في هذا الملف. - إذا كان لديك حجم كبير من البيانات، يمكنك إعداد خادم Milvus أكثر أداءً على docker أو kubernetes. في هذا الإعداد، يُرجى استخدام الخادم uri، على سبيل المثال
http://localhost:19530
، كـuri
. - إذا كنت ترغب في استخدام Zilliz Cloud، الخدمة السحابية المدارة بالكامل لـ Milvus، اضبط
uri
وtoken
، والتي تتوافق مع نقطة النهاية العامة ومفتاح Api في Zilliz Cloud.
milvus_uri = "./milvus_vanna.db"
milvus_client = MilvusClient(uri=milvus_uri)
vn_milvus = VannaMilvus(
config={
"api_key": os.getenv("OPENAI_API_KEY"),
"model": "gpt-3.5-turbo",
"milvus_client": milvus_client,
"embedding_function": model.DefaultEmbeddingFunction(),
"n_results": 2, # The number of results to return from Milvus semantic search.
}
)
هذا مثال بسيط مع عينة قليلة فقط من البيانات، لذلك قمنا بتعيين n_results
إلى 2 للتأكد من أننا نبحث عن أعلى نتيجتين متشابهتين. من الناحية العملية، يجب عليك تعيين n_results
إلى قيمة أعلى عند التعامل مع مجموعة بيانات تدريبية أكبر.
سنستخدم عينة من قاعدة بيانات SQLite مع عدد قليل من الجداول التي تحتوي على بعض البيانات النموذجية.
import sqlite3
sqlite_path = "./my-database.sqlite"
sql_connect = sqlite3.connect(sqlite_path)
c = sql_connect.cursor()
init_sqls = """
CREATE TABLE IF NOT EXISTS Customer (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Company TEXT NOT NULL,
City TEXT NOT NULL,
Phone TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS Company (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Industry TEXT NOT NULL,
Location TEXT NOT NULL,
EmployeeCount INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS User (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Username TEXT NOT NULL UNIQUE,
Email TEXT NOT NULL UNIQUE
);
INSERT INTO Customer (Name, Company, City, Phone)
VALUES ('John Doe', 'ABC Corp', 'New York', '123-456-7890');
INSERT INTO Customer (Name, Company, City, Phone)
VALUES ('Jane Smith', 'XYZ Inc', 'Los Angeles', '098-765-4321');
INSERT INTO Company (Name, Industry, Location, EmployeeCount)
VALUES ('ABC Corp', 'cutting-edge technology', 'New York', 100);
INSERT INTO User (Username, Email)
VALUES ('johndoe123', 'johndoe123@example.com');
"""
for sql in init_sqls.split(";"):
c.execute(sql)
sql_connect.commit()
# Connect to the SQLite database
vn_milvus.connect_to_sqlite(sqlite_path)
تدريب مع البيانات
يمكننا تدريب النموذج على بيانات DDL لقاعدة بيانات SQLite. نحصل على بيانات الـ DDL ونغذي بها الدالة train
.
# If there exists training data, we should remove it before training.
existing_training_data = vn_milvus.get_training_data()
if len(existing_training_data) > 0:
for _, training_data in existing_training_data.iterrows():
vn_milvus.remove_training_data(training_data["id"])
# Get the DDL of the SQLite database
df_ddl = vn_milvus.run_sql("SELECT type, sql FROM sqlite_master WHERE sql is not null")
# Train the model on the DDL data
for ddl in df_ddl["sql"].to_list():
vn_milvus.train(ddl=ddl)
Adding ddl: CREATE TABLE Customer (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Company TEXT NOT NULL,
City TEXT NOT NULL,
Phone TEXT NOT NULL
)
Adding ddl: CREATE TABLE sqlite_sequence(name,seq)
Adding ddl: CREATE TABLE Company (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Industry TEXT NOT NULL,
Location TEXT NOT NULL,
EmployeeCount INTEGER NOT NULL
)
Adding ddl: CREATE TABLE User (
ID INTEGER PRIMARY KEY AUTOINCREMENT,
Username TEXT NOT NULL UNIQUE,
Email TEXT NOT NULL UNIQUE
)
إلى جانب التدريب على بيانات DDL، يمكننا أيضًا التدريب على الوثائق واستعلامات SQL لقاعدة البيانات.
# Add documentation about your business terminology or definitions.
vn_milvus.train(
documentation="ABC Corp specializes in cutting-edge technology solutions and innovation."
)
vn_milvus.train(
documentation="XYZ Inc is a global leader in manufacturing and supply chain management."
)
# You can also add SQL queries to your training data.
vn_milvus.train(sql="SELECT * FROM Customer WHERE Name = 'John Doe'")
Adding documentation....
Adding documentation....
Using model gpt-3.5-turbo for 65.0 tokens (approx)
Question generated with sql: What are the details of the customer named John Doe?
Adding SQL...
'595b185c-e6ad-47b0-98fd-0e93ef9b6a0a-sql'
دعونا نلقي نظرة على بيانات التدريب.
training_data = vn_milvus.get_training_data()
training_data
# | المعرف | السؤال | المحتوى |
---|---|---|---|
0 | 595b185c-e6ad-47b0-98fd-0e93ef9b6a0a-sql | ما هي تفاصيل العميل المسمى Joh.... | حدد * من العميل حيث الاسم = "مجهول الهوية |
0 | 25f4956c-e370-4097-994f-996f22d145fa-ddl | لا يوجد | إنشاء جدول إنشاء جدول الشركة (\nالمعرف INTEGER PRIMARY... |
1 | b95ecc66-f65b-49dc-a9f1-c1842ad230ff-ddl | لا يوجد | إنشاء جدول إنشاء جدول العميل (المعرف INTEGER PRIMAR... |
2 | fcc73d15-30a5-4421-9d73-b8c3b0ed5305-ddl | لا يوجد | إنشاء جدول sqlite_sequence (الاسم، تسلسل) |
3 | feae618c-5910-4f6f-8b4b-6cc3e03aec06-ddl | لا يوجد | إنشاء جدول إنشاء مستخدم (\nالمعرف INTEGER PRIMARY KE.... |
0 | 79a48db1-ba1f-4fd5-be99-74f2ca2eaeeb-doc | لا يوجد | شركة XYZ Inc هي شركة رائدة عالميًا في مجال التصنيع... |
1 | 9f9df1b8-ae62-4823-ad28-d7e0f2d1f4c0-doc | لا يوجد | تتخصص شركة ABC Corp في مجال التكنولوجيا المتطورة... |
إنشاء SQLs وتنفيذها
كما تدربنا على بيانات DDL، أصبحت بنية الجدول متاحة الآن لإنشاء استعلامات SQL.
لنجرب سؤالًا بسيطًا.
sql = vn_milvus.generate_sql("what is the phone number of John Doe?")
vn_milvus.run_sql(sql)
SQL Prompt: [{'role': 'system', 'content': "You are a SQLite expert. Please help to generate a SQL query to answer the question. Your response should ONLY be based on the given context and follow the response guidelines and format instructions. \n===Tables \nCREATE TABLE Customer (\n ID INTEGER PRIMARY KEY AUTOINCREMENT,\n Name TEXT NOT NULL,\n Company TEXT NOT NULL,\n City TEXT NOT NULL,\n Phone TEXT NOT NULL\n)\n\nCREATE TABLE User (\n ID INTEGER PRIMARY KEY AUTOINCREMENT,\n Username TEXT NOT NULL UNIQUE,\n Email TEXT NOT NULL UNIQUE\n)\n\n\n===Additional Context \n\nABC Corp specializes in cutting-edge technology solutions and innovation.\n\nXYZ Inc is a global leader in manufacturing and supply chain management.\n\n===Response Guidelines \n1. If the provided context is sufficient, please generate a valid SQL query without any explanations for the question. \n2. If the provided context is almost sufficient but requires knowledge of a specific string in a particular column, please generate an intermediate SQL query to find the distinct strings in that column. Prepend the query with a comment saying intermediate_sql \n3. If the provided context is insufficient, please explain why it can't be generated. \n4. Please use the most relevant table(s). \n5. If the question has been asked and answered before, please repeat the answer exactly as it was given before. \n"}, {'role': 'user', 'content': 'What are the details of the customer named John Doe?'}, {'role': 'assistant', 'content': "SELECT * FROM Customer WHERE Name = 'John Doe'"}, {'role': 'user', 'content': 'what is the phone number of John Doe?'}]
Using model gpt-3.5-turbo for 367.25 tokens (approx)
LLM Response: SELECT Phone FROM Customer WHERE Name = 'John Doe'
# | الهاتف |
---|---|
0 | 123-456-7890 |
هنا سؤال أكثر تعقيداً. معلومات اسم شركة التصنيع موجودة في بيانات المستند، وهي معلومات أساسية. سيقوم استعلام SQL الذي تم إنشاؤه باسترداد معلومات العميل بناءً على اسم شركة التصنيع المحددة.
sql = vn_milvus.generate_sql("which customer works for a manufacturing corporation?")
vn_milvus.run_sql(sql)
SQL Prompt: [{'role': 'system', 'content': "You are a SQLite expert. Please help to generate a SQL query to answer the question. Your response should ONLY be based on the given context and follow the response guidelines and format instructions. \n===Tables \nCREATE TABLE Company (\n ID INTEGER PRIMARY KEY AUTOINCREMENT,\n Name TEXT NOT NULL,\n Industry TEXT NOT NULL,\n Location TEXT NOT NULL,\n EmployeeCount INTEGER NOT NULL\n)\n\nCREATE TABLE Customer (\n ID INTEGER PRIMARY KEY AUTOINCREMENT,\n Name TEXT NOT NULL,\n Company TEXT NOT NULL,\n City TEXT NOT NULL,\n Phone TEXT NOT NULL\n)\n\n\n===Additional Context \n\nXYZ Inc is a global leader in manufacturing and supply chain management.\n\nABC Corp specializes in cutting-edge technology solutions and innovation.\n\n===Response Guidelines \n1. If the provided context is sufficient, please generate a valid SQL query without any explanations for the question. \n2. If the provided context is almost sufficient but requires knowledge of a specific string in a particular column, please generate an intermediate SQL query to find the distinct strings in that column. Prepend the query with a comment saying intermediate_sql \n3. If the provided context is insufficient, please explain why it can't be generated. \n4. Please use the most relevant table(s). \n5. If the question has been asked and answered before, please repeat the answer exactly as it was given before. \n"}, {'role': 'user', 'content': 'What are the details of the customer named John Doe?'}, {'role': 'assistant', 'content': "SELECT * FROM Customer WHERE Name = 'John Doe'"}, {'role': 'user', 'content': 'which customer works for a manufacturing corporation?'}]
Using model gpt-3.5-turbo for 384.25 tokens (approx)
LLM Response: SELECT *
FROM Customer
WHERE Company = 'XYZ Inc'
# | المعرف | الاسم | الشركة | المدينة | رقم الهاتف |
---|---|---|---|---|---|
0 | 2 | جين سميث | شركة XYZ | لوس أنجلوس | 098-765-4321 |
افصل عن SQLite و Milvus وقم بإزالتها لتحرير الموارد.
sql_connect.close()
milvus_client.close()
os.remove(sqlite_path)
if os.path.exists(milvus_uri):
os.remove(milvus_uri)