Skip to content

Commit d378bd3

Browse files
Katia Arestikaresti
authored andcommitted
Missing guides
1 parent fde1143 commit d378bd3

157 files changed

Lines changed: 4016 additions & 279 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ See `.editorconfig` for full details.
4747

4848
### Module Categories
4949

50-
- **`infinispan-remote/`** Tutorials using Hot Rod client to connect to an Infinispan Server (client-server mode)
51-
- **`infinispan-embedded/`** Tutorials embedding Infinispan as a library (no server needed)
52-
- **`integrations/`** Tutorials for Spring Boot, Quarkus, and Hibernate integrations
53-
- **`infinispan-ai/`** AI/vector search tutorials (LangChain4j, vector search)
54-
- **`non-java-clients/`** C++, C#, JavaScript Hot Rod client examples
50+
- **`infinispan-remote/`** - Tutorials using Hot Rod client to connect to an Infinispan Server (client-server mode)
51+
- **`infinispan-embedded/`** - Tutorials embedding Infinispan as a library (no server needed)
52+
- **`integrations/`** - Tutorials for Spring Boot, Quarkus, and Hibernate integrations
53+
- **`infinispan-ai/`** - AI/vector search tutorials (LangChain4j, vector search)
54+
- **`non-java-clients/`** - C++, C#, JavaScript Hot Rod client examples
5555

5656
### Shared Connection Helper
5757

@@ -63,15 +63,15 @@ See `.editorconfig` for full details.
6363
### Tutorial Module Pattern
6464

6565
Each tutorial module follows the same structure:
66-
- `src/main/java/` Runnable main class demonstrating the feature
67-
- `src/test/java/` JUnit 5 test that exercises the same feature
68-
- `pom.xml` Inherits from root, declares `exec-maven-plugin` for `mvn exec:exec`
69-
- `guide.adoc` (optional) AsciiDoc tutorial guide published to infinispan.org
66+
- `src/main/java/` - Runnable main class demonstrating the feature
67+
- `src/test/java/` - JUnit 5 test that exercises the same feature
68+
- `pom.xml` - Inherits from root, declares `exec-maven-plugin` for `mvn exec:exec`
69+
- `guide.adoc` (optional) - AsciiDoc tutorial guide published to infinispan.org
7070

7171
### Documentation
7272

73-
- `documentation/asciidoc/` AsciiDoc source for published tutorial docs
74-
- `docs-maven-plugin/` Custom Maven plugin that processes `guide.adoc` files from each tutorial into the website format
73+
- `documentation/asciidoc/` - AsciiDoc source for published tutorial docs
74+
- `docs-maven-plugin/` - Custom Maven plugin that processes `guide.adoc` files from each tutorial into the website format
7575
- Guides are built with the `guides` Maven profile
7676

7777
## CI
@@ -80,6 +80,6 @@ GitHub Actions runs on pushes and PRs to `main`, `development`, and `16.0.x` bra
8080

8181
## Branch Strategy
8282

83-
- `development` uses latest Infinispan dev version (`quay.io/infinispan-test/server:main`)
84-
- `main` uses latest stable Infinispan release
83+
- `development` - uses latest Infinispan dev version (`quay.io/infinispan-test/server:main`)
84+
- `main` - uses latest stable Infinispan release
8585
- All contributions target `main`

docs-maven-plugin/src/main/java/org/infinispan/tutorial/docs/GuideMetadataGenerator.java

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
import java.util.ArrayList;
77
import java.util.Arrays;
88
import java.util.Comparator;
9+
import java.util.HashMap;
910
import java.util.LinkedHashMap;
1011
import java.util.List;
1112
import java.util.Map;
1213
import java.util.Set;
14+
import java.util.regex.Matcher;
15+
import java.util.regex.Pattern;
1316
import java.util.stream.Stream;
1417

1518
import org.asciidoctor.Asciidoctor;
@@ -142,7 +145,67 @@ private void processGuide(Path guideFile, String id, Asciidoctor asciidoctor,
142145
}
143146

