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)
相关推荐
customer084 分钟前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
全栈开发圈6 分钟前
新书速览|Java网络爬虫精解与实践
java·开发语言·爬虫
WaaTong9 分钟前
《重学Java设计模式》之 单例模式
java·单例模式·设计模式
面试鸭11 分钟前
离谱!买个人信息买到网安公司头上???
java·开发语言·职场和发展
沈询-阿里1 小时前
java-智能识别车牌号_基于spring ai和开源国产大模型_qwen vl
java·开发语言
AaVictory.1 小时前
Android 开发 Java中 list实现 按照时间格式 yyyy-MM-dd HH:mm 顺序
android·java·list
LuckyLay1 小时前
Spring学习笔记_27——@EnableLoadTimeWeaving
java·spring boot·spring
向阳12182 小时前
Dubbo负载均衡
java·运维·负载均衡·dubbo
Gu Gu Study2 小时前
【用Java学习数据结构系列】泛型上界与通配符上界
java·开发语言