Skip to content

Repository files navigation

Atlas

Atlas is an open-source personal knowledge platform for learning AI Engineering. It starts as a small monorepo with a FastAPI backend, a Next.js frontend placeholder, PostgreSQL with pgvector through Docker Compose, and a testable Python service structure.

The repository intentionally contains no personal documents. Runtime uploads go under data/uploads/, and uploaded files are ignored by Git.

Repository Layout

apps/
api/ FastAPI backend
web/ Next.js frontend placeholder
docs/
architecture/ Architecture and setup notes
learning-notes/ Notes created while learning AI Engineering
evals/ Evaluation fixtures, prompts, and experiments
examples/
sample_docs/ Public sample documents only
scripts/ Local helper scripts
data/
uploads/ Local upload storage, ignored by Git

Prerequisites

  • Python 3.11 or newer
  • uv
  • Docker and Docker Compose
  • Node.js 20 or newer for the frontend placeholder

Install uv if needed:

brew install uv

or:

curl -LsSf https://astral.sh/uv/install.sh | sh

Setup

  1. Create your local environment file:

    cp .env.example .env
  2. Install Python dependencies:

    uv sync --extra dev
  3. Start PostgreSQL with pgvector:

    docker compose up -d postgres
  4. Apply database migrations:

    uv run alembic upgrade head
  5. Run the API:

    uv run uvicorn atlas_api.main:app --app-dir apps/api/src --reload
  6. Check the health endpoint:

    curl http://localhost:8000/health
  7. Try the versioned API:

    curl http://localhost:8000/api/v1/notes
  8. Run tests:

    uv run pytest

Embeddings and Retrieval

Atlas defaults to deterministic fake embeddings so local development and tests never make network calls. To use OpenAI embeddings, set these values in .env and re-index the documents whose embeddings should use the configured model:

EMBEDDING_PROVIDER=openaiOPENAI_API_KEY=your_api_keyEMBEDDING_MODEL=text-embedding-3-smallVECTOR_DIMENSIONS=1536

VECTOR_DIMENSIONS must match the output size requested from the embedding model. The OpenAI text-embedding-3-small default is 1536. /rag/search embeds the query and asks PostgreSQL with pgvector to rank matching chunks when search_mode is vector or hybrid.

Retrieval expands each request with deterministic query rewrites before search. The original query is always searched first, followed by fake-provider rewrites in local development and tests. Atlas searches every query, merges the results, deduplicates by chunk_id, keeps the highest similarity score for each chunk, and returns matched_queries metadata showing which queries retrieved it.

/rag/search and /rag/answer accept search_mode values of vector, keyword, and hybrid; hybrid is the default. Keyword search runs over chunk text and uses PostgreSQL full-text search in PostgreSQL-backed environments, with a small SQLite fallback for local tests. Hybrid search runs vector and keyword search independently, merges the result sets, deduplicates by chunk_id, and ranks with reciprocal rank fusion: each source contributes 1 / (60 + rank) and chunks found by both sources move up. Results preserve source_name, collection, section, chunk_index, similarity_score, keyword_rank, and matched_by metadata.

Reranking is an optional second pass after retrieval. When enabled, Atlas first fetches top_k candidates with the selected search mode, scores each chunk against the original user query, sorts by reranker_score, keeps up to RERANKER_TOP_K, and removes chunks below RERANKER_SCORE_THRESHOLD. The fake provider is deterministic and local; no external reranker APIs are configured yet.

RERANKER_ENABLED=falseRERANKER_PROVIDER=fakeRERANKER_TOP_K=5RERANKER_SCORE_THRESHOLD=0.80

To run PostgreSQL integration coverage, point ATLAS_TEST_DATABASE_URL at an isolated pgvector-enabled test database. It uses the fake provider and does not call OpenAI:

ATLAS_TEST_DATABASE_URL=postgresql+psycopg://atlas:atlas_dev_password@localhost:5432/atlas_test \
uv run pytest -m integration

Context Preview

POST /api/v1/rag/context-preview shows the exact context that a later answer generation step would receive. It performs retrieval and context assembly only; it does not call an LLM.

{
"query": "How does retrieval work?",
"top_k": 5,
"max_chunks": 3,
"similarity_score_threshold": 0.7
}

The response preserves retrieval rank and includes source and section metadata for each assembled chunk. max_chunks bounds prompt size after retrieval. A similarity_score_threshold excludes chunks below the supplied cosine similarity score. Higher thresholds reduce irrelevant context but can remove useful supporting detail; lower thresholds preserve recall but consume more of the eventual model context window. Keeping this assembly step separate makes the prompt inspectable before an LLM is introduced.

Answer Generation

POST /api/v1/rag/answer retrieves matching chunks, filters out scores below similarity_score_threshold (or ANSWER_SIMILARITY_SCORE_THRESHOLD), retains the highest-ranked chunks that fit ANSWER_CONTEXT_MAX_CHARACTERS, assembles their context, and generates an answer. Citations are generated from the exact selected chunks and returned separately from the answer text. The response also returns the selected retrieved_chunks so retrieval, keyword, and reranker metadata can be inspected.

{
"query": "How does retrieval work?",
"top_k": 5,
"collection": "learning"
}

LLM_PROVIDER=fake is the default and produces deterministic local answers. Set LLM_PROVIDER=openai and OPENAI_API_KEY to use the OpenAI provider; LLM_MODEL selects the model. The provider receives an instruction to answer only from the assembled context, while Atlas itself owns citations so source metadata is not mixed into the answer text.

If retrieval produces no chunks that meet the score threshold or fit the context budget, Atlas returns Insufficient context to answer the question. with an empty citation list and does not call the LLM. Provider call failures return HTTP 502 rather than a fabricated answer.

RAG Evals

Atlas includes a small public-safe RAG evaluation fixture at evals/rag_cases.json. Run it with fake providers from the repository root:

uv run python scripts/run_rag_evals.py

The harness creates an isolated in-memory app, seeds synthetic documents, calls /api/v1/rag/answer, checks expected cited sources and answer phrases, verifies no-context handling, and prints per-case pass/fail plus a final score. It does not call OpenAI by default.

Frontend Placeholder

The frontend is intentionally minimal:

cd apps/web
npm install
npm run dev

Then open http://localhost:3000.

Development Notes

  • Keep personal notes, PDFs, and uploaded files out of the repository.
  • Add only sanitized examples under examples/sample_docs/.
  • Keep /api/v1 in the router aggregator, not in individual route handlers.
  • Put backend HTTP handlers in the HTTP layer, business logic in services, data access behind repositories, and model-provider calls behind provider abstractions.
  • Add migrations before using PostgreSQL for production data.
  • Plain text, Markdown, and PDFs with extractable text are chunked and indexed. Other file types are stored as uploaded documents until an extractor exists.

License

MIT. See LICENSE.

About

Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - nir-jas/atlas: Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability. · GitHub
Skip to content

