{"id":3407,"date":"2025-09-02T12:23:00","date_gmt":"2025-09-02T18:23:00","guid":{"rendered":"https:\/\/yyc.ninja\/index.php\/2025\/09\/02\/building-local-ai-that-actually-works-the-architecture-of-reliability\/"},"modified":"2026-10-14T23:47:15","modified_gmt":"2026-10-15T05:47:15","slug":"building-local-ai-that-actually-works-the-architecture-of-reliability","status":"publish","type":"post","link":"https:\/\/yyc.ninja\/index.php\/2025\/09\/02\/building-local-ai-that-actually-works-the-architecture-of-reliability\/","title":{"rendered":"Building Local AI That Actually Works: The Architecture of Reliability"},"content":{"rendered":"<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"630\" src=\"https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover.png\" alt=\"Building Local AI That Actually Works: The Architecture of Reliability\" class=\"wp-image-3406\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" srcset=\"https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover.png 1200w, https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover-300x158.png 300w, https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover-1024x538.png 1024w, https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover-768x403.png 768w, https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover-100x53.png 100w\" \/><\/figure>\n<p class=\"wp-block-paragraph\"><strong>A blueprint for executive and engineering teams to move from local AI prototypes to production-grade, scalable, and trustworthy systems.<\/strong><\/p>\n<hr class=\"wp-block-separator\" \/>\n<h3 class=\"wp-block-heading\">The Illusion of Competence<\/h3>\n<p class=\"wp-block-paragraph\">The pitch for local AI is irresistible: absolute privacy, zero API costs, and sub-second latency. You download a 30-billion-parameter model, fire up a sleek UI, and ask it to write a Python script or summarize a legal contract. The result is fluent, confident, and grammatically perfect.<\/p>\n<p class=\"wp-block-paragraph\">Then you use it in production.<\/p>\n<p class=\"wp-block-paragraph\">The model forgets what it was doing halfway through a task. It invents code APIs that don&#8217;t exist. It confidently cites case law that never happened. It botches tool calls, crashes your memory, and forces you right back to paying OpenAI or Anthropic.<\/p>\n<p class=\"wp-block-paragraph\"><strong>Here is the hard truth:<\/strong> The model is not the problem. The scaffolding is. <\/p>\n<p class=\"wp-block-paragraph\">Local AI fails because teams treat it like a software API rather than a system. Running a frontier model locally is an exercise in extreme systems engineering. You are fighting unified memory constraints, KV cache bombs, context drift, and the model&#8217;s innate desire to hallucinate when it doesn&#8217;t know something.<\/p>\n<p class=\"wp-block-paragraph\">This post synthesizes the best practices for building local AI\u2014spanning coding agents, general enterprise tasks, and high-stakes legal tech\u2014into a unified architecture. We will cover the hardware, the inference stack, the guardrails, and the scaling strategies required to make local AI actually work.<\/p>\n<hr class=\"wp-block-separator\" \/>\n<h3 class=\"wp-block-heading\">Phase 1: The Hardware Reality \u2014 Memory is Everything<\/h3>\n<p class=\"wp-block-paragraph\">The biggest mistake teams make is treating Unified Memory (Apple Silicon) or VRAM (AMD\/NVIDIA) as an infinite pool. It is not. It is a zero-sum battlefield where model weights, context caches, and application overhead fight to the death.<\/p>\n<h4 class=\"wp-block-heading\">The Problem: The GPU War<\/h4>\n<p class=\"wp-block-paragraph\">If you run a 14B model (8GB weights) and give it a 64,000-token context window, the KV cache (the model&#8217;s &#8220;working memory&#8221; for that conversation) can easily consume another 8GB. Now add your OS, your browser, and a voice transcription engine. The system runs out of memory, forcefully evicts the model, and your next chat takes 45 seconds to cold-start.<\/p>\n<h4 class=\"wp-block-heading\">The Best Practice: Honest Budgeting<\/h4>\n<p class=\"wp-block-paragraph\">You must set hard memory ceilings.<br \/>\n*   <strong>Apple Silicon (32GB):<\/strong> Cap your inference engine at 18GB. Pin your daily-driver model (e.g., a 14B Coder at 7.7GB) and a tiny utility model (1.7B at 1GB). Leave the remaining 10GB for KV cache, the OS, and transient loads.<br \/>\n*   <strong>The Context Window Trade-off:<\/strong> A 131,000-token context window sounds great, but pre-allocating memory for it will eat 15GB of VRAM before you even type a word. <strong>Cap context windows to 32K or 64K.<\/strong> Use RAG (Retrieval-Augmented Generation) to fetch relevant text, rather than stuffing the whole company wiki into the prompt.<\/p>\n<p class=\"wp-block-paragraph\"><strong>The Decision:<\/strong> Limit <code>max_context_window<\/code> per model role. A &#8220;Coder&#8221; gets 32K. An &#8220;Architect&#8221; gets 64K. This simple config change drops prefill time from 15 seconds to 2 seconds and prevents OOM crashes.<\/p>\n<hr class=\"wp-block-separator\" \/>\n<h3 class=\"wp-block-heading\">Phase 2: The Multi-Tasking Dilemma \u2014 One Engine, Many Hats<\/h3>\n<p class=\"wp-block-paragraph\">Teams quickly realize that coding tasks require rigid, deterministic AI, while brainstorming tasks require creative, stochastic AI. The instinct is to load two models. On 32GB or 48GB hardware, this is a fast path to OOM.<\/p>\n<h4 class=\"wp-block-heading\">The Best Practice: The &#8220;Personality Dial&#8221; via LiteLLM<\/h4>\n<p class=\"wp-block-paragraph\">You don&#8217;t need two models; you need dynamic sampling profiles. <\/p>\n<p class=\"wp-block-paragraph\">Install <strong>LiteLLM<\/strong> as a proxy in front of your inference engine (vLLM or Ollama). LiteLLM lets you define &#8220;Virtual Models&#8221; (roles) that route to the exact same physical model but inject different parameters.<\/p>\n<ul class=\"wp-block-list\">\n<li><strong><code>role\/coder<\/code>:<\/strong> Routes to <code>Model-14B<\/code>. Forces <code>temperature: 0.1<\/code>, <code>repetition_penalty: 1.15<\/code>. Strict, deterministic.<\/li>\n<li><strong><code>role\/creative<\/code>:<\/strong> Routes to <code>Model-14B<\/code>. Forces <code>temperature: 0.85<\/code>, <code>presence_penalty: 0.3<\/code>. Fluent, diverse.<\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\"><strong>The Decision:<\/strong> One pinned model, multiple personalities. This costs zero extra VRAM and allows your local box to serve both developers and marketing teams simultaneously.<\/p>\n<hr class=\"wp-block-separator\" \/>\n<h3 class=\"wp-block-heading\">Phase 3: Defeating Hallucinations \u2014 Mechanical Guardrails<\/h3>\n<p class=\"wp-block-paragraph\">LLMs are confabulation engines. When they don&#8217;t know a fact, they guess. In coding, they invent GitHub URLs and CLI commands. In law, they invent case citations. Text-only instructions (&#8220;Do not hallucinate&#8221;) fail because the model cannot distinguish between what it knows and what it guesses.<\/p>\n<h4 class=\"wp-block-heading\">The Coding Fix: Grammar Constraints<\/h4>\n<p class=\"wp-block-paragraph\">Instead of asking the model nicely to output valid JSON or a valid Git diff, <strong>force it to.<\/strong> Modern inference engines support GBNF grammars (via <code>xgrammar<\/code>). You define a mathematical rule for the output format. The sampler physically cannot select a token that violates the grammar.<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>Result:<\/strong> Malformed code diffs drop from 15% to 0%. Your validation loops stop chasing syntax errors.<\/li>\n<\/ul>\n<h4 class=\"wp-block-heading\">The Legal Fix: Citation Verification<\/h4>\n<p class=\"wp-block-paragraph\">In high-stakes domains, you must assume the model will fabricate citations. Your post-processing pipeline must mechanically verify them.<br \/>\n1.  <strong>Prompt for Tags:<\/strong> Train or prompt the model to output citations as <code>[CITE: Smith v. Jones, 2024]<\/code>.<br \/>\n2.  <strong>Regex Extraction:<\/strong> Use a script to strip everything inside the <code>[CITE: ...]<\/code> tags.<br \/>\n3.  <strong>RAG Cross-Check:<\/strong> Verify every extracted citation against the actual documents provided in the RAG context.<br \/>\n4.  <strong>Enforcement:<\/strong> If the citation is not in the source documents, replace it with <code>[CITATION NOT FOUND IN SOURCE]<\/code>.<\/p>\n<p class=\"wp-block-paragraph\"><strong>The Decision:<\/strong> Never trust the model&#8217;s obedience. Trust mechanical verification. Use Linters for code, Eyecite + Python for law.<\/p>\n<hr class=\"wp-block-separator\" \/>\n<h3 class=\"wp-block-heading\">Phase 4: Context Drift \u2014 The Goldfish Memory<\/h3>\n<p class=\"wp-block-paragraph\">When an agent works on a 20-step task, it fills its context window. By step 15, it has forgotten the original goal. It starts refactoring unrelated code or contradicting its own plan. This is &#8220;Context Drift.&#8221;<\/p>\n<h4 class=\"wp-block-heading\">The Best Practice: Externalize State (The State Machine)<\/h4>\n<p class=\"wp-block-paragraph\">Do not keep task state in the context window. Write it to disk.<\/p>\n<p class=\"wp-block-paragraph\">Implement a <strong>PLAN \u2192 PATCH \u2192 TEST \u2192 REVIEW<\/strong> loop driven by a <code>STATE.json<\/code> file on the filesystem.<\/p>\n<ol class=\"wp-block-list\">\n<li><strong>PLAN (Architect Model):<\/strong> Reads the goal, writes a plan to <code>.plan\/task.md<\/code>, updates <code>STATE.json<\/code> to <code>phase: \"patch\"<\/code>.<\/li>\n<li><strong>PATCH (Coder Model):<\/strong> Reads <em>only<\/em> the plan and the specific files listed in <code>STATE.json<\/code>. Makes the edit (max 100 lines). Updates <code>STATE.json<\/code> to <code>phase: \"test\"<\/code>.<\/li>\n<li><strong>TEST (Shell\/Linter):<\/strong> Runs mechanically. Updates <code>STATE.json<\/code> with <code>pass<\/code> or <code>fail<\/code>.<\/li>\n<li><strong>REVIEW (Fresh-Context LLM):<\/strong> A separate LLM with <em>no prior context<\/em> reviews the diff and test result. Accepts or sends it back to PATCH.<\/li>\n<\/ol>\n<p class=\"wp-block-paragraph\"><strong>The Decision:<\/strong> The context window is for the current step, not the history. Files are your working memory. This allows a 4B parameter model to execute 50-step tasks reliably without losing the plot.<\/p>\n<hr class=\"wp-block-separator\" \/>\n<h3 class=\"wp-block-heading\">Phase 5: The Architecture \u2014 Brains vs. Brawn<\/h3>\n<p class=\"wp-block-paragraph\">As you scale, mixing compute and data on the same box becomes a liability. If a voice transcription engine spikes while a lawyer is doing RAG, the GPU crashes.<\/p>\n<h4 class=\"wp-block-heading\">The Best Practice: The Two-Box Split<\/h4>\n<p class=\"wp-block-paragraph\">Separate your infrastructure into <strong>Stateless Compute<\/strong> and <strong>Stateful Orchestration<\/strong>.<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>Box A (The Brain &#8211; Inference):<\/strong> Pure GPU power. Runs vLLM. Has no database, no user data, no internet access. Holds zero persistent state. If it dies, Ansible rebuilds it in 10 minutes.<\/li>\n<li><strong>Box B (The Body &#8211; Application):<\/strong> CPU\/RAM heavy. Runs the UI, Vector DB, RAG pipelines, Guardrails, and Voice processing. Connects to Box A via a private 10GbE crossover cable.<\/li>\n<\/ul>\n<p class=\"wp-block-paragraph\"><strong>The Decision:<\/strong> Box A cannot phone home and cannot leak case files. Box B handles all observability and data. You back up Box B obsessively; you don&#8217;t back up Box A at all.<\/p>\n<hr class=\"wp-block-separator\" \/>\n<h3 class=\"wp-block-heading\">Phase 6: Scaling Horizontally<\/h3>\n<p class=\"wp-block-paragraph\">When your firm grows from 5 users to 50, how do you scale?<\/p>\n<h4 class=\"wp-block-heading\">Scaling Throughput (More Users)<\/h4>\n<p class=\"wp-block-paragraph\">Do not buy a bigger GPU. Buy more Box A&#8217;s.<br \/>\nRun LiteLLM on Box B as a load balancer. It tracks the active KV cache of vLLM Node 1, Node 2, and Node 3. It routes the new prompt to the least busy GPU.<\/p>\n<h4 class=\"wp-block-heading\">Scaling Capacity (Harder Tasks)<\/h4>\n<p class=\"wp-block-paragraph\">If you need to process 100-page contracts (requiring a massive 128K context window) or run a 70B model, you need Tensor Parallelism.<br \/>\nPut two W7900 GPUs in one chassis. Run vLLM with <code>--tensor-parallel-size 2<\/code>. The model weights split across both GPUs, giving you 96GB of unified VRAM for massive contexts.<\/p>\n<p class=\"wp-block-paragraph\"><strong>The Decision:<\/strong> Scale width for concurrency; scale depth (TP) for capacity.<\/p>\n<hr class=\"wp-block-separator\" \/>\n<h3 class=\"wp-block-heading\">Phase 7: The Voice Stack \u2014 Avoiding the AMD Trap<\/h3>\n<p class=\"wp-block-paragraph\">If you are building on AMD (W7800\/W7900) for cost-efficiency, voice transcription is a landmine. The popular <code>WhisperX<\/code> relies on <code>CTranslate2<\/code>, which is heavily optimized for NVIDIA. On AMD, it is buggy, requires compiling from source, and often forces you to fall back to CPU (killing real-time performance).<\/p>\n<h4 class=\"wp-block-heading\">The Best Practice: <code>whisper.cpp<\/code> + PyAnnote<\/h4>\n<p class=\"wp-block-paragraph\">Bypass Python-centric tooling for C++ native performance.<br \/>\n1.  Use <strong><code>whisper.cpp<\/code><\/strong> compiled with <strong>HIPBLAS<\/strong> (AMD&#8217;s acceleration layer). It is ultra-stable and incredibly fast on ROCm.<br \/>\n2.  Run <strong>PyAnnote<\/strong> separately (on CPU) to map <em>who<\/em> is speaking (Diarization).<br \/>\n3.  Stitch the ultra-fast text output of <code>whisper.cpp<\/code> with the speaker timestamps of PyAnnote in your application layer.<\/p>\n<p class=\"wp-block-paragraph\"><strong>The Decision:<\/strong> Use the right tool for the hardware. <code>whisper.cpp<\/code> solves the AMD stability nightmare.<\/p>\n<hr class=\"wp-block-separator\" \/>\n<h3 class=\"wp-block-heading\">Phase 8: To Fine-Tune or Not to Fine-Tune?<\/h3>\n<p class=\"wp-block-paragraph\">With a new model dropping every month (Qwen 3.5, 3.6, 3.7), spending weeks and thousands of dollars fine-tuning a model feels like chasing the tide.<\/p>\n<h4 class=\"wp-block-heading\">The Rule: RAG for Knowledge, LoRA for Behavior<\/h4>\n<ul class=\"wp-block-list\">\n<li><strong>Never fine-tune for facts.<\/strong> If you want the AI to know your internal API or your case law, use RAG. Fine-tuned knowledge is prone to hallucination and impossible to update.<\/li>\n<li><strong>Fine-tune for format.<\/strong> If you want the AI to <em>always<\/em> output citations in <code>[CITE: ...]<\/code> brackets, or <em>always<\/em> follow the PLAN\/PATCH state machine, train a <strong>LoRA (Low-Rank Adaptation)<\/strong>.<\/li>\n<\/ul>\n<h4 class=\"wp-block-heading\">The Upgrade Strategy<\/h4>\n<p class=\"wp-block-paragraph\">A LoRA is a tiny 800MB adapter that sits on top of a 20GB base model. When Qwen 3.7 drops, you don&#8217;t retrain from scratch. You swap the base model, and run your existing training data through it to generate a new 800MB LoRA adapter in minutes.<\/p>\n<p class=\"wp-block-paragraph\"><strong>The Decision:<\/strong> Keep your base models stock for easy upgrades. Use cheap, fast LoRAs to enforce corporate behavior and output formats.<\/p>\n<hr class=\"wp-block-separator\" \/>\n<h3 class=\"wp-block-heading\">Phase 9: Observability \u2014 You Can&#8217;t Improve What You Don&#8217;t Measure<\/h3>\n<p class=\"wp-block-paragraph\">Finally, local AI is a black box. You don&#8217;t know if the model is getting better or worse over time.<\/p>\n<h4 class=\"wp-block-heading\">The Best Practice: Self-Hosted Langfuse + Golden Evals<\/h4>\n<ol class=\"wp-block-list\">\n<li><strong>Deploy Langfuse locally<\/strong> on Box B. It connects to LiteLLM, tracing every prompt, completion, and latency metric without sending data to the cloud.<\/li>\n<li><strong>Create a &#8220;Golden Dataset.&#8221;<\/strong> Curate 50 perfect coding tasks or 50 perfect legal queries with verified outputs.<\/li>\n<li><strong>Nightly Evals.<\/strong> Run a cron job that executes these tasks against your current model stack. Log the results to Langfuse.<\/li>\n<li><strong>Regression Alerts.<\/strong> If you update a model and the citation accuracy drops from 95% to 80%, the system alerts you <em>before<\/em> the lawyers or developers complain.<\/li>\n<\/ol>\n<p class=\"wp-block-paragraph\"><strong>The Decision:<\/strong> Treat your local AI like a critical microservice. Monitor its accuracy obsessively.<\/p>\n<hr class=\"wp-block-separator\" \/>\n<h3 class=\"wp-block-heading\">Conclusion: The Discipline of Local AI<\/h3>\n<p class=\"wp-block-paragraph\">Building local AI that works is not a prompt-engineering problem; it is a systems-engineering discipline. <\/p>\n<p class=\"wp-block-paragraph\">You must budget memory ruthlessly, enforce formats mechanically, externalize state to disk, separate compute from data, and measure accuracy continuously. The model is just the engine. The harness, the guardrails, and the observability layer are the steering wheel and the brakes.<\/p>\n<p class=\"wp-block-paragraph\">By implementing the architecture outlined above\u2014LiteLLM routing, state-machine loops, mechanical verification, and the compute\/data split\u2014teams can build local AI systems that are not just private and fast, but actually reliable enough for production.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The pitch for local AI is irresistible: absolute privacy, zero API costs, and sub-second latency. You download a 30-billion-parameter model, fire up a sleek UI, and ask it to write a Python script or summarize a legal contract. The result is fluent, confident, and grammatically perfect.<\/p>\n","protected":false},"author":1,"featured_media":3406,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[27,26,25,28],"class_list":["post-3407","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to","tag-ai-architecture","tag-llm","tag-local-ai","tag-production-ai"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":8}},"featured_image_urls_v2":{"full":["https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover.png",1200,630,false],"thumbnail":["https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover-150x150.png",150,150,true],"medium":["https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover-300x158.png",300,158,true],"medium_large":["https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover-768x403.png",768,403,true],"large":["https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover-1024x538.png",1024,538,true],"RoboGalleryMansoryImagesCenter":["https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover-600x630.png",600,630,true],"RoboGalleryPreload":["https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover-100x53.png",100,53,true],"1536x1536":["https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover.png",1200,630,false],"2048x2048":["https:\/\/yyc.ninja\/wp-content\/uploads\/2026\/10\/01-building-local-ai-that-actually-works-the-architecture-of-reliability-cover.png",1200,630,false]},"post_excerpt_stackable_v2":"<p>The pitch for local AI is irresistible: absolute privacy, zero API costs, and sub-second latency. You download a 30-billion-parameter model, fire up a sleek UI, and ask it to write a Python script or summarize a legal contract. The result is fluent, confident, and grammatically perfect.<\/p>\n","category_list_v2":"<a href=\"https:\/\/yyc.ninja\/index.php\/category\/how-to\/\" rel=\"category tag\">How To Ninja<\/a>","author_info_v2":{"name":"YYC Ninja","url":"https:\/\/yyc.ninja\/index.php\/author\/admin\/"},"comments_num_v2":"0 comments","_links":{"self":[{"href":"https:\/\/yyc.ninja\/index.php\/wp-json\/wp\/v2\/posts\/3407","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/yyc.ninja\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/yyc.ninja\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/yyc.ninja\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/yyc.ninja\/index.php\/wp-json\/wp\/v2\/comments?post=3407"}],"version-history":[{"count":1,"href":"https:\/\/yyc.ninja\/index.php\/wp-json\/wp\/v2\/posts\/3407\/revisions"}],"predecessor-version":[{"id":3417,"href":"https:\/\/yyc.ninja\/index.php\/wp-json\/wp\/v2\/posts\/3407\/revisions\/3417"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/yyc.ninja\/index.php\/wp-json\/wp\/v2\/media\/3406"}],"wp:attachment":[{"href":"https:\/\/yyc.ninja\/index.php\/wp-json\/wp\/v2\/media?parent=3407"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yyc.ninja\/index.php\/wp-json\/wp\/v2\/categories?post=3407"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yyc.ninja\/index.php\/wp-json\/wp\/v2\/tags?post=3407"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}