Skip to content
Merged
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
38 changes: 38 additions & 0 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Quality

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
python:
uses: Sparkience-AI/.github/.github/workflows/reusable-python-quality.yml@adc5b60771b32fbf93f28304fbcf2dd5ad4a0464
with:
python-version: "3.12"
run-type-check: true

documentation:
uses: Sparkience-AI/.github/.github/workflows/reusable-docs-geo.yml@adc5b60771b32fbf93f28304fbcf2dd5ad4a0464

package:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: ${{ matrix.python-version }}
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
- name: Build distributions
run: uv build --no-sources
- name: Smoke-test installed wheel
run: |
python -m venv .wheel-smoke
.wheel-smoke/bin/python -m pip install --disable-pip-version-check dist/*.whl
.wheel-smoke/bin/sparkollama --version
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.venv/
.wheel-smoke/
.uv-cache/
dist/
build/
*.egg-info/
__pycache__/
*.py[cod]
.pytest_cache/
.mypy_cache/
.ruff_cache/
.coverage
htmlcov/
.env
.env.*
!.env.example
.streamlit/secrets.toml
12 changes: 12 additions & 0 deletions .streamlit/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[theme]
base = "dark"
primaryColor = "#e91e63"
backgroundColor = "#070707"
secondaryBackgroundColor = "#1f1f1f"
textColor = "#f5f5f5"

[server]
address = "127.0.0.1"

[browser]
gatherUsageStats = false
140 changes: 70 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,103 +1,103 @@
# SparkOllama 🤖
## Your AI, Your Conversations; Powered by Streamlit and Ollama; Developed by Sparkience AI Lab
# SparkOllama

Welcome to **SparkOllama**! This application is a sleek, AI-powered conversational interface built using Ollama's advanced language models. If you're looking for an effortless way to interact with AI through real-time responses, SparkOllama is the tool for you!
SparkOllama is an alpha, privacy-focused chat interface for models running on a local [Ollama](https://ollama.com/) service. It provides model discovery, bounded in-memory conversation history, and streamed responses without adding a cloud provider or hosted backend.

---
## Who it is for

### Features ✨
- **Multiple AI Models**: Choose from a list of available Ollama models to tailor your conversation.
- **Real-Time Streaming**: Get dynamic responses in real-time as you type, thanks to the Ollama API.
- **Clear Chat History**: Reset your conversation history at any time.
- **Stylish Dark Mode**: Enjoy a sleek, modern, and dark-themed interface for an immersive experience.

---
SparkOllama is for people who already use Ollama and want a small browser interface that keeps ordinary inference on their machine. It is not a public chat service, remote Ollama gateway, model manager, or autonomous agent.

### How It Works ⚙️
## Capabilities

1. **Model Selection**:
- Choose your AI model from a dropdown list. Ollama provides various models for different use cases.

2. **Chat with AI**:
- Type your query into the chat box, and the AI will respond in real-time with intelligent, conversational answers.

3. **Clear Chat**:
- Easily clear your chat history using the "Clear Chat History" button to start fresh at any time.
- Lists models installed in the local Ollama service.
- Streams local model responses into a Streamlit chat interface.
- Keeps conversation content only in the current application session.
- Bounds prompt and history size before sending context to Ollama.
- Clears history when the user requests it or changes models.
- Handles unavailable daemons, empty model lists, malformed responses, timeouts, and interrupted streams with user-facing states.
- Renders user and model content without unsafe HTML interpolation.

---
SparkOllama does not browse, execute code, access files, call tools, or send prompts to a cloud model.

### Installation 🚀
## Requirements

1. **Clone the Repository**:
```bash
git clone https://github.com/your-repo/sparkollama.git
cd sparkollama
```
- Windows, macOS, or Linux supported by Ollama and Python.
- Python 3.11, 3.12, or 3.13.
- [uv](https://docs.astral.sh/uv/) for the reproducible Python environment.
- A locally installed [Ollama](https://ollama.com/download) service.
- Enough disk and memory for the model you choose; requirements vary by model and quantization.

2. **Install Dependencies**:
```bash
pip install -r requirements.txt
```
## Local installation

3. **Run the Application**:
```bash
streamlit run file.py
```
```bash
git clone https://github.com/Sparkience-AI/SparkOllama.git
cd SparkOllama
uv sync --locked
```

4. **Open the App**:
- Visit `http://localhost:8501` in your browser to start interacting with SparkOllama!
Pull a small model if you do not already have one:

---
```bash
ollama pull llama3.2
```

### Key Files 🗂️
Start the application:

- **`file.py`**:
The main Streamlit app that handles user input, displays messages, and interacts with the Ollama API.

- **`style.css`**:
Custom CSS to give the application a sleek, modern look with a dark theme.
```bash
uv run --locked sparkollama
```

---
Open <http://127.0.0.1:8501>. The launcher binds Streamlit to loopback and disables Streamlit usage reporting. The original `app.py` and `file.py` launch commands remain available as source-checkout compatibility entry points and use the committed secure Streamlit configuration.

### User Interface 🖥️
## Local security posture

- **Wide Mode Layout**: Utilizes the full width of your screen for a more spacious experience.
- **Interactive Chat Boxes**: Different color schemes for user and AI responses for clarity and ease of reading.
- **Dark Theme**: Keep it sleek with a modern, dark-themed UI for comfortable use in low-light environments.
SparkOllama connects only to an explicit loopback endpoint, `http://127.0.0.1:11434`, and rejects remote or ambiguous endpoints in its provider boundary. Ollama's local API does not provide application authentication by default. Do not bind port `11434` to `0.0.0.0`, a LAN interface, or the public internet merely to use this application.

---
Conversation content is untrusted text. The application does not enable unsafe HTML when rendering messages, and models receive no tool authority. See [privacy and data handling](docs/privacy.md) and the [architecture and trust boundary](docs/architecture.md).

### Behind the Scenes 🧠
## Failure behavior

- **Ollama API**: SparkOllama leverages the Ollama chat API to stream conversational responses in real-time, enhancing the interactivity of the tool.
- **Streamlit**: Used to create a fast, responsive, and user-friendly web app interface.
- **Ollama is unavailable:** start the Ollama service and reload the page.
- **No model is installed:** run `ollama pull llama3.2` or select another model you have installed.
- **A stream is interrupted:** any received partial response remains visible and in the current session; the error does not expose prompt text.
- **History is too large:** older complete turns are removed from both session state and provider context; the UI reports provider-context omissions.
- **The latest prompt is too large:** the application rejects it rather than silently truncating it.

---
Review the [known limitations](docs/limitations.md) before relying on the application for sensitive or long-running work.

### Contribution Guidelines 🤝
## Architecture

We welcome contributions! If you'd like to contribute to SparkOllama, feel free to open an issue or submit a pull request.
The Streamlit interface calls a framework-independent `ChatService`, which validates conversation context and uses an `OllamaProvider` adapter. Deterministic tests inject fake clients, so normal CI does not require a daemon, model download, network request, or API key.

---
```text
Streamlit UI -> ChatService -> loopback-only OllamaProvider -> local Ollama daemon
| |
context policy error translation
```

### Future Plans 🔮
## Development

- **Improved Customization**: More model options and fine-tuning capabilities.
- **Saved Conversations**: Allow users to save and revisit past conversations.
- **Enhanced Visuals**: Even more customization for the UI, with options for light mode and font changes.
Run the same checks used by CI:

---
```bash
uv sync --locked --all-groups
uv run --locked ruff format --check .
uv run --locked ruff check .
uv run --locked mypy src
uv run --locked pytest -q
uv build --no-sources
```

### License 📜
The test suite covers endpoint policy, daemon failures, model response compatibility, streaming, partial-stream recovery, complete-turn context bounds, local server configuration, the installed launcher, and safe UI rendering. CI also builds and smoke-tests the wheel on Python 3.11, 3.12, and 3.13.

This project is licensed under the MIT License. See the `LICENSE` file for details.
## Documentation and AI discoverability

---
- [Privacy and retention](docs/privacy.md)
- [Architecture and trust boundary](docs/architecture.md)
- [Known limitations](docs/limitations.md)
- [`llms.txt`](llms.txt), provided as an experimental machine-readable project summary

### Stay Connected 🌐
The README and linked documents are the authoritative sources for installation, scope, privacy, and limitations. Generic claims about model intelligence are intentionally avoided because behavior depends on the selected local model.

Made with ❤️ by **Sparkience AI Lab**. Feel free to reach out or follow us for updates!
## License and support

Happy chatting with SparkOllama! 👨‍💻👩‍💻

---
SparkOllama is available under the [MIT License](LICENSE). Use GitHub issues for reproducible bugs and feature proposals. Report security concerns through the Sparkience organization security policy rather than a public issue.
5 changes: 5 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Canonical Streamlit entry point."""

from sparkollama.ui import run

run()
16 changes: 16 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Architecture

SparkOllama has four small boundaries:

1. `app.py` and `file.py` launch the Streamlit interface.
2. `sparkollama.ui` owns display and session state but not Ollama protocol handling.
3. `sparkollama.service` validates and bounds conversation context.
4. `sparkollama.providers` enforces the loopback endpoint policy and translates Ollama responses and failures.

The UI and deterministic tests use the same typed service contracts. Standard tests use fake clients and do not require a running daemon or model download.

## Trust boundary

User and model messages are untrusted text. They are rendered through Streamlit without enabling unsafe HTML. The only supported provider endpoint is an explicit loopback HTTP(S) URL with no credentials, query, fragment, or API path.

SparkOllama does not give the model tools, filesystem access, browsing, code execution, or permission to perform external actions.
11 changes: 11 additions & 0 deletions docs/limitations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Current limitations

SparkOllama is an alpha local chat client, not a hosted service.

- Only a loopback Ollama service is supported.
- Conversation history exists only in the current Streamlit session.
- Context is bounded by message and character limits, not a model-specific tokenizer.
- The current Streamlit interface cannot cancel an in-flight request. A 60-second Ollama client timeout bounds stalled requests; slow models may require a future user-configurable local setting.
- Partial streamed output is retained in the session when the connection fails.
- Model quality, safety, licensing, context size, and hardware needs depend on the model selected in Ollama.
- Saved conversations, remote endpoints, cloud models, tool calling, and public hosting are intentionally out of scope.
11 changes: 11 additions & 0 deletions docs/privacy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Privacy and data handling

SparkOllama is designed for a local Ollama service on `127.0.0.1` or `localhost`.

- Prompts and model responses remain in the active Streamlit session and are not saved by SparkOllama.
- Clearing the chat removes the current in-memory application history.
- SparkOllama disables Streamlit usage reporting and has no application telemetry, user accounts, cloud provider, or analytics integration.
- Ollama model downloads require network access, but ordinary inference is local after the model is present.
- Local models and Ollama may have their own files, caches, and logs. Review Ollama's configuration when local retention matters.

The committed configuration and installed launcher bind the Streamlit interface to `127.0.0.1`. SparkOllama does not treat a browser-accessible Ollama endpoint as authenticated. Keep ports `8501` and `11434` bound to loopback. Do not expose either service on a LAN or the public internet without a separately designed authenticated and encrypted gateway.
63 changes: 5 additions & 58 deletions file.py
Original file line number Diff line number Diff line change
@@ -1,58 +1,5 @@
import streamlit as st
import ollama
from typing import Dict, Generator

# Set wide mode
st.set_page_config(layout="wide")

# Load custom CSS for styling
with open("style.css") as css:
st.markdown(f'<style>{css.read()}</style>', unsafe_allow_html=True)

# Generator function for streaming chat responses from Ollama
def ollama_generator(model_name: str, messages: Dict) -> Generator:
stream = ollama.chat(model=model_name, messages=messages, stream=True)
for chunk in stream:
yield chunk['message']['content']

# Page title
st.title("🤖 SparkOllama: Made By Sparkience AI Lab")

# Initialize session state variables
if "selected_model" not in st.session_state:
st.session_state.selected_model = ""
if "messages" not in st.session_state:
st.session_state.messages = []

# Model Selection Dropdown (dark themed)
st.session_state.selected_model = st.selectbox(
"Please select the model:", [model["name"] for model in ollama.list()["models"]])

# Clear chat history functionality
if st.button("Clear Chat History"):
st.session_state.messages = []

# Display chat messages
for message in st.session_state.messages:
if message["role"] == "user":
with st.chat_message("user"):
st.markdown(f'<div class="chat-box user-message">{message["content"]}</div>',
unsafe_allow_html=True)
else:
with st.chat_message("assistant"):
st.markdown(f'<div class="chat-box assistant-message">{message["content"]}</div>',
unsafe_allow_html=True)

# Chat input functionality
if prompt := st.chat_input("How can I assist you?"):
# Add user message to chat history
st.session_state.messages.append({"role": "user", "content": prompt})

# Display user message in chat message container
with st.chat_message("user"):
st.markdown(f'<div class="chat-box user-message">{prompt}</div>', unsafe_allow_html=True)


with st.chat_message("assistant"):
response = st.write_stream(ollama_generator(st.session_state.selected_model, st.session_state.messages))
st.session_state.messages.append({"role": "assistant", "content": response})
"""Compatibility entry point for the original SparkOllama launch command."""

from sparkollama.ui import run

run()
12 changes: 12 additions & 0 deletions llms.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SparkOllama

SparkOllama is an open-source, privacy-focused local conversation client for models served by Ollama.

Authoritative sources:

- Project and installation: https://github.com/Sparkience-AI/SparkOllama#readme
- Privacy: https://github.com/Sparkience-AI/SparkOllama/blob/main/docs/privacy.md
- Architecture and trust boundary: https://github.com/Sparkience-AI/SparkOllama/blob/main/docs/architecture.md
- Known limitations: https://github.com/Sparkience-AI/SparkOllama/blob/main/docs/limitations.md

The complete product runs locally. There is no hosted SparkOllama service, cloud model provider, or agentic tool execution. The Ollama API is unauthenticated by default and must remain loopback-only.
Loading
Loading