en un clic
insurance-claim-routing-demo
// Interactive demo: Generate pseudo-labels from a strong teacher model, build a cheap student function, and evaluate accuracy. Showcases pseudo-labeling and teacher-student distillation.
// Interactive demo: Generate pseudo-labels from a strong teacher model, build a cheap student function, and evaluate accuracy. Showcases pseudo-labeling and teacher-student distillation.
Create, evaluate, and optimize custom AI functions using Snowflake Cortex AI Complete. Supports text, image, and document inputs. Use when: building LLM-powered functions, evaluating AI function performance, tuning prompts, selecting models, checking async job status. Triggers: ai function builder, custom ai function, user defined ai function, build my own llm function, evaluate ai function, tune ai function, optimize ai function, demo ai function, resume ai function job, image classification, document analysis, multimodal ai function.
Create a new custom AI function. Supports table-based or manual input specification, single or variant outputs. Direct AI_COMPLETE calls or additional pre- and post-processing.
Quick Start demo: Build a toxicity classifier and evaluate it — the fastest way to experience the core create → evaluate workflow.
Interactive demo: Build a legal contract field extractor and create a weighted composite metric that scores 4 fields independently. Showcases custom evaluation metrics for multi-field AI functions.
Interactive demo: Extract structured fields from SEC 10-K filing PDFs using multimodal AI, create a custom composite metric for per-field scoring, and evaluate extraction accuracy with per-field analysis.
Interactive demo: Build a policy-conditioned ticket router where a seed prompt performs poorly, then watch prompt optimization close the accuracy gap through prompt evolution and Pareto cost/quality analysis. The canonical demo for prompt optimization.
| name | insurance-claim-routing-demo |
| description | Interactive demo: Generate pseudo-labels from a strong teacher model, build a cheap student function, and evaluate accuracy. Showcases pseudo-labeling and teacher-student distillation. |
| parent_skill | demos |
Build an AI function that routes insurance claims using pseudo-labeled training data.
Seed input-only data → pseudo-label with a strong teacher → build a cheap student function → evaluate. Estimated time: ~10 minutes.
Explain to user:
Welcome to the Pseudo-Labeling & Teacher-Student Distillation Demo!
At the end of this demo, you will witness the Cortex AI Function Studio's ability to:
- Generate pseudo-labels using a strong teacher model (no labeled data needed!)
- Build a cheap student model that reproduces teacher-quality decisions
- Evaluate how closely the student matches the teacher using the exact_match metric
This demo starts with unlabeled claim intake records. We will use a strong
teacher model to create routing labels, then build a cheaper student model
and measure how closely it reproduces those decisions.
Claim routes:
- fast_track_auto
- property_damage
- injury_review
- fraud_review
- documentation_needed
- manual_specialist_review
Objects created: all prefixed with DEMO_ for easy cleanup.
If {database} and {schema} are already known from the prerequisite flow, accept them silently and skip the prompt.
Otherwise, ask user:
Where would you like to create the demo objects?
Database: [e.g., TEMP]
Schema: [e.g., PUBLIC]
Store the database and schema for use throughout the demo.
Explain to user:
I'll load 80 realistic insurance claim intake records from a pre-generated set:
auto collisions, property damage, theft, injury, fraud, and documentation cases.
Columns:
- CLAIM_SUMMARY (pre-generated, unique per row)
- INCIDENT_CHANNEL
- CUSTOMER_SEGMENT
I'll create:
- {database}.{schema}.DEMO_CLAIMS_UNLABELED
Run the data generation script:
PYTHONPATH=<SKILL_DIRECTORY>/src uv run --project <SKILL_DIRECTORY> python <SKILL_DIRECTORY>/src/generate_claims_data.py load \
--connection <CONNECTION_NAME> \
--database {database} \
--schema {schema}
Note: Replace <SKILL_DIRECTORY> with the absolute path to the cortex-ai-function-studio skill directory, and <CONNECTION_NAME> with the active Snowflake connection.
Verify creation and confirm summaries are diverse:
SELECT COUNT(*) FROM {database}.{schema}.DEMO_CLAIMS_UNLABELED;
SELECT LEFT(CLAIM_SUMMARY, 150) AS SUMMARY_PREVIEW, INCIDENT_CHANNEL, CUSTOMER_SEGMENT
FROM {database}.{schema}.DEMO_CLAIMS_UNLABELED
LIMIT 5;
Present the pseudo-label configuration:
Now we'll use a strong teacher model to label each claim intake row.
Default teacher model: claude-opus-4-6 (or the strongest available Claude Opus variant)
Fallback: use the strongest available Claude-family model in the account
Source table: {database}.{schema}.DEMO_CLAIMS_UNLABELED
Input columns: CLAIM_SUMMARY, INCIDENT_CHANNEL, CUSTOMER_SEGMENT
Output fields:
- claim_route (string) — routing category
Destination table: {database}.{schema}.DEMO_CLAIMS_DATA
If the default teacher model is unavailable, load references/model_selection.md and choose the strongest Claude-family option.
MANDATORY: Do not synthesize labels ad hoc in this demo. Load synthetic-data/SKILL.md and follow the Pseudo-Label Input-Only Tables workflow.
Pass this context into that workflow:
source_table: {database}.{schema}.DEMO_CLAIMS_UNLABELEDinput_columns: ['CLAIM_SUMMARY', 'INCIDENT_CHANNEL', 'CUSTOMER_SEGMENT']output_table: {database}.{schema}.DEMO_CLAIMS_DATAmodel: {teacher_model}task_description: Classify each claim intake row into exactly one routing category: fast_track_auto, property_damage, injury_review, fraud_review, documentation_needed, or manual_specialist_review.output_schema: {"properties": {"claim_route": {"type": "string", "description": "One of: fast_track_auto, property_damage, injury_review, fraud_review, documentation_needed, manual_specialist_review"}}}preview_rows: 0The label-synthesis workflow must:
EXPECTED as the default label columnShow the label distribution after labeling completes:
SELECT EXPECTED:claim_route::STRING AS CLAIM_ROUTE, COUNT(*) AS ROW_COUNT
FROM {database}.{schema}.DEMO_CLAIMS_DATA
GROUP BY 1
ORDER BY ROW_COUNT DESC;
The pseudo-label workflow stores labels as a VARIANT column (EXPECTED). Since our output has a single field, convert it to a plain string column for evaluation:
ALTER TABLE {database}.{schema}.DEMO_CLAIMS_DATA ADD COLUMN EXPECTED_OUTPUT VARCHAR;
UPDATE {database}.{schema}.DEMO_CLAIMS_DATA SET EXPECTED_OUTPUT = EXPECTED:claim_route::STRING;
ALTER TABLE {database}.{schema}.DEMO_CLAIMS_DATA DROP COLUMN EXPECTED;
Present the function configuration:
Now we'll create a cheaper student model for claim routing.
Default student model: llama3.1-8b
Function name: DEMO_ROUTE_CLAIM
Inputs: CLAIM_SUMMARY, INCIDENT_CHANNEL, CUSTOMER_SEGMENT
Outputs:
- claim_route (string) — routing category
System prompt:
"You are an insurance claim routing system. Given a claim summary, incident
channel, and customer segment, classify the claim into exactly one route:
fast_track_auto, property_damage, injury_review, fraud_review,
documentation_needed, or manual_specialist_review."
User prompt template:
"Claim summary: {CLAIM_SUMMARY}\nIncident channel: {INCIDENT_CHANNEL}\nCustomer segment: {CUSTOMER_SEGMENT}"
⚠️ STOP: Wait for user confirmation before creating the function.
Load create/SKILL.md and follow it from Step 7 onward, passing:
database, schemafunction_name: DEMO_ROUTE_CLAIMfunction_intention: Route insurance claims to the correct processing track.model: chosen student modelinputs: [{"name": "CLAIM_SUMMARY", "sql_type": "VARCHAR"}, {"name": "INCIDENT_CHANNEL", "sql_type": "VARCHAR"}, {"name": "CUSTOMER_SEGMENT", "sql_type": "VARCHAR"}]outputs: [{"name": "claim_route", "json_type": "string", "description": "One of: fast_track_auto, property_damage, injury_review, fraud_review, documentation_needed, manual_specialist_review"}]system_prompt: confirmed promptuser_prompt_template: Claim summary: {CLAIM_SUMMARY}\nIncident channel: {INCIDENT_CHANNEL}\nCustomer segment: {CUSTOMER_SEGMENT}Return here after the smoke test succeeds.
Present the evaluation configuration:
Let's evaluate how well the student model routes claims.
Since the function returns a single claim_route string, the built-in
exact_match metric works perfectly — it compares the predicted route
directly against the teacher-labeled EXPECTED_OUTPUT.
Default metric: exact_match
Experiment: auto-generated per evaluation (run_id)
⚠️ STOP: Wait for user confirmation before running evaluation.
Load evaluate/SKILL.md and follow it from Step 4 onward (Run Evaluation), passing:
function_name: {database}.{schema}.DEMO_ROUTE_CLAIMfunction_model: chosen student modeltest_table: {database}.{schema}.DEMO_CLAIMS_DATAinput_columns: ['CLAIM_SUMMARY', 'INCIDENT_CHANNEL', 'CUSTOMER_SEGMENT']label_column: EXPECTED_OUTPUTmetric_name: exact_matchThe evaluation auto-creates an experiment named after its run_id. Capture experiment_name from the JSON output for the queries below.
Skip Step 6 (next steps) in the evaluate workflow — return here after results are presented.
Once evaluation is done, review the results. Show the scores to the user. Offer to see what cases did not match:
Would you like to see which claims the function routed incorrectly?
If yes, query the per-row eval artifact (requires ENABLE_EXPERIMENT_SNOWURL_READ_PATH_RESOLUTION). First create the JSON file format (required — inline (TYPE => JSON) isn't supported on SnowURL):
CREATE OR REPLACE TEMPORARY FILE FORMAT eval_detail_json_fmt
TYPE = JSON
STRIP_OUTER_ARRAY = TRUE;
SELECT
LEFT($1:input_text::STRING, 150) AS SUMMARY_PREVIEW,
$1:expected::STRING AS EXPECTED_ROUTE,
$1:predicted::STRING AS PREDICTED_ROUTE,
$1:metric_score::FLOAT AS SCORE,
$1:metric_feedback::STRING AS FEEDBACK
FROM 'snow://experiment/{experiment_name}/versions/EVAL/eval_detail.json'
(FILE_FORMAT => eval_detail_json_fmt)
WHERE $1:metric_score::FLOAT < 1.0
ORDER BY SCORE
LIMIT 20;
Discuss common failure patterns. Explain that labels are teacher-generated (pseudo-labels), not human ground truth.
After reviewing results, continue to Step 7.
Ask user:
The Insurance Claim Routing demo is complete!
Would you like to clean up the demo objects?
This will drop:
- {database}.{schema}.DEMO_CLAIMS_UNLABELED
- {database}.{schema}.DEMO_CLAIMS_DATA
- {database}.{schema}.DEMO_ROUTE_CLAIM
- The per-evaluation experiment ({experiment_name})
⚠️ STOP: Wait for user confirmation before cleanup.
If yes, execute:
DROP TABLE IF EXISTS {database}.{schema}.DEMO_CLAIMS_UNLABELED;
DROP TABLE IF EXISTS {database}.{schema}.DEMO_CLAIMS_DATA;
DROP FUNCTION IF EXISTS {database}.{schema}.DEMO_ROUTE_CLAIM(VARCHAR, VARCHAR, VARCHAR);
DROP EXPERIMENT IF EXISTS {database}.{schema}.{experiment_name};
Summarize the workflow: unlabeled data → teacher pseudo-labels → cheap student function → evaluation.
Explain to user:
You completed the pseudo-labeling and teacher-student distillation workflow:
1. Loaded unlabeled insurance claim intake records
2. Used a strong teacher model (Claude Opus) to generate routing labels
3. Built a cheaper student model to reproduce teacher routing decisions
4. Evaluated the student against teacher labels using exact_match
Key takeaways:
Pseudo-labeling: When you don't have labeled data, a strong teacher model
can generate high-quality training labels from your unlabeled data. This
is dramatically faster than manual annotation.
Teacher-student distillation: Once you have labels, you can train a cheap
student model that approaches teacher quality at a fraction of the cost.
Want to build richer evaluation metrics? Try the "Custom Evaluation Metrics" demo.
Want to optimize the student's prompt? Try the "Prompt Optimization" demo.