Repository files navigation

Atlas

Atlas is an open-source personal knowledge platform for learning AI Engineering. It starts as a small monorepo with a FastAPI backend, a Next.js frontend placeholder, PostgreSQL with pgvector through Docker Compose, and a testable Python service structure.

The repository intentionally contains no personal documents. Runtime uploads go under data/uploads/, and uploaded files are ignored by Git.

Repository Layout

apps/
api/ FastAPI backend
web/ Next.js frontend placeholder
docs/
architecture/ Architecture and setup notes
learning-notes/ Notes created while learning AI Engineering
evals/ Evaluation fixtures, prompts, and experiments
examples/
sample_docs/ Public sample documents only
scripts/ Local helper scripts
data/
uploads/ Local upload storage, ignored by Git

Prerequisites

  • Python 3.11 or newer
  • uv
  • Docker and Docker Compose
  • Node.js 20 or newer for the frontend placeholder

Install uv if needed:

brew install uv

or:

curl -LsSf https://astral.sh/uv/install.sh | sh

Setup

  1. Create your local environment file:

    cp .env.example .env
  2. Install Python dependencies:

    uv sync --extra dev
  3. Start PostgreSQL with pgvector:

    docker compose up -d postgres
  4. Apply database migrations:

    uv run alembic upgrade head
  5. Run the API:

    uv run uvicorn atlas_api.main:app --app-dir apps/api/src --reload
  6. Check the health endpoint:

    curl http://localhost:8000/health
  7. Try the versioned API:

    curl http://localhost:8000/api/v1/notes
  8. Run tests:

    uv run pytest

Embeddings and Retrieval

Atlas defaults to deterministic fake embeddings so local development and tests never make network calls. To use OpenAI embeddings, set these values in .env and re-index the documents whose embeddings should use the configured model:

EMBEDDING_PROVIDER=openaiOPENAI_API_KEY=your_api_keyEMBEDDING_MODEL=text-embedding-3-smallVECTOR_DIMENSIONS=1536

VECTOR_DIMENSIONS must match the output size requested from the embedding model. The OpenAI text-embedding-3-small default is 1536. /rag/search embeds the query and asks PostgreSQL with pgvector to rank matching chunks when search_mode is vector or hybrid.

Retrieval expands each request with deterministic query rewrites before search. The original query is always searched first, followed by fake-provider rewrites in local development and tests. Atlas searches every query, merges the results, deduplicates by chunk_id, keeps the highest similarity score for each chunk, and returns matched_queries metadata showing which queries retrieved it.

/rag/search and /rag/answer accept search_mode values of vector, keyword, and hybrid; hybrid is the default. Keyword search runs over chunk text and uses PostgreSQL full-text search in PostgreSQL-backed environments, with a small SQLite fallback for local tests. Hybrid search runs vector and keyword search independently, merges the result sets, deduplicates by chunk_id, and ranks with reciprocal rank fusion: each source contributes 1 / (60 + rank) and chunks found by both sources move up. Results preserve source_name, collection, section, chunk_index, similarity_score, keyword_rank, and matched_by metadata.

Reranking is an optional second pass after retrieval. When enabled, Atlas first fetches top_k candidates with the selected search mode, scores each chunk against the original user query, sorts by reranker_score, keeps up to RERANKER_TOP_K, and removes chunks below RERANKER_SCORE_THRESHOLD. The fake provider is deterministic and local; no external reranker APIs are configured yet.

RERANKER_ENABLED=falseRERANKER_PROVIDER=fakeRERANKER_TOP_K=5RERANKER_SCORE_THRESHOLD=0.80

To run PostgreSQL integration coverage, point ATLAS_TEST_DATABASE_URL at an isolated pgvector-enabled test database. It uses the fake provider and does not call OpenAI:

ATLAS_TEST_DATABASE_URL=postgresql+psycopg://atlas:atlas_dev_password@localhost:5432/atlas_test \
uv run pytest -m integration

Context Preview

POST /api/v1/rag/context-preview shows the exact context that a later answer generation step would receive. It performs retrieval and context assembly only; it does not call an LLM.

{
"query": "How does retrieval work?",
"top_k": 5,
"max_chunks": 3,
"similarity_score_threshold": 0.7
}

The response preserves retrieval rank and includes source and section metadata for each assembled chunk. max_chunks bounds prompt size after retrieval. A similarity_score_threshold excludes chunks below the supplied cosine similarity score. Higher thresholds reduce irrelevant context but can remove useful supporting detail; lower thresholds preserve recall but consume more of the eventual model context window. Keeping this assembly step separate makes the prompt inspectable before an LLM is introduced.

Answer Generation

POST /api/v1/rag/answer retrieves matching chunks, filters out scores below similarity_score_threshold (or ANSWER_SIMILARITY_SCORE_THRESHOLD), retains the highest-ranked chunks that fit ANSWER_CONTEXT_MAX_CHARACTERS, assembles their context, and generates an answer. Citations are generated from the exact selected chunks and returned separately from the answer text. The response also returns the selected retrieved_chunks so retrieval, keyword, and reranker metadata can be inspected.

{
"query": "How does retrieval work?",
"top_k": 5,
"collection": "learning"
}

LLM_PROVIDER=fake is the default and produces deterministic local answers. Set LLM_PROVIDER=openai and OPENAI_API_KEY to use the OpenAI provider; LLM_MODEL selects the model. The provider receives an instruction to answer only from the assembled context, while Atlas itself owns citations so source metadata is not mixed into the answer text.

If retrieval produces no chunks that meet the score threshold or fit the context budget, Atlas returns Insufficient context to answer the question. with an empty citation list and does not call the LLM. Provider call failures return HTTP 502 rather than a fabricated answer.

RAG Evals

Atlas includes a small public-safe RAG evaluation fixture at evals/rag_cases.json. Run it with fake providers from the repository root:

uv run python scripts/run_rag_evals.py

The harness creates an isolated in-memory app, seeds synthetic documents, calls /api/v1/rag/answer, checks expected cited sources and answer phrases, verifies no-context handling, and prints per-case pass/fail plus a final score. It does not call OpenAI by default.

Frontend Placeholder

The frontend is intentionally minimal:

cd apps/web
npm install
npm run dev

Then open http://localhost:3000.

Development Notes

  • Keep personal notes, PDFs, and uploaded files out of the repository.
  • Add only sanitized examples under examples/sample_docs/.
  • Keep /api/v1 in the router aggregator, not in individual route handlers.
  • Put backend HTTP handlers in the HTTP layer, business logic in services, data access behind repositories, and model-provider calls behind provider abstractions.
  • Add migrations before using PostgreSQL for production data.
  • Plain text, Markdown, and PDFs with extractable text are chunked and indexed. Other file types are stored as uploaded documents until an extractor exists.

License

MIT. See LICENSE.

About

Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - nir-jas/atlas: Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability. · GitHub
Skip to content

