How to use Function wrappers in the new api ?

#2 · open · 1 comments

View on GitHub ↗

100xbiz

Problem: There is no clear example or documentation (currently outdated) on how to add function wrappers (are function wrappers deprecated ?) that can dynamically accept these variables and use them in function callbacks during chat prompt execution. Request: Please provide an example or extend the documentation to show how to configure function wrappers that can accept dynamic variables during a chat session. Example Scenario: Here’s a simplified version of what I am trying to achieve, focusing on modifying booking dates: Here there is a small modification; the customer before entering the chat session will provide the booking id, in a form (no AI involved) and the static data like the IP address of the customer is passed by the calling application and the : `Final req = Static data + AI input params` ```java @Service public class CustomerSupportAssistant { private final ChatClient chatClient; private final BookingService bookingService; @Autowired public CustomerSupportAssistant( ChatClient.Builder modelBuilder, VectorStore vectorStore, ChatMemory chatMemory, BookingService bookingService ) { this.bookingService = bookingService; this.chatClient = modelBuilder .defaultSystem(""" You are a customer chat support agent of an airline named "Funnair". Respond in a friendly, helpful, and joyful manner. You are interacting with customers through an online chat system. Use the provided functions to change bookings. Today is {current_date}. """) .defaultAdvisors( new PromptChatMemoryAdvisor(chatMemory), new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults())) // removed the default functions to add dynamic input functions .build(); } public Flux<String> chat( String chatId, String userMessageContent, Booking booking, // is now passed by the calling application / code String ipAddress // cannot be expected to be passed by customer in chat so is now passed by the calling application / code ) { var dynamicChatOptions = OpenAiChatOptions.builder() .withModel("gpt-3.5-turbo") .withMaxTokens(100) .withFunctionCallbacks( List.of( FunctionCallbackWrapper.builder( (ChangeBookingDatesRequest request) -> { bookingService.changeBooking( booking.id(), request.from(), // for validation if invalid dates are provided request.to(), request.ipAddress() // security check or audit log ); return "Booking dates changed successfully"; }) .withName("changeBooking") .withDescription("Change booking dates with additional parameters") .build())) .build(); return this.chatClient.prompt() .withOptions(dynamicChatOptions) .system(s -> s.param("current_date", LocalDate.now().toString())) .user(userMessageContent) .advisors(a -> a .param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId) .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100)) .stream().content(); } } ``` # ERROR When I try to implement the above approach, I'm getting the following error: The code works and there is no error till I add the `dynamicChatOptions` to the chatClient.prompt() method. my setup : ```yaml spring: ai: openai: api-key: ${OPEN_AI_KEY} chat: options: model: gpt-3.5-turbo-0125 ``` ```json { "error": { "message": "You didn't provide an API key. You need to provide your API key in an Authorization header using Bearer auth (i.e. Authorization: Bearer YOUR_KEY), or as the password field (with blank username) if you're accessing the API from your browser and are prompted for a username and password. You can obtain an API key from https://platform.openai.com/account/api-keys.", "type": "invalid_request_error", "param": null, "code": null } } ```

Comments

MishraRajMohit

The older FunctionCallbackWrapper API is now deprecated, replaced by FunctionCallback.builder(...). You should update to the new API to avoid runtime issues Use callback builder + inputType + capture external variables like FunctionCallback.call(String, ToolContext) that allows you to pass runtime context implicitly (e.g. booking ID, user IP) via the callback environment. for example : // 1. Define the function callback using a BiFunction to access ToolContext FunctionCallback callback = FunctionCallback.builder() .function("changeBookingDates", (ChangeBookingRequest req, ToolContext ctx) -> { String bookingId = (String) ctx.getContext().get("bookingId"); String ip = (String) ctx.getContext().get("ipAddress"); bookingService.changeBooking(bookingId, req.from(), req.to(), ip); return "Booking updated"; }) .description("Change booking dates with audit context") .inputType(ChangeBookingRequest.class) .build(); // 2. Build chat prompt with function and toolContext ChatResponse resp = chatClient.prompt() .user("Please change my booking dates from 2025-09-10 to 2025-09-12") .functions(callback) .toolContext(Map.of( "bookingId", booking.getId(), "ipAddress", ipAddress )) .call(); String assistantReply = resp.content(); this might help:👍