Skip to content

CAMEL-23953: Add batch operations for langchain4j embeddings - #25273

Merged
davsclaus merged 4 commits into
apache:mainfrom
gnodet:investigate-and-fix-camel-23953-camel-langchain4j
Sep 3, 2026
Merged

CAMEL-23953: Add batch operations for langchain4j embeddings#25273
davsclaus merged 4 commits into
apache:mainfrom
gnodet:investigate-and-fix-camel-23953-camel-langchain4j

Conversation

@gnodet

@gnodet gnodet commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Add batch embedAll, addAll, removeAll support for the LangChain4j embedding components, enabling efficient RAG ingestion pipelines.

Embeddings producer (camel-langchain4j-embeddings)

  • Detect List body and route to processBatch with model.embedAll()
  • Preserve text segments via TEXT_SEGMENTS header for seamless downstream chaining with the embedding store
  • Full GenAI observation support for batch operations (matching the new telemetry pattern on main)

Embedding store producer (camel-langchain4j-embeddingstore)

  • Batch ADD via EMBEDDINGS header with addAll variants (embeddings-only, with text segments, with caller IDs)
  • Caller-supplied IDs via EMBEDDING_ID (single) and EMBEDDING_IDS (batch) headers
  • Single add with caller ID + text segment preserved via addAll with singleton lists (no text segment loss)
  • Size validation between callerIds, embeddings, and textSegments — throws IllegalArgumentException on mismatch
  • Batch REMOVE by Collection<String> body or Filter header
  • Null/empty REMOVE throws IllegalArgumentException with clear message (safe failure, no destructive removeAll() fallback)
  • Integrates with the existing resolveEmbedding() / auto-embedding pattern from main

Shared constants (core/camel-api)

  • Add CAMEL_LANGCHAIN4J_EMBEDDINGS and CAMEL_LANGCHAIN4J_TEXT_SEGMENTS to CamelLangchain4jAttributes

Documentation & upgrade guide

  • Document batch ADD with text segment preservation, caller-supplied IDs, batch REMOVE strategies
  • Add upgrade guide entry for REMOVE behavior change and new batch headers

Tests

  • LangChain4jEmbeddingsBatchTest — batch embedding with string list, token usage, single-item path verification
  • LangChain4jEmbeddingStoreBatchOperationsTest — 12 tests covering all add/remove variants, size mismatch validation, caller ID with text segment preservation

Review comments addressed

All feedback from prior reviews has been incorporated in this rebased commit:

  • [HIGH] Destructive removeAll() fallback → throws IllegalArgumentException
  • [MEDIUM] Text segments lost in batch embed→store pipeline → preserved via TEXT_SEGMENTS header
  • [MEDIUM] Caller-supplied IDs silently discarded → loops with add(id, embedding) when no text segments
  • [MEDIUM] Single add with callerId drops text segment → uses addAll with singleton lists
  • [MEDIUM] Size mismatch not validated → explicit size checks with clear error messages
  • [MEDIUM] FQCN for ArrayList → proper import
  • [MEDIUM] EMBEDDINGS header not in CamelLangchain4jAttributes → added to shared interface
  • [LOW] Missing upgrade guide entry → added

Claude Code on behalf of @gnodet

@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@apupier apupier left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

several files require a regen


	modified:   catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-embeddings.json
	modified:   catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-embeddingstore.json
	modified:   catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/langchain4j-embeddings-component.adoc
	modified:   catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/langchain4j-embeddingstore-component.adoc
	modified:   dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LangChain4jEmbeddingStoreEndpointBuilderFactory.java
	modified:   dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/LangChain4jEmbeddingsEndpointBuilderFactory.java

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • catalog/camel-catalog
  • components/camel-ai/camel-langchain4j-embeddings
  • components/camel-ai/camel-langchain4j-embeddingstore
  • core/camel-api
  • docs
  • dsl/camel-endpointdsl

ℹ️ Dependent modules were not tested because the total number of affected modules exceeded the threshold (50). Use the test-dependents label to force testing all dependents.


🔬 Scalpel shadow comparison — Scalpel: 568 tested, 24 compile-only — current: 565 all tested

Maveniverse Scalpel detected 592 affected modules (current approach: 565).

⚠️ Modules only in Scalpel (27)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

Skip-tests mode would test 568 modules (6 direct + 562 downstream), skip tests for 24 (generated code, meta-modules)

Modules Scalpel would test (568)
  • archetypes
  • camel-a2a
  • camel-activemq
  • camel-activemq6
  • camel-ai-observability
  • camel-ai-observability-api
  • camel-ai-parent
  • camel-ai-resource
  • camel-ai-tool
  • camel-alibaba-common
  • camel-alibaba-eventbridge
  • camel-alibaba-fc
  • camel-alibaba-kms
  • camel-alibaba-mns
  • camel-alibaba-oss
  • camel-alibaba-ots
  • camel-alibaba-parent
  • camel-alibaba-sls
  • camel-alibaba-sms
  • camel-amqp
  • camel-api
  • camel-api-component-maven-plugin
  • camel-arangodb
  • camel-archetype-api-component
  • camel-archetype-component
  • camel-archetype-dataformat
  • camel-archetype-java
  • camel-archetype-main
  • camel-as2
  • camel-as2-api
  • camel-as2-parent
  • camel-asn1
  • camel-asterisk
  • camel-atmosphere-websocket
  • camel-atom
  • camel-attachments
  • camel-avro
  • camel-avro-rpc
  • camel-avro-rpc-jetty
  • camel-avro-rpc-parent
  • camel-avro-rpc-spi
  • camel-aws-bedrock
  • camel-aws-cloudtrail
  • camel-aws-common
  • camel-aws-config
  • camel-aws-parameter-store
  • camel-aws-parent
  • camel-aws-secrets-manager
  • camel-aws-security-hub
  • camel-aws2-athena
  • camel-aws2-comprehend
  • camel-aws2-cw
  • camel-aws2-ddb
  • camel-aws2-ec2
  • camel-aws2-ecs
  • camel-aws2-eks
  • camel-aws2-eventbridge
  • camel-aws2-iam
  • camel-aws2-kinesis
  • camel-aws2-kms
  • camel-aws2-lambda
  • camel-aws2-mq
  • camel-aws2-msk
  • camel-aws2-polly
  • camel-aws2-redshift
  • camel-aws2-rekognition
  • camel-aws2-s3
  • camel-aws2-s3-vectors
  • camel-aws2-ses
  • camel-aws2-sns
  • camel-aws2-sqs
  • camel-aws2-step-functions
  • camel-aws2-sts
  • camel-aws2-textract
  • camel-aws2-timestream
  • camel-aws2-transcribe
  • camel-aws2-translate
  • camel-azure-common
  • camel-azure-cosmosdb
  • camel-azure-eventgrid
  • camel-azure-eventhubs
  • camel-azure-files
  • camel-azure-functions
  • camel-azure-key-vault
  • camel-azure-parent
  • camel-azure-schema-registry
  • camel-azure-servicebus
  • camel-azure-storage-blob
  • camel-azure-storage-datalake
  • camel-azure-storage-queue
  • camel-barcode
  • camel-base
  • camel-base-engine
  • camel-base64
  • camel-bean
  • camel-bean-validator
  • camel-beanio
  • camel-bindy
  • camel-bonita
  • camel-box
  • camel-box-api
  • camel-box-parent
  • camel-braintree
  • camel-browse
  • camel-caffeine
  • camel-camunda
  • camel-cassandraql
  • camel-catalog
  • camel-catalog-common
  • camel-cbor
  • camel-chatscript
  • camel-chunk
  • camel-cli-connector
  • camel-cli-debug
  • camel-clickhouse
  • camel-clickup
  • camel-cloudevents
  • camel-cluster
  • camel-cm-sms
  • camel-coap
  • camel-cometd
  • camel-console
  • camel-consul
  • camel-controlbus
  • camel-core
  • camel-core-all
  • camel-core-catalog
  • camel-core-engine
  • camel-core-languages
  • camel-core-model
  • camel-core-processor
  • camel-core-reifier
  • camel-core-xml
  • camel-couchbase
  • camel-couchdb
  • camel-cron
  • camel-crypto
  • camel-crypto-pgp
  • camel-csv
  • camel-cxf-common
  • camel-cxf-parent
  • camel-cxf-rest
  • camel-cxf-soap
  • camel-cxf-spring-common
  • camel-cxf-spring-rest
  • camel-cxf-spring-soap
  • camel-cxf-spring-transport
  • camel-cxf-transport
  • camel-cyberark-vault
  • camel-dapr
  • camel-dataformat
  • camel-dataset
  • camel-datasonnet
  • camel-dataweave
  • camel-debezium-common
  • camel-debezium-common-parent
  • camel-debezium-db2
  • camel-debezium-maven-plugin
  • camel-debezium-mongodb
  • camel-debezium-mysql
  • camel-debezium-oracle
  • camel-debezium-parent
  • camel-debezium-postgres
  • camel-debezium-sqlserver
  • camel-debug
  • camel-dfdl
  • camel-dhis2
  • camel-dhis2-api
  • camel-dhis2-parent
  • camel-diagram
  • camel-direct
  • camel-disruptor
  • camel-djl
  • camel-dns
  • camel-docker
  • camel-docling
  • camel-drill
  • camel-dropbox
  • camel-dsl-modeline
  • camel-dsl-support
  • camel-duckdb
  • camel-dynamic-router
  • camel-ehcache
  • camel-elasticsearch
  • camel-elasticsearch-rest-client
  • camel-endpointdsl
  • camel-event
  • camel-exec
  • camel-fastjson
  • camel-fhir
  • camel-fhir-api
  • camel-fhir-parent
  • camel-file
  • camel-file-watch
  • camel-flatpack
  • camel-flink
  • camel-flowable
  • camel-fop
  • camel-fory
  • camel-freemarker
  • camel-ftp
  • camel-ftp-common
  • camel-geocoder
  • camel-git
  • camel-github2
  • camel-google-bigquery
  • camel-google-calendar
  • camel-google-common
  • camel-google-drive
  • camel-google-firestore
  • camel-google-functions
  • camel-google-mail
  • camel-google-parent
  • camel-google-pubsub
  • camel-google-secret-manager
  • camel-google-sheets
  • camel-google-speech-to-text
  • camel-google-storage
  • camel-google-text-to-speech
  • camel-google-vertexai
  • camel-google-vision
  • camel-graphql
  • camel-grok
  • camel-groovy
  • camel-grpc
  • camel-gson
  • camel-hashicorp-vault
  • camel-hazelcast
  • camel-health
  • camel-hivemq
  • camel-hl7
  • camel-http
  • camel-http-base
  • camel-http-common
  • camel-huawei-parent
  • camel-huaweicloud-common
  • camel-huaweicloud-dms
  • camel-huaweicloud-frs
  • camel-huaweicloud-functiongraph
  • camel-huaweicloud-iam
  • camel-huaweicloud-imagerecognition
  • camel-huaweicloud-obs
  • camel-huaweicloud-smn
  • camel-huggingface
  • camel-ibm-cos
  • camel-ibm-parent
  • camel-ibm-secrets-manager
  • camel-ibm-watson-discovery
  • camel-ibm-watson-language
  • camel-ibm-watson-speech-to-text
  • camel-ibm-watson-text-to-speech
  • camel-ibm-watsonx-ai
  • camel-ibm-watsonx-data
  • camel-ical
  • camel-iggy
  • camel-ignite
  • camel-infinispan
  • camel-infinispan-common
  • camel-infinispan-embedded
  • camel-infinispan-parent
  • camel-influxdb
  • camel-influxdb2
  • camel-iso8583
  • camel-jackson
  • camel-jackson-avro
  • camel-jackson-protobuf
  • camel-jackson3
  • camel-jackson3-avro
  • camel-jackson3-protobuf
  • camel-jackson3xml
  • camel-jacksonxml
  • camel-jactl
  • camel-jandex
  • camel-jasypt
  • camel-java-io
  • camel-java-joor-dsl
  • camel-javascript
  • camel-jaxb
  • camel-jbang-console
  • camel-jbang-mcp
  • camel-jbang-plugin-mcp
  • camel-jbang-plugin-route-parser
  • camel-jbang-plugin-tui
  • camel-jbang-plugin-validate
  • camel-jcache
  • camel-jcr
  • camel-jdbc
  • camel-jetty
  • camel-jetty-common
  • camel-jfr
  • camel-jgroups
  • camel-jgroups-raft
  • camel-jira
  • camel-jms
  • camel-jmx
  • camel-jolt
  • camel-jooq
  • camel-joor
  • camel-jpa
  • camel-jq
  • camel-jsch
  • camel-jslt
  • camel-json-validator
  • camel-jsonapi
  • camel-jsonata
  • camel-jsonb
  • camel-jsonpath
  • camel-jsoup
  • camel-jt400
  • camel-jta
  • camel-jte
  • camel-kafka
  • camel-kamelet
  • camel-kamelet-main-support
  • camel-keycloak
  • camel-knative
  • camel-knative-api
  • camel-knative-http
  • camel-knative-parent
  • camel-kserve
  • camel-kubernetes
  • camel-kudu
  • camel-langchain4j-agent
  • camel-langchain4j-agent-api
  • camel-langchain4j-chat
  • camel-langchain4j-core
  • camel-langchain4j-embeddings
  • camel-langchain4j-embeddingstore
  • camel-langchain4j-embeddingstore-api
  • camel-langchain4j-tokenizer
  • camel-langchain4j-web-search
  • camel-language
  • camel-launcher-container
  • camel-ldap
  • camel-ldif
  • camel-log
  • camel-lra
  • camel-lucene
  • camel-lumberjack
  • camel-lzf
  • camel-mail
  • camel-mail-microsoft-oauth
  • camel-main
  • camel-management
  • camel-management-api
  • camel-mapstruct
  • camel-master
  • camel-maven-plugin
  • camel-mcp-server
  • camel-mcp-server-api
  • camel-mdc
  • camel-metrics
  • camel-micrometer
  • camel-micrometer-observability
  • camel-micrometer-prometheus
  • camel-microprofile-config
  • camel-microprofile-fault-tolerance
  • camel-microprofile-health
  • camel-microprofile-parent
  • camel-milo
  • camel-milvus
  • camel-mina
  • camel-mina-sftp
  • camel-minio
  • camel-mllp
  • camel-mock
  • camel-mongodb
  • camel-mongodb-gridfs
  • camel-mustache
  • camel-mvel
  • camel-mybatis
  • camel-nats
  • camel-neo4j
  • camel-netty
  • camel-netty-http
  • camel-oaipmh
  • camel-oauth
  • camel-observability-services
  • camel-observation
  • camel-ocsf
  • camel-ognl
  • camel-olingo2
  • camel-olingo2-api
  • camel-olingo2-parent
  • camel-olingo4
  • camel-olingo4-api
  • camel-olingo4-parent
  • camel-once
  • camel-openai
  • camel-openapi-java
  • camel-openapi-rest-dsl-generator
  • camel-openapi-validator
  • camel-opensearch
  • camel-openstack
  • camel-opentelemetry
  • camel-opentelemetry-metrics
  • camel-opentelemetry2
  • camel-optaplanner
  • camel-paho
  • camel-paho-mqtt5
  • camel-parquet-avro
  • camel-pdf
  • camel-pg-replication-slot
  • camel-pgevent
  • camel-pgvector
  • camel-pinecone
  • camel-platform-http
  • camel-platform-http-jolokia
  • camel-platform-http-main
  • camel-platform-http-vertx
  • camel-plc4x
  • camel-pqc
  • camel-printer
  • camel-protobuf
  • camel-pubnub
  • camel-pulsar
  • camel-python
  • camel-python3
  • camel-qdrant
  • camel-quartz
  • camel-quickfix
  • camel-quickjs
  • camel-reactive-streams
  • camel-reactor
  • camel-redis
  • camel-ref
  • camel-resilience4j
  • camel-resilience4j-micrometer
  • camel-resourceresolver-github
  • camel-rest
  • camel-rest-openapi
  • camel-rest-postman
  • camel-restdsl-openapi-plugin
  • camel-robotframework
  • camel-rocketmq
  • camel-rss
  • camel-rxjava
  • camel-saga
  • camel-salesforce
  • camel-salesforce-codegen
  • camel-salesforce-maven-plugin
  • camel-salesforce-parent
  • camel-sap-netweaver
  • camel-saxon
  • camel-scheduler
  • camel-schematron
  • camel-seda
  • camel-servicenow
  • camel-servicenow-maven-plugin
  • camel-servicenow-parent
  • camel-servlet
  • camel-shell
  • camel-shiro
  • camel-sjms
  • camel-sjms2
  • camel-slack
  • camel-smb
  • camel-smooks
  • camel-smpp
  • camel-snakeyaml
  • camel-snmp
  • camel-soap
  • camel-solr
  • camel-spiffe
  • camel-splunk-hec
  • camel-spring
  • camel-spring-ai-chat
  • camel-spring-ai-embeddings
  • camel-spring-ai-image
  • camel-spring-ai-parent
  • camel-spring-ai-vector-store
  • camel-spring-batch
  • camel-spring-cloud-config
  • camel-spring-jdbc
  • camel-spring-ldap
  • camel-spring-main
  • camel-spring-parent
  • camel-spring-rabbitmq
  • camel-spring-redis
  • camel-spring-security
  • camel-spring-ws
  • camel-spring-xml
  • camel-sql
  • camel-ssh
  • camel-state-store
  • camel-state-store-parent
  • camel-stax
  • camel-stitch
  • camel-stream
  • camel-streamcaching-test
  • camel-stringtemplate
  • camel-stripe
  • camel-stub
  • camel-support
  • camel-swift
  • camel-syslog
  • camel-tahu
  • camel-tarfile
  • camel-telegram
  • camel-telemetry
  • camel-telemetry-dev
  • camel-tensorflow-serving
  • camel-test-infra-all
  • camel-test-infra-artemis
  • camel-test-infra-cli
  • camel-test-infra-core
  • camel-test-infra-smb
  • camel-test-junit5
  • camel-test-junit6
  • camel-test-main-junit5
  • camel-test-main-junit6
  • camel-test-parent
  • camel-test-spring-junit5
  • camel-test-spring-junit6
  • camel-thrift
  • camel-thymeleaf
  • camel-tika
  • camel-timer
  • camel-tooling-maven
  • camel-toon
  • camel-tracing
  • camel-twilio
  • camel-twitter
  • camel-ubl
  • camel-undertow
  • camel-undertow-spring-security
  • camel-univocity-parsers
  • camel-validator
  • camel-velocity
  • camel-vertx
  • camel-vertx-common
  • camel-vertx-http
  • camel-vertx-parent
  • camel-vertx-websocket
  • camel-wal
  • camel-wasm
  • camel-weather
  • camel-weaviate
  • camel-web3j
  • camel-webhook
  • camel-whatsapp
  • camel-wordpress
  • camel-workday
  • camel-xchange
  • camel-xj
  • camel-xml-io
  • camel-xml-io-dsl
  • camel-xml-jaxb
  • camel-xml-jaxb-dsl
  • camel-xml-jaxb-dsl-test-definition
  • camel-xml-jaxb-dsl-test-spring
  • camel-xml-jaxp
  • camel-xmlsecurity
  • camel-xmpp
  • camel-xpath
  • camel-xslt
  • camel-xslt-saxon
  • camel-yaml-dsl-common
  • camel-yaml-dsl-validator
  • camel-yaml-dsl-validator-maven-plugin
  • camel-yaml-io
  • camel-zendesk
  • camel-zip-deflater
  • camel-zipfile
  • camel-zookeeper
  • camel-zookeeper-master
  • components
  • docs