Repository files navigation

Atlas

Atlas is an open-source personal knowledge platform for learning AI Engineering. It starts as a small monorepo with a FastAPI backend, a Next.js frontend placeholder, PostgreSQL with pgvector through Docker Compose, and a testable Python service structure.

The repository intentionally contains no personal documents. Runtime uploads go under data/uploads/, and uploaded files are ignored by Git.

Repository Layout

apps/
api/ FastAPI backend
web/ Next.js frontend placeholder
docs/
architecture/ Architecture and setup notes
learning-notes/ Notes created while learning AI Engineering
evals/ Evaluation fixtures, prompts, and experiments
examples/
sample_docs/ Public sample documents only
scripts/ Local helper scripts
data/
uploads/ Local upload storage, ignored by Git

Prerequisites

  • Python 3.11 or newer
  • uv
  • Docker and Docker Compose
  • Node.js 20 or newer for the frontend placeholder

Install uv if needed:

brew install uv

or:

curl -LsSf https://astral.sh/uv/install.sh | sh

Setup

  1. Create your local environment file:

    cp .env.example .env
  2. Install Python dependencies:

    uv sync --extra dev
  3. Start PostgreSQL with pgvector:

    docker compose up -d postgres
  4. Apply database migrations:

    uv run alembic upgrade head
  5. Run the API:

    uv run uvicorn atlas_api.main:app --app-dir apps/api/src --reload
  6. Check the health endpoint:

    curl http://localhost:8000/health
  7. Try the versioned API:

    curl http://localhost:8000/api/v1/notes
  8. Run tests:

    uv run pytest

Embeddings and Retrieval

Atlas defaults to deterministic fake embeddings so local development and tests never make network calls. To use OpenAI embeddings, set these values in .env and re-index the documents whose embeddings should use the configured model:

EMBEDDING_PROVIDER=openaiOPENAI_API_KEY=your_api_keyEMBEDDING_MODEL=text-embedding-3-smallVECTOR_DIMENSIONS=1536

VECTOR_DIMENSIONS must match the output size requested from the embedding model. The OpenAI text-embedding-3-small default is 1536. /rag/search embeds the query and asks PostgreSQL with pgvector to rank matching chunks when search_mode is vector or hybrid.

Retrieval expands each request with deterministic query rewrites before search. The original query is always searched first, followed by fake-provider rewrites in local development and tests. Atlas searches every query, merges the results, deduplicates by chunk_id, keeps the highest similarity score for each chunk, and returns matched_queries metadata showing which queries retrieved it.

/rag/search and /rag/answer accept search_mode values of vector, keyword, and hybrid; hybrid is the default. Keyword search runs over chunk text and uses PostgreSQL full-text search in PostgreSQL-backed environments, with a small SQLite fallback for local tests. Hybrid search runs vector and keyword search independently, merges the result sets, deduplicates by chunk_id, and ranks with reciprocal rank fusion: each source contributes 1 / (60 + rank) and chunks found by both sources move up. Results preserve source_name, collection, section, chunk_index, similarity_score, keyword_rank, and matched_by metadata.

Reranking is an optional second pass after retrieval. When enabled, Atlas first fetches top_k candidates with the selected search mode, scores each chunk against the original user query, sorts by reranker_score, keeps up to RERANKER_TOP_K, and removes chunks below RERANKER_SCORE_THRESHOLD. The fake provider is deterministic and local; no external reranker APIs are configured yet.

RERANKER_ENABLED=falseRERANKER_PROVIDER=fakeRERANKER_TOP_K=5RERANKER_SCORE_THRESHOLD=0.80

To run PostgreSQL integration coverage, point ATLAS_TEST_DATABASE_URL at an isolated pgvector-enabled test database. It uses the fake provider and does not call OpenAI:

ATLAS_TEST_DATABASE_URL=postgresql+psycopg://atlas:atlas_dev_password@localhost:5432/atlas_test \
uv run pytest -m integration

Context Preview

POST /api/v1/rag/context-preview shows the exact context that a later answer generation step would receive. It performs retrieval and context assembly only; it does not call an LLM.

{
"query": "How does retrieval work?",
"top_k": 5,
"max_chunks": 3,
"similarity_score_threshold": 0.7
}

The response preserves retrieval rank and includes source and section metadata for each assembled chunk. max_chunks bounds prompt size after retrieval. A similarity_score_threshold excludes chunks below the supplied cosine similarity score. Higher thresholds reduce irrelevant context but can remove useful supporting detail; lower thresholds preserve recall but consume more of the eventual model context window. Keeping this assembly step separate makes the prompt inspectable before an LLM is introduced.

Answer Generation

POST /api/v1/rag/answer retrieves matching chunks, filters out scores below similarity_score_threshold (or ANSWER_SIMILARITY_SCORE_THRESHOLD), retains the highest-ranked chunks that fit ANSWER_CONTEXT_MAX_CHARACTERS, assembles their context, and generates an answer. Citations are generated from the exact selected chunks and returned separately from the answer text. The response also returns the selected retrieved_chunks so retrieval, keyword, and reranker metadata can be inspected.

{
"query": "How does retrieval work?",
"top_k": 5,
"collection": "learning"
}

LLM_PROVIDER=fake is the default and produces deterministic local answers. Set LLM_PROVIDER=openai and OPENAI_API_KEY to use the OpenAI provider; LLM_MODEL selects the model. The provider receives an instruction to answer only from the assembled context, while Atlas itself owns citations so source metadata is not mixed into the answer text.

If retrieval produces no chunks that meet the score threshold or fit the context budget, Atlas returns Insufficient context to answer the question. with an empty citation list and does not call the LLM. Provider call failures return HTTP 502 rather than a fabricated answer.

RAG Evals

Atlas includes a small public-safe RAG evaluation fixture at evals/rag_cases.json. Run it with fake providers from the repository root:

uv run python scripts/run_rag_evals.py

The harness creates an isolated in-memory app, seeds synthetic documents, calls /api/v1/rag/answer, checks expected cited sources and answer phrases, verifies no-context handling, and prints per-case pass/fail plus a final score. It does not call OpenAI by default.

Frontend Placeholder

The frontend is intentionally minimal:

cd apps/web
npm install
npm run dev

Then open http://localhost:3000.

Development Notes

  • Keep personal notes, PDFs, and uploaded files out of the repository.
  • Add only sanitized examples under examples/sample_docs/.
  • Keep /api/v1 in the router aggregator, not in individual route handlers.
  • Put backend HTTP handlers in the HTTP layer, business logic in services, data access behind repositories, and model-provider calls behind provider abstractions.
  • Add migrations before using PostgreSQL for production data.
  • Plain text, Markdown, and PDFs with extractable text are chunked and indexed. Other file types are stored as uploaded documents until an extractor exists.

License

MIT. See LICENSE.

About

Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - nir-jas/atlas: Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability. · GitHub
Skip to content

