[{"data":1,"prerenderedAt":1396},["ShallowReactive",2],{"page-\u002Fprompt-engineering\u002F16-working-with-gpt-and-other-models":3},{"id":4,"title":5,"body":6,"description":1389,"extension":1390,"meta":1391,"navigation":58,"path":1392,"seo":1393,"stem":1394,"__hash__":1395},"content\u002Fprompt-engineering\u002F16-working-with-gpt-and-other-models.md","16 — Working with GPT & Other Models",{"type":7,"value":8,"toc":1378},"minimark",[9,13,18,160,164,269,295,299,356,576,580,649,730,734,977,981,1100,1104,1208,1212,1216,1254,1258,1374],[10,11,5],"h1",{"id":12},"_16-working-with-gpt-other-models",[14,15,17],"h2",{"id":16},"the-portability-problem","The Portability Problem",[19,20,23],"code-wrapper",{"filename":21,"language":22},"portability_problem.py","python",[24,25,29],"pre",{"className":26,"code":27,"language":22,"meta":28,"style":28},"language-python shiki shiki-themes github-light github-dark","# An identical prompt string is NOT an identical instruction across model families.\n# Instruction-following style, formatting conventions, and how literally a constraint\n# is honored all vary meaningfully across model families.\n\n# A prompt engineered and tuned against one model is NOT guaranteed to perform the\n# same way on another, even when both are \"highly capable.\" Treating a prompt as\n# portable-by-default without re-validation is a common cause of silent degradation\n# after a model swap or upgrade.\n\n# WHAT TRANSFERS CLEANLY (model-agnostic fundamentals):\n#   - clarity, specificity, explicit constraints (Chapter 4)\n#   - structural decomposition (Chapter 10)\n#   - role separation (Chapter 2)\n#   - structured output schemas (Chapter 7)\n\n# WHAT NEEDS RE-TUNING PER FAMILY:\n#   - formatting conventions (XML tags, markdown defaults)\n#   - system-message weighting \u002F instruction hierarchy\n#   - reasoning-elicitation phrasing (CoT vs. let-the-model-reason-internally)\n#   - refusal\u002Fcaution thresholds\n#   - verbosity defaults\n","",[30,31,32,41,47,53,60,66,72,78,84,89,95,101,107,113,119,124,130,136,142,148,154],"code",{"__ignoreMap":28},[33,34,37],"span",{"class":35,"line":36},"line",1,[33,38,40],{"class":39},"sdCPZ","# An identical prompt string is NOT an identical instruction across model families.\n",[33,42,44],{"class":35,"line":43},2,[33,45,46],{"class":39},"# Instruction-following style, formatting conventions, and how literally a constraint\n",[33,48,50],{"class":35,"line":49},3,[33,51,52],{"class":39},"# is honored all vary meaningfully across model families.\n",[33,54,56],{"class":35,"line":55},4,[33,57,59],{"emptyLinePlaceholder":58},true,"\n",[33,61,63],{"class":35,"line":62},5,[33,64,65],{"class":39},"# A prompt engineered and tuned against one model is NOT guaranteed to perform the\n",[33,67,69],{"class":35,"line":68},6,[33,70,71],{"class":39},"# same way on another, even when both are \"highly capable.\" Treating a prompt as\n",[33,73,75],{"class":35,"line":74},7,[33,76,77],{"class":39},"# portable-by-default without re-validation is a common cause of silent degradation\n",[33,79,81],{"class":35,"line":80},8,[33,82,83],{"class":39},"# after a model swap or upgrade.\n",[33,85,87],{"class":35,"line":86},9,[33,88,59],{"emptyLinePlaceholder":58},[33,90,92],{"class":35,"line":91},10,[33,93,94],{"class":39},"# WHAT TRANSFERS CLEANLY (model-agnostic fundamentals):\n",[33,96,98],{"class":35,"line":97},11,[33,99,100],{"class":39},"#   - clarity, specificity, explicit constraints (Chapter 4)\n",[33,102,104],{"class":35,"line":103},12,[33,105,106],{"class":39},"#   - structural decomposition (Chapter 10)\n",[33,108,110],{"class":35,"line":109},13,[33,111,112],{"class":39},"#   - role separation (Chapter 2)\n",[33,114,116],{"class":35,"line":115},14,[33,117,118],{"class":39},"#   - structured output schemas (Chapter 7)\n",[33,120,122],{"class":35,"line":121},15,[33,123,59],{"emptyLinePlaceholder":58},[33,125,127],{"class":35,"line":126},16,[33,128,129],{"class":39},"# WHAT NEEDS RE-TUNING PER FAMILY:\n",[33,131,133],{"class":35,"line":132},17,[33,134,135],{"class":39},"#   - formatting conventions (XML tags, markdown defaults)\n",[33,137,139],{"class":35,"line":138},18,[33,140,141],{"class":39},"#   - system-message weighting \u002F instruction hierarchy\n",[33,143,145],{"class":35,"line":144},19,[33,146,147],{"class":39},"#   - reasoning-elicitation phrasing (CoT vs. let-the-model-reason-internally)\n",[33,149,151],{"class":35,"line":150},20,[33,152,153],{"class":39},"#   - refusal\u002Fcaution thresholds\n",[33,155,157],{"class":35,"line":156},21,[33,158,159],{"class":39},"#   - verbosity defaults\n",[14,161,163],{"id":162},"openai-conventions","OpenAI Conventions",[19,165,167],{"filename":166,"language":22},"openai_conventions.py",[24,168,170],{"className":26,"code":169,"language":22,"meta":28,"style":28},"# MESSAGE ROLES carry different weight than Claude's system-priority model.\n# OpenAI has evolved toward more granular instruction hierarchy:\n#   - platform-level instructions (highest)\n#   - developer-level instructions\n#   - user-level instructions\n# This is actively evolving — check current OpenAI docs for the specific\n# role\u002Fpriority model of the API version you're targeting.\n\n# MARKDOWN is well-respected, but default formatting tendency (heavier vs lighter\n# use of bullets\u002Fheaders\u002Fbold) shifts across model versions. If your app parses\n# or displays output in a way sensitive to formatting, specify the desired format\n# explicitly rather than relying on a version's current default.\n\n# REASONING-OPTIMIZED MODELS (o1, o3, etc.) often need LESS explicit CoT prompting\n# — and sometimes actively DISCOURAGE it. The model's built-in reasoning process can\n# be HINDERED by a prompt trying to over-specify reasoning steps. This is a meaningful\n# contrast with standard chat models where Chapter 5's explicit CoT techniques help.\n\n# RULE: check model-specific guidance before assuming either\n# \"add explicit reasoning steps\" or \"keep it simple and let it reason\" is right.\n",[30,171,172,177,182,187,192,197,202,207,211,216,221,226,231,235,240,245,250,255,259,264],{"__ignoreMap":28},[33,173,174],{"class":35,"line":36},[33,175,176],{"class":39},"# MESSAGE ROLES carry different weight than Claude's system-priority model.\n",[33,178,179],{"class":35,"line":43},[33,180,181],{"class":39},"# OpenAI has evolved toward more granular instruction hierarchy:\n",[33,183,184],{"class":35,"line":49},[33,185,186],{"class":39},"#   - platform-level instructions (highest)\n",[33,188,189],{"class":35,"line":55},[33,190,191],{"class":39},"#   - developer-level instructions\n",[33,193,194],{"class":35,"line":62},[33,195,196],{"class":39},"#   - user-level instructions\n",[33,198,199],{"class":35,"line":68},[33,200,201],{"class":39},"# This is actively evolving — check current OpenAI docs for the specific\n",[33,203,204],{"class":35,"line":74},[33,205,206],{"class":39},"# role\u002Fpriority model of the API version you're targeting.\n",[33,208,209],{"class":35,"line":80},[33,210,59],{"emptyLinePlaceholder":58},[33,212,213],{"class":35,"line":86},[33,214,215],{"class":39},"# MARKDOWN is well-respected, but default formatting tendency (heavier vs lighter\n",[33,217,218],{"class":35,"line":91},[33,219,220],{"class":39},"# use of bullets\u002Fheaders\u002Fbold) shifts across model versions. If your app parses\n",[33,222,223],{"class":35,"line":97},[33,224,225],{"class":39},"# or displays output in a way sensitive to formatting, specify the desired format\n",[33,227,228],{"class":35,"line":103},[33,229,230],{"class":39},"# explicitly rather than relying on a version's current default.\n",[33,232,233],{"class":35,"line":109},[33,234,59],{"emptyLinePlaceholder":58},[33,236,237],{"class":35,"line":115},[33,238,239],{"class":39},"# REASONING-OPTIMIZED MODELS (o1, o3, etc.) often need LESS explicit CoT prompting\n",[33,241,242],{"class":35,"line":121},[33,243,244],{"class":39},"# — and sometimes actively DISCOURAGE it. The model's built-in reasoning process can\n",[33,246,247],{"class":35,"line":126},[33,248,249],{"class":39},"# be HINDERED by a prompt trying to over-specify reasoning steps. This is a meaningful\n",[33,251,252],{"class":35,"line":132},[33,253,254],{"class":39},"# contrast with standard chat models where Chapter 5's explicit CoT techniques help.\n",[33,256,257],{"class":35,"line":138},[33,258,59],{"emptyLinePlaceholder":58},[33,260,261],{"class":35,"line":144},[33,262,263],{"class":39},"# RULE: check model-specific guidance before assuming either\n",[33,265,266],{"class":35,"line":150},[33,267,268],{"class":39},"# \"add explicit reasoning steps\" or \"keep it simple and let it reason\" is right.\n",[19,270,273],{"filename":271,"language":272},"openai_format_control.md","markdown",[24,274,277],{"className":275,"code":276,"language":272,"meta":28,"style":28},"language-markdown shiki shiki-themes github-light github-dark","Respond in plain prose only. Do not use markdown formatting — no bullet\npoints, no headers, no bold text, no numbered lists — even if the content\nwould normally lend itself to a list.\n",[30,278,279,285,290],{"__ignoreMap":28},[33,280,281],{"class":35,"line":36},[33,282,284],{"class":283},"ssxIu","Respond in plain prose only. Do not use markdown formatting — no bullet\n",[33,286,287],{"class":35,"line":43},[33,288,289],{"class":283},"points, no headers, no bold text, no numbered lists — even if the content\n",[33,291,292],{"class":35,"line":49},[33,293,294],{"class":283},"would normally lend itself to a list.\n",[14,296,298],{"id":297},"portability-example-structured-extraction","Portability Example: Structured Extraction",[19,300,302],{"filename":301,"language":272},"portable_vs_nonportable.md",[24,303,305],{"className":275,"code":304,"language":272,"meta":28,"style":28},"\u003C!-- Claude-optimized prompt using XML tags — works on most models but\n     reliability of the JSON output specifically varies by family -->\n\u003Cemail>\n{{raw email text}}\n\u003C\u002Femail>\n\n\u003Ctask>\nExtract the sender's requested action, deadline (if any), and urgency\nlevel (low\u002Fmedium\u002Fhigh) as JSON.\n\u003C\u002Ftask>\n",[30,306,307,312,317,322,327,332,336,341,346,351],{"__ignoreMap":28},[33,308,309],{"class":35,"line":36},[33,310,311],{"class":39},"\u003C!-- Claude-optimized prompt using XML tags — works on most models but\n",[33,313,314],{"class":35,"line":43},[33,315,316],{"class":39},"     reliability of the JSON output specifically varies by family -->\n",[33,318,319],{"class":35,"line":49},[33,320,321],{"class":283},"\u003Cemail>\n",[33,323,324],{"class":35,"line":55},[33,325,326],{"class":283},"{{raw email text}}\n",[33,328,329],{"class":35,"line":62},[33,330,331],{"class":283},"\u003C\u002Femail>\n",[33,333,334],{"class":35,"line":68},[33,335,59],{"emptyLinePlaceholder":58},[33,337,338],{"class":35,"line":74},[33,339,340],{"class":283},"\u003Ctask>\n",[33,342,343],{"class":35,"line":80},[33,344,345],{"class":283},"Extract the sender's requested action, deadline (if any), and urgency\n",[33,347,348],{"class":35,"line":86},[33,349,350],{"class":283},"level (low\u002Fmedium\u002Fhigh) as JSON.\n",[33,352,353],{"class":35,"line":91},[33,354,355],{"class":283},"\u003C\u002Ftask>\n",[19,357,359],{"filename":358,"language":22},"portable_structured_output.py",[24,360,362],{"className":26,"code":361,"language":22,"meta":28,"style":28},"import json\n\n# MORE PORTABLE: use each provider's NATIVE structured-output mechanism\n# rather than relying purely on prompted formatting instructions.\n# The SHAPE GUARANTEE transfers even when prose-level instruction nuances don't.\n\nEXTRACTION_SCHEMA = {\n    \"type\": \"object\",\n    \"properties\": {\n        \"requested_action\": {\"type\": \"string\"},\n        \"deadline\": {\"type\": [\"string\", \"null\"]},\n        \"urgency\": {\"type\": \"string\", \"enum\": [\"low\", \"medium\", \"high\"]},\n    },\n    \"required\": [\"requested_action\", \"deadline\", \"urgency\"],\n}\n\n# Provider-specific invocation (parameter names differ — check current docs):\n# Claude: output_config={\"format\": {\"type\": \"json_schema\", \"schema\": EXTRACTION_SCHEMA}}\n# OpenAI: response_format={\"type\": \"json_schema\", \"json_schema\": {\"schema\": EXTRACTION_SCHEMA}}\n#\n# The conceptual point that transfers everywhere: prefer letting the API constrain\n# generation over prompting-and-hoping whenever the feature is available.\n",[30,363,364,373,377,382,387,392,396,408,423,431,450,473,508,513,536,541,545,550,555,560,565,570],{"__ignoreMap":28},[33,365,366,370],{"class":35,"line":36},[33,367,369],{"class":368},"svdQ7","import",[33,371,372],{"class":283}," json\n",[33,374,375],{"class":35,"line":43},[33,376,59],{"emptyLinePlaceholder":58},[33,378,379],{"class":35,"line":49},[33,380,381],{"class":39},"# MORE PORTABLE: use each provider's NATIVE structured-output mechanism\n",[33,383,384],{"class":35,"line":55},[33,385,386],{"class":39},"# rather than relying purely on prompted formatting instructions.\n",[33,388,389],{"class":35,"line":62},[33,390,391],{"class":39},"# The SHAPE GUARANTEE transfers even when prose-level instruction nuances don't.\n",[33,393,394],{"class":35,"line":68},[33,395,59],{"emptyLinePlaceholder":58},[33,397,398,402,405],{"class":35,"line":74},[33,399,401],{"class":400},"snvgF","EXTRACTION_SCHEMA",[33,403,404],{"class":368}," =",[33,406,407],{"class":283}," {\n",[33,409,410,414,417,420],{"class":35,"line":80},[33,411,413],{"class":412},"sJ6F3","    \"type\"",[33,415,416],{"class":283},": ",[33,418,419],{"class":412},"\"object\"",[33,421,422],{"class":283},",\n",[33,424,425,428],{"class":35,"line":86},[33,426,427],{"class":412},"    \"properties\"",[33,429,430],{"class":283},": {\n",[33,432,433,436,439,442,444,447],{"class":35,"line":91},[33,434,435],{"class":412},"        \"requested_action\"",[33,437,438],{"class":283},": {",[33,440,441],{"class":412},"\"type\"",[33,443,416],{"class":283},[33,445,446],{"class":412},"\"string\"",[33,448,449],{"class":283},"},\n",[33,451,452,455,457,459,462,464,467,470],{"class":35,"line":97},[33,453,454],{"class":412},"        \"deadline\"",[33,456,438],{"class":283},[33,458,441],{"class":412},[33,460,461],{"class":283},": [",[33,463,446],{"class":412},[33,465,466],{"class":283},", ",[33,468,469],{"class":412},"\"null\"",[33,471,472],{"class":283},"]},\n",[33,474,475,478,480,482,484,486,488,491,493,496,498,501,503,506],{"class":35,"line":103},[33,476,477],{"class":412},"        \"urgency\"",[33,479,438],{"class":283},[33,481,441],{"class":412},[33,483,416],{"class":283},[33,485,446],{"class":412},[33,487,466],{"class":283},[33,489,490],{"class":412},"\"enum\"",[33,492,461],{"class":283},[33,494,495],{"class":412},"\"low\"",[33,497,466],{"class":283},[33,499,500],{"class":412},"\"medium\"",[33,502,466],{"class":283},[33,504,505],{"class":412},"\"high\"",[33,507,472],{"class":283},[33,509,510],{"class":35,"line":109},[33,511,512],{"class":283},"    },\n",[33,514,515,518,520,523,525,528,530,533],{"class":35,"line":115},[33,516,517],{"class":412},"    \"required\"",[33,519,461],{"class":283},[33,521,522],{"class":412},"\"requested_action\"",[33,524,466],{"class":283},[33,526,527],{"class":412},"\"deadline\"",[33,529,466],{"class":283},[33,531,532],{"class":412},"\"urgency\"",[33,534,535],{"class":283},"],\n",[33,537,538],{"class":35,"line":121},[33,539,540],{"class":283},"}\n",[33,542,543],{"class":35,"line":126},[33,544,59],{"emptyLinePlaceholder":58},[33,546,547],{"class":35,"line":132},[33,548,549],{"class":39},"# Provider-specific invocation (parameter names differ — check current docs):\n",[33,551,552],{"class":35,"line":138},[33,553,554],{"class":39},"# Claude: output_config={\"format\": {\"type\": \"json_schema\", \"schema\": EXTRACTION_SCHEMA}}\n",[33,556,557],{"class":35,"line":144},[33,558,559],{"class":39},"# OpenAI: response_format={\"type\": \"json_schema\", \"json_schema\": {\"schema\": EXTRACTION_SCHEMA}}\n",[33,561,562],{"class":35,"line":150},[33,563,564],{"class":39},"#\n",[33,566,567],{"class":35,"line":156},[33,568,569],{"class":39},"# The conceptual point that transfers everywhere: prefer letting the API constrain\n",[33,571,573],{"class":35,"line":572},22,[33,574,575],{"class":39},"# generation over prompting-and-hoping whenever the feature is available.\n",[14,577,579],{"id":578},"open-weight-models-and-chat-templates","Open-Weight Models and Chat Templates",[19,581,583],{"filename":582,"language":272},"chat_template.md",[24,584,586],{"className":275,"code":585,"language":272,"meta":28,"style":28},"\u003C!-- WRONG: informal, ignores the model's expected chat template -->\nHey, can you summarize this: {{document}}\n\n\u003C!-- RIGHT: matches the model's documented chat template exactly.\n     In practice, this is handled by the serving framework (transformers, vLLM,\n     llama.cpp) automatically. The actionable takeaway: confirm your tooling is\n     applying the CORRECT template for the specific model checkpoint. -->\n\u003Cs>[INST] Summarize the following document.\n\n{{document}} [\u002FINST]\n",[30,587,588,593,598,602,607,612,617,622,634,638],{"__ignoreMap":28},[33,589,590],{"class":35,"line":36},[33,591,592],{"class":39},"\u003C!-- WRONG: informal, ignores the model's expected chat template -->\n",[33,594,595],{"class":35,"line":43},[33,596,597],{"class":283},"Hey, can you summarize this: {{document}}\n",[33,599,600],{"class":35,"line":49},[33,601,59],{"emptyLinePlaceholder":58},[33,603,604],{"class":35,"line":55},[33,605,606],{"class":39},"\u003C!-- RIGHT: matches the model's documented chat template exactly.\n",[33,608,609],{"class":35,"line":62},[33,610,611],{"class":39},"     In practice, this is handled by the serving framework (transformers, vLLM,\n",[33,613,614],{"class":35,"line":68},[33,615,616],{"class":39},"     llama.cpp) automatically. The actionable takeaway: confirm your tooling is\n",[33,618,619],{"class":35,"line":74},[33,620,621],{"class":39},"     applying the CORRECT template for the specific model checkpoint. -->\n",[33,623,624,627,631],{"class":35,"line":80},[33,625,626],{"class":283},"\u003Cs>[",[33,628,630],{"class":629},"sSQSC","INST",[33,632,633],{"class":283},"] Summarize the following document.\n",[33,635,636],{"class":35,"line":86},[33,637,59],{"emptyLinePlaceholder":58},[33,639,640,643,646],{"class":35,"line":91},[33,641,642],{"class":283},"{{document}} [",[33,644,645],{"class":629},"\u002FINST",[33,647,648],{"class":283},"]\n",[19,650,652],{"filename":651,"language":22},"open_weight_tips.py",[24,653,655],{"className":26,"code":654,"language":22,"meta":28,"style":28},"# Open-weight models (Llama, Mistral, etc.) are OFTEN MORE SENSITIVE to exact\n# prompt template formatting than large hosted-API models. Many were instruction-tuned\n# against a VERY SPECIFIC chat template (particular special tokens or role markers).\n# Deviating from that exact template — even in ways a hosted model tolerates — can\n# measurably degrade output quality.\n\n# In practice, the templating is handled by the serving framework:\n#   - Hugging Face transformers: applies the correct chat template automatically\n#   - vLLM: same\n#   - llama.cpp: same\n# The actionable takeaway: CONFIRM your tooling applies the correct template.\n\n# Smaller models also generally benefit MORE from explicit few-shot examples (Chapter 3).\n# The zero-shot instruction-following gap between a frontier model and a smaller\n# open-weight one is often exactly the gap that 1-2 good examples closes.\n",[30,656,657,662,667,672,677,682,686,691,696,701,706,711,715,720,725],{"__ignoreMap":28},[33,658,659],{"class":35,"line":36},[33,660,661],{"class":39},"# Open-weight models (Llama, Mistral, etc.) are OFTEN MORE SENSITIVE to exact\n",[33,663,664],{"class":35,"line":43},[33,665,666],{"class":39},"# prompt template formatting than large hosted-API models. Many were instruction-tuned\n",[33,668,669],{"class":35,"line":49},[33,670,671],{"class":39},"# against a VERY SPECIFIC chat template (particular special tokens or role markers).\n",[33,673,674],{"class":35,"line":55},[33,675,676],{"class":39},"# Deviating from that exact template — even in ways a hosted model tolerates — can\n",[33,678,679],{"class":35,"line":62},[33,680,681],{"class":39},"# measurably degrade output quality.\n",[33,683,684],{"class":35,"line":68},[33,685,59],{"emptyLinePlaceholder":58},[33,687,688],{"class":35,"line":74},[33,689,690],{"class":39},"# In practice, the templating is handled by the serving framework:\n",[33,692,693],{"class":35,"line":80},[33,694,695],{"class":39},"#   - Hugging Face transformers: applies the correct chat template automatically\n",[33,697,698],{"class":35,"line":86},[33,699,700],{"class":39},"#   - vLLM: same\n",[33,702,703],{"class":35,"line":91},[33,704,705],{"class":39},"#   - llama.cpp: same\n",[33,707,708],{"class":35,"line":97},[33,709,710],{"class":39},"# The actionable takeaway: CONFIRM your tooling applies the correct template.\n",[33,712,713],{"class":35,"line":103},[33,714,59],{"emptyLinePlaceholder":58},[33,716,717],{"class":35,"line":109},[33,718,719],{"class":39},"# Smaller models also generally benefit MORE from explicit few-shot examples (Chapter 3).\n",[33,721,722],{"class":35,"line":115},[33,723,724],{"class":39},"# The zero-shot instruction-following gap between a frontier model and a smaller\n",[33,726,727],{"class":35,"line":121},[33,728,729],{"class":39},"# open-weight one is often exactly the gap that 1-2 good examples closes.\n",[14,731,733],{"id":732},"graceful-degradation-across-models","Graceful Degradation Across Models",[19,735,737],{"filename":736,"language":22},"graceful_degradation.py",[24,738,740],{"className":26,"code":739,"language":22,"meta":28,"style":28},"# Full portability isn't realistic. The practical goal: degrade GRACEFULLY,\n# not catastrophically, when run against a different model than tuned for.\n\nGRACEFUL_DEGRADATION_PRINCIPLES = {\n    \"explicit_constraints\": \"State length, tone, format plainly — don't rely on a model's default tendency\",\n    \"native_structured_output\": \"Prefer API-enforced schemas over prompted formatting when >1 model family\",\n    \"separable_cot\": \"Keep 'think step by step' as a clearly isolated, removable block — trivial to strip for reasoning-optimized models\",\n    \"eval_set_before_migration\": \"Build the eval set (Chapter 19) BEFORE you need it — the most reliable way to know if a prompt survived a swap\",\n}\n\n# ANTI-PATTERN: forking the entire prompt per model\n# PRODUCTION: maintain one shared \"core task\" block + small per-model wrapper sections\n# for formatting\u002Frole conventions. Keeps the actual task logic in one place to update.\n\nSHARED_CORE = \"\"\"\nClassify the support ticket into BILLING, BUG_REPORT, FEATURE_REQUEST,\nACCOUNT_ACCESS, or OTHER. Reply with only the category label.\n\"\"\"\n\n# Per-model wrapper (tiny — only what differs):\nCLAUDE_WRAPPER = {\"system\": f\"You are a ticket triage assistant.\\n\\n{SHARED_CORE}\"}\nGPT_WRAPPER = {\"system\": SHARED_CORE}  # GPT may not need the persona wrapper\nOPEN_WEIGHT_WRAPPER = {\n    \"system\": f\"You are a ticket triage assistant. {SHARED_CORE}\\n\\nExamples:\\nTicket: 'charged twice' → BILLING\\nTicket: 'app crashes' → BUG_REPORT\",\n    # Open-weight benefits more from few-shot examples (Chapter 3)\n}\n",[30,741,742,747,752,756,765,777,789,801,813,817,821,826,831,836,840,850,855,860,865,869,874,903,924,934,966,972],{"__ignoreMap":28},[33,743,744],{"class":35,"line":36},[33,745,746],{"class":39},"# Full portability isn't realistic. The practical goal: degrade GRACEFULLY,\n",[33,748,749],{"class":35,"line":43},[33,750,751],{"class":39},"# not catastrophically, when run against a different model than tuned for.\n",[33,753,754],{"class":35,"line":49},[33,755,59],{"emptyLinePlaceholder":58},[33,757,758,761,763],{"class":35,"line":55},[33,759,760],{"class":400},"GRACEFUL_DEGRADATION_PRINCIPLES",[33,762,404],{"class":368},[33,764,407],{"class":283},[33,766,767,770,772,775],{"class":35,"line":62},[33,768,769],{"class":412},"    \"explicit_constraints\"",[33,771,416],{"class":283},[33,773,774],{"class":412},"\"State length, tone, format plainly — don't rely on a model's default tendency\"",[33,776,422],{"class":283},[33,778,779,782,784,787],{"class":35,"line":68},[33,780,781],{"class":412},"    \"native_structured_output\"",[33,783,416],{"class":283},[33,785,786],{"class":412},"\"Prefer API-enforced schemas over prompted formatting when >1 model family\"",[33,788,422],{"class":283},[33,790,791,794,796,799],{"class":35,"line":74},[33,792,793],{"class":412},"    \"separable_cot\"",[33,795,416],{"class":283},[33,797,798],{"class":412},"\"Keep 'think step by step' as a clearly isolated, removable block — trivial to strip for reasoning-optimized models\"",[33,800,422],{"class":283},[33,802,803,806,808,811],{"class":35,"line":80},[33,804,805],{"class":412},"    \"eval_set_before_migration\"",[33,807,416],{"class":283},[33,809,810],{"class":412},"\"Build the eval set (Chapter 19) BEFORE you need it — the most reliable way to know if a prompt survived a swap\"",[33,812,422],{"class":283},[33,814,815],{"class":35,"line":86},[33,816,540],{"class":283},[33,818,819],{"class":35,"line":91},[33,820,59],{"emptyLinePlaceholder":58},[33,822,823],{"class":35,"line":97},[33,824,825],{"class":39},"# ANTI-PATTERN: forking the entire prompt per model\n",[33,827,828],{"class":35,"line":103},[33,829,830],{"class":39},"# PRODUCTION: maintain one shared \"core task\" block + small per-model wrapper sections\n",[33,832,833],{"class":35,"line":109},[33,834,835],{"class":39},"# for formatting\u002Frole conventions. Keeps the actual task logic in one place to update.\n",[33,837,838],{"class":35,"line":115},[33,839,59],{"emptyLinePlaceholder":58},[33,841,842,845,847],{"class":35,"line":121},[33,843,844],{"class":400},"SHARED_CORE",[33,846,404],{"class":368},[33,848,849],{"class":412}," \"\"\"\n",[33,851,852],{"class":35,"line":126},[33,853,854],{"class":412},"Classify the support ticket into BILLING, BUG_REPORT, FEATURE_REQUEST,\n",[33,856,857],{"class":35,"line":132},[33,858,859],{"class":412},"ACCOUNT_ACCESS, or OTHER. Reply with only the category label.\n",[33,861,862],{"class":35,"line":138},[33,863,864],{"class":412},"\"\"\"\n",[33,866,867],{"class":35,"line":144},[33,868,59],{"emptyLinePlaceholder":58},[33,870,871],{"class":35,"line":150},[33,872,873],{"class":39},"# Per-model wrapper (tiny — only what differs):\n",[33,875,876,879,881,884,887,889,892,895,898,901],{"class":35,"line":156},[33,877,878],{"class":400},"CLAUDE_WRAPPER",[33,880,404],{"class":368},[33,882,883],{"class":283}," {",[33,885,886],{"class":412},"\"system\"",[33,888,416],{"class":283},[33,890,891],{"class":368},"f",[33,893,894],{"class":412},"\"You are a ticket triage assistant.",[33,896,897],{"class":400},"\\n\\n{SHARED_CORE}",[33,899,900],{"class":412},"\"",[33,902,540],{"class":283},[33,904,905,908,910,912,914,916,918,921],{"class":35,"line":572},[33,906,907],{"class":400},"GPT_WRAPPER",[33,909,404],{"class":368},[33,911,883],{"class":283},[33,913,886],{"class":412},[33,915,416],{"class":283},[33,917,844],{"class":400},[33,919,920],{"class":283},"}  ",[33,922,923],{"class":39},"# GPT may not need the persona wrapper\n",[33,925,927,930,932],{"class":35,"line":926},23,[33,928,929],{"class":400},"OPEN_WEIGHT_WRAPPER",[33,931,404],{"class":368},[33,933,407],{"class":283},[33,935,937,940,942,944,947,950,953,956,959,961,964],{"class":35,"line":936},24,[33,938,939],{"class":412},"    \"system\"",[33,941,416],{"class":283},[33,943,891],{"class":368},[33,945,946],{"class":412},"\"You are a ticket triage assistant. ",[33,948,949],{"class":400},"{SHARED_CORE}\\n\\n",[33,951,952],{"class":412},"Examples:",[33,954,955],{"class":400},"\\n",[33,957,958],{"class":412},"Ticket: 'charged twice' → BILLING",[33,960,955],{"class":400},[33,962,963],{"class":412},"Ticket: 'app crashes' → BUG_REPORT\"",[33,965,422],{"class":283},[33,967,969],{"class":35,"line":968},25,[33,970,971],{"class":39},"    # Open-weight benefits more from few-shot examples (Chapter 3)\n",[33,973,975],{"class":35,"line":974},26,[33,976,540],{"class":283},[14,978,980],{"id":979},"tips-tricks","💡 Tips & Tricks",[19,982,984],{"filename":983,"language":22},"tips.py",[24,985,987],{"className":26,"code":986,"language":22,"meta":28,"style":28},"# [Portability] When a prompt runs against multiple model families (fallback,\n# A\u002FB test, multi-model router), maintain one shared \"core task\" block + small\n# per-model wrapper sections for formatting\u002Frole conventions. Don't fork the\n# entire prompt per model.\n\n# [Debug] If a prompt that worked well suddenly degrades after a routine model\n# version upgrade (even within the same family), suspect a shifted default behavior\n# (verbosity, refusal threshold, formatting) before suspecting your own prompt.\n# Providers change defaults between versions without it being a \"breaking change.\"\n\n# [Idiom] For reasoning-optimized models, try the simplest possible direct prompt\n# FIRST and only add explicit reasoning scaffolding if you can show empirically\n# it improves eval-set results. \"More structure is always at least neutral\" does\n# NOT hold for this model category.\n\n# [Performance] When working with a smaller\u002Fopen-weight model, invest evaluation\n# effort in confirming the chat template is applied correctly BEFORE concluding\n# the model itself is the limiting factor. Many \"this small model is just bad at\n# instruction-following\" reports trace to a template mismatch, not a capability gap.\n\n# [Idiom] Keep a small \"model assumptions\" note alongside any production prompt:\n# which model\u002Fversion it was tuned against, what native features it relies on.\n# This turns a future model migration into a checklist instead of archaeology.\n",[30,988,989,994,999,1004,1009,1013,1018,1023,1028,1033,1037,1042,1047,1052,1057,1061,1066,1071,1076,1081,1085,1090,1095],{"__ignoreMap":28},[33,990,991],{"class":35,"line":36},[33,992,993],{"class":39},"# [Portability] When a prompt runs against multiple model families (fallback,\n",[33,995,996],{"class":35,"line":43},[33,997,998],{"class":39},"# A\u002FB test, multi-model router), maintain one shared \"core task\" block + small\n",[33,1000,1001],{"class":35,"line":49},[33,1002,1003],{"class":39},"# per-model wrapper sections for formatting\u002Frole conventions. Don't fork the\n",[33,1005,1006],{"class":35,"line":55},[33,1007,1008],{"class":39},"# entire prompt per model.\n",[33,1010,1011],{"class":35,"line":62},[33,1012,59],{"emptyLinePlaceholder":58},[33,1014,1015],{"class":35,"line":68},[33,1016,1017],{"class":39},"# [Debug] If a prompt that worked well suddenly degrades after a routine model\n",[33,1019,1020],{"class":35,"line":74},[33,1021,1022],{"class":39},"# version upgrade (even within the same family), suspect a shifted default behavior\n",[33,1024,1025],{"class":35,"line":80},[33,1026,1027],{"class":39},"# (verbosity, refusal threshold, formatting) before suspecting your own prompt.\n",[33,1029,1030],{"class":35,"line":86},[33,1031,1032],{"class":39},"# Providers change defaults between versions without it being a \"breaking change.\"\n",[33,1034,1035],{"class":35,"line":91},[33,1036,59],{"emptyLinePlaceholder":58},[33,1038,1039],{"class":35,"line":97},[33,1040,1041],{"class":39},"# [Idiom] For reasoning-optimized models, try the simplest possible direct prompt\n",[33,1043,1044],{"class":35,"line":103},[33,1045,1046],{"class":39},"# FIRST and only add explicit reasoning scaffolding if you can show empirically\n",[33,1048,1049],{"class":35,"line":109},[33,1050,1051],{"class":39},"# it improves eval-set results. \"More structure is always at least neutral\" does\n",[33,1053,1054],{"class":35,"line":115},[33,1055,1056],{"class":39},"# NOT hold for this model category.\n",[33,1058,1059],{"class":35,"line":121},[33,1060,59],{"emptyLinePlaceholder":58},[33,1062,1063],{"class":35,"line":126},[33,1064,1065],{"class":39},"# [Performance] When working with a smaller\u002Fopen-weight model, invest evaluation\n",[33,1067,1068],{"class":35,"line":132},[33,1069,1070],{"class":39},"# effort in confirming the chat template is applied correctly BEFORE concluding\n",[33,1072,1073],{"class":35,"line":138},[33,1074,1075],{"class":39},"# the model itself is the limiting factor. Many \"this small model is just bad at\n",[33,1077,1078],{"class":35,"line":144},[33,1079,1080],{"class":39},"# instruction-following\" reports trace to a template mismatch, not a capability gap.\n",[33,1082,1083],{"class":35,"line":150},[33,1084,59],{"emptyLinePlaceholder":58},[33,1086,1087],{"class":35,"line":156},[33,1088,1089],{"class":39},"# [Idiom] Keep a small \"model assumptions\" note alongside any production prompt:\n",[33,1091,1092],{"class":35,"line":572},[33,1093,1094],{"class":39},"# which model\u002Fversion it was tuned against, what native features it relies on.\n",[33,1096,1097],{"class":35,"line":926},[33,1098,1099],{"class":39},"# This turns a future model migration into a checklist instead of archaeology.\n",[14,1101,1103],{"id":1102},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[19,1105,1107],{"filename":1106,"language":22},"edge_cases.py",[24,1108,1110],{"className":26,"code":1109,"language":22,"meta":28,"style":28},"# [Safety] A prompt relying on implicit system-prompt priority can fail silently on\n# an API using a different instruction hierarchy. A security-relevant constraint\n# should NEVER depend solely on message-role placement across an unverified provider.\n\n# [Gotcha] Refusal-threshold differences can look like a regression when they're a\n# policy difference. A legitimate request one model handles and another declines is\n# not necessarily a prompting bug — sometimes it reflects a different safety threshold.\n# The right response is adjusting the request's framing, not engineering around a guardrail.\n\n# [Gotcha] JSON-mode guarantees differ across providers: schema-validated vs merely\n# JSON-syntax-valid vs best-effort. Treating them as interchangeable without checking\n# is a common source of \"schema validation started failing after we switched providers.\"\n\n# [Gotcha] A model swap can silently change token-counting behavior. Different\n# tokenizers segment the same text differently — a prompt that fit under one model's\n# context limit is NOT guaranteed to fit under a similar-sized limit on another.\n\n# [Gotcha] \"It works when I test it manually\" is NOT evidence of portability. Manual\n# spot-checking during a migration reliably misses the specific edge cases where\n# behavior actually diverges. This is the gap the eval-set approach (Chapter 19) closes.\n",[30,1111,1112,1117,1122,1127,1131,1136,1141,1146,1151,1155,1160,1165,1170,1174,1179,1184,1189,1193,1198,1203],{"__ignoreMap":28},[33,1113,1114],{"class":35,"line":36},[33,1115,1116],{"class":39},"# [Safety] A prompt relying on implicit system-prompt priority can fail silently on\n",[33,1118,1119],{"class":35,"line":43},[33,1120,1121],{"class":39},"# an API using a different instruction hierarchy. A security-relevant constraint\n",[33,1123,1124],{"class":35,"line":49},[33,1125,1126],{"class":39},"# should NEVER depend solely on message-role placement across an unverified provider.\n",[33,1128,1129],{"class":35,"line":55},[33,1130,59],{"emptyLinePlaceholder":58},[33,1132,1133],{"class":35,"line":62},[33,1134,1135],{"class":39},"# [Gotcha] Refusal-threshold differences can look like a regression when they're a\n",[33,1137,1138],{"class":35,"line":68},[33,1139,1140],{"class":39},"# policy difference. A legitimate request one model handles and another declines is\n",[33,1142,1143],{"class":35,"line":74},[33,1144,1145],{"class":39},"# not necessarily a prompting bug — sometimes it reflects a different safety threshold.\n",[33,1147,1148],{"class":35,"line":80},[33,1149,1150],{"class":39},"# The right response is adjusting the request's framing, not engineering around a guardrail.\n",[33,1152,1153],{"class":35,"line":86},[33,1154,59],{"emptyLinePlaceholder":58},[33,1156,1157],{"class":35,"line":91},[33,1158,1159],{"class":39},"# [Gotcha] JSON-mode guarantees differ across providers: schema-validated vs merely\n",[33,1161,1162],{"class":35,"line":97},[33,1163,1164],{"class":39},"# JSON-syntax-valid vs best-effort. Treating them as interchangeable without checking\n",[33,1166,1167],{"class":35,"line":103},[33,1168,1169],{"class":39},"# is a common source of \"schema validation started failing after we switched providers.\"\n",[33,1171,1172],{"class":35,"line":109},[33,1173,59],{"emptyLinePlaceholder":58},[33,1175,1176],{"class":35,"line":115},[33,1177,1178],{"class":39},"# [Gotcha] A model swap can silently change token-counting behavior. Different\n",[33,1180,1181],{"class":35,"line":121},[33,1182,1183],{"class":39},"# tokenizers segment the same text differently — a prompt that fit under one model's\n",[33,1185,1186],{"class":35,"line":126},[33,1187,1188],{"class":39},"# context limit is NOT guaranteed to fit under a similar-sized limit on another.\n",[33,1190,1191],{"class":35,"line":132},[33,1192,59],{"emptyLinePlaceholder":58},[33,1194,1195],{"class":35,"line":138},[33,1196,1197],{"class":39},"# [Gotcha] \"It works when I test it manually\" is NOT evidence of portability. Manual\n",[33,1199,1200],{"class":35,"line":144},[33,1201,1202],{"class":39},"# spot-checking during a migration reliably misses the specific edge cases where\n",[33,1204,1205],{"class":35,"line":150},[33,1206,1207],{"class":39},"# behavior actually diverges. This is the gap the eval-set approach (Chapter 19) closes.\n",[14,1209,1211],{"id":1210},"spot-the-bug","🧠 Spot the Bug",[1213,1214,1215],"p",{},"A support-ticket triage prompt tuned on one model family is ported unchanged to a second provider: \"You are a ticket triage assistant. Categorize the ticket and return JSON: {\"category\": \"...\", \"priority\": \"...\"}. Think through your reasoning step by step before giving the final JSON.\" After the switch, responses increasingly fail to parse as JSON — the model includes reasoning text before the JSON, sometimes with the object embedded mid-paragraph. What changed?",[1217,1218,1219,1223,1226,1248,1251],"details",{},[1220,1221,1222],"summary",{},"Answer",[1213,1224,1225],{},"Two portability assumptions failed at once:",[1227,1228,1229,1237],"ol",{},[1230,1231,1232,1236],"li",{},[1233,1234,1235],"strong",{},"\"Think step by step\" + a request for clean isolated JSON"," works on some models but is exactly the interaction the new model family may handle differently — its default behavior interleaves reasoning and answer more freely, so the reasoning text sits next to (or wrapped around) the JSON instead of cleanly preceding it.",[1230,1238,1239,1247],{},[1233,1240,1241,1242,1246],{},"The original prompt relied on ",[1243,1244,1245],"em",{},"prompted"," JSON formatting"," rather than any provider-native structured-output guarantee. That reliability gap was already a portability risk — switching providers is exactly the event that exposes it.",[1213,1249,1250],{},"The robust fix: use the new provider's native structured-output\u002FJSON-schema feature so the final answer's shape is enforced by the API, and if step-by-step reasoning is still wanted, request it in a clearly separate, explicitly delimited section (or via the provider's dedicated reasoning mechanism) rather than trusting \"think step by step, then give JSON\" parses the same way across families.",[1213,1252,1253],{},"The lesson: an identical prompt string is not an identical instruction across model families — reasoning-elicitation phrasing and prompted-only formatting are the two things most likely to break silently on a model swap.",[14,1255,1257],{"id":1256},"key-takeaways","Key Takeaways",[19,1259,1261],{"filename":1260,"language":22},"key_takeaways.py",[24,1262,1264],{"className":26,"code":1263,"language":22,"meta":28,"style":28},"\"\"\"\nWorking with GPT & other models — portability and graceful degradation.\n\"\"\"\n\n# 1. Prompt portability is PARTIAL, not automatic. Model-agnostic fundamentals\n#    (clarity, structure, decomposition) transfer well; formatting conventions,\n#    system-message priority, and reasoning phrasing often do NOT.\n\n# 2. OpenAI: evolving instruction hierarchy (beyond flat system\u002Fuser), reasoning-\n#    optimized models that often perform better with SIMPLER prompts, not heavier\n#    CoT scaffolding. Check model-specific guidance.\n\n# 3. Prefer provider-native structured-output mechanisms over prompted formatting\n#    whenever a prompt might run against >1 model family. The enforced-shape\n#    guarantee transfers far better than prompted formatting reliability.\n\n# 4. Open-weight\u002Fsmaller models: more sensitive to exact chat-template formatting,\n#    benefit MORE from few-shot examples. Confirm your serving stack applies the\n#    correct template before concluding a model lacks capability.\n\n# 5. The only reliable way to know if a prompt survived a model migration is\n#    eval-set regression testing (Chapter 19) built BEFORE the migration —\n#    not manual spot-checking during or after it.\n",[30,1265,1266,1270,1275,1279,1283,1288,1293,1298,1302,1307,1312,1317,1321,1326,1331,1336,1340,1345,1350,1355,1359,1364,1369],{"__ignoreMap":28},[33,1267,1268],{"class":35,"line":36},[33,1269,864],{"class":412},[33,1271,1272],{"class":35,"line":43},[33,1273,1274],{"class":412},"Working with GPT & other models — portability and graceful degradation.\n",[33,1276,1277],{"class":35,"line":49},[33,1278,864],{"class":412},[33,1280,1281],{"class":35,"line":55},[33,1282,59],{"emptyLinePlaceholder":58},[33,1284,1285],{"class":35,"line":62},[33,1286,1287],{"class":39},"# 1. Prompt portability is PARTIAL, not automatic. Model-agnostic fundamentals\n",[33,1289,1290],{"class":35,"line":68},[33,1291,1292],{"class":39},"#    (clarity, structure, decomposition) transfer well; formatting conventions,\n",[33,1294,1295],{"class":35,"line":74},[33,1296,1297],{"class":39},"#    system-message priority, and reasoning phrasing often do NOT.\n",[33,1299,1300],{"class":35,"line":80},[33,1301,59],{"emptyLinePlaceholder":58},[33,1303,1304],{"class":35,"line":86},[33,1305,1306],{"class":39},"# 2. OpenAI: evolving instruction hierarchy (beyond flat system\u002Fuser), reasoning-\n",[33,1308,1309],{"class":35,"line":91},[33,1310,1311],{"class":39},"#    optimized models that often perform better with SIMPLER prompts, not heavier\n",[33,1313,1314],{"class":35,"line":97},[33,1315,1316],{"class":39},"#    CoT scaffolding. Check model-specific guidance.\n",[33,1318,1319],{"class":35,"line":103},[33,1320,59],{"emptyLinePlaceholder":58},[33,1322,1323],{"class":35,"line":109},[33,1324,1325],{"class":39},"# 3. Prefer provider-native structured-output mechanisms over prompted formatting\n",[33,1327,1328],{"class":35,"line":115},[33,1329,1330],{"class":39},"#    whenever a prompt might run against >1 model family. The enforced-shape\n",[33,1332,1333],{"class":35,"line":121},[33,1334,1335],{"class":39},"#    guarantee transfers far better than prompted formatting reliability.\n",[33,1337,1338],{"class":35,"line":126},[33,1339,59],{"emptyLinePlaceholder":58},[33,1341,1342],{"class":35,"line":132},[33,1343,1344],{"class":39},"# 4. Open-weight\u002Fsmaller models: more sensitive to exact chat-template formatting,\n",[33,1346,1347],{"class":35,"line":138},[33,1348,1349],{"class":39},"#    benefit MORE from few-shot examples. Confirm your serving stack applies the\n",[33,1351,1352],{"class":35,"line":144},[33,1353,1354],{"class":39},"#    correct template before concluding a model lacks capability.\n",[33,1356,1357],{"class":35,"line":150},[33,1358,59],{"emptyLinePlaceholder":58},[33,1360,1361],{"class":35,"line":156},[33,1362,1363],{"class":39},"# 5. The only reliable way to know if a prompt survived a model migration is\n",[33,1365,1366],{"class":35,"line":572},[33,1367,1368],{"class":39},"#    eval-set regression testing (Chapter 19) built BEFORE the migration —\n",[33,1370,1371],{"class":35,"line":926},[33,1372,1373],{"class":39},"#    not manual spot-checking during or after it.\n",[1375,1376,1377],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}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 .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .sSQSC, html code.shiki .sSQSC{--shiki-default:#032F62;--shiki-default-text-decoration:underline;--shiki-github-dark:#DBEDFF;--shiki-github-dark-text-decoration:underline}",{"title":28,"searchDepth":43,"depth":43,"links":1379},[1380,1381,1382,1383,1384,1385,1386,1387,1388],{"id":16,"depth":43,"text":17},{"id":162,"depth":43,"text":163},{"id":297,"depth":43,"text":298},{"id":578,"depth":43,"text":579},{"id":732,"depth":43,"text":733},{"id":979,"depth":43,"text":980},{"id":1102,"depth":43,"text":1103},{"id":1210,"depth":43,"text":1211},{"id":1256,"depth":43,"text":1257},"Prompt portability across model families — OpenAI conventions, reasoning-optimized models, open-weight chat templates, graceful degradation patterns, and migration testing. Code-first reference for mid-to-senior engineers.","md",{},"\u002Fprompt-engineering\u002F16-working-with-gpt-and-other-models",{"title":5,"description":1389},"prompt-engineering\u002F16-working-with-gpt-and-other-models","T0JlTN-p9CylCVsciE2J4euv14d5YlR4Ih0plcT9tYA",1789924651084]