2026-05-20 23:23:11 +01:00
#!/usr/bin/env python3
""" Emit tiny v0.1 utterance handoff fixtures for AquaSynth speech training.
This is intentionally not a Weksa runtime . It is a deterministic artifact
2026-05-21 10:21:48 +01:00
emitter for the first crawl - stage curriculum : simple IPA syllables with the
PanPhon 22 - feature basis , fixed - width Weksa / Epiphany input vectors , and pending
AquaSynth - owned learned outputs .
2026-05-20 23:23:11 +01:00
"""
from __future__ import annotations
import json
from pathlib import Path
ROOT = Path ( __file__ ) . resolve ( ) . parents [ 1 ]
OUT = ROOT / " examples " / " speech-training " / " tiny-panphon-v0.1 "
VECTORS = OUT / " vectors "
SCHEMA_VERSION = " weksa.utterance_embedding_handoff.v0.1 "
DECIDED_AT_UTC = " 2026-05-20T00:00:00Z "
FEATURE_ORDER = [
" syl " ,
" son " ,
" cons " ,
" cont " ,
" delrel " ,
" lat " ,
" nas " ,
" strid " ,
" voi " ,
" sg " ,
" cg " ,
" ant " ,
" cor " ,
" distr " ,
" lab " ,
" hi " ,
" lo " ,
" back " ,
" round " ,
" velaric " ,
" tense " ,
" long " ,
]
PROSODY_HINT_LABELS = [
" mean_pitch_pressure " ,
" pitch_rise " ,
" pitch_fall " ,
" pitch_range " ,
" loudness_pressure " ,
" loudness_attack " ,
" loudness_release " ,
" speaking_rate " ,
" articulation_precision " ,
" pause_pressure " ,
" phrase_final_lengthening " ,
" stress_contrast " ,
" clippedness " ,
" breathiness " ,
" creak_pressure " ,
" smoothness " ,
" warmth " ,
" threat " ,
" urgency " ,
" hesitation " ,
" irony_dryness " ,
" tenderness " ,
" contempt " ,
" command_force " ,
" question_contour " ,
" exclamation_pressure " ,
" secrecy_low_projection " ,
" ritual_formality_pressure " ,
" playful_pressure " ,
" fatigue " ,
" emotional_containment " ,
" reserved " ,
]
CHARACTER_STATE_LABELS = [
" valence " ,
" arousal " ,
" dominance " ,
" urgency " ,
" anger " ,
" despair " ,
" sadness " ,
" fear " ,
" anxiety " ,
" disgust " ,
" contempt " ,
" annoyance " ,
" dismissal " ,
" flippancy " ,
" playfulness " ,
" irony " ,
" tenderness " ,
" warmth " ,
" joy " ,
" excitement " ,
" fatigue " ,
" guardedness " ,
" confidence " ,
" shame " ,
" pride " ,
" threat " ,
" secrecy " ,
" hesitation " ,
" emotionalContainment " ,
" thoughtPressure " ,
" reactionIntensity " ,
" commandForce " ,
" currentLoad " ,
" initiativeHeat " ,
" pendingTurn " ,
" cooldownPressure " ,
" reactionBias " ,
" interruptThreshold " ,
" initiativeSpeed " ,
" voiceBubbly " ,
" voiceDryness " ,
" voiceFormality " ,
" voiceDirectness " ,
" voiceIntensity " ,
" voiceWarmth " ,
" voicePrecision " ,
" voiceRitualRegister " ,
" presentationPushiness " ,
" presentationSelfFocus " ,
" presentationPlay " ,
" presentationCareDemand " ,
" behaviorWorkDrive " ,
" behaviorBoundaryDefense " ,
" behaviorPurityDrive " ,
" behaviorPatience " ,
" stableAgreeableness " ,
" stableConscientiousness " ,
" stableNeuroticism " ,
" stableOpenness " ,
" organizationCoherence " ,
" organizationRigidity " ,
" slowTraitReserved62 " ,
" slowTraitReserved63 " ,
" slowTraitReserved64 " ,
]
PHONE_FEATURES = {
" a " : {
" syl " : 1 ,
" son " : 1 ,
" cons " : - 1 ,
" cont " : 1 ,
" voi " : 1 ,
" lo " : 1 ,
" round " : - 1 ,
" tense " : - 1 ,
} ,
" p " : {
" syl " : - 1 ,
" son " : - 1 ,
" cons " : 1 ,
" cont " : - 1 ,
" voi " : - 1 ,
" lab " : 1 ,
} ,
" t " : {
" syl " : - 1 ,
" son " : - 1 ,
" cons " : 1 ,
" cont " : - 1 ,
" voi " : - 1 ,
" ant " : 1 ,
" cor " : 1 ,
} ,
" k " : {
" syl " : - 1 ,
" son " : - 1 ,
" cons " : 1 ,
" cont " : - 1 ,
" voi " : - 1 ,
" back " : 1 ,
} ,
" s " : {
" syl " : - 1 ,
" son " : - 1 ,
" cons " : 1 ,
" cont " : 1 ,
" strid " : 1 ,
" voi " : - 1 ,
" ant " : 1 ,
" cor " : 1 ,
} ,
" m " : {
" syl " : - 1 ,
" son " : 1 ,
" cons " : 1 ,
" cont " : - 1 ,
" nas " : 1 ,
" voi " : 1 ,
" lab " : 1 ,
} ,
}
UTTERANCES = [
( " open-vowel-a " , " a " , [ " a " ] , " open low vowel baseline " ) ,
( " bilabial-pa " , " pa " , [ " p " , " a " ] , " voiceless bilabial stop into open vowel " ) ,
( " alveolar-ta " , " ta " , [ " t " , " a " ] , " voiceless alveolar stop into open vowel " ) ,
( " velar-ka " , " ka " , [ " k " , " a " ] , " voiceless velar stop into open vowel " ) ,
( " sibilant-sa " , " sa " , [ " s " , " a " ] , " voiceless alveolar sibilant into open vowel " ) ,
( " nasal-ma " , " ma " , [ " m " , " a " ] , " voiced bilabial nasal into open vowel " ) ,
]
def feature_vector ( phone : str ) - > list [ float ] :
features = PHONE_FEATURES [ phone ]
return [ float ( features . get ( name , 0 ) ) for name in FEATURE_ORDER ]
def frame ( phone : str , index : int , count : int ) - > dict :
is_vowel = PHONE_FEATURES [ phone ] . get ( " syl " ) == 1
duration_ms = 180 if is_vowel else 95
return {
" index " : index ,
" phone " : phone ,
" features " : feature_vector ( phone ) ,
" markers " : {
" stress " : 1.0 if is_vowel else 0.0 ,
" length " : 0.0 ,
" tone " : 0.0 ,
" boundary " : 1.0 if index == count - 1 else 0.0 ,
" duration_ms " : duration_ms ,
} ,
}
def write_json ( path : Path , value : object ) - > None :
path . parent . mkdir ( parents = True , exist_ok = True )
path . write_text ( json . dumps ( value , indent = 2 , ensure_ascii = False ) + " \n " , encoding = " utf-8 " )
def packet ( packet_id : str , ipa : str , phones : list [ str ] , note : str ) - > dict :
prosody_values = [ 0.0 ] * 32
prosody_values [ 7 ] = - 0.15
prosody_values [ 8 ] = 0.35
prosody_values [ 11 ] = 0.2
prosody_values [ 15 ] = 0.25
return {
" schema_version " : SCHEMA_VERSION ,
" packet_id " : f " tiny-panphon-v0.1/ { packet_id } " ,
" source_output_ref " : " examples/speech-training/tiny-panphon-v0.1/README.md " ,
" speaker_agent_id " : " neutral-human-baseline " ,
" text " : {
" spoken_text " : ipa ,
" normalized_text " : ipa ,
" channel_note " : " Pure IPA curriculum seed; semantic text embedding is intentionally zero. " ,
} ,
" inputs " : {
" speech_text_embedding " : {
" model_id " : " bge-m3:latest " ,
" dimensionality " : 1024 ,
" values_ref " : " vectors/zero-semantic-1024.json " ,
} ,
" panphon_sequence " : {
2026-05-21 10:21:48 +01:00
" model_id " : " panphon.v0.1.seed " ,
2026-05-20 23:23:11 +01:00
" source " : " hand-authored seed phones for AquaSynth crawl-stage parity tests " ,
" ipa " : ipa ,
" feature_order " : FEATURE_ORDER ,
" frames " : [ frame ( phone , i , len ( phones ) ) for i , phone in enumerate ( phones ) ] ,
} ,
" prosody_emphasis_hints " : {
" dimensionality " : 32 ,
" labels " : PROSODY_HINT_LABELS ,
" values " : prosody_values ,
} ,
" character_state_vector " : {
" source " : " epiphany.agent_utterance_state.v0 neutral baseline " ,
" schema_ref " : " E:/Projects/EpiphanyAgent/schemas/agent-utterance-state-schema.md " ,
" dimensionality " : 64 ,
" values_ref " : " vectors/neutral-character-64.json " ,
} ,
} ,
" phonetic_realization_embedding " : {
" owner " : " AquaSynth " ,
" model_id " : " aquasynth.panphon_sequence_encoder.v0.1 " ,
" dimensionality " : 256 ,
" status " : " pending_aquasynth_training_or_encoding " ,
" values_ref " : None ,
} ,
" utterance_embedding " : {
" owner " : " AquaSynth " ,
" model_id " : " aquasynth.utterance_embedding_encoder.v0.1 " ,
" version " : None ,
" training_set " : " tiny-panphon-v0.1 " ,
" dimensionality " : 64 ,
" status " : " pending_aquasynth_training_or_encoding " ,
" values_ref " : None ,
} ,
" audit_projection " : {
" semantic_preservation " : " No lexical semantics; preserve the requested IPA sound shape. " ,
" emphasis " : " Single syllable baseline stress where a vowel exists. " ,
" prosody " : " Neutral, slow, precise, no expressive contour. " ,
" character_pressure " : " Neutral speaker baseline. " ,
" delivery_shape " : note ,
} ,
" training_refs " : {
" positive_examples " : [
{
" kind " : " reference_synth_prompt " ,
" engine " : " eSpeak NG or equivalent baseline speech oracle " ,
" text " : ipa ,
}
] ,
" negative_examples " : [ ] ,
} ,
" trace " : {
" pipeline_receipts " : [
{
" stage " : " weksa_emit_tiny_panphon_handoff " ,
" decided_at_utc " : DECIDED_AT_UTC ,
" latency_budget_ms " : 10 ,
" observed_latency_ms " : 0 ,
" confidence " : 0.72 ,
}
] ,
" notes " : [
" This fixture is a crawl-stage training seed, not a full English lowering artifact. " ,
2026-05-21 10:21:48 +01:00
" The schema uses PanPhon ' s 22-feature basis; these seed values are hand-authored for the six seed phones until Weksa wires a canonical PanPhon dependency. " ,
2026-05-20 23:23:11 +01:00
" AquaSynth owns the learned 256-float phonetic realization embedding and 64-float utterance embedding. " ,
] ,
" uncertainties " : [
" Feature values should be regenerated from the canonical PanPhon library before broad phoneme coverage. " ,
" Durations are seed timing hints, not measured reference audio. " ,
] ,
} ,
}
def emit ( ) - > None :
write_json (
VECTORS / " zero-semantic-1024.json " ,
{
" model_id " : " bge-m3:latest " ,
" dimensionality " : 1024 ,
" values " : [ 0.0 ] * 1024 ,
" reason " : " Pure IPA fixture; semantic text channel is intentionally silent. " ,
} ,
)
write_json (
VECTORS / " neutral-character-64.json " ,
{
" source " : " epiphany.agent_utterance_state.v0 neutral baseline " ,
" dimensionality " : 64 ,
" labels " : CHARACTER_STATE_LABELS ,
" values " : [ 0.0 ] * 64 ,
} ,
)
packet_refs = [ ]
for packet_id , ipa , phones , note in UTTERANCES :
path = OUT / f " { packet_id } .json "
write_json ( path , packet ( packet_id , ipa , phones , note ) )
packet_refs . append ( path . name )
write_json (
OUT / " batch.json " ,
{
" schema_version " : " weksa.utterance_handoff_batch.v0.1 " ,
" batch_id " : " tiny-panphon-v0.1 " ,
" packet_schema_version " : SCHEMA_VERSION ,
" packet_refs " : packet_refs ,
" purpose " : " Initial AquaSynth parity curriculum for simple IPA sounds. " ,
} ,
)
if __name__ == " __main__ " :
emit ( )