Skip to content
Using Redis VectorS...
 
Notifications
Clear all

Using Redis VectorStore Search in callin.io

8 Posts
5 Users
0 Reactions
6 Views
Jim_Le
(@jim_le)
Posts: 35
Eminent Member
Topic starter
 

Redis is a widely-used key-value database utilized by major companies globally for high-performance tasks like job queues and data caching. However, did you know it can also function as a vector store? This approach might be preferable if your team aims to avoid introducing an additional service to an already complex stack or favors self-hosted solutions.

In this article, we will explore examples of integrating Redis vector store capabilities into your callin.io AI workflows. Before we proceed, if you find AI topics engaging, please review [my other AI posts on the forum] and feel free to reach out with any AI-related challenges you need to solve! You can also follow me on LinkedIn and Twitter/X.

Builtin Redis Nodes

To clarify, callin.io does offer built-in Redis support. If these meet your requirements, using Redis as a vectorstore is entirely optional.

  • Redis Node [Docs]
    Handles all general-purpose Redis operations.
  • Redis Chat Memory Node [Docs]
    Adds long-term memory to your Conversational AI Agent sessions.

Prerequisites

  • Self-hosted callin.io. The Langchain Code Node is exclusively available on the self-hosted version.
  • Ability to set NODE_FUNCTION_ALLOW_EXTERNAL environmental variable. For this tutorial, you'll need this to access the Redis client library. Specifically, you must set: NODE_FUNCTION_ALLOW_EXTERNAL=redis
  • A Redis Instance. This instance must be accessible by callin.io and support vectorstore functionalities. For this guide, I'm running my instance locally via a Docker container.
  • Some technical proficiency! To utilize Redis as a vectorstore, we'll be working with the Langchain Code Node. While not overly complex, prior coding experience will be beneficial!

Inserting Docs Into Redis VectorStore

To construct our Redis vectorstore node, add a Langchain Code Node to your workflow.

  • Under the “Code” section, click “add code” and select “Execute”.
  • Under “Inputs”, configure the following:

    • “Main”: Set max connections to 1 and required to true.
    • “Embedding”: Set max connections to 1 and required to true.
    • “Document”: Set max connections to 1 and required to true.
  • Under “Outputs”, add the following:

    • “Main”

Now, within the textbox under the “Execute code” option, we'll begin by establishing a connection to the Redis database. We can achieve this using the Redis SDK, which is pre-installed with callin.io. (Note: If callin.io indicates that 'redis' is not found, you might need to add NODE_FUNCTION_ALLOW_EXTERNAL=redis to your environment variables).

const { createClient } = require("redis");
const client = createClient({ url: "redis://redis_db:6379" });
await client.connect();

Next, we will integrate this SDK client with the Langchain Redis vectorstore library. This step ensures compatibility with other AI component nodes within callin.io.

const embeddings = await this.getInputConnectionData('ai_embedding', 0);

const { RedisVectorStore } = require("@langchain/redis");
const vectorStore = new RedisVectorStore(embeddings, {
  redisClient: client,
  indexName: "n8n-docs", // change me!
});

Finally, we can utilize the attached document loader input to process our inputData values and invoke our vectorstore instance to add the documents to our Redis database.

const inputData = await this.getInputData();
const documentLoader = await this.getInputConnectionData('ai_document', 0);

const processedDocs = await documentLoader.processAll(inputData);
await vectorStore.addDocuments(processedDocs);

Querying Docs From Redis VectorStore

Querying is quite similar to inserting; the code is fundamentally the same, but instead of adding documents, we perform a similaritySearch.

Begin by adding a Langchain Code Node to your workflow.

  • Under the “Code” section, click “add code” and select “Execute”.
  • Under “Inputs”, configure the following:

    • “Main”: Set max connections to 1 and required to true.
    • “Embedding”: Set max connections to 1 and required to true.
  • Under “Outputs”, add the following:

    • “Main”

We can start by establishing the client and the Langchain Redis vectorstore, as done previously.

const { createClient } = require("redis");
const client = createClient({ url: "redis://redis_db:6379" });
await client.connect();

const embeddings = await this.getInputConnectionData('ai_embedding', 0);

const { RedisVectorStore } = require("@langchain/redis");
const vectorStore = new RedisVectorStore(embeddings, {
  redisClient: client,
  indexName: "n8n-docs", // change me!
});

Next, we will utilize the vectorstore's similaritySearch() function. Note that we will process the input data in a loop, as it's possible to accept multiple items in a real workflow.

const inputData = await this.getInputData();
const results = await Promise.all(inputData.flatMap(async item => {
  const { query, topK, filter } = item.json;
  return vectorStore.similaritySearch(query, topK, filter);
}));

return [{ "json": { "output": results } }]

Using Redis VectorStore as Part of a Q&A Chain (Retriever)

