
مختبر أبحاث أمني: إعادة إنتاج CVE-2025-52467 (تنفيذ كود في سير عمل pull_request_target في pgai / استخراج GITHUB_TOKEN) — لقطة من timescale/pgai
أداة بحث آلية — ليست المشروع الأصلي.
هذا المستودع عبارة عن بيئة مختبرية مؤقتة أُنشئت بواسطة نظام آلي لأطروحة ماجستير في جامعة لافال حول إعادة إنتاج ثغرات أمنية موثقة في سير عمل GitHub Actions. وهو لقطة حرفية من
timescale/pgaiعند الالتزام2a209b058c60823b57e8b7775b10244ff340eb8b(2025-05-14)، مُعاد توزيعه بموجب ترخيص المشروع نفسه، الذي يُدرج ملفه دون تغيير في هذه اللقطة.المشروع الأصلي ليس طرفًا فيه، ولا يُستهدف أبدًا، والثغرة المدروسة هنا معلنة بالفعل. كل سر ومتغير في هذا المستودع هو قيمة وهمية مولّدة عشوائيًا — لا توجد أي بيانات اعتماد حقيقية. مراجع الإجراءات وصور المشغّل مثبتة على ما حُلّت إليه في 2025-05-14؛ راجع
pinning.mdفي مخرجات النظام الآلي لكل تغيير أُجري على اللقطة.الأسئلة أو الاعتراضات: [email protected]
مكتبة Python تحوّل PostgreSQL إلى محرك استرجاع قوي وجاهز للإنتاج لتطبيقات RAG والتطبيقات الوكيلة.
🔄 إنشاء ومزامنة تلقائية للتضمينات المتجهة (vector embeddings) من بيانات PostgreSQL ومستندات S3. تتحدّث التضمينات تلقائيًا مع تغيّر البيانات.
🔍 بحث متجه ودلالي قوي باستخدام pgvector وpgvectorscale.
🛡️ جاهز للإنتاج فورًا: يدعم المعالجة المجمّعة لتوليد تضمينات فعّالة، مع معالجة مدمجة لأعطال النماذج، وحدود المعدل، وارتفاعات زمن الاستجابة.
🐘 يعمل مع أي قاعدة بيانات PostgreSQL، بما في ذلك Timescale Cloud وAmazon RDS وSupabase والمزيد.
البنية الأساسية: يتكوّن النظام من تطبيق تكتبه أنت، وقاعدة بيانات PostgreSQL، وعمال توجيه متجهات (vectorizer workers) عديمي الحالة. يحدّد التطبيق إعداد توجيه المتجهات لتضمين البيانات من مصادر مثل PostgreSQL أو S3. يقرأ العمال هذا الإعداد، ويعالجون قائمة البيانات إلى تضمينات ونصوص مجزأة، ثم يكتبون النتائج مرة أخرى. يستعلم التطبيق بعد ذلك عن هذه البيانات لتشغيل RAG والبحث الدلالي.
تكمن القوة الرئيسية لهذه البنية في مرونتها: تعديلات البيانات التي يجريها التطبيق منفصلة عن عملية التضمين، ما يضمن ألا تؤثر الأعطال في خدمة التضمين على عمليات البيانات الأساسية.
أولًا، ثبّت حزمة pgai.``` pip install pgai
ثم، قم بتثبيت مكونات قاعدة بيانات pgai. يمكنك القيام بذلك من الطرفية باستخدام CLI أو في كود تطبيق Python الخاص بك باستخدام حزمة pgai الخاصة بـ Python.```
# from the cli
pgai install -d <database-url>
# or from the python package, often done as part of your application setup
import pgai
pgai.install(DB_URL)
يوضح هذا الدليل السريع كيف يتيح pgai Vectorizer البحث الدلالي وRAG عبر بيانات PostgreSQL من خلال إنشاء ومزامنة التضمينات تلقائيًا مع تغيّر البيانات.
يكمن "العامل السري" الرئيسي لـ pgai Vectorizer في نهجه التصريحي لتوليد التضمينات. ببساطة، قم بتعريف خط الأنابيب الخاص بك ودع Vectorizer يتولى التعقيد التشغيلي للحفاظ على مزامنة التضمينات، حتى عندما تكون نقاط نهاية التضمين غير موثوقة. يمكنك تعريف نسخة بسيطة من خط الأنابيب كما يلي:```sql CREATE TABLE IF NOT EXISTS wiki ( id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, url TEXT NOT NULL, title TEXT NOT NULL, text TEXT NOT NULL )
SELECT ai.create_vectorizer( 'wiki'::regclass, loading => ai.loading_column(column_name=>'text'), destination => ai.destination_table(target_table=>'wiki_embedding_storage'), embedding => ai.embedding_openai(model=>'text-embedding-ada-002', dimensions=>'1536') )
سوف يقوم المُوجّه المتجهي (Vectorizer) تلقائيًا بإنشاء التضمينات (embeddings) لجميع الصفوف في
جدول `wiki`، والأهم من ذلك، سيبقي التضمينات متزامنة مع
البيانات الأساسية أثناء تغيّرها. **فكّر في الأمر تقريبًا كأنك تُعلن عن فهرس (index)** على
جدول `wiki`، ولكن بدلاً من أن تدير قاعدة البيانات بنية الفهرس
بالنيابة عنك، فإن المُوجّه المتجهي هو من يدير التضمينات.
## تشغيل البدء السريع
**المتطلبات الأساسية:**
- قاعدة بيانات PostgreSQL ([تعليمات docker](https://docs.timescale.com/self-hosted/latest/install/installation-docker/)).
- مفتاح API من OpenAI (نستخدم openai للتضمين في البدء السريع، ولكن يمكنك استخدام [موفّرين متعددين](#supported-embedding-models)).
أنشئ ملف `.env` يحتوي على ما يلي:```
OPENAI_API_KEY=<your-openai-api-key>
DB_URL=<your-database-url>
يمكنك تنزيل كود بايثون الكامل وrequirements.txt من مثال البدء السريع وتشغيله في نفس الدليل الذي يحتوي على ملف .env.
يتطلب pgai تثبيت عدد من جداول الكتالوج والدوال في قاعدة البيانات. يتم ذلك باستخدام دالة pgai.install، والتي ستقوم بتثبيت المكونات الضرورية في مخطط ai الخاص بقاعدة البيانات.```python
pgai.install(DB_URL)
### إنشاء المُوجّه (Vectorizer)
يُعرّف هذا المُوجّه، الذي يُخبر النظام بكيفية إنشاء التضمينات (embeddings) من عمود `text` في جدول `wiki`. يُنشئ المُوجّه عرضًا باسم `wiki_embedding` يمكننا الاستعلام عنه للحصول على التضمينات (كما سنرى أدناه).```python
async def create_vectorizer(conn: psycopg.AsyncConnection):
async with conn.cursor() as cur:
await cur.execute("""
SELECT ai.create_vectorizer(
'wiki'::regclass,
if_not_exists => true,
loading => ai.loading_column(column_name=>'text'),
embedding => ai.embedding_openai(model=>'text-embedding-ada-002', dimensions=>'1536'),
destination => ai.destination_table(view_name=>'wiki_embedding')
)
""")
await conn.commit()
في هذا المثال، نقوم بتشغيل عامل التوجيه المتجهي مرة واحدة لإنشاء التضمينات للبيانات الموجودة.```python worker = Worker(DB_URL, once=True) worker.run()
في تطبيق حقيقي، لن نستدعي العامل يدويًا بهذه الطريقة في كل مرة نريد فيها إنشاء التضمينات. بدلاً من ذلك، سنقوم بتشغيل العامل في الخلفية وسيعمل بشكل مستمر، مستقصيًا عن العمل من الـ vectorizer.
يمكنك تشغيل العامل في الخلفية من التطبيق، أو الـ cli، أو docker. راجع توثيق [vectorizer worker](https://github.com/pvharmo2/gha-lab-e8902eccd3/blob/main/docs/vectorizer/worker.md) لمزيد من التفاصيل.
### ابحث في مقالات الويكي باستخدام البحث الدلالي
هذا هو البحث الدلالي القياسي لـ pgvector في PostgreSQL. يتم إجراء البحث مقابل عرض `wiki_embedding`، الذي يتم إنشاؤه بواسطة الـ vectorizer ويتضمن جميع الأعمدة من جدول `wiki` بالإضافة إلى عمود `embedding` ونص الأجزاء. تُرجع هذه الدالة كلاً من عمود `text` الكامل من جدول `wiki` والأجزاء الأصغر من النص الأكثر صلة بالاستعلام.```python
@dataclass
class WikiSearchResult:
id: int
url: str
title: str
text: str
chunk: str
distance: float
async def _find_relevant_chunks(client: AsyncOpenAI, query: str, limit: int = 1) -> List[WikiSearchResult]:
# Generate embedding for the query using OpenAI's API
response = await client.embeddings.create(
model="text-embedding-ada-002",
input=query,
encoding_format="float",
)
embedding = np.array(response.data[0].embedding)
# Query the database for the most similar chunks using pgvector's cosine distance operator (<=>)
async with pool.connection() as conn:
async with conn.cursor(row_factory=class_row(WikiSearchResult)) as cur:
await cur.execute("""
SELECT w.id, w.url, w.title, w.text, w.chunk, w.embedding <=> %s as distance
FROM wiki_embedding w
ORDER BY distance
LIMIT %s
""", (embedding, limit))
return await cur.fetchall()
هذا الكود ملحوظ لما لا يفعله. هذا إدراج بسيط لمقال جديد في جدول wiki. لم نكن بحاجة إلى فعل أي شيء مختلف لإنشاء التضمينات، فسيتولى عامل المتجهات (vectorizer worker) تحديث التضمينات مع تغيّر البيانات.```python
def insert_article_about_pgai(conn: psycopg.AsyncConnection):
async with conn.cursor(row_factory=class_row(WikiSearchResult)) as cur:
await cur.execute("""
INSERT INTO wiki (url, title, text) VALUES
('https://en.wikipedia.org/wiki/pgai', 'pgai', 'pgai is a Python library that turns PostgreSQL into the retrieval engine behind robust, production-ready RAG and Agentic applications. It does this by automatically creating vector embeddings for your data based on the vectorizer you define.')
""")
await conn.commit()
### تنفيذ RAG مع LLM
يقوم هذا الكود بتنفيذ RAG مع LLM. يستخدم الدالة `_find_relevant_chunks` المعرّفة أعلاه للعثور على المقاطع النصية الأكثر صلة من جدول `wiki` ثم يستخدم LLM لتوليد استجابة.```python
query = "What is the main thing pgai does right now?"
relevant_chunks = await _find_relevant_chunks(client, query)
context = "\n\n".join(
f"{chunk.title}:\n{chunk.text}"
for chunk in relevant_chunks
)
prompt = f"""Question: {query}
Please use the following context to provide an accurate response:
{context}
Answer:"""
response = await client.chat.completions.create({
model: "gpt-3.5-turbo",
messages: [{ role: "user", content: prompt }],
})
print("RAG response:")
print(response.choices[0].message.content)
ابحث عن أدلة البدء السريع الأخرى:
استكشف المزيد حول الـ vectorizer:
تتيح لك مكتبة pgai الخاصة بنا بلغة Python العمل مع التضمينات (embeddings) المُنشأة من بياناتك:
يمكنك استخدام تضمينات المتجهات من أجل:
نقدم أيضًا امتداد PostgreSQL يمكنه تنفيذ استدعاء نماذج LLM مباشرةً من SQL. وغالبًا ما يكون هذا مفيدًا لحالات الاستخدام مثل التصنيف والتلخيص وإثراء البيانات على بياناتك الحالية.
صُمم الـ vectorizer ليكون مرنًا وقابلًا للتخصيص. يُعرّف كل vectorizer خط أنابيب لإنشاء التضمينات من بياناتك. يُعرَّف خط الأنابيب بسلسلة من المكونات التي تُطبَّق بالتسلسل على البيانات:
النماذج التالية مدعومة للتضمين:
إن إنشاء تضمينات المتجهات ببساطة هو أمر سهل ومباشر. التحدي هو أن نماذج LLM غير موثوقة إلى حد ما وأن نقاط النهاية تُظهر أعطالًا متقطعة و/أو أداءً متدهورًا. جزء حاسم من التعامل السليم مع الأعطال هو أن عمليات تعديل البيانات الأساسية لديك (INSERT، UPDATE، DELETE) يجب ألا تعتمد على عملية التضمين. وإلا، فسيتعطل تطبيقك في كل مرة تكون فيها نقطة النهاية بطيئة أو تفشل وستتأثر تجربة المستخدم لديك.
عادةً، ستحتاج إلى تنفيذ خط أنابيب MLops مخصص للتعامل السليم مع أعطال نقطة النهاية. يتضمن هذا عادةً نظام قوائم انتظار مثل Kafka، وعمالًا متخصصين، وبنية تحتية أخرى للتعامل مع قائمة الانتظار وإعادة محاولة الطلبات الفاشلة. هذا قدر كبير من العمل ومن السهل ارتكاب الأخطاء فيه.
مع pgai، يمكنك تخطي كل ذلك والتركيز على بناء تطبيقك لأن الـ vectorizer يدير التضمينات نيابةً عنك. لقد بنينا منطق قوائم انتظار وإعادة محاولة مدمجًا للتعامل مع أوضاع الأعطال المختلفة التي قد تواجهها. ولأننا نقوم بهذا العمل في الخلفية، فإن عمليات تعديل البيانات الأساسية لا تعتمد على عملية التضمين. لهذا السبب فإن pgai جاهز للإنتاج مباشرةً.
تخلق العديد من قواعد بيانات المتجهات المتخصصة تضمينات لك. ومع ذلك، فإنها تفشل عادةً عندما تكون نقاط نهاية التضمين معطلة أو متدهورة، مما يضع عبء معالجة الأخطاء وإعادة المحاولات على عاتقك مرة أخرى.
نرحب بالمساهمات في pgai! راجع صفحة المساهمة لمزيد من المعلومات.
لا يزال pgai في مرحلة مبكرة. الآن هو وقت رائع للمساعدة في تشكيل اتجاه هذا المشروع؛ نحن حاليًا نحدد الأولويات. ألقِ نظرة على قائمة الميزات التي نفكر في العمل عليها. لا تتردد في التعليق، أو توسيع القائمة، أو الانضمام إلى منتدى المناقشات.
للبدء، ألقِ نظرة على كيفية المساهمة وكيفية إعداد بيئة تطوير/اختبار.
Timescale هي شركة قواعد بيانات PostgreSQL. لمعرفة المزيد، تفضل بزيارة timescale.com.
Timescale Cloud هي منصة سحابية عالية الأداء وموجهة للمطورين توفر خدمات PostgreSQL لأعباء العمل الأكثر تطلبًا في مجالات الذكاء الاصطناعي والسلاسل الزمنية والتحليلات والأحداث. Timescale Cloud مثالية لتطبيقات الإنتاج وتوفر توفرًا عاليًا ونسخًا احتياطيًا مباشرًا وترقيات بمرور الوقت وأدوارًا وأذونات وأمانًا ممتازًا.