أهلاً بك في الدرس الثاني من هذه الوحدة!
في الدرس السابق، استكشفنا لماذا يحتاج وكيلنا الذكي إلى ذاكرة طويلة المدى، وتوصلنا إلى أن الملفات النصية البسيطة ليست كافية لتخزين المعلومات بشكل منظم وقابل للبحث.
اليوم، سننتقل من النظرية إلى التطبيق العملي لتحقيق هدفنا التعليمي التالي: إعداد قاعدة بيانات بسيطة (مثل SQLite) لتخزين واسترجاع البيانات. سنضع حجر الأساس لذاكرة وكيلنا طويلة المدى، وسنتعلم كيف "نتحدث" إلى قاعدة البيانات باستخدام لغة بايثون لتخزين واسترجاع المعلومات بكفاءة.
1. ما هي قاعدة البيانات؟ ولماذا SQLite؟
قبل أن نكتب أي كود، دعنا نوضح بعض المفاهيم الأساسية.
- قاعدة البيانات (Database): هي ببساطة مجموعة منظمة من البيانات. تخيلها كخزانة ملفات رقمية فائقة التنظيم. بدلاً من تخزين المعلومات في ملف نصي واحد فوضوي، تسمح لنا قاعدة البيانات بتخزينها في جداول (Tables).
- الجدول (Table): يشبه جدول البيانات (Spreadsheet) في Excel. يتكون من أعمدة (Columns) تحدد نوع المعلومة (مثل:
id,content)، وصفوف (Rows) تمثل كل سجل أو معلومة مستقلة. - SQL (Structured Query Language): هي اللغة القياسية التي نستخدمها للتواصل مع قواعد البيانات. من خلالها، نرسل أوامر مثل "أنشئ جدولاً جديداً" أو "أعطني كل الذكريات التي حدثت بالأمس".
- SQLite: هي نوع محدد من أنظمة إدارة قواعد البيانات. ميزتها الكبرى أنها خفيفة وبدون خادم (Serverless)؛ فهي تخزن قاعدة البيانات بأكملها في ملف واحد على جهازك. والأهم من ذلك، أنها مدمجة في مكتبة بايثون القياسية، مما يعني أننا لا نحتاج إلى تثبيت أي شيء لبدء استخدامها.
لمزيد من التوضيح حول هذه المفاهيم، شاهد المقدمة التالية.
تعلم قواعد البيانات في فيديو واحد | كورس قواعد البيانات بالبايثون python sqlite3
يقدم هذا المقطع من قناة Abdelrahman Gamal شرحاً تمهيدياً ممتازاً يوضح الفرق بين لغة SQL وأنظمة إدارة قواعد البيانات مثل SQLite.
شاهد من بداية الفيديو حتى الدقيقة 2:13. ركز على فهم أن SQL هي اللغة، بينما SQLite هي الأداة التي نستخدمها في بايثون لتنفيذ أوامر هذه اللغة.
2. العمليات الأساسية على قواعد البيانات (CRUD)
معظم التفاعلات مع أي قاعدة بيانات تندرج تحت أربع عمليات أساسية تُعرف اختصاراً بـ CRUD:
- Create (إنشاء): إضافة بيانات جديدة (أو صفوف جديدة) إلى جدول. في SQL، نستخدم أمر
INSERT. - Read (قراءة): استرجاع البيانات من جدول. في SQL، نستخدم أمر
SELECT. - Update (تحديث): تعديل البيانات الموجودة بالفعل في جدول. في SQL، نستخدم أمر
UPDATE. - Delete (حذف): إزالة البيانات من جدول. في SQL، نستخدم أمر
DELETE.

3. إعداد قاعدة بيانات الذاكرة في بايثون
حان الوقت الآن لكتابة الكود. سنقوم بأربع خطوات أساسية:
- الاتصال بقاعدة البيانات.
- إنشاء جدول لتخزين الذكريات.
- إضافة بعض الذكريات إلى الجدول.
- قراءة الذكريات من الجدول.
الخطوة الأولى: الاتصال بقاعدة البيانات وإنشاء المؤشر (Cursor)
أولاً، نحتاج إلى استيراد مكتبة sqlite3 والاتصال بملف قاعدة البيانات. إذا لم يكن الملف موجوداً، فسيتم إنشاؤه تلقائياً.
import sqlite3
# الاتصال بقاعدة البيانات (سيتم إنشاء ملف 'agent_memory.db' إذا لم يكن موجوداً)
conn = sqlite3.connect('agent_memory.db')
# إنشاء كائن 'المؤشر' (cursor) الذي يسمح لنا بتنفيذ أوامر SQL
cursor = conn.cursor()
print("تم الاتصال بقاعدة البيانات بنجاح.")
# ... (سنكتب بقية الكود هنا) ...
# في نهاية البرنامج، من المهم جداً إغلاق الاتصال
conn.close()
print("تم إغلاق الاتصال.")
conn: يمثل الاتصال بقاعدة البيانات.cursor: هو الوسيط الذي نستخدمه لإرسال الأوامر واستقبال النتائج.
شاهد هذا المقطع لترى تطبيقاً عملياً لعملية الاتصال.
تعلم قواعد البيانات في فيديو واحد | كورس قواعد البيانات بالبايثون python sqlite3
يشرح هذا المقطع كيفية استخدام sqlite3.connect() لإنشاء ملف قاعدة البيانات والاتصال به، مع التأكيد على أهمية إغلاق الاتصال.
شاهد من الدقيقة 2:13 إلى 4:19.
الخطوة الثانية: إنشاء جدول الذكريات (CREATE TABLE)
الآن بعد أن اتصلنا بقاعدة البيانات، نحتاج إلى إنشاء هيكل لتخزين بياناتنا. سنقوم بإنشاء جدول اسمه memories يحتوي على ثلاثة أعمدة:
id: رقم فريد لكل ذكرى.content: محتوى الذاكرة النصي.timestamp: وقت إنشاء الذاكرة.

