Files
unslothai--unsloth/studio/backend/tests/test_rag_store.py
T
wehub-resource-sync e93507a09c
Lockfile supply-chain audit / lockfile supply-chain audit (push) Has been cancelled
Windows Studio GGUF CI / GPU prebuilt resolves without Visual Studio (push) Has been cancelled
Windows Studio GGUF CI / setup.ps1 unit tests (VS 2026 / CMake guard) (push) Has been cancelled
Windows Studio GGUF CI / real-VS detection (VS 2022) (push) Has been cancelled
Windows Studio GGUF CI / real-VS detection (VS 2026) (push) Has been cancelled
Windows Studio GGUF CI / VC++ runtime detect + install round-trip (windows-2025-vs2026) (push) Has been cancelled
Windows Studio GGUF CI / VC++ runtime detect + install round-trip (windows-latest) (push) Has been cancelled
Windows Studio Update CI / Studio Updating Tests (push) Has been cancelled
Wheel CI / Wheel build + content sanity + import smoke (push) Has been cancelled
Lint CI / Source lint (Python + shell + YAML + JSON + safety nets) (push) Has been cancelled
MLX CI on Mac M1 / dispatch (push) Has been cancelled
Security audit / advisory audit (pip + npm + cargo) (push) Has been cancelled
Security audit / pip scan-packages :: extras (push) Has been cancelled
Security audit / pip scan-packages :: studio (push) Has been cancelled
Security audit / pip scan-packages :: hf-stack (push) Has been cancelled
Security audit / npm scan-packages (Studio frontend tarballs) (push) Has been cancelled
Security audit / workflow-trigger lint (pull_request_target / cache-poisoning) (push) Has been cancelled
Security audit / pytest tests/security (push) Has been cancelled
Security audit / npm provenance + new install-script diff (push) Has been cancelled
Studio API CI / Studio API & Auth Tests (push) Has been cancelled
Backend CI / (Python 3.10) (push) Has been cancelled
Backend CI / (Python 3.11) (push) Has been cancelled
Backend CI / (Python 3.12) (push) Has been cancelled
Backend CI / (Python 3.13) (push) Has been cancelled
Backend CI / Repo tests (CPU) (push) Has been cancelled
Frontend CI / Frontend build + bundle sanity (push) Has been cancelled
Studio GGUF CI / OpenAI, Anthropic API tests (push) Has been cancelled
Studio GGUF CI / Tool calling Tests (push) Has been cancelled
Studio GGUF CI / JSON, images (push) Has been cancelled
Mac Studio GGUF CI / OpenAI, Anthropic API tests (push) Has been cancelled
Mac Studio GGUF CI / Tool calling Tests (push) Has been cancelled
Mac Studio GGUF CI / JSON, images (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-14) (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-15) (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-26) (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-15-intel) (push) Has been cancelled
Mac Studio API CI / Studio API & Auth Tests (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-26-intel) (push) Has been cancelled
Mac Studio UI CI / Chat UI Tests (push) Has been cancelled
Studio Tauri CI / Tauri Linux debug build (no codesign) (push) Has been cancelled
Mac Studio Update CI / Studio Updating Tests (push) Has been cancelled
Studio UI CI / Chat UI Tests (push) Has been cancelled
Windows Studio API CI / Studio API & Auth Tests (push) Has been cancelled
Windows Studio UI CI / Chat UI Tests (push) Has been cancelled
Studio Update CI / Studio Updating Tests (push) Has been cancelled
Core / Core (HF=default + TRL=default) (push) Has been cancelled
Core / Core (HF=4.57.6 + TRL<1) (push) Has been cancelled
Core / Core (HF=latest + TRL=latest) (push) Has been cancelled
Core / llama.cpp build + smoke (push) Has been cancelled
Windows Studio GGUF CI / OpenAI, Anthropic API tests (push) Has been cancelled
Windows Studio GGUF CI / Tool calling Tests (push) Has been cancelled
Windows Studio GGUF CI / JSON, images (push) Has been cancelled
Windows Studio GGUF CI / Studio install + inference without Visual Studio (push) Has been cancelled
Studio export capability / capability (macos-latest) (push) Has been cancelled
Studio export capability / capability (ubuntu-latest) (push) Has been cancelled
Studio export capability / capability (windows-latest) (push) Has been cancelled
Cross-platform parity / parity (macos-latest) (push) Has been cancelled
Cross-platform parity / parity (windows-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
Studio load-orchestrator CI / test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:59:56 +08:00

126 lines
4.7 KiB
Python

# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
"""Store tests: incremental writes, dedupe, delete, scope, dense + lexical."""
import math
from core.rag import store
from core.rag.chunking import Chunk
VOCAB = ["alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel"]
def embed(text):
v = [float(text.lower().count(w)) for w in VOCAB]
n = math.sqrt(sum(x * x for x in v)) or 1.0
return [x / n for x in v]
def _chunk(
text,
index = 0,
page = None,
):
return Chunk(
text = text,
token_count = len(text.split()),
page_number = page,
source_page_index = 0,
chunk_index = index,
page_char_start = 0,
page_char_end = len(text),
)
def _add_doc(conn, scope, doc_id, filename, sha, texts):
chunks = [_chunk(t, i) for i, t in enumerate(texts)]
vectors = [embed(t) for t in texts]
store.create_document(conn, scope = scope, filename = filename, sha256 = sha, document_id = doc_id)
store.add_chunks(conn, scope, doc_id, chunks, vectors)
def test_lexical_returns_only_matching_docs(rag_conn):
_add_doc(rag_conn, "kb_a", "d1", "d1.txt", "h1", ["alpha bravo charlie"])
_add_doc(rag_conn, "kb_a", "d2", "d2.txt", "h2", ["golf hotel india"])
hits = store.search_lexical(rag_conn, "kb_a", "alpha", 10)
assert [cid for cid, _ in hits] == ["d1:0"] # d2 not returned (score 0)
def test_scope_isolation(rag_conn):
_add_doc(rag_conn, "kb_a", "d1", "f", "h1", ["alpha bravo"])
_add_doc(rag_conn, "kb_b", "d2", "f", "h2", ["alpha bravo"])
assert [cid for cid, _ in store.search_lexical(rag_conn, "kb_b", "alpha", 10)] == ["d2:0"]
def test_match_query_sanitizes_special_chars():
assert store._match_query('AND OR "quote" (paren) -dash') != ""
def test_lexical_does_not_crash_on_punctuation(rag_conn):
_add_doc(rag_conn, "kb_a", "d1", "f", "h1", ["alpha bravo"])
# Must not raise on FTS operators in the query.
store.search_lexical(rag_conn, "kb_a", 'NEAR("x" AND', 5)
def test_dense_ranks_by_cosine(rag_conn):
_add_doc(rag_conn, "kb_a", "d1", "f", "h1", ["alpha alpha"])
_add_doc(rag_conn, "kb_a", "d2", "f", "h2", ["hotel golf"])
ranked = store.search_dense(rag_conn, "kb_a", embed("alpha"), 10)
assert ranked[0][0] == "d1:0" and ranked[0][1] > 0.99
def test_dense_empty_before_any_ingest(rag_conn):
# No chunks_vec table yet -> [], no crash.
assert store.search_dense(rag_conn, "kb_a", embed("alpha"), 10) == []
def test_dedupe_by_hash(rag_conn):
_add_doc(rag_conn, "kb_a", "d1", "f", "SHA", ["alpha"])
assert store.document_by_hash(rag_conn, "kb_a", "SHA") == "d1"
assert store.document_by_hash(rag_conn, "kb_a", "OTHER") is None
def test_delete_document_purges_all_tables(rag_conn):
_add_doc(rag_conn, "kb_a", "d1", "f", "h1", ["alpha bravo"])
store.delete_document(rag_conn, "d1")
assert store.search_lexical(rag_conn, "kb_a", "alpha", 10) == []
assert store.search_dense(rag_conn, "kb_a", embed("alpha"), 10) == []
assert store.chunks_by_id(rag_conn, ["d1:0"]) == {}
assert store.get_document(rag_conn, "d1") is None
def test_incremental_add_is_flat(rag_conn):
# Adding doc2 must not touch doc1's fts rowids (append, not rebuild).
_add_doc(rag_conn, "kb_a", "d1", "f", "h1", ["alpha bravo charlie"])
before = rag_conn.execute(
"SELECT rowid, chunk_id FROM chunks_fts WHERE scope='kb_a'"
).fetchall()
_add_doc(rag_conn, "kb_a", "d2", "f", "h2", ["delta echo foxtrot"])
after = rag_conn.execute(
"SELECT rowid, chunk_id FROM chunks_fts WHERE scope='kb_a' AND chunk_id LIKE 'd1:%'"
).fetchall()
before_d1 = [(r["rowid"], r["chunk_id"]) for r in before if r["chunk_id"].startswith("d1:")]
after_d1 = [(r["rowid"], r["chunk_id"]) for r in after]
assert before_d1 == after_d1
def test_chunks_by_id_joins_filename(rag_conn):
_add_doc(rag_conn, "kb_a", "d1", "paper.pdf", "h1", ["body text here"])
rows = store.chunks_by_id(rag_conn, ["d1:0"])
assert rows["d1:0"]["filename"] == "paper.pdf"
assert rows["d1:0"]["text"] == "body text here"
def test_kb_crud_and_delete_cascades(rag_conn):
kb_id = store.create_kb(rag_conn, name = "My KB", description = "d", kb_id = "K1")
assert store.get_kb(rag_conn, kb_id)["name"] == "My KB"
assert [k["id"] for k in store.list_kbs(rag_conn)] == ["K1"]
scope = store.kb_scope("K1")
_add_doc(rag_conn, scope, "doc1", "f", "h1", ["alpha bravo"])
store.delete_kb(rag_conn, "K1")
assert store.get_kb(rag_conn, "K1") is None
assert store.list_documents(rag_conn, scope) == []
assert store.search_lexical(rag_conn, scope, "alpha", 10) == []