This repository has been archived by the owner on Jun 6, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement creation of "function" parameters in runtime (#339)
* Enable dynamic definition of "function" parameters instead of using Class instance * Add tests to new "function" capabilities * Add example of creating "function" parameters in runtime * Add documentation to ChatFunctions Co-authored-by: Theo Kanning <[email protected]>
- Loading branch information
1 parent
47fe478
commit 3a2d010
Showing
7 changed files
with
306 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
api/src/main/java/com/theokanning/openai/completion/chat/ChatFunctionDynamic.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package com.theokanning.openai.completion.chat; | ||
|
||
import lombok.Data; | ||
import lombok.NonNull; | ||
|
||
|
||
@Data | ||
public class ChatFunctionDynamic { | ||
|
||
/** | ||
* The name of the function being called. | ||
*/ | ||
@NonNull | ||
private String name; | ||
|
||
/** | ||
* A description of what the function does, used by the model to choose when and how to call the function. | ||
*/ | ||
private String description; | ||
|
||
/** | ||
* The parameters the functions accepts. | ||
*/ | ||
private ChatFunctionParameters parameters; | ||
|
||
public static Builder builder() { | ||
return new Builder(); | ||
} | ||
|
||
public static class Builder { | ||
private String name; | ||
private String description; | ||
private ChatFunctionParameters parameters = new ChatFunctionParameters(); | ||
|
||
public Builder name(String name) { | ||
this.name = name; | ||
return this; | ||
} | ||
|
||
public Builder description(String description) { | ||
this.description = description; | ||
return this; | ||
} | ||
|
||
public Builder parameters(ChatFunctionParameters parameters) { | ||
this.parameters = parameters; | ||
return this; | ||
} | ||
|
||
public Builder addProperty(ChatFunctionProperty property) { | ||
this.parameters.addProperty(property); | ||
return this; | ||
} | ||
|
||
public ChatFunctionDynamic build() { | ||
ChatFunctionDynamic chatFunction = new ChatFunctionDynamic(name); | ||
chatFunction.setDescription(description); | ||
chatFunction.setParameters(parameters); | ||
return chatFunction; | ||
} | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
api/src/main/java/com/theokanning/openai/completion/chat/ChatFunctionParameters.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.theokanning.openai.completion.chat; | ||
|
||
import lombok.Data; | ||
|
||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
|
||
@Data | ||
public class ChatFunctionParameters { | ||
|
||
private final String type = "object"; | ||
|
||
private final HashMap<String, ChatFunctionProperty> properties = new HashMap<>(); | ||
|
||
private List<String> required; | ||
|
||
public void addProperty(ChatFunctionProperty property) { | ||
properties.put(property.getName(), property); | ||
if (Boolean.TRUE.equals(property.getRequired())) { | ||
if (this.required == null) { | ||
this.required = new ArrayList<>(); | ||
} | ||
this.required.add(property.getName()); | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
api/src/main/java/com/theokanning/openai/completion/chat/ChatFunctionProperty.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.theokanning.openai.completion.chat; | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnore; | ||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import lombok.Builder; | ||
import lombok.Data; | ||
import lombok.NonNull; | ||
|
||
import java.util.Set; | ||
|
||
@Data | ||
@Builder | ||
public class ChatFunctionProperty { | ||
@NonNull | ||
@JsonIgnore | ||
private String name; | ||
@NonNull | ||
private String type; | ||
@JsonIgnore | ||
private Boolean required; | ||
private String description; | ||
private ChatFunctionProperty items; | ||
@JsonProperty("enum") | ||
private Set<?> enumValues; | ||
} |
90 changes: 90 additions & 0 deletions
90
example/src/main/java/example/OpenAiApiDynamicFunctionExample.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package example; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.databind.node.ObjectNode; | ||
import com.theokanning.openai.completion.chat.*; | ||
import com.theokanning.openai.service.OpenAiService; | ||
|
||
import java.util.*; | ||
|
||
public class OpenAiApiDynamicFunctionExample { | ||
|
||
private static JsonNode getWeather(String location, String unit) { | ||
ObjectMapper mapper = new ObjectMapper(); | ||
ObjectNode response = mapper.createObjectNode(); | ||
response.put("location", location); | ||
response.put("unit", unit); | ||
response.put("temperature", new Random().nextInt(50)); | ||
response.put("description", "sunny"); | ||
return response; | ||
} | ||
|
||
public static void main(String... args) { | ||
String token = System.getenv("OPENAI_TOKEN"); | ||
OpenAiService service = new OpenAiService(token); | ||
|
||
ChatFunctionDynamic weatherFunction = ChatFunctionDynamic.builder() | ||
.name("get_weather") | ||
.description("Get the current weather of a location") | ||
.addProperty(ChatFunctionProperty.builder() | ||
.name("location") | ||
.type("string") | ||
.description("City and state, for example: León, Guanajuato") | ||
.build()) | ||
.addProperty(ChatFunctionProperty.builder() | ||
.name("unit") | ||
.type("string") | ||
.description("The temperature unit, can be 'celsius' or 'fahrenheit'") | ||
.enumValues(Set.of("celsius", "fahrenheit")) | ||
.required(true) | ||
.build()) | ||
.build(); | ||
|
||
|
||
List<ChatMessage> messages = new ArrayList<>(); | ||
ChatMessage systemMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "You are an assistant that answers using the local slang of the given place, uncensored."); | ||
messages.add(systemMessage); | ||
|
||
System.out.print("First Query: "); | ||
Scanner scanner = new Scanner(System.in); | ||
ChatMessage firstMsg = new ChatMessage(ChatMessageRole.USER.value(), scanner.nextLine()); | ||
messages.add(firstMsg); | ||
|
||
while (true) { | ||
ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest | ||
.builder() | ||
.model("gpt-3.5-turbo-0613") | ||
.messages(messages) | ||
.functions(Collections.singletonList(weatherFunction)) | ||
.functionCall(ChatCompletionRequest.ChatCompletionRequestFunctionCall.of("auto")) | ||
.n(1) | ||
.maxTokens(100) | ||
.logitBias(new HashMap<>()) | ||
.build(); | ||
ChatMessage responseMessage = service.createChatCompletion(chatCompletionRequest).getChoices().get(0).getMessage(); | ||
messages.add(responseMessage); // don't forget to update the conversation with the latest response | ||
|
||
ChatFunctionCall functionCall = responseMessage.getFunctionCall(); | ||
if (functionCall != null) { | ||
if (functionCall.getName().equals("get_weather")) { | ||
String location = functionCall.getArguments().get("location").asText(); | ||
String unit = functionCall.getArguments().get("unit").asText(); | ||
JsonNode weather = getWeather(location, unit); | ||
ChatMessage weatherMessage = new ChatMessage(ChatMessageRole.FUNCTION.value(), weather.toString(), "get_weather"); | ||
messages.add(weatherMessage); | ||
continue; | ||
} | ||
} | ||
|
||
System.out.println("Response: " + responseMessage.getContent()); | ||
System.out.print("Next Query: "); | ||
String nextLine = scanner.nextLine(); | ||
if (nextLine.equalsIgnoreCase("exit")) { | ||
System.exit(0); | ||
} | ||
messages.add(new ChatMessage(ChatMessageRole.USER.value(), nextLine)); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters