Build a Private LLM Knowledge Base with Redis and DeepSeek4J in 10 Minutes
This tutorial shows how to harness Redis's dual role as a high‑performance cache and a vector database, guiding you through Docker setup, vector storage methods, and Java Lettuce integration to build a private large‑language‑model knowledge base with DeepSeek4J.
Dual Function Overview
As a Cache System
Redis is best known for its caching capabilities. It can:
Fast key‑value access
Support multiple data types (strings, hashes, lists, etc.)
Provide data expiration mechanisms
Deliver high‑performance read/write operations
As a Vector Database
Redis can also serve as a vector database, supporting:
Storage of high‑dimensional vector data
Similarity search (KNN queries)
Vector range queries
Metadata filtering
Running Test
<code>docker run -p 6379:6379 --name redis-stack redis/redis-stack:latest</code>Vector Data Storage
Redis supports two main vector storage methods:
Hash storage
<code>HSET docs:01 doc_embedding <vector_bytes> category sports</code>JSON storage
<code>JSON.SET docs:01 $ '{"doc_embedding":[0.34,0.63,-0.54,-0.69,0.98,0.61], "category": "sports"}'</code>When visualizing data with the RedisInsight client, users can see stored vectors and related information. Note that the KEYS command cannot display vector data because vectors are stored in a specific format within hashes or JSON.
Java SDK Integration
This article uses Lettuce as the Java client to interact with Redis vectors.
<code>import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
/**
* @author lengleng
*/
public class LettuceVectorExample {
public static void main(String[] args) {
// Create Redis client
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
StatefulRedisConnection<String, String> connection = redisClient.connect();
RedisCommands<String, String> commands = connection.sync();
// Create index with vector field
String createIndex = "FT.CREATE myIndex ON HASH PREFIX 1 doc: SCHEMA embedding VECTOR FLAT 6 TYPE FLOAT32 DIM 4 DISTANCE_METRIC COSINE";
commands.sendCommand("FT.CREATE", "myIndex", "ON", "HASH", "PREFIX", "1", "doc:", "SCHEMA", "embedding", "VECTOR", "FLAT", "6", "TYPE", "FLOAT32", "DIM", "4", "DISTANCE_METRIC", "COSINE");
// Store vector data
float[] vector = {0.1f, 0.2f, 0.3f, 0.4f};
String vectorStr = floatArrayToString(vector); // Convert to string representation
commands.hset("doc:1", "embedding", vectorStr);
// Execute vector search (KNN)
float[] queryVector = {0.15f, 0.25f, 0.35f, 0.45f};
String query = "(@embedding:[VECTOR_RANGE 0.5 " + floatArrayToString(queryVector) + "])=>{$KNN: 1}";
String result = commands.sendCommand("FT.SEARCH", "myIndex", query).toString();
System.out.println("Search result: " + result);
// Close connection
connection.close();
redisClient.shutdown();
}
// Helper method: convert float array to space‑separated string
private static String floatArrayToString(float[] vector) {
StringBuilder sb = new StringBuilder();
for (float v : vector) {
sb.append(v).append(" ");
}
return sb.toString().trim();
}
}
</code>Conclusion
Redis's dual functionality provides unique advantages for modern application architectures. By configuring and using it properly, a single instance can simultaneously satisfy caching and vector‑search needs, saving resources and simplifying system design.
Java Architecture Diary
Committed to sharing original, high‑quality technical articles; no fluff or promotional content.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.