Repository files navigation

Atlas

Atlas is an open-source personal knowledge platform for learning AI Engineering. It starts as a small monorepo with a FastAPI backend, a Next.js frontend placeholder, PostgreSQL with pgvector through Docker Compose, and a testable Python service structure.

The repository intentionally contains no personal documents. Runtime uploads go under data/uploads/, and uploaded files are ignored by Git.

Repository Layout

apps/
api/ FastAPI backend
web/ Next.js frontend placeholder
docs/
architecture/ Architecture and setup notes
learning-notes/ Notes created while learning AI Engineering
evals/ Evaluation fixtures, prompts, and experiments
examples/
sample_docs/ Public sample documents only
scripts/ Local helper scripts
data/
uploads/ Local upload storage, ignored by Git

Prerequisites

  • Python 3.11 or newer
  • uv
  • Docker and Docker Compose
  • Node.js 20 or newer for the frontend placeholder

Install uv if needed:

brew install uv

or:

curl -LsSf https://astral.sh/uv/install.sh | sh

Setup

  1. Create your local environment file:

    cp .env.example .env
  2. Install Python dependencies:

    uv sync --extra dev
  3. Start PostgreSQL with pgvector:

    docker compose up -d postgres
  4. Apply database migrations:

    uv run alembic upgrade head
  5. Run the API:

    uv run uvicorn atlas_api.main:app --app-dir apps/api/src --reload
  6. Check the health endpoint:

    curl http://localhost:8000/health
  7. Try the versioned API:

    curl http://localhost:8000/api/v1/notes
  8. Run tests:

    uv run pytest

Embeddings and Retrieval

Atlas defaults to deterministic fake embeddings so local development and tests never make network calls. To use OpenAI embeddings, set these values in .env and re-index the documents whose embeddings should use the configured model:

EMBEDDING_PROVIDER=openaiOPENAI_API_KEY=your_api_keyEMBEDDING_MODEL=text-embedding-3-smallVECTOR_DIMENSIONS=1536

VECTOR_DIMENSIONS must match the output size requested from the embedding model. The OpenAI text-embedding-3-small default is 1536. /rag/search embeds the query and asks PostgreSQL with pgvector to rank matching chunks when search_mode is vector or hybrid.

Retrieval expands each request with deterministic query rewrites before search. The original query is always searched first, followed by fake-provider rewrites in local development and tests. Atlas searches every query, merges the results, deduplicates by chunk_id, keeps the highest similarity score for each chunk, and returns matched_queries metadata showing which queries retrieved it.

/rag/search and /rag/answer accept search_mode values of vector, keyword, and hybrid; hybrid is the default. Keyword search runs over chunk text and uses PostgreSQL full-text search in PostgreSQL-backed environments, with a small SQLite fallback for local tests. Hybrid search runs vector and keyword search independently, merges the result sets, deduplicates by chunk_id, and ranks with reciprocal rank fusion: each source contributes 1 / (60 + rank) and chunks found by both sources move up. Results preserve source_name, collection, section, chunk_index, similarity_score, keyword_rank, and matched_by metadata.

Reranking is an optional second pass after retrieval. When enabled, Atlas first fetches top_k candidates with the selected search mode, scores each chunk against the original user query, sorts by reranker_score, keeps up to RERANKER_TOP_K, and removes chunks below RERANKER_SCORE_THRESHOLD. The fake provider is deterministic and local; no external reranker APIs are configured yet.

RERANKER_ENABLED=falseRERANKER_PROVIDER=fakeRERANKER_TOP_K=5RERANKER_SCORE_THRESHOLD=0.80

To run PostgreSQL integration coverage, point ATLAS_TEST_DATABASE_URL at an isolated pgvector-enabled test database. It uses the fake provider and does not call OpenAI:

ATLAS_TEST_DATABASE_URL=postgresql+psycopg://atlas:atlas_dev_password@localhost:5432/atlas_test \
uv run pytest -m integration

Context Preview

POST /api/v1/rag/context-preview shows the exact context that a later answer generation step would receive. It performs retrieval and context assembly only; it does not call an LLM.

{
"query": "How does retrieval work?",
"top_k": 5,
"max_chunks": 3,
"similarity_score_threshold": 0.7
}

The response preserves retrieval rank and includes source and section metadata for each assembled chunk. max_chunks bounds prompt size after retrieval. A similarity_score_threshold excludes chunks below the supplied cosine similarity score. Higher thresholds reduce irrelevant context but can remove useful supporting detail; lower thresholds preserve recall but consume more of the eventual model context window. Keeping this assembly step separate makes the prompt inspectable before an LLM is introduced.

Answer Generation

POST /api/v1/rag/answer retrieves matching chunks, filters out scores below similarity_score_threshold (or ANSWER_SIMILARITY_SCORE_THRESHOLD), retains the highest-ranked chunks that fit ANSWER_CONTEXT_MAX_CHARACTERS, assembles their context, and generates an answer. Citations are generated from the exact selected chunks and returned separately from the answer text. The response also returns the selected retrieved_chunks so retrieval, keyword, and reranker metadata can be inspected.

{
"query": "How does retrieval work?",
"top_k": 5,
"collection": "learning"
}

LLM_PROVIDER=fake is the default and produces deterministic local answers. Set LLM_PROVIDER=openai and OPENAI_API_KEY to use the OpenAI provider; LLM_MODEL selects the model. The provider receives an instruction to answer only from the assembled context, while Atlas itself owns citations so source metadata is not mixed into the answer text.

If retrieval produces no chunks that meet the score threshold or fit the context budget, Atlas returns Insufficient context to answer the question. with an empty citation list and does not call the LLM. Provider call failures return HTTP 502 rather than a fabricated answer.

RAG Evals

Atlas includes a small public-safe RAG evaluation fixture at evals/rag_cases.json. Run it with fake providers from the repository root:

uv run python scripts/run_rag_evals.py

The harness creates an isolated in-memory app, seeds synthetic documents, calls /api/v1/rag/answer, checks expected cited sources and answer phrases, verifies no-context handling, and prints per-case pass/fail plus a final score. It does not call OpenAI by default.

Frontend Placeholder

The frontend is intentionally minimal:

cd apps/web
npm install
npm run dev

Then open http://localhost:3000.

Development Notes

  • Keep personal notes, PDFs, and uploaded files out of the repository.
  • Add only sanitized examples under examples/sample_docs/.
  • Keep /api/v1 in the router aggregator, not in individual route handlers.
  • Put backend HTTP handlers in the HTTP layer, business logic in services, data access behind repositories, and model-provider calls behind provider abstractions.
  • Add migrations before using PostgreSQL for production data.
  • Plain text, Markdown, and PDFs with extractable text are chunked and indexed. Other file types are stored as uploaded documents until an extractor exists.

License

MIT. See LICENSE.

About

Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - nir-jas/atlas: Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability. · GitHub
Skip to content

Repository files navigation

