增加FAISS向量数据库检索存储等功能。
This commit is contained in:
@@ -0,0 +1,312 @@
|
||||
# FAISS向量管理器
|
||||
|
||||
这是一个基于FAISS的向量管理器,专为食物分类项目设计,提供了完整的向量索引管理功能。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- ✅ **FAISS索引管理**: 支持创建、保存和加载FAISS索引
|
||||
- ✅ **向量操作**: 支持向量的增删改查操作
|
||||
- ✅ **相似度搜索**: 支持余弦相似度搜索和阈值过滤
|
||||
- ✅ **批量操作**: 提供高效的批量向量操作接口
|
||||
- ✅ **元数据管理**: 支持向量元数据的存储和检索
|
||||
- ✅ **多种索引类型**: 支持不同的FAISS索引类型
|
||||
- ✅ **持久化存储**: 支持索引的保存和加载
|
||||
|
||||
## 安装依赖
|
||||
|
||||
```bash
|
||||
pip install faiss-cpu numpy
|
||||
# 或者如果需要GPU支持
|
||||
pip install faiss-gpu numpy
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 基本使用
|
||||
|
||||
```python
|
||||
from faiss.faiss_manager import FAISSManager
|
||||
import numpy as np
|
||||
|
||||
# 创建管理器
|
||||
manager = FAISSManager(
|
||||
dimension=512, # 向量维度
|
||||
index_type="IndexFlatIP", # 索引类型
|
||||
normalize_vectors=True, # 启用向量标准化
|
||||
metric_type="cosine" # 使用余弦相似度
|
||||
)
|
||||
|
||||
# 添加单个向量
|
||||
vector = np.random.random(512).astype(np.float32)
|
||||
manager.add_vector(
|
||||
vector=vector,
|
||||
vector_id="food_001",
|
||||
metadata={"name": "回锅肉", "category": "川菜", "spicy_level": 3}
|
||||
)
|
||||
|
||||
# 搜索相似向量
|
||||
query_vector = np.random.random(512).astype(np.float32)
|
||||
results = manager.search_similar(query_vector, k=5)
|
||||
|
||||
for vector_id, similarity, metadata in results:
|
||||
print(f"ID: {vector_id}, 相似度: {similarity:.4f}, 菜名: {metadata['name']}")
|
||||
```
|
||||
|
||||
### 2. 批量操作
|
||||
|
||||
```python
|
||||
# 批量添加向量
|
||||
batch_vectors = np.random.random((100, 512)).astype(np.float32)
|
||||
batch_ids = [f"food_{i:03d}" for i in range(100)]
|
||||
batch_metadata = [
|
||||
{"name": f"菜品{i}", "category": "川菜", "spicy_level": i % 5}
|
||||
for i in range(100)
|
||||
]
|
||||
|
||||
results = manager.add_vectors_batch(batch_vectors, batch_ids, batch_metadata)
|
||||
print(f"成功添加: {sum(results)}/{len(results)} 个向量")
|
||||
|
||||
# 批量删除向量
|
||||
delete_ids = [f"food_{i:03d}" for i in range(10)]
|
||||
delete_results = manager.delete_vectors_batch(delete_ids)
|
||||
print(f"成功删除: {sum(delete_results)}/{len(delete_results)} 个向量")
|
||||
```
|
||||
|
||||
### 3. 索引保存和加载
|
||||
|
||||
```python
|
||||
# 保存索引
|
||||
save_path = "./my_faiss_index"
|
||||
success = manager.save_index(save_path)
|
||||
if success:
|
||||
print("索引保存成功")
|
||||
|
||||
# 加载索引
|
||||
new_manager = FAISSManager(dimension=512)
|
||||
success = new_manager.load_index(save_path)
|
||||
if success:
|
||||
print("索引加载成功")
|
||||
|
||||
# 验证加载结果
|
||||
info = new_manager.get_index_info()
|
||||
print(f"加载的向量数量: {info['active_vectors']}")
|
||||
```
|
||||
|
||||
## API 参考
|
||||
|
||||
### FAISSManager 类
|
||||
|
||||
#### 初始化参数
|
||||
|
||||
- `dimension` (int): 向量维度
|
||||
- `index_type` (str): 索引类型,支持:
|
||||
- `"IndexFlatIP"`: 内积索引(适合余弦相似度)
|
||||
- `"IndexFlatL2"`: L2距离索引
|
||||
- `"IndexIVFFlat"`: IVF索引(适合大规模数据)
|
||||
- `"IndexHNSW"`: HNSW索引(高性能近似搜索)
|
||||
- `normalize_vectors` (bool): 是否标准化向量
|
||||
- `metric_type` (str): 距离度量类型 ("cosine", "l2", "ip")
|
||||
|
||||
#### 主要方法
|
||||
|
||||
##### 向量操作
|
||||
|
||||
```python
|
||||
# 添加单个向量
|
||||
add_vector(vector, vector_id, metadata=None) -> bool
|
||||
|
||||
# 批量添加向量
|
||||
add_vectors_batch(vectors, vector_ids, metadata_list=None) -> List[bool]
|
||||
|
||||
# 更新向量
|
||||
update_vector(vector, vector_id, metadata=None) -> bool
|
||||
|
||||
# 删除单个向量
|
||||
delete_vector(vector_id) -> bool
|
||||
|
||||
# 批量删除向量
|
||||
delete_vectors_batch(vector_ids) -> List[bool]
|
||||
```
|
||||
|
||||
##### 搜索操作
|
||||
|
||||
```python
|
||||
# 相似度搜索
|
||||
search_similar(query_vector, k=10, threshold=None) -> List[Tuple[str, float, Dict]]
|
||||
|
||||
# 根据ID获取向量信息
|
||||
get_vector_by_id(vector_id) -> Optional[Tuple[np.ndarray, Dict]]
|
||||
```
|
||||
|
||||
##### 索引管理
|
||||
|
||||
```python
|
||||
# 保存索引
|
||||
save_index(save_path) -> bool
|
||||
|
||||
# 加载索引
|
||||
load_index(load_path) -> bool
|
||||
|
||||
# 清空索引
|
||||
clear_index() -> bool
|
||||
|
||||
# 获取索引信息
|
||||
get_index_info() -> Dict[str, Any]
|
||||
```
|
||||
|
||||
## 使用场景
|
||||
|
||||
### 1. 食物图像检索
|
||||
|
||||
```python
|
||||
# 为食物分类项目设计的示例
|
||||
manager = FAISSManager(dimension=2048, index_type="IndexFlatIP")
|
||||
|
||||
# 添加食物向量(通过CNN模型提取的特征)
|
||||
food_features = extract_features_from_images(food_images) # 假设的特征提取函数
|
||||
food_metadata = [
|
||||
{"name": "回锅肉", "category": "川菜", "ingredients": ["猪肉", "青椒", "豆瓣酱"]},
|
||||
{"name": "西红柿鸡蛋", "category": "家常菜", "ingredients": ["西红柿", "鸡蛋"]},
|
||||
# ... 更多食物数据
|
||||
]
|
||||
|
||||
manager.add_vectors_batch(food_features, food_ids, food_metadata)
|
||||
|
||||
# 查询相似食物
|
||||
query_image_feature = extract_features_from_image(query_image)
|
||||
similar_foods = manager.search_similar(query_image_feature, k=5, threshold=0.7)
|
||||
|
||||
for food_id, similarity, metadata in similar_foods:
|
||||
print(f"相似食物: {metadata['name']} (相似度: {similarity:.3f})")
|
||||
```
|
||||
|
||||
### 2. 文本向量检索
|
||||
|
||||
```python
|
||||
# 用于文本相似度检索
|
||||
manager = FAISSManager(dimension=768, index_type="IndexFlatIP")
|
||||
|
||||
# 添加文本向量(通过BERT等模型编码)
|
||||
text_embeddings = encode_texts(recipe_texts) # 假设的文本编码函数
|
||||
recipe_metadata = [
|
||||
{"title": "回锅肉制作方法", "difficulty": "中等", "time": "30分钟"},
|
||||
# ... 更多菜谱数据
|
||||
]
|
||||
|
||||
manager.add_vectors_batch(text_embeddings, recipe_ids, recipe_metadata)
|
||||
|
||||
# 搜索相关菜谱
|
||||
query_embedding = encode_text("如何做川菜")
|
||||
related_recipes = manager.search_similar(query_embedding, k=3)
|
||||
```
|
||||
|
||||
## 性能优化建议
|
||||
|
||||
### 1. 索引类型选择
|
||||
|
||||
- **小规模数据 (<10K向量)**: 使用 `IndexFlatIP` 或 `IndexFlatL2`
|
||||
- **中等规模数据 (10K-1M向量)**: 使用 `IndexIVFFlat`
|
||||
- **大规模数据 (>1M向量)**: 使用 `IndexHNSW` 或更复杂的索引
|
||||
|
||||
### 2. 内存优化
|
||||
|
||||
```python
|
||||
# 对于大规模数据,考虑使用IVF索引
|
||||
manager = FAISSManager(
|
||||
dimension=512,
|
||||
index_type="IndexIVFFlat",
|
||||
normalize_vectors=True
|
||||
)
|
||||
|
||||
# 训练IVF索引(需要足够的训练数据)
|
||||
if hasattr(manager.index, 'train') and not manager.index.is_trained:
|
||||
training_vectors = np.random.random((10000, 512)).astype(np.float32)
|
||||
manager.index.train(training_vectors)
|
||||
```
|
||||
|
||||
### 3. 批量操作
|
||||
|
||||
```python
|
||||
# 优先使用批量操作而不是循环调用单个操作
|
||||
# 好的做法
|
||||
manager.add_vectors_batch(vectors, ids, metadata_list)
|
||||
|
||||
# 避免的做法
|
||||
for vector, id, metadata in zip(vectors, ids, metadata_list):
|
||||
manager.add_vector(vector, id, metadata)
|
||||
```
|
||||
|
||||
## 测试
|
||||
|
||||
运行测试以验证功能:
|
||||
|
||||
```bash
|
||||
# 运行基本测试
|
||||
python faiss/test_faiss_manager.py
|
||||
|
||||
# 运行使用示例
|
||||
python faiss/example_usage.py
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **向量维度**: 所有向量必须具有相同的维度
|
||||
2. **ID唯一性**: 向量ID必须唯一,重复ID会导致更新操作
|
||||
3. **内存使用**: FAISS索引会占用内存,大规模数据需要考虑内存限制
|
||||
4. **删除操作**: FAISS不支持真正的删除,删除操作只是标记,需要重建索引来释放空间
|
||||
5. **向量标准化**: 使用余弦相似度时建议启用向量标准化
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **维度不匹配错误**
|
||||
```python
|
||||
# 确保所有向量维度一致
|
||||
assert vector.shape[-1] == manager.dimension
|
||||
```
|
||||
|
||||
2. **索引未训练错误**
|
||||
```python
|
||||
# 对于IVF索引,需要先训练
|
||||
if hasattr(manager.index, 'train') and not manager.index.is_trained:
|
||||
manager.index.train(training_data)
|
||||
```
|
||||
|
||||
3. **内存不足**
|
||||
```python
|
||||
# 使用更节省内存的索引类型
|
||||
manager = FAISSManager(dimension=512, index_type="IndexIVFFlat")
|
||||
```
|
||||
|
||||
## 扩展功能
|
||||
|
||||
### 自定义距离度量
|
||||
|
||||
```python
|
||||
class CustomFAISSManager(FAISSManager):
|
||||
def custom_similarity_function(self, query_vector, k=10):
|
||||
"""自定义相似度计算"""
|
||||
# 实现自定义逻辑
|
||||
pass
|
||||
```
|
||||
|
||||
### 多模态检索
|
||||
|
||||
```python
|
||||
# 结合图像和文本特征
|
||||
image_manager = FAISSManager(dimension=2048, index_type="IndexFlatIP")
|
||||
text_manager = FAISSManager(dimension=768, index_type="IndexFlatIP")
|
||||
|
||||
# 融合检索结果
|
||||
def multimodal_search(image_query, text_query, alpha=0.7):
|
||||
image_results = image_manager.search_similar(image_query, k=20)
|
||||
text_results = text_manager.search_similar(text_query, k=20)
|
||||
|
||||
# 融合结果逻辑
|
||||
# ...
|
||||
```
|
||||
|
||||
## 许可证
|
||||
|
||||
本项目采用 MIT 许可证。
|
||||
Reference in New Issue
Block a user