openai-java icon indicating copy to clipboard operation
openai-java copied to clipboard

Still experiencing "Unrecognized token 'data': was expecting..." when using stream(true)...code works fine when stream(false) is set.

Open mcfasa09 opened this issue 2 years ago • 7 comments

This issue was set to "Closed" (issue #52), but I am still having the same issue despite trying the recommended fix. I've been pulling my hair out with this one for three days. Please help?

Here is my code that gives the error in the logcat, "Unrecognized token 'data': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')":

From another method:
        final Duration ai_timeout = Duration.ofSeconds(75);
        service = new OpenAiService("MY_API_KEY_GOES_HERE", ai_timeout);
        String userInput = binding.fragmentMainUsersEditTextToAi.getText().toString();
        new OpenAITask().execute(userInput);


String Username;
private class OpenAITask extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... params) {

        SetThreadPolicy();

        //TODO: Set username to "Username" variable to the users username:
        Username = "Username goes here.";

        String question = params[0];
        String response = "";

        CompletionRequest request = CompletionRequest.builder()
                .prompt(question)
                .model("text-davinci-003")
                .maxTokens(220)
                .topP(0.1)
                .stream(Boolean.TRUE) //TODO: Figure out why setting .stream(true) causes the error: Unrecognized token 'data': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
                .echo(false)
                .frequencyPenalty(0.0)
                .user(Username)
                .build();

        List<String> responses = null;

        try {
            responses = service.createCompletion(request)
                    .getChoices()
                    .stream()
                    .map(CompletionChoice::getText)
                    .collect(Collectors.toList());

            System.out.println(responses);

            if (responses != null && responses.size() > 0) {
                responses.stream().forEach(System.out::println);
                response = responses.get(0);
            } else {
                System.out.println("Response is null or size=0");
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return response;
    }


    @Override
    protected void onPostExecute(String response) {
        if (response != null && !response.isEmpty()) {
            Log.d("Debug", "response: " + response);

            messagesAdapter.appendMessage(new com.wiscoapps.askai.Message(response.trim(), false)); //Note: ".trim()" will remove any leading or trailing whitespace or line breaks from the response before appending the text.

            storeMessagesAndRecyclerViewPositionToSharedPreferences();

            messagesAdapter.notifyItemInserted(messagesAdapter.getItemCount() - 1);

            // Smooth scroll to the last item in the RecyclerView:
            retrieveMessagesFromSharedPreferences();
            LinearLayoutManager layoutManager = ((LinearLayoutManager) binding.messagesRecyclerView.getLayoutManager());
            if (layoutManager != null && layoutManager.findLastCompletelyVisibleItemPosition() < messagesAdapter.getItemCount() - 1) {
                binding.messagesRecyclerView.requestLayout();
                if (binding.messagesRecyclerView.getLayoutManager() instanceof LinearLayoutManager) {
                    LinearLayoutManager linearLayoutManager = (LinearLayoutManager) binding.messagesRecyclerView.getLayoutManager();
                    linearLayoutManager.smoothScrollToPosition(binding.messagesRecyclerView, null, messagesAdapter.getItemCount() - 1);
                }
            }

            //TODO: HANDLE EXCEPTIONS/ALERT USER...like if the user hasn't input an API...an invalid API is input...no internet connection...etc.
        }
    }

mcfasa09 avatar Feb 03 '23 01:02 mcfasa09

Can you print your prompt out? I want to make sure you don't have to quote it.

String question = "\" + params[0] + "\"";

cryptoapebot avatar Feb 03 '23 02:02 cryptoapebot

Thanks for the reply. That does not change the issue. I can type in a string for the prompt as well, and the same result happens.

mcfasa09 avatar Feb 03 '23 02:02 mcfasa09

Let me experiment.

This from the code: * Whether to stream back partial progress. * If set, tokens will be sent as data-only server-sent events as they become available, * with the stream terminated by a data: DONE message.

I'm wondering if you need to define a get output stream? I don't know the exact syntax w/o testing it yet.

			BufferedReader bri = new BufferedReader(new InputStreamReader(service.createCompletion.getInputStream()));
			String line;
			while ((line = bri.readLine()) != null) {
				System.out.println(line);
			}
			bri.close();

Because I wonder in your .collect it's not handling the DONE correctly?

i.e.

{response : "whatever....multiple lines and stuff"}
DONE. 

cryptoapebot avatar Feb 03 '23 02:02 cryptoapebot

Some previous discussion and ideas on the subject.

https://github.com/openai/openai-node/issues/18

cryptoapebot avatar Feb 03 '23 03:02 cryptoapebot

	public static HttpResponse<InputStream> dalle2stream(String prompt) {
		String json = json_request.replace("${PROMPT}", prompt);
		HttpRequest request = 
				HttpRequest.newBuilder()
				.uri(URI.create(openai_image))						
		        .header("Content-Type","application/json")					
		        .header("Authorization", OPENAI_API_KEY)
		        .POST(HttpRequest.BodyPublishers.ofString(json))
				.build();
		HttpResponse<InputStream> response = null;
		try {
			response = httpClient.send(request, HttpResponse.BodyHandlers.ofInputStream());
			if ((response.statusCode() / 100) != 2) {
				System.out.println("response code: " + response.statusCode());
				System.out.println("response body: " + response.body());
			} else {
				return response;
			}
		} catch (IOException | InterruptedException e) {
			System.out.println("response code: " + response.statusCode());
			e.printStackTrace();
		}

		return null;
	}

cryptoapebot avatar Feb 03 '23 05:02 cryptoapebot

The response for stream(true) utilizes the Server-Sent Events protocol, which is not currently supported by this project's retrofit2 API. Discussions on this issue can be found here https://github.com/square/retrofit/issues/1029.

Unfortunately, it does not seem as though this issue can be resolved in the near future as long as retrofit is in use.

terryyin avatar Feb 16 '23 04:02 terryyin

See #129

cryptoapebot avatar Mar 16 '23 23:03 cryptoapebot

This is fixed in 0.12.0 :+1:

TheoKanning avatar Apr 01 '23 19:04 TheoKanning