Files
strukto-ai--mirage/python/mirage/core/chroma/search.py
T
wehub-resource-sync bcbd1bdb22
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:44 +08:00

122 lines
4.3 KiB
Python

from typing import Any
from mirage.cache.index import IndexCacheStore, IndexEntry
from mirage.core.chroma.path import resolve_path
from mirage.core.chroma.walk import walk
from mirage.types import PathSpec
from mirage.utils.key_prefix import mount_prefix_of, rekey
from mirage.utils.score import score_from_distance
async def search_segments(
accessor,
query: str,
paths: list[PathSpec],
index: IndexCacheStore,
top_k: int = 10,
mount_prefix: str = "",
) -> bytes:
validate_args(query, top_k)
if not mount_prefix and paths:
mount_prefix = mount_prefix_of(paths[0].virtual,
paths[0].resource_path)
kwargs: dict[str, Any] = {
"query_texts": [query],
"n_results": top_k,
"include": ["documents", "metadatas", "distances"],
}
scoped_slugs: set[str] | None = None
if paths:
scoped_slugs = set((await target_entries(accessor, paths,
index)).keys())
if not scoped_slugs:
return b""
kwargs["where"] = {
accessor.config.slug_field: {
"$in": sorted(scoped_slugs)
}
}
collection = await accessor.get_collection()
response = await collection.query(**kwargs)
return query_result_to_bytes(response, accessor.config.slug_field,
mount_prefix, scoped_slugs)
def validate_args(query: str, top_k: int) -> None:
if not query:
raise ValueError("search: query is required")
if len(query) > 250:
raise ValueError("search: query cannot exceed 250 characters")
if top_k <= 0:
raise ValueError("search: top-k must be positive")
async def target_entries(
accessor,
paths: list[PathSpec],
index: IndexCacheStore,
) -> dict[str, IndexEntry]:
targets: dict[str, IndexEntry] = {}
for path in paths:
resolved = await resolve_path(accessor, path, index)
if resolved.entry is not None and not resolved.is_dir:
targets[str(resolved.entry.extra["slug"])] = resolved.entry
continue
if resolved.is_dir:
children = await walk(accessor,
path,
index,
include_root=False,
strip_prefix=False)
for child in children:
child_spec = PathSpec.from_str_path(
child, rekey(path.virtual, path.resource_path, child))
child_resolved = await resolve_path(accessor, child_spec,
index)
if (child_resolved.entry is not None
and not child_resolved.is_dir):
targets[str(child_resolved.entry.extra["slug"]
)] = child_resolved.entry
return targets
def query_result_to_bytes(
response: dict[str, Any],
slug_field: str,
mount_prefix: str,
scoped_slugs: set[str] | None = None,
) -> bytes:
documents = first_result_list(response.get("documents"))
metadatas = first_result_list(response.get("metadatas"))
distances = first_result_list(response.get("distances"))
contents: list[str] = []
for index, document in enumerate(documents):
metadata = metadatas[index] if index < len(metadatas) else {}
if not isinstance(metadata, dict):
continue
slug = metadata.get(slug_field)
if slug is None:
continue
slug_value = str(slug).strip("/")
if scoped_slugs is not None and slug_value not in scoped_slugs:
continue
score = score_from_distance(distances[index] if index <
len(distances) else None)
path = "/" + slug_value
prefix = mount_prefix.rstrip("/")
if prefix:
path = prefix + path
content = "" if document is None else str(document)
contents.append(f"{path}:{score}\n{content}")
if not contents:
return b""
return ("\n".join(contents) + "\n").encode()
def first_result_list(value: object) -> list:
if not isinstance(value, list):
return []
if value and isinstance(value[0], list):
return value[0]
return value