กำลังเริ่มต้นข้อมูล Chroma ที่ต้องการจำ

import { ChromaClient } from 'chromadb'

เริ่มต้นการใช้งาน Client

const client = new ChromaClient();

การดำเนินการทั่วไปของ Client

await client.reset() // ล้างฐานข้อมูล

การทำงานกับคอลเล็กชัน

Chromadb ใช้แนวคิดของ collection เพื่อการจัดการเซ็ตข้อมูลเวกเตอร์ ซึ่งสามารถเปรียบเทียบกับตารางใน 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: ["lorem ipsum...", "doc2", "doc3", ...],
})
// อธิบายพารามิเตอร์
// ids - จำเป็น
// embeddings - ไม่จำเป็น
// metadata - ไม่จำเป็น
// documents - ไม่จำเป็น

หาก Chroma ได้รับรายการของเอกสาร จะใช้ฟังก์ชันเวกเตอร์ของคอลเลคชันโดยอัตโนมัติเพื่อคำนวณเวกเตอร์ของเอกสาร (หากไม่ได้ระบุฟังก์ชันเวกเตอร์เมื่อสร้างคอลเลคชัน ค่าเริ่มต้นจะถูกใช้) Chroma ยังจะเก็บเอกสารเองเช่นกัน หากเอกสารมีขนาดใหญ่เกินไปที่จะใช้กับฟังก์ชันเวกเตอร์ที่ถูกเลือก เกิดข้อยกเว้นจะเกิดขึ้น

ทุกเอกสารจะต้องมี ID ที่ไม่ซ้ำกัน (ids) เพิ่ม ID เดียวกันสองครั้งจะทำให้ค่าเริ่วต้นถูกเก็บไว้เท่านั้น เราสามารถระบุรายการทางอเมตาดาต้าเพิ่มเติมสำหรับแต่ละเอกสารเพื่อเก็บข้อมูลเพิ่มเติมสำหรับการกรองข้อมูลในการค้นหา

โดยอนไล คุณสามารถระบุรายการของเวกเตอร์ที่เกี่ยวข้องกับเอกสารโดยตรง และ 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: ["lorem ipsum...", "doc2", "doc3", ...],
})

หากมิตรงกับขนาดของข้อมูลเวกเตอร์ที่ระบุ ตัวเลือกข้อยกเว้นจะเกิดขึ้น

คุณสามารถจัดเก็บเอกสารที่อยู่ในที่อื่นและเพียงแค่ระบุข้อมูลเวกเตอร์และรายการข้อมูลเพิ่มเติมเพื่อเก็บเข้าไปยัง 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 และถือเป็นผูกพันกับ IDs

การค้นหาข้อมูลในคอลเล็กชัน

เมธอด .query สามารถใช้ในการค้นหาชุดข้อมูลของชุดข้อมูล Chroma ในหลายวิธี

คุณสามารถค้นหาโดยใช้ query_embeddings (ข้อมูลเวกเตอร์)

เกร็ด: เพื่อให้ได้ query_embeddings ในสถานการณ์การพัฒนาจริง ๆ บางที คำค้นของผู้ใช้จะถูกคำนวณก่อนเป็นเวกเตอร์คำค้นผ่านโมเดล text embedding และจากนั้นเวกเตอร์นี้จะถูกใช้ในการค้นหาเนื้อหาที่คล้ายกัน

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 ในรูปแบบของพจนานุกรม เพิ่มเติม และสามารถให้ได้เงื่อนไขกรอง where_document ในรูปแบบของพจนานุกรมเพื่อกรองผลลัพธ์ตามเนื้อหาของเอกสาร

หาก query_embeddings ที่ให้กับฟังก์ชันไม่สอดคล้องกับมิติของคอลเล็กชัน จะเกิดข้อยกเว้นขึ้น หากต้องการให้มีความสอดคล้องของเวกเตอร์ ขอแนะนำให้ใช้โมเดล text embedding เดียวกันในการคำนวณเวกเตอร์

คุณยังสามารถค้นหาโดยใช้เซ็ตของข้อความคำค้น Chroma จะคำนวณเวกเตอร์สำหรับแต่ละข้อความคำค้นโดยใช้ฟังก์ชันฝังหลังของคอลเล็กชัน และจากนั้นดำเนินการค้นหาโดยใช้เวกเตอร์ข้อความที่สร้างขึ้น

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

