惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
T
Threat Research - Cisco Blogs
H
Hacker News: Front Page
N
News and Events Feed by Topic
Know Your Adversary
Know Your Adversary
Cisco Talos Blog
Cisco Talos Blog
SecWiki News
SecWiki News
C
Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tor Project blog
K
Kaspersky official blog
Forbes - Security
Forbes - Security
Webroot Blog
Webroot Blog
Schneier on Security
Schneier on Security
P
Privacy & Cybersecurity Law Blog
H
Heimdal Security Blog
Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog
S
SegmentFault 最新的问题
V
Vulnerabilities – Threatpost
T
Tenable Blog
T
Tailwind CSS Blog
P
Privacy International News Feed
WordPress大学
WordPress大学
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
博客园 - Franky
Hacker News: Ask HN
Hacker News: Ask HN
Jina AI
Jina AI
C
Cybersecurity and Infrastructure Security Agency CISA
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
雷峰网
雷峰网
Vercel News
Vercel News
A
About on SuperTechFans
爱范儿
爱范儿
Simon Willison's Weblog
Simon Willison's Weblog
AWS News Blog
AWS News Blog
The Last Watchdog
The Last Watchdog
Engineering at Meta
Engineering at Meta
Spread Privacy
Spread Privacy
Security Archives - TechRepublic
Security Archives - TechRepublic
博客园 - 司徒正美
量子位
博客园 - 三生石上(FineUI控件)
J
Java Code Geeks
Hacker News - Newest:
Hacker News - Newest: "LLM"
Recorded Future
Recorded Future
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Martin Fowler
Martin Fowler
Project Zero
Project Zero

博客园 - 慕尘

在浏览器跑 Qwen2.5 使用 WSL 在 Windows 上安装 Linux LangExtract pgvector Goose trafilatura unstructured python里使用Playwright python的jieba MinGW nomic-embed-text 解析非结构化数据 LangChain 的 DocumentLoader 能够使用require但不能使用import ChromaDB nvm-windows 使用js实现文字转语音 pyttsx3 Ollama笔记
向量数据库 Faiss
慕尘 · 2025-03-24 · via 博客园 - 慕尘

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

使用

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