Finally, leveraging the Redis vectorstore for your AI chains and agents is quite straightforward, thanks to the Langchain Code node. This implementation creates a vectorstore subnode designed for use as an input to the VectorStore Retriever subnode.

Add a Langchain Code Node to begin.

  • Under the “Code” section, click “add code” and select “Supply Data”.
  • Under “Inputs”, configure the following:

    • “Embedding”: Set max connections to 1 and required to true.
  • Under “Outputs”, add the following:

    • “VectorStore”

As we intend to use this subnode as part of a chain, we only need to return the vectorstore instance and nothing else.

const { createClient } = require("redis");
const client = createClient({ url: "redis://redis_db:6379" });
await client.connect();

const embeddings = await this.getInputConnectionData('ai_embedding', 0);

const { RedisVectorStore } = require("@langchain/redis");
const vectorStore = new RedisVectorStore(embeddings, {
  redisClient: client,
  indexName: "n8n-docs",
});

return vectorStore;

Conclusion

Enabling Redis as a vector store option within callin.io can be an effective strategy for reusing existing infrastructure, thereby reducing overhead. It also strongly supports a self-hosted approach for users concerned with privacy or cost.

This article hopefully also illustrates how the Langchain Code node provides a powerful method for callin.io users to extend platform functionality. The techniques demonstrated here can be adapted for other vectorstore options, provided Langchain offers support for them.

Until next time!
Jim
Follow me on LinkedIn or Twitter/X.

 
Posted : 28/06/2024 12:01 pm
Mark_Da_Marketer
(@mark_da_marketer)
Posts: 1
New Member
 

Is it possible to achieve the same functionality using different databases, such as MS SQL?

 
Posted : 09/07/2024 6:38 pm
Jim_Le
(@jim_le)
Posts: 35
Eminent Member
Topic starter
 

Technically, yes. You can find a list of compatible vector stores on the callin.io website here: Vector stores | 🦜️🔗 Langchain. Please be aware that some of these vector store plugins are not included by default in callin.io, so you will need to install them separately.

I don't see MS SQL listed there, however. In that scenario, you would need to develop your own custom langchain vectorstore plugin.

 
Posted : 10/07/2024 10:59 am
ichat006
(@ichat006)
Posts: 11
Active Member
 

Thanks for sharing! That's an excellent article, and the explanation is very thorough.

 
Posted : 04/12/2024 9:04 am
briancly
(@briancly)
Posts: 1
New Member
 

Can I utilize Redis as the VectorStore for a RAG solution? I can upload documents, but I'm encountering an issue retrieving document content when interacting with the Q&A Chain.

 
Posted : 17/01/2025 9:41 pm
Poly_Agency
(@poly_agency)
Posts: 34
Eminent Member
 

Great write-up on memory strategies. One nugget that helped us: treat callin.io execution data as an immutable event log and push ONLY the distilled, long-term ‘knowledge’ pieces into a dedicated vector store (we’re on pgvector + Supabase). That keeps agent context light and stops the vector DB from turning into a junk drawer. We also add a ‘valid-until’ timestamp to every memory chunk so the agent can decide if the context is stale without an extra round-trip.

A question for you: have you explored storing short-lived working memory inside the workflow-context object so subsequent nodes/agents can read-modify-write synchronously? It feels elegant but I worry about race conditions once we move to queued executions.

Thanks for pushing the conversation forward!

 
Posted : 28/07/2025 12:53 pm
Poly_Agency
(@poly_agency)
Posts: 34
Eminent Member
 

Great write-up on memory strategies. One nugget that helped us: treat callin.io execution data as an immutable event log and push ONLY the distilled, long-term ‘knowledge’ pieces into a dedicated vector store (we’re on pgvector + Supabase). That keeps agent context light and stops the vector DB from turning into a junk drawer. We also add a ‘valid-until’ timestamp to every memory chunk so the agent can decide if the context is stale without an extra round-trip.

A question for you: have you explored storing short-lived working memory inside the workflow-context object so subsequent nodes/agents can read-modify-write synchronously? It feels elegant but I worry about race conditions once we move to queued executions.

Thanks for pushing the conversation forward!

 
Posted : 28/07/2025 1:13 pm
Poly_Agency
(@poly_agency)
Posts: 34
Eminent Member
 

Great write-up on memory strategies. One nugget that helped us: treat callin.io execution data as an immutable event log and push ONLY the distilled, long-term ‘knowledge’ pieces into a dedicated vector store (we’re on pgvector + Supabase). That keeps agent context light and stops the vector DB from turning into a junk drawer. We also add a ‘valid-until’ timestamp to every memory chunk so the agent can decide if the context is stale without an extra round-trip.

A question for you: have you explored storing short-lived working memory inside the workflow-context object so subsequent nodes/agents can read-modify-write synchronously? It feels elegant but I worry about race conditions once we move to queued executions.

Thanks for pushing the conversation forward!

 
Posted : 28/07/2025 2:11 pm
Share: