-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathsync_model_config.py
More file actions
199 lines (160 loc) · 7.65 KB
/
sync_model_config.py
File metadata and controls
199 lines (160 loc) · 7.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
"""
Sync model configuration from the canonical Python model_settings.json
to the JavaScript/TypeScript web app.
Generates:
1. cassia-web/lib/config/model-data.ts (TypeScript constants)
2. Updates cassia-web/public/examples/model_settings.json (updates model names, preserves schema)
Usage:
python sync_model_config.py
"""
import json
import os
import sys
def load_canonical_config():
"""Load the canonical model_settings.json from the Python package."""
script_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(script_dir, "CASSIA", "data", "model_settings.json")
with open(config_path, 'r', encoding='utf-8') as f:
return json.load(f)
def generate_model_data_ts(config, output_path):
"""Generate the TypeScript constants file from the canonical config."""
providers = config.get("providers", {})
pipeline_defaults = config.get("pipeline_defaults", {})
agent_defaults = config.get("agent_defaults", {})
symphony_presets = config.get("symphony_presets", {})
model_personas = config.get("model_personas", {})
lines = []
lines.append("// AUTO-GENERATED by sync_model_config.py — DO NOT EDIT MANUALLY")
lines.append("// Source: CASSIA_python/CASSIA/data/model_settings.json")
lines.append(f"// Generated from config version: {config.get('version', 'unknown')}")
lines.append("")
# MODELS constant
lines.append("export const MODELS = {")
for provider, tiers in providers.items():
tier_entries = ", ".join(f'{k}: "{v}"' for k, v in tiers.items())
lines.append(f' {provider}: {{ {tier_entries} }},')
lines.append("} as const;")
lines.append("")
# DEFAULT_MODELS
lines.append("export const DEFAULT_MODELS: Record<string, string> = {")
for provider, tiers in providers.items():
recommended = tiers.get("recommended", tiers.get("best", ""))
lines.append(f' {provider}: "{recommended}",')
lines.append("};")
lines.append("")
# PIPELINE_DEFAULTS
lines.append("export const PIPELINE_DEFAULTS = {")
for provider, stages in pipeline_defaults.items():
stage_entries = []
for stage, model in stages.items():
# Convert Python snake_case keys to JS camelCase
js_key = stage
if stage == "annotationboost":
js_key = "annotationBoost"
stage_entries.append(f'{js_key}: "{model}"')
lines.append(f' {provider}: {{ {", ".join(stage_entries)} }},')
lines.append("} as const;")
lines.append("")
# AGENT_DEFAULTS
lines.append("export const AGENT_DEFAULTS = {")
for provider, agents in agent_defaults.items():
lines.append(f" {provider}: {{")
for agent, settings in agents.items():
model = settings.get("model", "")
temp = settings.get("temperature", 0)
lines.append(f' {agent}: {{ model: "{model}", temperature: {temp} }},')
lines.append(" },")
lines.append("} as const;")
lines.append("")
# SYMPHONY_PRESETS
lines.append("export const SYMPHONY_PRESETS = {")
for tier, models in symphony_presets.items():
model_list = ", ".join(f'"{m}"' for m in models)
lines.append(f" {tier}: [{model_list}],")
lines.append("} as const;")
lines.append("")
# MODEL_PERSONAS
lines.append("export const MODEL_PERSONAS: Record<string, string> = {")
for model_id, persona in model_personas.items():
lines.append(f' "{model_id}": "{persona}",')
lines.append("};")
lines.append("")
content = "\n".join(lines)
os.makedirs(os.path.dirname(output_path), exist_ok=True)
with open(output_path, 'w', encoding='utf-8') as f:
f.write(content)
print(f" Generated: {output_path}")
def update_js_model_settings(config, js_json_path):
"""Update the JS model_settings.json with values from the canonical config.
Preserves the JS-specific schema (descriptions, cost_tiers, context_window, etc.)
but updates default_model, recommended_model, and provider_shortcuts.
"""
if not os.path.exists(js_json_path):
print(f" Skipped (file not found): {js_json_path}")
return
with open(js_json_path, 'r', encoding='utf-8') as f:
js_config = json.load(f)
canonical_providers = config.get("providers", {})
# Update default_model and recommended_model for each provider
for provider_key in ["openai", "anthropic", "openrouter"]:
if provider_key in js_config.get("providers", {}) and provider_key in canonical_providers:
canonical = canonical_providers[provider_key]
js_provider = js_config["providers"][provider_key]
js_provider["default_model"] = canonical.get("recommended", canonical.get("best", ""))
js_provider["recommended_model"] = canonical.get("recommended", canonical.get("best", ""))
# Update provider_shortcuts
canonical_aliases = config.get("aliases", {}).get("provider_specific", {})
if "provider_shortcuts" in js_config:
for provider_key in ["openai", "anthropic", "openrouter"]:
if provider_key in canonical_providers:
canonical = canonical_providers[provider_key]
shortcuts = js_config["provider_shortcuts"].get(provider_key, {})
shortcuts["best"] = canonical.get("best", shortcuts.get("best", ""))
shortcuts["default"] = canonical.get("recommended", shortcuts.get("default", ""))
shortcuts["fast"] = canonical.get("fast", shortcuts.get("fast", ""))
# Update use_case_recommendations from pipeline_defaults
pipeline = config.get("pipeline_defaults", {}).get("openrouter", {})
if "use_case_recommendations" in js_config and pipeline:
recs = js_config["use_case_recommendations"]
if "annotation" in recs and "annotation" in pipeline:
recs["annotation"]["best"] = pipeline["annotation"]
if "scoring" in recs and "score" in pipeline:
recs["scoring"]["best"] = pipeline["score"]
if "annotation_boost" in recs and "annotationboost" in pipeline:
recs["annotation_boost"]["best"] = pipeline["annotationboost"]
if "merging" in recs and "merge" in pipeline:
recs["merging"]["best"] = pipeline["merge"]
# Update version info
js_config["version"] = config.get("version", js_config.get("version", "1.0.0"))
js_config["last_updated"] = config.get("last_updated", "")
with open(js_json_path, 'w', encoding='utf-8') as f:
json.dump(js_config, f, indent=2, ensure_ascii=False)
f.write("\n")
print(f" Updated: {js_json_path}")
def main():
script_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(script_dir)
# If script is in CASSIA_python/, project root is one level up
if os.path.basename(script_dir) == "CASSIA_python":
project_root = os.path.dirname(script_dir)
else:
project_root = script_dir
print("=== Syncing model configuration to JS ===\n")
# Load canonical config
config = load_canonical_config()
print(f" Loaded canonical config v{config.get('version', '?')} ({config.get('last_updated', '?')})")
# Generate TypeScript constants
ts_output = os.path.join(
project_root, "docs", "cassia_javascript", "cassia-web",
"lib", "config", "model-data.ts"
)
generate_model_data_ts(config, ts_output)
# Update JS model_settings.json
js_json_path = os.path.join(
project_root, "docs", "cassia_javascript", "cassia-web",
"public", "examples", "model_settings.json"
)
update_js_model_settings(config, js_json_path)
print("\n=== Model config sync complete ===")
if __name__ == "__main__":
main()