|
| 1 | +--- |
| 2 | +title: "Resolving LangChain4j AI services by interface" |
| 3 | +date: 2024-12-20 |
| 4 | +draft: false |
| 5 | +authors: [aldettinger] |
| 6 | +categories: ["Camel", "AI"] |
| 7 | +preview: "Explain the new feature to resolve AI services by interface directly from Camel Quarkus" |
| 8 | +--- |
| 9 | + |
| 10 | +# Introduction |
| 11 | + |
| 12 | +In a recent series [of Artificial Intelligence related blog posts](/categories/AI/), we have learned about the Camel Quarkus LangChain4j extension. |
| 13 | +It offers possibilities to implement new AI related scenarios like data extraction. |
| 14 | +The underlying implementation of Quarkus LangChain4j seems to offer interesting abstractions that, for instance make it possible to switch between Large Language Models quite simply. |
| 15 | +We have also started to see some improvements when it comes to invoking AI services thanks to camel bean binding and annotations. |
| 16 | +That's a good start, still after experimentation, there is room for more improvement, especially when it comes to AI service resolution from Camel. |
| 17 | + |
| 18 | +# AI service resolution by interface |
| 19 | + |
| 20 | +In the past we needed to manually inject the AI service as shown below: |
| 21 | + |
| 22 | +``` |
| 23 | +@ApplicationScoped |
| 24 | +public class MyRoutes extends RouteBuilder { |
| 25 | +
|
| 26 | + @Inject |
| 27 | + MyAIService myAiService; |
| 28 | +
|
| 29 | + @Override |
| 30 | + public void configure() { |
| 31 | + from("...") |
| 32 | + .bean(myAiService); |
| 33 | + } |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +Looking a bit more, is there really a great interest to manually inject the bean with `@Inject`? |
| 38 | +As you know, the community is oriented toward inverting the developer experience with tools like [Camel JBang](/manual/camel-jbang.html). |
| 39 | +This philosophy mandates to concentrate on the integration logic first and then deal with runtime intricacies later on, if ever needed. |
| 40 | + |
| 41 | +And in the end, the code snippet seen above is kind of breaking this principle. |
| 42 | +So how could we improve the situation ? |
| 43 | +After some thought, it turns out that a more transparent injection could help in such a situation. |
| 44 | + |
| 45 | +Indeed, if we could erase this explicit manual injection, chances are that the code would arguably be more: |
| 46 | + + Compact |
| 47 | + + Focused on the integration logic |
| 48 | + + Abstracted from the underlying runtime |
| 49 | + |
| 50 | +Pushing the rationale further, the question should even be asked the opposite way. |
| 51 | +Like, how would a common camel user write such an integration route ? |
| 52 | +And actually, it could be done in a simpler way as follows: |
| 53 | + |
| 54 | +``` |
| 55 | +@ApplicationScoped |
| 56 | +public class MyRoutes extends RouteBuilder { |
| 57 | +
|
| 58 | + @Override |
| 59 | + public void configure() { |
| 60 | + from("...") |
| 61 | + .bean(MyAIService.class); |
| 62 | + } |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +This time, we only mandate the expected AI service interface and let camel to do whatever is needed under the hood to resolve it. |
| 67 | +This looks a nice idea, however while experimenting this construct... It resulted in a cryptic error message. |
| 68 | + |
| 69 | +People used to create Camel Quarkus extensions will have noticed quickly that the Quarkus bean removal mechanism would hit there. |
| 70 | +More precisely, with Quarkus, the dependency injection occurs at build time, once and for all. |
| 71 | +In this spirit, a bean that is not referenced at build time could be considered useless and literally [removed](https://quarkus.io/blog/unused-beans/). |
| 72 | + |
| 73 | +And in the case at hand, Camel and Quarkus do not play well to the point of automatically detecting that situation. |
| 74 | +As always, there are manual [workarounds](https://quarkus.io/guides/cdi-reference#eliminate_false_positives) that could be applied. |
| 75 | + |
| 76 | +However, this kind of issues is best fixed in the Camel Quarkus LangChain4j extension itself. |
| 77 | +Indeed, this extension aims at solving as much as possible the intricacies of developing camel routes using high-level [AI services](https://docs.langchain4j.dev/tutorials/ai-services/). |
| 78 | +The good news is that the [AI service resolution by interface](/camel-quarkus/next/reference/extensions/langchain4j.html#extensions-langchain4j-configuration-resolving-ai-services-by-interface) has just been delivered with the recent [Camel Quarkus 3.17.0 release](/blog/2024/12/camel-quarkus-release-3.17.0/). |
| 79 | + |
| 80 | +# Conclusion |
| 81 | + |
| 82 | +Initially, I hesitated to create the Camel Quarkus LangChain4j extension, as the scope was too narrow. |
| 83 | +Still experimentation after experimentation, we discover some intricacies and user experience improvements that in the end amply justify the maintenance cost of this new extension. |
| 84 | +Being able to resolve AI services by interface is just one of those goodness. |
| 85 | +There are actually more coming in future versions. |
| 86 | +That should be a good subject for a next blog post. |
| 87 | +Meanwhile, I would encourage the community to test out the [Camel Quarkus Langchain4j extension](/camel-quarkus/next/reference/extensions/langchain4j.html). |
| 88 | +And please, as usual, feel welcome to report any bugs and improvements [here](https://github.com/apache/camel-quarkus/issues/new/choose). |
0 commit comments