144147
guides.add(guide);
145-
Files.copy(guideFile, guidesOutputDir.resolve(id + ".adoc"));
148+
149+
String resolved = resolveIncludes(content, guideFile.getParent());
150+
Files.writeString(guidesOutputDir.resolve(id + ".adoc"), resolved);
151+
}
152+
153+
private static final Pattern INCLUDE_PATTERN =
154+
Pattern.compile("^include::(.+?)\\[tag=(\\w[\\w-]*)\\]\\s*$", Pattern.MULTILINE);
155+
156+
private final Map<Path, List<String>> fileCache = new HashMap<>();
157+
158+
private String resolveIncludes(String content, Path baseDir) {
159+
Matcher matcher = INCLUDE_PATTERN.matcher(content);
160+
StringBuilder sb = new StringBuilder();
161+
while (matcher.find()) {
162+
String filePath = matcher.group(1);
163+
String tagName = matcher.group(2);
164+
String extracted = extractTag(baseDir.resolve(filePath), tagName);
165+
matcher.appendReplacement(sb, Matcher.quoteReplacement(extracted));
166+
}
167+
matcher.appendTail(sb);
168+
return sb.toString();
169+
}
170+
171+
private String extractTag(Path file, String tag) {
172+
List<String> lines = fileCache.computeIfAbsent(file, f -> {
173+
try {
174+
return Files.readAllLines(f);
175+
} catch (IOException e) {
176+
System.err.println("WARNING: Cannot read include file: " + f);
177+
return List.of();
178+
}
179+
});
180+
if (lines.isEmpty()) {
181+
return "// Include not found: " + file.getFileName() + "[tag=" + tag + "]";
182+
}
183+
184+
String startMarker = "tag::" + tag + "[]";
185+
String endMarker = "end::" + tag + "[]";
186+
StringBuilder sb = new StringBuilder();
187+
boolean capturing = false;
188+
for (String line : lines) {
189+
if (line.contains(startMarker)) {
190+
capturing = true;
191+
continue;
192+
}
193+
if (line.contains(endMarker)) {
194+
capturing = false;
195+
continue;
196+
}
197+
if (capturing) {
198+
sb.append(line).append('\n');
199+
}
200+
}
201+
String result = sb.toString();
202+
if (result.isEmpty()) {
203+
return "// Tag not found: " + tag + " in " + file.getFileName();
204+
}
205+
if (result.endsWith("\n")) {
206+
result = result.substring(0, result.length() - 1);
207+
}
208+
return result;
146209
}
147210

148211
private String attrString(Document doc, String name) {

infinispan-ai/langchain4j/guide.adoc

Lines changed: 10 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -31,68 +31,36 @@ Add LangChain4j with the Infinispan embedding store and an ONNX embedding model:
3131
</dependency>
3232
----
3333

34-
The quantized MiniLM model runs locally — no API keys or external services needed.
34+
The quantized MiniLM model runs locally. No API keys or external services needed.
3535

36-
== Step 2: Initialize the Embedding Model
36+
== Step 2: Initialize the Model and Create the Embedding Store
3737

38-
Create a local embedding model that converts text to vectors:
38+
Create a local embedding model that converts text to vectors, then connect the embedding store to Infinispan:
3939

4040
[source,java]
4141
----
42-
EmbeddingModel embeddingModel = new AllMiniLmL6V2QuantizedEmbeddingModel();
43-
System.out.println("Dimension: " + embeddingModel.dimension()); // 384
42+
include::src/main/java/org/infinispan/tutorial/simple/ai/langchain4j/InfinispanLangchain4j.java[tag=setup]
4443
----
4544

46-
== Step 3: Create the Infinispan Embedding Store
47-
48-
Connect the embedding store to Infinispan:
49-
50-
[source,java]
51-
----
52-
ConfigurationBuilder builder = TutorialsConnectorHelper.connectionConfig();
53-
InfinispanEmbeddingStore embeddingStore = InfinispanEmbeddingStore.builder()
54-
.cacheName("langchain4j-embeddings")
55-
.dimension(embeddingModel.dimension())
56-
.infinispanConfigBuilder(builder)
57-
.distance(3) // inner product distance
58-
.build();
59-
----
60-
61-
== Step 4: Store Text as Embeddings
45+
== Step 3: Store Text as Embeddings
6246

6347
Convert text segments to vectors and store them:
6448

6549
[source,java]
6650
----
67-
TextSegment segment = TextSegment.from(
68-
"Infinispan supports vector search for AI use cases",
69-
Metadata.from("source", "docs").put("topic", "ai"));
70-
71-
Embedding embedding = embeddingModel.embed(segment).content();
72-
embeddingStore.add(embedding, segment);
51+
include::src/main/java/org/infinispan/tutorial/simple/ai/langchain4j/InfinispanLangchain4j.java[tag=add-embedding]
7352
----
7453

75-
== Step 5: Search by Semantic Similarity
54+
== Step 4: Search by Semantic Similarity
7655

77-
Query with natural language — the model finds semantically similar text, not just keyword matches:
56+
Query with natural language. The model finds semantically similar text, not just keyword matches:
7857

7958
[source,java]
8059
----
81-
String query = "How can I use Infinispan with AI?";
82-
Embedding queryEmbedding = embeddingModel.embed(query).content();
83-
84-
EmbeddingSearchRequest request = EmbeddingSearchRequest.builder()
85-
.queryEmbedding(queryEmbedding)
86-
.maxResults(3)
87-
.build();
88-
89-
EmbeddingSearchResult<TextSegment> result = embeddingStore.search(request);
90-
for (EmbeddingMatch<TextSegment> match : result.matches()) {
91-
System.out.printf("Score: %.4f | %s%n", match.score(), match.embedded().text());
92-
}
60+
include::src/main/java/org/infinispan/tutorial/simple/ai/langchain4j/InfinispanLangchain4j.java[tag=search]
9361
----
9462

95-
== Step 6: Run the Tutorial
63+
== Step 5: Run the Tutorial
9664

9765
[source,bash]
9866
----

infinispan-ai/langchain4j/src/main/java/org/infinispan/tutorial/simple/ai/langchain4j/InfinispanLangchain4j.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public static void main(String[] args) {
3030
}
3131
}
3232