Atlas

Atlas is an open-source personal knowledge platform for learning AI Engineering. It starts as a small monorepo with a FastAPI backend, a Next.js frontend placeholder, PostgreSQL with pgvector through Docker Compose, and a testable Python service structure.

The repository intentionally contains no personal documents. Runtime uploads go under data/uploads/, and uploaded files are ignored by Git.

Repository Layout

apps/
api/ FastAPI backend
web/ Next.js frontend placeholder
docs/
architecture/ Architecture and setup notes
learning-notes/ Notes created while learning AI Engineering
evals/ Evaluation fixtures, prompts, and experiments
examples/
sample_docs/ Public sample documents only
scripts/ Local helper scripts
data/
uploads/ Local upload storage, ignored by Git

Prerequisites

  • Python 3.11 or newer
  • uv
  • Docker and Docker Compose
  • Node.js 20 or newer for the frontend placeholder

Install uv if needed:

brew install uv

or:

curl -LsSf https://astral.sh/uv/install.sh | sh

Setup

  1. Create your local environment file:

    cp .env.example .env
  2. Install Python dependencies:

    uv sync --extra dev
  3. Start PostgreSQL with pgvector:

    docker compose up -d postgres
  4. Apply database migrations:

    uv run alembic upgrade head
  5. Run the API:

    uv run uvicorn atlas_api.main:app --app-dir apps/api/src --reload
  6. Check the health endpoint:

    curl http://localhost:8000/health
  7. Try the versioned API:

    curl http://localhost:8000/api/v1/notes
  8. Run tests:

    uv run pytest

Embeddings and Retrieval

Atlas defaults to deterministic fake embeddings so local development and tests never make network calls. To use OpenAI embeddings, set these values in .env and re-index the documents whose embeddings should use the configured model:

EMBEDDING_PROVIDER=openaiOPENAI_API_KEY=your_api_keyEMBEDDING_MODEL=text-embedding-3-smallVECTOR_DIMENSIONS=1536

VECTOR_DIMENSIONS must match the output size requested from the embedding model. The OpenAI text-embedding-3-small default is 1536. /rag/search embeds the query and asks PostgreSQL with pgvector to rank matching chunks when search_mode is vector or hybrid.

Retrieval expands each request with deterministic query rewrites before search. The original query is always searched first, followed by fake-provider rewrites in local development and tests. Atlas searches every query, merges the results, deduplicates by chunk_id, keeps the highest similarity score for each chunk, and returns matched_queries metadata showing which queries retrieved it.

/rag/search and /rag/answer accept search_mode values of vector, keyword, and hybrid; hybrid is the default. Keyword search runs over chunk text and uses PostgreSQL full-text search in PostgreSQL-backed environments, with a small SQLite fallback for local tests. Hybrid search runs vector and keyword search independently, merges the result sets, deduplicates by chunk_id, and ranks with reciprocal rank fusion: each source contributes 1 / (60 + rank) and chunks found by both sources move up. Results preserve source_name, collection, section, chunk_index, similarity_score, keyword_rank, and matched_by metadata.

Reranking is an optional second pass after retrieval. When enabled, Atlas first fetches top_k candidates with the selected search mode, scores each chunk against the original user query, sorts by reranker_score, keeps up to RERANKER_TOP_K, and removes chunks below RERANKER_SCORE_THRESHOLD. The fake provider is deterministic and local; no external reranker APIs are configured yet.

RERANKER_ENABLED=falseRERANKER_PROVIDER=fakeRERANKER_TOP_K=5RERANKER_SCORE_THRESHOLD=0.80

To run PostgreSQL integration coverage, point ATLAS_TEST_DATABASE_URL at an isolated pgvector-enabled test database. It uses the fake provider and does not call OpenAI:

ATLAS_TEST_DATABASE_URL=postgresql+psycopg://atlas:atlas_dev_password@localhost:5432/atlas_test \
uv run pytest -m integration

Context Preview

POST /api/v1/rag/context-preview shows the exact context that a later answer generation step would receive. It performs retrieval and context assembly only; it does not call an LLM.

{
"query": "How does retrieval work?",
"top_k": 5,
"max_chunks": 3,
"similarity_score_threshold": 0.7
}

The response preserves retrieval rank and includes source and section metadata for each assembled chunk. max_chunks bounds prompt size after retrieval. A similarity_score_threshold excludes chunks below the supplied cosine similarity score. Higher thresholds reduce irrelevant context but can remove useful supporting detail; lower thresholds preserve recall but consume more of the eventual model context window. Keeping this assembly step separate makes the prompt inspectable before an LLM is introduced.

Answer Generation

POST /api/v1/rag/answer retrieves matching chunks, filters out scores below similarity_score_threshold (or ANSWER_SIMILARITY_SCORE_THRESHOLD), retains the highest-ranked chunks that fit ANSWER_CONTEXT_MAX_CHARACTERS, assembles their context, and generates an answer. Citations are generated from the exact selected chunks and returned separately from the answer text. The response also returns the selected retrieved_chunks so retrieval, keyword, and reranker metadata can be inspected.

{
"query": "How does retrieval work?",
"top_k": 5,
"collection": "learning"
}

LLM_PROVIDER=fake is the default and produces deterministic local answers. Set LLM_PROVIDER=openai and OPENAI_API_KEY to use the OpenAI provider; LLM_MODEL selects the model. The provider receives an instruction to answer only from the assembled context, while Atlas itself owns citations so source metadata is not mixed into the answer text.

If retrieval produces no chunks that meet the score threshold or fit the context budget, Atlas returns Insufficient context to answer the question. with an empty citation list and does not call the LLM. Provider call failures return HTTP 502 rather than a fabricated answer.

RAG Evals

Atlas includes a small public-safe RAG evaluation fixture at evals/rag_cases.json. Run it with fake providers from the repository root:

uv run python scripts/run_rag_evals.py

The harness creates an isolated in-memory app, seeds synthetic documents, calls /api/v1/rag/answer, checks expected cited sources and answer phrases, verifies no-context handling, and prints per-case pass/fail plus a final score. It does not call OpenAI by default.

Frontend Placeholder

The frontend is intentionally minimal:

cd apps/web
npm install
npm run dev

Then open http://localhost:3000.

Development Notes

  • Keep personal notes, PDFs, and uploaded files out of the repository.
  • Add only sanitized examples under examples/sample_docs/.
  • Keep /api/v1 in the router aggregator, not in individual route handlers.
  • Put backend HTTP handlers in the HTTP layer, business logic in services, data access behind repositories, and model-provider calls behind provider abstractions.
  • Add migrations before using PostgreSQL for production data.
  • Plain text, Markdown, and PDFs with extractable text are chunked and indexed. Other file types are stored as uploaded documents until an extractor exists.

License

MIT. See LICENSE.

About

Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - nir-jas/atlas: Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability. · GitHub
Skip to content

Repository files navigation

