-
Notifications
You must be signed in to change notification settings - Fork 652
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
Gemini : Streaming example not working on Android #249
Comments
@rachelsaunders, @thatfiredev please take a look. |
Hello, I notice this method is doing a lot of logging, would it be possible to see an example of one of these logs? Also, I'm not sure what you mean by adding "s.request(1)". There are no variables named "s" in your example code. Please tell me more. |
Hi @davidmotson, sorry about the confusion, I have added @Override
public void onSubscribe(Subscription s) {
s.request(1);
} I did this because when I tried to Log the chunks inside the onNext method, I wasn't getting anything. @Override
public void onNext(GenerateContentResponse generateContentResponse) {
String chunk = generateContentResponse.getText();
fullResponse[0] += chunk;
Log.d("GeminiPro", "onNext: " + chunk);
} |
You mentioned the logs, here they are : This is what I get without adding
This is what I get after adding
|
Oh, I think you're right, I see the problem now, I'll get this fixed asap.
A slight oversight, but as you can see the prompt is not actually passed through to the generateContentStream method here, leading to this error. While I'll fix it right away, the change may not be released immediately, if this is blocking for you, then my recommendation would be use kotlin's extension methods or maybe a static method to fix this within your own codebase:
|
Thank you, @davidmotson, and I am glad that I help to raise this issue. As you saw, I was using Java to interact with the Gemini API and you showed me a solution using Kotlin. I would to try it, can you show me how to implement this ? |
Ah, so this kotlin code is from the shim we have to allow interactions in java. If you make a new kotlin file in your project named, for example: "GenerativeModelFuturesExtension.kt" and throw this code in there, either as an extension function, or a static one, you should be able to call it from java, for example: package com.google.ai.client.generativeai.java
import com.google.ai.client.generativeai.type.Content
import com.google.ai.client.generativeai.type.GenerateContentResponse
import kotlinx.coroutines.reactive.asPublisher
import org.reactivestreams.Publisher
class GenerativeModelFuturesExtension {
companion object {
fun generateContentStream(
model: GenerativeModelFutures,
vararg prompt: Content
): Publisher<GenerateContentResponse> =
model.getGenerativeModel().generateContentStream(*prompt).asPublisher()
}
} can be called with: GenerativeModelFuturesExtension.generateContentStream(model, new Content.Builder().addText("Some prompt goes here").build()).subscribe(new Subscriber<GenerateContentResponse>() {
//implementation goes here
}); You'll likely need to change some stuff, like the package, to match where you've put this code, but it should be fairly similar to copying some java code into your codebase. |
Thanks, I have tried yesterday to implement what you shared with me, but I had to add more dependencies and I still have some problems. I will try my best to see if I can make it work, and then I will post the solution here, maybe someone might find it helpful. |
I am glad that I was able to implement what you suggested to me @davidmotson. Here is how I have done it. First, if initially the project in Android Studio was a Java project then in the // Dependencies for the Gemini API library
implementation("com.google.ai.client.generativeai:generativeai:0.1.2")
implementation("com.google.guava:guava:31.0.1-android")
implementation("org.reactivestreams:reactive-streams:1.0.4")
// Dependencies for the Kotlin Coroutines library (This is what you should add)
implementation("androidx.core:core-ktx:+")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.7.3") After that, create the package <your-package-name>
import com.google.ai.client.generativeai.java.GenerativeModelFutures
import com.google.ai.client.generativeai.type.Content
import com.google.ai.client.generativeai.type.GenerateContentResponse
import kotlinx.coroutines.reactive.asPublisher
import org.reactivestreams.Publisher
class GenerativeModelFuturesExtension {
companion object {
fun generateContentStream(
model: GenerativeModelFutures,
vararg prompt: Content
): Publisher<GenerateContentResponse> =
model.getGenerativeModel().generateContentStream(*prompt).asPublisher()
}
} At this point, if Android Studio is telling you that Kotlin is not configured, then click on the configure button as shown in the image below Then click OK Now, after the Kotlin configuration, make sure that the correct version of JVM is used. In my case, it was set to 17 then I changed it back to 1.8 because I am using JAVA 1.8 android {
kotlinOptions {
jvmTarget = "1.8"
}
} Now, you can use the Kotlin class you created like this public void getResponse(String query, ResponseCallback callback) {
GenerativeModelFutures model = getModel();
Content.Builder contentBuilder = new Content.Builder();
contentBuilder.setRole("user");
contentBuilder.addText(query);
Content content = contentBuilder.build();
Log.d("GeminiPro", "getResponse: " + query);
Log.d("GeminiPro", "getResponse: " + content);
final String[] fullResponse = {""};
Publisher<GenerateContentResponse> streamingResponse = GenerativeModelFuturesExtension.Companion.generateContentStream(model, content);
streamingResponse.subscribe(new Subscriber<GenerateContentResponse>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
@Override
public void onNext(GenerateContentResponse generateContentResponse) {
String chunk = generateContentResponse.getText();
fullResponse[0] += chunk;
callback.onResponse(fullResponse[0]);
Log.d("GeminiPro", "onNext: " + chunk);
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
callback.onError(t);
Log.d("GeminiPro", "onError: " + t.getMessage());
}
@Override
public void onComplete() {
System.out.println(fullResponse[0]);
callback.onResponse(fullResponse[0]);
Log.d("GeminiPro", "onComplete: " + fullResponse[0]);
}
});
} In the public interface ResponseCallback {
void onResponse(String response);
void onError(Throwable throwable);
} And here is how I handle the response in the model.getResponse(query, new ResponseCallback() {
@Override
public void onResponse(String response) {
runOnUiThread(() -> {
responseTextView.setText(response);
progressBar.setVisibility(View.GONE);
});
}
@Override
public void onError(Throwable throwable) {
runOnUiThread(() -> {
responseTextView.setText("Error: " + throwable.getMessage());
progressBar.setVisibility(View.GONE);
});
}
}); One important note, to update the views, you should use the That's it, I hope this helps. |
Hey @davidmotson, Can you please look at issue #257 ? Regarding this issue, I will consider that it was solved and I will close it. |
This has been fixed in release |
Awesome 😎 |
Hello! I'm trying to make an Android chatbot app (in Java), and I've read the Gemini API quickstart guide for Android and looked at the Java code. In my code, I just cannot get these imports to work:
I already have these implementations in my build.gradle file:
Is there something I'm missing? :( |
Hey @theJayTea to better track your issue, could you open a new issue and include as much detail as possible, including the error you are seeing? Thanks! |
Hello, I was following the quick-start guide that shows how to use the Gemini API in Android apps. So far I have been able to replicate most of the examples, but I was facing some problems because I have been getting errors while trying to run the code samples.
In this issue that I opened, I will focus on the streaming example. The
getResponse
method is a method that I created to get the model's response with streaming support.First, in the code sample. The
onSubscribe
was not used, when I did the same nothing, I got nothing. The code kept running without giving a response. So, I addeds.request(1)
to request something from the publisher. This addition threw an exception that didn't make sense :contents is not specified
why ?The content variable is already defined. I don't know if I am missing something or this is a bug that should be solved.
The text was updated successfully, but these errors were encountered: