dosi-semantic-authoring
GitHub指导基于严格 OSI YAML 规范构建 Dosi 语义模型,涵盖数据集、字段、关系及指标的编写规则。重点强调使用 DDL 声明作为键和关系的唯一证据,禁止通过查询数据推断主键或外键,确保语义模型的准确性和可验证性。
Trigger Scenarios
Install
npx skills add Datus-ai/Datus-agent --skill dosi-semantic-authoring -g -y
SKILL.md
Frontmatter
{
"name": "dosi-semantic-authoring",
"tags": [
"semantic-model",
"metrics",
"osi",
"dosi"
],
"version": "1.2.0",
"description": "Dosi native OSI dataset, relationship, and metric authoring guidance",
"allowed_agents": [
"semantic_modeling",
"gen_semantic_model",
"gen_metrics"
],
"user_invocable": false,
"disable_model_invocation": false
}
Dosi Semantic Authoring
Author the active Dosi semantic model as strict OSI core YAML. Use this skill for native document authoring rules; use the active adapter specification and native validation as the exact document and DATUS-extension contract. The node prompt owns target selection, result-set strategy, mutation order, validation, and synchronization.
Model reusable semantics
- Keep one
semantic_modelper file and stablesnake_casenames. Preserve unrelated content; an upsert replaces the complete same-named object. - Bind a dataset to a qualified physical table or a complete reusable SELECT. Declare every referenced physical column as a field with the active OSI dialect.
- Mark time fields with
dimension: {is_time: true}. Keep other fields available as dimensions. - Use source DDL as the only evidence for new key declarations. For a physical table, transcribe its declared physical primary key into
primary_keyand its declared unique constraints or whole-table unique indexes on plain columns intounique_keys. Preserve each complete composite key and its declared column order. Partial or expression indexes do not establish a whole-table key on their named columns. ClickHousePRIMARY KEY/ORDER BYand StarRocks/DorisDUPLICATE KEYare sort keys, not uniqueness declarations. - Do not execute data queries to discover or verify keys, including full-table NULL/duplicate checks. Samples, approximate distinct counts, column names, SQL JOINs, and stated grain are not substitutes for DDL key declarations.
- If the DDL is unavailable or declares no usable key, leave the key undeclared and continue modeling fields, datasets, and independent metrics. Do not block the whole request or ask to scan the table to fill the gap. For a query-backed dataset, retain a DDL-declared source key only when the query provably preserves it; a one-to-many join can repeat it. Otherwise leave the key undeclared without scanning the source or query result.
- Give a field a
labelwhen its column name is not what a reader would call it. - Give a dataset
ai_context.instructionswhen its grain or intended use does not follow from the description, and give a fieldai_context.synonymswhen users ask for it by a name the column does not carry. Leave both out otherwise: restating the description dilutes what a reader can act on. - Define model-level relationships with aligned
from_columnsandto_columns; bind the target columns to one complete DDL-declared key that holds at the target dataset's grain. If no such key is available, omit the new relationship and any metrics that cannot be faithfully modeled without it, explain the omission, and continue with the remaining assets. Do not invent a key to make a relationship or metric compile.
Choose DATUS metric capabilities
Put Dosi-only metadata in the owning object's DATUS custom_extensions entry. Encode data as one JSON-object string and stamp it with the runtime <datus_extension_version>. The injected active DATUS extension specification is authoritative for supported carriers, keys, exact shapes, enums, constraints, and examples; never invent a field from this conceptual guide.
-
Prefer a plain base metric when one aggregate or arithmetic expression completely represents the business meaning.
-
Use a derived filter metric when the business concept narrows one reusable base metric. Use a derived compose metric only when the result combines two or more reusable metrics. Author and validate every referenced base metric first; do not inline its calculation again or create a one-input passthrough.
-
Use a structured window metric for period comparison, rolling, cumulative, ranking, distribution, or framed statistical calculations. Keep the underlying OSI expression as the plain aggregate described by the active contract.
-
Use a parameterized metric only when different callers must supply a bounded runtime business input to the same reusable definition. Stable policy belongs in the metric itself. Declare each parameter's type, default, and allowed values or bounds according to the active contract.
-
Use explicit measure metadata only when the metric needs a stable engine-facing measure identity or behavior that cannot be inferred from its OSI expression.
-
Combine capabilities only when the active contract explicitly permits their keys and dependencies on the same carrier. If the requested capability is absent from that contract, report it as unsupported by the installed engine instead of approximating it in YAML.
-
Use
time_dimensionto resolve the business time when inference is ambiguous; qualify metric-level references when field names collide. -
Use
time_granularityfor the field's stored grain andjoin_typeforleftorinnerrelationship behavior. -
Use metric
datasetto attribute an otherwise unbound aggregate such asCOUNT(*). -
Give each business metric a description,
ai_context.instructions, and a three-levelsubject_path.
- name: revenue
description: Total order revenue
ai_context: {instructions: Use order_date as business time.}
expression: {dialects: [{dialect: <osi_dialect>, expression: SUM(orders.amount)}]}
custom_extensions:
- vendor_name: DATUS
data: '{"v":"<datus_extension_version>","time_dimension":"orders.order_date","subject_path":["sales","revenue","total"],"unit":"USD"}'
Author base and window metrics
-
Express a base metric with its natural aggregate, ratio, or arithmetic expression. Put a durable metric condition inside its aggregate with
CASE WHEN. -
Express each window result as a standalone metric whose OSI expression is one plain aggregate. Put the derivation in one structured
windowobject. -
Choose the window family from the intended calculation and use the exact form advertised by the active contract.
-
Derive time, query grain, ordering, partition, and frame from the requested analytic meaning. Treat query grain as a runtime argument.
-
Reuse a window metric only when its base aggregate, time axis, calculation, ordering, partition, and frame all match.
-
Preserve meaningful window nulls for missing comparison buckets or incomplete required frames.
Validate the final model with the native Dosi parser/compiler after the last mutation.
For a parameterized metric, inspect its param_schema in list_metrics, then verify query behavior with query_metrics(params={...}, dry_run=True). Exercise the default and meaningful enum/boundary or list-valued cases; never invent undeclared parameter names. Native validation proves the definition compiles, while this optional query check proves a user-requested binding shape.
Version History
-
6da6962
Current 2026-09-23 03:22
重构为仅依赖 DDL 声明来确定主键和唯一键,移除了对全表扫描和数据验证的依赖;移除未使用的语义子树上下文查找逻辑。
-
71384a0
2026-08-29 00:05
补充了ai_context、label、primary_key/unique_keys的使用条件;明确datatype字段不被支持;细化了键值转录与推断的区别及验证要求。
- 8fb79f6 2026-08-20 12:33


