Ollama Clojure Frontend - Breeze
Introduction
Breeze is a small ollama frontend, with few features, expect that it just works. It allows to talk to ollama in realtime, with a really small memory/disk footprint.
Prerequisites are:
- Ollama, to run the models
- Docker, to run this image from dockerhub.
Start the docker image
docker run -it --rm -p 3000:3000 hellonico/breeze
Breeze UI
The setup screen includes:
- ollama url
- ollama model
- system prompt
Then, the chat screen allows to chat just like your usual web chat.
Works for
Just like other chat frontends, the tokens are rendered in real time.
Code Internals
The application has:
- a frontend in ClojureScript/Reagent
- a backend in Clojure/Ring
- the two are connected via websockets.
Pyjama is doing the streaming logic between ollama and the Clojure backend.
Basically the core of the Clojure ring server is:
(let [state (atom (assoc ?data :processing true))
client-chan (fn [_ text] (chsk-send! uid [:chat/token text]))]
(p/ollama-chat state (partial client-chan nil))
(future
(loop []
(if (:processing @state)
(do (Thread/sleep 500) (recur))
(chsk-send! uid [:chat/done nil])))))
We create a core.async client-chan and then this is passed a parameter to ollama-chat which does the streaming for us.
Docker Internals
The docker build phase:
- compiles the clojurescript to javascript, and
- creates an uber-ed jar file, containing all the clojure code and the dependencies
# ---- Build stage ----
FROM eclipse-temurin:21-jdk AS builder
# ... install build deps
WORKDIR /app
# Copy configs and deps
COPY deps.edn package.json shadow-cljs.edn build.clj ./
COPY src ./src
COPY public ./public
# Install JS deps
RUN npm install
# customized ollama url to refer to the host ip
RUN sed -i 's|http://localhost:11434|http://host.docker.internal:11434|g' ./src/myapp/core.cljs
# Compile ClojureScript
RUN npx shadow-cljs release app
# Build backend uberjar
RUN clojure -T:build uber
The docker run image:
- includes the compiled clojurescript
- includes the jar file from the build phase
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
COPY --from=builder /app/public ./public
EXPOSE 3000
ENTRYPOINT ["java", "-jar", "app.jar"]
New features
Right now, low hanging fruits are:
- Chat History Persistence
Why: Right now, messages disappear on reload. Persisting chats would let users revisit past sessions.
- Multiple Conversations
Why: Let users manage different threads of thought (like tabs or threads in ChatGPT).
- Export Chat (Markdown/PDF)
Why: Super helpful for saving valuable exchanges.
- Prompt Templates
Why: Let power users quickly apply useful system prompts (e.g. “Act like a proofreader”).
- Typing Indicators & Streaming Delay Simulation
Why: For realism and UX polish.
- Auth (optional)
Why: To unlock saved history, custom settings per user, etc.
Git project
If you need a feature urgently, get in touch on the project at: https://github.com/hellonico/breeze