คุณยังสามารถใช้ .get เพื่อค้นหาข้อมูลจากคอลเล็กชันตาม id

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

.get ยังสนับสนุน where และ where_document filters หากไม่มี id ที่ให้ จะส่งคืนข้อมูลทั้งหมดในคอลเล็กชันที่ตรงกับ where และ where_document filters

การระบุฟิลด์ที่จะส่งคืน

เมื่อใช้ get หรือ query คุณสามารถใช้พารามิเตอร์ include เพื่อระบุฟิลด์ข้อมูลที่จะส่งคืน รวมถึงข้อมูลเวกเตอร์ เอกสาร และข้อมูลใด ๆ ใน metadata โดยค่าเริ่มต้น Chroma จะส่งคืนเอกสาร metadata และระยะทางของเวกเตอร์ คุณสามารถระบุฟิลด์ที่จะส่งคืนโดยการส่งอาร์เรย์ของชื่อฟิลด์ที่เป็นค่าเพิ่มเติมไปยังพารามิเตอร์ 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 สนับสนุนการกรองคำค้นข้อมูลโดยใช้ metadata และเนื้อหาของเอกสาร การกรองโดยใช้ where ใช้สำหรับการกรองเมตาดาต้า และการกรองโดยใช้ where_document ใช้สำหรับการกรองเนื้อหาของเอกสาร ข้างล่างเป็นการอธิบายวิธีเขียนเงื่อนไขของกรอง

การกรองโดยใช้เมตาดาต้า

เพื่อกรองเมตาดาต้า จำเป็นต้องมีพจนานุกรมกรอง where สำหรับคำค้น เพจนานุกรมจำเป็นต้องมีโครงสร้างดังต่อไปนี้

{
    "metadata_field": {
        <Operator>: <Value>
    }
}

การกรองเมตาดาต้าสนับสนุนตัวดำเนินการต่อไปนี้:

  • $eq - เท่ากับ (string, integer, float)
  • $ne - ไม่เท่ากับ (string, integer, float)
  • $gt - มากกว่า (int, float)
  • $gte - มากกว่าหรือเท่ากับ (int, float)
  • $lt - น้อยกว่า (integer, float)
  • $lte - น้อยกว่าหรือเท่ากับ (int, float)

การใช้ตัวดำเนินการ $eq เทียบเท่ากับการใช้กรอง where

{
    "metadata_field": "search_string"
}


{
    "metadata_field": {
        "$eq": "search_string"
    }
}

การกรองเนื้อหาของเอกสาร

เพื่อกรองเนื้อหาของเอกสาร จำเป็นต้องมีพจนานุกรมกรอง where_document สำหรับคำค้น เพจนานุกรมจำเป็นต้องมีโครงสร้างดังต่อไปนี้

{
    "$contains": "search_string"
}

การใช้ตัวดำเนินการตรรกะ

คุณยังสามารถใช้ตัวดำเนินการตรรกะ $and และ $or เพื่อรวมตัวกรองหลายรายการเข้าด้วยกัน

ตัวดำเเนินการ $and จะส่งคืนผลลัพธ์ที่ตรงกับทุกตัวกรองในรายการ

{
    "$and": [
        {
            "metadata_field": {
                <Operator>: <Value>
            }
        },
        {
            "metadata_field": {
                <Operator>: <Value>
            }
        }
    ]
}

ตัวดำเเนินการ $or จะส่งคืนผลลัพธ์ที่ตรงกับเงื่อนไขการกรองใดก็ได้ในรายการ

{
    "$or": [
        {
            "metadata_field": {
                <Operator>: <Value>
            }
        },
        {
            "metadata_field": {
                <Operator>: <Value>
            }
        }
    ]
}

การอัพเดตข้อมูล

Chroma ยังรองรับการดำเนินการ 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"]
})

การลบข้อมูล

Chroma รองรับการใช้ .delete เพื่อลบข้อมูลจากคอลเลคชันโดยใช้รหัส

await collection.delete({
    ids: ["id1", "id2", "id3",...], //ids
    where: {"chapter": "20"} //where
})