شروع داده‌های پایا Chroma

import { ChromaClient } from 'chromadb'

مقدمه کردن مشترک

const client = new ChromaClient();

عملیات مشترک معمول

await client.reset() // پایگاه داده را پاک کن

کار با مجموعه‌ها

Chromadb از مفهوم مجموعه برای مدیریت مجموعه‌های داده بردار استفاده می‌کند، که می‌توان آن را به جداول در MySQL تشبیه کرد.

ایجاد، مشاهده و حذف مجموعه‌ها

Chroma از نام مجموعه در URL استفاده می‌کند، لذا محدودیت‌هایی برای نام‌گذاری وجود دارد:

  • طول نام باید بین 3 تا 63 کاراکتر باشد.
  • نام باید با حروف کوچک یا اعداد شروع و پایان یابد و می‌تواند شامل نقطه، خط تیره و زیرخط در میان آن‌ها باشد.
  • نام نمی‌تواند دو نقطه متوالی داشته باشد.
  • نام نمی‌تواند یک آدرس IP معتبر باشد.

برای ایجاد یک مجموعه، نام مجموعه و یک تابع محاسبه بردار اختیاری (همچنین به نام تابع جاسازی) باید مشخص شود. اگر یک تابع جاسازی ارائه شود، هربار که به مجموعه دسترسی داده می‌شود باید ارائه شود.

توجه: تابع جاسازی برای محاسبه بردارهای متن استفاده می‌شود.

import { ChromaClient } from 'chromadb'

ایجاد و مرجع دهی به یک مجموعه به صورت زیر نشان داده شده است:

let collection = await client.createCollection({name: "my_collection", embeddingFunction: emb_fn})

let collection2 = await client.getCollection({name: "my_collection", embeddingFunction: emb_fn})

تابع جاسازی ورودی متن را گرفته و داده بردار محاسبه شده را برمی‌گرداند.

توجه: مبتدیان می‌توانند درباره مدل‌های جاسازی متن از این آموزش بیشتر بدانند.

مجموعه‌های موجود می‌توانند با استفاده از .getCollection بر اساس نام مرجع دهی شده و همچنین با استفاده از.deleteCollection حذف شوند.

const collection = await client.getCollection({name: "tizi365"}) // مرجع دهی به مجموعه tizi365
await client.deleteCollection({name: "my_collection"}) // حذف مجموعه

عملیات متداول مجموعه

await collection.peek() // نخستین 10 رکورد داده را در مجموعه برمی‌گرداند
await collection.count() // تعداد کل رکوردهای داده در مجموعه را برمی‌گرداند

تنظیم روش‌های محاسبه فاصله برداری

createCollection شامل یک پارامتر اختیاری metadata است، جایی که مقدار hnsw:space می‌تواند برای سفارشی‌سازی روش محاسبه فضای فاصله برای فضای بردار تنظیم شود.

توجه: داده‌های بردار نشان دهنده شباهت بین بردارها با محاسبه فاصله فضایی بین آن‌ها است، که فواصل نزدیک بیانگر شباهت بیشتر و برعکس است.

let collection = client.createCollection("collection_name", undefined, metadata={ "hnsw:space": "cosine" })

گزینه‌های معتبر برای hnsw:space "l2"، "ip" یا "cosine" هستند. پیش‌فرض "l2" است.

اضافه کردن داده به یک مجموعه

از .add برای اضافه کردن داده به مجموعه Chroma استفاده کنید.

بدون مشخص کردن بردار سند، داده را بصورت مستقیم اضافه کنید:

