Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 15 additions & 7 deletions .github/workflows/eval.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@ jobs:
qdrant:
image: qdrant/qdrant:v1.12.4
ports: ["6333:6333"]
minio:
image: minio/minio:RELEASE.2024-10-13T13-34-11Z
env:
MINIO_ROOT_USER: kbminio
MINIO_ROOT_PASSWORD: kbminio-secret
ports: ["9000:9000"]
options: --health-cmd "curl -fsS http://localhost:9000/minio/health/live" --health-interval 3s --health-retries 20

steps:
- uses: actions/checkout@v4
Expand All @@ -41,6 +34,21 @@ jobs:
version: "0.11.17"
- run: uv python install 3.11
- run: uv sync --all-extras
- name: Start MinIO
# minio/minio image requires "server /data" as the CMD argument; GitHub Actions service
# containers have no way to pass CMD args, so we start minio as a background container step.
run: |
docker run -d --name minio \
-p 9000:9000 \
-e MINIO_ROOT_USER=kbminio \
-e MINIO_ROOT_PASSWORD=kbminio-secret \
minio/minio:RELEASE.2024-10-13T13-34-11Z server /data
for i in $(seq 1 20); do
if curl -fsS http://localhost:9000/minio/health/live; then
echo "MinIO is ready"; break
fi
sleep 3
done
- name: Lint + unit tests
run: |
uv run ruff check src tests
Expand Down
4 changes: 1 addition & 3 deletions src/kb/api/routes/infer.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,7 @@ async def infer_from_files(
)
remaining = max(sample_count - len(samples), 0)
if remaining:
samples.extend(
_sample_texts_from_elements(elements, sample_count=remaining)
)
samples.extend(_sample_texts_from_elements(elements, sample_count=remaining))
except Exception as e:
errors.append({"filename": filename, "error": str(e)})

Expand Down
8 changes: 6 additions & 2 deletions src/kb/api/routes/ingest_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,9 @@ async def ingest_record(body: RecordIn) -> RecordOut:
"is_parent": False,
"source": "record",
},
content_hash=chunk_content_hash(f"record:{body.project}:{body.kind}:{body.type}:{excerpt}"),
content_hash=chunk_content_hash(
f"record:{body.project}:{body.kind}:{body.type}:{excerpt}"
),
)
)
upserted += 1
Expand All @@ -233,7 +235,9 @@ async def ingest_record(body: RecordIn) -> RecordOut:
await store.delete_by_file(body.kind, file_id)
await store.upsert(body.kind, chunks)
except Exception as e:
await repo.set_file_status(file_id, "failed", error=f"record vector indexing failed: {e}"[:500])
await repo.set_file_status(
file_id, "failed", error=f"record vector indexing failed: {e}"[:500]
)
raise HTTPException(503, f"record stored but vector indexing failed: {e}") from e

return RecordOut(
Expand Down
8 changes: 4 additions & 4 deletions src/kb/api/routes/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,7 @@ async def apply_draft(draft_id: str, body: ApplyDraftIn | None = None) -> dict:
@router.post("/drafts/{draft_id}/discard")
async def discard_draft(draft_id: str, body: DraftProjectIn | None = None) -> dict:
body = body or DraftProjectIn()
row = await repo.update_schema_draft_status(
draft_id, project=body.project, status="discarded"
)
row = await repo.update_schema_draft_status(draft_id, project=body.project, status="discarded")
if not row:
raise HTTPException(404, "schema draft not found")
return row
Expand All @@ -147,7 +145,9 @@ async def reprocess_for_active_schema(domain: str, body: ReprocessIn | None = No
body = body or ReprocessIn()
sch = await get_active_schema(domain, project=body.project)
if not sch:
raise HTTPException(404, f"No active schema for domain '{domain}' in project '{body.project}'")
raise HTTPException(
404, f"No active schema for domain '{domain}' in project '{body.project}'"
)
enqueued = await reindex_domain_with_schema(
project=body.project,
domain=domain,
Expand Down
3 changes: 1 addition & 2 deletions src/kb/query/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,8 +679,7 @@ def _section_score(h: Any) -> float:
and (
hard_citation_gate
or not (
crag_score >= verify_skip_threshold
and confidence_value >= verify_skip_threshold
crag_score >= verify_skip_threshold and confidence_value >= verify_skip_threshold
)
)
)
Expand Down
4 changes: 3 additions & 1 deletion src/kb/query/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
_TOKEN_RE = re.compile(r"[A-Za-z0-9][A-Za-z0-9_-]{2,}")


def _explicit_filters(scope: dict[str, Any] | None, filters: dict[str, Any] | None) -> dict[str, Any]:
def _explicit_filters(
scope: dict[str, Any] | None, filters: dict[str, Any] | None
) -> dict[str, Any]:
out: dict[str, Any] = {}
if scope:
for key in ("entity_id", "file_id", "parent_id"):
Expand Down
6 changes: 2 additions & 4 deletions src/kb/vector/qdrant_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,10 @@ async def upsert(self, domain: str, chunks: list[Chunk]) -> None:
collection_name=_collection(domain),
scroll_filter=qm.Filter(
must=[
qm.FieldCondition(
key="project", match=qm.MatchValue(value=project)
),
qm.FieldCondition(key="project", match=qm.MatchValue(value=project)),
qm.FieldCondition(
key="content_hash", match=qm.MatchAny(any=list(set(hashes)))
)
),
]
),
limit=len(hashes) * 2,
Expand Down
Loading