[{"data":1,"prerenderedAt":2526},["ShallowReactive",2],{"navigation":3,"api-navigation":184,"\u002Flearn\u002Ftutorials\u002Fwhy-laco":206,"docyard:crossref-index":2525},[4,8,155,174,180],{"title":5,"path":6,"stem":7},"Getting Started","\u002Fgetting-started","1.getting-started",{"title":9,"path":10,"stem":11,"children":12},"Learn","\u002Flearn","2.learn",[13,15,66,99,133],{"title":9,"path":10,"stem":14},"2.learn\u002Findex",{"title":16,"path":17,"stem":18,"children":19},"Tutorials","\u002Flearn\u002Ftutorials","2.learn\u002F1.tutorials\u002Findex",[20,21,26,30,34,38,42,46,50,54,58,62],{"title":16,"path":17,"stem":18},{"title":22,"path":23,"stem":24,"icon":25},"Why Laco?","\u002Flearn\u002Ftutorials\u002Fwhy-laco","2.learn\u002F1.tutorials\u002F01.why-laco","i-lucide-notebook",{"title":27,"path":28,"stem":29,"icon":25},"First Steps with Laco","\u002Flearn\u002Ftutorials\u002Ffirst-steps","2.learn\u002F1.tutorials\u002F02.first-steps",{"title":31,"path":32,"stem":33,"icon":25},"Lazy Call and Partial","\u002Flearn\u002Ftutorials\u002Flazy-call-and-partial","2.learn\u002F1.tutorials\u002F03.lazy-call-and-partial",{"title":35,"path":36,"stem":37,"icon":25},"Hyperparameters and Interpolation","\u002Flearn\u002Ftutorials\u002Fhyperparameters-and-interpolation","2.learn\u002F1.tutorials\u002F04.hyperparameters-and-interpolation",{"title":39,"path":40,"stem":41,"icon":25},"Loading, Saving, and the CLI","\u002Flearn\u002Ftutorials\u002Floading-saving-cli","2.learn\u002F1.tutorials\u002F05.loading-saving-cli",{"title":43,"path":44,"stem":45,"icon":25},"Nested Configs and Containers","\u002Flearn\u002Ftutorials\u002Fnested-configs-and-containers","2.learn\u002F1.tutorials\u002F06.nested-configs-and-containers",{"title":47,"path":48,"stem":49,"icon":25},"Typed Groups and Schemas","\u002Flearn\u002Ftutorials\u002Ftyped-groups-and-schemas","2.learn\u002F1.tutorials\u002F07.typed-groups-and-schemas",{"title":51,"path":52,"stem":53,"icon":25},"Pipeline Configs","\u002Flearn\u002Ftutorials\u002Fpipeline-configs","2.learn\u002F1.tutorials\u002F08.pipeline-configs",{"title":55,"path":56,"stem":57,"icon":25},"Tasks and the App Loop","\u002Flearn\u002Ftutorials\u002Ftasks-and-app-loop","2.learn\u002F1.tutorials\u002F09.tasks-and-app-loop",{"title":59,"path":60,"stem":61,"icon":25},"Tracing","\u002Flearn\u002Ftutorials\u002Ftracing","2.learn\u002F1.tutorials\u002F10.tracing",{"title":63,"path":64,"stem":65,"icon":25},"Production Patterns","\u002Flearn\u002Ftutorials\u002Fproduction-patterns","2.learn\u002F1.tutorials\u002F11.production-patterns",{"title":67,"path":68,"stem":69,"children":70},"Concepts","\u002Flearn\u002Fconcepts","2.learn\u002F2.concepts\u002Findex",[71,72,76,80,84,88,92,95],{"title":67,"path":68,"stem":69},{"title":73,"path":74,"stem":75},"Config as Python","\u002Flearn\u002Fconcepts\u002Fconfig-as-python","2.learn\u002F2.concepts\u002F1.config-as-python",{"title":77,"path":78,"stem":79},"Lazy Construction","\u002Flearn\u002Fconcepts\u002Flazy-construction","2.learn\u002F2.concepts\u002F2.lazy-construction",{"title":81,"path":82,"stem":83},"Lie-Typing","\u002Flearn\u002Fconcepts\u002Flie-typing","2.learn\u002F2.concepts\u002F3.lie-typing",{"title":85,"path":86,"stem":87},"Interpolation","\u002Flearn\u002Fconcepts\u002Finterpolation","2.learn\u002F2.concepts\u002F4.interpolation",{"title":89,"path":90,"stem":91},"Typed Groups","\u002Flearn\u002Fconcepts\u002Ftyped-groups","2.learn\u002F2.concepts\u002F5.typed-groups",{"title":59,"path":93,"stem":94},"\u002Flearn\u002Fconcepts\u002Ftracing","2.learn\u002F2.concepts\u002F6.tracing",{"title":96,"path":97,"stem":98},"App Loop","\u002Flearn\u002Fconcepts\u002Fapp-loop","2.learn\u002F2.concepts\u002F7.app-loop",{"title":100,"path":101,"stem":102,"children":103},"How-To Guides","\u002Flearn\u002Fhow-to","2.learn\u002F3.how-to\u002Findex",[104,105,109,113,117,121,125,129],{"title":100,"path":101,"stem":102},{"title":106,"path":107,"stem":108},"Override Configs","\u002Flearn\u002Fhow-to\u002Foverride-configs","2.learn\u002F3.how-to\u002F1.override-configs",{"title":110,"path":111,"stem":112},"Safe Loading","\u002Flearn\u002Fhow-to\u002Fsafe-loading","2.learn\u002F3.how-to\u002F2.safe-loading",{"title":114,"path":115,"stem":116},"Custom Resolvers","\u002Flearn\u002Fhow-to\u002Fcustom-resolvers","2.learn\u002F3.how-to\u002F3.custom-resolvers",{"title":118,"path":119,"stem":120},"Lint and Strict Mode","\u002Flearn\u002Fhow-to\u002Flint-and-strict","2.learn\u002F3.how-to\u002F4.lint-and-strict",{"title":122,"path":123,"stem":124},"Publishing a reproducible app with laco app","\u002Flearn\u002Fhow-to\u002Flaco-app","2.learn\u002F3.how-to\u002F5.laco-app",{"title":126,"path":127,"stem":128},"Reproduce an Experiment","\u002Flearn\u002Fhow-to\u002Freproduce-experiment","2.learn\u002F3.how-to\u002F6.reproduce-experiment",{"title":130,"path":131,"stem":132},"Migrate from argparse","\u002Flearn\u002Fhow-to\u002Fmigrate-from-argparse","2.learn\u002F3.how-to\u002F7.migrate-from-argparse",{"title":134,"path":135,"stem":136,"children":137},"Examples Curriculum","\u002Flearn\u002Fexamples","2.learn\u002F4.examples\u002Findex",[138,139,143,147,151],{"title":134,"path":135,"stem":136},{"title":140,"path":141,"stem":142},"Foundation Examples","\u002Flearn\u002Fexamples\u002Ffoundations","2.learn\u002F4.examples\u002F1.foundations",{"title":144,"path":145,"stem":146},"Building Blocks","\u002Flearn\u002Fexamples\u002Fbuilding-blocks","2.learn\u002F4.examples\u002F2.building-blocks",{"title":148,"path":149,"stem":150},"Typed-Group Variants","\u002Flearn\u002Fexamples\u002Ftyped-variants","2.learn\u002F4.examples\u002F3.typed-variants",{"title":152,"path":153,"stem":154},"End-to-End Pipelines","\u002Flearn\u002Fexamples\u002Fpipelines","2.learn\u002F4.examples\u002F4.pipelines",{"title":156,"path":157,"stem":158,"children":159},"Resources","\u002Fresources","3.resources",[160,162,166,170],{"title":156,"path":157,"stem":161},"3.resources\u002Findex",{"title":163,"path":164,"stem":165},"Integrations","\u002Fresources\u002Fintegrations","3.resources\u002F1.integrations",{"title":167,"path":168,"stem":169},"Migration guide: Laco 0.x → 1.0","\u002Fresources\u002Fmigration-0.x-to-1.0","3.resources\u002F2.migration-0.x-to-1.0",{"title":171,"path":172,"stem":173},"Laco vs hydra-zen","\u002Fresources\u002Flaco-vs-hydra-zen","3.resources\u002F3.laco-vs-hydra-zen",{"title":175,"path":176,"stem":177,"children":178},"API Reference","\u002Fapi","4.api\u002Findex",[179],{"title":175,"path":176,"stem":177},{"title":181,"path":182,"stem":183},"Lazy Configuration for Python","\u002F","index",[185,188,191,194,197,200,203],{"title":186,"path":187},"cli","\u002Fapi\u002Fcli",{"title":189,"path":190},"compat","\u002Fapi\u002Fcompat",{"title":192,"path":193},"handler","\u002Fapi\u002Fhandler",{"title":195,"path":196},"keys","\u002Fapi\u002Fkeys",{"title":198,"path":199},"language","\u002Fapi\u002Flanguage",{"title":201,"path":202},"ops","\u002Fapi\u002Fops",{"title":204,"path":205},"utils","\u002Fapi\u002Futils",{"id":207,"title":22,"body":208,"description":2519,"extension":2520,"meta":2521,"navigation":2522,"path":23,"seo":2523,"stem":24,"__hash__":2524},"content\u002F2.learn\u002F1.tutorials\u002F01.why-laco.md",{"type":209,"value":210,"toc":2506},"minimark",[211,215,232,235,247,250,255,261,659,664,667,717,737,739,743,746,886,889,892,985,988,993,1059,1070,1072,1076,1086,1215,1218,1228,1249,1251,1255,1267,1367,1370,1380,1385,1411,1413,1417,1433,1612,1615,1624,1629,1665,1667,1671,1683,1801,1804,1810,1830,1832,1836,1853,1856,1973,1976,1979,1988,2104,2107,2192,2197,2200,2366,2370,2415,2417,2421,2424,2453,2473,2475,2502],[212,213,22],"h1",{"id":214},"why-laco",[216,217,218,222,223,227,228,231],"p",{},[219,220,221],"strong",{},"Prerequisites:"," Basic Python. Prior use of ",[224,225,226],"code",{},"argparse"," or a YAML-based config loader such as ",[224,229,230],{},"yaml.safe_load"," is helpful.",[216,233,234],{},"This notebook traces the path from a plain argparse script to Laco. Each step shows what the previous tool cannot do.",[216,236,237,238,242,243,246],{},"No GPU or PyTorch required: all runnable cells use only the standard library or Laco itself.\nPyTorch is referenced in ",[239,240,241],"em",{},"illustrative"," (non-executed) cells, marked with a\n",[224,244,245],{},"# torch required"," comment.",[248,249],"hr",{},[251,252,254],"h2",{"id":253},"section-1-the-configuration-problem","Section 1: The Configuration Problem",[216,256,257,258,260],{},"Every machine-learning experiment starts with a script. Here is the canonical one: a\ntraining loop with a handful of hyperparameters exposed via ",[224,259,226],{},".",[262,263,268],"pre",{"className":264,"code":265,"language":266,"meta":267,"style":267},"language-python shiki shiki-themes material-theme-lighter github-light github-dark","# Illustrative only — not executed as a runnable script here\n# (would need torch, a dataset, etc.)\n\nimport argparse\n\ndef get_args():\n    p = argparse.ArgumentParser()\n    p.add_argument(\"--lr\",          type=float, default=1e-3)\n    p.add_argument(\"--batch_size\",  type=int,   default=32)\n    p.add_argument(\"--model\",       type=str,   default=\"Linear\")\n    p.add_argument(\"--hidden_dim\",  type=int,   default=256)\n    p.add_argument(\"--epochs\",      type=int,   default=10)\n    return p.parse_args()\n\n# --- main training loop ---\n# args = get_args()\n# model_class = getattr(torch.nn, args.model)  # hope the string is right!\n# model = model_class(args.hidden_dim, num_classes)\n# optimizer = torch.optim.SGD(model.parameters(), lr=args.lr)\n# for epoch in range(args.epochs):\n#     for x, y in DataLoader(dataset, batch_size=args.batch_size):\n#         loss = criterion(model(x), y)\n#         loss.backward()\n#         optimizer.step()\n#         optimizer.zero_grad()\nprint(\"Script stub defined (not run).\")\n","python","",[224,269,270,279,285,292,303,308,323,345,396,436,479,516,554,570,575,581,587,593,599,605,611,617,623,629,635,641],{"__ignoreMap":267},[271,272,275],"span",{"class":273,"line":274},"line",1,[271,276,278],{"class":277},"sutJx","# Illustrative only — not executed as a runnable script here\n",[271,280,282],{"class":273,"line":281},2,[271,283,284],{"class":277},"# (would need torch, a dataset, etc.)\n",[271,286,288],{"class":273,"line":287},3,[271,289,291],{"emptyLinePlaceholder":290},true,"\n",[271,293,295,299],{"class":273,"line":294},4,[271,296,298],{"class":297},"sVHd0","import",[271,300,302],{"class":301},"su5hD"," argparse\n",[271,304,306],{"class":273,"line":305},5,[271,307,291],{"emptyLinePlaceholder":290},[271,309,311,315,319],{"class":273,"line":310},6,[271,312,314],{"class":313},"sbsja","def",[271,316,318],{"class":317},"sGLFI"," get_args",[271,320,322],{"class":321},"sP7_E","():\n",[271,324,326,329,333,336,338,342],{"class":273,"line":325},7,[271,327,328],{"class":301},"    p ",[271,330,332],{"class":331},"smGrS","=",[271,334,335],{"class":301}," argparse",[271,337,260],{"class":321},[271,339,341],{"class":340},"slqww","ArgumentParser",[271,343,344],{"class":321},"()\n",[271,346,348,351,353,356,359,363,367,369,372,376,378,382,384,387,389,393],{"class":273,"line":347},8,[271,349,350],{"class":301},"    p",[271,352,260],{"class":321},[271,354,355],{"class":340},"add_argument",[271,357,358],{"class":321},"(",[271,360,362],{"class":361},"sjJ54","\"",[271,364,366],{"class":365},"s_sjI","--lr",[271,368,362],{"class":361},[271,370,371],{"class":321},",",[271,373,375],{"class":374},"s99_P","          type",[271,377,332],{"class":331},[271,379,381],{"class":380},"sZMiF","float",[271,383,371],{"class":321},[271,385,386],{"class":374}," default",[271,388,332],{"class":331},[271,390,392],{"class":391},"srdBf","1e-3",[271,394,395],{"class":321},")\n",[271,397,399,401,403,405,407,409,412,414,416,419,421,424,426,429,431,434],{"class":273,"line":398},9,[271,400,350],{"class":301},[271,402,260],{"class":321},[271,404,355],{"class":340},[271,406,358],{"class":321},[271,408,362],{"class":361},[271,410,411],{"class":365},"--batch_size",[271,413,362],{"class":361},[271,415,371],{"class":321},[271,417,418],{"class":374},"  type",[271,420,332],{"class":331},[271,422,423],{"class":380},"int",[271,425,371],{"class":321},[271,427,428],{"class":374},"   default",[271,430,332],{"class":331},[271,432,433],{"class":391},"32",[271,435,395],{"class":321},[271,437,439,441,443,445,447,449,452,454,456,459,461,464,466,468,470,472,475,477],{"class":273,"line":438},10,[271,440,350],{"class":301},[271,442,260],{"class":321},[271,444,355],{"class":340},[271,446,358],{"class":321},[271,448,362],{"class":361},[271,450,451],{"class":365},"--model",[271,453,362],{"class":361},[271,455,371],{"class":321},[271,457,458],{"class":374},"       type",[271,460,332],{"class":331},[271,462,463],{"class":380},"str",[271,465,371],{"class":321},[271,467,428],{"class":374},[271,469,332],{"class":331},[271,471,362],{"class":361},[271,473,474],{"class":365},"Linear",[271,476,362],{"class":361},[271,478,395],{"class":321},[271,480,482,484,486,488,490,492,495,497,499,501,503,505,507,509,511,514],{"class":273,"line":481},11,[271,483,350],{"class":301},[271,485,260],{"class":321},[271,487,355],{"class":340},[271,489,358],{"class":321},[271,491,362],{"class":361},[271,493,494],{"class":365},"--hidden_dim",[271,496,362],{"class":361},[271,498,371],{"class":321},[271,500,418],{"class":374},[271,502,332],{"class":331},[271,504,423],{"class":380},[271,506,371],{"class":321},[271,508,428],{"class":374},[271,510,332],{"class":331},[271,512,513],{"class":391},"256",[271,515,395],{"class":321},[271,517,519,521,523,525,527,529,532,534,536,539,541,543,545,547,549,552],{"class":273,"line":518},12,[271,520,350],{"class":301},[271,522,260],{"class":321},[271,524,355],{"class":340},[271,526,358],{"class":321},[271,528,362],{"class":361},[271,530,531],{"class":365},"--epochs",[271,533,362],{"class":361},[271,535,371],{"class":321},[271,537,538],{"class":374},"      type",[271,540,332],{"class":331},[271,542,423],{"class":380},[271,544,371],{"class":321},[271,546,428],{"class":374},[271,548,332],{"class":331},[271,550,551],{"class":391},"10",[271,553,395],{"class":321},[271,555,557,560,563,565,568],{"class":273,"line":556},13,[271,558,559],{"class":297},"    return",[271,561,562],{"class":301}," p",[271,564,260],{"class":321},[271,566,567],{"class":340},"parse_args",[271,569,344],{"class":321},[271,571,573],{"class":273,"line":572},14,[271,574,291],{"emptyLinePlaceholder":290},[271,576,578],{"class":273,"line":577},15,[271,579,580],{"class":277},"# --- main training loop ---\n",[271,582,584],{"class":273,"line":583},16,[271,585,586],{"class":277},"# args = get_args()\n",[271,588,590],{"class":273,"line":589},17,[271,591,592],{"class":277},"# model_class = getattr(torch.nn, args.model)  # hope the string is right!\n",[271,594,596],{"class":273,"line":595},18,[271,597,598],{"class":277},"# model = model_class(args.hidden_dim, num_classes)\n",[271,600,602],{"class":273,"line":601},19,[271,603,604],{"class":277},"# optimizer = torch.optim.SGD(model.parameters(), lr=args.lr)\n",[271,606,608],{"class":273,"line":607},20,[271,609,610],{"class":277},"# for epoch in range(args.epochs):\n",[271,612,614],{"class":273,"line":613},21,[271,615,616],{"class":277},"#     for x, y in DataLoader(dataset, batch_size=args.batch_size):\n",[271,618,620],{"class":273,"line":619},22,[271,621,622],{"class":277},"#         loss = criterion(model(x), y)\n",[271,624,626],{"class":273,"line":625},23,[271,627,628],{"class":277},"#         loss.backward()\n",[271,630,632],{"class":273,"line":631},24,[271,633,634],{"class":277},"#         optimizer.step()\n",[271,636,638],{"class":273,"line":637},25,[271,639,640],{"class":277},"#         optimizer.zero_grad()\n",[271,642,644,648,650,652,655,657],{"class":273,"line":643},26,[271,645,647],{"class":646},"sptTA","print",[271,649,358],{"class":321},[271,651,362],{"class":361},[271,653,654],{"class":365},"Script stub defined (not run).",[271,656,362],{"class":361},[271,658,395],{"class":321},[660,661],"docyard-notebook-output",{"data":662,"kind":663},"U2NyaXB0IHN0dWIgZGVmaW5lZCAobm90IHJ1bikuCg==","stream",[216,665,666],{},"This holds up until:",[668,669,670,686,693,711],"ul",{},[671,672,673,674,677,678,681,682,685],"li",{},"A colleague asks you to ",[219,675,676],{},"reproduce Run #42 from last month",". What were the exact\nflags? Did you ",[224,679,680],{},"--lr 3e-4"," or ",[224,683,684],{},"--lr 0.0003","? Argparse doesn't save anything.",[671,687,688,689,692],{},"You want to ",[219,690,691],{},"sweep over learning rates",". You write a Bash loop, and hope no flag\ngets silently ignored.",[671,694,695,696,698,699,702,703,706,707,710],{},"Your model grows. ",[224,697,494],{}," now needs to be a ",[239,700,701],{},"list"," of layer widths.\nArgparse can do ",[224,704,705],{},"nargs='+'",", but then your CLI becomes\n",[224,708,709],{},"python train.py --hidden_dim 256 128 64 --lr 1e-3",", which is fragile and hard to read.",[671,712,688,713,716],{},[219,714,715],{},"swap the optimizer",". That's a new argument, a new code branch,\nmore flags…",[216,718,719,722,723,726,727,726,730,733,734,260],{},[219,720,721],{},"Argparse pain points in one sentence:"," it has ",[239,724,725],{},"no serialization",", ",[239,728,729],{},"no nesting",[239,731,732],{},"no\nlazy object construction",", and ",[239,735,736],{},"no type checking beyond primitive conversions",[248,738],{},[251,740,742],{"id":741},"section-2-the-yaml-step","Section 2: The YAML Step",[216,744,745],{},"The natural next step: move configuration into a YAML file so it can be committed to\nversion control and passed around.",[262,747,749],{"className":264,"code":748,"language":266,"meta":267,"style":267},"import yaml\n\nyaml_config = \"\"\"\nlr: 1.0e-3\nbatch_size: 32\nmodel: Linear\nhidden_dim: 256\nepochs: 10\n\"\"\"\n\ncfg = yaml.safe_load(yaml_config)\nprint(cfg)\nprint(type(cfg))          # plain dict\nprint(type(cfg[\"lr\"]))    # float — YAML parsed it\n",[224,750,751,758,762,772,777,782,787,792,797,802,806,828,839,858],{"__ignoreMap":267},[271,752,753,755],{"class":273,"line":274},[271,754,298],{"class":297},[271,756,757],{"class":301}," yaml\n",[271,759,760],{"class":273,"line":281},[271,761,291],{"emptyLinePlaceholder":290},[271,763,764,767,769],{"class":273,"line":287},[271,765,766],{"class":301},"yaml_config ",[271,768,332],{"class":331},[271,770,771],{"class":361}," \"\"\"\n",[271,773,774],{"class":273,"line":294},[271,775,776],{"class":365},"lr: 1.0e-3\n",[271,778,779],{"class":273,"line":305},[271,780,781],{"class":365},"batch_size: 32\n",[271,783,784],{"class":273,"line":310},[271,785,786],{"class":365},"model: Linear\n",[271,788,789],{"class":273,"line":325},[271,790,791],{"class":365},"hidden_dim: 256\n",[271,793,794],{"class":273,"line":347},[271,795,796],{"class":365},"epochs: 10\n",[271,798,799],{"class":273,"line":398},[271,800,801],{"class":361},"\"\"\"\n",[271,803,804],{"class":273,"line":438},[271,805,291],{"emptyLinePlaceholder":290},[271,807,808,811,813,816,818,821,823,826],{"class":273,"line":481},[271,809,810],{"class":301},"cfg ",[271,812,332],{"class":331},[271,814,815],{"class":301}," yaml",[271,817,260],{"class":321},[271,819,820],{"class":340},"safe_load",[271,822,358],{"class":321},[271,824,825],{"class":340},"yaml_config",[271,827,395],{"class":321},[271,829,830,832,834,837],{"class":273,"line":518},[271,831,647],{"class":646},[271,833,358],{"class":321},[271,835,836],{"class":340},"cfg",[271,838,395],{"class":321},[271,840,841,843,845,848,850,852,855],{"class":273,"line":556},[271,842,647],{"class":646},[271,844,358],{"class":321},[271,846,847],{"class":380},"type",[271,849,358],{"class":321},[271,851,836],{"class":340},[271,853,854],{"class":321},"))",[271,856,857],{"class":277},"          # plain dict\n",[271,859,860,862,864,866,868,870,873,875,878,880,883],{"class":273,"line":572},[271,861,647],{"class":646},[271,863,358],{"class":321},[271,865,847],{"class":380},[271,867,358],{"class":321},[271,869,836],{"class":340},[271,871,872],{"class":321},"[",[271,874,362],{"class":361},[271,876,877],{"class":365},"lr",[271,879,362],{"class":361},[271,881,882],{"class":321},"]))",[271,884,885],{"class":277},"    # float — YAML parsed it\n",[660,887],{"data":888,"kind":663},"eydscic6IDAuMDAxLCAnYmF0Y2hfc2l6ZSc6IDMyLCAnbW9kZWwnOiAnTGluZWFyJywgJ2hpZGRlbl9kaW0nOiAyNTYsICdlcG9jaHMnOiAxMH0KPGNsYXNzICdkaWN0Jz4KPGNsYXNzICdmbG9hdCc+Cg==",[216,890,891],{},"It is serializable, committable, diffable. But consider what the training script now\nlooks like when it needs to actually build a model from the config:",[262,893,895],{"className":264,"code":894,"language":266,"meta":267,"style":267},"# Illustrative — shows what you have to write by hand (torch not imported here)\nsource = '''\nimport yaml, torch\n\nwith open(\"config.yaml\") as f:\n    cfg = yaml.safe_load(f)\n\n# No lazy construction — you have to manually wire up every class\nmodel_class = getattr(torch.nn, cfg[\"model\"])   # magic string lookup\nmodel = model_class(cfg[\"hidden_dim\"], num_classes)\n\n# No autocomplete — cfg is just a dict[str, Any]\n# Type error at runtime, not at write-time:\noptimizer = torch.optim.SGD(model.parameters(), lr=cfg[\"lrr\"])  # typo!\n'''\nprint(source)\n",[224,896,897,902,912,917,921,926,931,935,940,945,950,954,959,964,969,974],{"__ignoreMap":267},[271,898,899],{"class":273,"line":274},[271,900,901],{"class":277},"# Illustrative — shows what you have to write by hand (torch not imported here)\n",[271,903,904,907,909],{"class":273,"line":281},[271,905,906],{"class":301},"source ",[271,908,332],{"class":331},[271,910,911],{"class":361}," '''\n",[271,913,914],{"class":273,"line":287},[271,915,916],{"class":365},"import yaml, torch\n",[271,918,919],{"class":273,"line":294},[271,920,291],{"emptyLinePlaceholder":290},[271,922,923],{"class":273,"line":305},[271,924,925],{"class":365},"with open(\"config.yaml\") as f:\n",[271,927,928],{"class":273,"line":310},[271,929,930],{"class":365},"    cfg = yaml.safe_load(f)\n",[271,932,933],{"class":273,"line":325},[271,934,291],{"emptyLinePlaceholder":290},[271,936,937],{"class":273,"line":347},[271,938,939],{"class":365},"# No lazy construction — you have to manually wire up every class\n",[271,941,942],{"class":273,"line":398},[271,943,944],{"class":365},"model_class = getattr(torch.nn, cfg[\"model\"])   # magic string lookup\n",[271,946,947],{"class":273,"line":438},[271,948,949],{"class":365},"model = model_class(cfg[\"hidden_dim\"], num_classes)\n",[271,951,952],{"class":273,"line":481},[271,953,291],{"emptyLinePlaceholder":290},[271,955,956],{"class":273,"line":518},[271,957,958],{"class":365},"# No autocomplete — cfg is just a dict[str, Any]\n",[271,960,961],{"class":273,"line":556},[271,962,963],{"class":365},"# Type error at runtime, not at write-time:\n",[271,965,966],{"class":273,"line":572},[271,967,968],{"class":365},"optimizer = torch.optim.SGD(model.parameters(), lr=cfg[\"lrr\"])  # typo!\n",[271,970,971],{"class":273,"line":577},[271,972,973],{"class":361},"'''\n",[271,975,976,978,980,983],{"class":273,"line":583},[271,977,647],{"class":646},[271,979,358],{"class":321},[271,981,982],{"class":340},"source",[271,984,395],{"class":321},[660,986],{"data":987,"kind":663},"CmltcG9ydCB5YW1sLCB0b3JjaAoKd2l0aCBvcGVuKCJjb25maWcueWFtbCIpIGFzIGY6CiAgICBjZmcgPSB5YW1sLnNhZmVfbG9hZChmKQoKIyBObyBsYXp5IGNvbnN0cnVjdGlvbiDigJQgeW91IGhhdmUgdG8gbWFudWFsbHkgd2lyZSB1cCBldmVyeSBjbGFzcwptb2RlbF9jbGFzcyA9IGdldGF0dHIodG9yY2gubm4sIGNmZ1sibW9kZWwiXSkgICAjIG1hZ2ljIHN0cmluZyBsb29rdXAKbW9kZWwgPSBtb2RlbF9jbGFzcyhjZmdbImhpZGRlbl9kaW0iXSwgbnVtX2NsYXNzZXMpCgojIE5vIGF1dG9jb21wbGV0ZSDigJQgY2ZnIGlzIGp1c3QgYSBkaWN0W3N0ciwgQW55XQojIFR5cGUgZXJyb3IgYXQgcnVudGltZSwgbm90IGF0IHdyaXRlLXRpbWU6Cm9wdGltaXplciA9IHRvcmNoLm9wdGltLlNHRChtb2RlbC5wYXJhbWV0ZXJzKCksIGxyPWNmZ1sibHJyIl0pICAjIHR5cG8hCgo=",[216,989,990],{},[219,991,992],{},"Remaining YAML pain points:",[994,995,996,1009],"table",{},[997,998,999],"thead",{},[1000,1001,1002,1006],"tr",{},[1003,1004,1005],"th",{},"Problem",[1003,1007,1008],{},"Detail",[1010,1011,1012,1025,1039,1047],"tbody",{},[1000,1013,1014,1018],{},[1015,1016,1017],"td",{},"No lazy construction",[1015,1019,1020,1021,1024],{},"Must manually map strings to classes (",[224,1022,1023],{},"getattr",")",[1000,1026,1027,1030],{},[1015,1028,1029],{},"No IDE autocomplete",[1015,1031,1032,1034,1035,1038],{},[224,1033,836],{}," is ",[224,1036,1037],{},"dict[str, Any]",", so there are no hints",[1000,1040,1041,1044],{},[1015,1042,1043],{},"Runtime-only errors",[1015,1045,1046],{},"Typos in keys are silent until the experiment crashes",[1000,1048,1049,1052],{},[1015,1050,1051],{},"No nested objects",[1015,1053,1054,1055,1058],{},"Representing ",[224,1056,1057],{},"SGD(lr=1e-3, momentum=0.9)"," requires custom parsing",[216,1060,1061,1062,1065,1066,1069],{},"The config ",[239,1063,1064],{},"file"," is now reproducible; the ",[239,1067,1068],{},"object graph"," construction is still manual.",[248,1071],{},[251,1073,1075],{"id":1074},"section-3-omegaconf-structured-configs","Section 3: OmegaConf + Structured Configs",[216,1077,1078,1085],{},[1079,1080,1084],"a",{"href":1081,"rel":1082},"https:\u002F\u002Fomegaconf.readthedocs.io\u002F",[1083],"nofollow","OmegaConf"," adds typed access and variable interpolation\non top of YAML. With structured configs (dataclasses as schemas) you also get IDE\nautocomplete.",[262,1087,1089],{"className":264,"code":1088,"language":266,"meta":267,"style":267},"# Illustrative — requires omegaconf\nsource = '''\nfrom dataclasses import dataclass, field\nfrom omegaconf import OmegaConf, MISSING\n\n@dataclass\nclass TrainingConfig:\n    lr: float = 1e-3\n    batch_size: int = 32\n    model: str = MISSING       # must be provided\n    hidden_dim: int = 256\n    epochs: int = 10\n\n# Merge schema defaults with a YAML override file\nschema = OmegaConf.structured(TrainingConfig)\noverride = OmegaConf.load(\"config.yaml\")\ncfg = OmegaConf.merge(schema, override)\n\n# Now cfg.lr gives type-checked float access — IDE knows the type!\n# BUT: model construction still requires manual getattr:\nmodel_class = getattr(torch.nn, cfg.model)   # still a magic string\nmodel = model_class(cfg.hidden_dim, num_classes)\n'''\nprint(source)\n",[224,1090,1091,1096,1104,1109,1114,1118,1123,1128,1133,1138,1143,1148,1153,1157,1162,1167,1172,1177,1181,1186,1191,1196,1201,1205],{"__ignoreMap":267},[271,1092,1093],{"class":273,"line":274},[271,1094,1095],{"class":277},"# Illustrative — requires omegaconf\n",[271,1097,1098,1100,1102],{"class":273,"line":281},[271,1099,906],{"class":301},[271,1101,332],{"class":331},[271,1103,911],{"class":361},[271,1105,1106],{"class":273,"line":287},[271,1107,1108],{"class":365},"from dataclasses import dataclass, field\n",[271,1110,1111],{"class":273,"line":294},[271,1112,1113],{"class":365},"from omegaconf import OmegaConf, MISSING\n",[271,1115,1116],{"class":273,"line":305},[271,1117,291],{"emptyLinePlaceholder":290},[271,1119,1120],{"class":273,"line":310},[271,1121,1122],{"class":365},"@dataclass\n",[271,1124,1125],{"class":273,"line":325},[271,1126,1127],{"class":365},"class TrainingConfig:\n",[271,1129,1130],{"class":273,"line":347},[271,1131,1132],{"class":365},"    lr: float = 1e-3\n",[271,1134,1135],{"class":273,"line":398},[271,1136,1137],{"class":365},"    batch_size: int = 32\n",[271,1139,1140],{"class":273,"line":438},[271,1141,1142],{"class":365},"    model: str = MISSING       # must be provided\n",[271,1144,1145],{"class":273,"line":481},[271,1146,1147],{"class":365},"    hidden_dim: int = 256\n",[271,1149,1150],{"class":273,"line":518},[271,1151,1152],{"class":365},"    epochs: int = 10\n",[271,1154,1155],{"class":273,"line":556},[271,1156,291],{"emptyLinePlaceholder":290},[271,1158,1159],{"class":273,"line":572},[271,1160,1161],{"class":365},"# Merge schema defaults with a YAML override file\n",[271,1163,1164],{"class":273,"line":577},[271,1165,1166],{"class":365},"schema = OmegaConf.structured(TrainingConfig)\n",[271,1168,1169],{"class":273,"line":583},[271,1170,1171],{"class":365},"override = OmegaConf.load(\"config.yaml\")\n",[271,1173,1174],{"class":273,"line":589},[271,1175,1176],{"class":365},"cfg = OmegaConf.merge(schema, override)\n",[271,1178,1179],{"class":273,"line":595},[271,1180,291],{"emptyLinePlaceholder":290},[271,1182,1183],{"class":273,"line":601},[271,1184,1185],{"class":365},"# Now cfg.lr gives type-checked float access — IDE knows the type!\n",[271,1187,1188],{"class":273,"line":607},[271,1189,1190],{"class":365},"# BUT: model construction still requires manual getattr:\n",[271,1192,1193],{"class":273,"line":613},[271,1194,1195],{"class":365},"model_class = getattr(torch.nn, cfg.model)   # still a magic string\n",[271,1197,1198],{"class":273,"line":619},[271,1199,1200],{"class":365},"model = model_class(cfg.hidden_dim, num_classes)\n",[271,1202,1203],{"class":273,"line":625},[271,1204,973],{"class":361},[271,1206,1207,1209,1211,1213],{"class":273,"line":631},[271,1208,647],{"class":646},[271,1210,358],{"class":321},[271,1212,982],{"class":340},[271,1214,395],{"class":321},[660,1216],{"data":1217,"kind":663},"CmZyb20gZGF0YWNsYXNzZXMgaW1wb3J0IGRhdGFjbGFzcywgZmllbGQKZnJvbSBvbWVnYWNvbmYgaW1wb3J0IE9tZWdhQ29uZiwgTUlTU0lORwoKQGRhdGFjbGFzcwpjbGFzcyBUcmFpbmluZ0NvbmZpZzoKICAgIGxyOiBmbG9hdCA9IDFlLTMKICAgIGJhdGNoX3NpemU6IGludCA9IDMyCiAgICBtb2RlbDogc3RyID0gTUlTU0lORyAgICAgICAjIG11c3QgYmUgcHJvdmlkZWQKICAgIGhpZGRlbl9kaW06IGludCA9IDI1NgogICAgZXBvY2hzOiBpbnQgPSAxMAoKIyBNZXJnZSBzY2hlbWEgZGVmYXVsdHMgd2l0aCBhIFlBTUwgb3ZlcnJpZGUgZmlsZQpzY2hlbWEgPSBPbWVnYUNvbmYuc3RydWN0dXJlZChUcmFpbmluZ0NvbmZpZykKb3ZlcnJpZGUgPSBPbWVnYUNvbmYubG9hZCgiY29uZmlnLnlhbWwiKQpjZmcgPSBPbWVnYUNvbmYubWVyZ2Uoc2NoZW1hLCBvdmVycmlkZSkKCiMgTm93IGNmZy5sciBnaXZlcyB0eXBlLWNoZWNrZWQgZmxvYXQgYWNjZXNzIOKAlCBJREUga25vd3MgdGhlIHR5cGUhCiMgQlVUOiBtb2RlbCBjb25zdHJ1Y3Rpb24gc3RpbGwgcmVxdWlyZXMgbWFudWFsIGdldGF0dHI6Cm1vZGVsX2NsYXNzID0gZ2V0YXR0cih0b3JjaC5ubiwgY2ZnLm1vZGVsKSAgICMgc3RpbGwgYSBtYWdpYyBzdHJpbmcKbW9kZWwgPSBtb2RlbF9jbGFzcyhjZmcuaGlkZGVuX2RpbSwgbnVtX2NsYXNzZXMpCgo=",[216,1219,1220,1223,1224,1227],{},[219,1221,1222],{},"What OmegaConf adds:"," typed attribute access, interpolation (",[224,1225,1226],{},"${lr}","), merge semantics.",[216,1229,1230,1233,1234,1237,1238,1241,1242,726,1245,1248],{},[219,1231,1232],{},"What it still doesn't do:"," the ",[224,1235,1236],{},"@dataclass"," schema and the YAML file are ",[239,1239,1240],{},"two separate\nthings"," that can silently diverge. Add a field to the dataclass and forget to add it to\nyour YAML directory, and nothing errors until runtime. Lazy construction of arbitrary\nPython objects (",[224,1243,1244],{},"nn.Linear",[224,1246,1247],{},"SGD",", your custom loss…) is still not supported at the\nconfig level.",[248,1250],{},[251,1252,1254],{"id":1253},"section-4-pytorch-lightning-cli","Section 4: PyTorch Lightning CLI",[216,1256,1257,1262,1263,1266],{},[1079,1258,1261],{"href":1259,"rel":1260},"https:\u002F\u002Flightning.ai\u002Fdocs\u002Fpytorch\u002Fstable\u002Fapi\u002Flightning.pytorch.cli.LightningCLI.html",[1083],"LightningCLI","\ngoes further: it generates a CLI ",[239,1264,1265],{},"and"," wires up the model and datamodule automatically,\nreading a YAML config.",[262,1268,1270],{"className":264,"code":1269,"language":266,"meta":267,"style":267},"# Illustrative — requires lightning\nsource = '''\nfrom lightning.pytorch.cli import LightningCLI\nfrom my_project.model import MyModel\nfrom my_project.data import MyDataModule\n\n# Entire training loop, CLI, and config loading in one line:\ncli = LightningCLI(MyModel, MyDataModule)\n\n# config.yaml:\n# model:\n#   class_path: my_project.model.MyModel\n#   init_args:\n#     hidden_dim: 256\n# trainer:\n#   max_epochs: 10\n'''\nprint(source)\n",[224,1271,1272,1277,1285,1290,1295,1300,1304,1309,1314,1318,1323,1328,1333,1338,1343,1348,1353,1357],{"__ignoreMap":267},[271,1273,1274],{"class":273,"line":274},[271,1275,1276],{"class":277},"# Illustrative — requires lightning\n",[271,1278,1279,1281,1283],{"class":273,"line":281},[271,1280,906],{"class":301},[271,1282,332],{"class":331},[271,1284,911],{"class":361},[271,1286,1287],{"class":273,"line":287},[271,1288,1289],{"class":365},"from lightning.pytorch.cli import LightningCLI\n",[271,1291,1292],{"class":273,"line":294},[271,1293,1294],{"class":365},"from my_project.model import MyModel\n",[271,1296,1297],{"class":273,"line":305},[271,1298,1299],{"class":365},"from my_project.data import MyDataModule\n",[271,1301,1302],{"class":273,"line":310},[271,1303,291],{"emptyLinePlaceholder":290},[271,1305,1306],{"class":273,"line":325},[271,1307,1308],{"class":365},"# Entire training loop, CLI, and config loading in one line:\n",[271,1310,1311],{"class":273,"line":347},[271,1312,1313],{"class":365},"cli = LightningCLI(MyModel, MyDataModule)\n",[271,1315,1316],{"class":273,"line":398},[271,1317,291],{"emptyLinePlaceholder":290},[271,1319,1320],{"class":273,"line":438},[271,1321,1322],{"class":365},"# config.yaml:\n",[271,1324,1325],{"class":273,"line":481},[271,1326,1327],{"class":365},"# model:\n",[271,1329,1330],{"class":273,"line":518},[271,1331,1332],{"class":365},"#   class_path: my_project.model.MyModel\n",[271,1334,1335],{"class":273,"line":556},[271,1336,1337],{"class":365},"#   init_args:\n",[271,1339,1340],{"class":273,"line":572},[271,1341,1342],{"class":365},"#     hidden_dim: 256\n",[271,1344,1345],{"class":273,"line":577},[271,1346,1347],{"class":365},"# trainer:\n",[271,1349,1350],{"class":273,"line":583},[271,1351,1352],{"class":365},"#   max_epochs: 10\n",[271,1354,1355],{"class":273,"line":589},[271,1356,973],{"class":361},[271,1358,1359,1361,1363,1365],{"class":273,"line":595},[271,1360,647],{"class":646},[271,1362,358],{"class":321},[271,1364,982],{"class":340},[271,1366,395],{"class":321},[660,1368],{"data":1369,"kind":663},"CmZyb20gbGlnaHRuaW5nLnB5dG9yY2guY2xpIGltcG9ydCBMaWdodG5pbmdDTEkKZnJvbSBteV9wcm9qZWN0Lm1vZGVsIGltcG9ydCBNeU1vZGVsCmZyb20gbXlfcHJvamVjdC5kYXRhIGltcG9ydCBNeURhdGFNb2R1bGUKCiMgRW50aXJlIHRyYWluaW5nIGxvb3AsIENMSSwgYW5kIGNvbmZpZyBsb2FkaW5nIGluIG9uZSBsaW5lOgpjbGkgPSBMaWdodG5pbmdDTEkoTXlNb2RlbCwgTXlEYXRhTW9kdWxlKQoKIyBjb25maWcueWFtbDoKIyBtb2RlbDoKIyAgIGNsYXNzX3BhdGg6IG15X3Byb2plY3QubW9kZWwuTXlNb2RlbAojICAgaW5pdF9hcmdzOgojICAgICBoaWRkZW5fZGltOiAyNTYKIyB0cmFpbmVyOgojICAgbWF4X2Vwb2NoczogMTAKCg==",[216,1371,1372,1375,1376,1379],{},[219,1373,1374],{},"What LightningCLI adds:"," automatic CLI generation, class-path instantiation\n(",[224,1377,1378],{},"class_path: my_project.model.MyModel",").",[216,1381,1382],{},[219,1383,1384],{},"Constraints:",[668,1386,1387,1405,1408],{},[671,1388,1389,1390,1393,1394,1397,1398,1400,1401,1404],{},"Your model ",[219,1391,1392],{},"must"," subclass ",[224,1395,1396],{},"LightningModule","; your data ",[219,1399,1392],{}," be a\n",[224,1402,1403],{},"LightningDataModule",". Third-party or custom objects that don't fit this hierarchy are\nhard to compose.",[671,1406,1407],{},"Config composition is limited to what Lightning's parser understands: no arbitrary\nnesting of objects.",[671,1409,1410],{},"You're buying into the entire Lightning ecosystem; it's not a standalone config library.",[248,1412],{},[251,1414,1416],{"id":1415},"section-5-full-hydra","Section 5: Full Hydra",[216,1418,1419,1424,1425,1428,1429,1432],{},[1079,1420,1423],{"href":1421,"rel":1422},"https:\u002F\u002Fhydra.cc\u002F",[1083],"Hydra"," is the first tool that solves ",[239,1426,1427],{},"lazy construction"," properly:\na ",[224,1430,1431],{},"_target_"," key in YAML tells Hydra which class to instantiate.",[262,1434,1436],{"className":264,"code":1435,"language":266,"meta":267,"style":267},"# Illustrative — requires hydra-core\nsource = '''\n# conf\u002Fmodel\u002Flinear.yaml\n# _target_: torch.nn.Linear\n# in_features: 8\n# out_features: 1\n\n# conf\u002Foptimizer\u002Fsgd.yaml\n# _target_: torch.optim.SGD\n# lr: 1e-3\n# momentum: 0.9\n\n# conf\u002Fconfig.yaml\n# defaults:\n#   - model: linear\n#   - optimizer: sgd\n\nimport hydra\nfrom hydra.utils import instantiate\nfrom omegaconf import DictConfig\n\n@hydra.main(config_path=\"conf\", config_name=\"config\", version_base=None)\ndef train(cfg: DictConfig):\n    model = instantiate(cfg.model)\n    optimizer = instantiate(cfg.optimizer, params=model.parameters())\n    # cfg.model is typed as DictConfig, NOT nn.Linear\n    # cfg.optimizer.lr  ->  Any  (no static type)\n    ...\n\nif __name__ == \"__main__\":\n    train()\n'''\nprint(source)\n",[224,1437,1438,1443,1451,1456,1461,1466,1471,1475,1480,1485,1490,1495,1499,1504,1509,1514,1519,1523,1528,1533,1538,1542,1547,1552,1557,1562,1567,1573,1579,1584,1590,1596,1601],{"__ignoreMap":267},[271,1439,1440],{"class":273,"line":274},[271,1441,1442],{"class":277},"# Illustrative — requires hydra-core\n",[271,1444,1445,1447,1449],{"class":273,"line":281},[271,1446,906],{"class":301},[271,1448,332],{"class":331},[271,1450,911],{"class":361},[271,1452,1453],{"class":273,"line":287},[271,1454,1455],{"class":365},"# conf\u002Fmodel\u002Flinear.yaml\n",[271,1457,1458],{"class":273,"line":294},[271,1459,1460],{"class":365},"# _target_: torch.nn.Linear\n",[271,1462,1463],{"class":273,"line":305},[271,1464,1465],{"class":365},"# in_features: 8\n",[271,1467,1468],{"class":273,"line":310},[271,1469,1470],{"class":365},"# out_features: 1\n",[271,1472,1473],{"class":273,"line":325},[271,1474,291],{"emptyLinePlaceholder":290},[271,1476,1477],{"class":273,"line":347},[271,1478,1479],{"class":365},"# conf\u002Foptimizer\u002Fsgd.yaml\n",[271,1481,1482],{"class":273,"line":398},[271,1483,1484],{"class":365},"# _target_: torch.optim.SGD\n",[271,1486,1487],{"class":273,"line":438},[271,1488,1489],{"class":365},"# lr: 1e-3\n",[271,1491,1492],{"class":273,"line":481},[271,1493,1494],{"class":365},"# momentum: 0.9\n",[271,1496,1497],{"class":273,"line":518},[271,1498,291],{"emptyLinePlaceholder":290},[271,1500,1501],{"class":273,"line":556},[271,1502,1503],{"class":365},"# conf\u002Fconfig.yaml\n",[271,1505,1506],{"class":273,"line":572},[271,1507,1508],{"class":365},"# defaults:\n",[271,1510,1511],{"class":273,"line":577},[271,1512,1513],{"class":365},"#   - model: linear\n",[271,1515,1516],{"class":273,"line":583},[271,1517,1518],{"class":365},"#   - optimizer: sgd\n",[271,1520,1521],{"class":273,"line":589},[271,1522,291],{"emptyLinePlaceholder":290},[271,1524,1525],{"class":273,"line":595},[271,1526,1527],{"class":365},"import hydra\n",[271,1529,1530],{"class":273,"line":601},[271,1531,1532],{"class":365},"from hydra.utils import instantiate\n",[271,1534,1535],{"class":273,"line":607},[271,1536,1537],{"class":365},"from omegaconf import DictConfig\n",[271,1539,1540],{"class":273,"line":613},[271,1541,291],{"emptyLinePlaceholder":290},[271,1543,1544],{"class":273,"line":619},[271,1545,1546],{"class":365},"@hydra.main(config_path=\"conf\", config_name=\"config\", version_base=None)\n",[271,1548,1549],{"class":273,"line":625},[271,1550,1551],{"class":365},"def train(cfg: DictConfig):\n",[271,1553,1554],{"class":273,"line":631},[271,1555,1556],{"class":365},"    model = instantiate(cfg.model)\n",[271,1558,1559],{"class":273,"line":637},[271,1560,1561],{"class":365},"    optimizer = instantiate(cfg.optimizer, params=model.parameters())\n",[271,1563,1564],{"class":273,"line":643},[271,1565,1566],{"class":365},"    # cfg.model is typed as DictConfig, NOT nn.Linear\n",[271,1568,1570],{"class":273,"line":1569},27,[271,1571,1572],{"class":365},"    # cfg.optimizer.lr  ->  Any  (no static type)\n",[271,1574,1576],{"class":273,"line":1575},28,[271,1577,1578],{"class":365},"    ...\n",[271,1580,1582],{"class":273,"line":1581},29,[271,1583,291],{"emptyLinePlaceholder":290},[271,1585,1587],{"class":273,"line":1586},30,[271,1588,1589],{"class":365},"if __name__ == \"__main__\":\n",[271,1591,1593],{"class":273,"line":1592},31,[271,1594,1595],{"class":365},"    train()\n",[271,1597,1599],{"class":273,"line":1598},32,[271,1600,973],{"class":361},[271,1602,1604,1606,1608,1610],{"class":273,"line":1603},33,[271,1605,647],{"class":646},[271,1607,358],{"class":321},[271,1609,982],{"class":340},[271,1611,395],{"class":321},[660,1613],{"data":1614,"kind":663},"CiMgY29uZi9tb2RlbC9saW5lYXIueWFtbAojIF90YXJnZXRfOiB0b3JjaC5ubi5MaW5lYXIKIyBpbl9mZWF0dXJlczogOAojIG91dF9mZWF0dXJlczogMQoKIyBjb25mL29wdGltaXplci9zZ2QueWFtbAojIF90YXJnZXRfOiB0b3JjaC5vcHRpbS5TR0QKIyBscjogMWUtMwojIG1vbWVudHVtOiAwLjkKCiMgY29uZi9jb25maWcueWFtbAojIGRlZmF1bHRzOgojICAgLSBtb2RlbDogbGluZWFyCiMgICAtIG9wdGltaXplcjogc2dkCgppbXBvcnQgaHlkcmEKZnJvbSBoeWRyYS51dGlscyBpbXBvcnQgaW5zdGFudGlhdGUKZnJvbSBvbWVnYWNvbmYgaW1wb3J0IERpY3RDb25maWcKCkBoeWRyYS5tYWluKGNvbmZpZ19wYXRoPSJjb25mIiwgY29uZmlnX25hbWU9ImNvbmZpZyIsIHZlcnNpb25fYmFzZT1Ob25lKQpkZWYgdHJhaW4oY2ZnOiBEaWN0Q29uZmlnKToKICAgIG1vZGVsID0gaW5zdGFudGlhdGUoY2ZnLm1vZGVsKQogICAgb3B0aW1pemVyID0gaW5zdGFudGlhdGUoY2ZnLm9wdGltaXplciwgcGFyYW1zPW1vZGVsLnBhcmFtZXRlcnMoKSkKICAgICMgY2ZnLm1vZGVsIGlzIHR5cGVkIGFzIERpY3RDb25maWcsIE5PVCBubi5MaW5lYXIKICAgICMgY2ZnLm9wdGltaXplci5sciAgLT4gIEFueSAgKG5vIHN0YXRpYyB0eXBlKQogICAgLi4uCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgdHJhaW4oKQoK",[216,1616,1617,1620,1621,1623],{},[219,1618,1619],{},"What Hydra adds:"," composable config groups, ",[224,1622,1431],{},"-based lazy instantiation,\nsweepers, multirun.",[216,1625,1626],{},[219,1627,1628],{},"Remaining friction:",[668,1630,1631,1642,1658],{},[671,1632,1633,1634,1637,1638,1641],{},"Config is split across a ",[239,1635,1636],{},"directory"," of YAML files with magic string group references\n(",[224,1639,1640],{},"defaults: [model: linear]","), so refactoring a class name requires hunting all YAML files.",[671,1643,1644,1645,1034,1648,1651,1652,1654,1655,260],{},"Static types are lost: ",[224,1646,1647],{},"cfg.model",[224,1649,1650],{},"DictConfig",", not ",[224,1653,1244],{},".\nThe IDE cannot autocomplete ",[224,1656,1657],{},"cfg.model.in_features",[671,1659,1660,1661,1664],{},"The ",[224,1662,1663],{},"@hydra.main"," decorator changes how your script is run (subprocess isolation,\nworking-directory changes), which is subtle to debug.",[248,1666],{},[251,1668,1670],{"id":1669},"section-6-hydra-zen","Section 6: hydra-zen",[216,1672,1673,1678,1679,1682],{},[1079,1674,1677],{"href":1675,"rel":1676},"https:\u002F\u002Fmit-ll-responsible-ai.github.io\u002Fhydra-zen\u002F",[1083],"hydra-zen"," solves one big Hydra\nannoyance: instead of writing YAML by hand, you use Python ",[224,1680,1681],{},"builds()"," calls to generate\nconfig dataclasses.",[262,1684,1686],{"className":264,"code":1685,"language":266,"meta":267,"style":267},"# Illustrative — requires hydra-zen and torch\nsource = '''\nfrom hydra_zen import builds, instantiate\nfrom torch import nn\n\nLinearConf = builds(nn.Linear, in_features=8, out_features=1)\ncfg = LinearConf()  # an instance of the generated dataclass\n\n# This is already better — no YAML file needed!\n# BUT: the return type of builds() is type[Any].\n# The IDE sees:  cfg : Any\n# Not:           cfg : nn.Linear\n\nmodel = instantiate(cfg)   # works at runtime\n# model : Any              # IDE has no idea this is nn.Linear\n\n# Nested composition:\nModelConf = builds(MyModel, encoder=builds(Encoder, depth=24))\n# The nested encoder field is also typed Any\n# cfg.encoder.depth  ->  AttributeError at write-time (no static type)\n'''\nprint(source)\n",[224,1687,1688,1693,1701,1706,1711,1715,1720,1725,1729,1734,1739,1744,1749,1753,1758,1763,1767,1772,1777,1782,1787,1791],{"__ignoreMap":267},[271,1689,1690],{"class":273,"line":274},[271,1691,1692],{"class":277},"# Illustrative — requires hydra-zen and torch\n",[271,1694,1695,1697,1699],{"class":273,"line":281},[271,1696,906],{"class":301},[271,1698,332],{"class":331},[271,1700,911],{"class":361},[271,1702,1703],{"class":273,"line":287},[271,1704,1705],{"class":365},"from hydra_zen import builds, instantiate\n",[271,1707,1708],{"class":273,"line":294},[271,1709,1710],{"class":365},"from torch import nn\n",[271,1712,1713],{"class":273,"line":305},[271,1714,291],{"emptyLinePlaceholder":290},[271,1716,1717],{"class":273,"line":310},[271,1718,1719],{"class":365},"LinearConf = builds(nn.Linear, in_features=8, out_features=1)\n",[271,1721,1722],{"class":273,"line":325},[271,1723,1724],{"class":365},"cfg = LinearConf()  # an instance of the generated dataclass\n",[271,1726,1727],{"class":273,"line":347},[271,1728,291],{"emptyLinePlaceholder":290},[271,1730,1731],{"class":273,"line":398},[271,1732,1733],{"class":365},"# This is already better — no YAML file needed!\n",[271,1735,1736],{"class":273,"line":438},[271,1737,1738],{"class":365},"# BUT: the return type of builds() is type[Any].\n",[271,1740,1741],{"class":273,"line":481},[271,1742,1743],{"class":365},"# The IDE sees:  cfg : Any\n",[271,1745,1746],{"class":273,"line":518},[271,1747,1748],{"class":365},"# Not:           cfg : nn.Linear\n",[271,1750,1751],{"class":273,"line":556},[271,1752,291],{"emptyLinePlaceholder":290},[271,1754,1755],{"class":273,"line":572},[271,1756,1757],{"class":365},"model = instantiate(cfg)   # works at runtime\n",[271,1759,1760],{"class":273,"line":577},[271,1761,1762],{"class":365},"# model : Any              # IDE has no idea this is nn.Linear\n",[271,1764,1765],{"class":273,"line":583},[271,1766,291],{"emptyLinePlaceholder":290},[271,1768,1769],{"class":273,"line":589},[271,1770,1771],{"class":365},"# Nested composition:\n",[271,1773,1774],{"class":273,"line":595},[271,1775,1776],{"class":365},"ModelConf = builds(MyModel, encoder=builds(Encoder, depth=24))\n",[271,1778,1779],{"class":273,"line":601},[271,1780,1781],{"class":365},"# The nested encoder field is also typed Any\n",[271,1783,1784],{"class":273,"line":607},[271,1785,1786],{"class":365},"# cfg.encoder.depth  ->  AttributeError at write-time (no static type)\n",[271,1788,1789],{"class":273,"line":613},[271,1790,973],{"class":361},[271,1792,1793,1795,1797,1799],{"class":273,"line":619},[271,1794,647],{"class":646},[271,1796,358],{"class":321},[271,1798,982],{"class":340},[271,1800,395],{"class":321},[660,1802],{"data":1803,"kind":663},"CmZyb20gaHlkcmFfemVuIGltcG9ydCBidWlsZHMsIGluc3RhbnRpYXRlCmZyb20gdG9yY2ggaW1wb3J0IG5uCgpMaW5lYXJDb25mID0gYnVpbGRzKG5uLkxpbmVhciwgaW5fZmVhdHVyZXM9OCwgb3V0X2ZlYXR1cmVzPTEpCmNmZyA9IExpbmVhckNvbmYoKSAgIyBhbiBpbnN0YW5jZSBvZiB0aGUgZ2VuZXJhdGVkIGRhdGFjbGFzcwoKIyBUaGlzIGlzIGFscmVhZHkgYmV0dGVyIOKAlCBubyBZQU1MIGZpbGUgbmVlZGVkIQojIEJVVDogdGhlIHJldHVybiB0eXBlIG9mIGJ1aWxkcygpIGlzIHR5cGVbQW55XS4KIyBUaGUgSURFIHNlZXM6ICBjZmcgOiBBbnkKIyBOb3Q6ICAgICAgICAgICBjZmcgOiBubi5MaW5lYXIKCm1vZGVsID0gaW5zdGFudGlhdGUoY2ZnKSAgICMgd29ya3MgYXQgcnVudGltZQojIG1vZGVsIDogQW55ICAgICAgICAgICAgICAjIElERSBoYXMgbm8gaWRlYSB0aGlzIGlzIG5uLkxpbmVhcgoKIyBOZXN0ZWQgY29tcG9zaXRpb246Ck1vZGVsQ29uZiA9IGJ1aWxkcyhNeU1vZGVsLCBlbmNvZGVyPWJ1aWxkcyhFbmNvZGVyLCBkZXB0aD0yNCkpCiMgVGhlIG5lc3RlZCBlbmNvZGVyIGZpZWxkIGlzIGFsc28gdHlwZWQgQW55CiMgY2ZnLmVuY29kZXIuZGVwdGggIC0+ICBBdHRyaWJ1dGVFcnJvciBhdCB3cml0ZS10aW1lIChubyBzdGF0aWMgdHlwZSkKCg==",[216,1805,1806,1809],{},[219,1807,1808],{},"What hydra-zen adds:"," Python-first config construction, with no YAML directory required.",[216,1811,1812,1815,1816,1034,1819,1651,1822,1825,1826,1829],{},[219,1813,1814],{},"The one remaining gap:"," the return type of ",[224,1817,1818],{},"builds(T, ...)()",[224,1820,1821],{},"Any",[224,1823,1824],{},"T",".\nWhen configs are deeply nested, the IDE cannot follow the types across composition\nboundaries. You lose autocomplete precisely where you need it most: on the ",[239,1827,1828],{},"fields"," of\nthe instantiated object.",[248,1831],{},[251,1833,1835],{"id":1834},"section-7-enter-laco","Section 7: Enter Laco",[216,1837,1838,1839,1842,1843,1846,1847,1849,1850,1852],{},"Laco's key insight is called the ",[219,1840,1841],{},"lie-typing contract",": the static return type declared\nby the config primitive intentionally ",[239,1844,1845],{},"lies"," to the type-checker, claiming to return the\ntarget type ",[224,1848,1824],{}," while actually returning a ",[224,1851,1650],{}," at runtime.",[216,1854,1855],{},"This is not a bug. It is a deliberate design choice that keeps deeply nested config\ncomposition tractable under Python's type system.",[262,1857,1859],{"className":264,"code":1858,"language":266,"meta":267,"style":267},"import laco.language as L\n\n# Use stdlib int so this cell runs without torch\ncfg = L.call(int)()      # static type (what pyright sees): int\n                         # runtime type (what Python holds): DictConfig\n\nprint(\"type at runtime :\", type(cfg))\nprint(\"_target_ key    :\", cfg._target_)  # noqa: LACO001\n",[224,1860,1861,1879,1883,1888,1912,1917,1921,1946],{"__ignoreMap":267},[271,1862,1863,1865,1868,1870,1873,1876],{"class":273,"line":274},[271,1864,298],{"class":297},[271,1866,1867],{"class":301}," laco",[271,1869,260],{"class":321},[271,1871,198],{"class":1872},"skxfh",[271,1874,1875],{"class":297}," as",[271,1877,1878],{"class":301}," L\n",[271,1880,1881],{"class":273,"line":281},[271,1882,291],{"emptyLinePlaceholder":290},[271,1884,1885],{"class":273,"line":287},[271,1886,1887],{"class":277},"# Use stdlib int so this cell runs without torch\n",[271,1889,1890,1892,1894,1897,1899,1902,1904,1906,1909],{"class":273,"line":294},[271,1891,810],{"class":301},[271,1893,332],{"class":331},[271,1895,1896],{"class":301}," L",[271,1898,260],{"class":321},[271,1900,1901],{"class":340},"call",[271,1903,358],{"class":321},[271,1905,423],{"class":380},[271,1907,1908],{"class":321},")()",[271,1910,1911],{"class":277},"      # static type (what pyright sees): int\n",[271,1913,1914],{"class":273,"line":305},[271,1915,1916],{"class":277},"                         # runtime type (what Python holds): DictConfig\n",[271,1918,1919],{"class":273,"line":310},[271,1920,291],{"emptyLinePlaceholder":290},[271,1922,1923,1925,1927,1929,1932,1934,1936,1939,1941,1943],{"class":273,"line":325},[271,1924,647],{"class":646},[271,1926,358],{"class":321},[271,1928,362],{"class":361},[271,1930,1931],{"class":365},"type at runtime :",[271,1933,362],{"class":361},[271,1935,371],{"class":321},[271,1937,1938],{"class":380}," type",[271,1940,358],{"class":321},[271,1942,836],{"class":340},[271,1944,1945],{"class":321},"))\n",[271,1947,1948,1950,1952,1954,1957,1959,1961,1964,1966,1968,1970],{"class":273,"line":347},[271,1949,647],{"class":646},[271,1951,358],{"class":321},[271,1953,362],{"class":361},[271,1955,1956],{"class":365},"_target_ key    :",[271,1958,362],{"class":361},[271,1960,371],{"class":321},[271,1962,1963],{"class":340}," cfg",[271,1965,260],{"class":321},[271,1967,1431],{"class":1872},[271,1969,1024],{"class":321},[271,1971,1972],{"class":277},"  # noqa: LACO001\n",[660,1974],{"data":1975,"kind":663},"dHlwZSBhdCBydW50aW1lIDogPGNsYXNzICdvbWVnYWNvbmYuZGljdGNvbmZpZy5EaWN0Q29uZmlnJz4KX3RhcmdldF8ga2V5ICAgIDogYnVpbHRpbnMuaW50Cg==",[660,1977],{"data":1978,"kind":663},"PGNlbGwtOD46NDogTGF6eUNhbGxJbnRyb3NwZWN0aW9uV2FybmluZzogTC5jYWxsKGludCwgc3RyaWN0PVRydWUpOiBjYW5ub3QgaW50cm9zcGVjdCB0YXJnZXQgc2lnbmF0dXJlOyBzdHJpY3QtbW9kZSBrd2FyZyB2YWxpZGF0aW9uIGlzIGRpc2FibGVkIGZvciB0aGlzIGNhbGwuIFBhc3MgYHN0cmljdD1GYWxzZWAgZXhwbGljaXRseSB0byBzaWxlbmNlIHRoaXMgd2FybmluZy4KICBjZmcgPSBMLmNhbGwoaW50KSgpICAgICAgIyBzdGF0aWMgdHlwZSAod2hhdCBweXJpZ2h0IHNlZXMpOiBpbnQK",[216,1980,1981,1982,1984,1985,1987],{},"The IDE (and pyright) sees ",[224,1983,836],{}," as ",[224,1986,423],{},". That means:",[668,1989,1990,2001,2096],{},[671,1991,1992,1995,1996,1998,1999,1379],{},[224,1993,1994],{},"cfg.bit_length()"," autocompletes (even though ",[224,1997,836],{}," is really a ",[224,2000,1650],{},[671,2002,2003,2004],{},"Nested composition keeps its types:\n",[262,2005,2007],{"className":264,"code":2006,"language":266,"meta":267,"style":267},"class Model:\n    encoder: Encoder\n\nmodel_cfg = L.call(Model)(encoder=L.call(Encoder)(depth=24))\n# model_cfg : Model  (static)\n# model_cfg.encoder : Encoder  (static — autocomplete works!)\n",[224,2008,2009,2021,2032,2036,2086,2091],{"__ignoreMap":267},[271,2010,2011,2014,2018],{"class":273,"line":274},[271,2012,2013],{"class":313},"class",[271,2015,2017],{"class":2016},"sbgvK"," Model",[271,2019,2020],{"class":321},":\n",[271,2022,2023,2026,2029],{"class":273,"line":281},[271,2024,2025],{"class":301},"    encoder",[271,2027,2028],{"class":321},":",[271,2030,2031],{"class":301}," Encoder\n",[271,2033,2034],{"class":273,"line":287},[271,2035,291],{"emptyLinePlaceholder":290},[271,2037,2038,2041,2043,2045,2047,2049,2051,2054,2057,2060,2062,2065,2067,2069,2071,2074,2076,2079,2081,2084],{"class":273,"line":294},[271,2039,2040],{"class":301},"model_cfg ",[271,2042,332],{"class":331},[271,2044,1896],{"class":301},[271,2046,260],{"class":321},[271,2048,1901],{"class":340},[271,2050,358],{"class":321},[271,2052,2053],{"class":340},"Model",[271,2055,2056],{"class":321},")(",[271,2058,2059],{"class":374},"encoder",[271,2061,332],{"class":331},[271,2063,2064],{"class":340},"L",[271,2066,260],{"class":321},[271,2068,1901],{"class":340},[271,2070,358],{"class":321},[271,2072,2073],{"class":340},"Encoder",[271,2075,2056],{"class":321},[271,2077,2078],{"class":374},"depth",[271,2080,332],{"class":331},[271,2082,2083],{"class":391},"24",[271,2085,1945],{"class":321},[271,2087,2088],{"class":273,"line":305},[271,2089,2090],{"class":277},"# model_cfg : Model  (static)\n",[271,2092,2093],{"class":273,"line":310},[271,2094,2095],{"class":277},"# model_cfg.encoder : Encoder  (static — autocomplete works!)\n",[671,2097,2098,2101,2102,1852],{},[224,2099,2100],{},"laco.instantiate(model_cfg)"," produces a real ",[224,2103,2053],{},[216,2105,2106],{},"The full table of lie-typing constructs:",[994,2108,2109,2122],{},[997,2110,2111],{},[1000,2112,2113,2116,2119],{},[1003,2114,2115],{},"Construct",[1003,2117,2118],{},"Static type (IDE sees)",[1003,2120,2121],{},"Runtime value",[1010,2123,2124,2142,2161,2176],{},[1000,2125,2126,2131,2135],{},[1015,2127,2128],{},[224,2129,2130],{},"L.call(T)(**kw)",[1015,2132,2133],{},[224,2134,1824],{},[1015,2136,2137,2139,2140,1024],{},[224,2138,1650],{}," (with ",[224,2141,1431],{},[1000,2143,2144,2149,2154],{},[1015,2145,2146],{},[224,2147,2148],{},"L.partial(T)(**kw)",[1015,2150,2151],{},[224,2152,2153],{},"functools.partial[T]",[1015,2155,2156,2139,2158,1024],{},[224,2157,1650],{},[224,2159,2160],{},"_partial_: true",[1000,2162,2163,2168,2173],{},[1015,2164,2165],{},[224,2166,2167],{},"L.just(obj)",[1015,2169,2170],{},[224,2171,2172],{},"type(obj)",[1015,2174,2175],{},"identity-instantiated node",[1000,2177,2178,2183,2187],{},[1015,2179,2180],{},[224,2181,2182],{},"L.required[T]()",[1015,2184,2185],{},[224,2186,1824],{},[1015,2188,2189],{},[224,2190,2191],{},"OmegaConf.MISSING",[2193,2194,2196],"h3",{"id":2195},"comparing-the-full-tool-landscape","Comparing the full tool landscape",[216,2198,2199],{},"Now that we understand what Laco does, here is how the major configuration tools compare\nacross seven properties.",[994,2201,2202,2230],{},[997,2203,2204],{},[1000,2205,2206,2208,2212,2215,2218,2221,2224,2227],{},[1003,2207],{},[1003,2209,2211],{"align":2210},"center","Serializable",[1003,2213,2214],{"align":2210},"Type-safe",[1003,2216,2217],{"align":2210},"No magic strings",[1003,2219,2220],{"align":2210},"Lazy construction",[1003,2222,2223],{"align":2210},"IDE autocomplete",[1003,2225,2226],{"align":2210},"Built-in CLI",[1003,2228,2229],{"align":2210},"Low learning curve",[1010,2231,2232,2253,2272,2291,2309,2327,2345],{},[1000,2233,2234,2236,2239,2241,2244,2246,2249,2251],{},[1015,2235,226],{},[1015,2237,2238],{"align":2210},"No",[1015,2240,2238],{"align":2210},[1015,2242,2243],{"align":2210},"Yes",[1015,2245,2238],{"align":2210},[1015,2247,2248],{"align":2210},"Partial",[1015,2250,2243],{"align":2210},[1015,2252,2243],{"align":2210},[1000,2254,2255,2258,2260,2262,2264,2266,2268,2270],{},[1015,2256,2257],{},"Raw JSON \u002F YAML",[1015,2259,2243],{"align":2210},[1015,2261,2238],{"align":2210},[1015,2263,2238],{"align":2210},[1015,2265,2238],{"align":2210},[1015,2267,2238],{"align":2210},[1015,2269,2238],{"align":2210},[1015,2271,2243],{"align":2210},[1000,2273,2274,2277,2279,2281,2283,2285,2287,2289],{},[1015,2275,2276],{},"OmegaConf + YAML",[1015,2278,2243],{"align":2210},[1015,2280,2248],{"align":2210},[1015,2282,2238],{"align":2210},[1015,2284,2238],{"align":2210},[1015,2286,2248],{"align":2210},[1015,2288,2238],{"align":2210},[1015,2290,2248],{"align":2210},[1000,2292,2293,2295,2297,2299,2301,2303,2305,2307],{},[1015,2294,1261],{},[1015,2296,2243],{"align":2210},[1015,2298,2248],{"align":2210},[1015,2300,2248],{"align":2210},[1015,2302,2243],{"align":2210},[1015,2304,2248],{"align":2210},[1015,2306,2243],{"align":2210},[1015,2308,2248],{"align":2210},[1000,2310,2311,2313,2315,2317,2319,2321,2323,2325],{},[1015,2312,1423],{},[1015,2314,2243],{"align":2210},[1015,2316,2238],{"align":2210},[1015,2318,2238],{"align":2210},[1015,2320,2243],{"align":2210},[1015,2322,2238],{"align":2210},[1015,2324,2243],{"align":2210},[1015,2326,2238],{"align":2210},[1000,2328,2329,2331,2333,2335,2337,2339,2341,2343],{},[1015,2330,1677],{},[1015,2332,2243],{"align":2210},[1015,2334,2248],{"align":2210},[1015,2336,2243],{"align":2210},[1015,2338,2243],{"align":2210},[1015,2340,2248],{"align":2210},[1015,2342,2243],{"align":2210},[1015,2344,2248],{"align":2210},[1000,2346,2347,2352,2354,2356,2358,2360,2362,2364],{},[1015,2348,2349],{},[219,2350,2351],{},"Laco",[1015,2353,2243],{"align":2210},[1015,2355,2243],{"align":2210},[1015,2357,2243],{"align":2210},[1015,2359,2243],{"align":2210},[1015,2361,2243],{"align":2210},[1015,2363,2243],{"align":2210},[1015,2365,2248],{"align":2210},[2193,2367,2369],{"id":2368},"observations-from-the-table","Observations from the table",[668,2371,2372,2377,2383,2391,2399,2406],{},[671,2373,2374,2376],{},[219,2375,226],{}," is the easiest to learn but fails on every property that matters at scale.",[671,2378,2379,2382],{},[219,2380,2381],{},"Raw YAML"," gains serializability but loses everything else.",[671,2384,2385,2387,2388,2390],{},[219,2386,1084],{}," and ",[219,2389,1261],{}," are partial improvements: they add types or a CLI\nbut require framework buy-in or still leave object construction manual.",[671,2392,2393,2395,2396,2398],{},[219,2394,1423],{}," introduces lazy construction via ",[224,2397,1431],{}," but sacrifices type safety and\nIDE support. Magic string group references make refactoring fragile.",[671,2400,2401,2403,2404,260],{},[219,2402,1677],{}," patches Hydra's Python-ergonomics gap but still types everything as ",[224,2405,1821],{},[671,2407,2408,2410,2411,2414],{},[219,2409,2351],{}," reaches ",[239,2412,2413],{},"all green"," except learning curve, which is what this tutorial series\nis here to flatten.",[248,2416],{},[251,2418,2420],{"id":2419},"wrapping-up","Wrapping Up",[216,2422,2423],{},"The configuration problem is not just about storing hyperparameters. It is about\ndescribing an entire object graph (model, optimizer, scheduler, data pipeline) in a way\nthat is:",[2425,2426,2427,2432,2437,2447],"ol",{},[671,2428,2429,2431],{},[219,2430,2211],{},": experiments are reproducible.",[671,2433,2434,2436],{},[219,2435,2214],{},": errors surface at edit-time, not at crash-time.",[671,2438,2439,2442,2443,2446],{},[219,2440,2441],{},"Lazily constructed",": the config file is a ",[239,2444,2445],{},"recipe",", not a running program.",[671,2448,2449,2452],{},[219,2450,2451],{},"IDE-friendly",": composing nested objects doesn't require guessing types by hand.",[216,2454,2455,2456,2458,2459,2462,2463,2465,2466,2468,2469,2472],{},"Laco achieves all four by embracing the ",[219,2457,1841],{},": config primitives like\n",[224,2460,2461],{},"L.call(T)"," tell the IDE you have a ",[224,2464,1824],{}," while quietly storing a ",[224,2467,1650],{}," recipe.\n",[224,2470,2471],{},"laco.instantiate()"," bakes the recipe into a real Python object whenever you need it.",[248,2474],{},[216,2476,2477,2484,2485,726,2488,726,2491,733,2494,2497,2498,2501],{},[219,2478,2479,2480,2483],{},"The next notebook, ",[224,2481,2482],{},"02.first-steps.ipynb",", writes your first working Laco\nconfig",", walking through ",[224,2486,2487],{},"L.call",[224,2489,2490],{},"laco.load",[224,2492,2493],{},"laco.instantiate",[224,2495,2496],{},"laco.dump",",\nand loading the ",[224,2499,2500],{},"linear_regression"," example that ships with the library.",[2503,2504,2505],"style",{},"html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .slqww, html code.shiki .slqww{--shiki-light:#6182B8;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sptTA, html code.shiki .sptTA{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}",{"title":267,"searchDepth":287,"depth":287,"links":2507},[2508,2509,2510,2511,2512,2513,2514,2518],{"id":253,"depth":281,"text":254},{"id":741,"depth":281,"text":742},{"id":1074,"depth":281,"text":1075},{"id":1253,"depth":281,"text":1254},{"id":1415,"depth":281,"text":1416},{"id":1669,"depth":281,"text":1670},{"id":1834,"depth":281,"text":1835,"children":2515},[2516,2517],{"id":2195,"depth":287,"text":2196},{"id":2368,"depth":287,"text":2369},{"id":2419,"depth":281,"text":2420},"Prerequisites: Basic Python. Prior use of argparse or a YAML-based config loader such as yaml.safe_load is helpful.","md",{"notebook":290},{"icon":25},{"title":22,"description":2519},"nuJmcVEJFiTf8SrW7QQ6Qo3bF0TsVZ3eXNiSptef_W8",{},1785687301540]