|
| 1 | +package assistant; |
| 2 | + |
| 3 | +import com.cjcrafter.openai.OpenAI; |
| 4 | +import com.cjcrafter.openai.assistants.Assistant; |
| 5 | +import com.cjcrafter.openai.assistants.ListAssistantResponse; |
| 6 | +import com.cjcrafter.openai.threads.Thread; |
| 7 | +import com.cjcrafter.openai.threads.message.*; |
| 8 | +import com.cjcrafter.openai.threads.runs.CreateRunRequest; |
| 9 | +import com.cjcrafter.openai.threads.runs.MessageCreationDetails; |
| 10 | +import com.cjcrafter.openai.threads.runs.Run; |
| 11 | +import com.cjcrafter.openai.threads.runs.RunStep; |
| 12 | +import io.github.cdimascio.dotenv.Dotenv; |
| 13 | + |
| 14 | +import java.util.Scanner; |
| 15 | + |
| 16 | +public class ThreadExample { |
| 17 | + |
| 18 | + public static void main(String[] args) throws InterruptedException { |
| 19 | + // To use dotenv, you need to add the "io.github.cdimascio:dotenv-kotlin:version" |
| 20 | + // dependency. Then you can add a .env file in your project directory. |
| 21 | + OpenAI openai = OpenAI.builder() |
| 22 | + .apiKey(Dotenv.load().get("OPENAI_TOKEN")) |
| 23 | + .build(); |
| 24 | + |
| 25 | + // Ask the user to choose an assistant |
| 26 | + ListAssistantResponse assistants = openai.assistants().list(); |
| 27 | + for (int i = 0; i < assistants.getData().size(); i++) { |
| 28 | + Assistant assistant = assistants.getData().get(i); |
| 29 | + System.out.println(i + ". " + assistant); |
| 30 | + } |
| 31 | + |
| 32 | + Scanner scan = new Scanner(System.in); |
| 33 | + int choice = Integer.parseInt(scan.nextLine()); |
| 34 | + Assistant assistant = assistants.getData().get(choice); |
| 35 | + |
| 36 | + // We have to create a new thread. We'll save this thread, so we can |
| 37 | + // add user messages and get responses later. |
| 38 | + Thread thread = openai.threads().create(); |
| 39 | + |
| 40 | + while (true) { |
| 41 | + |
| 42 | + // Handle user input |
| 43 | + System.out.println("Type your input below: "); |
| 44 | + String input = scan.nextLine(); |
| 45 | + openai.threads().messages(thread).create(CreateThreadMessageRequest.builder() |
| 46 | + .role(ThreadUser.USER) |
| 47 | + .content(input) |
| 48 | + .build()); |
| 49 | + |
| 50 | + // After adding a message to the thread, we have to "run" the thread |
| 51 | + Run run = openai.threads().runs(thread).create(CreateRunRequest.builder() |
| 52 | + .assistant(assistant) |
| 53 | + .build()); |
| 54 | + |
| 55 | + // This is a known limitation in OpenAI, and they are working to |
| 56 | + // address this so that we can easily stream a response without |
| 57 | + // nonsense like this. |
| 58 | + while (!run.getStatus().isTerminal()) { |
| 59 | + java.lang.Thread.sleep(1000); |
| 60 | + run = openai.threads().runs(thread).retrieve(run); |
| 61 | + } |
| 62 | + |
| 63 | + // Once the run stops, we want to retrieve the steps of the run. |
| 64 | + // this includes message outputs, function calls, code |
| 65 | + // interpreters, etc. |
| 66 | + for (RunStep step : openai.threads().runs(thread).steps(run).list().getData()) { |
| 67 | + if (step.getType() != RunStep.Type.MESSAGE_CREATION) { |
| 68 | + System.out.println("Assistant made step: " + step.getType()); |
| 69 | + continue; |
| 70 | + } |
| 71 | + |
| 72 | + // This cast is safe since we checked the type above |
| 73 | + MessageCreationDetails details = (MessageCreationDetails) step.getStepDetails(); |
| 74 | + ThreadMessage message = openai.threads().messages(thread).retrieve(details.getMessageCreation().getMessageId()); |
| 75 | + for (ThreadMessageContent content : message.getContent()) { |
| 76 | + if (content.getType() != ThreadMessageContent.Type.TEXT) { |
| 77 | + System.err.println("Unhandled message content type: " + content.getType()); |
| 78 | + System.err.println("This will never occur since this Assistant doesn't use images."); |
| 79 | + System.exit(-1); |
| 80 | + } |
| 81 | + |
| 82 | + System.out.println(((TextContent) content).getText().getValue()); |
| 83 | + } |
| 84 | + } |
| 85 | + } |
| 86 | + } |
| 87 | +} |
0 commit comments