await collection.add({
    ids: ["id1", "id2", "id3", ...],
    metadatas: [{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
    documents: ["لورم ایپسوم...", "سند2", "سند3", ...],
})
// توضیحات پارامتر
// ids - اجباری
// embeddings - اختیاری
// metadata - اختیاری
// documents - اختیاری

اگر Chroma یک لیست از سند ها دریافت کند، به طور خودکار از تابع جاسازی مجموعه استفاده خواهد کرد تا بردارها برای اسناد محاسبه شوند (اگر تابع جاسازی هنگام ایجاد مجموعه ارائه نشده باشد، مقدار پیش‌فرض استفاده خواهد شد). همچنین Chroma سندها را نیز ذخیره می‌کند. اگر یک سند بسیار بزرگ برای استفاده با تابع جاسازی انتخاب شده باشد، یک استثنا رخ می‌دهد.

هر سند باید یک شناسه یکتا (ids) داشته باشد. اضافه کردن دوباره یک شناسه منحصر به فرد منجر به تنها ذخیره شدن مقدار اولیه خواهد شد. یک لیست اختیاری از دیکشنری‌های metadata (metadatas) هم برای هر سند می‌توان ارائه داد تا اطلاعات اضافی برای فیلتر کردن داده‌ها در طول پرس و جوها ذخیره شود.

در غیر اینصورت، شما می‌توانید به طور مستقیم یک لیست از داده‌های بردار مرتبط با سند ارائه دهید و Chroma از داده‌های برداری که شما ارائه کرده‌اید بدون محاسبه خودکار بردار استفاده خواهد کرد.

await collection.add({
    ids: ["id1", "id2", "id3", ...],
    embeddings: [[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
    metadatas: [{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
    documents: ["لورم ایپسوم...", "سند2", "سند3", ...],
})

اگر ابعاد (طول) داده‌های بردار ارائه شده با ابعاد مجموعه مطابقت نداشته باشد، یک استثنا رخ می‌دهد.

همچنین شما می‌توانید سندها را در جای دیگر ذخیره کرده و به صورت ساده داده‌های بردار و لیست metadata را به Chroma ارائه دهید. شما می‌توانید از ids برای ارتباط دادن بردارها با اسنادی که در جای دیگر ذخیره شده‌اند، استفاده کنید.

await collection.add({
    ids: ["id1", "id2", "id3", ...],
    embeddings: [[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
    metadatas: [{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
})

توجه: عملکرد اصلی پایگاه داده بردار، جستجوی شباهت معنایی براساس داده‌های بردار است. برای کاهش اندازه پایگاه داده بردار و بهبود کارایی، می‌توانیم انتخاب کنیم تا داده‌های بردار و برخی شرایط ویژگی‌پذیر دیگر را در پایگاه داده بردار ذخیره کنیم. داده‌های دیگر مانند محتوای مقاله را می‌توان در پایگاه داده‌هایی مانند MYSQL ذخیره کرد، تا زمانی که از طریق شناسه‌ها ارتباط داشته باشند.

درخواست داده های مجموعه

روش .query می‌تواند برای جستجو در مجموعه داده Chroma به چندین روش استفاده شود.

می‌توانید با استفاده از مجموعه query_embeddings (داده های بردار) جستجو کنید.

نکته: برای دریافت query_embeddings، در سناریوهای توسعه واقعی، ابتدا پرس و جو کاربر را از طریق یک مدل جا به جایی متن محاسبه میکنند، و سپس از این بردار برای جستجوی محتوای مشابه استفاده میشود.

const result = await collection.query({
    queryEmbeddings: [[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
    nResults: 10,
    where: {"metadata_field": "is_equal_to_this"},
})
// ترتیب ورودی
// query_embeddings - اختیاری
// n_results - ضروری
// where - اختیاری
// query_texts - اختیاری

جستجو نتایج بالای n_results برای هر بردار پرس و جو (query_embedding) را به ترتیب بر می‌گرداند. می‌توان یک فیلتر where دلخواه را فراهم کرد تا نتایج بر اساس اطلاعات فراداده مرتبط با هر سند فیلتر شوند. علاوه بر این، می‌توان یک دیکشنری فیلتر where_document اختیاری فراهم کرد تا نتایج بر اساس محتوای سند فیلتر شوند.

اگر query_embeddings ارائه شده با ابعاد مجموعه سازگار نباشد، یک استثناء رخ می‌دهد. برای اطمینان از سازگاری بردار، توصیه میشود از همان مدل جا به جایی متن برای محاسبه بردارها استفاده کنید.

همچنین می‌توانید با استفاده از یک مجموعه متن‌ها پرس و جو کنید. Chroma ابتدا برای هر متن پرس و جویی برای محاسبه بردار با استفاده از تابع جا به جایی مجموعه انجام می دهد، و سپس با استفاده از بردارهای متنی تولید شده، پرس و جو را انجام می دهد.

await collection.query({
    nResults: 10, // n_results
    where: {"metadata_field": "is_equal_to_this"}, // where
    queryTexts: ["doc10", "thus spake zarathustra", ...], // query_text
})

همچنین می‌توانید از .get برای پرس و جوی داده ها از مجموعه بر اساس شناسه استفاده کنید.

await collection.get({
    ids: ["id1", "id2", "id3", ...], //ids
    where: {"style": "style1"} // where
})

.get همچنین از فیلترهای where و where_document پشتیبانی میکند. اگر id ارائه نشود، تمام داده‌های موجود در مجموعه که با فیلترهای where و where_document مطابقت داشته باشند را برمیگرداند.

تعیین فیلدهای برگشتی

هنگام استفاده از get یا query، می‌توانید از پارامتر include برای تعیین فیلدهای داده‌های برگشتی استفاده کنید، شامل داده‌های بردار، سند‌ها و هرگونه داده در اطلاعات فراداده. به طور پیش‌فرض، Chroma سند‌ها، اطلاعات فراداده و فواصل بردار را برمیگرداند. می‌توانید فیلدهای برگشتی را با گذاشتن یک آرایه از نام‌های فیلد به پارامتر includes از get یا query مشخص کنید.

collection.get(
    include=["documents"]
)

collection.query(
    query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
    include=["documents"]
)

استفاده از فیلترهای Where

Chroma از فیلتر کردن پرس و جوها بر اساس اطلاعات فراداده و محتوای سند پشتیبانی می‌کند. فیلتر where برای فیلتر کردن فراداده استفاده می‌شود، و فیلتر where_document برای فیلتر کردن محتوای سند استفاده می‌شود. در زیر، توضیح می‌دهیم چگونه عبارت‌های شرطی فیلتر را بنویسید.

فیلتر کردن بر اساس اطلاعات فراداده

برای فیلتر کردن اطلاعات فراداده، یک دیکشنری فیلتر where برای پرس و جو باید فراهم شود. این دیکشنری باید ساختار زیر را داشته باشد:

{
    "metadata_field": {
        <عامل>: <مقدار>
    }
}

فیلتر کردن اطلاعات فراداده از اپراتورهای زیر پشتیبانی میکند:

  • $eq - برابر (رشته، عدد صحیح، عدد اعشاری)
  • $ne - نا برابر (رشته، عدد صحیح، عدد اعشاری)
  • $gt - بزرگتر از (عدد صحیح، عدد اعشاری)
  • $gte - بزرگتر مساوی به (عدد صحیح، عدد اعشاری)
  • $lt - کمتر از (عدد صحیح، عدد اعشاری)
  • $lte - کمتر مساوی به (عدد صحیح، عدد اعشاری)

استفاده از اپراتور $eq معادل است با استفاده از فیلتر where.

{
    "metadata_field": "رشته_جستجو"
}


{
    "metadata_field": {
        "$eq": "رشته_جستجو"
    }
}

فیلتر کردن محتوای سند

برای فیلتر کردن محتوای سند، یک دیکشنری فیلتر where_document برای پرس و جو باید فراهم شود. این دیکشنری باید ساختار زیر را داشته باشد:

{
    "$contains": "رشته_جستجو"
}

استفاده از عملگرهای منطقی

همچنین می‌توانید از عملگرهای منطقی $and و $or برای ترکیب چندین فیلتر استفاده کنید.

عملگر $and نتایجی را که با همه‌ی فیلترها در لیست مطابقت دارند، برمی‌گرداند.

{
    "$and": [
        {
            "metadata_field": {
                <عملگر>: <مقدار>
            }
        },
        {
            "metadata_field": {
                <عملگر>: <مقدار>
            }
        }
    ]
}

عملگر $or نتایجی را که با هر شرط فیلتر در لیست مطابقت دارند، برمی‌گرداند.

{
    "$or": [
        {
            "metadata_field": {
                <عملگر>: <مقدار>
            }
        },
        {
            "metadata_field": {
                <عملگر>: <مقدار>
            }
        }
    ]
}

به‌روزرسانی داده

کروما همچنین پشتیبانی از عملیات upsert دارد که می‌تواند داده‌های موجود را به‌روز کند و اگر داده وجود نداشته باشد، داده‌های جدید را درج کند.

await collection.upsert({
    ids: ["id1", "id2", "id3"],
    embeddings: [[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2]],
    metadatas: [{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}],
    documents: ["doc1", "doc2", "doc3"]
})

حذف داده

کروما پشتیبانی از استفاده از .delete برای حذف داده از مجموعه بر اساس شناسه دارد.

await collection.delete({
    ids: ["id1", "id2", "id3",...], //شناسه‌ها
    where: {"chapter": "20"} //شرط
})