Skip to content

Commit ef06a59

Browse files
authored
Add Coherence Embedding Store Support (helidon-io#10419)
1 parent 3d6596d commit ef06a59

File tree

15 files changed

+700
-37
lines changed

15 files changed

+700
-37
lines changed

langchain4j/codegen/src/main/java/io/helidon/integrations/langchain4j/codegen/ConfigureMethodBuilder.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,19 @@ class ConfigureMethodBuilder {
4444
.addDescriptionLine("<b>Skipped:</b>")
4545
.addDescriptionLine("<ul>");
4646

47-
if (parentTypeInfo.elementInfo().stream()
47+
var customBuilderMappingMethod = parentTypeInfo.elementInfo().stream()
4848
.filter(m -> m.kind().equals(ElementKind.METHOD))
4949
.filter(m -> m.parameterArguments().isEmpty())
5050
.filter(m -> m.typeName().equals(builderTypeInfo.typeName()))
51-
.anyMatch(m -> m.elementName().equals("configuredBuilder"))) {
51+
.filter(m -> m.elementName().equals("configuredBuilder"))
52+
.findFirst();
53+
54+
if (customBuilderMappingMethod.isPresent()) {
5255
confMethodBuilder
5356
.addContent("var modelBuilder = ")
5457
.addContent(parentTypeInfo.typeName())
55-
.addContentLine(".super.configuredBuilder();");
58+
.addContent(".super.configuredBuilder(")
59+
.addContentLine(");");
5660
} else {
5761
confMethodBuilder.addContent("var modelBuilder = ").addContent(modelTypeName).addContentLine(".builder();");
5862
}

langchain4j/codegen/src/main/java/io/helidon/integrations/langchain4j/codegen/IntrospectionBlueprintBuilder.java

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,17 @@ private static boolean isInjectedByDefault(TypedElementInfo modelBldMethod) {
167167
return false;
168168
}
169169

170-
void addArrayProperty(String propName, TypeName propType, TypedElementInfo modelBldMethod) {
170+
void addArrayProperty(String propName, TypeName propType, TypedElementInfo modelBldMethod, boolean skipBuilderMapping) {
171171
var methodBuilder = createMethodBuilder(modelBldMethod)
172172
.name(propName);
173173

174174
methodBuilder.addAnnotation(BLDR_SINGULAR_ANNOTATION);
175175

176176
methodBuilder.returnType(TypeName.builder(LIST).addTypeArgument(propType).build());
177177

178-
confMethodBuilder.configureProperty(propName, propType, false, true, false);
178+
if (!skipBuilderMapping) {
179+
confMethodBuilder.configureProperty(propName, propType, false, true, false);
180+
}
179181

180182
if (overrideProps.containsKey(propName)) {
181183
confMethodBuilder.commentOverriddenProperty(overrideProps.get(propName));
@@ -184,8 +186,7 @@ void addArrayProperty(String propName, TypeName propType, TypedElementInfo model
184186
}
185187
}
186188

187-
void addOptionalProperty(String propName, TypeName propType, TypedElementInfo modelBldMethod) {
188-
var custBuilderMappingAnnotation = modelBldMethod.findAnnotation(LangchainTypes.MODEL_CUSTOM_BUILDER_MAPPING);
189+
void addOptionalProperty(String propName, TypeName propType, TypedElementInfo modelBldMethod, boolean skipBuilderMapping) {
189190
var methodBuilder = createMethodBuilder(modelBldMethod)
190191
.name(propName);
191192

@@ -198,20 +199,21 @@ void addOptionalProperty(String propName, TypeName propType, TypedElementInfo mo
198199

199200
if (overrideProps.containsKey(propName)) {
200201
confMethodBuilder.commentOverriddenProperty(overrideProps.get(propName));
201-
confMethodBuilder.configureProperty(propName, propType, false, false,
202-
// Overridden non-optional props are kept mandatory
203-
overrideProps.get(propName).typeName().isOptional());
202+
if (!skipBuilderMapping) {
203+
confMethodBuilder.configureProperty(propName, propType, false, false,
204+
// Overridden non-optional props are kept mandatory
205+
overrideProps.get(propName).typeName().isOptional());
206+
}
204207

205208
} else {
206209
classModelBuilder().addMethod(methodBuilder.build());
207-
if (custBuilderMappingAnnotation.isEmpty()) {
210+
if (!skipBuilderMapping) {
208211
confMethodBuilder.configureProperty(propName, propType, false, false, true);
209212
}
210213
}
211214
}
212215

213-
void addCollectionProperty(String propName, TypeName propType, TypedElementInfo modelBldMethod) {
214-
var custBuilderMappingAnnotation = modelBldMethod.findAnnotation(LangchainTypes.MODEL_CUSTOM_BUILDER_MAPPING);
216+
void addCollectionProperty(String propName, TypeName propType, TypedElementInfo modelBldMethod, boolean skipBuilderMapping) {
215217
var methodBuilder = createMethodBuilder(modelBldMethod)
216218
.name(propName);
217219

@@ -222,7 +224,7 @@ void addCollectionProperty(String propName, TypeName propType, TypedElementInfo
222224
.type(propType)
223225
.build());
224226

225-
if (custBuilderMappingAnnotation.isEmpty()) {
227+
if (!skipBuilderMapping) {
226228
confMethodBuilder.configureProperty(propName, propType, false, false, false);
227229
}
228230

@@ -363,15 +365,16 @@ IntrospectionBlueprintBuilder introspectBuilder(List<String> skips, Set<String>
363365
for (var m : propertyMap.values()) {
364366
var methodName = m.signature().name();
365367
var paramType = m.signature().parameterTypes().getFirst();
368+
var skipBuilderMapping = m.findAnnotation(LangchainTypes.MODEL_CUSTOM_BUILDER_MAPPING).isPresent();
366369

367370
if (paramType.array() && !hasCollectionAlternative(m, propertyList)) {
368-
this.addArrayProperty(methodName, paramType, m);
371+
this.addArrayProperty(methodName, paramType, m, skipBuilderMapping);
369372

370373
} else if (paramType.isList() || paramType.isSet() || paramType.isMap()) {
371-
this.addCollectionProperty(methodName, paramType, m);
374+
this.addCollectionProperty(methodName, paramType, m, skipBuilderMapping);
372375

373376
} else {
374-
this.addOptionalProperty(methodName, paramType, m);
377+
this.addOptionalProperty(methodName, paramType, m, skipBuilderMapping);
375378

376379
}
377380
}
@@ -404,13 +407,13 @@ private void introspectOverrides() {
404407
} else {
405408

406409
if (propertyType.array() && !hasCollectionAlternative(m, new ArrayList<>(overrideProps.values()))) {
407-
this.addArrayProperty(propertyName, propertyType, m);
410+
this.addArrayProperty(propertyName, propertyType, m, skipBuilderMapping);
408411

409412
} else if (propertyType.isList() || propertyType.isSet() || propertyType.isMap()) {
410-
this.addCollectionProperty(propertyName, propertyType, m);
413+
this.addCollectionProperty(propertyName, propertyType, m, skipBuilderMapping);
411414

412415
} else {
413-
this.addOptionalProperty(propertyName, propertyType, m);
416+
this.addOptionalProperty(propertyName, propertyType, m, skipBuilderMapping);
414417

415418
}
416419
}

langchain4j/langchain4j/src/main/java/io/helidon/integrations/langchain4j/EmbeddingStoreContentRetrieverConfigBlueprint.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,21 @@ interface EmbeddingStoreContentRetrieverConfigBlueprint {
4949
/**
5050
* Embedding store to use in the content retriever.
5151
*
52-
* @return an {@link java.util.Optional} containing the embedding store
52+
* @return an {@link java.util.Optional} default service bean is injected or {@code embedding-model.service-registry.named}
53+
* can be used to select a named bean
5354
*/
55+
@Option.Configured
56+
@Option.RegistryService
5457
EmbeddingStore<TextSegment> embeddingStore();
5558

5659
/**
5760
* Explicit embedding model to use in the content retriever.
5861
*
59-
* @return an {@link java.util.Optional} containing the embedding model bean name or "discovery:auto" if the bean must be
60-
* discovered automatically
62+
* @return an {@link java.util.Optional} default service bean is injected or {@code embedding-model.service-registry.named}
63+
* can be used to select a named bean
6164
*/
65+
@Option.Configured
66+
@Option.RegistryService
6267
Optional<EmbeddingModel> embeddingModel();
6368

6469
/**

langchain4j/langchain4j/src/main/java/io/helidon/integrations/langchain4j/EmbeddingStoreContentRetrieverFactory.java

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,9 @@
2323
import io.helidon.common.Weight;
2424
import io.helidon.common.Weighted;
2525
import io.helidon.common.config.Config;
26-
import io.helidon.common.types.TypeName;
2726
import io.helidon.service.registry.Service;
2827

29-
import dev.langchain4j.data.segment.TextSegment;
30-
import dev.langchain4j.model.embedding.EmbeddingModel;
3128
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
32-
import dev.langchain4j.store.embedding.EmbeddingStore;
3329

3430
import static io.helidon.integrations.langchain4j.EmbeddingStoreContentRetrieverConfigBlueprint.CONFIG_ROOT;
3531

@@ -41,17 +37,11 @@
4137
@Service.Singleton
4238
@Weight(Weighted.DEFAULT_WEIGHT - 10)
4339
public class EmbeddingStoreContentRetrieverFactory implements Supplier<Optional<EmbeddingStoreContentRetriever>> {
44-
private static final TypeName STORE_TYPE = TypeName.builder()
45-
.type(EmbeddingStore.class)
46-
.addTypeArgument(TypeName.create(TextSegment.class))
47-
.build();
4840

4941
private final LazyValue<Optional<EmbeddingStoreContentRetriever>> contentRetriever;
5042

5143
@Service.Inject
52-
EmbeddingStoreContentRetrieverFactory(Supplier<EmbeddingStore<TextSegment>> embeddingStore,
53-
Supplier<Optional<EmbeddingModel>> embeddingModel,
54-
Config config) {
44+
EmbeddingStoreContentRetrieverFactory(Config config) {
5545
var configBuilder =
5646
EmbeddingStoreContentRetrieverConfig.builder().config(config.get(CONFIG_ROOT));
5747

@@ -60,9 +50,6 @@ public class EmbeddingStoreContentRetrieverFactory implements Supplier<Optional<
6050
if (!configBuilder.enabled()) {
6151
return Optional.empty();
6252
}
63-
configBuilder.embeddingStore(embeddingStore.get());
64-
embeddingModel.get().ifPresent(configBuilder::embeddingModel);
65-
6653
return Optional.of(create(configBuilder.build()));
6754
});
6855
} else {

0 commit comments

Comments
 (0)