In an intriguing experiment for the Dev.to community, developer Malek Aitouaret detailed the architecture and lessons learned from Pseudo.NET, a tool that uses a local 7B parameter Large Language Model to convert free-form pseudocode into executable C# programs. The project challenges the traditional necessity of rigid syntax for teaching algorithms by allowing users to write code in natural language, which is then processed by qwen2.5-coder:7b running locally via Ollama. This approach eliminates the need for API keys and ensures data privacy, a critical feature for educational environments where student data sensitivity is paramount.

The Architectural Split: Model as Parser, Not Generator

The core design decision of Pseudo.NET is the strict separation of concerns between the LLM and the backend. The model does not generate the final source code; instead, its sole responsibility is to produce a structured JSON Abstract Syntax Tree (AST). This tree is then validated, repaired if necessary, and passed to a deterministic C# backend for compilation. By constraining the model's output to a fixed set of node kinds, the developer mitigates the risk of hallucinated code syntax while retaining the flexibility of natural language input. The pipeline flows from free-form pseudocode to a local LLM, then to a JSON AST, validation, and finally a standard build process.

Lesson 1: Small Models Struggle With Boolean Flags

A significant technical hurdle encountered was the model's tendency to omit boolean flags in the JSON output. In early iterations, fields like "tapped": true were frequently dropped, causing non-deterministic behavior in generated programs, such as keyboard inputs triggering only once instead of continuously. The solution involved replacing boolean flags with named string values, such as changing "tapped": true to "press": "held". This shift in schema design proved more robust, as the 7B model was far less likely to forget a named string value than a missing boolean. Additionally, the order of fields in the JSON prompt was optimized, placing critical style attributes immediately after the node kind to improve consistency.

Lesson 2: Concrete Examples Beat Abstract Rules

Prompt engineering for code generation revealed that abstract prose rules were inconsistently followed by the 7B model. For instance, instructions defining negation logic as a unary NOT were often ignored or misinterpreted. However, providing concrete JSON examples within the prompt significantly improved adherence to these rules. This improvement came at a cost: adding more examples increased prompt length, which ironically caused the model to forget previously established rules. To combat this regression, the developer implemented a rigorous testing net that regenerates sample programs and validates the generated C# against expected outcomes every time the prompt is modified. This automated validation is essential for maintaining stability in small model applications.

Lesson 3: Determinism Through Caching, Not Temperature

Despite setting the model temperature to 0 to ensure identical outputs for identical inputs, the developer found that relying solely on the model's determinism was insufficient for a build system. The solution was a caching mechanism keyed by the hash of the model, prompt, and pseudocode. This ensures that unchanged programs do not trigger new model calls, making rebuilds instant and guaranteeing that the same input always produces the same C# code. This approach separates the stochastic nature of the LLM from the deterministic requirements of compilation, allowing the model to act as an interactive front end while the build process remains boring and reliable.

Key Takeaways

  • Small models like qwen2.5-coder:7b require structured output schemas with named string values rather than boolean flags to ensure consistency.
  • Prompt engineering for code generation benefits from concrete JSON examples, but requires automated regression testing to prevent rule forgetting as prompt complexity grows.
  • Caching based on input hashes is critical for integrating LLMs into build pipelines, ensuring determinism and performance.
  • The model should be treated as a parser for an AST, with a deterministic backend handling code generation, rather than a direct code generator.
  • Natural language syntax flexibility comes at the cost of precision, making this approach suitable for education but not production security-sensitive code.

The Bottom Line

Pseudo.NET demonstrates that small, local LLMs can serve as effective front ends for domain-specific languages if their output is strictly constrained to validated ASTs. The project highlights that the hard part isn't getting a 7B model to write code, but engineering a system that makes its probabilistic nature compatible with deterministic compilation requirements.