diff --git a/README.adoc b/README.adoc
index b95c2c14..6fa0f673 100644
--- a/README.adoc
+++ b/README.adoc
@@ -27,7 +27,7 @@ readme's instructions.
=== Examples
// examples: START
-Number of Examples: 69 (0 deprecated)
+Number of Examples: 70 (0 deprecated)
[width="100%",cols="4,2,4",options="header"]
|===
@@ -35,6 +35,8 @@ Number of Examples: 69 (0 deprecated)
| link:ai-agent/README.adoc[Ai Agent] (ai-agent) | AI | An example showing how to work with Camel Spring AI for chat, tools, and vector store
+| link:qdrant/readme.adoc[Qdrant] (qdrant) | AI | An example showing a full RAG pipeline using Camel OpenAI and Qdrant as vector store
+
| link:aot-basic/readme.adoc[Aot Basic] (aot-basic) | AOT | Example on how to leverage Spring Boot AOT in Camel Spring Boot
| link:endpointdsl/readme.adoc[Endpointdsl] (endpointdsl) | Beginner | Using type-safe Endpoint DSL
diff --git a/pom.xml b/pom.xml
index 32c11514..4163f396 100644
--- a/pom.xml
+++ b/pom.xml
@@ -72,6 +72,7 @@
platform-http
platform-http-proxy
pojo
+ qdrant
rabbitmq
reactive-streams
resilience4j
diff --git a/qdrant/input/playlist.txt b/qdrant/input/playlist.txt
new file mode 100644
index 00000000..b2b432de
--- /dev/null
+++ b/qdrant/input/playlist.txt
@@ -0,0 +1,253 @@
+Metallica - Enter Sandman
+The Police - Flexible Strategies
+Pink Floyd - Comfortably Numb
+Billy Joel - Piano Man
+Crowded House - Don't Dream It's Over
+Pink Floyd - Poles Apart
+Pink Floyd - Summer '68
+Sting - Fields Of Gold
+The Police - Every Breath You Take
+The Police - Wrapped Around Your Finger
+Pink Floyd - Atom Heart Mother
+Kansas - Carry On Wayward Son
+Genesis - The Cinema Show
+Genesis - Squonk
+Fleetwood Mac - Dreams
+Pink Floyd - The Great Gig in the Sky
+Genesis - Evidence of Autumn
+Genesis - Firth of Fifth
+Bruce Springsteen - Prove It All Night
+Bruce Springsteen - Atlantic City
+Bruce Springsteen - Rosalita (Come Out Tonight)
+The Police - Truth Hits Everybody
+The Who - Baba O'Riley
+The Police - No Time This Time
+Survivor - Eye of the Tiger
+Dire Straits - Money For Nothing
+Bruce Springsteen - Radio Nowhere
+Foreigner - I Want to Know What Love Is
+The Police - Bombs Away
+REO Speedwagon - Keep On Loving You
+The Doors - Riders on the Storm
+TOTO - Africa
+The Police - Darkness
+Phil Collins - In The Air Tonight
+Genesis - That's All
+The Police - Don't Stand So Close To Me
+Pink Floyd - Wish You Were Here
+Guns N' Roses - Sweet Child O' Mine
+Genesis - In Too Deep
+The Police - Hungry For You
+Genesis - Turn It On Again
+Sting - Shape Of My Heart
+The Police - Synchronicity II
+David Bowie - Heroes
+Pink Floyd - Money
+U2 - One
+Bruce Springsteen - Spirit in the Night
+The Doors - Light My Fire
+The Police - Peanuts
+Pink Floyd - Learning To Fly
+Sting - Desert Rose
+Creedence Clearwater Revival - Have You Ever Seen The Rain
+Bruce Springsteen - Glory Days
+Led Zeppelin - Stairway to Heaven
+The Police - Canary In A Coalmine
+The Police - Man In A Suitcase
+Genesis - Land of Confusion
+Genesis - Illegal Alien
+Lynyrd Skynyrd - Sweet Home Alabama
+The Police - A Sermon
+Genesis - Supper's Ready
+Pink Floyd - Fat Old Sun
+Genesis - I Can't Dance
+Genesis - Get 'Em Out by Friday
+The Kinks - You Really Got Me
+Pink Floyd - Pigs (Three Different Ones)
+Bad Company - Feel Like Makin' Love
+Thin Lizzy - The Boys Are Back In Town
+Peter Frampton - Show Me The Way
+Bon Jovi - Livin' On A Prayer
+The Police - Fall Out
+Pink Floyd - Keep Talking
+Deep Purple - Smoke On The Water
+The Smiths - How Soon Is Now?
+Bruce Springsteen - Wrecking Ball
+Genesis - Domino
+Genesis - Watcher of the Skies
+Paul Simon - You Can Call Me Al
+Jethro Tull - Aqualung
+Pink Floyd - The Fletcher Memorial Home
+Alice Cooper - School's Out
+The Police - De Do Do Do, De Da Da Da
+Pink Floyd - Sorrow
+Tears For Fears - Everybody Wants To Rule The World
+Bruce Springsteen - Badlands
+ZZ Top - La Grange
+Bruce Springsteen - American Skin (41 Shots)
+Bruce Springsteen - Waitin' on a Sunny Day
+The Police - Omegaman
+The Police - Does Everyone Stare
+Pink Floyd - Waiting for the Worms
+Genesis - Your Own Special Way
+The Police - Roxanne
+Dire Straits - Sultans of Swing
+Genesis - Duchess
+Status Quo - Rockin' All Over The World
+Sting - Englishman In New York
+The Cure - Lovesong
+Iron Maiden - The Number of the Beast
+John Mellencamp - Jack & Diane
+Duran Duran - Hungry Like the Wolf
+The Police - Bed's Too Big Without You
+Bruce Springsteen - Fire
+Bruce Springsteen - Racing in the Street
+The Police - Every Little Thing She Does Is Magic
+Elton John - Rocket Man
+The Police - So Lonely
+Bruce Springsteen - Point Blank
+Scorpions - Wind of Change
+Bruce Springsteen - Tenth Avenue Freeze-Out
+Pink Floyd - Time
+Bruce Springsteen - Blinded by the Light
+Pink Floyd - Marooned
+Van Halen - Jump
+Genesis - Entangled
+Pink Floyd - Another Brick in the Wall, Pt. 2
+Genesis - Follow You Follow Me
+Def Leppard - Pour Some Sugar On Me
+David Bowie - Moonage Daydream
+The Police - Voices Inside My Head
+Phil Collins - You Can't Hurry Love
+Bruce Springsteen - Dancing In the Dark
+Genesis - Afterglow
+Genesis - Home by the Sea
+Bruce Springsteen - Tunnel of Love
+Bruce Springsteen - Better Days
+Bruce Springsteen - Lonesome Day
+The Police - Demolition Man
+Pink Floyd - Brain Damage
+The Police - Walking on the Moon
+The Police - King Of Pain
+Pink Floyd - In the Flesh?
+Boston - More Than a Feeling
+Pink Floyd - See Emily Play
+Genesis - The Musical Box
+KISS - Rock and Roll All Nite
+Pink Floyd - Us and Them
+Bruce Springsteen - My Hometown
+Queen - Bohemian Rhapsody
+Bruce Springsteen - Secret Garden
+The Police - Murder By Numbers
+Genesis - Tonight, Tonight, Tonight
+Genesis - Stagnation
+Eagles - Hotel California
+Genesis - Blood on the Rooftops
+Genesis - Misunderstanding
+Whitesnake - Here I Go Again
+The Police - It's Alright For You
+Bruce Springsteen - Hungry Heart
+Depeche Mode - Enjoy The Silence
+Meat Loaf - Bat Out of Hell
+Genesis - Ripples
+Black Sabbath - Paranoid
+Bruce Springsteen - Streets of Philadelphia
+Poison - Every Rose Has Its Thorn
+Steppenwolf - Born To Be Wild
+The Police - Deathwish
+Men At Work - Down Under
+Bruce Springsteen - Born to Run
+Queen - Another One Bites The Dust
+Pink Floyd - Run Like Hell
+Pink Floyd - Set the Controls for the Heart of the Sun
+Rod Stewart - Maggie May
+Pink Floyd - Astronomy Domine
+Pink Floyd - Welcome to the Machine
+Yes - Owner of a Lonely Heart
+The Police - Hole In My Life
+Pink Floyd - High Hopes
+Tom Petty - Free Fallin'
+Bruce Springsteen - Darkness on the Edge of Town
+Bruce Springsteen - The Rising
+Bruce Springsteen - Pink Cadillac
+Bruce Springsteen - Jungleland
+Pink Floyd - Arnold Layne
+Bruce Springsteen - Brilliant Disguise
+The Rolling Stones - Gimme Shelter
+Heart - Barracuda
+Genesis - The Lamb Lies Down on Broadway
+Steely Dan - Do It Again
+Genesis - Carpet Crawlers
+Pink Floyd - Young Lust
+The Cars - Drive
+Pink Floyd - On the Turning Away
+Pink Floyd - Outside the Wall
+The Clash - London Calling
+AC/DC - Back In Black
+Pink Floyd - Mother
+Phil Collins - Against All Odds
+The Police - Friends
+Bruce Springsteen - I'm On Fire
+Pink Floyd - Vera
+The Police - Rehumanize Yourself
+Pink Floyd - Echoes
+Genesis - Keep It Dark
+Pink Floyd - Careful with That Axe, Eugene
+The Police - Message In A Bottle
+Motley Crue - Kickstart My Heart
+Bruce Springsteen - Human Touch
+The Police - Bring On The Night
+Genesis - Abacab
+Bruce Springsteen - Born in the U.S.A.
+Steve Miller Band - The Joker
+Genesis - Throwing It All Away
+Steve Winwood - Higher Love
+The Rolling Stones - Paint It, Black
+Genesis - Heathaze
+Simple Minds - Don't You (Forget About Me)
+Journey - Don't Stop Believin'
+Pink Floyd - One of These Days
+The Beach Boys - Good Vibrations
+Bruce Springsteen - Thunder Road
+Creedence Clearwater Revival - Bad Moon Rising
+The Police - Shadows In The Rain
+Bruce Springsteen - The E Street Shuffle
+The Police - Spirits In The Material World
+The Police - Tea In The Sahara
+Bruce Springsteen - Bobby Jean
+Santana - Black Magic Woman
+Bruce Springsteen - Land of Hope and Dreams
+The Police - Invisible Sun
+Genesis - No Son Of Mine
+Pink Floyd - Sheep
+The Police - Driven To Tears
+The Police - Contact
+U2 - With Or Without You
+Genesis - Invisible Touch
+Genesis - Paperlate
+Prince - Purple Rain
+The Police - Low Life
+Bruce Springsteen - Working on a Dream
+Peter Gabriel - Sledgehammer
+Pink Floyd - Shine On You Crazy Diamond
+Pink Floyd - Brain Damage (Dark Side of the Moon)
+Pink Floyd - Empty Spaces
+Bruce Springsteen - Ghost of Tom Joad
+Genesis - Duke's Travels
+Bryan Adams - Summer of '69
+Pink Floyd - Dogs
+Eurythmics - Sweet Dreams (Are Made of This)
+Blondie - Heart of Glass
+Genesis - Dancing With the Moonlit Knight
+Bruce Springsteen - Long Walk Home
+Electric Light Orchestra - Mr. Blue Sky
+Genesis - Mama
+Bruce Springsteen - Independence Day
+Genesis - Many Too Many
+Genesis - Man on the Corner
+Genesis - One for the Vine
+Pink Floyd - Hey You
+Bruce Springsteen - The River
+Jimi Hendrix - Purple Haze
+Aerosmith - Dream On
+Pink Floyd - Goodbye Blue Sky
diff --git a/qdrant/pom.xml b/qdrant/pom.xml
new file mode 100644
index 00000000..f020fe79
--- /dev/null
+++ b/qdrant/pom.xml
@@ -0,0 +1,125 @@
+
+
+
+
+ 4.0.0
+
+ org.apache.camel.springboot.example
+ examples
+ 4.19.0-SNAPSHOT
+
+
+ camel-example-spring-boot-qdrant
+ Camel SB Examples :: Qdrant
+ An example showing a full RAG pipeline using Camel OpenAI and Qdrant as vector store
+
+
+ AI
+ UTF-8
+ UTF-8
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot-version}
+ pom
+ import
+
+
+
+ org.apache.camel.springboot
+ camel-spring-boot-bom
+ ${project.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+
+ org.apache.camel.springboot
+ camel-spring-boot-starter
+
+
+ org.apache.camel.springboot
+ camel-qdrant-starter
+
+
+ org.apache.camel.springboot
+ camel-openai-starter
+
+
+ org.apache.camel.springboot
+ camel-file-starter
+
+
+ org.apache.camel.springboot
+ camel-yaml-dsl-starter
+
+
+ org.apache.camel.springboot
+ camel-jackson-starter
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.apache.camel
+ camel-test-spring-junit6
+ ${camel-version}
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring-boot-version}
+
+
+
+ repackage
+
+
+
+
+
+
+
diff --git a/qdrant/readme.adoc b/qdrant/readme.adoc
new file mode 100644
index 00000000..68c87a5e
--- /dev/null
+++ b/qdrant/readme.adoc
@@ -0,0 +1,66 @@
+== Camel Example Spring Boot RAG with Qdrant
+
+This example shows a full end-to-end RAG (Retrieval-Augmented Generation) pipeline
+using the Camel OpenAI component for embeddings and chat, with Qdrant as vector store.
+
+=== Prerequisites
+
+1. A running Qdrant instance:
+
+----
+camel infra run qdrant
+----
+
+2. A running Ollama instance with the required models:
+
+----
+ollama pull nomic-embed-text
+ollama pull granite4:3b
+----
+
+=== How to run
+
+You can run this example using:
+
+----
+mvn spring-boot:run
+----
+
+=== What happens
+
+When the application starts, it executes the following RAG pipeline:
+
+1. **Create Collection** - Creates `rag_collection` in Qdrant. A collection is a named group of points, where each point holds an embedding vector and an optional payload (in this case, the original text). The collection is configured with Cosine distance, which measures how semantically similar two vectors are: the closer to 1.0, the more similar.
+2. **Index Documents** - Reads `.txt` files from the `input/` directory (a playlist of songs is provided as sample data). Each document is sent to the `nomic-embed-text` model via `openai:embeddings`, which converts the text into a 768-dimensional numerical vector (the embedding). An embedding is a dense array of floats that captures the semantic meaning of the text: texts with similar meaning produce vectors that are close together in the vector space. The embedding and the original text are then upserted into Qdrant as a point.
+3. **RAG Query** - Takes a question (e.g. _"Give me at least five songs containing the 'moon' word in the title"_), converts it into an embedding using the same model, and performs a similarity search in Qdrant to find the documents whose vectors are closest to the question vector. The retrieved document texts are assembled into a context prompt and sent to `openai:chat-completion` for a grounded answer.
+
+=== Configuration
+
+Edit `src/main/resources/application.properties` to configure:
+
+* `camel.component.qdrant.host` - Qdrant server host (default: localhost)
+* `camel.component.qdrant.port` - Qdrant gRPC port (default: 6334)
+* `camel.component.openai.base-url` - OpenAI-compatible API base URL (default: Ollama at http://localhost:11434/v1)
+* `camel.component.openai.model` - Chat completion model (default: granite4:3b)
+* `camel.component.openai.embedding-model` - Embedding model (default: nomic-embed-text)
+
+To use OpenAI instead of Ollama, change the base URL and set your API key:
+
+----
+camel.component.openai.base-url=https://api.openai.com/v1
+camel.component.openai.api-key=${OPENAI_API_KEY}
+camel.component.openai.model=gpt-4o-mini
+camel.component.openai.embedding-model=text-embedding-3-small
+----
+
+Note: when switching to a different embedding model, update the vector size in the collection creation accordingly (e.g., 1536 for text-embedding-3-small).
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/support.html[let us know].
+
+We also love contributors, so
+https://camel.apache.org/contributing.html[get involved] :-)
+
+The Camel riders!
diff --git a/qdrant/src/main/java/org/apache/camel/example/springboot/qdrant/Application.java b/qdrant/src/main/java/org/apache/camel/example/springboot/qdrant/Application.java
new file mode 100644
index 00000000..415ff7b3
--- /dev/null
+++ b/qdrant/src/main/java/org/apache/camel/example/springboot/qdrant/Application.java
@@ -0,0 +1,12 @@
+package org.apache.camel.example.springboot.qdrant;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/qdrant/src/main/resources/application.properties b/qdrant/src/main/resources/application.properties
new file mode 100644
index 00000000..2c10f5f5
--- /dev/null
+++ b/qdrant/src/main/resources/application.properties
@@ -0,0 +1,13 @@
+camel.main.name=QdrantRAGExample
+camel.main.run-controller=true
+
+# Qdrant
+camel.component.qdrant.host=localhost
+camel.component.qdrant.port=6334
+camel.component.qdrant.max-results=10
+
+# OpenAI component (configured for Ollama)
+camel.component.openai.base-url=http://localhost:11434/v1
+camel.component.openai.api-key=ollama
+camel.component.openai.model=granite4:3b
+camel.component.openai.embedding-model=nomic-embed-text
diff --git a/qdrant/src/main/resources/camel/qdrant-rag.yaml b/qdrant/src/main/resources/camel/qdrant-rag.yaml
new file mode 100644
index 00000000..6c4c9f9d
--- /dev/null
+++ b/qdrant/src/main/resources/camel/qdrant-rag.yaml
@@ -0,0 +1,157 @@
+- beans:
+ - name: ragCreateCollection
+ type: org.apache.camel.component.qdrant.rag.RAGCreateCollection
+ properties:
+ size: "768"
+ distance: "Cosine"
+ - name: ragUpsert
+ type: org.apache.camel.component.qdrant.rag.RAGUpsert
+ properties:
+ payloadKey: "content"
+ textVariable: "text"
+ - name: ragResultExtractor
+ type: org.apache.camel.component.qdrant.rag.RAGResultExtractor
+ properties:
+ payloadKey: "content"
+
+# Create collection on startup
+- route:
+ id: init-collection
+ from:
+ uri: timer:init
+ parameters:
+ repeatCount: "1"
+ delay: "1000"
+ steps:
+ - log:
+ message: "Creating collection: rag_collection"
+ - doTry:
+ steps:
+ - process:
+ ref: ragCreateCollection
+ - to:
+ uri: qdrant:rag_collection
+ - log:
+ message: "Collection created successfully"
+ doCatch:
+ - exception:
+ - java.lang.Exception
+ steps:
+ - log:
+ message: "Collection already exists or error: ${exception.message}"
+
+# Index documents from input directory (split file line-by-line)
+- route:
+ id: index-documents
+ from:
+ uri: file:input
+ parameters:
+ noop: "true"
+ include: ".*\\.txt"
+ initialDelay: "3000"
+ steps:
+ - log:
+ message: "Indexing document: ${header.CamelFileName}"
+ - convertBodyTo:
+ type: java.lang.String
+ - split:
+ tokenize: "\n"
+ steps:
+ - to:
+ uri: direct:index
+
+# Embed and store a document in Qdrant
+- route:
+ id: embed-and-store
+ from:
+ uri: direct:index
+ steps:
+ - setVariable:
+ name: text
+ expression:
+ simple:
+ expression: "${body}"
+ - to:
+ uri: openai:embeddings
+ - process:
+ ref: ragUpsert
+ - to:
+ uri: qdrant:rag_collection
+ - log:
+ message: "Document indexed successfully"
+
+# Query route
+- route:
+ id: rag-query
+ from:
+ uri: timer:query
+ parameters:
+ repeatCount: "1"
+ delay: "15000"
+ steps:
+ - setBody:
+ expression:
+ constant:
+ expression: "Give me at least five songs containing the 'moon' word in the title"
+ - log:
+ message: "Query: ${body}"
+ - to:
+ uri: direct:rag
+
+# RAG pipeline: embed query -> similarity search -> chat completion
+- route:
+ id: rag-pipeline
+ from:
+ uri: direct:rag
+ steps:
+ - setVariable:
+ name: query
+ expression:
+ simple:
+ expression: "${body}"
+ - setBody:
+ expression:
+ simple:
+ expression: "From the following query, extract the number of results requested. Reply with ONLY the number, nothing else. If no specific number is mentioned, reply with 10.\n\nQuery: ${variable.query}"
+ - to:
+ uri: openai:chat-completion
+ - setHeader:
+ name: CamelQdrantMaxResults
+ expression:
+ simple:
+ expression: "${body.trim()}"
+ resultType: int
+ - log:
+ message: "Max results requested: ${header.CamelQdrantMaxResults}"
+ - setBody:
+ expression:
+ simple:
+ expression: "${variable.query}"
+ - to:
+ uri: openai:embeddings
+ - setHeader:
+ name: CamelQdrantAction
+ constant: SIMILARITY_SEARCH
+ - setHeader:
+ name: CamelQdrantIncludePayload
+ constant: "true"
+ - setHeader:
+ name: CamelQdrantIncludeVectors
+ constant: "false"
+ - to:
+ uri: qdrant:rag_collection
+ - bean:
+ ref: ragResultExtractor
+ method: extract
+ - marshal:
+ json: {}
+ - log:
+ message: "Result by Qdrant: \n ${body}"
+ - setBody:
+ expression:
+ simple:
+ expression: "Based on the following search results ranked by relevance:\n${body}\n\n${variable.query}"
+ - to:
+ uri: openai:chat-completion
+ - log:
+ message: "AI Response: \n ${body}"
\ No newline at end of file