# Red Hat Oracle — Architecture & Project Plan

## Vision

Red Hat Oracle is an AI-powered knowledge assistant that ingests all code
repositories and Slack conversations from Red Hat engineering teams, indexes
them in a vector database, and provides an interactive chat interface backed
by local or cloud LLMs.

The goal: be the **oracle** — all-knowing, all-wise — for Red Hat Insights,
Ansible, and internal engineering knowledge.

---

## 1. Requirements

### Functional

| ID | Requirement |
|----|-------------|
| F1 | Ingest all repos from GitHub orgs (RedHatInsights, ansible) via PAT/SSH |
| F2 | Ingest all repos from internal GitLab groups (automation-analytics, Dataverse, service, insights-platform, releng, insights-qe) via PAT/SSH |
| F3 | Ingest Slack workspace messages and threads |
| F4 | Chunk and embed all ingested content into a vector database |
| F5 | Support semantic search across all indexed knowledge |
| F6 | RAG pipeline: retrieve relevant context and generate answers via LLM |
| F7 | Support local LLMs via Ollama |
| F8 | Support Intel hardware acceleration via OpenVINO (NPU/iGPU/CPU) |
| F9 | Support external LLMs (OpenAI, Anthropic) |
| F10 | Interactive chat sessions with history |
| F11 | CLI interface (terminal chat, like opencode/codex) |
| F12 | GUI interface (desktop app) |
| F13 | YAML-driven configuration for all sources, providers, and settings |

### Non-Functional

| ID | Requirement |
|----|-------------|
| NF1 | Cross-platform: Windows, Linux, macOS |
| NF2 | Memory-sensitive — avoid bloated runtimes, offload heavy work to native backends |
| NF3 | Incremental sync — only fetch/update changed repos and messages |
| NF4 | No data loss — shallow clones preserve all file content at HEAD |
| NF5 | Secrets never stored in plaintext config — env vars or system keyring |

---

## 2. Architecture Overview

```
┌─────────────────────────────────────────────────────────────┐
│                        User Interface                        │
│                                                              │
│   ┌──────────────┐              ┌──────────────┐            │
│   │   CLI (Rich   │              │  GUI (PySide6) │            │
│   │  + prompt_    │              │               │            │
│   │   toolkit)    │              │               │            │
│   └──────┬───────┘              └──────┬───────┘            │
│          │                             │                     │
│          └──────────┬──────────────────┘                     │
│                     │                                        │
│              ┌──────▼──────┐                                │
│              │  Chat Session │                                │
│              │  Manager      │                                │
│              └──────┬──────┘                                │
│                     │                                        │
│              ┌──────▼──────┐                                │
│              │  RAG Pipeline │                                │
│              │              │                                │
│              │  query →     │                                │
│              │  retrieve →  │                                │
│              │  augment →   │                                │
│              │  generate    │                                │
│              └───┬─────┬───┘                                │
│                  │     │                                     │
│     ┌────────────▼─┐ ┌─▼────────────┐                       │
│     │ Vector Store  │ │ LLM Provider  │                       │
│     │ (ChromaDB)    │ │ Abstraction   │                       │
│     │               │ │               │                       │
│     │ - search      │ │ - Ollama      │                       │
│     │ - ingest      │ │ - OpenVINO    │                       │
│     │ - embeddings  │ │ - OpenAI      │                       │
│     └───────┬───────┘ │ - Anthropic   │                       │
│             │         └───────────────┘                       │
│     ┌───────▼───────┐                                        │
│     │ Data Sources   │                                        │
│     │                │                                        │
│     │ - GitHub       │                                        │
│     │ - GitLab       │                                        │
│     │ - Slack        │                                        │
│     └───────────────┘                                        │
│                                                              │
│     ┌───────────────┐                                        │
│     │ Config (YAML)  │                                        │
│     └───────────────┘                                        │
└─────────────────────────────────────────────────────────────┘
```

---

## 3. Project Structure

