向量数据库 Faiss

Faiss(Facebook AI Similarity Search)是由 Facebook AI Research (FAIR) 开发的高效向量相似性搜索库

npm install faiss-node

使用

import pkg from 'faiss-node';
const { IndexFlatL2, Index, IndexFlatIP, MetricType } = pkg;

// 定义向量维度为 2
const dimension = 2;

// 创建一个 L2 距离的 Flat 索引
const index = new IndexFlatL2(dimension);

// 输出索引的维度、是否训练完成以及当前存储的向量数量
console.log(index.getDimension()); // 2
console.log(index.isTrained()); // true
console.log(index.ntotal()); // 0
console.log("========================================")
// 向索引中插入数据
index.add([1, 0]); // 插入向量 [1, 0]
index.add([1, 2]); // 插入向量 [1, 2]
index.add([1, 3]); // 插入向量 [1, 3]
index.add([1, 1]); // 插入向量 [1, 1]
// 输出当前索引中存储的向量数量
console.log(index.ntotal()); // 4

// 设置查询最近邻的数量 k=4,并执行搜索
const k = 4;
const results = index.search([1, 0], k); // 查询与向量 [1, 0] 最近的 4 个向量
console.log("labels:",results.labels); // 输出匹配的向量 ID [ 0, 3, 1, 2 ]
//distance = sqrt((x1 - y1)^2 + (x2 - y2)^2 + ... + (xn - yn)^2)
console.log("distances:",results.distances); // 输出对应的 L2 距离 [ 0, 1, 4, 9 ]
console.log("========================================")
// 将索引保存到文件
const fname = 'faiss.index';
index.write(fname); // 保存索引到文件 'faiss.index'

// 从文件加载索引
const index_loaded = IndexFlatL2.read(fname); // 从文件读取索引
console.log(index_loaded.getDimension()); // 输出加载索引的维度 2
console.log(index_loaded.ntotal()); // 输出加载索引中存储的向量数量 4
const results1 = index_loaded.search([1, 1], 4); // 查询与向量 [1, 1] 最近的 4 个向量
console.log("labels:",results1.labels); // 输出匹配的向量 ID [ 3, 0, 1, 2 ]
console.log("distances:",results1.distances); // 输出对应的 L2 距离 [ 0, 1, 1, 4 ]
console.log("========================================")

// 创建一个新的 L2 索引并合并现有索引的数据
const newIndex = new IndexFlatL2(dimension); // 创建新的索引
newIndex.mergeFrom(index); // 将现有索引的数据合并到新索引
console.log(newIndex.ntotal()); // 输出新索引中存储的向量数量 4
console.log("========================================")

// 删除指定 ID 的向量
console.log(newIndex.search([1, 2], 1)); // 查询与向量 [1, 2] 最近的 1 个向量
const removedCount = newIndex.removeIds([0]); // 删除 ID 为 0 的向量
console.log(removedCount); // 输出删除的向量数量 1
console.log(newIndex.ntotal()); // 输出新索引中剩余的向量数量 3
console.log(newIndex.search([1, 2], 1)); // 再次查询与向量 [1, 2] 最近的 1 个向量
console.log("========================================")

// 创建一个内积距离的 Flat 索引
const ipIndex = new IndexFlatIP(2); // 创建内积距离索引
ipIndex.add([1, 0]); // 插入向量 [1, 0]
// 将索引序列化为缓冲区并反序列化
const index_buf = newIndex.toBuffer(); // 将索引序列化为缓冲区
const deserializedIndex = Index.fromBuffer(index_buf); // 从缓冲区反序列化索引
console.log(deserializedIndex.ntotal()); // 输出反序列化索引中存储的向量数量 3
console.log("========================================")

// 使用工厂方法创建 HNSW 索引,使用内积作为距离度量
const hnswIndex = Index.fromFactory(2, 'HNSW,Flat', MetricType.METRIC_INNER_PRODUCT); // 创建 HNSW 索引
const x = [1, 0, 0, 1]; // 定义训练数据
hnswIndex.train(x); // 训练索引
hnswIndex.add(x); // 插入训练数据
// 定义查询向量
const queryVector = [1, 0];
// 执行搜索,内积公式:dotProduct = sum(x[i] * y[i]),即两个向量对应元素相乘后求和
const searchResults = hnswIndex.search(queryVector, 1);
// 输出搜索结果
console.log("labels:", searchResults.labels); // 输出匹配的向量 ID
console.log("distances:", searchResults.distances); // 输出对应的内积距离

 

在LangChain简单示例

安装

npm install @langchain/community @langchain/ollama

应用

import { FaissStore } from "@langchain/community/vectorstores/faiss";
import { OllamaEmbeddings } from "@langchain/ollama";
const embeddings = new OllamaEmbeddings({
    baseUrl: "http://XX.XX.XX.XX:11434", // Default value
    model: "nomic-embed-text:latest",
});
// console.log(embeddings)
const vectorStore = await FaissStore.fromTexts(
  ["Hello world", "Bye bye", "hello nice world"],
  [{ id: 2 }, { id: 1 }, { id: 3 }],
  embeddings
);

const resultOne = await vectorStore.similaritySearch("hello world", 1);
console.log(resultOne);

https://github.com/ewfian/faiss-node

https://js.langchain.com.cn/docs/modules/indexes/vector_stores/integrations/faiss

posted @ 2025-03-24 10:26  慕尘  阅读(245)  评论(0)    收藏  举报