Modules with tests skipped (24)
  • apache-camel
  • camel-allcomponents
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

Build reactor — dependencies compiled but only changed modules were tested (6 modules)
  • Camel :: AI :: LangChain4j :: Embedding
  • Camel :: AI :: LangChain4j :: EmbeddingStore
  • Camel :: API
  • Camel :: Catalog :: Camel Catalog
  • Camel :: Docs
  • Camel :: Endpoint DSL

⚙️ View full build and test results

@gnodet

gnodet commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Claude Code on behalf of gnodet

@apupier Thanks for catching that! The 6 generated files have been regenerated and committed in the second commit (ee64789). The catalog JSONs, catalog docs, and endpoint DSL factories are now up to date.

Could you re-review when you get a chance?

@gnodet
gnodet marked this pull request as ready for review July 31, 2026 11:38
@gnodet
gnodet requested review from Croway and cunningt July 31, 2026 11:39

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The batch operations design is well-structured and addresses a real performance concern for RAG pipelines. Tests are well-written using AssertJ and a recording store pattern, and documentation with Java/YAML examples is good. However, there are several issues that should be addressed:

[HIGH] Destructive removeAll() fallback — The remove() method now calls store.removeAll() (clearing the entire store) when body is null/empty and no filter is set. Previously this would throw IllegalArgumentException via langchain4j's ensureNotBlank() — a safe failure mode. Making the most destructive operation the default fallback when no input is provided is a data safety risk. Consider requiring explicit intent (e.g., a dedicated header flag or a distinct action like CLEAR).

