Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/No-Country-simulation/G9-LATAM-Team-58/llms.txt

Use this file to discover all available pages before exploring further.

Mindloom is organized into four discrete layers that each own a single concern: the Web layer handles user interaction, the API layer validates and orchestrates, the Inference Service handles all machine learning, and Oracle Autonomous Database handles persistence and vector similarity search. No layer reaches past its immediate neighbor — the web never calls inference, and inference never touches the database.

The Four Layers

Web — React + Vite

Serves the user-facing interface for ingesting content, browsing the library, running searches, uploading CSV files, and viewing the corpus knowledge map. Built with React, Vite, TanStack Query, and shadcn/ui. In production it is served by nginx, which also reverse-proxies /api to the API container.

API — Java 25 + Spring Boot

The sole public entry point. Validates all input, calls the Inference Service for classification and embeddings, persists results to Oracle via JPA and JDBC, and exposes every REST endpoint consumed by the web. The only layer that touches the database.

Inference Service — Python 3.12 + FastAPI

A stateless service that loads a single model artifact (model.joblib) from OCI Object Storage on startup. Provides /predict for full content classification and /embed for query vectorization. Never touches the database.

Oracle Autonomous Database

Stores every content record including a VECTOR(384) column for semantic similarity. Nearest-neighbor queries run directly in the database engine using VECTOR_DISTANCE(COSINE), so the full indexed corpus participates in every search without a separate ranking service.

System Diagram

Content Ingestion Flow

When a user submits a new document via POST /content, the following sequence occurs:
1
Web sends the request
2
The React interface posts a JSON body containing title and body to the API:
3
{
  "title": "Introducción a Spring Boot",
  "body": "En este contenido se presentan los conceptos básicos para crear APIs REST con Java y Spring Boot."
}
4
API calls Inference /predict
5
The API forwards only the body field to the Inference Service’s POST /predict endpoint. The title is not sent — the classifier works on content, not metadata.
6
{ "text": "En este contenido se presentan los conceptos básicos..." }
7
The Inference Service applies the E5 "passage: " prefix internally, encodes the text with intfloat/multilingual-e5-small (384 dimensions), builds the 884-feature vector for the LogisticRegression classifier, and returns everything the API needs in a single response:
8
{
  "category": "Backend",
  "probability": 0.89,
  "keywords": ["java", "spring", "rest"],
  "explanation": ["spring", "rest", "endpoint"],
  "embedding": [0.021, -0.118, "…384 floats…"],
  "cluster_id": 3,
  "x": 4.21,
  "y": -1.07
}
9
A single call to /predict covers the entire indexing pipeline. Calling a separate embeddings endpoint for the same text would run the encoder twice — the most computationally expensive step — for no additional information. The cluster_id and UMAP coordinates (x, y) are also computed here, inside the artifact’s kmeans and umap_reducer objects, which the Java API cannot access directly.
10
API persists the record in two steps
11
JPA cannot map Oracle’s native VECTOR type, so persistence requires two database operations:
12
  • JPA insert — saves all scalar fields (id, title, body, category, probability, keywords, cluster_id, x, y, added_at).
  • JDBC update — sets the embedding column using a raw UPDATE statement with the 384-float array cast to VECTOR(384, FLOAT32).
  • 13
    API queries for 5 nearest neighbors
    14
    Immediately after insertion, the API queries Oracle to find the five most semantically similar documents already in the corpus:
    15
    SELECT id, title, category,
           1 - VECTOR_DISTANCE(embedding, :qv, COSINE) AS similarity
    FROM contents
    WHERE id <> :base_id
    ORDER BY VECTOR_DISTANCE(embedding, :qv, COSINE)
    FETCH FIRST :n ROWS ONLY
    
    16
    These results populate the related array in the 201 Created response.

    Semantic Search Flow

    GET /search?mode=semantic follows a similar but lighter path:
    1
    API calls Inference /embed
    2
    The query string is sent to POST /embed with type: "query". The type field is mandatory with no default — the E5 model requires the "query: " prefix when vectorizing search queries and "passage: " when indexing documents. Mixing them silently degrades search quality without raising any error.
    3
    { "text": "cómo validar entradas en Spring", "type": "query" }
    
    4
    The Inference Service returns a single 384-dimensional vector:
    5
    { "embedding": [0.021, -0.118, "…384 floats…"] }
    
    6
    API queries Oracle with VECTOR_DISTANCE
    7
    The API submits the query vector to Oracle Autonomous Database, which ranks all documents by cosine distance using its native AI Vector Search engine. The full corpus participates in every query — no sampling, no external ranking service.

    Port Reference

    ServicePortNotes
    API8080Published to host (ports: "8080:8080"); accessible directly during development
    Inference8000Internal only (expose: "8000"); not published to host — only the API calls it
    Web (dev)5173Vite dev server; proxies to API at http://localhost:8080 by default
    Web (prod)80nginx container (enabled with --profile web); reverse-proxies /api to the API
    Port 8000 on the host is intentionally kept closed. The Inference Service is an internal dependency of the API, not a public endpoint. The Docker Compose file uses expose rather than ports for the inference service to enforce this boundary.

    Scaffold Mode

    The API is designed to start without any database connection. By default, application.properties excludes DataSourceAutoConfiguration and HibernateJpaAutoConfiguration via spring.autoconfigure.exclude, so the application boots with no JDBC driver, no connection pool, and no JPA context:
    spring.autoconfigure.exclude=\
      org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration,\
      org.springframework.boot.hibernate.autoconfigure.HibernateJpaAutoConfiguration
    
    In this scaffold mode, all DB-backed endpoints (GET /contents, GET /search, POST /content, etc.) return 503 Service Unavailable. Endpoints that do not touch the database — such as GET /health and inference-proxying routes — continue to function normally. The db profile re-enables the excluded auto-configurations and requires the three datasource variables (SPRING_DATASOURCE_URL, SPRING_DATASOURCE_USERNAME, SPRING_DATASOURCE_PASSWORD) and TNS_ADMIN to be present. Docker Compose always starts the api container with SPRING_PROFILES_ACTIVE=db.
    GET /health always returns 200 OK in both modes. In scaffold mode the database dependency is reported as enabled: false and the overall status is UP as long as the Inference Service is reachable. In db mode, the health controller probes Oracle with SELECT 1 FROM DUAL on a 3-second timeout using Java virtual threads — a timed-out probe marks the dependency reachable: false without taking down the endpoint.

    Explore Further

    Deployment Overview

    Run Mindloom on an OCI Ampere A1 VM with nginx and the full web profile.

    Inference Service

    Understand the model artifact, E5 prefixes, feature construction, and the embedding vs. features distinction.

    POST /content

    Full reference for the ingestion endpoint, including request/response schema and error codes.

    Quickstart

    Get all four layers running locally in under 5 minutes.

    Build docs developers (and LLMs) love