Showing posts with label UX. Show all posts
Showing posts with label UX. Show all posts

Thursday, January 15, 2026

[Deep Dive] Text-to-Config: Teaching AI to Speak "JSON

[Deep Dive] Text-to-Config: Teaching AI to Speak "JSON"

How to engineer the perfect prompt to convert fuzzy human requests into strict machine configurations.

In Part 2, we designed a beautiful JSON Schema for our parking lot system. It’s like building a perfect skeleton. But a skeleton cannot move on its own.

Now, in Part 3, we need to build the "Brain." We need to take a user's messy, vague request (e.g., "Make it cheap for the weekend") and convert it into that strict JSON format.

This is where Prompt Engineering comes in. We are not just "chatting" with the AI; we are programming it using English.

1. The "Strict Manager" Persona

If you ask ChatGPT normally, "Please make a config," it acts like a helpful assistant. It might give you explanations, Python code, or unnecessary polite text.

We don't want that. We want a machine.

We must define a System Prompt that forces the AI into a specific role. Think of this as the "Employee Handbook" you give to a new intern.

System Prompt Template You are a Parking Configuration Engine. Your goal is to convert natural language requests into a JSON object based on the provided schema. RULES: 1. Output JSON Only: Do not include markdown formatting (like ```json), explanations, or polite conversation. Just the raw JSON. 2. Determinism: If the user does not specify a value (e.g., "cheap"), return an ERROR code. Do not guess the price. 3. Current Time: Today is {current_date}. Use this to calculate "this weekend" or "tonight".

2. The Complete Python Implementation

Here is the actual Python code you can use. I have added detailed comments to explain how to handle the OpenAI API safely.

[Image of Python code structure diagram]
import json
from openai import OpenAI
from datetime import datetime

client = OpenAI(api_key="YOUR_API_KEY")

# 1. Provide the Schema Context (The "Rulebook")
# We inject this into the prompt so the AI knows the structure.
SCHEMA_CONTEXT = """
SCHEMA DEFINITION:
{
  "rules": [
    {
      "conditions": { "start_time": "ISO8601", "end_time": "ISO8601" },
      "actions": [ { "type": "SET_PRICE", "amount": float } ]
    }
  ]
}
"""

def generate_parking_config(user_input):
    # Get current time for relative date calculations (e.g., "This Friday")
    now_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    # 2. Construct the Messages
    messages = [
        {
            "role": "system",
            "content": f"You are a Strict Config Generator. Current Time: {now_str}. \nSchema: {SCHEMA_CONTEXT}"
        },
        {
            "role": "user",
            "content": user_input
        }
    ]

    try:
        response = client.chat.completions.create(
            model="gpt-4-turbo", # Use a smart model for logic
            messages=messages,
            temperature=0,       # Important! 0 means 'no creativity'. We want logic.
            response_format={ "type": "json_object" } # Force valid JSON
        )

        json_str = response.choices[0].message.content
        return json.loads(json_str)

    except Exception as e:
        return { "error": "AI_PROCESSING_FAILED", "details": str(e) }

Key Technical Details:

  • temperature=0: This is critical. It tells the AI to be "deterministic" and boring. We don't want creative parking fees.
  • response_format={"type": "json_object"}: This ensures the API doesn't return half-finished text. It guarantees syntax correctness.
  • datetime.now(): By injecting the current time, the AI can correctly understand relative terms like "tonight" or "next weekend."

3. Real-World Examples: Handling Ambiguity

The biggest challenge is when users are vague. Let's see how our setup handles different inputs.

Good Input "Set the price to $10/hr for tonight."

The input is specific. The AI has the amount ($10) and the time (tonight).

Output:
{
  "actions": [ { "type": "SET_PRICE", "amount": 10.0 } ],
  "conditions": { "start": "2024-05-20T18:00:00", "end": "..." }
}
Vague Input "Make it cheap for students."

This is dangerous. What is "cheap"? $1? $0? 50% off? The AI should not guess.

Because we set the system prompt to be strict, the AI returns an error object asking for clarification.

Output:
{
  "error": "MISSING_PARAMETER",
  "message": "You requested a 'cheap' rate, but did not specify the exact price amount."
}

4. Pro Tip: Chain-of-Thought (CoT)

Sometimes, complex logic fails. For example: "Charge $10 normally, but if it's a weekend AND a concert, charge double."

To solve this, ask the AI to "think" before it acts. Add a "reasoning" field to your JSON schema.

Advanced Technique "Before generating the final config, populate the 'reasoning' field. Explain your logic step-by-step."

This forces the model to verify its own logic (e.g., "User said double $10, so the price is $20") before creating the final JSON. It dramatically reduces logical errors.

Conclusion

We now have a system that speaks JSON fluently and handles vague inputs safely. We have bridged the gap between human language and machine configuration.

However, there is one final danger. Even if the JSON is valid, the logic might be disastrous (e.g., setting the price to -$500). In the next post, we will build the final defense layer: Logic Guardrails.

The Death of the Settings Page: Building a "Text-to-Config" Engine

[Deep Dive] The Death of the Settings Page: Building a "Text-to-Config" Engine

Why the future of software configuration isn't more buttons—it's Natural Language.

1. The Saturday Night "Feature Request"

It’s 9:00 PM on a Saturday. You are a backend engineer, finally unwinding after a long week. Suddenly, your phone buzzes. It’s the client—a manager of a large downtown parking complex.

Client: "Emergency! There's a surprise Beyoncé concert at the stadium across the street. The lot is flooding with cars. I need to change the pricing rules right now."

You: "Sure, just log in to the admin dashboard and update the hourly rate."

Client: "I can't! I need to charge $20/hour, but only until midnight, and I want to disable the 30-minute free grace period for anyone who isn't a monthly subscriber. Your dashboard doesn't have a button for that combination!"

The client is right. Your "Settings Page" has a field for Base Rate and a toggle for Grace Period. It does not have a complex logic builder for specific time windows combined with user-group exceptions.

To solve this, you have to:

  1. Open your laptop.
  2. Write a hotfix in the codebase (if event == 'concert'...).
  3. Deploy to production.
  4. Pray nothing breaks.

This scenario highlights a fundamental flaw in modern UI development: The "Checkbox Hell."

2. The Trap of the "Perfect" Dashboard

We often try to solve complexity by building more UI. If a user needs a new rule, we add a new checkbox. If they need a condition, we add a dropdown.

In the domain of Parking Logic, this approach hits a wall because the complexity is combinatorial.

  • Variables: Time (Day/Night), Day (Weekday/Weekend), Duration.
  • Actors: Guest, Resident, VIP, Delivery Truck, EV.
  • Rules: Base rate, Caps, Discounts, Grace periods.

The "Spaghetti UI" Code

If you tried to build a React form to handle just 50% of possible parking scenarios, your frontend code would look like this nightmare:

// The "Checkbox Hell" - A maintenance nightmare
const PricingRuleEditor = () => {
  return (
    <div className="rule-container">
      <Input label="Base Price" />
      <Select label="Apply to Group">
        <Option value="all">Everyone</Option>
        <Option value="vip">VIP Only</Option>
        {/* What if they want "VIP AND Residents"? */}
      </Select>
      
      <div className="conditionals">
        <Checkbox label="Is Weekend?" />
        <Checkbox label="Is Holiday?" />
        
        {/* Nested Logic hell */}
        {isEventNight && (
          <div className="event-settings">
             <TimePicker label="Start Time" />
             <Checkbox label="Disable Discounts?" />
          </div>
        )}
      </div>
    </div>
  );
};

This UI is rigid. The moment the client invents a rule you didn't predict, your UI fails.

3. The Shift: Text-to-Config Architecture

The solution isn't a better UI. It's No UI.

We are entering the era of Text-to-Config. Instead of clicking buttons, the user communicates their intent in natural language. An LLM acts as a translator, converting that intent into a strict, machine-readable Configuration Object.

The Workflow:

1. User Input: "Set rate to $20/hr for tonight. No grace period for visitors."
2. Translation (LLM): Maps text to JSON Schema.
3. Execution: Backend engine calculates fees.

4. Designing the "Universal" Schema

To make this work in production, you cannot just let AI output random JSON. You need a Schema Contract.

We can break down any parking rule into four atomic components: Context, Target, Action, and Priority. Here is the robust JSON schema design:

{
  "config_meta": {
    "policy_name": "Beyonce_Concert_Event",
    "created_at": "2024-05-20T21:05:00Z"
  },
  "rules_engine": [
    // Rule 1: The Concert Rate ($20/hr)
    {
      "rule_id": "event_base_rate",
      "priority": 100, // High priority overrides default
      "conditions": {
        "time_window": {
          "start": "2024-05-20T18:00:00",
          "end": "2024-05-21T00:00:00"
        }
      },
      "actions": [
        {
          "type": "SET_UNIT_PRICE",
          "value": 20.00,
          "unit": "hour"
        }
      ]
    },
    // Rule 2: Remove Grace Period for Visitors
    {
      "rule_id": "no_free_time_visitors",
      "priority": 100,
      "conditions": {
        "user_groups": ["visitor"], 
        "match_mode": "include"
      },
      "actions": [
        {
          "type": "DISABLE_FEATURE",
          "feature_key": "grace_period_30m" 
        }
      ]
    }
  ]
}

5. Implementation: How the Code "Reads" the Config

You stop writing if/else chains. Instead, you write a generic Rule Evaluator in Python:

def calculate_parking_fee(car_context, active_config):
    # 1. Sort rules by Priority (High to Low)
    sorted_rules = sorted(active_config['rules_engine'], key=lambda x: x['priority'], reverse=True)

    for rule in sorted_rules:
        # 2. Check Conditions (Does this rule apply to this car?)
        if not check_conditions(rule['conditions'], car_context):
            continue
            
        # 3. Apply Actions
        for action in rule['actions']:
            if action['type'] == 'SET_UNIT_PRICE':
                current_price = action['value']
            elif action['type'] == 'DISABLE_FEATURE':
                car_context['grace_period'] = False
                
    return current_price

This code doesn't know about "Beyoncé" or "Concerts." It only knows how to process rules. This makes your system incredibly resilient.

6. The Future: From "Clicking" to "Declaring"

Text-to-Config is more than just a convenient feature; it is a fundamental shift in how we design software interfaces. We are moving away from Imperative UI (where users must know how to configure settings) to Declarative Configuration (where users simply state what they want).

By decoupling the user interface from the business logic through a robust JSON schema, we create systems that are scalable, maintainable, and ready for any "Saturday Night Emergency" the real world throws at them.

[Deep Dive] Text-to-Config: Teaching AI to Speak "JSON

[Deep Dive] Text-to-Config: Teaching AI to Speak "JSON" How to engineer the perfect prompt to convert fu...