[MEDIUM] Caller-supplied IDs silently discarded in addBatch() — When EMBEDDING_IDS header is set but no TextSegment body is provided, the code falls through to store.addAll(embeddings) which generates new IDs, silently ignoring the user-provided IDs. Should either loop with add(id, embedding) or throw an error explaining that caller-supplied IDs require text segments for batch operations.

[MEDIUM] FQCN for ArrayListnew java.util.ArrayList<>() used without importing ArrayList, violating the project's no-FQCN convention.

[MEDIUM] EMBEDDINGS header not in CamelLangchain4jAttributes — The new cross-component header constant uses a hardcoded string instead of referencing CamelLangchain4jAttributes in core/camel-api, breaking consistency with the existing EMBEDDING, VECTOR, TEXT_SEGMENT pattern.

[LOW] Missing upgrade guide entry — No entry in the upgrade guide for the behavioral change in REMOVE operation (null body previously threw exception, now clears the store).

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Claude Code on behalf of Guillaume Nodet

@github-actions github-actions Bot added the core label Jul 31, 2026
@gnodet

gnodet commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Claude Code on behalf of gnodet

All review findings have been addressed in commit f267c76:

Finding Severity Resolution
Destructive removeAll() fallback HIGH Now throws IllegalArgumentException — explicit ID(s) or filter required
Caller-supplied IDs silently discarded MEDIUM Loops with add(id, embedding) when no text segments
FQCN for ArrayList MEDIUM Proper import added
EMBEDDINGS not in CamelLangchain4jAttributes MEDIUM Added to core/camel-api with @since 4.22
Missing upgrade guide entry LOW N/A — the null-body behavior was introduced in this same PR, not a change to existing released behavior

