Skip to main content

如何缓存嵌入结果

¥How to cache embedding results

Prerequisites

本指南假设你熟悉以下概念:

¥This guide assumes familiarity with the following concepts:

嵌入可以存储或临时缓存,以避免重新计算。

¥Embeddings can be stored or temporarily cached to avoid needing to recompute them.

可以使用 CacheBackedEmbeddings 实例进行缓存嵌入。

¥Caching embeddings can be done using a CacheBackedEmbeddings instance.

缓存支持的嵌入器是对嵌入器的封装器,它将嵌入缓存在键值存储中。

¥The cache backed embedder is a wrapper around an embedder that caches embeddings in a key-value store.

文本经过哈希处理,哈希值用作缓存中的键。

¥The text is hashed and the hash is used as the key in the cache.

初始化 CacheBackedEmbeddings 的主要支持方式是 fromBytesStore 静态方法。这需要以下参数:

¥The main supported way to initialized a CacheBackedEmbeddings is the fromBytesStore static method. This takes in the following parameters:

  • underlyingEmbeddings:要使用的嵌入模型。

    ¥underlyingEmbeddings: The embeddings model to use.

  • documentEmbeddingCache:用于存储文档嵌入的缓存。

    ¥documentEmbeddingCache: The cache to use for storing document embeddings.

  • namespace:(可选,默认为 "")用于文档缓存的命名空间。此命名空间用于避免与其他缓存冲突。例如,你可以将其设置为所使用的嵌入模型的名称。

    ¥namespace: (optional, defaults to "") The namespace to use for document cache. This namespace is used to avoid collisions with other caches. For example, you could set it to the name of the embedding model used.

注意:请务必设置命名空间参数,以避免使用不同嵌入模型嵌入的相同文本发生冲突。

¥Attention: Be sure to set the namespace parameter to avoid collisions of the same text embedded using different embeddings models.

内存

¥In-memory

npm install @langchain/openai @langchain/community @langchain/core

这是一个带有内存缓存的基本测试示例。这种类型的缓存主要用于单元测试或原型设计。如果你需要长时间存储嵌入数据,请勿使用此缓存:

¥Here's a basic test example with an in memory cache. This type of cache is primarily useful for unit tests or prototyping. Do not use this cache if you need to actually store the embeddings for an extended period of time:

import { OpenAIEmbeddings } from "@langchain/openai";
import { CacheBackedEmbeddings } from "langchain/embeddings/cache_backed";
import { InMemoryStore } from "@langchain/core/stores";
import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
import { FaissStore } from "@langchain/community/vectorstores/faiss";
import { TextLoader } from "langchain/document_loaders/fs/text";

const underlyingEmbeddings = new OpenAIEmbeddings();

const inMemoryStore = new InMemoryStore();

const cacheBackedEmbeddings = CacheBackedEmbeddings.fromBytesStore(
underlyingEmbeddings,
inMemoryStore,
{
namespace: underlyingEmbeddings.model,
}
);

const loader = new TextLoader("./state_of_the_union.txt");
const rawDocuments = await loader.load();
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 1000,
chunkOverlap: 0,
});
const documents = await splitter.splitDocuments(rawDocuments);

// No keys logged yet since the cache is empty
for await (const key of inMemoryStore.yieldKeys()) {
console.log(key);
}

let time = Date.now();
const vectorstore = await FaissStore.fromDocuments(
documents,
cacheBackedEmbeddings
);
console.log(`Initial creation time: ${Date.now() - time}ms`);
/*
Initial creation time: 1905ms
*/

// The second time is much faster since the embeddings for the input docs have already been added to the cache
time = Date.now();
const vectorstore2 = await FaissStore.fromDocuments(
documents,
cacheBackedEmbeddings
);
console.log(`Cached creation time: ${Date.now() - time}ms`);
/*
Cached creation time: 8ms
*/

// Many keys logged with hashed values
const keys = [];
for await (const key of inMemoryStore.yieldKeys()) {
keys.push(key);
}

console.log(keys.slice(0, 5));
/*
[
'text-embedding-ada-002ea9b59e760e64bec6ee9097b5a06b0d91cb3ab64',
'text-embedding-ada-0023b424f5ed1271a6f5601add17c1b58b7c992772e',
'text-embedding-ada-002fec5d021611e1527297c5e8f485876ea82dcb111',
'text-embedding-ada-00262f72e0c2d711c6b861714ee624b28af639fdb13',
'text-embedding-ada-00262d58882330038a4e6e25ea69a938f4391541874'
]
*/

API Reference:

Redis

以下是使用 Redis 缓存的示例。

¥Here's an example with a Redis cache.

你首先需要安装 ioredis 作为对等依赖,并传入一个已初始化的客户端:

¥You'll first need to install ioredis as a peer dependency and pass in an initialized client:

npm install ioredis
import { Redis } from "ioredis";

import { OpenAIEmbeddings } from "@langchain/openai";
import { CacheBackedEmbeddings } from "langchain/embeddings/cache_backed";
import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
import { FaissStore } from "@langchain/community/vectorstores/faiss";
import { RedisByteStore } from "@langchain/community/storage/ioredis";
import { TextLoader } from "langchain/document_loaders/fs/text";

const underlyingEmbeddings = new OpenAIEmbeddings();

// Requires a Redis instance running at http://localhost:6379.
// See https://github.com/redis/ioredis for full config options.
const redisClient = new Redis();
const redisStore = new RedisByteStore({
client: redisClient,
});

const cacheBackedEmbeddings = CacheBackedEmbeddings.fromBytesStore(
underlyingEmbeddings,
redisStore,
{
namespace: underlyingEmbeddings.model,
}
);

const loader = new TextLoader("./state_of_the_union.txt");
const rawDocuments = await loader.load();
const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 1000,
chunkOverlap: 0,
});
const documents = await splitter.splitDocuments(rawDocuments);

let time = Date.now();
const vectorstore = await FaissStore.fromDocuments(
documents,
cacheBackedEmbeddings
);
console.log(`Initial creation time: ${Date.now() - time}ms`);
/*
Initial creation time: 1808ms
*/

// The second time is much faster since the embeddings for the input docs have already been added to the cache
time = Date.now();
const vectorstore2 = await FaissStore.fromDocuments(
documents,
cacheBackedEmbeddings
);
console.log(`Cached creation time: ${Date.now() - time}ms`);
/*
Cached creation time: 33ms
*/

// Many keys logged with hashed values
const keys = [];
for await (const key of redisStore.yieldKeys()) {
keys.push(key);
}

console.log(keys.slice(0, 5));
/*
[
'text-embedding-ada-002fa9ac80e1bf226b7b4dfc03ea743289a65a727b2',
'text-embedding-ada-0027dbf9c4b36e12fe1768300f145f4640342daaf22',
'text-embedding-ada-002ea9b59e760e64bec6ee9097b5a06b0d91cb3ab64',
'text-embedding-ada-002fec5d021611e1527297c5e8f485876ea82dcb111',
'text-embedding-ada-002c00f818c345da13fed9f2697b4b689338143c8c7'
]
*/

API Reference:

后续步骤

¥Next steps

现在你已经学习了如何使用缓存来避免重新计算嵌入。

¥You've now learned how to use caching to avoid recomputing embeddings.

接下来,查看 检索增强生成的完整教程

¥Next, check out the full tutorial on retrieval-augmented generation.