helios-cortex 0.1.0__tar.gz
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.
- helios_cortex-0.1.0/.gitignore +21 -0
- helios_cortex-0.1.0/CONTRACTS.md +108 -0
- helios_cortex-0.1.0/PKG-INFO +38 -0
- helios_cortex-0.1.0/pyproject.toml +79 -0
- helios_cortex-0.1.0/src/helios_cortex/__init__.py +18 -0
- helios_cortex-0.1.0/src/helios_cortex/_optional.py +17 -0
- helios_cortex-0.1.0/src/helios_cortex/_pending/__init__.py +8 -0
- helios_cortex-0.1.0/src/helios_cortex/_pending/browse.py +181 -0
- helios_cortex-0.1.0/src/helios_cortex/_pending/crawler/__init__.py +6 -0
- helios_cortex-0.1.0/src/helios_cortex/_pending/crawler/presets/index.yaml +13 -0
- helios_cortex-0.1.0/src/helios_cortex/_pending/crawler/presets/retail-returns.yaml +535 -0
- helios_cortex-0.1.0/src/helios_cortex/_pending/crawler/settings.py +566 -0
- helios_cortex-0.1.0/src/helios_cortex/_pending/crawler/sources.py +144 -0
- helios_cortex-0.1.0/src/helios_cortex/_pending/crawler_settings.py +94 -0
- helios_cortex-0.1.0/src/helios_cortex/_pending/evidence.py +416 -0
- helios_cortex-0.1.0/src/helios_cortex/artifact_storage.py +289 -0
- helios_cortex-0.1.0/src/helios_cortex/artifacts.py +376 -0
- helios_cortex-0.1.0/src/helios_cortex/audit_sink.py +86 -0
- helios_cortex-0.1.0/src/helios_cortex/caller.py +46 -0
- helios_cortex-0.1.0/src/helios_cortex/catalog/__init__.py +21 -0
- helios_cortex-0.1.0/src/helios_cortex/catalog/base.py +91 -0
- helios_cortex-0.1.0/src/helios_cortex/compiler/__init__.py +9 -0
- helios_cortex-0.1.0/src/helios_cortex/compiler/compiler.py +402 -0
- helios_cortex-0.1.0/src/helios_cortex/conformance.py +364 -0
- helios_cortex-0.1.0/src/helios_cortex/data_authorization.py +222 -0
- helios_cortex-0.1.0/src/helios_cortex/domain.py +118 -0
- helios_cortex-0.1.0/src/helios_cortex/engines/__init__.py +16 -0
- helios_cortex-0.1.0/src/helios_cortex/engines/base.py +108 -0
- helios_cortex-0.1.0/src/helios_cortex/engines/dialect.py +62 -0
- helios_cortex-0.1.0/src/helios_cortex/engines/duckdb_engine.py +55 -0
- helios_cortex-0.1.0/src/helios_cortex/engines/sqlalchemy_engine.py +121 -0
- helios_cortex-0.1.0/src/helios_cortex/engines/trino_engine.py +132 -0
- helios_cortex-0.1.0/src/helios_cortex/index/__init__.py +46 -0
- helios_cortex-0.1.0/src/helios_cortex/index/__main__.py +35 -0
- helios_cortex-0.1.0/src/helios_cortex/index/ids.py +63 -0
- helios_cortex-0.1.0/src/helios_cortex/index/mappings.py +128 -0
- helios_cortex-0.1.0/src/helios_cortex/index/ontology_versions.py +104 -0
- helios_cortex-0.1.0/src/helios_cortex/index/records.py +300 -0
- helios_cortex-0.1.0/src/helios_cortex/index/runs.py +102 -0
- helios_cortex-0.1.0/src/helios_cortex/index/schema_impala.sql +201 -0
- helios_cortex-0.1.0/src/helios_cortex/index/store.py +123 -0
- helios_cortex-0.1.0/src/helios_cortex/index/tables.py +142 -0
- helios_cortex-0.1.0/src/helios_cortex/llm/__init__.py +17 -0
- helios_cortex-0.1.0/src/helios_cortex/llm/client.py +535 -0
- helios_cortex-0.1.0/src/helios_cortex/ontology/__init__.py +35 -0
- helios_cortex-0.1.0/src/helios_cortex/ontology/graph.py +209 -0
- helios_cortex-0.1.0/src/helios_cortex/ontology/mapping.py +439 -0
- helios_cortex-0.1.0/src/helios_cortex/ontology/parser.py +336 -0
- helios_cortex-0.1.0/src/helios_cortex/ossie/__init__.py +2 -0
- helios_cortex-0.1.0/src/helios_cortex/ossie/format.py +43 -0
- helios_cortex-0.1.0/src/helios_cortex/ossie/model.py +263 -0
- helios_cortex-0.1.0/src/helios_cortex/ossie/ossie-schema.json +367 -0
- helios_cortex-0.1.0/src/helios_cortex/plugins.py +128 -0
- helios_cortex-0.1.0/src/helios_cortex/py.typed +0 -0
- helios_cortex-0.1.0/src/helios_cortex/registry/__init__.py +214 -0
- helios_cortex-0.1.0/src/helios_cortex/registry/__main__.py +27 -0
- helios_cortex-0.1.0/src/helios_cortex/registry/migrations/env.py +18 -0
- helios_cortex-0.1.0/src/helios_cortex/registry/migrations/script.py.mako +20 -0
- helios_cortex-0.1.0/src/helios_cortex/registry/migrations/versions/0001_registry.py +73 -0
- helios_cortex-0.1.0/src/helios_cortex/registry/sql.py +312 -0
- helios_cortex-0.1.0/src/helios_cortex/runs.py +517 -0
- helios_cortex-0.1.0/src/helios_cortex/settings.py +355 -0
- helios_cortex-0.1.0/src/helios_cortex/visibility.py +46 -0
- helios_cortex-0.1.0/tests/conftest.py +11 -0
- helios_cortex-0.1.0/tests/fixtures/sample_requests.json +28 -0
- helios_cortex-0.1.0/tests/fixtures/tpcds-harvest.json +649 -0
- helios_cortex-0.1.0/tests/golden/compile/bigquery/ad_hoc_measures.sql +14 -0
- helios_cortex-0.1.0/tests/golden/compile/bigquery/filtered_and_ordered.sql +19 -0
- helios_cortex-0.1.0/tests/golden/compile/bigquery/pinned_relationship.sql +8 -0
- helios_cortex-0.1.0/tests/golden/compile/bigquery/revenue_by_year.sql +8 -0
- helios_cortex-0.1.0/tests/golden/compile/bigquery/snowflake_join.sql +16 -0
- helios_cortex-0.1.0/tests/golden/compile/duckdb/ad_hoc_measures.sql +14 -0
- helios_cortex-0.1.0/tests/golden/compile/duckdb/filtered_and_ordered.sql +19 -0
- helios_cortex-0.1.0/tests/golden/compile/duckdb/pinned_relationship.sql +8 -0
- helios_cortex-0.1.0/tests/golden/compile/duckdb/revenue_by_year.sql +8 -0
- helios_cortex-0.1.0/tests/golden/compile/duckdb/snowflake_join.sql +16 -0
- helios_cortex-0.1.0/tests/golden/compile/postgres/ad_hoc_measures.sql +14 -0
- helios_cortex-0.1.0/tests/golden/compile/postgres/filtered_and_ordered.sql +19 -0
- helios_cortex-0.1.0/tests/golden/compile/postgres/pinned_relationship.sql +8 -0
- helios_cortex-0.1.0/tests/golden/compile/postgres/revenue_by_year.sql +8 -0
- helios_cortex-0.1.0/tests/golden/compile/postgres/snowflake_join.sql +16 -0
- helios_cortex-0.1.0/tests/golden/compile/snowflake/ad_hoc_measures.sql +14 -0
- helios_cortex-0.1.0/tests/golden/compile/snowflake/filtered_and_ordered.sql +19 -0
- helios_cortex-0.1.0/tests/golden/compile/snowflake/pinned_relationship.sql +8 -0
- helios_cortex-0.1.0/tests/golden/compile/snowflake/revenue_by_year.sql +8 -0
- helios_cortex-0.1.0/tests/golden/compile/snowflake/snowflake_join.sql +16 -0
- helios_cortex-0.1.0/tests/golden/compile/trino/ad_hoc_measures.sql +14 -0
- helios_cortex-0.1.0/tests/golden/compile/trino/filtered_and_ordered.sql +19 -0
- helios_cortex-0.1.0/tests/golden/compile/trino/pinned_relationship.sql +8 -0
- helios_cortex-0.1.0/tests/golden/compile/trino/revenue_by_year.sql +8 -0
- helios_cortex-0.1.0/tests/golden/compile/trino/snowflake_join.sql +16 -0
- helios_cortex-0.1.0/tests/ozone/docker-compose.yaml +24 -0
- helios_cortex-0.1.0/tests/ozone/docker-config +29 -0
- helios_cortex-0.1.0/tests/test_artifact_storage.py +116 -0
- helios_cortex-0.1.0/tests/test_artifacts.py +208 -0
- helios_cortex-0.1.0/tests/test_audit_sink.py +63 -0
- helios_cortex-0.1.0/tests/test_caller.py +94 -0
- helios_cortex-0.1.0/tests/test_catalog_plugins.py +101 -0
- helios_cortex-0.1.0/tests/test_compile_golden.py +45 -0
- helios_cortex-0.1.0/tests/test_compiler.py +79 -0
- helios_cortex-0.1.0/tests/test_conformance.py +72 -0
- helios_cortex-0.1.0/tests/test_contracts.py +42 -0
- helios_cortex-0.1.0/tests/test_data_policy.py +125 -0
- helios_cortex-0.1.0/tests/test_dialects.py +57 -0
- helios_cortex-0.1.0/tests/test_engine_identity.py +60 -0
- helios_cortex-0.1.0/tests/test_engine_plugins.py +123 -0
- helios_cortex-0.1.0/tests/test_environment_reads.py +70 -0
- helios_cortex-0.1.0/tests/test_import_side_effects.py +117 -0
- helios_cortex-0.1.0/tests/test_index_mappings.py +147 -0
- helios_cortex-0.1.0/tests/test_index_ontology_versions.py +76 -0
- helios_cortex-0.1.0/tests/test_index_schema.py +214 -0
- helios_cortex-0.1.0/tests/test_logging_rules.py +55 -0
- helios_cortex-0.1.0/tests/test_ontology_mapping.py +176 -0
- helios_cortex-0.1.0/tests/test_ontology_parser.py +203 -0
- helios_cortex-0.1.0/tests/test_optional_dependencies.py +133 -0
- helios_cortex-0.1.0/tests/test_plugins.py +98 -0
- helios_cortex-0.1.0/tests/test_profile_engines.py +56 -0
- helios_cortex-0.1.0/tests/test_registry.py +52 -0
- helios_cortex-0.1.0/tests/test_registry_records.py +24 -0
- helios_cortex-0.1.0/tests/test_registry_sql.py +120 -0
- helios_cortex-0.1.0/tests/test_settings.py +216 -0
- helios_cortex-0.1.0/tests/test_trino_engine.py +170 -0
- helios_cortex-0.1.0/tests/test_trino_live.py +72 -0
- helios_cortex-0.1.0/tests/test_visibility.py +40 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
tpcds/
|
|
2
|
+
*.parquet
|
|
3
|
+
__pycache__/
|
|
4
|
+
.env
|
|
5
|
+
.env.sh
|
|
6
|
+
/requirements.lock
|
|
7
|
+
.helios-python/
|
|
8
|
+
state/
|
|
9
|
+
*.db-wal
|
|
10
|
+
*.db-shm
|
|
11
|
+
node_modules/
|
|
12
|
+
apps/ui/dist/
|
|
13
|
+
apps/helios/ui/dist/
|
|
14
|
+
apps/helios/ui/src/content/docs/
|
|
15
|
+
*.tsbuildinfo
|
|
16
|
+
.cursor/
|
|
17
|
+
runs/
|
|
18
|
+
run_archive/
|
|
19
|
+
.DS_Store
|
|
20
|
+
*.pptx
|
|
21
|
+
.venv/
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# helios-cortex contracts
|
|
2
|
+
|
|
3
|
+
This file is helios-cortex's public API. The names in the tables below are the semantic-versioning
|
|
4
|
+
boundary: other packages (helios-model, helios-serve, helios-mcp, plugins and host
|
|
5
|
+
applications) may depend on them, and they change only as the policy below allows. Everything
|
|
6
|
+
else in `helios_cortex` is internal, and can change or disappear in any release.
|
|
7
|
+
|
|
8
|
+
`tests/test_contracts.py` imports every name listed here from the module given, so the tables
|
|
9
|
+
cannot drift from the code.
|
|
10
|
+
|
|
11
|
+
## Stability levels
|
|
12
|
+
|
|
13
|
+
- **Stable.** Changed only under the deprecation policy.
|
|
14
|
+
- **Provisional.** Public, but a named burndown task will reshape it. Depend on it if you need
|
|
15
|
+
to, and expect to update your code when that task lands. It becomes Stable afterwards.
|
|
16
|
+
- **Planned.** Not written yet. Listed so that the boundary is complete.
|
|
17
|
+
|
|
18
|
+
## Deprecation policy
|
|
19
|
+
|
|
20
|
+
helios-cortex is pre-1.0 (0.y.z).
|
|
21
|
+
|
|
22
|
+
- **While pre-1.0:** a release that removes or changes a Stable name bumps the minor version (y).
|
|
23
|
+
Where it can, the old spelling keeps working for one more minor release and emits a
|
|
24
|
+
`DeprecationWarning` naming its replacement. Patch releases (z) never change a Stable name.
|
|
25
|
+
- **From 1.0:** standard semantic versioning. A Stable name is deprecated in a minor release
|
|
26
|
+
(with a `DeprecationWarning` and a changelog entry) and removed no earlier than the next
|
|
27
|
+
major release.
|
|
28
|
+
- **What counts as a change:** removing or renaming a name, removing a parameter or field,
|
|
29
|
+
making an optional parameter required, narrowing an accepted type, or changing the meaning
|
|
30
|
+
of a return value. Adding optional parameters, fields or methods is not a change.
|
|
31
|
+
- **Provisional names:** may change in any minor release. The changelog says how to migrate.
|
|
32
|
+
|
|
33
|
+
## Contract
|
|
34
|
+
|
|
35
|
+
### Configuration
|
|
36
|
+
|
|
37
|
+
| Module | Names | Level | Notes |
|
|
38
|
+
|---|---|---|---|
|
|
39
|
+
| `helios_cortex.settings` | `Settings`, `ConnectionSettings`, `CatalogSettings`, `LLMSettings` | Stable | Resolution order, the config file and named connections and catalogs. A connection's `identity` (`service`, the default, `impersonate` or `token`) picks the engine identity mode. Core reads `HELIOS_*` and the LLM ecosystem's names (`ANTHROPIC_API_KEY`, `MISTRAL_API_KEY`, `LLM_PROVIDER`). A subclass adds a platform's variables by overriding `profile_sources` (after the conventional environment, before the config file); helios-cloudera's `WorkbenchSettings` reads the Workbench and Cloudera names. `registry_url` (secret) names the model registry's database. `artifact_storage` (`location` plus filesystem options, secrets hidden) puts artifacts on object storage. |
|
|
40
|
+
|
|
41
|
+
### Semantic model and compiler
|
|
42
|
+
|
|
43
|
+
| Module | Names | Level | Notes |
|
|
44
|
+
|---|---|---|---|
|
|
45
|
+
| `helios_cortex.ossie.model` | `SemanticModel`, `Dataset`, `Field`, `Relationship`, `Metric` | Stable | The in-memory form of a published Ossie model. |
|
|
46
|
+
| `helios_cortex.ossie` | `validate`, `dump_yaml`, `SPEC_VERSION` | Provisional | The Ossie format (`helios_cortex.ossie.format`): the spec version Helios writes, validation against the vendored schema plus referential checks, and YAML output. Building a document from a discovery proposal is helios-model's (`helios_model.build`). |
|
|
47
|
+
| `helios_cortex.compiler` | `Compiler`, `SemanticRequest`, `Filter`, `Measure`, `Compiled`, `CompileError`, `FilterValueTypeError` | Provisional | `compile(request, dialect)` needs a dialect: the engine's `dialect` or a SQLGlot dialect name; there is no default. |
|
|
48
|
+
|
|
49
|
+
### Ontology
|
|
50
|
+
|
|
51
|
+
| Module | Names | Level | Notes |
|
|
52
|
+
|---|---|---|---|
|
|
53
|
+
| `helios_cortex.ontology` | `OntologyGraph`, `GraphNode`, `GraphEdge`, `OntologyGraphError` | Stable | |
|
|
54
|
+
| `helios_cortex.ontology` | `SourceMapping`, `load_mapping`, `load_mappings` | Stable | |
|
|
55
|
+
|
|
56
|
+
### Index
|
|
57
|
+
|
|
58
|
+
| Module | Names | Level | Notes |
|
|
59
|
+
|---|---|---|---|
|
|
60
|
+
| `helios_cortex.index` | `IndexStore` | Stable | |
|
|
61
|
+
| `helios_cortex.index` | `OntologyVersionRecord`, `OntologyActivationRecord`, `CrawlRunRecord`, `AssetRecord`, `SegmentRecord`, `MentionRecord`, `EntityRecord`, `EntityLinkRecord`, `RelationshipRecord`, `ClaimRecord`, `ClaimEvidenceRecord`, `EvaluationRecord` | Stable | Rows of the `helios_index` tables. New optional fields are allowed. |
|
|
62
|
+
|
|
63
|
+
### Storage
|
|
64
|
+
|
|
65
|
+
| Module | Names | Level | Notes |
|
|
66
|
+
|---|---|---|---|
|
|
67
|
+
| `helios_cortex.artifacts` | `ArtifactStore`, `Activation`, `ActivationConflict`, `ArtifactError`, `ANY` | Provisional | On a local directory or object storage (`ArtifactStore.from_settings`: `[artifact_storage]` else `artifacts_dir`). Published revisions are immutable (named by their YAML's SHA-256, written once); the active revision is the newest entry of `models/<id>/active/`, and `activate(..., expected_sequence=)` is a compare-and-swap (`ActivationConflict`). `read_published_ossie` / `read_revision` work on every backend and verify hashes; methods returning a local `Path` work on a local directory only. Discovery runs live in the same storage under `runs/` (`ArtifactStore.runs`). |
|
|
68
|
+
| `helios_cortex.artifact_storage` | `ArtifactStorage`, `storage_for`, `LocalStorage` | Provisional | `storage_for(location, **options)`: a path or `file://`, `s3://` (`[s3]`), `abfs://` / `abfss://` / `az://` (`[azure]`), `gs://` (`[gcs]`), `ofs://` through Ozone HttpFS (`[ozone]`). The one conditional operation is `create` (write only if absent, atomically), on which immutability and the activation log are built. |
|
|
69
|
+
| `helios_cortex.runs` | `RunStore` | Provisional | Discovery runs, `<run_id>/{harvest,profile,propose,review}.json`: `write`, `load`, `run_ids`, `latest_run_id`, `list_runs`, `detail`. On any storage: `ArtifactStore.runs` (under `runs/`), `RunStore.from_settings` (with the artifacts on object storage, else `runs_dir`), or `RunStore(path)` for a local runs directory. `runs_dir` is a local path, None on object storage. |
|
|
70
|
+
| `helios_cortex.conformance` | `RegistryConformance`, `ArtifactStorageConformance` | Provisional | The tests every backend must pass, Helios's and third parties': subclass one and provide a `registry` or `storage` fixture returning an empty backend. The registry suite checks the `ModelRegistry` rules, including concurrent writers; the storage suite checks the operations (byte-exact content, listing at the prefix boundary, `create` atomic under 10 racing writers) and runs `ArtifactStore` and `RunStore` on the backend. Needs the `[testing]` extra (pytest). New tests may be added in minor releases; a backend that passed may then fail, which is the point. |
|
|
71
|
+
| `helios_cortex.registry` | `ModelRegistry`, `InMemoryRegistry`, `SqlRegistry`, `RegisteredModel`, `SemanticRevision`, `RegistryError`, `RegistryNotReady`, `RevisionConflict`, `DRAFT`, `PUBLISHED` | Provisional | What libraries need to find models: data sources, models (status, creation) and their immutable semantic revisions. Every backend keeps the rules in the module docstring and passes `RegistryConformance`. `InMemoryRegistry` is the reference; `SqlRegistry` stores the records in any SQLAlchemy database by URL (`Settings.registry_url`, default a SQLite file in the data directory), with Alembic migrations in the package (`python -m helios_cortex.registry upgrade`; version table `helios_registry_version`, tables prefixed `helios_`); connections are checked before use, so a database failover does not fail the next call). No ownership: which models a caller sees is the host's `ModelVisibility`. The old console keeps its own SQLite repository until Phase 8, sharing `SemanticRevision`. |
|
|
72
|
+
| `helios_cortex.domain` | `Model`, `DataSource`, `DataSourceReference` | Provisional | Registry records with no ownership (organizations left in 2.6). The registry stores them as they are. |
|
|
73
|
+
|
|
74
|
+
### Engines and LLM
|
|
75
|
+
|
|
76
|
+
| Module | Names | Level | Notes |
|
|
77
|
+
|---|---|---|---|
|
|
78
|
+
| `helios_cortex.engines` | `Engine`, `QueryResult`, `engine_for`, `SqlDialect`, `dialect_for` | Provisional | An engine plugin (`helios.engines`) is an `Engine` subclass whose `from_connection(ConnectionSettings)` validates the connection's options and honours its `identity`; `engine_for(connection)` loads the plugin a connection names and builds it. `query(sql, caller=None, *, limit)` runs as the service identity with no caller, and as the caller under the connection's identity mode otherwise; `identity_modes` lists the modes an engine supports. Plugins register under `helios.engines` (`helios_cortex.plugins`). An engine's `dialect` (a `SqlDialect`) renders the compiler's queries and Helios's own statements; plugins subclass it for what SQLGlot lacks (`render_query`, `count_distinct`, `identifier`). The catalog and statistics methods (`databases`, `tables`, `columns`, `row_count`, `recent_queries`) default to `information_schema` and `COUNT(*)`; each takes a keyword-only `caller=None` with the same meaning as `query`'s, so a harvest sees what its caller may see, and a plugin that overrides one must accept and honour it. |
|
|
79
|
+
| `helios_cortex.engines.duckdb_engine` | `DuckDBEngine`, `DuckDBOptions` | Provisional | `engine = "duckdb"`, option `path` (default `:memory:`); `service` mode only. |
|
|
80
|
+
| `helios_cortex.engines.sqlalchemy_engine` | `SqlAlchemyEngine`, `SqlAlchemyOptions` | Provisional | `engine = "sqlalchemy"`, option `url`; needs the `[sqlalchemy]` extra and the database's driver. `service` mode only; introspection through the SQLAlchemy inspector. |
|
|
81
|
+
| `helios_cortex.engines.trino_engine` | `TrinoEngine`, `TrinoOptions`, `TrinoIdentityError` | Provisional | `engine = "trino"`, options `host`, `port`, `catalog`, `schema`, `user`, `password` (basic authentication, https only), `http_scheme`, `verify`; needs the `[trino]` extra. All three identity modes: `service` (the service user), `impersonate` (authenticates as the service user, runs the session as the caller and checks `current_user`), `token` (the caller's JWT). |
|
|
82
|
+
| `helios_cortex.catalog` | `catalog_for`, `capabilities`, `GLOSSARY`, `LINEAGE`, `GlossaryCatalog`, `LineageCatalog`, `ColumnLineage`, `CatalogError` | Provisional | A catalog plugin (`helios.catalogs`) is a class whose `from_catalog(CatalogSettings)` builds it; `catalog_for` loads the one a `[catalogs.<name>]` entry names. Its capabilities are optional and detected from what it implements: `glossary` (`GlossaryCatalog`) and `lineage` (`LineageCatalog.column_lineage` → `ColumnLineage`); a plugin with neither is refused. Tables and columns come from the engine, so no catalog is needed to harvest. Atlas (helios-cloudera) offers both. Harvesting with a catalog is helios-model's (`helios_model.Catalog`, over `helios_model.harvest.TableHarvester`); the glossary is read with the catalog's own credentials, not the caller's. |
|
|
83
|
+
| `helios_cortex.llm` | `LLMClient`, `LLMError`, `LLMTimeoutError`, `llm_from_settings` | Stable | Needs the `[llm]` extra; without it, importing the module says so. |
|
|
84
|
+
|
|
85
|
+
### Identity and plugins
|
|
86
|
+
|
|
87
|
+
| Module | Names | Level | Notes |
|
|
88
|
+
|---|---|---|---|
|
|
89
|
+
| `helios_cortex` | `IdentityMode`, `IdentityError` | Stable | `service`, `impersonate`, `token`; `IdentityError` (a `PermissionError`) when a caller lacks the username or token its mode needs. |
|
|
90
|
+
| `helios_cortex.data_authorization` | `DataPolicy`, `DataResource`, `DataAction`, `EngineIdentityAuthorizer`, `PlatformDataAuthorizer`, `PlatformDataDecision`, `DataRestriction`, `DataRestrictionDecision`, `DataAuthorizationDecision`, `DataAuthorizationDenied` | Stable | Platform enforcement plus deny-only host restrictions. The default platform authorizer allows query execution only when `DataResource.identity_mode` runs it as the caller. |
|
|
91
|
+
| `helios_cortex.visibility` | `ModelVisibility`, `AllModels`, `ModelNotVisible`, `visible_models`, `require_visible` | Stable | The host decides which models a caller may list and use; the default shows every model in the registry. A hidden model raises the same `LookupError` as a missing one. |
|
|
92
|
+
| `helios_cortex.audit_sink` | `AuditRecord`, `AuditSink`, `LoggingAuditSink`, `record_safely`, `sql_fingerprint` | Stable | Libraries emit `AuditRecord`s (action, outcome, model, caller username, row count, SQL fingerprint, error); the host's sink stores them. The default logs to `helios_cortex.audit_sink`. New optional fields are allowed. |
|
|
93
|
+
| `helios_cortex` | `Caller` | Stable | The host's caller: `username`, `token` (left out of `repr`, never logged) and free-form `attributes`, all optional. Helios authenticates no one; the engine's identity mode (2.2) decides which field it uses. |
|
|
94
|
+
| `helios_cortex.plugins` | `load`, `installed`, `names`, `missing_configured`, `require_configured`, `PluginInfo`, `PluginError`, `PluginNotFound`, `PluginLoadError`, `ENGINES`, `CATALOGS`, `STORES`, `TOOLS`, `COMMANDS`, `GROUPS` | Provisional | Entry-point groups `helios.engines`, `helios.catalogs`, `helios.stores`, `helios.tools`, `helios.commands`; the group names are Stable. What a plugin object must provide is set per group: engines in 3.5 (an `Engine` subclass with `from_connection`; see `helios_cortex.engines`), catalogs in 3.7 (a class with `from_catalog`; see `helios_cortex.catalog`), stores in 4.x, tools in 5.x, commands in 5.5. Settings that name a missing plugin still load; `require_configured` is the host's startup check. |
|
|
95
|
+
|
|
96
|
+
## Internal
|
|
97
|
+
|
|
98
|
+
Everything not in a table above is internal. Most of it is leaving helios-cortex, which is
|
|
99
|
+
why it stays where it is instead of moving under `_internal/` and then moving again:
|
|
100
|
+
|
|
101
|
+
| Code | Where it goes |
|
|
102
|
+
|---|---|
|
|
103
|
+
| `ontology/parser.py`, the rest of `ontology/mapping.py`, `index/` modules other than the store and records | Reviewed for promotion when helios-crawl is built (Phase 10) |
|
|
104
|
+
| `_pending/` | helios-serve and helios-crawl; import-linter keeps other code from importing it |
|
|
105
|
+
|
|
106
|
+
## Typing
|
|
107
|
+
|
|
108
|
+
helios-cortex ships `py.typed`. The type annotations on contract names are part of the contract.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: helios-cortex
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Helios core: shared semantic query and data governance layer
|
|
5
|
+
Author: Helios Team
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Requires-Dist: alembic>=1.13
|
|
9
|
+
Requires-Dist: duckdb>=1.3.0
|
|
10
|
+
Requires-Dist: jsonschema>=4.23.0
|
|
11
|
+
Requires-Dist: platformdirs>=4.0
|
|
12
|
+
Requires-Dist: pydantic-settings>=2.6
|
|
13
|
+
Requires-Dist: pydantic>=2.9.0
|
|
14
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
15
|
+
Requires-Dist: sqlalchemy>=2.0
|
|
16
|
+
Requires-Dist: sqlglot>=27.0.0
|
|
17
|
+
Provides-Extra: azure
|
|
18
|
+
Requires-Dist: adlfs>=2024.4; extra == 'azure'
|
|
19
|
+
Provides-Extra: evidence
|
|
20
|
+
Requires-Dist: lancedb>=0.39.0; extra == 'evidence'
|
|
21
|
+
Requires-Dist: sentence-transformers>=6.1.0; extra == 'evidence'
|
|
22
|
+
Provides-Extra: gcs
|
|
23
|
+
Requires-Dist: gcsfs>=2024.6; extra == 'gcs'
|
|
24
|
+
Provides-Extra: llm
|
|
25
|
+
Requires-Dist: httpx>=0.27.0; extra == 'llm'
|
|
26
|
+
Provides-Extra: ontology
|
|
27
|
+
Requires-Dist: linkml-runtime>=1.8.0; extra == 'ontology'
|
|
28
|
+
Provides-Extra: ozone
|
|
29
|
+
Requires-Dist: fsspec>=2024.6; extra == 'ozone'
|
|
30
|
+
Requires-Dist: requests>=2.32; extra == 'ozone'
|
|
31
|
+
Provides-Extra: postgres
|
|
32
|
+
Requires-Dist: psycopg[binary]>=3.2; extra == 'postgres'
|
|
33
|
+
Provides-Extra: s3
|
|
34
|
+
Requires-Dist: s3fs>=2024.6; extra == 's3'
|
|
35
|
+
Provides-Extra: testing
|
|
36
|
+
Requires-Dist: pytest>=8.0; extra == 'testing'
|
|
37
|
+
Provides-Extra: trino
|
|
38
|
+
Requires-Dist: trino>=0.330; extra == 'trino'
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "helios-cortex"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Helios core: shared semantic query and data governance layer"
|
|
9
|
+
authors = [{name = "Helios Team"}]
|
|
10
|
+
license = "Apache-2.0"
|
|
11
|
+
requires-python = ">=3.11"
|
|
12
|
+
# The base install: the compiler, semantic model, DuckDB, and the model registry on
|
|
13
|
+
# SQLite (SQLAlchemy and Alembic; the database itself is the standard library).
|
|
14
|
+
# Everything else is an extra; tests/test_optional_dependencies.py keeps it so.
|
|
15
|
+
dependencies = [
|
|
16
|
+
"duckdb>=1.3.0",
|
|
17
|
+
"jsonschema>=4.23.0",
|
|
18
|
+
"platformdirs>=4.0",
|
|
19
|
+
"pydantic>=2.9.0",
|
|
20
|
+
"pydantic-settings>=2.6",
|
|
21
|
+
"pyyaml>=6.0.0", # semantic model files and ontology mappings
|
|
22
|
+
"sqlglot>=27.0.0",
|
|
23
|
+
"sqlalchemy>=2.0", # the model registry (SQLite by default) and the sqlalchemy engine
|
|
24
|
+
"alembic>=1.13", # registry schema migrations
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.optional-dependencies]
|
|
28
|
+
# LLM providers (helios_cortex.llm), used to propose models.
|
|
29
|
+
llm = [
|
|
30
|
+
"httpx>=0.27.0",
|
|
31
|
+
]
|
|
32
|
+
# LinkML ontology parsing (helios_cortex.ontology.parser).
|
|
33
|
+
ontology = [
|
|
34
|
+
"linkml-runtime>=1.8.0",
|
|
35
|
+
]
|
|
36
|
+
# Postgres for the registry (postgresql+psycopg://...) and the sqlalchemy engine. Other
|
|
37
|
+
# databases: install their SQLAlchemy driver (snowflake-sqlalchemy, mysqlclient, ...).
|
|
38
|
+
postgres = [
|
|
39
|
+
"psycopg[binary]>=3.2",
|
|
40
|
+
]
|
|
41
|
+
# The trino engine plugin (all three identity modes).
|
|
42
|
+
trino = [
|
|
43
|
+
"trino>=0.330",
|
|
44
|
+
]
|
|
45
|
+
# Object storage for the ArtifactStore (helios_cortex.artifact_storage), by URL scheme.
|
|
46
|
+
s3 = [
|
|
47
|
+
"s3fs>=2024.6", # s3:// (AWS S3, MinIO, Ozone's S3 gateway)
|
|
48
|
+
]
|
|
49
|
+
azure = [
|
|
50
|
+
"adlfs>=2024.4", # abfs://, abfss://, az:// (ADLS Gen2, Blob storage)
|
|
51
|
+
]
|
|
52
|
+
gcs = [
|
|
53
|
+
"gcsfs>=2024.6", # gs://
|
|
54
|
+
]
|
|
55
|
+
ozone = [
|
|
56
|
+
"fsspec>=2024.6", # ofs://, through Ozone's HttpFS (WebHDFS) gateway
|
|
57
|
+
"requests>=2.32",
|
|
58
|
+
]
|
|
59
|
+
# The backend conformance suite (helios_cortex.conformance), for testing a registry or
|
|
60
|
+
# storage backend.
|
|
61
|
+
testing = [
|
|
62
|
+
"pytest>=8.0",
|
|
63
|
+
]
|
|
64
|
+
# Searching crawled documents. Without these, crawls run and evidence search
|
|
65
|
+
# reports that it is unavailable. sentence-transformers brings PyTorch.
|
|
66
|
+
evidence = [
|
|
67
|
+
"lancedb>=0.39.0",
|
|
68
|
+
"sentence-transformers>=6.1.0",
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
# The built-in engine plugins. Impala and Atlas come with helios-cloudera
|
|
72
|
+
# (see helios_cortex.plugins). trino needs its extra; sqlalchemy needs the database's driver.
|
|
73
|
+
[project.entry-points."helios.engines"]
|
|
74
|
+
duckdb = "helios_cortex.engines.duckdb_engine:DuckDBEngine"
|
|
75
|
+
sqlalchemy = "helios_cortex.engines.sqlalchemy_engine:SqlAlchemyEngine"
|
|
76
|
+
trino = "helios_cortex.engines.trino_engine:TrinoEngine"
|
|
77
|
+
|
|
78
|
+
[tool.hatch.build.targets.wheel]
|
|
79
|
+
packages = ["src/helios_cortex"]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""helios core library: shared clients and logic for jobs and applications."""
|
|
2
|
+
|
|
3
|
+
from helios_cortex.caller import Caller, IdentityError, IdentityMode
|
|
4
|
+
|
|
5
|
+
__all__ = ["Caller", "IdentityError", "IdentityMode"]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def __getattr__(name: str) -> str:
|
|
9
|
+
# __version__ is read from the installed metadata on first use, so importing
|
|
10
|
+
# helios_cortex opens no files.
|
|
11
|
+
if name == "__version__":
|
|
12
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
return version("helios-cortex")
|
|
16
|
+
except PackageNotFoundError: # running from a source path without an install
|
|
17
|
+
return "0.0.0+unknown"
|
|
18
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Optional dependencies: the base install is the compiler, semantic model, DuckDB and
|
|
2
|
+
SQLite; anything else comes with an extra (``pip install 'helios-cortex[llm]'``).
|
|
3
|
+
|
|
4
|
+
A module that needs an extra raises ``missing_extra(...)`` from the ImportError, so
|
|
5
|
+
the message says what to install instead of naming a package the user never chose.
|
|
6
|
+
Base modules import those modules only where they are used.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def missing_extra(feature: str, extra: str, error: ImportError) -> ModuleNotFoundError:
|
|
12
|
+
"""The error for ``feature`` when the package ``error`` failed to import is missing."""
|
|
13
|
+
return ModuleNotFoundError(
|
|
14
|
+
f"{feature} needs the optional dependency {error.name or 'it imports'}: "
|
|
15
|
+
f"pip install 'helios-cortex[{extra}]'",
|
|
16
|
+
name=error.name,
|
|
17
|
+
)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""Feature code that core used to reach into, held here until its package exists.
|
|
2
|
+
|
|
3
|
+
- health: helios-serve (Phase 6)
|
|
4
|
+
- crawler, crawler_settings, evidence, browse: helios-crawl (Phase 10)
|
|
5
|
+
|
|
6
|
+
Nothing outside this directory in helios_cortex may import it; import-linter
|
|
7
|
+
enforces that (burndown 1.2). Each module leaves when its package is created.
|
|
8
|
+
"""
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""Browsing what the crawler found, from an ontology class down to passages
|
|
2
|
+
(CR-9): the entities of a class, then one entity's documents and the passages
|
|
3
|
+
that mention it.
|
|
4
|
+
|
|
5
|
+
Reads each source's latest successful crawl. A finished run never changes, so
|
|
6
|
+
its tables are kept in memory; runs that are no longer the latest are dropped.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import posixpath
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
from helios_cortex._pending import evidence
|
|
15
|
+
from helios_cortex.index.records import AssetRecord, EntityRecord, MentionRecord, RelationshipRecord, SegmentRecord
|
|
16
|
+
from helios_cortex.index.store import IndexStore
|
|
17
|
+
|
|
18
|
+
ASSETS = "helios_index.assets"
|
|
19
|
+
SEGMENTS = "helios_index.segments"
|
|
20
|
+
MENTIONS = "helios_index.mentions"
|
|
21
|
+
ENTITY_LINKS = "helios_index.entity_links"
|
|
22
|
+
RELATIONSHIPS = "helios_index.relationships"
|
|
23
|
+
MAX_DOCUMENTS = 30
|
|
24
|
+
|
|
25
|
+
_tables: dict[tuple[str, str], list[Any]] = {}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _rows(store: IndexStore, crawl_run_id: str, table: str) -> list[Any]:
|
|
29
|
+
key = (crawl_run_id, table)
|
|
30
|
+
if key not in _tables:
|
|
31
|
+
_tables[key] = store.read(table, {"crawl_run_id": crawl_run_id})
|
|
32
|
+
return _tables[key]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _latest(store: IndexStore) -> list[Any]:
|
|
36
|
+
latest = evidence.latest_runs(store)
|
|
37
|
+
keep = {run.crawl_run_id for run in latest}
|
|
38
|
+
for key in [k for k in _tables if k[0] not in keep]:
|
|
39
|
+
del _tables[key]
|
|
40
|
+
return latest
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _entity_view(entity: EntityRecord, source: str) -> dict[str, Any]:
|
|
44
|
+
return {
|
|
45
|
+
"entity_id": entity.entity_id,
|
|
46
|
+
"class": entity.ontology_class,
|
|
47
|
+
"name": entity.canonical_name,
|
|
48
|
+
"keys": list(entity.external_ids),
|
|
49
|
+
"source": source,
|
|
50
|
+
"crawl_run_id": entity.crawl_run_id,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def class_entities(
|
|
55
|
+
store: IndexStore, classes: list[str], query: str = "", limit: int = 50
|
|
56
|
+
) -> dict[str, Any]:
|
|
57
|
+
"""Entities of the given ontology classes, most-documented first."""
|
|
58
|
+
wanted = {c.casefold() for c in classes}
|
|
59
|
+
needle = query.strip().casefold()
|
|
60
|
+
found: list[dict[str, Any]] = []
|
|
61
|
+
for run in _latest(store):
|
|
62
|
+
documents: dict[str, set[str]] = {}
|
|
63
|
+
for rel in _rows(store, run.crawl_run_id, RELATIONSHIPS):
|
|
64
|
+
if isinstance(rel, RelationshipRecord) and (rel.source_kind, rel.target_kind) == ("asset", "entity"):
|
|
65
|
+
documents.setdefault(rel.target_id, set()).add(rel.source_id)
|
|
66
|
+
for entity in _rows(store, run.crawl_run_id, evidence.ENTITIES):
|
|
67
|
+
if not isinstance(entity, EntityRecord) or entity.ontology_class.casefold() not in wanted:
|
|
68
|
+
continue
|
|
69
|
+
haystack = " ".join([entity.canonical_name, *entity.external_ids]).casefold()
|
|
70
|
+
if needle and needle not in haystack:
|
|
71
|
+
continue
|
|
72
|
+
found.append(
|
|
73
|
+
{**_entity_view(entity, run.source), "documents": len(documents.get(entity.entity_id, ()))}
|
|
74
|
+
)
|
|
75
|
+
found.sort(key=lambda e: (-e["documents"], e["name"]))
|
|
76
|
+
return {"total": len(found), "entities": found[: max(1, min(limit, 500))]}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _document_name(asset: AssetRecord) -> str:
|
|
80
|
+
locator = asset.source_locator or {}
|
|
81
|
+
path = str(locator.get("key") or locator.get("uri") or locator.get("path") or "")
|
|
82
|
+
return posixpath.basename(path) or asset.asset_id
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def entity_documents(store: IndexStore, crawl_run_id: str, entity_id: str) -> dict[str, Any] | None:
|
|
86
|
+
"""One entity with its documents, the passages that mention it (with the
|
|
87
|
+
character ranges of each mention), related entities and claims."""
|
|
88
|
+
run = next((r for r in _latest(store) if r.crawl_run_id == crawl_run_id), None)
|
|
89
|
+
if run is None:
|
|
90
|
+
return None
|
|
91
|
+
entities = {
|
|
92
|
+
e.entity_id: e for e in _rows(store, crawl_run_id, evidence.ENTITIES) if isinstance(e, EntityRecord)
|
|
93
|
+
}
|
|
94
|
+
entity = entities.get(entity_id)
|
|
95
|
+
if entity is None:
|
|
96
|
+
return None
|
|
97
|
+
|
|
98
|
+
relation: dict[str, str] = {} # asset_id -> About or Mentions (About wins)
|
|
99
|
+
related: list[dict[str, Any]] = []
|
|
100
|
+
for rel in _rows(store, crawl_run_id, RELATIONSHIPS):
|
|
101
|
+
if not isinstance(rel, RelationshipRecord):
|
|
102
|
+
continue
|
|
103
|
+
if rel.source_kind == "asset" and rel.target_id == entity_id:
|
|
104
|
+
if relation.get(rel.source_id) != "About":
|
|
105
|
+
relation[rel.source_id] = rel.relationship_type
|
|
106
|
+
elif rel.source_kind == "entity" and entity_id in (rel.source_id, rel.target_id):
|
|
107
|
+
other = entities.get(rel.target_id if rel.source_id == entity_id else rel.source_id)
|
|
108
|
+
if other is not None:
|
|
109
|
+
related.append(
|
|
110
|
+
{
|
|
111
|
+
"relationship": rel.relationship_type,
|
|
112
|
+
"direction": "out" if rel.source_id == entity_id else "in",
|
|
113
|
+
"entity_id": other.entity_id,
|
|
114
|
+
"class": other.ontology_class,
|
|
115
|
+
"name": other.canonical_name,
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
links = {
|
|
120
|
+
link.mention_id: link
|
|
121
|
+
for link in store.read(ENTITY_LINKS, {"crawl_run_id": crawl_run_id, "entity_id": entity_id})
|
|
122
|
+
}
|
|
123
|
+
by_segment: dict[str, list[dict[str, Any]]] = {}
|
|
124
|
+
for mention in _rows(store, crawl_run_id, MENTIONS):
|
|
125
|
+
link = links.get(mention.mention_id) if isinstance(mention, MentionRecord) else None
|
|
126
|
+
if link is None:
|
|
127
|
+
continue
|
|
128
|
+
by_segment.setdefault(mention.segment_id, []).append(
|
|
129
|
+
{
|
|
130
|
+
"surface_form": mention.surface_form,
|
|
131
|
+
"start": mention.start_offset,
|
|
132
|
+
"end": mention.end_offset,
|
|
133
|
+
"resolved_by": link.resolved_by,
|
|
134
|
+
"link_type": link.link_type,
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
passages: dict[str, list[dict[str, Any]]] = {}
|
|
138
|
+
for segment in _rows(store, crawl_run_id, SEGMENTS):
|
|
139
|
+
if isinstance(segment, SegmentRecord) and segment.segment_id in by_segment:
|
|
140
|
+
passages.setdefault(segment.asset_id, []).append(
|
|
141
|
+
{
|
|
142
|
+
"segment_id": segment.segment_id,
|
|
143
|
+
"segment_type": segment.segment_type,
|
|
144
|
+
"ordinal": segment.ordinal,
|
|
145
|
+
"locator": segment.locator,
|
|
146
|
+
"text": segment.text,
|
|
147
|
+
"mentions": sorted(
|
|
148
|
+
by_segment[segment.segment_id], key=lambda m: (m["start"] is None, m["start"] or 0)
|
|
149
|
+
),
|
|
150
|
+
}
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
documents = []
|
|
154
|
+
for asset in _rows(store, crawl_run_id, ASSETS):
|
|
155
|
+
if not isinstance(asset, AssetRecord):
|
|
156
|
+
continue
|
|
157
|
+
if asset.asset_id not in relation and asset.asset_id not in passages:
|
|
158
|
+
continue
|
|
159
|
+
documents.append(
|
|
160
|
+
{
|
|
161
|
+
"asset_id": asset.asset_id,
|
|
162
|
+
"name": _document_name(asset),
|
|
163
|
+
"class": asset.ontology_class,
|
|
164
|
+
"mime_type": asset.mime_type,
|
|
165
|
+
"timestamp": asset.semantic_timestamp,
|
|
166
|
+
"relationship": relation.get(asset.asset_id, "Mentions"),
|
|
167
|
+
"passages": sorted(passages.get(asset.asset_id, []), key=lambda p: p["ordinal"]),
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
documents.sort(
|
|
171
|
+
key=lambda d: (d["relationship"] != "About", -len(d["passages"]), d["timestamp"] or "", d["name"])
|
|
172
|
+
)
|
|
173
|
+
claims = evidence.entity_claims(store, entity_id)
|
|
174
|
+
return {
|
|
175
|
+
"entity": _entity_view(entity, run.source),
|
|
176
|
+
"documents_total": len(documents),
|
|
177
|
+
"documents": documents[:MAX_DOCUMENTS],
|
|
178
|
+
"related": sorted(related, key=lambda r: (r["relationship"], r["name"]))[:50],
|
|
179
|
+
"claims_total": claims["claims_total"],
|
|
180
|
+
"claims": claims["claims"],
|
|
181
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"""Shared crawler definitions: settings (CR-0e). The crawler itself runs as a
|
|
2
|
+
Workbench Job in the Helios project (apps/helios/crawler)."""
|
|
3
|
+
|
|
4
|
+
from helios_cortex._pending.crawler.settings import EMPTY_SETTINGS, CrawlerSettings, load_preset, ontology_problems, presets
|
|
5
|
+
|
|
6
|
+
__all__ = ["EMPTY_SETTINGS", "CrawlerSettings", "load_preset", "ontology_problems", "presets"]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Shipped crawler settings presets. Each is <name>.yaml in this directory: a
|
|
2
|
+
# complete settings document a user can load, edit and save as a version.
|
|
3
|
+
presets:
|
|
4
|
+
retail-returns:
|
|
5
|
+
title: Retail returns
|
|
6
|
+
description: >-
|
|
7
|
+
Store returns over a TPC-DS warehouse: emails, chat threads and PDF return
|
|
8
|
+
reports. Identifier patterns for RMA, case and ticket numbers, the PDF
|
|
9
|
+
report's labels, and cue phrases for damage, return reason and refunds.
|
|
10
|
+
|
|
11
|
+
# Before settings schema 2 one set of rules was built into the crawler. A stored
|
|
12
|
+
# schema 1 document is read as this preset with the document's sections on top.
|
|
13
|
+
schema_1_defaults: retail-returns
|