集合與資料管理
以下以 Python Client 為例,說明 Chroma 集合(Collection)的建立、管理,以及集合內資料的新增、修改與刪除;不介紹資料取得或查詢。
## 1. 建立 Chroma Client
```python
import chromadb
# 持久化到本機磁碟
client = chromadb.PersistentClient(path="./chroma_data")
```
若使用 Chroma Server,也可以使用 HTTP Client:
```python
client = chromadb.HttpClient(
host="localhost",
port=8000
)
```
- `PersistentClient`:資料儲存在本機指定目錄。
- `HttpClient`:透過 HTTP 連接遠端 Chroma Server。
---
## 2. 建立 Collection
### 2.1 使用 `create_collection`
```python
collection = client.create_collection(
name="documents",
metadata={
"description": "文件集合",
"hnsw:space": "cosine"
}
)
```
常見的 `hnsw:space` 距離設定:
- `"l2"`:歐氏距離
- `"cosine"`:餘弦距離
- `"ip"`:內積
如果指定名稱的 Collection 已存在,`create_collection()` 通常會產生錯誤。
---
### 2.2 使用 `get_or_create_collection`
如果不確定 Collection 是否已存在,可以使用:
```python
collection = client.get_or_create_collection(
name="documents",
metadata={
"description": "文件集合",
"hnsw:space": "cosine"
}
)
```
這個方法的行為是:
- 不存在時建立 Collection。
- 已存在時使用既有 Collection。
- 適合應用程式啟動時初始化資料庫。
---
## 3. Collection 的管理
### 3.1 列出 Collection
```python
collections = client.list_collections()
for item in collections:
print(item)
```
這是管理 Collection 用途,而不是取得集合內的資料。
---
### 3.2 修改 Collection 名稱與 Metadata
```python
collection.modify(
name="knowledge_documents",
metadata={
"description": "知識庫文件"
}
)
```
修改後,原本的變數仍可能指向同一個 Collection 物件,但之後應以新的名稱管理它。
要注意:
- `name` 必須符合 Chroma 的名稱規則。
- Collection 名稱通常必須是唯一的。
- Metadata 更新時,建議傳入完整的 Metadata,不要假設系統會自動合併所有舊欄位。
- `hnsw:space` 等索引相關設定通常應在建立 Collection 時決定,建立後不宜任意變更。
---
### 3.3 刪除整個 Collection
```python
client.delete_collection(name="documents")
```
這會刪除:
- Collection 本身
- Collection 內所有文件
- 相關 Embedding 與 Metadata
此操作通常不可復原,因此應避免在未確認名稱時直接執行。
---
## 4. 新增資料
Collection 中的每筆資料都必須有唯一的 `id`。
### 4.1 新增文件,讓 Chroma 自動產生 Embedding
```python
collection.add(
ids=["doc-001", "doc-002"],
documents=[
"Chroma 是一個向量資料庫。",
"Collection 用來管理一組相關資料。"
],
metadatas=[
{
"source": "manual",
"category": "database"
},
{
"source": "manual",
"category": "collection"
}
]
)
```
使用 `documents` 時,Chroma 會透過 Collection 設定的 Embedding Function 產生向量。
欄位必須符合以下條件:
- `ids` 中每個 ID 必須唯一。
- `documents`、`metadatas` 的筆數必須和 `ids` 相同。
- Metadata 的值通常應為字串、數字或布林值等簡單型別。
- 同一個 Collection 中的向量維度必須一致。
---
### 4.2 直接新增已產生的 Embedding
如果應用程式已經自行產生向量,可以直接傳入 `embeddings`:
```python
collection.add(
ids=["vec-001", "vec-002"],
embeddings=[
[0.12, 0.34, 0.56],
[0.23, 0.45, 0.67]
],
metadatas=[
{"source": "external"},
{"source": "external"}
],
documents=[
"第一筆向量對應的文字",
"第二筆向量對應的文字"
]
)
```
注意:
- 所有 Embedding 必須有相同維度。
- 若自行傳入 Embedding,後續新增資料也必須使用相容的向量模型。
- 不同模型產生的向量通常不應混在同一個 Collection 中。
---
### 4.3 ID 不可重複
```python
collection.add(
ids=["doc-001"],
documents=["另一份文件"]
)
```
如果 `doc-001` 已存在,`add()` 不適合用來覆蓋原資料,通常會發生重複 ID 錯誤。這種情況應改用 `update()` 或 `upsert()`。
---
## 5. 修改資料
### 5.1 修改文件內容
```python
collection.update(
ids=["doc-001"],
documents=[
"這是修改後的文件內容。"
]
)
```
`update()` 通常用於已存在的 ID。
---
### 5.2 修改 Metadata
```python
collection.update(
ids=["doc-001"],
metadatas=[
{
"source": "updated_manual",
"category": "database",
"version": 2
}
]
)
```
建議修改 Metadata 時,傳入該筆資料完整的 Metadata,避免不小心遺失原本欄位。
---
### 5.3 同時修改文件、Metadata 與 Embedding
```python
collection.update(
ids=["doc-001"],
documents=["更新後的文件內容"],
metadatas=[
{
"source": "manual",
"category": "database",
"version": 2
}
],
embeddings=[
[0.15, 0.37, 0.59]
]
)
```
如果文件內容改變,而系統使用向量進行相似度運算,通常也應同步更新 Embedding。否則文件文字與向量可能不一致。
---
### 5.4 使用 `upsert`:有則修改、無則新增
```python
collection.upsert(
ids=["doc-001", "doc-003"],
documents=[
"已存在的文件,將被更新。",
"不存在的文件,將被新增。"
],
metadatas=[
{"version": 2},
{"version": 1}
]
)
```
`upsert()` 的行為:
- ID 已存在:更新該筆資料。
- ID 不存在:新增該筆資料。
適合同步外部資料來源,例如定期將文件資料寫入 Chroma。
---
## 6. 刪除資料
### 6.1 依 ID 刪除
```python
collection.delete(
ids=["doc-001", "doc-002"]
)
```
這會刪除指定 ID 的資料。
---
### 6.2 依 Metadata 條件刪除
```python
collection.delete(
where={
"category": "temporary"
}
)
```
也可以使用比較運算條件:
```python
collection.delete(
where={
"version": {
"$lt": 2
}
}
)
```
常見條件運算子包括:
- `$eq`:等於
- `$ne`:不等於
- `$gt`:大於
- `$gte`:大於或等於
- `$lt`:小於
- `$lte`:小於或等於
- `$in`:值存在於指定清單
- `$nin`:值不存在於指定清單
例如:
```python
collection.delete(
where={
"source": {
"$in": ["test", "temporary"]
}
}
)
```
---
### 6.3 依文件內容條件刪除
```python
collection.delete(
where_document={
"$contains": "測試資料"
}
)
```
這會刪除文件內容包含指定文字的資料。
刪除條件可能造成大量資料被移除,因此正式環境應先確認條件範圍,並避免使用過於寬鬆的條件。
---
## 7. 常用操作整理
| 操作 | 方法 | 用途 |
|---|---|---|
| 建立 Collection | `client.create_collection()` | 建立新的集合 |
| 建立或使用既有 Collection | `client.get_or_create_collection()` | 初始化時避免重複建立 |
| 修改 Collection | `collection.modify()` | 修改名稱或 Metadata |
| 刪除 Collection | `client.delete_collection()` | 刪除整個集合 |
| 新增資料 | `collection.add()` | 只新增不存在的 ID |
| 修改資料 | `collection.update()` | 修改已存在的 ID |
| 新增或修改 | `collection.upsert()` | ID 存在則更新,不存在則新增 |
| 刪除資料 | `collection.delete()` | 依 ID 或條件刪除 |
核心原則是:`id` 是每筆資料的唯一識別碼;`add()` 負責新增、`update()` 負責修改、`upsert()` 負責新增或覆蓋,而 `delete()` 可依 ID 或 Metadata 條件移除資料。
相關學習地圖、教學課程
Python 人工智慧