-
Notifications
You must be signed in to change notification settings - Fork 728
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
Update ModelListener API to be more integration friendly #1157
Conversation
The idea here is to allow the onRequest method to return an object which will then be passed along to the response and error methods. This allows for integrations to attach anything they need when the request is made and access it when the response or error methods are called. On the implementation side this looks a little awkward because of the generics, but the upside is that for users / integrators of ModelListener the signature of the class and methods provide very good hints on how to implement them
Hi @geoand I really like the idea of making it more flexible, but I am not sure about this exact implementation. For me it feels simpler to have a public class Context<Request, Response> {
private Request request;
private Response response;
private final Map<Object, Object> attributes = new HashMap<>();
} And public interface ModelListener<Request, Response> {
default void onRequest(Request request, Context<Request, Response> context) {
}
default void onResponse(Response response, Context<Request, Response> context) {
}
default void onError(Throwable error, Context<Request, Response> context) {
}
} Then users can store and retrieve attributes like this: ModelListener<ChatLanguageModelRequest, ChatLanguageModelResponse> modelListener =
new ModelListener<ChatLanguageModelRequest, ChatLanguageModelResponse>() {
@Override
public void onRequest(ChatLanguageModelRequest request,
Context<ChatLanguageModelRequest, ChatLanguageModelResponse> context) {
context.attributes().put("id", "12345");
}
@Override
public void onResponse(ChatLanguageModelResponse response,
Context<ChatLanguageModelRequest, ChatLanguageModelResponse> context) {
ChatLanguageModelRequest request = context.request();
Object id = context.attributes().get("id");
}
@Override
public void onError(Throwable error,
Context<ChatLanguageModelRequest, ChatLanguageModelResponse> context) {
ChatLanguageModelRequest request = context.request();
ChatLanguageModelResponse response = context.response();
Object id = context.attributes().get("id");
}
}; WDYT? |
It is used in the Vertx metrics integration fairly extensively |
The context idea works equally well, whichever you prefer is fine with me |
I like the idea of a Alternatively, perhaps we can have separate // all fields final for immutability
@Getter
@Builder
public class RequestContext<TRequest> {
private final TRequest request;
private final Map<Object, Object> attributes = new HashMap<>();
}
@Getter
@Builder
public class ResponseContext<TRequest, TResponse> {
private final RequestContext<TRequest> requestContext;
private final TResponse response;
}
@Getter
@Builder
public class ErrorContext<TRequest> {
private final RequestContext<TRequest> requestContext;
private final Exception exception;
}
public interface ModelListener<TRequest, TResponse> {
default void onRequest(RequestContext<TRequest> context) {
}
default void onResponse(ResponseContext<TRequest, TResponse> context) {
}
default void onException(ErrorContext<TRequest> context) {
}
} This would also allow us to have different data associated with |
@langchain4j any chance we could get one of these proposals in |
@geoand yes, I plan to check this today |
🙏🏼 |
Hi @brunobat, @geoand, @ashimoon I have doubts about generic |
From my POV (as an integrator, not and end user), that's fine. |
@geoand thanks, do you see any major drawbacks from the user perspective? |
Not really |
Closing this as #1229 was merged |
The idea here is to allow the onRequest method to return an object which will then be passed along to the
response and error methods.
This allows for integrations to attach anything they need when the request is made and access it when the response or error methods are called.
On the implementation side this looks a little
awkward because of the generics, but the upside
is that for users / integrators of
ModelListener
,the signature of the class and methods provide very good hints on how to implement them
This follows up on the discussion I started here.