Skip to content

Add assistants #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jan 6, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
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
6 changes: 1 addition & 5 deletions .gitattributes
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf

* text eol=lf
Empty file modified .github/FUNDING.yml
100644 → 100755
Empty file.
Empty file modified .github/workflows/dokka-publish.yml
100644 → 100755
Empty file.
Empty file modified .gitignore
100644 → 100755
Empty file.
Empty file modified LICENSE
100644 → 100755
Empty file.
Empty file modified README.md
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion build.gradle.kts
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import com.github.breadmoirai.githubreleaseplugin.GithubReleaseTask

group = "com.cjcrafter"
version = "2.0.2"
version = "2.0.2-SNAPSHOT"

plugins {
`java-library`
Expand Down
2 changes: 1 addition & 1 deletion examples/build.gradle.kts
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ dependencies {
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.3")
implementation("io.github.cdimascio:dotenv-kotlin:6.4.1")

implementation("ch.qos.logback:logback-classic:1.4.11")
implementation("ch.qos.logback:logback-classic:1.4.12")

// https://mvnrepository.com/artifact/org.mariuszgromada.math/MathParser.org-mXparser
// Used for tool tests
Expand Down
117 changes: 117 additions & 0 deletions examples/src/main/java/assistant/AssistantExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package assistant;

import com.cjcrafter.openai.OpenAI;
import com.cjcrafter.openai.assistants.CreateAssistantRequest;
import com.cjcrafter.openai.assistants.ModifyAssistantRequest;
import io.github.cdimascio.dotenv.Dotenv;

import java.util.Scanner;

public class AssistantExample {

// To use dotenv, you need to add the "io.github.cdimascio:dotenv-kotlin:version"
// dependency. Then you can add a .env file in your project directory.
public static final OpenAI openai = OpenAI.builder()
.apiKey(Dotenv.load().get("OPENAI_TOKEN"))
.build();

public static final Scanner scan = new Scanner(System.in);

public static void main(String[] args) {

int input;
do {
System.out.println("1. Create");
System.out.println("2. Retrieve");
System.out.println("3. List");
System.out.println("4. Delete");
System.out.println("5. Modify");
System.out.println("6. Exit");

System.out.print("Code: ");
input = Integer.parseInt(scan.nextLine());
switch (input) {
case 1:
create();
break;
case 2:
retrieve();
break;
case 3:
list();
break;
case 4:
delete();
break;
case 5:
modify();
break;
case 6:
System.out.println("Goodbye!");
break;
default:
System.out.println("Invalid code!");
}
} while (input != 6);
}

public static void create() {
System.out.print("Model: ");
String model = scan.nextLine();
System.out.print("Name: ");
String name = scan.nextLine();
System.out.print("Description: ");
String description = scan.nextLine();
System.out.print("Instructions: ");
String instructions = scan.nextLine();

CreateAssistantRequest request = CreateAssistantRequest.builder()
.model(model)
.name(name)
.description(description)
.instructions(instructions)
.build();

System.out.println("Request: " + request);
System.out.println("Response: " + openai.getAssistants().create(request));
}

public static void retrieve() {
System.out.print("ID: ");
String id = scan.nextLine();

System.out.println("Response: " + openai.getAssistants().retrieve(id));
}

public static void list() {
System.out.println("Response: " + openai.getAssistants().list());
}

public static void delete() {
System.out.print("ID: ");
String id = scan.nextLine();

System.out.println("Response: " + openai.getAssistants().delete(id));
}


public static void modify() {
System.out.print("ID: ");
String id = scan.nextLine();
System.out.print("Name: ");
String name = scan.nextLine();
System.out.print("Description: ");
String description = scan.nextLine();
System.out.print("Instructions: ");
String instructions = scan.nextLine();

ModifyAssistantRequest request = ModifyAssistantRequest.builder()
.name(name)
.description(description)
.instructions(instructions)
.build();

System.out.println("Request: " + request);
System.out.println("Response: " + openai.getAssistants().modify(id, request));
}
}
87 changes: 87 additions & 0 deletions examples/src/main/java/assistant/ThreadExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package assistant;

import com.cjcrafter.openai.OpenAI;
import com.cjcrafter.openai.assistants.Assistant;
import com.cjcrafter.openai.assistants.ListAssistantResponse;
import com.cjcrafter.openai.threads.Thread;
import com.cjcrafter.openai.threads.message.*;
import com.cjcrafter.openai.threads.runs.CreateRunRequest;
import com.cjcrafter.openai.threads.runs.MessageCreationDetails;
import com.cjcrafter.openai.threads.runs.Run;
import com.cjcrafter.openai.threads.runs.RunStep;
import io.github.cdimascio.dotenv.Dotenv;

import java.util.Scanner;

public class ThreadExample {

public static void main(String[] args) throws InterruptedException {
// To use dotenv, you need to add the "io.github.cdimascio:dotenv-kotlin:version"
// dependency. Then you can add a .env file in your project directory.
OpenAI openai = OpenAI.builder()
.apiKey(Dotenv.load().get("OPENAI_TOKEN"))
.build();

// Ask the user to choose an assistant
ListAssistantResponse assistants = openai.assistants().list();
for (int i = 0; i < assistants.getData().size(); i++) {
Assistant assistant = assistants.getData().get(i);
System.out.println(i + ". " + assistant);
}

Scanner scan = new Scanner(System.in);
int choice = Integer.parseInt(scan.nextLine());
Assistant assistant = assistants.getData().get(choice);

// We have to create a new thread. We'll save this thread, so we can
// add user messages and get responses later.
Thread thread = openai.threads().create();

while (true) {

// Handle user input
System.out.println("Type your input below: ");
String input = scan.nextLine();
openai.threads().messages(thread).create(CreateThreadMessageRequest.builder()
.role(ThreadUser.USER)
.content(input)
.build());

// After adding a message to the thread, we have to "run" the thread
Run run = openai.threads().runs(thread).create(CreateRunRequest.builder()
.assistant(assistant)
.build());

// This is a known limitation in OpenAI, and they are working to
// address this so that we can easily stream a response without
// nonsense like this.
while (!run.getStatus().isTerminal()) {
java.lang.Thread.sleep(1000);
run = openai.threads().runs(thread).retrieve(run);
}

// Once the run stops, we want to retrieve the steps of the run.
// this includes message outputs, function calls, code
// interpreters, etc.
for (RunStep step : openai.threads().runs(thread).steps(run).list().getData()) {
if (step.getType() != RunStep.Type.MESSAGE_CREATION) {
System.out.println("Assistant made step: " + step.getType());
continue;
}

// This cast is safe since we checked the type above
MessageCreationDetails details = (MessageCreationDetails) step.getStepDetails();
ThreadMessage message = openai.threads().messages(thread).retrieve(details.getMessageCreation().getMessageId());
for (ThreadMessageContent content : message.getContent()) {
if (content.getType() != ThreadMessageContent.Type.TEXT) {
System.err.println("Unhandled message content type: " + content.getType());
System.err.println("This will never occur since this Assistant doesn't use images.");
System.exit(-1);
}

System.out.println(((TextContent) content).getText().getValue());
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package chat;

import com.cjcrafter.openai.Models;
import com.cjcrafter.openai.OpenAI;
import com.cjcrafter.openai.chat.ChatMessage;
import com.cjcrafter.openai.chat.ChatRequest;
Expand All @@ -13,7 +14,7 @@
/**
* In this Java example, we will be using the Chat API to create a simple chatbot.
*/
public class ChatCompletion {
public class ChatCompletionExample {

public static void main(String[] args) {

Expand All @@ -29,7 +30,7 @@ public static void main(String[] args) {

// Here you can change the model's settings, add tools, and more.
ChatRequest request = ChatRequest.builder()
.model("gpt-3.5-turbo")
.model(Models.Chat.GPT_3_5_TURBO)
.messages(messages)
.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* Instead of waiting for the full response to generate, we will "stream" tokens
* 1 by 1 as they are generated.
*/
public class StreamChatCompletion {
public class StreamChatCompletionExample {

public static void main(String[] args) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* 1 by 1 as they are generated. We will also add a Math tool so that the chatbot
* can solve math problems with a math parser.
*/
public class StreamChatCompletionFunction {
public class StreamChatCompletionFunctionExample {

public static void main(String[] args) {

Expand All @@ -46,7 +46,7 @@ public static void main(String[] args) {
ChatRequest request = ChatRequest.builder()
.model("gpt-3.5-turbo")
.messages(messages)
.addTool(FunctionTool.builder()
.addTool(Function.builder()
.name("solve_math_problem")
.description("Returns the result of a math problem as a double")
.addStringParameter("equation", "The math problem for you to solve", true)
Expand Down Expand Up @@ -98,10 +98,10 @@ public static ChatMessage handleToolCall(ToolCall call, List<Tool> validTools) {
// at tool calls (And you probably aren't very good at prompt
// engineering yet!). OpenAI will often "Hallucinate" arguments.
try {
if (call.getType() != ToolType.FUNCTION)
if (call.getType() != Tool.Type.FUNCTION)
throw new HallucinationException("Unknown tool call type: " + call.getType());

FunctionCall function = call.getFunction();
FunctionCall function = ((FunctionToolCall) call).getFunction();
Map<String, JsonNode> arguments = function.tryParseArguments(validTools); // You can pass null here for less strict parsing
String equation = arguments.get("equation").asText();
double result = solveEquation(equation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* In this Java example, we will be using the Legacy Completion API to generate
* a response.
*/
public class Completion {
public class CompletionExample {

public static void main(String[] args) {

Expand Down
Loading