```
redhat-oracle/
├── pyproject.toml                 # Project metadata, dependencies, entry points
├── oracle.yaml                    # Default/example configuration
├── plan/
│   ├── architecture.md            # This document
│   ├── data-flow.md               # Data ingestion and query flow
│   └── milestones.md              # Phased delivery plan
├── src/
│   └── redhat_oracle/
│       ├── __init__.py
│       ├── __main__.py            # Entry point: `python -m redhat_oracle`
│       ├── core/
│       │   ├── __init__.py
│       │   ├── config.py          # YAML config loading, validation, platform detection
│       │   ├── session.py         # Chat session management (history, persistence)
│       │   ├── rag.py             # RAG pipeline (retrieve → augment → generate)
│       │   ├── sources/
│       │   │   ├── __init__.py
│       │   │   ├── github.py      # GitHub org repo sync (PAT + SSH)
│       │   │   ├── gitlab.py      # GitLab group repo sync (PAT + SSH)
│       │   │   └── slack.py       # Slack channel/thread ingestion
│       │   ├── vectordb/
│       │   │   ├── __init__.py
│       │   │   ├── chunker.py     # AST-aware and fixed-size text chunking
│       │   │   ├── embeddings.py  # Embedding provider abstraction
│       │   │   └── store.py       # ChromaDB vector store operations
│       │   └── llm/
│       │       ├── __init__.py
│       │       ├── base.py        # Abstract LLM provider interface
│       │       ├── ollama.py      # Ollama local LLM
│       │       ├── openvino.py    # OpenVINO NPU/iGPU/CPU inference
│       │       └── external.py    # OpenAI, Anthropic API providers
│       ├── cli/
│       │   ├── __init__.py
│       │   └── app.py             # CLI commands and interactive chat
│       └── gui/
│           ├── __init__.py
│           └── app.py             # PySide6 desktop GUI
├── tests/
│   ├── test_config.py
│   ├── test_chunker.py
│   ├── test_sources.py
│   └── test_rag.py
└── docs/
```

---

## 4. Technology Choices

### Language: Python

Python is the orchestration layer. The heavy computation (embedding, vector
search, LLM inference) is handled by native C++/Rust libraries:

| Component | Actual Engine | Python's Role |
|-----------|--------------|---------------|
| Embeddings | ONNX Runtime / PyTorch C++ | Call `.encode()` |
| Vector search | hnswlib (C++) via ChromaDB | Call `.query()` |
| LLM inference | llama.cpp (Ollama) / OpenVINO C++ | HTTP call |
| Git operations | libgit2 (C) via GitPython | Call `.clone()` |

This means Python's memory overhead is minimal — it's just glue.

### Key Libraries

| Purpose | Library | Why |
|---------|---------|-----|
| Config | PyYAML + Pydantic | Type-safe YAML config with validation |
| Git | GitPython | Mature, cross-platform git operations |
| HTTP | httpx | Modern async-capable HTTP client |
| Vector DB | ChromaDB | Embedded (no server), pure Python API, C++ search engine |
| Embeddings | sentence-transformers | Best local embedding models |
| Local LLM | ollama (Python client) | Simple HTTP client to Ollama server |
| Intel LLM | OpenVINO + optimum-intel | NPU/iGPU/CPU optimized inference |
| External LLM | openai, anthropic | Official SDKs |
| CLI | click + prompt-toolkit + rich | Lightweight, interactive terminal UI |
| GUI | PySide6 (Qt) | Cross-platform, polished desktop UI |
| Platform dirs | platformdirs | XDG-compliant paths on all OSes |

### Vector Database: ChromaDB

**Why a vector DB is worth it:**
- Red Hat Insights alone has 300+ repos. Ansible has 100+. Add 6 GitLab groups
  and Slack history — that's potentially millions of code chunks and messages.
- You cannot fit this in an LLM context window.
- Semantic search lets users ask questions in natural language and find relevant
  code/conversations without knowing exact file paths or keywords.
- The vector DB is embedded (runs in-process), so no separate server to manage.

**What we don't lose with shallow clones (depth=1):**
- All file content at HEAD is preserved — every file is fully readable.
- What's excluded: full commit history. This is a deliberate trade-off for
  disk space. If commit history is needed, set `depth: null` in config.

---

## 5. Configuration Design

All configuration lives in `oracle.yaml`. The loader merges configs from
multiple locations in precedence order:

1. `/etc/redhat-oracle/oracle.yaml` (system, Linux/macOS only)
2. `~/.config/redhat-oracle/oracle.yaml` (user)
3. `./oracle.yaml` (project/working directory)

Higher-precedence files override lower ones (deep merge).

### Secrets Management

Tokens are **never stored in the YAML file** in production. Instead:

```yaml
sources:
  github:
    token: null  # Use env var instead
```

```bash
export ORACLE_GITHUB_TOKEN="ghp_..."
export ORACLE_GITLAB_TOKEN="glpat-..."
export ORACLE_SLACK_TOKEN="xoxb-..."
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
```

The config loader checks env vars as fallback when YAML values are null.

### Source Configuration

```yaml
sources:
  github:
    token: null
    use_ssh: true
    orgs:
      - name: RedHatInsights
        include: []          # glob patterns, empty = all
        exclude: []          # glob patterns to skip
        depth: 1             # shallow clone (null = full)
      - name: ansible

  gitlab:
    token: null
    use_ssh: true
    instances:
      - url: https://gitlab.cee.redhat.com
        token: null          # instance-specific override
        groups:
          - name: automation-analytics
          - name: Dataverse
          - name: service
          - name: insights-platform
          - name: releng
          - name: insights-qe

  slack:
    token: null
    channels: []             # empty = all accessible
    history_days: 365
```

---

## 6. Data Flow

### Ingestion Pipeline

```
GitHub/GitLab Orgs           Slack Workspace
       │                           │
       ▼                           ▼
  Clone/Pull repos          Fetch messages
  (PAT + SSH)               (Bot token)
       │                           │
       ▼                           ▼
  Read source files          Group by thread
       │                           │
       ▼                           ▼
  Chunk (AST for Python,    Chunk (fixed-size
   fixed-size for others)    with overlap)
       │                           │
       ▼                           ▼
  Generate embeddings        Generate embeddings
  (sentence-transformers     (same model)
   or Ollama)
       │                           │
       ▼                           ▼
  ┌─────────────────────────────────┐
  │        ChromaDB Vector Store     │
  │                                  │
  │  Collections:                    │
  │   - oracle_github                │
  │   - oracle_gitlab                │
  │   - oracle_slack                 │
  └─────────────────────────────────┘
```

### Query Pipeline (RAG)

```
User Question
      │
      ▼
Generate query embedding
      │
      ▼
Search ChromaDB (top-k similar chunks)
      │
      ▼
Build augmented prompt:
  ┌──────────────────────────────┐
  │ System prompt (you are the   │
  │ Red Hat Oracle...)           │
  │                              │
  │ Retrieved context:           │
  │   [chunk 1 with metadata]    │
  │   [chunk 2 with metadata]    │
  │   ...                        │
  │                              │
  │ Chat history (last N msgs)   │
  │                              │
  │ User question                │
  └──────────────────────────────┘
      │
      ▼
Send to LLM (Ollama / OpenVINO / OpenAI / Anthropic)
      │
      ▼
Stream response to user
(with source citations)
```

---

## 7. LLM Provider Strategy

```
                    ┌──────────────┐
                    │ LLMProvider   │  (abstract base)
                    │               │
                    │ + generate()  │
                    │ + stream()    │
                    └──────┬───────┘
                           │
          ┌────────────────┼────────────────┐
          │                │                │
  ┌───────▼──────┐ ┌──────▼───────┐ ┌──────▼──────┐
  │ OllamaLLM    │ │ OpenVINOLLM  │ │ ExternalLLM │
  │              │ │              │ │             │
  │ HTTP to      │ │ Direct       │ │ OpenAI SDK  │
  │ localhost    │ │ inference    │ │ Anthropic   │
  │ :11434       │ │ NPU/iGPU/   │ │ SDK         │
  │              │ │ CPU          │ │             │
  └──────────────┘ └──────────────┘ └─────────────┘
```

**Selection logic:**
1. User sets `llm.default_provider` in config
2. CLI/GUI can override at runtime: `oracle chat --provider openai`
3. Fallback chain if default is unavailable