Atlas

Atlas is an open-source personal knowledge platform for learning AI Engineering. It starts as a small monorepo with a FastAPI backend, a Next.js frontend placeholder, PostgreSQL with pgvector through Docker Compose, and a testable Python service structure.

The repository intentionally contains no personal documents. Runtime uploads go under data/uploads/, and uploaded files are ignored by Git.

Repository Layout

apps/
api/ FastAPI backend
web/ Next.js frontend placeholder
docs/
architecture/ Architecture and setup notes
learning-notes/ Notes created while learning AI Engineering
evals/ Evaluation fixtures, prompts, and experiments
examples/
sample_docs/ Public sample documents only
scripts/ Local helper scripts
data/
uploads/ Local upload storage, ignored by Git

Prerequisites

  • Python 3.11 or newer
  • uv
  • Docker and Docker Compose
  • Node.js 20 or newer for the frontend placeholder

Install uv if needed:

brew install uv

or:

curl -LsSf https://astral.sh/uv/install.sh | sh

Setup

  1. Create your local environment file:

    cp .env.example .env
  2. Install Python dependencies:

    uv sync --extra dev
  3. Start PostgreSQL with pgvector:

    docker compose up -d postgres
  4. Apply database migrations:

    uv run alembic upgrade head
  5. Run the API:

    uv run uvicorn atlas_api.main:app --app-dir apps/api/src --reload
  6. Check the health endpoint:

    curl http://localhost:8000/health
  7. Try the versioned API:

    curl http://localhost:8000/api/v1/notes
  8. Run tests:

    uv run pytest

Embeddings and Retrieval

Atlas defaults to deterministic fake embeddings so local development and tests never make network calls. To use OpenAI embeddings, set these values in .env and re-index the documents whose embeddings should use the configured model:

EMBEDDING_PROVIDER=openaiOPENAI_API_KEY=your_api_keyEMBEDDING_MODEL=text-embedding-3-smallVECTOR_DIMENSIONS=1536

VECTOR_DIMENSIONS must match the output size requested from the embedding model. The OpenAI text-embedding-3-small default is 1536. /rag/search embeds the query and asks PostgreSQL with pgvector to rank matching chunks when search_mode is vector or hybrid.

Retrieval expands each request with deterministic query rewrites before search. The original query is always searched first, followed by fake-provider rewrites in local development and tests. Atlas searches every query, merges the results, deduplicates by chunk_id, keeps the highest similarity score for each chunk, and returns matched_queries metadata showing which queries retrieved it.

/rag/search and /rag/answer accept search_mode values of vector, keyword, and hybrid; hybrid is the default. Keyword search runs over chunk text and uses PostgreSQL full-text search in PostgreSQL-backed environments, with a small SQLite fallback for local tests. Hybrid search runs vector and keyword search independently, merges the result sets, deduplicates by chunk_id, and ranks with reciprocal rank fusion: each source contributes 1 / (60 + rank) and chunks found by both sources move up. Results preserve source_name, collection, section, chunk_index, similarity_score, keyword_rank, and matched_by metadata.

Reranking is an optional second pass after retrieval. When enabled, Atlas first fetches top_k candidates with the selected search mode, scores each chunk against the original user query, sorts by reranker_score, keeps up to RERANKER_TOP_K, and removes chunks below RERANKER_SCORE_THRESHOLD. The fake provider is deterministic and local; no external reranker APIs are configured yet.

RERANKER_ENABLED=falseRERANKER_PROVIDER=fakeRERANKER_TOP_K=5RERANKER_SCORE_THRESHOLD=0.80

To run PostgreSQL integration coverage, point ATLAS_TEST_DATABASE_URL at an isolated pgvector-enabled test database. It uses the fake provider and does not call OpenAI:

ATLAS_TEST_DATABASE_URL=postgresql+psycopg://atlas:atlas_dev_password@localhost:5432/atlas_test \
uv run pytest -m integration

Context Preview

POST /api/v1/rag/context-preview shows the exact context that a later answer generation step would receive. It performs retrieval and context assembly only; it does not call an LLM.

{
"query": "How does retrieval work?",
"top_k": 5,
"max_chunks": 3,
"similarity_score_threshold": 0.7
}

The response preserves retrieval rank and includes source and section metadata for each assembled chunk. max_chunks bounds prompt size after retrieval. A similarity_score_threshold excludes chunks below the supplied cosine similarity score. Higher thresholds reduce irrelevant context but can remove useful supporting detail; lower thresholds preserve recall but consume more of the eventual model context window. Keeping this assembly step separate makes the prompt inspectable before an LLM is introduced.

Answer Generation

POST /api/v1/rag/answer retrieves matching chunks, filters out scores below similarity_score_threshold (or ANSWER_SIMILARITY_SCORE_THRESHOLD), retains the highest-ranked chunks that fit ANSWER_CONTEXT_MAX_CHARACTERS, assembles their context, and generates an answer. Citations are generated from the exact selected chunks and returned separately from the answer text. The response also returns the selected retrieved_chunks so retrieval, keyword, and reranker metadata can be inspected.

{
"query": "How does retrieval work?",
"top_k": 5,
"collection": "learning"
}

LLM_PROVIDER=fake is the default and produces deterministic local answers. Set LLM_PROVIDER=openai and OPENAI_API_KEY to use the OpenAI provider; LLM_MODEL selects the model. The provider receives an instruction to answer only from the assembled context, while Atlas itself owns citations so source metadata is not mixed into the answer text.

If retrieval produces no chunks that meet the score threshold or fit the context budget, Atlas returns Insufficient context to answer the question. with an empty citation list and does not call the LLM. Provider call failures return HTTP 502 rather than a fabricated answer.

RAG Evals

Atlas includes a small public-safe RAG evaluation fixture at evals/rag_cases.json. Run it with fake providers from the repository root:

uv run python scripts/run_rag_evals.py

The harness creates an isolated in-memory app, seeds synthetic documents, calls /api/v1/rag/answer, checks expected cited sources and answer phrases, verifies no-context handling, and prints per-case pass/fail plus a final score. It does not call OpenAI by default.

Frontend Placeholder

The frontend is intentionally minimal:

cd apps/web
npm install
npm run dev

Then open http://localhost:3000.

Development Notes

  • Keep personal notes, PDFs, and uploaded files out of the repository.
  • Add only sanitized examples under examples/sample_docs/.
  • Keep /api/v1 in the router aggregator, not in individual route handlers.
  • Put backend HTTP handlers in the HTTP layer, business logic in services, data access behind repositories, and model-provider calls behind provider abstractions.
  • Add migrations before using PostgreSQL for production data.
  • Plain text, Markdown, and PDFs with extractable text are chunked and indexed. Other file types are stored as uploaded documents until an extractor exists.

License

MIT. See LICENSE.

About

Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - nir-jas/atlas: Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability. · GitHub
Skip to content

Repository files navigation

Atlas