33+
// tag::setup[]
3334
static void initEmbeddingModel() {
3435
embeddingModel = new AllMiniLmL6V2QuantizedEmbeddingModel();
3536
System.out.println("Embedding model initialized. Dimension: " + embeddingModel.dimension());
@@ -45,6 +46,7 @@ static void connectAndCreateStore() {
4546
.build();
4647
System.out.println("Connected to Infinispan and created embedding store.");
4748
}
49+
// end::setup[]
4850

4951
static void storeAndSearch() {
5052
// Store some text segments with metadata
@@ -57,6 +59,7 @@ static void storeAndSearch() {
5759

5860
System.out.println("Stored 3 text segments with embeddings.\n");
5961

62+
// tag::search[]
6063
// Search by similarity
6164
String query = "How can I use Infinispan with AI?";
6265
System.out.println("Query: \"" + query + "\"");
@@ -75,13 +78,16 @@ static void storeAndSearch() {
7578
System.out.printf(" Score: %.4f | Text: %s%n",
7679
match.score(), match.embedded().text());
7780
}
81+
// end::search[]
7882
}
7983

84+
// tag::add-embedding[]
8085
static void addEmbedding(String text, Metadata metadata) {
8186
TextSegment segment = TextSegment.from(text, metadata);
8287
Embedding embedding = embeddingModel.embed(segment).content();
8388
embeddingStore.add(embedding, segment);
8489
}
90+
// end::add-embedding[]
8591

8692
static void disconnect() {
8793
if (embeddingStore != null) {

infinispan-ai/mcp-server/AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
This project connects to an Infinispan server via its MCP endpoint.
22

33
Always use the Infinispan MCP server tools to interact with Infinispan (manage caches, counters, schemas, entries).
4-
Do not use curl or the REST API directly — the MCP server is the intended interface.
4+
Do not use curl or the REST API directly. The MCP server is the intended interface.
55

66
The Infinispan MCP server is configured in `.mcp.json` and provides tools for:
77
- Cache operations (create, list, get, put, remove, query)
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
= Vector Search with Infinispan
2+
:summary: Perform kNN vector search and hybrid queries combining vector similarity with full-text and metadata filters
3+
:mode: ai
4+
:topics: vector-search,knn
5+
:keywords: vector,knn,embedding,similarity,cosine,hybrid,full-text,indexed,protobuf
6+
:duration: 10
7+
:source-dir: infinispan-ai/vector-search
8+
9+
== What You Will Learn
10+
11+
How to store entities with vector embeddings in Infinispan and perform kNN (k-nearest neighbor) vector searches, including hybrid queries that combine vector similarity with full-text search and metadata filters.
12+
13+
== Prerequisites
14+
15+
* Java 17+
16+
* An Infinispan Server running on `localhost:11222` (or Docker/Podman available for Testcontainers)
17+
18+
== Step 1: Define an Indexed Entity with a Vector Field
19+
20+
Use the `@Vector` annotation to declare a vector field with its dimension and similarity function:
21+
22+
[source,java]
23+
----
24+
@Proto
25+
@Indexed
26+
public record Beer(
27+
@Keyword(projectable = true, sortable = true)
28+
String name,
29+
30+
@Keyword(projectable = true, normalizer = "lowercase")
31+
String style,
32+
33+
@Keyword(projectable = true, sortable = true, normalizer = "lowercase")
34+
String brewery,
35+
36+
@Keyword(projectable = true, normalizer = "lowercase")
37+
String country,
38+
39+
@Basic(projectable = true, sortable = true)
40+
Double abv,
41+
42+
@Text
43+
String description,
44+
45+
@Vector(dimension = 3, similarity = VectorSimilarity.COSINE)
46+
float[] descriptionEmbedding
47+
) {
48+
}
49+
----
50+
51+
== Step 2: Connect and Register the Schema
52+
53+
Connect to the server and register the Protobuf schema for your entity:
54+
55+
[source,java]
56+
----
57+
include::src/main/java/org/infinispan/tutorial/simple/remote/vectorsearch/VectorSearchQuickstart.java[tag=connect]
58+
----
59+
60+
== Step 3: Perform a kNN Vector Search
61+
62+
Use the `<->` operator with `~:k` to find the k nearest neighbors:
63+
64+
[source,java]
65+
----
66+
include::src/main/java/org/infinispan/tutorial/simple/remote/vectorsearch/VectorSearchQuickstart.java[tag=knn]
67+
----
68+
69+
== Step 4: Run Hybrid Queries
70+
71+
Combine vector similarity with metadata filters using the `filtering` clause, or with full-text filters:
72+
73+
[source,java]
74+
----
75+
include::src/main/java/org/infinispan/tutorial/simple/remote/vectorsearch/VectorSearchQuickstart.java[tag=hybrid]
76+
----
77+
78+
== Step 5: Run the Tutorial
79+
80+
[source,bash]
81+
----
82+
mvn package exec:exec
83+
----
84+
85+
The output demonstrates full-text search, keyword/range filters, projections, kNN vector search with score projections, and hybrid queries filtering by style, country, and description text.
86+
87+
== What's Next
88+
89+
* link:../langchain4j/guide.html[Semantic search with LangChain4j] for vector search with an AI embedding model

infinispan-ai/vector-search/src/main/java/org/infinispan/tutorial/simple/remote/vectorsearch/VectorSearchQuickstart.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public static void main(String[] args) throws Exception {
4848
disconnect();
4949
}
5050

51+
// tag::connect[]
5152
static void connect() throws Exception {
5253
ConfigurationBuilder builder = TutorialsConnectorHelper.connectionConfig();
5354
builder.addContextInitializer(new BeerSchemaImpl());
@@ -60,6 +61,7 @@ static void connect() throws Exception {
6061
cacheManager.administration().schemas().createOrUpdate(new BeerSchemaImpl());
6162
cache = cacheManager.getCache(CACHE_NAME);
6263
}
64+
// end::connect[]
6365

6466
static void disconnect() {
6567
TutorialsConnectorHelper.stop(cacheManager);
@@ -157,6 +159,7 @@ static void projectionsAndSorting() {
157159

158160
// ---- Vector search (kNN) ----
159161

162+
// tag::knn[]
160163
static void knnVectorSearch() {
161164
System.out.println("=== kNN: 3 beers closest to 'dark roasty' vector [0.9, 0.1, 0.1] ===");
162165
Query<Beer> query = cache.query(
@@ -168,6 +171,7 @@ static void knnVectorSearch() {
168171
}
169172
System.out.println();
170173
}
174+
// end::knn[]
171175

172176
static void scoreProjection() {
173177
System.out.println("=== kNN with score: 3 beers closest to 'light crisp lager' vector [0.05, 0.9, 0.1] ===");
@@ -184,6 +188,7 @@ static void scoreProjection() {
184188

185189
// ---- Hybrid queries: vector + metadata ----
186190

191+
// tag::hybrid[]
187192
static void hybridFilterByStyle() {
188193
System.out.println("=== Hybrid: closest to 'refreshing summer beer' [0.05, 0.95, 0.05], only lagers under 5% ABV ===");
189194
Query<Object[]> query = cache.query(
@@ -228,4 +233,5 @@ static void hybridFullTextAndVector() {
228233
}
229234
System.out.println();
230235
}
236+
// end::hybrid[]
231237
}

0 commit comments

Comments
 (0)