سنستخدم الأمر CREATE TABLE في SQL.
# أمر SQL لإنشاء جدول
# IF NOT EXISTS: تمنع حدوث خطأ إذا كان الجدول موجوداً بالفعل
# INTEGER PRIMARY KEY AUTOINCREMENT: يضمن أن كل صف جديد سيحصل على id فريد تلقائياً
# TEXT NOT NULL: يعني أن حقل المحتوى لا يمكن أن يكون فارغاً
# TIMESTAMP DEFAULT CURRENT_TIMESTAMP: يسجل وقت إنشاء الصف تلقائياً
create_table_query = """
CREATE TABLE IF NOT EXISTS memories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
content TEXT NOT NULL,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);
"""
# تنفيذ الأمر باستخدام المؤشر
cursor.execute(create_table_query)
print("تم التأكد من وجود جدول 'memories'.")
هذا المقطع يشرح بالتفصيل كيفية تعريف الجداول والأعمدة وأنواع البيانات.
تعلم قواعد البيانات في فيديو واحد | كورس قواعد البيانات بالبايثون python sqlite3
هذا الجزء من الفيديو يغطي بالتفصيل كيفية استخدام أمر CREATE TABLE لتعريف بنية الجدول، وتحديد أسماء الأعمدة وأنواع بياناتها مثل TEXT و INTEGER.
شاهد من الدقيقة 4:19 إلى 10:52. ركز على فهم بناء جملة CREATE TABLE وكيفية تحديد الأعمدة وأنواعها.
الخطوة الثالثة: تخزين الذكريات (INSERT)
الآن لنضف بعض البيانات إلى جدولنا باستخدام الأمر INSERT INTO. من أفضل الممارسات الأمنية استخدام علامات الاستفهام (?) كعناصر نائبة للقيم، ثم تمرير القيم في execute لتجنب هجمات "حقن SQL".
# بيانات الذكريات التي نريد إضافتها
memories_to_add = [
("تذكر أن المستخدم يفضل الملخصات القصيرة."),
("تمت مناقشة فكرة مشروع جديد حول تحليل البيانات اليوم.")
]
# أمر الإضافة مع استخدام العناصر النائبة
insert_query = "INSERT INTO memories (content) VALUES (?);"
# إضافة الذكريات واحدة تلو الأخرى
for memory in memories_to_add:
cursor.execute(insert_query, (memory,)) # لاحظ أن القيم يجب أن تكون داخل tuple
print(f"تم إضافة {len(memories_to_add)} ذكريات جديدة.")
# لحفظ التغييرات بشكل دائم في ملف قاعدة البيانات، يجب أن نقوم بعمل 'commit'
conn.commit()
شاهد هذا المقطع لتفهم كيفية إضافة البيانات.
تعلم قواعد البيانات في فيديو واحد | كورس قواعد البيانات بالبايثون python sqlite3
يشرح هذا المقطع كيفية استخدام INSERT INTO لإضافة صف واحد من البيانات إلى الجدول.
شاهد من الدقيقة 10:52 إلى 15:03. انتبه إلى كيفية تحديد الجدول والأعمدة، ثم تمرير القيم.
الخطوة الرابعة: استرجاع الذكريات (SELECT)
أخيراً، لنسترجع البيانات التي قمنا بتخزينها باستخدام الأمر SELECT.
# استرجاع كل الأعمدة (*) من جدول الذكريات
select_query = "SELECT id, content, timestamp FROM memories;"
print("\n--- الذكريات المخزنة ---")
# تنفيذ الاستعلام والمرور على النتائج
for row in cursor.execute(select_query):
print(f"ID: {row[0]}, Memory: {row[1]}, Time: {row[2]}")
print("------------------------")
هذا المقطع يوضح كيفية استرجاع البيانات وعرضها.
تعلم قواعد البيانات في فيديو واحد | كورس قواعد البيانات بالبايثون python sqlite3
يغطي هذا المقطع أساسيات استرجاع البيانات باستخدام أمر SELECT. يوضح كيفية اختيار كل الأعمدة (*) أو أعمدة محددة، وكيفية المرور على النتائج لعرضها.
شاهد من الدقيقة 19:03 إلى 26:51. ركز على كيفية استخدام SELECT واستخدام حلقة for لقراءة الصفوف الناتجة.
4. الكود الكامل
هذا هو الكود الكامل الذي يجمع كل الخطوات معاً. يمكنك تشغيله في ملف بايثون واحد لرؤية النتيجة.
import sqlite3
# --- 1. الاتصال وإنشاء المؤشر ---
conn = sqlite3.connect('agent_memory.db')
cursor = conn.cursor()
print("تم الاتصال بقاعدة البيانات بنجاح.")
# --- 2. إنشاء الجدول ---
create_table_query = """
CREATE TABLE IF NOT EXISTS memories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
content TEXT NOT NULL,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);
"""
cursor.execute(create_table_query)
print("تم التأكد من وجود جدول 'memories'.")
# --- 3. إضافة البيانات ---
# (يمكنك إضافة المزيد من الذكريات هنا في كل مرة تشغل فيها الكود)
new_memory_content = "المستخدم سأل عن الطقس في الرياض."
insert_query = "INSERT INTO memories (content) VALUES (?);"
cursor.execute(insert_query, (new_memory_content,))
print("تمت إضافة ذاكرة جديدة.")
# حفظ التغييرات (مهم جداً!)
conn.commit()
# --- 4. استرجاع وعرض البيانات ---
select_query = "SELECT id, content, timestamp FROM memories;"
print("\n--- كل الذكريات المخزنة ---")
all_memories = cursor.execute(select_query).fetchall() # .fetchall() لجلب كل النتائج مرة واحدة
for row in all_memories:
print(f" ID: {row[0]}, Memory: {row[1]}, Time: {row[2]}")
print("--------------------------")
# --- 5. إغلاق الاتصال ---
conn.close()
print("تم إغلاق الاتصال.")
اختبر فهمك!
بناءً على الكود الكامل أعلاه، قم بتعديل البرنامج ليقوم بما يلي:
- أضف عموداً جديداً إلى جدول
memoriesاسمهtypeمن نوعTEXT. هذا العمود سيحدد نوع الذاكرة (مثلاً: "حقيقة"، "تجربة"). - عند إضافة ذاكرة جديدة، أضف نوعها أيضاً. على سبيل المثال، الذاكرة "المستخدم سأل عن الطقس في الرياض" يمكن أن تكون من نوع "تجربة".
- عند عرض الذكريات، قم بعرض النوع أيضاً.
تلميح: ستحتاج إلى تعديل أمر CREATE TABLE، وأمر INSERT INTO، وأمر SELECT، بالإضافة إلى جملة الطباعة النهائية. قد تحتاج إلى حذف ملف agent_memory.db القديم أولاً ليتم إنشاء الجدول بالهيكل الجديد.
اظهر الإجابة
import sqlite3
import os
# حذف قاعدة البيانات القديمة إن وجدت للبدء من جديد
if os.path.exists('agent_memory.db'):
os.remove('agent_memory.db')
# 1. الاتصال
conn = sqlite3.connect('agent_memory.db')
cursor = conn.cursor()
# 2. إنشاء الجدول (مع العمود الجديد 'type')
create_table_query = """
CREATE TABLE IF NOT EXISTS memories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
content TEXT NOT NULL,
type TEXT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);
"""
cursor.execute(create_table_query)
# 3. إضافة البيانات (مع تحديد النوع)
new_memory_content = "المستخدم سأل عن الطقس في الرياض."
new_memory_type = "تجربة"
insert_query = "INSERT INTO memories (content, type) VALUES (?, ?);"
cursor.execute(insert_query, (new_memory_content, new_memory_type))
conn.commit()
# 4. استرجاع وعرض البيانات (مع عرض النوع)
select_query = "SELECT id, content, type, timestamp FROM memories;"
print("\n--- كل الذكريات المخزنة ---")
all_memories = cursor.execute(select_query).fetchall()
for row in all_memories:
# row[0]=id, row[1]=content, row[2]=type, row[3]=timestamp
print(f" ID: {row[0]}, Type: {row[2]}, Memory: {row[1]}, Time: {row[3]}")
print("--------------------------")
# 5. إغلاق الاتصال
conn.close()
خلاصة الدرس
في هذا الدرس، قمنا بأول خطوة عملية نحو بناء ذاكرة قوية لوكيلنا.
أهم النقاط التي تعلمناها:
- SQLite هي قاعدة بيانات بسيطة وقوية ومدمجة في بايثون، ومثالية لبناء ذاكرة الوكيل.
- الخطوات الأساسية للتعامل مع قاعدة البيانات هي: الاتصال (
connect)، إنشاء مؤشر (cursor)، تنفيذ الأوامر (execute)، حفظ التغييرات (commit)، وإغلاق الاتصال (close). - الأوامر الأساسية في لغة SQL التي استخدمناها هي:
CREATE TABLEلإنشاء هيكل البيانات.INSERT INTOلإضافة بيانات جديدة.SELECTلاسترجاع البيانات.
ماذا بعد؟
أنت الآن تملك الأساس التقني لتخزين واسترجاع البيانات بشكل منظم. في الدرس القادم، سنقوم بدمج هذه المعرفة في وكيلنا. سنتعلم كيفية "تصميم دالة لحفظ المعلومات المهمة (مثل ملخصات المحادثات) في قاعدة البيانات". سنبني "أداة" جديدة تسمح للوكيل باتخاذ قرار حفظ معلومة ما في ذاكرته طويلة المدى بشكل مستقل.