Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ training/cloud/examples
training/instructlab/instructlab
vector_dbs/milvus/volumes/milvus/*
.idea
target
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Java-based chatbot application with SQL-based RAG - Quarkus

This application implements a chatbot with SQL RAG functionality backed by
Quarkus and its LangChain4j extension. The UI communicates with the backend
application via web sockets and the backend uses the OpenAI API to talk to
the model served by Podman AI Lab.

The RAG data is stored in a PostgreSQL database. The application always asks
the model in the background to generate a SQL query that yields data
necessary to ask a question. Then, the application executes that query and
passes the result, encoded as a JSON object, to the model along with
the original user prompt.

Documentation for Quarkus+LangChain4j can be found at
https://docs.quarkiverse.io/quarkus-langchain4j/dev/.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
version: v1.0
application:
type: language
name: ChatBot_Java_Quarkus_SQL_RAG
description: Chatbot sample with SQL-based RAG based on Quarkus
containers:
- name: llamacpp-server
contextdir: ../../../model_servers/llamacpp_python
containerfile: ./base/Containerfile
model-service: true
backend:
- llama-cpp
arch:
- arm64
- amd64
ports:
- 8001
image: quay.io/ai-lab/llamacpp_python:latest
- name: postgresql-server
contextdir: ../../../relational_dbs/postgresql
containerfile: Containerfile
arch:
- arm64
- amd64
ports:
- 5432
image: quay.io/ai-lab/postgresql:latest
- name: quarkus-chat-app
contextdir: app
containerfile: Containerfile
arch:
- arm64
- amd64
ports:
- 8080
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
wrapperVersion=3.3.2
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM registry.access.redhat.com/ubi8/openjdk-21:latest
WORKDIR /deployments
COPY --chown=185 . .
RUN mvn package
EXPOSE 8080
ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
ENV JAVA_APP_JAR="/deployments/target/quarkus-app/quarkus-run.jar"
# FIXME: the sleep is to allow the postgresql container to start first and
# should be replaced with a mechanism to declare that the application
# container depends on the database container, once something like that is
# supported...
CMD echo "sleeping for 10 seconds..."; sleep 10; /usr/local/s2i/run
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The recipes should following the cloud native pattern so should implement retry if the targeted service is not available or handle propertly failures so is this required ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, Quarkus itself does not support retries like this (it relies on it being restarted if the database isn't ready yet) and just refuses to boot if it can't connect :( I know this is a terrible solution, but I don't have any better idea.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or is it possible to declare somewhere (in ai-lab.yaml) that the Quarkus pod should be restarted until it boots properly?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No because the design has been made so that there is no synchronisation between the containers that are started. There is no way to delay the connection to the database ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yrodiere could you advise if there is a way to let Quarkus boot even when the database is not available yet, and let Hibernate execute its database generation strategy more lazily? I checked the configuration properties and nothing came to my mind.

Copy link
Copy Markdown

@yrodiere yrodiere Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no built-in way to let db generation execute lazily -- among other reasons because that could be very dangerous (you don't want that to happen twice).

Also, booting with an offline DB is technically not supported yet (it's WIP: quarkusio/quarkus#43396), but if you're not using anything exotic it'll probably work anyway.

The way to go would be to disable DB generation/validation, and execute it explicitly through custom code relying on org.hibernate.SessionFactory#getSchemaManager .

The problem will be to detect when you should initialize the DB... Maybe Agroal provides a "first connection" event that could be used for that, I don't know. That's probably something that should be filed as a new feature, as a follow-up to 43396 -- but it's not limited to Hibernate ORM, you'd have the same problem with Flyway schema management (which, by the way, is what you should be using in prod).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, in any case, none of this looks like something we want to do in this recipe that should be kept as simple as possible. IMO, AI lab should provide a way to declare dependencies between pods. Without it, I have no better idea than a dumb sleep command

Copy link
Copy Markdown
Contributor Author

@jmartisk jmartisk Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, or maybe, add some piece of a shell script to wait for the database port to be open before calling /usr/local/s2i/run?? Would that be ok?

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading