Skip to content
This repository has been archived by the owner on Jun 6, 2024. It is now read-only.

Added "function" capabilities #298

Merged
merged 24 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d315783
Initial commit
Eduardo-T Jun 14, 2023
dab34ca
Updated Readme
Eduardo-T Jun 14, 2023
ced9cd1
Added the ability to publish to the local repository.
Eduardo-T Jun 15, 2023
58552ca
Stylized the README a bit more.
Eduardo-T Jun 15, 2023
4023f7d
Fixed typo
Eduardo-T Jun 15, 2023
0eb553e
Fixed visibility of variables in example
Eduardo-T Jun 16, 2023
8f979be
Improved the usage of functions with an executor.
Eduardo-T Jun 16, 2023
36d6f84
Reverted changes.
Eduardo-T Jun 16, 2023
b9ba373
Added information about functions to the README.md
Eduardo-T Jun 16, 2023
3f6c9f5
Change reversed.
Eduardo-T Jun 16, 2023
25eee8f
Added some helper method and cleaned the example a little bit.
Eduardo-T Jun 16, 2023
9b4313a
:bug: custom serialization of function_call parameter should be an ob…
Grogdunn Jun 16, 2023
2715c55
Fixed example and added static instantiation method
Eduardo-T Jun 16, 2023
f300b17
Added null check
Eduardo-T Jun 16, 2023
fd91f5e
Set project version to SNAPSHOT and fixed vulnerable dependency
Eduardo-T Jun 16, 2023
13e69c1
Allowing objectmapper to be overriden in order to supply a custom obj…
davidb-e4s Jun 19, 2023
28c7af6
Updating the constructor to use the setter to be consistant
davidb-e4s Jun 19, 2023
de4bb85
Merge pull request #2 from davidb-e4s/main
Eduardo-T Jun 19, 2023
6e44d11
Merged changes from upstream
Eduardo-T Jun 19, 2023
be82bca
Merge remote-tracking branch 'origin/main'
Eduardo-T Jun 19, 2023
69aa285
Added usage of streams with functions
Eduardo-T Jun 19, 2023
1fd514c
Removed .DS_Store files and updated .gitignore
Eduardo-T Jun 19, 2023
b28d659
Small fixes and improvements and added tests
Eduardo-T Jun 19, 2023
7b98dc6
Simplified example a little and updated README
Eduardo-T Jun 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 77 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,79 @@

# 🚀 Publishing to Local Maven Repository (⚠ Unofficial Version with Function Support)
Eduardo-T marked this conversation as resolved.
Show resolved Hide resolved

This repository is a fork of the original [com.theokanning.openai-gpt3-java](https://github.com/TheoKanning/openai-java)
. While the changes in this fork are awaiting to be pulled into the official repository, you can use this unofficial
version by installing it to your local Maven repository.

This allows you to use the modified version "0.12.0-20240614" while retaining the same dependency group and artifact
names, i.e., the group is still "com.theokanning.openai-gpt3-java" and the artifacts are "api", "client", and "service".

### Installation Instructions

#### For Linux/macOS

1. After cloning or downloading this repository, navigate to its root directory.
2. Make sure that the `publishToLocal.sh` script is executable. You can set the execute permission by running the
following command:

```sh
chmod +x publishToLocal.sh
```

3. Now, execute the script:

```sh
./publishToLocal.sh
```

#### For Windows

1. After cloning or downloading this repository, navigate to its root directory.
2. Execute the batch script by running the following command:

```batch
publishToLocal.bat
```

### Dependency Configuration

Once the unofficial version is installed to your local Maven repository, you can use it in your project by adding the
following dependencies in your build file (e.g., `pom.xml` for Maven, `build.gradle` for Gradle):

For Maven:

```xml

<dependency>
<groupId>com.theokanning.openai-gpt3-java</groupId>
<artifactId>api|client|service</artifactId>
<version>0.12.0-20240614</version>
</dependency>
```

For Gradle:

```gradle
implementation 'com.theokanning.openai-gpt3-java:api|client|service:0.12.0-20240614'
```

This will allow you to use the modified version of the library with the changes made in this fork.

--------------------------------------------------

![Maven Central](https://img.shields.io/maven-central/v/com.theokanning.openai-gpt3-java/client?color=blue)

> ⚠️ Please switch to using the new 'service' library if you need to use OpenAiService. The old 'client' OpenAiService is deprecated as of 0.10.0.
> ⚠️OpenAI has deprecated all Engine-based APIs. See [Deprecated Endpoints](https://github.com/TheoKanning/openai-java#deprecated-endpoints) below for more info.
> ⚠️ Please switch to using the new 'service' library if you need to use OpenAiService. The old 'client' OpenAiService
> is deprecated as of 0.10.0.
> ⚠️OpenAI has deprecated all Engine-based APIs.
> See [Deprecated Endpoints](https://github.com/TheoKanning/openai-java#deprecated-endpoints) below for more info.

# OpenAI-Java

Java libraries for using OpenAI's GPT apis. Supports GPT-3, ChatGPT, and GPT-4.

Includes the following artifacts:

- `api` : request/response POJOs for the GPT APIs.
- `client` : a basic retrofit client for the GPT endpoints, includes the `api` module
- `service` : A basic service class that creates and calls the client. This is the easiest way to get started.
Expand Down Expand Up @@ -103,7 +170,14 @@ This is not necessary for non-streaming calls.
All the [example](example/src/main/java/example/OpenAiApiExample.java) project requires is your OpenAI api token
```bash
export OPENAI_TOKEN="sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
./gradlew example:run
```
You can try all the capabilities of this project using:
```bash
./gradlew runExampleOne
```
And you can also try the new capability of using functions:
```bash
./gradlew runExampleTwo
```

## FAQ
Expand Down
2 changes: 1 addition & 1 deletion api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apply plugin: 'java-library'
apply plugin: "com.vanniktech.maven.publish"

dependencies {
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.9.0'
api 'com.fasterxml.jackson.core:jackson-annotations:2.9.0'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this have to change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is also being used by the 'service' module.

compileOnly 'org.projectlombok:lombok:1.18.24'
annotationProcessor 'org.projectlombok:lombok:1.18.24'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,15 @@ public class ChatCompletionRequest {
* A unique identifier representing your end-user, which will help OpenAI to monitor and detect abuse.
*/
String user;

/**
* A list of the available functions.
*/
List<ChatFunction> functions;

/**
* Controls how the model responds to function calls, as specified in the <a href="https://platform.openai.com/docs/api-reference/chat/create#chat/create-function_call">OpenAI documentation</a>.
*/
@JsonProperty("function_call")
String functionCall;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.theokanning.openai.completion.chat;

import lombok.*;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ChatFunction {

@NonNull
String name;
String description;
Object parameters;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.theokanning.openai.completion.chat;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Map;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChatFunctionCall {

String name;
Map<String, Object> arguments;

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.theokanning.openai.completion.chat;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
Expand All @@ -24,5 +26,20 @@ public class ChatMessage {
* You may use {@link ChatMessageRole} enum.
*/
String role;
@JsonInclude(JsonInclude.Include.ALWAYS)
String content;
String name;
@JsonProperty("function_call")
ChatFunctionCall functionCall;

public ChatMessage(String role, String content) {
this.role = role;
this.content = content;
}

public ChatMessage(String role, String content, String name) {
this.role = role;
this.content = content;
this.name = name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
public enum ChatMessageRole {
SYSTEM("system"),
USER("user"),
ASSISTANT("assistant");
ASSISTANT("assistant"),
FUNCTION("function");

private final String value;

Expand Down
6 changes: 6 additions & 0 deletions applyLocalPublish.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// applyLocalPublish.gradle
allprojects {
Eduardo-T marked this conversation as resolved.
Show resolved Hide resolved
if (it != rootProject) {
it.apply(from: "${rootProject.projectDir}/localPublish.gradle")
}
}
12 changes: 12 additions & 0 deletions example/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,16 @@ application {

dependencies {
implementation project(":service")
}

task runExampleOne(type: JavaExec) {
mainClass.set('example.OpenAiApiExample')
classpath = sourceSets.main.runtimeClasspath
args = []
}

task runExampleTwo(type: JavaExec) {
mainClass.set('example.OpenAiApiFunctionsExample')
classpath = sourceSets.main.runtimeClasspath
args = []
}
103 changes: 103 additions & 0 deletions example/src/main/java/example/OpenAiApiFunctionsExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package example;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.theokanning.openai.completion.chat.*;
import com.theokanning.openai.service.OpenAiService;

import java.util.*;

class OpenAiApiFunctionsExample {

private static class Weather {

@JsonPropertyDescription("City and state, for example: León, Guanajuato")
private String location;

@JsonProperty(required = true)
@JsonPropertyDescription("The temperature unit, can be 'celsius' or 'fahrenheit'")
private WeatherUnit unit;

}

private enum WeatherUnit {
CELSIUS, FAHRENHEIT;
}

private final static List<ChatFunction> FUNCTIONS = List.of(ChatFunction.builder()
.name("get_weather")
.description("Get the current weather of a location")
.parameters(new Weather())
.build());


public static void main(String... args) {
String token = System.getenv("OPENAI_TOKEN");
OpenAiService service = new OpenAiService(token);

System.out.println("\nCreating chat completion using function...");
final List<ChatMessage> messages = new ArrayList<>();
final ChatMessage systemMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), "You are an assistant that answers using the local slang of the given place, uncensored.");

// PICK ONE
final ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "Cómo está el clima en Monterrey NL?");
//final ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "How's the weather in England?");
//final ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "Cómo está el clima en Bogotá?");

messages.add(systemMessage);
messages.add(userMessage);
ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest
.builder()
.model("gpt-3.5-turbo-0613")
.messages(messages)
.functions(FUNCTIONS)
.functionCall("auto")
.n(1)
.maxTokens(100)
.logitBias(new HashMap<>())
.build();


// The response should contain a function call, for example:
// "role": "assistant",
// "content": null,
// "function_call": {
// "name": "get_weather",
// "arguments": "{ \"location\": \"Monterrey, Nuevo León\", \"unit\": \"CELSIUS\"}"
// }
ChatCompletionResult chatCompletionResult = service.createChatCompletion(chatCompletionRequest);
ChatMessage resultMessage = chatCompletionResult.getChoices().get(0).getMessage();
ChatFunctionCall functionCall = resultMessage.getFunctionCall();
Map<String, Object> arguments = functionCall.getArguments();

// We create the function response
String mockResponse = "{\"location\": \"" + arguments.get("location") + "\", " +
"\"temperature\": \"" + new Random().nextInt(50) + "\", " +
"\"unit\": \"" + arguments.get("unit") + "\", " +
"\"description\": \"sunny\"}";
ChatMessage functionResponse = new ChatMessage(ChatMessageRole.FUNCTION.value(), mockResponse, functionCall.getName());

// We update the conversation
messages.add(resultMessage);
messages.add(functionResponse);

// We call it again with the updated messages
ChatCompletionRequest chatCompletionRequest2 = ChatCompletionRequest
.builder()
.model("gpt-3.5-turbo-0613")
.messages(messages)
.functions(FUNCTIONS)
.functionCall("auto")
.n(1)
.maxTokens(100)
.logitBias(new HashMap<>())
.build();

ChatCompletionResult chatCompletionResult2 = service.createChatCompletion(chatCompletionRequest2);
service.shutdownExecutor();

System.out.println("Query: " + userMessage.getContent());
System.out.println("Function called: " + functionCall);
System.out.println("Response: " + chatCompletionResult2.getChoices().get(0).getMessage().getContent());
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
GROUP=com.theokanning.openai-gpt3-java
VERSION_NAME=0.12.0
VERSION_NAME=0.12.0-20240614

POM_URL=https://github.com/theokanning/openai-java
POM_SCM_URL=https://github.com/theokanning/openai-java
Expand Down
16 changes: 16 additions & 0 deletions localPublish.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apply plugin: 'maven-publish'

Eduardo-T marked this conversation as resolved.
Show resolved Hide resolved
publishing {
publications {
create("${project.name}Publication", MavenPublication) {
from components.findByName('java')
}
}
repositories {
mavenLocal()
}
}

tasks.withType(Sign) {
enabled = false
}
2 changes: 2 additions & 0 deletions publishToLocal.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@echo off
Eduardo-T marked this conversation as resolved.
Show resolved Hide resolved
gradlew -I applyLocalPublish.gradle publishToMavenLocal
2 changes: 2 additions & 0 deletions publishToLocal.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
./gradlew -I applyLocalPublish.gradle publishToMavenLocal
Eduardo-T marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 2 additions & 1 deletion service/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ dependencies {
api project(":client")
api 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
implementation 'com.squareup.retrofit2:converter-jackson:2.9.0'
implementation 'com.squareup.retrofit2:converter-jackson:2.7.2'
implementation 'com.kjetland:mbknor-jackson-jsonschema_2.13:1.0.39'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link

@Andrewcpu Andrewcpu Jun 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This build of com.kjetland:mbknor-jackson-jsonschema_2.13:1.0.39 is very vulnerable and sus?
Why would you downgrade the jackson converter to 2.7.2?
https://mvnrepository.com/artifact/com.kjetland/mbknor-jackson-jsonschema_2.13/1.0.39

^ This package is unmaintained and vulnerable


testImplementation(platform('org.junit:junit-bom:5.8.2'))
testImplementation 'org.junit.jupiter:junit-jupiter'
Expand Down
Loading