> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-fbfa8bee.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> مجموعة بيانات تضم 400 مليون صورة مع تعليقات توضيحية للصور باللغة الإنجليزية

# مجموعة بيانات Laion-400M

تحتوي [مجموعة بيانات Laion-400M](https://laion.ai/blog/laion-400-open-dataset/) على 400 مليون صورة مع تعليقات توضيحية للصور باللغة الإنجليزية. وتوفّر Laion اليوم [مجموعة بيانات أكبر من ذلك](https://laion.ai/blog/laion-5b/)، لكن العمل معها سيكون مشابهًا.

تتضمن مجموعة البيانات عنوان URL للصورة، وتضمينات لكلٍّ من الصورة والتعليق التوضيحي للصورة، ودرجة تشابه بين الصورة والتعليق التوضيحي للصورة، بالإضافة إلى البيانات الوصفية، مثل عرض الصورة/ارتفاعها، والترخيص، وعلامة NSFW. ويمكننا استخدام مجموعة البيانات لتوضيح [البحث التقريبي عن أقرب الجيران](/ar/reference/engines/table-engines/mergetree-family/annindexes) في ClickHouse.

<div id="data-preparation">
  ## إعداد البيانات
</div>

تُخزَّن التضمينات والبيانات الوصفية في ملفات منفصلة ضمن البيانات الخام. وتتضمن خطوة إعداد البيانات تنزيل هذه البيانات ودمج الملفات،
ثم تحويلها إلى CSV واستيرادها إلى ClickHouse. يمكنك استخدام البرنامج النصي `download.sh` التالي لهذا الغرض:

```bash theme={null}
number=${1}
if [[ $number == '' ]]; then
    number=1
fi;
wget --tries=100 https://deploy.laion.ai/8f83b608504d46bb81708ec86e912220/embeddings/img_emb/img_emb_${number}.npy          # download image embedding
wget --tries=100 https://deploy.laion.ai/8f83b608504d46bb81708ec86e912220/embeddings/text_emb/text_emb_${number}.npy        # download text embedding
wget --tries=100 https://deploy.laion.ai/8f83b608504d46bb81708ec86e912220/embeddings/metadata/metadata_${number}.parquet    # download metadata
python3 process.py $number # merge files and convert to CSV
```

تم تعريف النص البرمجي `process.py` كما يلي:

```python theme={null}
import pandas as pd
import numpy as np
import os
import sys

str_i = str(sys.argv[1])
npy_file = "img_emb_" + str_i + '.npy'
metadata_file = "metadata_" + str_i + '.parquet'
text_npy =  "text_emb_" + str_i + '.npy'

# load all files
im_emb = np.load(npy_file)
text_emb = np.load(text_npy) 
data = pd.read_parquet(metadata_file)

# combine files
data = pd.concat([data, pd.DataFrame({"image_embedding" : [*im_emb]}), pd.DataFrame({"text_embedding" : [*text_emb]})], axis=1, copy=False)

# columns to be imported into ClickHouse
data = data[['url', 'caption', 'NSFW', 'similarity', "image_embedding", "text_embedding"]]

# transform np.arrays to lists
data['image_embedding'] = data['image_embedding'].apply(lambda x: x.tolist())
data['text_embedding'] = data['text_embedding'].apply(lambda x: x.tolist())

# this small hack is needed because caption sometimes contains all kind of quotes
data['caption'] = data['caption'].apply(lambda x: x.replace("'", " ").replace('"', " "))

# export data as CSV file
data.to_csv(str_i + '.csv', header=False)

# removed raw data files
os.system(f"rm {npy_file} {metadata_file} {text_npy}")
```

لبدء مسار إعداد البيانات، نفّذ:

```bash theme={null}
seq 0 409 | xargs -P1 -I{} bash -c './download.sh {}'
```

مجموعة البيانات مُقسّمة إلى 410 ملفات، ويحتوي كل ملف على حوالي مليون صف. إذا كنت ترغب في العمل على مجموعة فرعية أصغر من البيانات، فما عليك سوى تعديل النطاقات، مثل `seq 0 9 | ...`.

(سكريبت Python أعلاه بطيء جدًا (\~2-10 دقائق لكل ملف)، ويستهلك قدرًا كبيرًا من الذاكرة (41 GB لكل ملف)، كما أن ملفات CSV الناتجة كبيرة (10 GB لكل ملف)، لذا توخَّ الحذر. إذا كان لديك ما يكفي من RAM، فزِد قيمة `-P1` للحصول على مزيد من التوازي. إذا ظل هذا بطيئًا جدًا، ففكّر في إيجاد آلية أفضل لإدخال البيانات — ربما عبر تحويل ملفات .npy إلى parquet، ثم تنفيذ بقية المعالجة باستخدام ClickHouse.)

<div id="create-table">
  ## إنشاء جدول
</div>

لإنشاء جدول في البداية من دون فهارس، شغّل:

```sql theme={null}
CREATE TABLE laion
(
    `id` Int64,
    `url` String,
    `caption` String,
    `NSFW` String,
    `similarity` Float32,
    `image_embedding` Array(Float32),
    `text_embedding` Array(Float32)
)
ENGINE = MergeTree
ORDER BY id
```

لاستيراد ملفات CSV إلى ClickHouse:

```sql theme={null}
INSERT INTO laion FROM INFILE '{path_to_csv_files}/*.csv'
```

لاحظ أن العمود `id` هو للتوضيح فقط، ويُعبِّئه البرنامج النصي بقيم غير فريدة.

<div id="run-a-brute-force-vector-similarity-search">
  ## نفّذ بحث تشابه متجهي بأسلوب الفحص الشامل
</div>

لتنفيذ بحث متجهي تقريبي بأسلوب الفحص الشامل، نفّذ:

```sql theme={null}
SELECT url, caption FROM laion ORDER BY cosineDistance(image_embedding, {target:Array(Float32)}) LIMIT 10
```

`target` هو مصفوفة تضم 512 عنصرًا، وهو أيضًا معامل للعميل.
وسنستعرض في نهاية المقال طريقة عملية للحصول على مصفوفات كهذه.
أما الآن، فيمكننا استخدام تضمين لصورة عشوائية لمجموعة LEGO بوصفه `target`.

**النتيجة**

```markdown theme={null}
    ┌─url───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─caption──────────────────────────────────────────────────────────────────────────┐
 1. │ https://s4.thcdn.com/productimg/600/600/11340490-9914447026352671.jpg                                                                                                                         │ LEGO Friends: Puppy Treats & Tricks (41304)                                      │
 2. │ https://www.avenuedelabrique.com/img/uploads/f20fd44bfa4bd49f2a3a5fad0f0dfed7d53c3d2f.jpg                                                                                                     │ Nouveau LEGO Friends 41334 Andrea s Park Performance 2018                        │
 3. │ http://images.esellerpro.com/2489/I/667/303/3938_box_in.jpg                                                                                                                                   │ 3938 LEGO Andreas Bunny House Girls Friends Heartlake Age 5-12 / 62 Pieces  New! │
 4. │ http://i.shopmania.org/180x180/7/7f/7f1e1a2ab33cde6af4573a9e0caea61293dfc58d.jpg?u=https%3A%2F%2Fs.s-bol.com%2Fimgbase0%2Fimagebase3%2Fextralarge%2FFC%2F4%2F0%2F9%2F9%2F9200000049789904.jpg │ LEGO Friends Avonturenkamp Boomhuis - 41122                                      │
 5. │ https://s.s-bol.com/imgbase0/imagebase/large/FC/5/5/9/4/1004004011684955.jpg                                                                                                                  │ LEGO Friends Andrea s Theatershow - 3932                                         │
 6. │ https://www.jucariicucubau.ro/30252-home_default/41445-lego-friends-ambulanta-clinicii-veterinare.jpg                                                                                         │ 41445 - LEGO Friends - Ambulanta clinicii veterinare                             │
 7. │ https://cdn.awsli.com.br/600x1000/91/91201/produto/24833262/234c032725.jpg                                                                                                                    │ LEGO FRIENDS 41336 EMMA S ART CAFÉ                                               │
 8. │ https://media.4rgos.it/s/Argos/6174930_R_SET?$Thumb150$&amp;$Web$                                                                                                                             │ more details on LEGO Friends Stephanie s Friendship Cake Set - 41308.            │
 9. │ https://thumbs4.ebaystatic.com/d/l225/m/mG4k6qAONd10voI8NUUMOjw.jpg                                                                                                                           │ Lego Friends Gymnast 30400 Polybag 26 pcs                                        │
10. │ http://www.ibrickcity.com/wp-content/gallery/41057/thumbs/thumbs_lego-41057-heartlake-horse-show-friends-3.jpg                                                                                │ lego-41057-heartlake-horse-show-friends-3                                        │
    └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────┘

10 rows in set. Elapsed: 4.605 sec. Processed 100.38 million rows, 309.98 GB (21.80 million rows/s., 67.31 GB/s.)
```

<div id="run-an-approximate-vector-similarity-search-with-a-vector-similarity-index">
  ## أجرِ بحثًا تقريبيًا عن تشابه المتجهات باستخدام فهرس تشابه المتجهات
</div>

لنُعرِّف الآن فهرسَي تشابه متجهات على الجدول.

```sql theme={null}
ALTER TABLE laion ADD INDEX image_index image_embedding TYPE vector_similarity('hnsw', 'cosineDistance', 512, 'bf16', 64, 256)
ALTER TABLE laion ADD INDEX text_index text_embedding TYPE vector_similarity('hnsw', 'cosineDistance', 512, 'bf16', 64, 256)
```

توضّح [الوثائق](/ar/reference/engines/table-engines/mergetree-family/annindexes) المعلمات واعتبارات الأداء المتعلقة بإنشاء الفهرس والبحث.
يحدّد تعريف الفهرس أعلاه فهرس HNSW يستخدم "مسافة جيب التمام" بوصفها مقياس المسافة، مع ضبط المعلمة "hnsw\_max\_connections\_per\_layer" على 64 والمعلمة "hnsw\_candidate\_list\_size\_for\_construction" على 256.
يستخدم الفهرس الأعداد العائمة بنصف الدقة (bfloat16) كتكميم لتحسين استخدام الذاكرة.

لبناء الفهرس وتخزينه فعليًا، شغّل هذه العبارات:

```sql theme={null}
ALTER TABLE laion MATERIALIZE INDEX image_index;
ALTER TABLE laion MATERIALIZE INDEX text_index;
```

قد يستغرق إنشاء الفهرس وحفظه بضع دقائق أو حتى ساعات، وذلك بحسب عدد الصفوف ومعلمات فهرس HNSW.

لإجراء بحث في المتجهات، ما عليك سوى تنفيذ الاستعلام نفسه مرة أخرى:

```sql theme={null}
SELECT url, caption FROM laion ORDER BY cosineDistance(image_embedding, {target:Array(Float32)}) LIMIT 10
```

**النتيجة**

```response theme={null}
    ┌─url───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─caption──────────────────────────────────────────────────────────────────────────┐
 1. │ https://s4.thcdn.com/productimg/600/600/11340490-9914447026352671.jpg                                                                                                                         │ LEGO Friends: Puppy Treats & Tricks (41304)                                      │
 2. │ https://www.avenuedelabrique.com/img/uploads/f20fd44bfa4bd49f2a3a5fad0f0dfed7d53c3d2f.jpg                                                                                                     │ Nouveau LEGO Friends 41334 Andrea s Park Performance 2018                        │
 3. │ http://images.esellerpro.com/2489/I/667/303/3938_box_in.jpg                                                                                                                                   │ 3938 LEGO Andreas Bunny House Girls Friends Heartlake Age 5-12 / 62 Pieces  New! │
 4. │ http://i.shopmania.org/180x180/7/7f/7f1e1a2ab33cde6af4573a9e0caea61293dfc58d.jpg?u=https%3A%2F%2Fs.s-bol.com%2Fimgbase0%2Fimagebase3%2Fextralarge%2FFC%2F4%2F0%2F9%2F9%2F9200000049789904.jpg │ LEGO Friends Avonturenkamp Boomhuis - 41122                                      │
 5. │ https://s.s-bol.com/imgbase0/imagebase/large/FC/5/5/9/4/1004004011684955.jpg                                                                                                                  │ LEGO Friends Andrea s Theatershow - 3932                                         │
 6. │ https://www.jucariicucubau.ro/30252-home_default/41445-lego-friends-ambulanta-clinicii-veterinare.jpg                                                                                         │ 41445 - LEGO Friends - Ambulanta clinicii veterinare                             │
 7. │ https://cdn.awsli.com.br/600x1000/91/91201/produto/24833262/234c032725.jpg                                                                                                                    │ LEGO FRIENDS 41336 EMMA S ART CAFÉ                                               │
 8. │ https://media.4rgos.it/s/Argos/6174930_R_SET?$Thumb150$&amp;$Web$                                                                                                                             │ more details on LEGO Friends Stephanie s Friendship Cake Set - 41308.            │
 9. │ https://thumbs4.ebaystatic.com/d/l225/m/mG4k6qAONd10voI8NUUMOjw.jpg                                                                                                                           │ Lego Friends Gymnast 30400 Polybag 26 pcs                                        │
10. │ http://www.ibrickcity.com/wp-content/gallery/41057/thumbs/thumbs_lego-41057-heartlake-horse-show-friends-3.jpg                                                                                │ lego-41057-heartlake-horse-show-friends-3                                        │
    └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────┘

10 rows in set. Elapsed: 0.019 sec. Processed 137.27 thousand rows, 24.42 MB (7.38 million rows/s., 1.31 GB/s.)
```

انخفض زمن استجابة الاستعلام بشكل ملحوظ لأن أقرب الجيران استُرجعوا باستخدام الفهرس المتجهي.
قد يُرجع البحث عن التشابه المتجهي باستخدام فهرس تشابه المتجهات نتائج تختلف اختلافًا طفيفًا عن نتائج الفحص الشامل.
يمكن لفهرس HNSW أن يحقق قيمة استرجاع قريبة من 1 (بنفس دقة الفحص الشامل) مع اختيار معاملات HNSW بعناية وتقييم جودة الفهرس.

<div id="creating-embeddings-with-udfs">
  ## إنشاء التضمينات باستخدام UDFs
</div>

عادةً ما تكون الحاجة إلى إنشاء تضمينات لصور جديدة أو لتسميات توضيحية جديدة للصور، ثم البحث في البيانات عن أزواج متشابهة من الصور/التسميات التوضيحية للصور. ويمكننا استخدام [UDF](/ar/reference/functions/regular-functions/udf) لإنشاء المتجه `target` من داخل العميل. ومن المهم استخدام النموذج نفسه لإنشاء البيانات والتضمينات الجديدة الخاصة بعمليات البحث. تستخدم البرامج النصية التالية النموذج `ViT-B/32`، وهو أيضًا النموذج الذي تستند إليه مجموعة البيانات.

<div id="text-embeddings">
  ### تضمينات النص
</div>

أولاً، احفظ برنامج Python النصي التالي في الدليل `user_scripts/` ضمن مسار بيانات ClickHouse، ومنحه صلاحية التنفيذ (`chmod +x encode_text.py`).

`encode_text.py`:

```python theme={null}
#!/usr/bin/python3
#!Note: Change the above python3 executable location if a virtual env is being used.
import clip
import torch
import numpy as np
import sys

if __name__ == '__main__':
    device = "cuda" if torch.cuda.is_available() else "cpu"
    model, preprocess = clip.load("ViT-B/32", device=device)
    for text in sys.stdin:
        inputs = clip.tokenize(text)
        with torch.no_grad():
            text_features = model.encode_text(inputs)[0].tolist()
            print(text_features)
        sys.stdout.flush()
```

ثم أنشئ `encode_text_function.xml` في مسار يُشار إليه بواسطة `<user_defined_executable_functions_config>/path/to/*_function.xml</user_defined_executable_functions_config>` ضمن ملف إعدادات خادم ClickHouse.

```xml theme={null}
<functions>
    <function>
        <type>executable</type>
        <name>encode_text</name>
        <return_type>Array(Float32)</return_type>
        <argument>
            <type>String</type>
            <name>text</name>
        </argument>
        <format>TabSeparated</format>
        <command>encode_text.py</command>
        <command_read_timeout>1000000</command_read_timeout>
    </function>
</functions>
```

يمكنك الآن ببساطة أن تستخدم:

```sql theme={null}
SELECT encode_text('cat');
```

سيكون التشغيل الأول بطيئًا لأنه يحمّل النموذج، لكن مرات التشغيل اللاحقة ستكون سريعة. بعد ذلك، يمكننا نسخ الناتج إلى `SET param_target=...`، ومن ثم كتابة الاستعلامات بسهولة. وبدلًا من ذلك، يمكن استخدام الدالة `encode_text()` مباشرةً كوسيطة للدالة `cosineDistance`:

```SQL theme={null}
SELECT url
FROM laion
ORDER BY cosineDistance(text_embedding, encode_text('a dog and a cat')) ASC
LIMIT 10
```

لاحظ أن UDF ‏`encode_text()` نفسه قد يستغرق بضع ثوانٍ لحساب متجه التضمين وإرجاعه.

<div id="image-embeddings">
  ### تضمين الصور
</div>

يمكن إنشاء تضمين الصور بالطريقة نفسها، ونوفّر نصًا برمجيًا بلغة Python يمكنه إنشاء تضمين لصورة مخزّنة محليًا كملف.

`encode_image.py`

```python theme={null}
#!/usr/bin/python3
#!Note: Change the above python3 executable location if a virtual env is being used.
import clip
import torch
import numpy as np
from PIL import Image
import sys

if __name__ == '__main__':
    device = "cuda" if torch.cuda.is_available() else "cpu"
    model, preprocess = clip.load("ViT-B/32", device=device)
    for text in sys.stdin:
        image = preprocess(Image.open(text.strip())).unsqueeze(0).to(device)
        with torch.no_grad():
            image_features = model.encode_image(image)[0].tolist()
            print(image_features)
        sys.stdout.flush()
```

`encode_image_function.xml`

```xml theme={null}
<functions>
    <function>
        <type>executable_pool</type>
        <name>encode_image</name>
        <return_type>Array(Float32)</return_type>
        <argument>
            <type>String</type>
            <name>path</name>
        </argument>
        <format>TabSeparated</format>
        <command>encode_image.py</command>
        <command_read_timeout>1000000</command_read_timeout>
    </function>
</functions>
```

حمّل صورةً تجريبية للبحث:

```shell theme={null}
# get a random image of a LEGO set
$ wget http://cdn.firstcry.com/brainbees/images/products/thumb/191325a.jpg
```

ثم شغّل هذا الاستعلام لإنشاء تضمين الصورة أعلاه:

```sql theme={null}
SELECT encode_image('/path/to/your/image');
```

استعلام البحث الكامل هو :

```sql theme={null}
SELECT
    url,
    caption
FROM laion
ORDER BY cosineDistance(image_embedding, encode_image('/path/to/your/image')) ASC
LIMIT 10
```
