myrmidon / python /src /server /services /knowledge /knowledge_repository.py
tek Atrust
chore(deploy): build monolithic server for Hugging Face
d5ef46f
Raw
History Blame Contribute Delete
4.53 kB
"""
Knowledge Repository
Handles database operations for knowledge items, documents, and code examples.
"""
from typing import Any
from ...config.logfire_config import safe_logfire_error
class KnowledgeRepository:
"""
Repository for database operations related to knowledge items.
"""
def __init__(self, supabase_client):
self.supabase = supabase_client
async def get_document_counts_batch(self, source_ids: list[str]) -> dict[str, int]:
"""Get document counts for multiple sources."""
try:
counts = {}
for source_id in source_ids:
result = (
self.supabase.from_("archon_crawled_pages")
.select("id", count="exact", head=True)
.eq("source_id", source_id)
.execute()
)
counts[source_id] = result.count if hasattr(result, "count") else 0
return counts
except Exception as e:
safe_logfire_error(f"Failed to get document counts | error={str(e)}")
return dict.fromkeys(source_ids, 0)
async def get_code_example_counts_batch(self, source_ids: list[str]) -> dict[str, int]:
"""Get code example counts for multiple sources."""
try:
counts = {}
for source_id in source_ids:
result = (
self.supabase.from_("archon_code_examples")
.select("id", count="exact", head=True)
.eq("source_id", source_id)
.execute()
)
counts[source_id] = result.count if hasattr(result, "count") else 0
return counts
except Exception as e:
safe_logfire_error(f"Failed to get code example counts | error={str(e)}")
return dict.fromkeys(source_ids, 0)
async def get_first_urls_batch(self, source_ids: list[str]) -> dict[str, str]:
"""Get first URL for each source in a batch."""
try:
result = (
self.supabase.from_("archon_crawled_pages")
.select("source_id, url")
.in_("source_id", source_ids)
.order("created_at", desc=False)
.execute()
)
urls = {}
for item in result.data or []:
source_id = item["source_id"]
if source_id not in urls:
urls[source_id] = item["url"]
for source_id in source_ids:
if source_id not in urls:
urls[source_id] = f"source://{source_id}"
return urls
except Exception as e:
safe_logfire_error(f"Failed to get first URLs | error={str(e)}")
return {sid: f"source://{sid}" for sid in source_ids}
async def get_item_chunks(
self, source_id: str, page: int = 1, per_page: int = 50, domain_filter: str | None = None
) -> tuple[bool, dict[str, Any]]:
"""Get document chunks for a specific knowledge item with pagination and filtering."""
try:
per_page = max(1, min(per_page, 100))
page = max(1, page)
query = self.supabase.from_("archon_crawled_pages").select(
"id, source_id, content, metadata, url", count="exact"
)
query = query.eq("source_id", source_id)
if domain_filter:
query = query.ilike("url", f"%{domain_filter}%")
offset = (page - 1) * per_page
query = query.order("url", desc=False).order("id", desc=False)
query = query.range(offset, offset + per_page - 1)
result = query.execute()
if getattr(result, "error", None):
return False, {"error": str(result.error)}
chunks = result.data if result.data else []
total_count = result.count if hasattr(result, "count") and result.count is not None else len(chunks)
return True, {
"chunks": chunks,
"pagination": {
"total": total_count,
"page": page,
"per_page": per_page,
"total_pages": (total_count + per_page - 1) // per_page if total_count > 0 else 0,
},
}
except Exception as e:
safe_logfire_error(f"Failed to fetch chunks | source_id={source_id} | error={str(e)}")
return False, {"error": str(e)}