Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
5410403
fix(retrieval): enable production node filter
suguanYang Sep 1, 2026
1b51db9
Merge pull request #378 from Ontos-AI/fix/wangbinqi/enable-node-filter
suguanYang Sep 1, 2026
05e1aaf
perf: optimize map-nav snapshot and scoring
suguanYang Sep 1, 2026
25c074c
fix: enforce snapshot generation and validation
suguanYang Sep 1, 2026
1223551
fix: harden map-nav snapshot cache
suguanYang Sep 1, 2026
6ed286d
perf: narrow map index frequency lookup
suguanYang Sep 1, 2026
a3ad93a
perf: avoid legacy job chunk hydration
suguanYang Sep 1, 2026
62f0804
Merge pull request #379 from Ontos-AI/perf/wangbinqi/map-nav-snapshot…
suguanYang Sep 1, 2026
79f169b
feat(retrieval): switch map-unit BM25 to word-level tokens
EricNGOntos Sep 2, 2026
667d021
Merge pull request #380 from Ontos-AI/feat/wuchengke/word-level-map-u…
EricNGOntos Sep 2, 2026
0e374bc
refactor(retrieval): remove legacy evidence rendering and implement n…
EricNGOntos Sep 2, 2026
f432972
Merge pull request #381 from Ontos-AI/feat/wuchengke/unify-evidence-a…
EricNGOntos Sep 2, 2026
05afe68
perf: persist per-channel map index statistics
suguanYang Sep 2, 2026
daefd1d
fix: preserve map index compatibility across filtered scopes
suguanYang Sep 2, 2026
9615a23
docs: reset parity benchmark after main rebase
suguanYang Sep 2, 2026
13c5735
chore: align retrieval helper naming
suguanYang Sep 2, 2026
5ec7295
docs: mark discarded local benchmark historical
suguanYang Sep 2, 2026
3566fc8
fix: stabilize persisted index aggregation order
suguanYang Sep 2, 2026
060613a
docs: define retrieval score parity tolerance
suguanYang Sep 2, 2026
f258270
revert: remove ineffective index ordering
suguanYang Sep 2, 2026
54a848b
docs: record restored dump parity benchmark
suguanYang Sep 2, 2026
882d5e1
feat: add map unit statistics backfill command
suguanYang Sep 2, 2026
aad2604
fix: support runtime backfill script paths
suguanYang Sep 2, 2026
462e64b
perf: reuse pinned revisions during discovery
suguanYang Sep 3, 2026
ff06455
docs: record revision pin reuse benchmark
suguanYang Sep 3, 2026
32c3e09
perf: read index metadata from revision pins
suguanYang Sep 3, 2026
d7f41fb
test: cover pinned index metadata parity
suguanYang Sep 3, 2026
8dc0b48
docs: document local agentic database ssl settings
suguanYang Sep 3, 2026
93dac29
perf: skip redundant map section scope scan
suguanYang Sep 3, 2026
db6ae64
perf: defer filtered map scope allocation
suguanYang Sep 3, 2026
ff33ba5
fix: preserve filtered map scope semantics
suguanYang Sep 3, 2026
689dde7
fix: format mapnav resource metrics
suguanYang Sep 3, 2026
abf0d28
fix: harden retrieval backfill readiness checks
suguanYang Sep 3, 2026
b32c4a5
docs: add retrieval serving index rollout runbook
suguanYang Sep 3, 2026
3c1248f
fix: preserve legacy retrieval on empty map-unit matches
suguanYang Sep 3, 2026
e59111b
fix: preserve retrieval semantics during statistics backfill
suguanYang Sep 3, 2026
662be67
Merge pull request #382 from Ontos-AI/perf/wangbinqi/retrieval-servin…
suguanYang Sep 3, 2026
6a1f825
fix: resolve statistics backfill runtime path
suguanYang Sep 3, 2026
671057d
Merge pull request #383 from Ontos-AI/fix/wangbinqi/statistics-backfi…
suguanYang Sep 3, 2026
3207a67
fix(worker): normalize encoded document filenames
suguanYang Sep 7, 2026
56f48b8
Merge pull request #386 from Ontos-AI/fix/wangbinqi/decode-upload-fil…
suguanYang Sep 7, 2026
c0a2442
chore: resolve staging and main migration conflicts
suguanYang Sep 7, 2026
2ad2035
fix: remove unused merge migration import
suguanYang Sep 7, 2026
988d541
Merge pull request #389 from Ontos-AI/fix/wangbinqi/resolve-staging-m…
suguanYang Sep 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,10 @@ generation and retries or falls back if publication changes it during capture.

The compatibility requirement that a serving-index retrieval returns the same
selected chunk IDs, ordering, rounded scores, citations, and asset references
as the legacy retrieval path for the same request.
as the legacy retrieval path for the same request. Every retrieval optimization
must preserve this quality contract; a latency improvement without validated
semantic parity is not shippable. Validation also compares source sections,
evidence content, router, and stop reason for each pinned request.

