sable-sphynx 0.7.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sable_sphynx-0.7.0.dev0.dist-info/METADATA +152 -0
- sable_sphynx-0.7.0.dev0.dist-info/RECORD +174 -0
- sable_sphynx-0.7.0.dev0.dist-info/WHEEL +5 -0
- sable_sphynx-0.7.0.dev0.dist-info/top_level.txt +1 -0
- sphynx/__init__.py +469 -0
- sphynx/__init__.pyi +376 -0
- sphynx/_analytical_client.py +77 -0
- sphynx/_analytical_values.py +252 -0
- sphynx/_audit_client.py +173 -0
- sphynx/_comparison_adapters.py +113 -0
- sphynx/_componentized_full_rag.py +34 -0
- sphynx/_composed_pipeline.py +109 -0
- sphynx/_full_rag_grading.py +218 -0
- sphynx/_full_rag_trace.py +221 -0
- sphynx/_local_eval.py +268 -0
- sphynx/_pipeline_core.py +243 -0
- sphynx/_pr_client.py +237 -0
- sphynx/_rag_diagnostics_calibration.py +285 -0
- sphynx/_rag_diagnostics_catalog.py +39 -0
- sphynx/_rag_diagnostics_common.py +26 -0
- sphynx/_rag_diagnostics_contracts.py +186 -0
- sphynx/_rag_diagnostics_engine.py +243 -0
- sphynx/_rag_diagnostics_importers.py +242 -0
- sphynx/_rag_diagnostics_ranking.py +81 -0
- sphynx/_rag_diagnostics_semantic.py +325 -0
- sphynx/_rag_ranking.py +149 -0
- sphynx/_speech_benchmark_scoring.py +140 -0
- sphynx/_speech_benchmark_sources.py +275 -0
- sphynx/_speech_complete_scoring.py +218 -0
- sphynx/_speech_complete_source.py +118 -0
- sphynx/_speech_kido.py +294 -0
- sphynx/_speech_scoring.py +77 -0
- sphynx/_track_capture.py +213 -0
- sphynx/analytical_views.py +515 -0
- sphynx/assessment_contracts.py +378 -0
- sphynx/assessment_selection.py +57 -0
- sphynx/audit_access.py +245 -0
- sphynx/audit_contracts.py +204 -0
- sphynx/audit_requests.py +180 -0
- sphynx/authoring.py +188 -0
- sphynx/benchmarks.py +568 -0
- sphynx/candidates.py +62 -0
- sphynx/catalog.py +272 -0
- sphynx/chunking.py +372 -0
- sphynx/clickhouse_reader.py +169 -0
- sphynx/client.py +486 -0
- sphynx/comparison_core.py +149 -0
- sphynx/comparison_views.py +223 -0
- sphynx/components.py +1661 -0
- sphynx/contracts.py +514 -0
- sphynx/customer_rerank.py +299 -0
- sphynx/customer_retrieval.py +146 -0
- sphynx/data/benchmark-releases.v1.json +164 -0
- sphynx/data/public-benchmark-release.v1.json +354 -0
- sphynx/data/rag-diagnostics-synthetic.v1.json +6982 -0
- sphynx/data/rag-paper-references.v1.json +176 -0
- sphynx/data/rag-paper-schemas.v1.json +1069 -0
- sphynx/data/rag-rerank-v1.json +507 -0
- sphynx/dataset_catalog_data.py +1214 -0
- sphynx/dataset_readiness.py +138 -0
- sphynx/dataset_v3.py +999 -0
- sphynx/demo.py +130 -0
- sphynx/demo_candidates/__init__.py +1 -0
- sphynx/demo_candidates/dense.py +11 -0
- sphynx/demo_candidates/lexical.py +21 -0
- sphynx/diagnostics.py +207 -0
- sphynx/documentation.py +737 -0
- sphynx/documentation_candidate.py +939 -0
- sphynx/evals.py +538 -0
- sphynx/evaluation_protocols.py +124 -0
- sphynx/evaluator_bindings.py +370 -0
- sphynx/evidence.py +352 -0
- sphynx/execution_capabilities.py +109 -0
- sphynx/fast_search.py +285 -0
- sphynx/full_rag.py +341 -0
- sphynx/hosted/__init__.py +18 -0
- sphynx/hosted/benchmark_intake.py +218 -0
- sphynx/hosted/contracts.py +361 -0
- sphynx/hosted/model_admission.py +130 -0
- sphynx/hosted/model_artifacts.py +298 -0
- sphynx/hosted/model_contracts.py +63 -0
- sphynx/hosted/model_gcs.py +181 -0
- sphynx/hosted/model_history.py +84 -0
- sphynx/hosted/model_session.py +233 -0
- sphynx/hosted/public_suite.py +74 -0
- sphynx/hosted/registry.py +97 -0
- sphynx/hosted/revisions.py +126 -0
- sphynx/hosted/sandbox.py +105 -0
- sphynx/hosted/submission.py +287 -0
- sphynx/hosted_workflow.py +451 -0
- sphynx/http_transport.py +86 -0
- sphynx/integrated_rag.py +352 -0
- sphynx/integrated_workflow.py +552 -0
- sphynx/integration_contracts.py +474 -0
- sphynx/invocation.py +791 -0
- sphynx/invocation_candidates.py +392 -0
- sphynx/invocation_catalog_data.py +40 -0
- sphynx/learned_catalog_data.py +30 -0
- sphynx/learned_rerank.py +267 -0
- sphynx/legacy_full_rag.py +67 -0
- sphynx/lifecycle.py +885 -0
- sphynx/lifecycle_workflow.py +490 -0
- sphynx/metric_views.py +474 -0
- sphynx/metrics.py +282 -0
- sphynx/model_adapters.py +438 -0
- sphynx/model_catalog_data.py +30 -0
- sphynx/official_benchmarks.py +385 -0
- sphynx/packs.py +258 -0
- sphynx/pipeline.py +313 -0
- sphynx/pipeline_workflow.py +551 -0
- sphynx/pr_evaluations.py +560 -0
- sphynx/progress.py +89 -0
- sphynx/public_bundle.py +173 -0
- sphynx/public_eval.py +62 -0
- sphynx/public_rerank.py +355 -0
- sphynx/py.typed +0 -0
- sphynx/pytest_plugin.py +62 -0
- sphynx/question_robustness.py +437 -0
- sphynx/rag.py +329 -0
- sphynx/rag_diagnostics.py +309 -0
- sphynx/rag_papers/__init__.py +29 -0
- sphynx/rag_papers/__main__.py +45 -0
- sphynx/rag_papers/candidates.py +19 -0
- sphynx/rag_papers/contracts.py +282 -0
- sphynx/rag_papers/datasets.py +291 -0
- sphynx/rag_papers/experiments.py +116 -0
- sphynx/rag_papers/judges.py +308 -0
- sphynx/rag_papers/registry.py +33 -0
- sphynx/rag_papers/runner.py +176 -0
- sphynx/rag_papers/sable.py +135 -0
- sphynx/rag_papers/schemas.py +12 -0
- sphynx/rag_papers/scoring.py +249 -0
- sphynx/rag_papers/semantic.py +288 -0
- sphynx/rag_papers/trec.py +80 -0
- sphynx/recorded_scores.py +352 -0
- sphynx/records.py +124 -0
- sphynx/reflex_traces.py +193 -0
- sphynx/report_rendering.py +71 -0
- sphynx/rerank_family_contracts.py +150 -0
- sphynx/rerank_workflow.py +424 -0
- sphynx/research_candidate.py +190 -0
- sphynx/results.py +852 -0
- sphynx/retrieval.py +750 -0
- sphynx/retrieval_candidates.py +295 -0
- sphynx/retrieval_catalog_data.py +19 -0
- sphynx/retrieval_recordings.py +125 -0
- sphynx/reviewer_audit.py +266 -0
- sphynx/routing_policies.py +375 -0
- sphynx/runner.py +544 -0
- sphynx/sable_rerank.py +489 -0
- sphynx/score_reliability.py +393 -0
- sphynx/speech_benchmarks.py +204 -0
- sphynx/speech_campaigns.py +378 -0
- sphynx/speech_complete.py +236 -0
- sphynx/speech_contracts.py +225 -0
- sphynx/speech_evidence.py +429 -0
- sphynx/speech_listening.py +115 -0
- sphynx/speech_multilingual.py +71 -0
- sphynx/speech_tts.py +479 -0
- sphynx/sql/001_sync_v1.sql +30 -0
- sphynx/stage_contracts.py +199 -0
- sphynx/statistical_catalog_data.py +53 -0
- sphynx/statistical_rerank.py +232 -0
- sphynx/sync.py +797 -0
- sphynx/workbench.py +378 -0
- sphynx/workbench_catalog_data.py +13 -0
- sphynx/workbench_tracks.py +78 -0
- sphynx/workflow_async.py +197 -0
- sphynx/workflow_contracts.py +594 -0
- sphynx/workflow_decisions.py +211 -0
- sphynx/workflow_defaults.py +16 -0
- sphynx/workflow_extensions.py +212 -0
- sphynx/workflow_registry.py +513 -0
- sphynx/workflows.py +792 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""Small source-readiness summaries with explicit identity and provenance.
|
|
2
|
+
|
|
3
|
+
These utilities describe supplied rows and pinned bytes. They do not establish
|
|
4
|
+
review authority, independent labels, holdout quality, or benchmark capability.
|
|
5
|
+
Summaries omit raw question text, labels, identifiers, and local source paths.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import hashlib
|
|
10
|
+
from collections.abc import Iterable, Mapping
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
import re
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from .contracts import ContractError, canonical_json
|
|
16
|
+
|
|
17
|
+
_SHA256 = re.compile(r"sha256:[0-9a-f]{64}\Z")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _text(value: Any, field: str) -> str:
|
|
21
|
+
if type(value) is not str or not value.strip() or "\x00" in value:
|
|
22
|
+
raise ContractError(f"{field} must be nonempty text")
|
|
23
|
+
try:
|
|
24
|
+
value.encode("utf-8", errors="strict")
|
|
25
|
+
except UnicodeEncodeError:
|
|
26
|
+
raise ContractError(f"{field} must contain valid Unicode") from None
|
|
27
|
+
return value
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _rows(values: Iterable[Any], field: str) -> list[Any]:
|
|
31
|
+
if isinstance(values, (str, bytes, Mapping)):
|
|
32
|
+
raise ContractError(f"{field} must be an iterable of rows")
|
|
33
|
+
try:
|
|
34
|
+
return list(values)
|
|
35
|
+
except TypeError:
|
|
36
|
+
raise ContractError(f"{field} must be an iterable of rows") from None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def overlap_summary(left: Iterable[str], right: Iterable[str]) -> dict[str, Any]:
|
|
40
|
+
"""Count exact unique identities; hash their sorted unique intersection.
|
|
41
|
+
|
|
42
|
+
Row counts retain duplicates. Overlap, union, and the overlap digest use
|
|
43
|
+
sets, so duplicate rows and ordering do not change their identity meaning.
|
|
44
|
+
IDs are compared exactly, without question-text or case normalization.
|
|
45
|
+
"""
|
|
46
|
+
left_rows = _rows(left, "left identities")
|
|
47
|
+
right_rows = _rows(right, "right identities")
|
|
48
|
+
left_ids = {_text(value, "left identity") for value in left_rows}
|
|
49
|
+
right_ids = {_text(value, "right identity") for value in right_rows}
|
|
50
|
+
overlap = left_ids & right_ids
|
|
51
|
+
digest = hashlib.sha256(canonical_json(sorted(overlap)).encode("utf-8")).hexdigest()
|
|
52
|
+
return {
|
|
53
|
+
"left_rows": len(left_rows), "right_rows": len(right_rows),
|
|
54
|
+
"left_unique": len(left_ids), "right_unique": len(right_ids),
|
|
55
|
+
"union_unique": len(left_ids | right_ids), "overlap_unique": len(overlap),
|
|
56
|
+
"left_only_unique": len(left_ids - right_ids), "right_only_unique": len(right_ids - left_ids),
|
|
57
|
+
"overlap_digest": "sha256:" + digest,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def routing_provenance_summary(questions: Iterable[Mapping[str, Any]],
|
|
62
|
+
labels: Iterable[Mapping[str, Any]]) -> dict[str, Any]:
|
|
63
|
+
"""Join unique question IDs and summarize supplied routing provenance.
|
|
64
|
+
|
|
65
|
+
Repeated questions are extra rows after the first occurrence of a company
|
|
66
|
+
and user-turn pair. Normalization collapses whitespace and applies casefold;
|
|
67
|
+
it does not remove punctuation, infer paraphrases, or match text across companies.
|
|
68
|
+
Family identity is supplied label metadata, not inferred from repeated text.
|
|
69
|
+
Incomplete or empty family metadata remains unknown.
|
|
70
|
+
"""
|
|
71
|
+
question_rows = _rows(questions, "questions")
|
|
72
|
+
label_rows = _rows(labels, "labels")
|
|
73
|
+
question_by_id: dict[str, Mapping[str, Any]] = {}
|
|
74
|
+
repeated_keys: set[tuple[str, str]] = set()
|
|
75
|
+
for row in question_rows:
|
|
76
|
+
if not isinstance(row, Mapping):
|
|
77
|
+
raise ContractError("question rows must be objects")
|
|
78
|
+
question_id = _text(row.get("question_id"), "question ID")
|
|
79
|
+
if question_id in question_by_id:
|
|
80
|
+
raise ContractError("question IDs must be unique")
|
|
81
|
+
company = _text(row.get("company_id"), "company ID")
|
|
82
|
+
turn = _text(row.get("user_turn"), "user turn")
|
|
83
|
+
question_by_id[question_id] = row
|
|
84
|
+
repeated_keys.add((" ".join(company.casefold().split()), " ".join(turn.casefold().split())))
|
|
85
|
+
|
|
86
|
+
label_by_id: dict[str, Mapping[str, Any]] = {}
|
|
87
|
+
for row in label_rows:
|
|
88
|
+
if not isinstance(row, Mapping):
|
|
89
|
+
raise ContractError("label rows must be objects")
|
|
90
|
+
question_id = _text(row.get("question_id"), "label question ID")
|
|
91
|
+
if question_id in label_by_id:
|
|
92
|
+
raise ContractError("label question IDs must be unique")
|
|
93
|
+
if question_id not in question_by_id:
|
|
94
|
+
raise ContractError("label question IDs do not match question IDs")
|
|
95
|
+
if "company_id" in row and row["company_id"] != question_by_id[question_id]["company_id"]:
|
|
96
|
+
raise ContractError("label company identity differs from its question")
|
|
97
|
+
label_by_id[question_id] = row
|
|
98
|
+
if set(label_by_id) != set(question_by_id):
|
|
99
|
+
raise ContractError("labels must match questions one to one")
|
|
100
|
+
|
|
101
|
+
missing_families = 0
|
|
102
|
+
families: set[tuple[str, str]] = set()
|
|
103
|
+
for question_id, row in label_by_id.items():
|
|
104
|
+
family = row.get("family_id")
|
|
105
|
+
if family is None or (type(family) is str and not family.strip()):
|
|
106
|
+
missing_families += 1
|
|
107
|
+
continue
|
|
108
|
+
family = _text(family, "family ID")
|
|
109
|
+
families.add((question_by_id[question_id]["company_id"], family))
|
|
110
|
+
known_families = bool(question_rows) and missing_families == 0
|
|
111
|
+
return {
|
|
112
|
+
"question_rows": len(question_rows), "label_rows": len(label_rows),
|
|
113
|
+
"question_unique": len(question_by_id),
|
|
114
|
+
"repeated_question_rows": len(question_rows) - len(repeated_keys),
|
|
115
|
+
"repeated_question_status": "known",
|
|
116
|
+
"family_status": "known" if known_families else "unknown",
|
|
117
|
+
"family_count": len(families) if known_families else None,
|
|
118
|
+
"missing_family_rows": missing_families,
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def verify_source_file(path: str | Path, expected_sha256: str | None = None) -> dict[str, Any]:
|
|
123
|
+
"""Verify actual file bytes against an explicit lowercase SHA-256 pin.
|
|
124
|
+
|
|
125
|
+
Missing or malformed pins fail before reading. The calculated digest is
|
|
126
|
+
compared with the caller's pin; it is never adopted as a new authority.
|
|
127
|
+
Return byte metadata only, without exposing the source path or content.
|
|
128
|
+
"""
|
|
129
|
+
if type(expected_sha256) is not str or not _SHA256.fullmatch(expected_sha256):
|
|
130
|
+
raise ContractError("source verification requires an explicit lowercase sha256 pin")
|
|
131
|
+
try:
|
|
132
|
+
raw = Path(path).read_bytes()
|
|
133
|
+
except (OSError, TypeError, ValueError):
|
|
134
|
+
raise ContractError("source file could not be read") from None
|
|
135
|
+
actual = "sha256:" + hashlib.sha256(raw).hexdigest()
|
|
136
|
+
if actual != expected_sha256:
|
|
137
|
+
raise ContractError("source bytes differ from the supplied SHA-256 pin")
|
|
138
|
+
return {"sha256": actual, "size_bytes": len(raw)}
|