**Ollama** is the recommended default — it runs locally, supports dozens of
models, and the Python client is just HTTP calls (minimal memory).

**OpenVINO** is for users with Intel hardware who want to run models directly
without Ollama. Uses optimum-intel to load and run quantized models on
NPU, integrated GPU, or CPU.

---

## 8. Storage Layout

All data stored under platform-appropriate directories:

| Platform | Base Directory |
|----------|---------------|
| Linux | `~/.local/share/redhat-oracle/` |
| macOS | `~/Library/Application Support/redhat-oracle/` |
| Windows | `%LOCALAPPDATA%/redhat-oracle/` |

```
~/.local/share/redhat-oracle/
├── repos/
│   ├── github/
│   │   ├── RedHatInsights/
│   │   │   ├── insights-core/
│   │   │   ├── frontend-components/
│   │   │   └── ...
│   │   └── ansible/
│   │       ├── ansible/
│   │       ├── ansible-lint/
│   │       └── ...
│   └── gitlab/
│       └── gitlab.cee.redhat.com/
│           ├── automation-analytics/
│           ├── Dataverse/
│           ├── service/
│           ├── insights-platform/
│           ├── releng/
│           └── insights-qe/
├── vectordb/
│   └── chroma/               # ChromaDB persistent storage
├── sessions/
│   ├── 2025-02-10_14-30.json  # Chat session history
│   └── ...
└── logs/
```

---

## 9. CLI Design

```
oracle                         # Launch interactive chat (default)
oracle chat                    # Interactive chat session
oracle chat --provider openai  # Chat using specific LLM provider
oracle chat --resume           # Resume last session

oracle ingest                  # Sync all sources and update vector DB
oracle ingest --source github  # Sync only GitHub repos
oracle ingest --source gitlab  # Sync only GitLab repos
oracle ingest --source slack   # Sync only Slack messages

oracle status                  # Show index stats, source counts
oracle config                  # Show resolved configuration
oracle config --edit           # Open config in $EDITOR

oracle search "query"          # Direct vector search (no LLM)
```

Interactive chat UI (terminal):

```
┌─ Red Hat Oracle ──────────────────────────────┐
│                                                │
│ Oracle: How can I help you?                    │
│                                                │
│ You: How does the insights-core               │
│      upload process work?                      │
│                                                │
│ Oracle: The upload process in insights-core    │
│ is handled by the `Uploader` class in          │
│ `insights/client/upload.py:45`. It...          │
│                                                │
│ Sources:                                       │
│   - insights-core/insights/client/upload.py    │
│   - #platform-dev (2025-01-15): "the upload..." │
│                                                │
│ [You]: _                                       │
└────────────────────────────────────────────────┘
```

---

## 10. GUI Design

PySide6 (Qt) desktop application with:

- **Chat panel** — main area, markdown rendering for responses
- **Source panel** — sidebar showing indexed sources and stats
- **Settings** — LLM provider selection, model parameters
- **Session management** — save, load, export chat sessions

The GUI is an optional dependency (`pip install redhat-oracle[gui]`).

---

## 11. Security Considerations

| Concern | Mitigation |
|---------|-----------|
| Tokens in config files | Env vars preferred; YAML values are null by default |
| Internal GitLab repos | PAT scoped to read-only; repos stored locally only |
| Slack messages (PII) | Data stays local; vector DB is on-disk, not cloud |
| LLM data leakage | Local LLMs (Ollama/OpenVINO) keep all data on-device |
| External LLM APIs | User explicitly opts in; warning shown in config |

---

## 12. Memory & Performance Strategy

| Strategy | Impact |
|----------|--------|
| Shallow clones (depth=1) | ~90% less disk than full clone |
| ChromaDB embedded mode | No separate server process |
| Sentence-transformers `all-MiniLM-L6-v2` | 80MB model, fast inference |
| Ollama for LLM | Separate process, own memory management |
| Lazy loading of embedding model | Only loaded when ingesting/querying |
| Streaming LLM responses | Low memory for long responses |
| Batch embedding (64 at a time) | Controlled memory during ingestion |
| Index only files < 512KB | Skip generated/vendored blobs |