### Retrieval Revision Pin

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Add the token-leading covering index for map-unit lookups."""

from __future__ import annotations

from collections.abc import Sequence

from alembic import op


revision: str = "a0b1c2d3e4f5"
down_revision: str | None = "9f0a1b2c3d4e"
branch_labels: Sequence[str] | None = None
depends_on: Sequence[str] | None = None

_INDEX_NAME = "idx_document_map_unit_tokens_token_lookup"


def upgrade() -> None:
"""Create the additive index without taking a table-wide write lock."""
uses_external_transaction: bool = bool(
op.get_context().opts.get("knowhere_external_transaction", False)
)
statement: str = (
f"CREATE INDEX {{concurrently}}IF NOT EXISTS {_INDEX_NAME} "
"ON document_map_unit_tokens (channel, token_hash, map_unit_id) "
"INCLUDE (token, frequency)"
)
if uses_external_transaction:
op.execute(statement.format(concurrently=""))
return
with op.get_context().autocommit_block():
op.execute(statement.format(concurrently="CONCURRENTLY "))


def downgrade() -> None:
"""Remove only the index introduced by this migration."""
uses_external_transaction: bool = bool(
op.get_context().opts.get("knowhere_external_transaction", False)
)
if uses_external_transaction:
op.execute(f"DROP INDEX IF EXISTS {_INDEX_NAME}")
return
with op.get_context().autocommit_block():
op.execute(f"DROP INDEX CONCURRENTLY IF EXISTS {_INDEX_NAME}")
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Add persisted per-channel BM25 corpus statistics."""

from __future__ import annotations

from collections.abc import Sequence

from alembic import op


revision: str = "b1c2d3e4f5a6"
down_revision: str | None = "a0b1c2d3e4f5"
branch_labels: Sequence[str] | None = None
depends_on: Sequence[str] | None = None


def upgrade() -> None:
"""Add nullable statistics so incomplete legacy rows keep the fallback."""
column_names: tuple[str, ...] = (
"path_document_count",
"path_total_length",
"content_document_count",
"content_total_length",
)
for column_name in column_names:
op.execute(
f"ALTER TABLE document_map_unit_indexes "
f"ADD COLUMN IF NOT EXISTS {column_name} INTEGER"
)


def downgrade() -> None:
"""Remove the additive statistics columns."""
column_names: tuple[str, ...] = (
"content_total_length",
"content_document_count",
"path_total_length",
"path_document_count",
)
for column_name in column_names:
op.execute(
f"ALTER TABLE document_map_unit_indexes DROP COLUMN IF EXISTS {column_name}"
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Repair a missing or invalid token-leading map-unit covering index."""

from __future__ import annotations

from collections.abc import Sequence

from alembic import op
from sqlalchemy import text


revision: str = "c2d3e4f5a6b7"
down_revision: str | None = "b1c2d3e4f5a6"
branch_labels: Sequence[str] | None = None
depends_on: Sequence[str] | None = None

_INDEX_NAME = "idx_document_map_unit_tokens_token_lookup"
_INDEX_COLUMNS = "(channel, token_hash, map_unit_id) INCLUDE (token, frequency)"


def _is_index_ready() -> bool:
"""Return whether the current schema contains a usable covering index."""
is_ready = op.get_bind().execute(
text(
"SELECT indexes.indisvalid AND indexes.indisready "
"FROM pg_index AS indexes "
"JOIN pg_class AS classes ON classes.oid = indexes.indexrelid "
"JOIN pg_namespace AS namespaces "
"ON namespaces.oid = classes.relnamespace "
"WHERE namespaces.nspname = current_schema() "
"AND classes.relname = :index_name"
),
{"index_name": _INDEX_NAME},
).scalar_one_or_none()
return bool(is_ready)


def _repair_index(*, concurrently: bool) -> None:
"""Replace a missing or unusable index using the allowed DDL mode."""
if _is_index_ready():
return
concurrent_clause: str = "CONCURRENTLY " if concurrently else ""
op.execute(f"DROP INDEX {concurrent_clause}IF EXISTS {_INDEX_NAME}")
op.execute(
f"CREATE INDEX {concurrent_clause}{_INDEX_NAME} "
f"ON document_map_unit_tokens {_INDEX_COLUMNS}"
)


def upgrade() -> None:
"""Ensure the additive covering index exists and is usable."""
uses_external_transaction: bool = bool(
op.get_context().opts.get("knowhere_external_transaction", False)
)
if uses_external_transaction:
_repair_index(concurrently=False)
return
with op.get_context().autocommit_block():
_repair_index(concurrently=True)


def downgrade() -> None:
"""Keep the index owned by the preceding additive migration."""
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Merge the retrieval index migration branches."""

from __future__ import annotations

from collections.abc import Sequence

revision: str = "d3e4f5a6b7c8"
down_revision: tuple[str, str] = (
"0a1b2c3d4e5f",
"c2d3e4f5a6b7",
)
branch_labels: Sequence[str] | None = None
depends_on: Sequence[str] | None = None


def upgrade() -> None:
"""Merge migration heads without applying additional schema changes."""


def downgrade() -> None:
"""Split the migration graph back into its two parent heads."""
4 changes: 2 additions & 2 deletions apps/api/app/services/document_ingestion/creation_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from dataclasses import dataclass
from datetime import datetime, timezone
from typing import cast
from urllib.parse import urlparse
from urllib.parse import unquote, urlparse

from app.repositories.job_repository import JobRepository
from app.services.document_ingestion.command import DocumentIngestionCommand
Expand Down Expand Up @@ -308,7 +308,7 @@ def _build_job_response(

def _resolve_url_source_file_name(*, source_url: str, file_extension: str) -> str:
parsed_url = urlparse(source_url)
url_basename = str(os.path.basename(parsed_url.path))
url_basename = unquote(str(os.path.basename(parsed_url.path)))
if url_basename and os.path.splitext(url_basename)[1].lower() == file_extension:
return url_basename
if url_basename:
Expand Down
Loading
Loading