Atlas is an open-source personal knowledge platform for learning AI Engineering. It starts as a small monorepo with a FastAPI backend, a Next.js frontend placeholder, PostgreSQL with pgvector through Docker Compose, and a testable Python service structure.

The repository intentionally contains no personal documents. Runtime uploads go under data/uploads/, and uploaded files are ignored by Git.

Repository Layout

apps/
api/ FastAPI backend
web/ Next.js frontend placeholder
docs/
architecture/ Architecture and setup notes
learning-notes/ Notes created while learning AI Engineering
evals/ Evaluation fixtures, prompts, and experiments
examples/
sample_docs/ Public sample documents only
scripts/ Local helper scripts
data/
uploads/ Local upload storage, ignored by Git

Prerequisites

  • Python 3.11 or newer
  • uv
  • Docker and Docker Compose
  • Node.js 20 or newer for the frontend placeholder

Install uv if needed:

brew install uv

or:

curl -LsSf https://astral.sh/uv/install.sh | sh

Setup

  1. Create your local environment file:

    cp .env.example .env
  2. Install Python dependencies:

    uv sync --extra dev
  3. Start PostgreSQL with pgvector:

    docker compose up -d postgres
  4. Apply database migrations:

    uv run alembic upgrade head
  5. Run the API:

    uv run uvicorn atlas_api.main:app --app-dir apps/api/src --reload
  6. Check the health endpoint:

    curl http://localhost:8000/health
  7. Try the versioned API:

    curl http://localhost:8000/api/v1/notes
  8. Run tests:

    uv run pytest

Embeddings and Retrieval

Atlas defaults to deterministic fake embeddings so local development and tests never make network calls. To use OpenAI embeddings, set these values in .env and re-index the documents whose embeddings should use the configured model:

EMBEDDING_PROVIDER=openaiOPENAI_API_KEY=your_api_keyEMBEDDING_MODEL=text-embedding-3-smallVECTOR_DIMENSIONS=1536

VECTOR_DIMENSIONS must match the output size requested from the embedding model. The OpenAI text-embedding-3-small default is 1536. /rag/search embeds the query and asks PostgreSQL with pgvector to rank matching chunks when search_mode is vector or hybrid.

Retrieval expands each request with deterministic query rewrites before search. The original query is always searched first, followed by fake-provider rewrites in local development and tests. Atlas searches every query, merges the results, deduplicates by chunk_id, keeps the highest similarity score for each chunk, and returns matched_queries metadata showing which queries retrieved it.

/rag/search and /rag/answer accept search_mode values of vector, keyword, and hybrid; hybrid is the default. Keyword search runs over chunk text and uses PostgreSQL full-text search in PostgreSQL-backed environments, with a small SQLite fallback for local tests. Hybrid search runs vector and keyword search independently, merges the result sets, deduplicates by chunk_id, and ranks with reciprocal rank fusion: each source contributes 1 / (60 + rank) and chunks found by both sources move up. Results preserve source_name, collection, section, chunk_index, similarity_score, keyword_rank, and matched_by metadata.

Reranking is an optional second pass after retrieval. When enabled, Atlas first fetches top_k candidates with the selected search mode, scores each chunk against the original user query, sorts by reranker_score, keeps up to RERANKER_TOP_K, and removes chunks below RERANKER_SCORE_THRESHOLD. The fake provider is deterministic and local; no external reranker APIs are configured yet.

RERANKER_ENABLED=falseRERANKER_PROVIDER=fakeRERANKER_TOP_K=5RERANKER_SCORE_THRESHOLD=0.80

To run PostgreSQL integration coverage, point ATLAS_TEST_DATABASE_URL at an isolated pgvector-enabled test database. It uses the fake provider and does not call OpenAI:

ATLAS_TEST_DATABASE_URL=postgresql+psycopg://atlas:atlas_dev_password@localhost:5432/atlas_test \
uv run pytest -m integration

Context Preview

POST /api/v1/rag/context-preview shows the exact context that a later answer generation step would receive. It performs retrieval and context assembly only; it does not call an LLM.

{
"query": "How does retrieval work?",
"top_k": 5,
"max_chunks": 3,
"similarity_score_threshold": 0.7
}

The response preserves retrieval rank and includes source and section metadata for each assembled chunk. max_chunks bounds prompt size after retrieval. A similarity_score_threshold excludes chunks below the supplied cosine similarity score. Higher thresholds reduce irrelevant context but can remove useful supporting detail; lower thresholds preserve recall but consume more of the eventual model context window. Keeping this assembly step separate makes the prompt inspectable before an LLM is introduced.

Answer Generation

POST /api/v1/rag/answer retrieves matching chunks, filters out scores below similarity_score_threshold (or ANSWER_SIMILARITY_SCORE_THRESHOLD), retains the highest-ranked chunks that fit ANSWER_CONTEXT_MAX_CHARACTERS, assembles their context, and generates an answer. Citations are generated from the exact selected chunks and returned separately from the answer text. The response also returns the selected retrieved_chunks so retrieval, keyword, and reranker metadata can be inspected.

{
"query": "How does retrieval work?",
"top_k": 5,
"collection": "learning"
}

LLM_PROVIDER=fake is the default and produces deterministic local answers. Set LLM_PROVIDER=openai and OPENAI_API_KEY to use the OpenAI provider; LLM_MODEL selects the model. The provider receives an instruction to answer only from the assembled context, while Atlas itself owns citations so source metadata is not mixed into the answer text.

If retrieval produces no chunks that meet the score threshold or fit the context budget, Atlas returns Insufficient context to answer the question. with an empty citation list and does not call the LLM. Provider call failures return HTTP 502 rather than a fabricated answer.

RAG Evals

Atlas includes a small public-safe RAG evaluation fixture at evals/rag_cases.json. Run it with fake providers from the repository root:

uv run python scripts/run_rag_evals.py

The harness creates an isolated in-memory app, seeds synthetic documents, calls /api/v1/rag/answer, checks expected cited sources and answer phrases, verifies no-context handling, and prints per-case pass/fail plus a final score. It does not call OpenAI by default.

Frontend Placeholder

The frontend is intentionally minimal:

cd apps/web
npm install
npm run dev

Then open http://localhost:3000.

Development Notes

  • Keep personal notes, PDFs, and uploaded files out of the repository.
  • Add only sanitized examples under examples/sample_docs/.
  • Keep /api/v1 in the router aggregator, not in individual route handlers.
  • Put backend HTTP handlers in the HTTP layer, business logic in services, data access behind repositories, and model-provider calls behind provider abstractions.
  • Add migrations before using PostgreSQL for production data.
  • Plain text, Markdown, and PDFs with extractable text are chunked and indexed. Other file types are stored as uploaded documents until an extractor exists.

License

MIT. See LICENSE.

About

Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - nir-jas/atlas: Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability. · GitHub
Skip to content

Repository files navigation

Atlas

