OpenAI Function Call Java Example

From the project: https://github.com/HamaWhiteGG/langchain-java

Please refer to the ChatFunctionTest for the complete test code.

1. Core main process

  • Generates a ChatParameter instance that represents the given class.
  • Invoke the OpenAI API and return the function name and parameters.
  • Execute functions through the FunctionExecutor.

2. Step-by-step introduction

2.1 Declare function parameters and response

java 复制代码
public record Weather(
        @JsonProperty(required = true)
        @JsonPropertyDescription("The city and state, e.g. San Francisco, CA")
        String location,

        @JsonPropertyDescription("The temperature unit")
        WeatherUnit unit
) {}


public enum WeatherUnit {

    CELSIUS,
    FAHRENHEIT
}


@Data
@Builder
public class WeatherResponse {

    public String location;

    public WeatherUnit unit;

    public int temperature;

    public String description;
}


WeatherResponse getCurrentWeather(Weather weather) {
    // mock function
    return WeatherResponse.builder()
            .location(weather.location())
            .unit(weather.unit())
            .temperature(new Random().nextInt(50))
            .description("sunny")
            .build();
}

2.2 Generates a ChatParameter instance that represents the given class

Automatically convert Weather.class to ChatParameter using the ChatParameterUtils.generate method.

java 复制代码
ChatFunction.ChatParameter chatParameter = ChatParameterUtils.generate(Weather.class);

The output of converting chatParameter to JSON String is as follows:

json 复制代码
{
    "type" : "object",
    "properties" : {
        "location" : {
            "type" : "string",
            "description" : "The city and state, e.g. San Francisco, CA"
        },
        "unit" : {
            "type" : "string",
            "description" : "The temperature unit",
            "enum" : [
                "celsius",
                "fahrenheit"
            ]
        }
    },
    "required" : [
        "location"
    ]
}

2.3 Invoke the OpenAI API and return the function name and parameters.

java 复制代码
ChatFunction chatFunction = ChatFunction.builder()
        .name(functionName)
        .description("Get the current weather in a given location")
        .parameters(ChatParameterUtils.generate(Weather.class))
        .build();

Message message = Message.of("What is the weather like in Boston?");

ChatCompletion chatCompletion = ChatCompletion.builder()
        .model("gpt-4")
        .temperature(0)
        .messages(List.of(message))
        .tools(List.of(new Tool(chatFunction)))
        .toolChoice("auto")
        .build();

ChatCompletionResp response = client.createChatCompletion(chatCompletion);
ChatChoice chatChoice = response.getChoices().get(0);

The output of converting chatChoice to JSON String is as follows:

json 复制代码
{
    "index":0,
    "message":{
        "role":"assistant",
        "content":null,
        "tool_calls":[
            {
                "id":"call_aS4LspVVBkE8uIiBSLZWXe6O",
                "type":"function",
                "function":{
                    "name":"get_current_weather",
                    "arguments":"{\n  \"location\": \"Boston, MA\"\n}"
                }
            }
        ]
    },
    "finish_reason":"tool_calls"
}

2.4 Execute functions through the FunctionExecutor.

The code for FunctionExecutor is as follows, allowing the caller to avoid explicit type casting through generics, making the code more concise and elegant.

java 复制代码
public class FunctionExecutor {

    private static final Map<String, Function<?, ?>> FUNCTION_MAP = new HashMap<>(16);

    public static <T> void register(String functionName, Function<T, ?> function) {
        FUNCTION_MAP.put(functionName, function);
    }

    @SuppressWarnings("unchecked")
    public static <T, R> R execute(String functionName, Class<T> clazz, String arguments) throws ClassCastException {
        Function<T, R> function = (Function<T, R>) FUNCTION_MAP.get(functionName);
        if (function == null) {
            throw new IllegalArgumentException("No function registered with name: " + functionName);
        }
        T input = convertFromJsonStr(arguments, clazz);
        return function.apply(input);
    }
}

The caller's code is as follows:

java 复制代码
Function function = chatChoice.getMessage().getToolCalls().get(0).getFunction();

// execute function
WeatherResponse weatherResponse = FunctionExecutor.execute(function.getName(), Weather.class, function.getArguments());
System.out.println(weatherResponse)

The final result is:

shell 复制代码
WeatherResponse(location=Boston, MA, unit=null, temperature=2, description=sunny)
相关推荐
有来技术2 分钟前
从0到1手撸企业级权限系统:基于 youlai-boot(开源) + Java17 + Spring Boot 3 完整实战
java·spring boot·后端
皮卡兔子屋8 分钟前
java虚拟机---JVM
java·jvm
艾妮艾妮27 分钟前
C语言常见3种排序
java·c语言·开发语言·c++·算法·c#·排序算法
java技术小馆28 分钟前
Zookeeper中的Zxid是如何设计的
java·分布式·zookeeper·云原生
葵野寺37 分钟前
【多线程】synchronized锁升级和优化
java·开发语言·java-ee
SimonKing1 小时前
因为不知道条件注解@Conditional,错失15K的Offer!
java·后端·架构
橘猫云计算机设计1 小时前
基于springboot微信小程序的旅游攻略系统(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·微信小程序·毕业设计·旅游
落榜程序员1 小时前
Java 基础-30-单例设计模式:懒汉式与饿汉式
java·开发语言
顾林海1 小时前
深度解析ArrayList工作原理
android·java·面试