Adding streaming endpoints
Overview
In this step of the guide, you’ll add some endpoints to provide a client-friendly API in front of all of the RAG components you’ve been building. You’ll create an API for submitting your "Ask Akka" questions (prompts), and one that serves up a self-hosted, static asset web UI.
Prerequisites
-
Java 21, we recommend Eclipse Adoptium
-
Apache Maven version 3.9 or later
-
An Akka account
-
Docker Engine 27 or later
You will need to have your MongoDB Atlas database URL and your Open AI API key available, as they are required to run the Ask Akka service.
If you are following along with each step rather than using the completed solution, then you’ll need the code you wrote in the previous step.
Adding a streaming API
Akka HTTP endpoints have the ability to return streams of data via server-sent events (SSE). For more information on this feature, check out the Akka SSE documentation.
@Acl(allow = @Acl.Matcher(principal = Acl.Principal.INTERNET))
@HttpEndpoint("/api")
public class AskHttpEndpoint {
public record QueryRequest(String userId, String sessionId, String question) {
}
private final ComponentClient componentClient;
private final AskAkkaAgent askAkkaAgent; (1)
private final Materializer materializer;
public AskHttpEndpoint(AskAkkaAgent askAkkaAgent, Materializer materializer, ComponentClient componentClient) {
this.askAkkaAgent = askAkkaAgent;
this.materializer = materializer;
this.componentClient = componentClient;
}
/**
* This method runs the search and streams the response to the UI.
*/
@Post("/ask")
public HttpResponse ask(QueryRequest request) {
var response = askAkkaAgent
.ask(request.userId, request.sessionId, request.question)
.map(StreamedResponse::content); (2)
return HttpResponses.serverSentEvents(response); (3)
}
}
1 | Inject the AskAkkaAgent class created in the previous step |
2 | Extract the content field from each StreamedResponse |
3 | Use the serverSentEvents function to easily send a stream via SSE |
The userId
and sessionId
parameters are required in QueryRequest
along with the question
field.
Adding the users API
There is a convenience endpoint that you can use to query the list of sessions for a given user:
@Acl(allow = @Acl.Matcher(principal = Acl.Principal.INTERNET))
@HttpEndpoint("/api")
public class UsersEndpoint {
private final ComponentClient componentClient;
public UsersEndpoint(ComponentClient componentClient) {
this.componentClient = componentClient;
}
@Get("/users/{userId}/sessions/")
public ConversationHistoryView.ConversationHistory getSession(String userId) {
return componentClient.forView()
.method(ConversationHistoryView::getSessionsByUser)
.invoke(userId);
}
}
One subtle thing worth pointing out here is that both the streaming RAG endpoint and the user view query endpoint have the exact same route as defined in @HttpEndpoint("/api")
.
Adding the static UI endpoint
You can now add an endpoint that serves up the static UI. This is surprisingly simple in Akka, as the HTTP endpoint class has built-in support for serving these kinds of assets.
@HttpEndpoint
@Acl(allow = @Acl.Matcher(principal = Acl.Principal.ALL))
public class UiEndpoint {
@Get("/")
public HttpResponse index() {
return HttpResponses.staticResource("index.html"); (1)
}
}
1 | The staticResource function serves up a file from main/resources/static-resources |
And lastly, we just need to fill out the index.html file to provide the static UI for Ask Akka.
There is far too much code in the HTML file to list out here. If you want to run the UI with the Ask Akka service, here you might want to switch to the version that is in the repository so you can get all of the single-file React code.
Running the service
Running the service should now just be a matter of running mvn compile exec:java
. Make sure that you have set both the OPENAI_API_KEY
and MONGODB_ATLAS_URI
environment variables before running exec:java
.
If you haven’t run the indexer yet, do so with:
curl -XPOST localhost:9000/api/index/start
Once you’ve made sure that your MongoDB Atlas database has a functioning and properly named vector index, you can use the Ask Akka service with a simple curl
command:
curl localhost:9000/api/ask --header "Content-Type: application/json" -XPOST \
--data '{ "userId": "001", "sessionId": "foo", "question":"How many components exist in the Akka SDK?"}'
Next steps
Now that you’ve gone through the process of building the Ask Akka sample, you should start playing with it and even breaking it. Change the indexing parameters like chunk size and see if that affects how the LLM performs. The key is to roll up your sleeves and get dirty, as that’s the best way to extend your learning beyond what’s covered in this guide.
Make sure you check out our thorough discussion of agentic AI and where Akka fits in the ecosystem.