-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable Tools to Define Execution Model #1023
Conversation
I was curious to test these changes in my workspace, but when I use the Moving on, I would like to ask about a piece of code used within the |
Can you perhaps add a test into this PR that surfaces the problem? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome stuff!
I only added a few minor comments, but we should also see what is causing the problem that @andreadimaio mentions
core/deployment/src/main/java/io/quarkiverse/langchain4j/deployment/AiServicesProcessor.java
Outdated
Show resolved
Hide resolved
...eployment/src/main/java/io/quarkiverse/langchain4j/deployment/items/ToolMethodBuildItem.java
Show resolved
Hide resolved
core/deployment/src/test/java/io/quarkiverse/langchain4j/test/tools/ToolExecutionModelTest.java
Show resolved
Hide resolved
It should have been a draft - sorry. |
Yes, I could create something in the |
Up to @cescoffier |
@andreadimaio would be great! I know a few cases that should not have been working but were working that are now rejected (calling an imperative method from the event loop without the Now there is still a bit of work do do, as I "forgot" to implement context propagation. It should not take long, but my next coding session will be next week :-( |
Here you can find the test cescoffier#1.
If I remove the annotations: |
Oh oh… that may require a change in Quarkus. I’m wondering why it works in
core…
…On Thu 31 Oct 2024 at 12:35, Andrea Di Maio ***@***.***> wrote:
Here you can find the test cescoffier#1
<cescoffier#1>.
When I run the test, I get the exception:
The @Blocking, @nonblocking and @RunOnVirtualThread annotations may only be used on "entrypoint" methods (methods invoked by various frameworks in Quarkus)
Using the @Blocking, @nonblocking and @RunOnVirtualThread annotations on methods that can only be invoked by application code is invalid
at io.quarkus.deployment.execannotations.ExecutionModelAnnotationsProcessor.check(ExecutionModelAnnotationsProcessor.java:55)
at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:733)
at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:856)
at io.quarkus.builder.BuildContext.run(BuildContext.java:256)
at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2516)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2495)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1521)
at java.base/java.lang.Thread.run(Thread.java:1583)
at org.jboss.threads.JBossThread.run(JBossThread.java:483)
If I remove the annotations: @Blocking, @nonblocking and
@RunOnVirtualThread, the tests are green.
—
Reply to this email directly, view it on GitHub
<#1023 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADCG7OP76PQBJGI4YBOQQ3Z6IIWVAVCNFSM6AAAAABQ4XUUEOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDINBZGYZTSMJVG4>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
There is a package name check… but I should be able to emit the right build
item to handle this.
On Thu 31 Oct 2024 at 12:44, clement escoffier ***@***.***>
wrote:
… Oh oh… that may require a change in Quarkus. I’m wondering why it works in
core…
On Thu 31 Oct 2024 at 12:35, Andrea Di Maio ***@***.***>
wrote:
> Here you can find the test cescoffier#1
> <cescoffier#1>.
> When I run the test, I get the exception:
>
> The @Blocking, @nonblocking and @RunOnVirtualThread annotations may only be used on "entrypoint" methods (methods invoked by various frameworks in Quarkus)
> Using the @Blocking, @nonblocking and @RunOnVirtualThread annotations on methods that can only be invoked by application code is invalid
> at io.quarkus.deployment.execannotations.ExecutionModelAnnotationsProcessor.check(ExecutionModelAnnotationsProcessor.java:55)
> at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:733)
> at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:856)
> at io.quarkus.builder.BuildContext.run(BuildContext.java:256)
> at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
> at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2516)
> at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2495)
> at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1521)
> at java.base/java.lang.Thread.run(Thread.java:1583)
> at org.jboss.threads.JBossThread.run(JBossThread.java:483)
>
> If I remove the annotations: @Blocking, @nonblocking and
> @RunOnVirtualThread, the tests are green.
>
> —
> Reply to this email directly, view it on GitHub
> <#1023 (comment)>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AADCG7OP76PQBJGI4YBOQQ3Z6IIWVAVCNFSM6AAAAABQ4XUUEOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDINBZGYZTSMJVG4>
> .
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>
|
@andreadimaio I think I fixed it. |
Yes, it works! |
About this code? I think it can be removed and managed with annotations. |
Uhm... if I remove these lines from the if (tools != null) {
// Today Langchain4j doesn't allow to use the async operation with tools.
// One idea might be to give to the developer the possibility to use the VirtualThread.
mutiny.emitOn(Infrastructure.getDefaultWorkerPool());
} And I try to call a tool method annotated with @ToolBox(Calculator.class)
public Multi<String> message(@UserMessage String message); @ApplicationScoped
public class Calculator {
@Inject
EmbeddingModel model;
@Tool
@Blocking
public int sum(int a, int b) {
model.embed("test");
return a + b;
}
} I am getting |
QuarkusToolExecutor case BLOCKING:
if (io.vertx.core.Context.isOnEventLoopThread()) {
throw new IllegalStateException("Cannot execute blocking tools on event loop thread");
} I think the problem at this point is the |
It should have done the switch automatically. I will add a few tests.
…On Thu 31 Oct 2024 at 16:50, Andrea Di Maio ***@***.***> wrote:
case BLOCKING:
if (io.vertx.core.Context.isOnEventLoopThread()) {
throw new IllegalStateException("Cannot execute blocking tools on event loop thread");
}
—
Reply to this email directly, view it on GitHub
<#1023 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADCG7MYNHP6J2GGUJ3KRHTZ6JGUTAVCNFSM6AAAAABQ4XUUEOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDINJQGIZDENRQG4>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Yes, if the switch is the line |
Interesting, can I reproduce it with your test? |
Ok, I know why it happens - I need to think about the proper way to fix it. |
Not yet, but I can try to add it.
What's happening? |
Basically, each item is emitted on the event loop. In my tests, I simplified this a bit too much by sending all the items synchronously on subscription (on the event loop). The current switch only happens at subscription time. So it works for my tests... but only in my tests. |
@cescoffier I'd like to include this in the next release, but if it still needs plenty of work, we can have in a later one |
I have a plan to fix the remaining issue. When do you want to cut the release? |
This week was the plan, but it's not set in stone |
I just got 1 free hour this afternoon, that should be enough |
💪 |
This commit introduces support for tools to define their execution model with annotations such as @Blocking, @nonblocking, and @RunOnVirtualThread, or to rely on the method signature to specify the execution model. Execution constraints are enforced based on the caller thread: for instance, blocking calls are disallowed on the event loop. For reactive AiService method (streaming), a detection is done at build time to determine if the execution can be done on the event loop or need to be switched to a worker thread. The detection checks the execution model of the various tool methods the AI service method can invoke.
…and @RunOnVirtualThread
56e1d7c
to
b33c558
Compare
@geoand how do we modify samples? I need to bump the version of quarkus langchain4j to demonstrate the feature. If I switch to 999-SNAPSHOT would it breaks the world? |
…es can use blocking tools
(@geoand well... let's try) |
It seems like some of the tests fail |
@geoand @andreadimaio Seems like Watsonx is doing something that now blocks the event loop - I'm having a look. |
Hopefully, it should be better now. The issue was that the initial call was not on a Vert.x context (neither event loop nor worker), which broke the switch (as I had nowhere to switch to). |
All green! |
I could do some testing in my local environment if you think it would be useful. But I can do that in a bit. |
… done from a Vert.x context
5f1eea1
to
bc7d6c0
Compare
It works!! 🚀 if (tools != null) {
// Today Langchain4j doesn't allow to use the async operation with tools.
// One idea might be to give to the developer the possibility to use the VirtualThread.
mutiny.emitOn(Infrastructure.getDefaultWorkerPool());
} If you don't want to add this change here, I can open another PR. |
Removed emitOn on default worker pool for watsonx.ai
This commit introduces support for tools to define their execution model with annotations such as @Blocking, @nonblocking, and @RunOnVirtualThread, or to rely on the method signature to specify the execution model.
Execution constraints are enforced based on the caller thread; for instance, blocking calls are disallowed on the event loop.
For reactive AiService method (streaming), a detection is done at build time to determine if the execution can be done on the event loop or need to be switched to a worker thread. The detection checks the execution model of the various tool methods the AI service method can invoke.