Atlas is an open-source personal knowledge platform for learning AI Engineering. It starts as a small monorepo with a FastAPI backend, a Next.js frontend placeholder, PostgreSQL with pgvector through Docker Compose, and a testable Python service structure.

The repository intentionally contains no personal documents. Runtime uploads go under data/uploads/, and uploaded files are ignored by Git.

Repository Layout

apps/
api/ FastAPI backend
web/ Next.js frontend placeholder
docs/
architecture/ Architecture and setup notes
learning-notes/ Notes created while learning AI Engineering
evals/ Evaluation fixtures, prompts, and experiments
examples/
sample_docs/ Public sample documents only
scripts/ Local helper scripts
data/
uploads/ Local upload storage, ignored by Git

Prerequisites

  • Python 3.11 or newer
  • uv
  • Docker and Docker Compose
  • Node.js 20 or newer for the frontend placeholder

Install uv if needed:

brew install uv

or:

curl -LsSf https://astral.sh/uv/install.sh | sh

Setup

  1. Create your local environment file:

    cp .env.example .env
  2. Install Python dependencies:

    uv sync --extra dev
  3. Start PostgreSQL with pgvector:

    docker compose up -d postgres
  4. Apply database migrations:

    uv run alembic upgrade head
  5. Run the API:

    uv run uvicorn atlas_api.main:app --app-dir apps/api/src --reload
  6. Check the health endpoint:

    curl http://localhost:8000/health
  7. Try the versioned API:

    curl http://localhost:8000/api/v1/notes
  8. Run tests:

    uv run pytest

Embeddings and Retrieval

Atlas defaults to deterministic fake embeddings so local development and tests never make network calls. To use OpenAI embeddings, set these values in .env and re-index the documents whose embeddings should use the configured model:

EMBEDDING_PROVIDER=openaiOPENAI_API_KEY=your_api_keyEMBEDDING_MODEL=text-embedding-3-smallVECTOR_DIMENSIONS=1536

VECTOR_DIMENSIONS must match the output size requested from the embedding model. The OpenAI text-embedding-3-small default is 1536. /rag/search embeds the query and asks PostgreSQL with pgvector to rank matching chunks when search_mode is vector or hybrid.

Retrieval expands each request with deterministic query rewrites before search. The original query is always searched first, followed by fake-provider rewrites in local development and tests. Atlas searches every query, merges the results, deduplicates by chunk_id, keeps the highest similarity score for each chunk, and returns matched_queries metadata showing which queries retrieved it.

/rag/search and /rag/answer accept search_mode values of vector, keyword, and hybrid; hybrid is the default. Keyword search runs over chunk text and uses PostgreSQL full-text search in PostgreSQL-backed environments, with a small SQLite fallback for local tests. Hybrid search runs vector and keyword search independently, merges the result sets, deduplicates by chunk_id, and ranks with reciprocal rank fusion: each source contributes 1 / (60 + rank) and chunks found by both sources move up. Results preserve source_name, collection, section, chunk_index, similarity_score, keyword_rank, and matched_by metadata.

Reranking is an optional second pass after retrieval. When enabled, Atlas first fetches top_k candidates with the selected search mode, scores each chunk against the original user query, sorts by reranker_score, keeps up to RERANKER_TOP_K, and removes chunks below RERANKER_SCORE_THRESHOLD. The fake provider is deterministic and local; no external reranker APIs are configured yet.

RERANKER_ENABLED=falseRERANKER_PROVIDER=fakeRERANKER_TOP_K=5RERANKER_SCORE_THRESHOLD=0.80

To run PostgreSQL integration coverage, point ATLAS_TEST_DATABASE_URL at an isolated pgvector-enabled test database. It uses the fake provider and does not call OpenAI:

ATLAS_TEST_DATABASE_URL=postgresql+psycopg://atlas:atlas_dev_password@localhost:5432/atlas_test \
uv run pytest -m integration

Context Preview

POST /api/v1/rag/context-preview shows the exact context that a later answer generation step would receive. It performs retrieval and context assembly only; it does not call an LLM.

{
"query": "How does retrieval work?",
"top_k": 5,
"max_chunks": 3,
"similarity_score_threshold": 0.7
}

The response preserves retrieval rank and includes source and section metadata for each assembled chunk. max_chunks bounds prompt size after retrieval. A similarity_score_threshold excludes chunks below the supplied cosine similarity score. Higher thresholds reduce irrelevant context but can remove useful supporting detail; lower thresholds preserve recall but consume more of the eventual model context window. Keeping this assembly step separate makes the prompt inspectable before an LLM is introduced.

Answer Generation

POST /api/v1/rag/answer retrieves matching chunks, filters out scores below similarity_score_threshold (or ANSWER_SIMILARITY_SCORE_THRESHOLD), retains the highest-ranked chunks that fit ANSWER_CONTEXT_MAX_CHARACTERS, assembles their context, and generates an answer. Citations are generated from the exact selected chunks and returned separately from the answer text. The response also returns the selected retrieved_chunks so retrieval, keyword, and reranker metadata can be inspected.

{
"query": "How does retrieval work?",
"top_k": 5,
"collection": "learning"
}

LLM_PROVIDER=fake is the default and produces deterministic local answers. Set LLM_PROVIDER=openai and OPENAI_API_KEY to use the OpenAI provider; LLM_MODEL selects the model. The provider receives an instruction to answer only from the assembled context, while Atlas itself owns citations so source metadata is not mixed into the answer text.

If retrieval produces no chunks that meet the score threshold or fit the context budget, Atlas returns Insufficient context to answer the question. with an empty citation list and does not call the LLM. Provider call failures return HTTP 502 rather than a fabricated answer.

RAG Evals

Atlas includes a small public-safe RAG evaluation fixture at evals/rag_cases.json. Run it with fake providers from the repository root:

uv run python scripts/run_rag_evals.py

The harness creates an isolated in-memory app, seeds synthetic documents, calls /api/v1/rag/answer, checks expected cited sources and answer phrases, verifies no-context handling, and prints per-case pass/fail plus a final score. It does not call OpenAI by default.

Frontend Placeholder

The frontend is intentionally minimal:

cd apps/web
npm install
npm run dev

Then open http://localhost:3000.

Development Notes

  • Keep personal notes, PDFs, and uploaded files out of the repository.
  • Add only sanitized examples under examples/sample_docs/.
  • Keep /api/v1 in the router aggregator, not in individual route handlers.
  • Put backend HTTP handlers in the HTTP layer, business logic in services, data access behind repositories, and model-provider calls behind provider abstractions.
  • Add migrations before using PostgreSQL for production data.
  • Plain text, Markdown, and PDFs with extractable text are chunked and indexed. Other file types are stored as uploaded documents until an extractor exists.

License

MIT. See LICENSE.

About

Open-source personal knowledge platform for learning and building production-grade AI engineering systems with RAG, agents, evals, and observability.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages