@@ -533,6 +533,195 @@ If you use `@JsonProperty(required = false)`, the `false` value will be ignored.
533
533
must mark all properties as _ required_ , so the schema generated from your Java classes will respect
534
534
that restriction and ignore any annotation that would violate it.
535
535
536
+ ## Function calling
537
+
538
+ OpenAI [ Function Calling] ( https://platform.openai.com/docs/guides/function-calling?api-mode=chat )
539
+ lets you integrate external functions directly into the language model's responses. Instead of
540
+ producing plain text, the model can output instructions (with parameters) for calling a function
541
+ when appropriate. You define a [ JSON schema] ( https://json-schema.org/overview/what-is-jsonschema )
542
+ for functions, and the model uses it to decide when and how to trigger these calls, enabling more
543
+ interactive, data-driven applications.
544
+
545
+ A JSON schema describing a function's parameters can be defined via the API by building a
546
+ [ ` ChatCompletionTool ` ] ( openai-java-core/src/main/kotlin/com/openai/models/chat/completions/ChatCompletionTool.kt )
547
+ containing a
548
+ [ ` FunctionDefinition ` ] ( openai-java-core/src/main/kotlin/com/openai/models/FunctionDefinition.kt )
549
+ and then using ` addTool ` to set it on the input parameters. The response from the AI model may then
550
+ contain requests to call your functions, detailing the functions' names and their parameter values
551
+ as JSON data that conforms to the JSON schema from the function definition. You can then parse the
552
+ parameter values from this JSON, invoke your functions, and pass your functions' results back to the
553
+ AI model. A full, working example of _ Function Calling_ using the low-level API can be seen in
554
+ [ ` FunctionCallingRawExample ` ] ( openai-java-example/src/main/java/com/openai/example/FunctionCallingRawExample.java ) .
555
+
556
+ However, for greater convenience, the SDK can derive a function and its parameters automatically
557
+ from the structure of an arbitrary Java class: the class's name provides the function name, and the
558
+ class's fields define the function's parameters. When the AI model responds with the parameter
559
+ values in JSON form, you can then easily convert that JSON to an instance of your Java class and
560
+ use the parameter values to invoke your custom function. A full, working example of the use of
561
+ _ Function Calling_ with Java classes to define function parameters can be seen in
562
+ [ ` FunctionCallingExample ` ] ( openai-java-example/src/main/java/com/openai/example/FunctionCallingExample.java ) .
563
+
564
+ Like for _ Structured Outputs_ , Java classes can contain fields declared to be instances of other
565
+ classes and can use collections. Optionally, annotations can be used to set the descriptions of the
566
+ function (class) and its parameters (fields) to assist the AI model in understanding the purpose of
567
+ the function and the possible values of its parameters.
568
+
569
+ ``` java
570
+ import com.fasterxml.jackson.annotation.JsonClassDescription ;
571
+ import com.fasterxml.jackson.annotation.JsonPropertyDescription ;
572
+
573
+ @JsonClassDescription (" Gets the quality of the given SDK." )
574
+ static class GetSdkQuality {
575
+ @JsonPropertyDescription (" The name of the SDK." )
576
+ public String name;
577
+
578
+ public SdkQuality execute () {
579
+ return new SdkQuality (
580
+ name, name. contains(" OpenAI" ) ? " It's robust and polished!" : " *shrug*" );
581
+ }
582
+ }
583
+
584
+ static class SdkQuality {
585
+ public String quality;
586
+
587
+ public SdkQuality (String name , String evaluation ) {
588
+ quality = name + " : " + evaluation;
589
+ }
590
+ }
591
+
592
+ @JsonClassDescription (" Gets the review score (out of 10) for the named SDK." )
593
+ static class GetSdkScore {
594
+ public String name;
595
+
596
+ public int execute () {
597
+ return name. contains(" OpenAI" ) ? 10 : 3 ;
598
+ }
599
+ }
600
+ ```
601
+
602
+ When your functions are defined, add them to the input parameters using ` addTool(Class<T>) ` and then
603
+ call them if requested to do so in the AI model's response. ` Function.argments(Class<T>) ` can be
604
+ used to parse a function's parameters in JSON form to an instance of your function-defining class.
605
+ The fields of that instance will be set to the values of the parameters to the function call.
606
+
607
+ After calling the function, use ` ChatCompletionToolMessageParam.Builder.contentAsJson(Object) ` to
608
+ pass the function's result back to the AI model. The method will convert the result to JSON form
609
+ for consumption by the model. The ` Object ` can be any object, including simple ` String ` instances
610
+ and boxed primitive types.
611
+
612
+ ``` java
613
+ import com.openai.client.OpenAIClient ;
614
+ import com.openai.client.okhttp.OpenAIOkHttpClient ;
615
+ import com.openai.models.ChatModel ;
616
+ import com.openai.models.chat.completions.* ;
617
+ import java.util.Collection ;
618
+
619
+ OpenAIClient client = OpenAIOkHttpClient . fromEnv();
620
+
621
+ ChatCompletionCreateParams . Builder createParamsBuilder = ChatCompletionCreateParams . builder()
622
+ .model(ChatModel . GPT_3_5_TURBO )
623
+ .maxCompletionTokens(2048 )
624
+ .addTool(GetSdkQuality . class)
625
+ .addTool(GetSdkScore . class)
626
+ .addUserMessage(" How good are the following SDKs and what do reviewers say: "
627
+ + " OpenAI Java SDK, Unknown Company SDK." );
628
+
629
+ client. chat(). completions(). create(createParamsBuilder. build()). choices(). stream()
630
+ .map(ChatCompletion . Choice :: message)
631
+ // Add each assistant message onto the builder so that we keep track of the
632
+ // conversation for asking a follow-up question later.
633
+ .peek(createParamsBuilder:: addMessage)
634
+ .flatMap(message - > {
635
+ message. content(). ifPresent(System . out:: println);
636
+ return message. toolCalls(). stream(). flatMap(Collection :: stream);
637
+ })
638
+ .forEach(toolCall - > {
639
+ Object result = callFunction(toolCall. function());
640
+ // Add the tool call result to the conversation.
641
+ createParamsBuilder. addMessage(ChatCompletionToolMessageParam . builder()
642
+ .toolCallId(toolCall. id())
643
+ .contentAsJson(result)
644
+ .build());
645
+ });
646
+
647
+ // Ask a follow-up question about the function call result.
648
+ createParamsBuilder. addUserMessage(" Why do you say that?" );
649
+ client. chat(). completions(). create(createParamsBuilder. build()). choices(). stream()
650
+ .flatMap(choice - > choice. message(). content(). stream())
651
+ .forEach(System . out:: println);
652
+
653
+ static Object callFunction(ChatCompletionMessageToolCall . Function function) {
654
+ switch (function. name()) {
655
+ case " GetSdkQuality" :
656
+ return function. arguments(GetSdkQuality . class). execute();
657
+ case " GetSdkScore" :
658
+ return function. arguments(GetSdkScore . class). execute();
659
+ default :
660
+ throw new IllegalArgumentException (" Unknown function: " + function. name());
661
+ }
662
+ }
663
+ ```
664
+
665
+ In the code above, an ` execute() ` method encapsulates each function's logic. However, there is no
666
+ requirement to follow that pattern. You are free to implement your function's logic in any way that
667
+ best suits your use case. The pattern above is only intended to _ suggest_ that a suitable pattern
668
+ may make the process of function calling simpler to understand and implement.
669
+
670
+ ### Usage with the Responses API
671
+
672
+ _ Function Calling_ is also supported for the Responses API. The usage is the same as described
673
+ except where the Responses API differs slightly from the Chat Completions API. Pass the top-level
674
+ class to ` addTool(Class<T>) ` when building the parameters. In the response, look for
675
+ [ ` RepoonseOutputItem ` ] ( openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseOutputItem.kt )
676
+ instances that are function calls. Parse the parameters to each function call to an instance of the
677
+ class using
678
+ [ ` ResponseFunctionToolCall.arguments(Class<T>) ` ] ( openai-java-core/src/main/kotlin/com/openai/models/responses/ResponseFunctionToolCall.kt ) .
679
+ Finally, pass the result of each call back to the model.
680
+
681
+ For a full example of the usage of _ Function Calling_ with the Responses API, see
682
+ [ ` ResponsesFunctionCallingExample ` ] ( openai-java-example/src/main/java/com/openai/example/ResponsesFunctionCallingExample.java ) .
683
+
684
+ ### Local function JSON schema validation
685
+
686
+ Like for _ Structured Outputs_ , you can perform local validation to check that the JSON schema
687
+ derived from your function class respects the restrictions imposed by OpenAI on such schemas. Local
688
+ validation is enabled by default, but it can be disabled by adding ` JsonSchemaLocalValidation.NO ` to
689
+ the call to ` addTool ` .
690
+
691
+ ``` java
692
+ ChatCompletionCreateParams . Builder createParamsBuilder = ChatCompletionCreateParams . builder()
693
+ .model(ChatModel . GPT_3_5_TURBO )
694
+ .maxCompletionTokens(2048 )
695
+ .addTool(GetSdkQuality . class, JsonSchemaLocalValidation . NO )
696
+ .addTool(GetSdkScore . class, JsonSchemaLocalValidation . NO )
697
+ .addUserMessage(" How good are the following SDKs and what do reviewers say: "
698
+ + " OpenAI Java SDK, Unknown Company SDK." );
699
+ ```
700
+
701
+ See [ Local JSON schema validation] ( #local-json-schema-validation ) for more details on local schema
702
+ validation and under what circumstances you might want to disable it.
703
+
704
+ ### Annotating function classes
705
+
706
+ You can use annotations to add further information about functions to the JSON schemas that are
707
+ derived from your function classes, or to exclude individual fields from the parameters to the
708
+ function. Details from annotations captured in the JSON schema may be used by the AI model to
709
+ improve its response. The SDK supports the use of
710
+ [ Jackson Databind] ( https://github.com/FasterXML/jackson-databind ) annotations.
711
+
712
+ - Use ` @JsonClassDescription ` to add a description to a function class detailing when and how to use
713
+ that function.
714
+ - Use ` @JsonTypeName ` to set the function name to something other than the simple name of the class,
715
+ which is used by default.
716
+ - Use ` @JsonPropertyDescription ` to add a detailed description to function parameter (a field of
717
+ a function class).
718
+ - Use ` @JsonIgnore ` to omit a field of a class from the generated JSON schema for a function's
719
+ parameters.
720
+
721
+ OpenAI provides some
722
+ [ Best practices for defining functions] ( https://platform.openai.com/docs/guides/function-calling#best-practices-for-defining-functions )
723
+ that may help you to understand how to use the above annotations effectively for your functions.
724
+
536
725
## File uploads
537
726
538
727
The SDK defines methods that accept files.
0 commit comments