Regarding the upgrade guide point: since the REMOVE-with-null-body behavior never existed in a released version (it was introduced in this PR's first commit and corrected in this follow-up), there's no behavioral change for existing users to migrate from — so no upgrade guide entry is needed.

@gnodet
gnodet requested a review from apupier July 31, 2026 12:06

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thorough batch-operations implementation for both embedding and embedding-store components. The caller-supplied-ID support and batch REMOVE are welcome additions. A few data-flow issues stood out that could affect RAG ingestion pipelines:

1. Text segments lost in batch embed → store pipeline (medium)

In LangChain4jEmbeddingsProducer.processBatch(), the message body is overwritten with List<Embedding> at line 96 (message.setBody(embeddings)). Unlike the single-document path — which preserves the original text segment via the TEXT_SEGMENT header — the batch path sets no TEXT_SEGMENTS header. When this flows downstream to the embedding store producer, addBatch() checks whether the body is List<TextSegment> but finds List<Embedding> instead, falling through to addAll(embeddings) and storing embeddings without their text segments.

This is the exact chaining pipeline documented in the PR's own langchain4j-embeddingstore-component.adoc (embed → store), making it a real data-loss scenario for RAG pipelines — search results will return embeddings but not the original text.

2. Size mismatch between callerIds and embeddings not validated (medium)

In LangChain4jEmbeddingStoreProducer.addBatch(), when callerIds != null && textSegments == null, the loop iterates embeddings.size() times and accesses callerIds.get(i) without a size-equality check. If callerIds.size() < embeddings.size(), this throws an unhelpful IndexOutOfBoundsException. If callerIds.size() > embeddings.size(), trailing IDs are silently ignored and incorrectly included in the response body. A defensive size check with a clear error message would improve debuggability.

3. Caller-supplied ID path silently drops text segment (medium)

In the single-add path, when callerId != null, store.add(callerId, embedding) is called and the text-segment check is skipped entirely. The langchain4j EmbeddingStore API has no add(String id, Embedding, TextSegment) method, which explains the current code. However, addAll(List<String>, List<Embedding>, List<TextSegment>) exists and could be used with singleton lists as a workaround. The PR's documentation example shows a chain that sets EMBEDDING_ID after embedding — this exact pipeline loses the text segment.

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Claude Code on behalf of @gnodet

@davsclaus
davsclaus force-pushed the investigate-and-fix-camel-23953-camel-langchain4j branch from f267c76 to a3c3ecb Compare August 6, 2026 13:24

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this well-structured addition of batch operations to the langchain4j embedding components — the RecordingEmbeddingStore test pattern is particularly good, and the documentation with Java/YAML tabs is solid.

Two medium-severity issues remain from the prior self-review rounds that should be addressed before merging.

This review focuses on project rules and conventions. It does not replace specialized AI review tools (CodeRabbit, Sourcery) or static analyzers (SonarCloud).

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Claude Code on behalf of davsclaus

@atiaomar1978-hub

Copy link
Copy Markdown
Contributor

Grok code review — CAMEL-23953

Verdict: Approve with improvements — focused, well-tested batch wiring that closes the LangChain4j API gap without breaking existing routes.


Architecture

langchain4j-embeddings Producer
  List body → embedAll → EMBEDDINGS header + List<Embedding> body
  single body → embed → EMBEDDING / VECTOR / TEXT_SEGMENT headers

langchain4j-embeddingstore Producer ADD
  EMBEDDINGS header → addBatch (addAll variants + caller ID loop)
  EMBEDDING header → single add (+ optional EMBEDDING_ID)

langchain4j-embeddingstore Producer REMOVE
  FILTER header → removeAll(filter)
  Collection body → removeAll(ids)
  String body → remove(id)

Clean dispatch; good javadoc on operation matrix.


Strengths

  • Addresses CAMEL-23953 directly — uses upstream embedAll/addAll/removeAll.
  • Cross-component header constant in camel-api (not a one-off string).
  • Excellent unit tests with RecordingEmbeddingStore counting invocations.
  • Docs + generated catalog/endpoint DSL kept in sync.
  • Author already fixed the two critical review findings (store wipe, discarded caller IDs).

Remaining suggestions

# Area Suggestion
1 Upgrade guide Document REMOVE null/empty body behavior vs 4.21
2 Validation Assert equal list sizes before batch ADD
3 RAG pipeline Document embed→store pattern preserving List<TextSegment> for addAll(embeddings, segments)
4 Batch detection Narrow instanceof List or validate convertible elements
5 Tests Add mismatch + embed→store integration route

Issue status summary

Original issue Resolution
REMOVE null → removeAll() store wipe ✅ Fixed + tested
Caller IDs ignored in batch ✅ Fixed + tested
FQCN ArrayList ✅ Fixed
Hardcoded EMBEDDINGS header ✅ Fixed (CamelLangchain4jAttributes)
List size mismatch ⚠️ Open
Batch embed loses text segments ⚠️ Open (documentation)
Upgrade guide ⚠️ Open
EMBEDDING_ID vs TEXT_SEGMENT precedence ⚠️ Open (document)

Recommendation

Ready for merge after upgrade-guide entry and list-size validation (small diff). Suggest reviewers: @gnodet (author), @davsclaus (AI components).

AI-generated Grok review on behalf of atiaomar1978-hub.

@atiaomar1978-hub

Copy link
Copy Markdown
Contributor

Bugbot review — CAMEL-23953 batch embeddings/embeddingstore

Reviewed investigate-and-fix-camel-23953-camel-langchain4j vs main.

Scope

Adds batch embedAll / addAll / removeAll wiring for LangChain4j embeddings + embedding store; new cross-component CAMEL_LANGCHAIN4J_EMBEDDINGS constant; docs + catalog + endpoint DSL regeneration.

Verified (looks good)

  • Backward compatible single-item paths preserved (tests confirm).
  • Prior HIGH issue (REMOVE null body → wipe store) fixed with explicit IllegalArgumentException.
  • Prior caller-ID batch bug fixed (loop add(id, embedding) when no text segments).
  • CamelLangchain4jAttributes constant added with @since 4.22 — consistent with existing pattern.
  • RecordingEmbeddingStore tests verify SDK method dispatch (9 store tests + 3 embed tests).
  • AssertJ used in new tests; MockEndpoint-style patterns not applicable (producer-only).

Open issues (see inline threads)

Severity Issue Status
Medium No size validation for EMBEDDING_IDS / embeddings / textSegments lists Open
Medium Batch embed replaces body with embeddings — text segments not forwarded for store pipeline Open (doc/UX)
Medium body instanceof List batch trigger is overly broad Open
Low Missing upgrade guide entry for REMOVE null-body behavior change Open
Low Single ADD: EMBEDDING_ID silently ignores TEXT_SEGMENT Open (document or validate)

Test coverage verdict

Good for merge — core batch paths and regression guard (removeWithNoBodyOrFilterThrows) covered. Add mismatch/edge-case tests before calling it complete.

Bugbot verdict: Approve with minor follow-ups (upgrade guide + list validation).

AI-generated Bugbot review on behalf of atiaomar1978-hub.

@apupier apupier left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

several conflicts and build is failing

Add batch embedAll, addAll, removeAll support for LangChain4j embedding
components, enabling efficient RAG ingestion pipelines.

Embeddings producer:
- Detect List body and route to processBatch with embedAll
- Preserve text segments via TEXT_SEGMENTS header for downstream use
- Full GenAI observation support for batch operations

Embedding store producer:
- Batch ADD via EMBEDDINGS header with addAll variants
- Caller-supplied IDs via EMBEDDING_ID/EMBEDDING_IDS headers
- Single add with caller ID + text segment preserved via addAll singleton
- Size validation between callerIds, embeddings, and textSegments
- Batch REMOVE by Collection<String> body or Filter header
- Null/empty REMOVE throws IllegalArgumentException (safe failure)

Shared constants:
- Add CAMEL_LANGCHAIN4J_EMBEDDINGS and CAMEL_LANGCHAIN4J_TEXT_SEGMENTS
  to CamelLangchain4jAttributes in core/camel-api

Documentation and upgrade guide:
- Document batch ADD, caller-supplied IDs, and batch REMOVE
- Add upgrade guide entry for REMOVE behavior change and new headers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet
gnodet force-pushed the investigate-and-fix-camel-23953-camel-langchain4j branch from a3c3ecb to 83b9dc9 Compare September 2, 2026 13:53
@gnodet gnodet changed the title CAMEL-23953: Add batch operations for langchain4j embeddings and embeddingstore CAMEL-23953: Add batch operations for langchain4j embeddings Sep 2, 2026
@gnodet

gnodet commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

All review findings have been addressed in the rebased commit (83b9dc9):

  1. Text segments lost in batch embed→store pipeline — Fixed. The batch path now preserves text segments via a new TEXT_SEGMENTS header (CamelLangChain4jEmbeddingsTextSegments), added to CamelLangchain4jAttributes in core/camel-api. The embedding store producer reads text segments from this header first, falling back to the body. The embed→store pipeline now works seamlessly.

  2. Size mismatch not validated — Fixed. Added explicit size checks before addAll(callerIds, embeddings, textSegments) and the add(id, embedding) loop. Throws IllegalArgumentException with clear sizes.

  3. Caller-supplied ID drops text segment — Fixed. When both EMBEDDING_ID and TEXT_SEGMENT are present, uses addAll(singletonList) to preserve both.

  4. Upgrade guide entry — Added entries for both camel-langchain4j-embeddings (batch embedding, new headers) and camel-langchain4j-embeddingstore (batch ADD/REMOVE, behavior change).

  5. Rebased onto current main — Integrated with the new GenAI observation pattern and resolveEmbedding()/auto-embedding support.

Claude Code on behalf of @gnodet

@gnodet

gnodet commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

@apupier The conflicts have been resolved — the branch is now cleanly rebased onto current main. The code integrates with the GenAI observation pattern and resolveEmbedding() auto-embedding support that were added since the original PR.

Claude Code on behalf of @gnodet

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

✅ Generated files are up to date

An earlier CI run reported uncommitted generated changes; the latest run no longer does.

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this — the batch add/remove logic is clean and the store-side test coverage (asserting which store overload each path invokes) is genuinely thorough. The prior review feedback (destructive removeAll() fallback, text-segment preservation, size validation, shared header constants) has clearly been incorporated. One blocking item and a few suggestions.

🔴 Blocking

Wrong release version targeted. camel-4.22.0 is already released and main is now 4.23.0-SNAPSHOT, so these features ship in 4.23, not 4.22:

  • The two @since 4.22 tags in CamelLangchain4jAttributes.java should be @since 4.23 (CLAUDE.md: use the upcoming minor release). See inline suggestions.
  • The upgrade-guide entries were added to camel-4x-upgrade-guide-4_22.adoc (a released line). They belong in the existing camel-4x-upgrade-guide-4_23.adoc, under "Upgrading Camel 4.22 to 4.23". As-is they are attached to a version that can never contain the change. Both the === camel-langchain4j-embeddings and the === camel-langchain4j-embeddingstore additions need to move.

🟡 Suggestions (non-blocking)

  1. LangChain4jEmbeddingsBatchTest.batchEmbeddingTokenUsage is named/@DisplayName'd "sets token usage headers" but only asserts EMBEDDINGS is not null — it never checks INPUT_TOKEN_COUNT/TOTAL_TOKEN_COUNT. Either assert the token headers or rename the test to match what it verifies.
  2. REMOVE with an empty Collection (LangChain4jEmbeddingStoreProducer.remove): an empty-collection body hits store.removeAll(ids) directly, which throws langchain4j's own opaque "cannot be null or empty" — the exact failure the null/empty guard was added to prevent. Consider treating an empty collection the same as a no-body REMOVE so it produces the clear IllegalArgumentException.
  3. Empty List body (LangChain4jEmbeddingsProducer.process): any List routes to processBatchmodel.embedAll(emptyList) when empty; behavior is model-dependent. A guard or a quick test would make the empty-batch case explicit.

✅ Looks good

  • Single-path token/finish-reason headers correctly mirrored in populateBatchHeaders.
  • Text-segment preservation via header + body fallback in addBatch is correct for the chained embed→store pipeline.
  • Generated catalog/endpoint-dsl files regenerated and committed.

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Comment thread core/camel-api/src/main/java/org/apache/camel/ai/CamelLangchain4jAttributes.java Outdated
Comment thread core/camel-api/src/main/java/org/apache/camel/ai/CamelLangchain4jAttributes.java Outdated
Comment thread docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc Outdated
- Change @SInCE 4.22 to @SInCE 4.23 on CAMEL_LANGCHAIN4J_EMBEDDINGS
  and CAMEL_LANGCHAIN4J_TEXT_SEGMENTS constants (4.22.0 is already
  released, main is 4.23.0-SNAPSHOT)
- Move langchain4j-embeddings and langchain4j-embeddingstore upgrade
  guide entries from camel-4x-upgrade-guide-4_22.adoc to
  camel-4x-upgrade-guide-4_23.adoc
- batchEmbeddingTokenUsage: assert INPUT_TOKEN_COUNT and
  TOTAL_TOKEN_COUNT headers are set and positive
- REMOVE with empty Collection: throw IllegalArgumentException
  instead of passing through to store.removeAll(emptyCollection)
- Batch embedding with empty List: throw IllegalArgumentException
  instead of passing through to model.embedAll(emptyList)
@davsclaus davsclaus added this to the 4.23.0 milestone Sep 3, 2026
@davsclaus davsclaus added the enhancement New feature or request label Sep 3, 2026
@davsclaus
davsclaus merged commit c72c14f into apache:main Sep 3, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants