javaboiii의 Web

API - OpenAi Assistant API (feat.JAVA) - 사용하기

javaboiii 2024. 11. 6. 11:19

WEB

생성한 Assistant 사용하기

현재 Assistant API는 베타버전이기 때문에

요청 시 헤더에 "OpenAI-Beta : assistant=v2" 를 붙여줘야됨

 

1. Assistant 생성

2. Thread 생성 

 

// 스레드 생성 요청
public static SimSimeDTO getThread(SimSimeDTO simsimeDTO, JSONParser parser) {
    System.out.println("KosimeFunction.java getThread() 시작");
    HttpClient client = HttpClient.newHttpClient();

    // 스레드 생성 요청 본문 (assistant ID 포함)
    String threadRequestBody = "{}";
    String getThreadUrl = API_URL+"threads";
    // 스레드 생성 요청
    HttpRequest threadRequest = HttpRequest.newBuilder()
            .uri(URI.create(getThreadUrl))
            .header("Authorization", "Bearer " + API_KEY)
            .header("Content-Type", "application/json")
            .header("OpenAI-Beta", "assistants=v2")  // 베타 헤더 추가
            .POST(HttpRequest.BodyPublishers.ofString(threadRequestBody))
            .build();

    String thread_id = "";
    try {
        HttpResponse<String> threadResponse = client.send(threadRequest, HttpResponse.BodyHandlers.ofString());
        System.out.println("스레드 생성 응답: " + threadResponse.body());

        // JSON 파싱을 통해 thread_id 추출
        JSONObject jsonObject = (JSONObject) parser.parse(threadResponse.body());
        thread_id = (String)jsonObject.get("id");
        simsimeDTO.setThread_id(thread_id);


        // 추출한 thread_id로 대화 요청
        //sendMessage(client, threadId);

        // 응답에서 thread_id 추출
        //String threadId = threadResponse.body(); // 응답 JSON에서 thread_id 추출
    } catch (IOException | InterruptedException e) {
        System.err.println("getThread 응답: " + e.getMessage());
        e.printStackTrace();
    } catch (ParseException e) {
        System.out.println("JSON 파싱 오류");
        e.printStackTrace();
    }
    System.out.println("KosimeFunction.java getThread() 끝");
    return simsimeDTO;
}

 

thread 요청 시 thread_id를 응답해줌

 

3. Thread에 Message 추가  - 응답받은 thread_id를 이용해 해당 thread에 사용자 메세지를 추가

 

// 스레드에 사용자 메세지 set 요청
public static void setMessage(SimSimeDTO simsimeDTO, JSONParser parser) {
    System.out.println("KosimeFunction.java setMessage() 시작");
    HttpClient client = HttpClient.newHttpClient();
    // Step 2: 스레드에 메시지 담기
    String messageUrl = API_URL + "threads/" + simsimeDTO.getThread_id()+ "/messages";
    String messageRequestBody = String.format(
            "{\"role\": \"user\", \"content\": \"%s\"}",
            simsimeDTO.getUserMessage()
    );
    HttpRequest messageRequest = HttpRequest.newBuilder()
            .uri(URI.create(messageUrl))  // URI.create()로 URI 생성
            .header("Authorization", "Bearer " + API_KEY)
            .header("Content-Type", "application/json")
            .header("OpenAI-Beta", "assistants=v2")
            .POST(BodyPublishers.ofString(messageRequestBody, StandardCharsets.UTF_8))
            .build();

    HttpResponse<String> messageResponse = null;
    try {
        messageResponse = client.send(messageRequest, HttpResponse.BodyHandlers.ofString());
    } catch (IOException | InterruptedException e) {
        System.out.println("스레드 set message 중 오류 발생");
        e.printStackTrace();
    }
    System.out.println("setMessage 응답: " + messageResponse.body());

    System.out.println("KosimeFunction.java setMessage() 끝");
}

 

4. 해당 Thread에서 assistant 실행(Run) - thread_id를 이용해서 해당 스레드를 실행

 

// 스레드 실행 요청
public static SimSimeDTO runThread(SimSimeDTO simsimeDTO, JSONParser parser) {
    System.out.println("KosimeFunction.java runThread() 시작");
    HttpClient client = HttpClient.newHttpClient();


    String runUrl = API_URL + "threads/" + simsimeDTO.getThread_id() + "/runs";
    String runRequestBody = String.format(
            "{\"assistant_id\": \"%s\"}",
            ASSISTANT_ID
    );

    HttpRequest runRequest = HttpRequest.newBuilder()
            .uri(URI.create(runUrl))  // URI.create()로 URI 생성
            .header("Authorization", "Bearer " + API_KEY)
            .header("Content-Type", "application/json")
            .header("OpenAI-Beta", "assistants=v2")
            .POST(BodyPublishers.ofString(runRequestBody, StandardCharsets.UTF_8))
            .build();

    HttpResponse<String> runResponse = null;
    try {
        runResponse = client.send(runRequest, BodyHandlers.ofString());
    } catch (IOException | InterruptedException e) {
        System.out.println("스레드 실행 중 오류 발생");
        e.printStackTrace();
    }
    System.out.println("runThread 응답: " + runResponse.body());

    JSONObject jsonObject;

    try {
        jsonObject = (JSONObject) parser.parse(runResponse.body());
        String status = (String)jsonObject.get("status");
        simsimeDTO.setStatus(status);
    } catch (ParseException e) {
        System.out.println("JSON 파싱 오류");
        e.printStackTrace();
    }
    System.out.println("Status: " + simsimeDTO.getStatus());

    System.out.println("KosimeFunction.java runThread() 끝");
    return simsimeDTO;
}

스레드 실행 요청 시

스레드 응답 상태를 반환함

상태 목록
queued 아직 실행이 되지  않고 대기중인 상태
in_progress 처리중
requires_action 사용자 입력 대기중
cancelling 작업 취소중
cancelled 작업 취소 완료
failed 실패(오류)
completed 작업 완료
expired 작업 만료

베타버전 이기 때문에 응답이 느리다는 이야기를 구글링중 보게됨

while (simsimeDTO != null && (simsimeDTO.getStatus().equals("queued") || simsimeDTO.getStatus().equals("in_progress"))) {
    System.out.println("while문 들어옴");
    // 응답 상태 및 응답을 확인하기 위해 5초 대기 후 요청
    try {
        System.out.println("thread.sleep 시작");
        Thread.sleep(5000); // 5초 대기
        System.out.println("thread.sleep 끝");
    } catch (InterruptedException e) {
        System.out.println("thread.sleep 실패");
        e.printStackTrace();
    }

    simsimeDTO.setThread_id(threadId); // 스레드 id set
    // assistant 응답 요청
    simsimeDTO = KosimeFunction.getMessage(simsimeDTO, parser);

    // 응답 상태가 completed이면 반복문 종료
    if(simsimeDTO.getStatus().equals("completed")) {
        break;
    }
}

 

응답 상태가 completed가 아니면

대기중이거나 처리중이라면

assistant 메세지를 5초에 한번씩 확인함

 

5. assistan 응답 메세지 확인

// assistant 응답 get 요청
public static SimSimeDTO getMessage(SimSimeDTO simsimeDTO, JSONParser parser) {
    System.out.println("KosimeFunction.java getMessage() 시작");
    HttpClient client = HttpClient.newHttpClient();
    // 스레드의 모든 메시지를 가져오는 API URL
    String getMessagesUrl = API_URL + "threads/" + simsimeDTO.getThread_id() + "/messages";
    HttpRequest getMessagesRequest = HttpRequest.newBuilder()
            .uri(URI.create(getMessagesUrl))
            .header("Authorization", "Bearer " + API_KEY)
            .header("Content-Type", "application/json")
            .header("OpenAI-Beta", "assistants=v2")
            .GET()
            .build();
    HttpResponse<String> getMessagesResponse= null;
    try {
        getMessagesResponse = client.send(getMessagesRequest, HttpResponse.BodyHandlers.ofString());

        // API에서 가져온 전체 메시지 출력 (여기서 Assistant 응답 확인 가능)
        System.out.println("getMessage 응답: " + getMessagesResponse.body());

    } catch (Exception e) {
        e.printStackTrace();
    }

    try {
        JSONObject responseJson = (JSONObject) parser.parse(getMessagesResponse.body());

        // data 배열을 추출
        JSONArray dataArray = (JSONArray) responseJson.get("data");
        boolean foundAssistantResponse = false;

        // data 배열의 각 요소를 확인
        for (Object dataObject : dataArray) {
            JSONObject data = (JSONObject) dataObject;

            // role이 assistant인 메시지를 찾기
            String role = (String) data.get("role");
            if ("assistant".equals(role)) {
                // assistant의 응답이 있는 경우만 처리
                JSONArray contentArray = (JSONArray) data.get("content");
                for (Object contentObject : contentArray) {
                    JSONObject content = (JSONObject) contentObject;
                    JSONObject text = (JSONObject) content.get("text");
                    String assistantMessage = (String) text.get("value");

                    // 결과 출력
                    System.out.println("Assistant 응답: " + assistantMessage);
                    simsimeDTO.setAssistantMessage(assistantMessage);
                    simsimeDTO.setStatus("completed");
                    foundAssistantResponse = true;
                }
                break;  // assistant 메시지를 찾으면 반복 종료
            }
        }

        if (!foundAssistantResponse) {
            System.out.println("Assistant 응답이 없습니다.");
            simsimeDTO.setStatus("queued");
        }
    } catch (ParseException e) {
        System.out.println("JSON 파싱 실패");
        e.printStackTrace();
    }

    System.out.println("KosimeFunction.java getMessage() 끝");
    return simsimeDTO;
}