คู่มือการพัฒนาละเอียดเกี่ยวกับ Python Chromadb
การติดตั้ง
pip install chromadb
การจัดเก็บข้อมูลของ Chromadb
import chromadb
คุณสามารถกำหนดเส้นทางที่ใช้เก็บไฟล์ฐานข้อมูลของ Chroma ได้ หากมีข้อมูลอยู่แล้ว ไฟล์ฐานข้อมูลจะถูกโหลดโดยอัตโนมัติเมื่อโปรแกรมเริ่มทำงาน
client = chromadb.PersistentClient(path="/data/tizi365.db")
พารามิเตอร์ path
คือเส้นทางไปยังไฟล์ฐานข้อมูลของ Chroma
หมายเหตุ: สำหรับฐานข้อมูลของ Chroma การสร้างวัตถุไคลเอ็นต์ครั้งเดียวพอ การโหลดและบันทึกลูกค้าหลายๆ คนในเส้นทางเดียวกันอาจนำไปสู่พฤติกรรมที่ไม่คาดคิด เช่นการลบข้อมูล โดยทั่วไปแล้วแค่สร้างไคลเอ็นต์ Chroma คนเดียวในแอพพลิเคชั่นก็พอเพียง
ฟังก์ชันที่ใช้บ่อยของวัตถุไคลเอ็นต์:
client.reset() # ล้างและรีเซ็ตฐานข้อมูลอย่างสมบูรณ์
การดำเนินการของคอลเล็กชัน
Chromadb ใช้คอลเล็กชัน collection
เพื่อการบริหารจัดการกับข้อมูลเวกเตอร์ซึ่งสามารถเปรียบเสมือนกับตารางใน MYSQL
การสร้าง การดู และลบคอลเล็กชัน
Chroma ใช้ชื่อคอลเล็กชันใน URL ดังนั้นมีหลายข้อจำกัดในการตั้งชื่อ:
- ความยาวของชื่อต้องอยู่ระหว่าง 3 ถึง 63 ตัวอักษร
- ชื่อต้องขึ้นต้นและลงท้ายด้วยตัวอักษรพิมพ์เล็กหรือตัวเลข และสามารถมีจุด, ขีดล่าง, และขีดบรรจุในระหว่าง
- ชื่อไม่สามารถมีจุดสองติดกัน
- ชื่อไม่สามารถเป็นที่อยู่ IP ที่ถูกต้อง
เพื่อสร้างคอลเล็กชัน คุณจำเป็นต้องระบุชื่อคอลเล็กชันและฟังก์ชันการคำนวณเวกเตอร์ทางเลือก (เรียกว่าฟังก์ชันฝังตัว) หากมีฟังก์ชันฝังตัวจะต้องระบุทุกครั้งที่มีการเข้าถึงคอลเล็กชัน
หมายเหตุ: วัตถุของฟังก์ชันการคำนวณเวกเตอร์ (ฟังก์ชันฝังตัว) มีวัตถุคือคำนวณเวกเตอร์ข้อความ
collection = client.create_collection(name="my_collection", embedding_function=emb_fn)
collection = client.get_collection(name="my_collection", embedding_function=emb_fn)
ฟังก์ชันฝังตัวรับข้อความเป็นอินพุตและคืนเวกเตอร์ที่คำนวณได้
หมายเหตุ: ผู้เริ่มต้นสามารถเรียนรู้เกี่ยวกับคู่มือการเรียนรู้โมเดลการฝังข้อความ
คุณสามารถอ้างอิงถึงคอลเล็กชันที่มีอยู่ด้วยฟังก์ชัน .get_collection
และใช้ .delete_collection
เพื่อลบคอลเล็กชัน คุณยังสามารถใช้ .get_or_create_collection
เพื่ออ้างถึงคอลเล็กชัน (หากมีอยู่) หรือสร้างมันหากไม่มี
collection = client.get_collection(name="tizi365")
collection = client.get_or_create_collection(name="tizi365")
client.delete_collection(name="tizi365")
ดำเนินการของคอลเล็กชันที่ใช้บ่อยอื่นๆ:
collection.peek() # คืนค่าลิสต์ของข้อมูล 10 ตัวแรกในคอลเล็กชัน
collection.count() # คืนค่าจำนวนรวมของข้อมูลในคอลเล็กชัน
collection.modify(name="new_name") # เปลี่ยนชื่อคอลเล็กชัน
การกำหนดวิธีการคำนวณระยะห่างของเวกเตอร์
ฟังก์ชัน create_collection
ยังรวมพารามิเตอร์ข้อมูลเสริมที่เป็นทางเลือกด้วย โดยการตั้งค่าของ hnsw:space
เพื่อปรับแต่งวิธีการคำนวณระยะห่างของเวกเตอร์
หมายเหตุ: ข้อมูลเวกเตอร์แทนความคล้ายคลึงระหว่างเวกเตอร์โดยการคำนวณระยะห่างของพื้นที่ระหว่างเวกเตอร์ ระยะห่างที่ใกล้ที่สุด ความคล้ายคลึงสูงขึ้นและถกลับกัน
collection = client.create_collection(
name="collection_name",
metadata={"hnsw:space": "cosine"} # l2 เป็นวิธีการคำนวณเริ่มต้น
)
ตัวเลือกที่ถูกต้องสำหรับ hnsw:space
คือ "l2", "ip", หรือ "cosine" เริ่มต้นคือ "l2"
เพิ่มข้อมูลลงในคอลเล็กชัน
ใช้ .add
เมท็อดเพื่อเพิ่มข้อมูลลงใน Chroma
เพิ่มข้อมูลโดยตรงโดยไม่ระบุเวกเตอร์ของเอกสาร:
collection.add(
documents=["lorem ipsum...", "doc2", "doc3", ...],
metadatas=[{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
ids=["id1", "id2", "id3", ...]
)
หาก Chroma ได้รับรายการของเอกสาร จะใช้ฟังก์ชันเวกเตอร์ของคอลเล็กชันเพื่อคำนวณเวกเตอร์สำหรับเอกสารโดยอัตโนมัติ (หากไม่มีการระบุฟังก์ชันเวกเตอร์เมื่อสร้างคอลเล็กชัน ค่าเริ่มต้นจะถูกใช้) Chroma ยังจะเก็บเอกสารเองด้วย หากเอกสารมีขนาดใหญ่เกินไปที่จะคำนวณโดยใช้ฟังก์ชันเวกเตอร์ที่ถูกเลือก ข้อยกเว้นจะเกิดขึ้น
แต่ละเอกสารต้องมี ID ที่ไม่ซ้ำกัน (ids) การเพิ่ม ID เดียวกันสองครั้งจะทำให้การจัดเก็บค่าเริ่มต้นอย่างเดียว เพิ่มเติมได้ที่คุณสามารถให้รายการของพจนานุกรมเมตาดาต้า (metadatas) สำหรับแต่ละเอกสารเพื่อเก็บข้อมูลเพิ่มเติมที่สามารถใช้สำหรับการกรองข้อมูลระหว่างการค้นหา
ในกรณีอื่น ๆ คุณสามารถให้รายการของข้อมูลเวกเตอร์ที่เกี่ยวข้องกับเอกสารโดยตรง และ Chroma จะใช้ข้อมูลเวกเตอร์ที่คุณให้โดยไม่คำนวณเวกเตอร์โดยอัตโนมัติ
collection.add(
documents=["doc1", "doc2", "doc3", ...],
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"}, ...],
ids=["id1", "id2", "id3", ...]
)
หากมิติข้อมูลเวกเตอร์ที่ให้ไม่ตรงกับมิติของคอลเล็กชัน จะเกิดข้อยกเว้นขึ้น
คุณยังสามารถเก็บเอกสารที่อื่นไว้และให้ Chroma ด้วยข้อมูลเวกเตอร์และรายการเมตาดาต้า คุณสามารถใช้ id เพื่อเชื่อมโยงเวกเตอร์กับเอกสารที่เก็บไว้ที่อื่น
collection.add(
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"}, ...],
ids=["id1", "id2", "id3", ...]
)
หมายเหตุ: ฟังก์ชันหลักของฐานข้อมูลเวกเตอร์คือการค้นหาความคล้ายคลึงแบบปรากฎทางวรรณคดีโดยใช้ข้อมูลเวกเตอร์ เพื่อลดขนาดของฐานข้อมูลเวกเตอร์และปรับประสิทธิภาพให้ดียิ่งขึ้น เราสามารถเลือกที่จะจัดเก็บข้อมูลเวกเตอร์และคุณลักษณะในการกรองที่จำเป็นบางอย่างในฐานข้อมูลเวกเตอร์ ข้อมูลอื่น ๆ เช่น เนื้อหาบทความ สามารถเก็บไว้ในฐานข้อมูลเช่น MYSQL โดยเพียงแต่เชื่อมโยงผ่าน IDs ได้
การสอบถามข้อมูลชุดข้อมูล
เมธอด .query สามารถใช้ในการสอบถามชุดข้อมูล Chroma ในหลายรูปแบบ
คุณสามารถสอบถามโดยใช้ชุด query_embeddings (ข้อมูลเวกเตอร์)
เคล็ดลับ: ในสถานการณ์การพัฒนาจริง ๆ query_embeddings มักจะได้รับโดยการคำนวณเวกเตอร์ของคำค้นของผู้ใช้ผ่านโมเดล text embedding ก่อน แล้วจึงใช้เวกเตอร์นี้ในการสอบถามเนื้อหาที่คล้ายกัน
collection.query(
query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
n_results=10,
where={"metadata_field": "is_equal_to_this"},
where_document={"$contains":"search_string"}
)
การสอบถามจะคืนผลลัพธ์ที่ดีที่สุดสำหรับทุกเวกเตอร์คำค้น (query_embedding) ที่กำหนด ตามลำดับ สามารถให้แบบกรอง where เพื่อกรองผลลัพธ์ตาม metadata ที่เกี่ยวข้องกับทุกเอกสาร และสามารถให้แบบกรอง where_document เพื่อกรองผลลัพธ์ตามเนื้อหาของเอกสาร
หาก query_embeddings ที่ให้ไว้ไม่สอดคล้องกับมิติของชุดข้อมูล การเกิดข้อยกเว้นจะเกิดขึ้น ในการให้มิติเวกเตอร์ที่สอดคล้องกัน ให้ใช้โมเดล text embedding เดียวกันในการคำนวณเวกเตอร์
คุณยังสามารถสอบถามโดยใช้ชุด query texts ได้ Chroma จะคำนวณเวกเตอร์สำหรับแต่ละข้อความคำค้นโดยใช้ฟังก์ชันการฝังเข็มของคอลเลคชัน และจากนั้นทำการสอบถามโดยใช้เวกเตอร์ข้อความที่สร้างขึ้น
collection.query(
query_texts=["doc10", "thus spake zarathustra", ...],
n_results=10,
where={"metadata_field": "is_equal_to_this"},
where_document={"$contains":"search_string"}
)
คุณยังสามารถใช้ .get เพื่อสอบถามข้อมูลจากคอลเลคชันตาม id
collection.get(
ids=["id1", "id2", "id3", ...],
where={"style": "style1"}
)
.get ยังรองรับการกรอง where และ where_document หากไม่มี id ที่กำหนด จะคืนค่ารายการทั้งหมดในคอลเลคชันที่สอดคล้องกับ where และ where_document
การระบุฟิลด์ที่ต้องการคืน
ในการใช้ get หรือ query คุณสามารถใช้พารามิเตอร์ include เพื่อระบุข้อมูลที่ต้องการที่จะคืน-- embeddings
, documents
, หรือ metadatas
, และสำหรับ query ต้องมีการคืนข้อมูลระยะห่าง ตามค่าเริ่มต้น Chroma จะคืนเอกสารและเมตาดาต้า และคืนข้อมูลระยะห่างสำหรับการสอบถาม ในขณะที่ "ids" จะคุณสามารถระบุฟิลด์ที่ต้องการคืนโดยการส่งอาร์เรย์ของชื่อฟิลด์ไปยังพารามิเตอร์ includes ของเมท็อด query หรือ get
collection.get(
include=["documents"]
)
collection.query(
query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
include=["documents"]
)
การใช้ Where Filters
Chroma รองรับการกรองคำค้นโดยใช้ metadata และเนื้อหาของเอกสาร ฟิลเตอร์ where ใช้สำหรับกรองเมตาดาต้า และ where_document ใช้สำหรับกรองเนื้อหาเอกสาร และต่อไปนี้จะอธิบายวิธีการเขียนสูตรกรองเงื่อนไข
กรองโดย Metadata
เพื่อกรองเมตาดาต้า คุณต้องให้รายการฟิลเตอร์ 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>
}
}
]
}
การปรับปรุงข้อมูลในคอลเลกชัน
การใช้ .update
ช่วยให้คุณสามารถปรับปรุงคุณสมบัติใดๆ ของข้อมูลในคอลเลกชันได้
collection.update(
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", ...],
)
หากไม่พบ id ในคอลเลกชัน จะมีการบันทึกข้อผิดพลาดและการปรับปรุงจะถูกละทิ้ง หากเอกสารที่ให้มาไม่มีเวกเตอร์ที่สอดคล้อง ฟังก์ชันการฝังเวกเตอร์ของคอลเลกชันจะถูกใช้ในการคำนวณเวกเตอร์
หากข้อมูลเวกเตอร์ที่ให้มามีมิติที่แตกต่างกับคอลเลกชัน จะเกิดข้อยกเว้นขึ้น
Chroma ยังรองรับการดำเนินการ upsert ซึ่งสามารถปรับปรุงข้อมูลที่มีอยู่และแทรกข้อมูลใหม่หากยังไม่มีอยู่
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
เพื่อลบข้อมูลออกจากคอลเลกชันตาม id
โดยเฉพาะ และเวกเตอร์ เอกสาร และเมตาดาต้าที่เกี่ยวข้องกับแต่ละข้อมูลจะถูกลบออกด้วย
collection.delete(
ids=["id1", "id2", "id3",...],
where={"chapter": "20"}
)
.delete
ยังรองรับตัวกรอง where
หากไม่มี id ที่ให้มา จะลบรายการทั้งหมดในคอลเลกชันที่ตรงกับตัวกรอง where
ไว้