ದೊಡ್ಡ ಭಾಷಾ ಮಾದರಿಗಳಿಂದ (LLMs) ಬರುವ ವಿರೂಪಗೊಂಡ (malformed) JSON ಅನ್ನು ಸರಿಪಡಿಸುವ ವೆಚ್ಚವನ್ನು ನಿಯಂತ್ರಿಸಲು, ರಿಪೇರಿ ಪ್ರಯತ್ನಗಳನ್ನು ಎರಡಕ್ಕೆ ಸೀಮಿತಗೊಳಿಸುವ ಮೂಲಕ ಈಗ ಡೆವಲಪರ್‌ಗಳು ಸಾಧ್ಯವಾಗುತ್ತದೆ ಎಂದು ಒಂದು ಸರಳ ಪೈಥಾನ್ ಲೂಪ್ ತೋರಿಸುತ್ತದೆ. ಈ ಮಾದರಿ—ಜನರೇಟ್ ಮಾಡಿ, ಪಾರ್ಸ್ ಮಾಡಿ, ವ್ಯಾಲಿಡೇಟ್ ಮಾಡಿ, ಮರುಪ್ರಯತ್ನಿಸಿ, ನಂತರ ಸ್ವೀಕರಿಸಿ ಅಥವಾ ವಿಫಲಗೊಳಿಸಿ—"ಬಹುಶಃ ಸರಿಯಾದ JSON" ಅನ್ನು ಅಳೆಯಬಹುದಾದ ಯಶಸ್ಸಿನ ದರಕ್ಕೆ ಪರಿವರ್ತಿಸುತ್ತದೆ ಮತ್ತು ಅತಿಯಾದ ಟೋಕನ್ ಬಳಕೆಯನ್ನು ತಡೆಯುತ್ತದೆ.

ರಿಪೇರಿ ಲೂಪ್ ಏಕೆ ಮುಖ್ಯ?

LLMಗಳಿಗೆ ಹೆಚ್ಚಾಗಿ "JSON ಅನ್ನು ಹಿಂತಿರುಗಿಸಿ" ಎಂದು ಸೂಚಿಸಲಾಗುತ್ತದೆ, ಆದರೂ ಔಟ್‌ಪುಟ್‌ನಲ್ಲಿ ಆಗಾಗ್ಗೆ ಸಿಂಟ್ಯಾಕ್ಸ್ ದೋಷಗಳು (syntax errors), ಕೀಲಿಗಳ ಕೊರತೆ ಅಥವಾ ವ್ಯವಹಾರದ ನಿಯಮಗಳನ್ನು ಉಲ್ಲಂಘಿಸುವ ಮೌಲ್ಯಗಳು ಇರುತ್ತವೆ. ಕಟ್ಟುನಿಟ್ಟಾದ ಪೇಲೋಡ್ (payload) ನಿರೀಕ್ಷಿಸುವ ಡೌನ್‌ಸ್ಟ್ರೀಮ್ ಸಿಸ್ಟಮ್ ಅಂತಹ ಔಟ್‌ಪುಟ್ ಪಡೆದರೆ ಕ್ರ್ಯಾಶ್ ಆಗಬಹುದು ಅಥವಾ ತಪ್ಪು ಫಲಿತಾಂಶಗಳನ್ನು ನೀಡಬಹುದು. ಈ ಸಮಸ್ಯೆಗಳನ್ನು ಪತ್ತೆಹಚ್ಚಲು ಮತ್ತು ಸರಿಪಡಿಸಲು ವ್ಯವಸ್ಥಿತವಾದ ಮಾರ್ಗವಿಲ್ಲದಿದ್ದರೆ, ತಂಡಗಳು ಹೆಚ್ಚಿನ ವಿಫಲತೆಯ ದರವನ್ನು ಒಪ್ಪಿಕೊಳ್ಳಬೇಕಾಗುತ್ತದೆ ಅಥವಾ ಮಾದರಿಯು ಸರಿಯಾದ ಉತ್ತರ ನೀಡುವವರೆಗೆ ಪದೇ ಪದೇ ಪ್ರಾಂಪ್ಟ್ ಮಾಡುವ ಮೂಲಕ ಹಣವನ್ನು ವ್ಯರ್ಥ ಮಾಡಬೇಕಾಗುತ್ತದೆ.

ಮೂರು ವ್ಯಾಲಿಡೇಶನ್ ಪದರಗಳು

ಒಂದು ವಿಶ್ವಾಸಾರ್ಹ ಲೂಪ್ ವ್ಯಾಲಿಡೇಶನ್ ಅನ್ನು ಈ ಕೆಳಗಿನಂತೆ ವಿಂಗಡಿಸುತ್ತದೆ:

  • Syntax – ಸ್ಟ್ರಿಂಗ್ ಅನ್ನು JSON ಆಗಿ ಪಾರ್ಸ್ ಮಾಡಲಾಗುತ್ತದೆಯೇ?
  • Shape – ಟಾಪ್-ಲೆವೆಲ್ ಆಬ್ಜೆಕ್ಟ್‌ನಲ್ಲಿ ನಿರೀಕ್ಷಿತ ಕೀಲಿಗಳು (keys) ಸರಿಯಾಗಿವೆಯೇ?
  • Semantic – ಮೌಲ್ಯಗಳು ಡೊಮೇನ್ ನಿರ್ಬಂಧಗಳನ್ನು (domain constraints) ಪಾಲಿಸುತ್ತವೆಯೇ (ಉದಾಹರಣೆಗೆ, ಒಂದು "category" ಮೊದಲೇ ನಿರ್ಧರಿಸಿದ ಸೆಟ್‌ಗೆ ಸೇರಿದ್ದೇ)?

ಮೊದಲ ವೈಫಲ್ಯದ ಪದರದಲ್ಲೇ ನಿಲ್ಲುವ ಮೂಲಕ, ಲೂಪ್ ಮಾದರಿಗೆ ನಿಖರವಾದ ದೋಷ ಸಂದೇಶವನ್ನು ನೀಡಬಹುದು, ಇದು ಮುಂದಿನ ಪ್ರಯತ್ನದಲ್ಲಿ ಸರಿಯಾದ ಪರಿಹಾರ ಸಿಗುವ ಸಾಧ್ಯತೆಯನ್ನು ಗಮನಾರ್ಹವಾಗಿ ಹೆಚ್ಚಿಸುತ್ತದೆ.

ಕನಿಷ್ಠ ಪೈಥಾನ್ ಉದಾಹರಣೆ

ಈ ಕೆಳಗಿನ ಕೋಡ್ ಕೇವಲ ಸ್ಟ್ಯಾಂಡರ್ಡ್ ಲೈಬ್ರರಿಯನ್ನು ಬಳಸುತ್ತದೆ. ಇದು ಒಂದು ಸಣ್ಣ ಸ್ಕೀಮಾವನ್ನು (category ಮತ್ತು summary ಕೀಲಿಗಳನ್ನು ಹೊಂದಿರುವ ಡಿಕ್ಷನರಿ) ಮತ್ತು ಅನುಮತಿಸಲಾದ ವರ್ಗಗಳ (categories) ಸ್ಥಿರ ಪಟ್ಟಿಯನ್ನು ವ್ಯಾಖ್ಯಾನಿಸುತ್ತದೆ.

import json

CATEGORIES = {"bug", "feature", "question"}

def validate(raw: str):
    try:
        value = json.loads(raw)
    except json.JSONDecodeError as exc:
        return None, f"syntax: {exc.msg}"

    if not isinstance(value, dict):
        return None, "shape: root must be an object"
    if set(value) != {"category", "summary"}:
        return None, "shape: expected category and summary"
    if value["category"] not in CATEGORIES:
        return None, "semantic: invalid category"
    if not isinstance(value["summary"], str) or not value["summary"].strip():
        return None, "semantic: summary must be text"

    return value, None

ರಿಪೇರಿ ಲೂಪ್ ಸ್ವತಃ ಪ್ರಯತ್ನಗಳ ಮೇಲೆ ಕಟ್ಟುನಿಟ್ಟಾದ ಮಿತಿಯನ್ನು ಹೇರುತ್ತದೆ:

MAX_ATTEMPTS = 2
raw = model_response   # initial LLM output

for attempt in range(MAX_ATTEMPTS + 1):
    value, error = validate(raw)
    if error is None:
        break
    if attempt == MAX_ATTEMPTS:
        raise RuntimeError(f"failed after {MAX_ATTEMPTS} retries: {error}")

    # Send the error and schema back to the model for a fix
    raw = ask_model_to_repair(raw, error)

ಒಂದು ವೇಳೆ JSON ಮೊದಲ ಪ್ರಯತ್ನದಲ್ಲೇ ವ್ಯಾಲಿಡೇಶನ್ ಪಾಸಾದರೆ, ಲೂಪ್ ತಕ್ಷಣವೇ ಹೊರಬರುತ್ತದೆ. ಇಲ್ಲದಿದ್ದರೆ ಅದು ಮರುಪ್ರಯತ್ನಿಸುತ್ತದೆ, ಮಾದರಿಗೆ ಸಂಕ್ಷಿಪ್ತ ಪೇಲೋಡ್ ಅನ್ನು ನೀಡುತ್ತದೆ: ಮೂಲ ಔಟ್‌ಪುಟ್, ನಿಖರವಾದ ಎರರ್ ಸ್ಟ್ರಿಂಗ್ ಮತ್ತು ನಿರೀಕ್ಷಿತ ಸ್ಕೀಮಾ. ಎರಡು ಪ್ರಯತ್ನಗಳು ವಿಫಲವಾದ ನಂತರ ಪ್ರಕ್ರಿಯೆಯು ಸ್ಪಷ್ಟವಾದ ಎಕ್ಸೆಪ್ಶನ್‌ನೊಂದಿಗೆ (exception) ಸ್ಥಗಿತಗೊಳ್ಳುತ್ತದೆ.

ವೆಚ್ಚ-ಪರಿಣಾಮಕಾರಿ ರಿಪೇರಿಗಳಿಗಾಗಿ ಎರಡು ನಿಯಮಗಳು

  1. ರಿಪೇರಿ ಪ್ರಾಂಪ್ಟ್‌ಗಳನ್ನು ಸಂಕ್ಷಿಪ್ತವಾಗಿಡಿ – ಕೇವಲ ರೇ (raw) JSON, ದೋಷ ಸಂದೇಶ ಮತ್ತು ಸ್ಕೀಮಾವನ್ನು ಮಾತ್ರ ಸೇರಿಸಿ. ದೀರ್ಘವಾದ ಚಾಟ್ ಇತಿಹಾಸವನ್ನು ಸೇರಿಸುವುದು ಟೋಕನ್ ಬಳಕೆಯನ್ನು ಹೆಚ್ಚಿಸುತ್ತದೆ ಮತ್ತು ಮಾದರಿಯನ್ನು ಗೊಂದಲಕ್ಕೀಡು ಮಾಡಬಹುದು, ಇದು ನಿಖರತೆಯನ್ನು ಸುಧಾರಿಸದೆ ಪ್ರತಿ ಮರುಪ್ರಯತ್ನದ ವೆಚ್ಚವನ್ನು ಹೆಚ್ಚಿಸುತ್ತದೆ.

  2. ವ್ಯಾಲಿಡೇಶನ್ ಅನ್ನು ಫ್ಯಾಕ್ಟ್-ಚೆಕಿಂಗ್‌ನಿಂದ ಪ್ರತ್ಯೇಕಿಸಿ – ಪಾರ್ಸರ್ ರಚನಾತ್ಮಕ ಸಮಸ್ಯೆಗಳನ್ನು ಪತ್ತೆಹಚ್ಚಬಹುದು, ಆದರೆ "summary" ಹೇಳಿಕೆಯು ನಿಜವೇ ಎಂದು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಫ್ಯಾಕ್ಟ್-ಚೆಕಿಂಗ್ ನಂತರದ ಹಂತದಲ್ಲಿ ಇರಬೇಕು; ಸುಳ್ಳು ಹೇಳಿಕೆಯನ್ನು "ರಿಪೇರಿ" ಮಾಡಲು ಪ್ರಯತ್ನಿಸುವುದು ಕೇವಲ ಆ ಸುಳ್ಳನ್ನು ಅಚ್ಚುಕಟ್ಟಾಗಿ ಕಾಣುವಂತೆ ಮಾಡುತ್ತದೆ ಅಷ್ಟೆ.

ಯಶಸ್ಸನ್ನು ಅಳೆಯುವುದು

ಪ್ರತಿ ಪ್ರಯತ್ನದ ದೋಷದ ಪ್ರಕಾರವನ್ನು (syntax, shape, semantic) ಮತ್ತು ಲೂಪ್ ಯಶಸ್ವಿಯಾಗಿದೆಯೇ ಎಂಬುದನ್ನು ಲಾಗ್ ಮಾಡುವುದು ಒಂದು ನಿರ್ದಿಷ್ಟ ಮೆಟ್ರಿಕ್ ಅನ್ನು ನೀಡುತ್ತದೆ: ಮಿತಿಗೊಳಿಸಿದ ಮರುಪ್ರಯತ್ನಗಳ ಒಳಗೆ ಬಳಸಲು ಸಾಧ್ಯವಾಗುವ LLM ಪ್ರತಿಕ್ರಿಯೆಗಳ ಪ್ರಮಾಣ. ತಂಡಗಳು ಇದನ್ನು ಕಾಲಕಾಲಕ್ಕೆ ಟ್ರ್ಯಾಕ್ ಮಾಡಬಹುದು, ಪ್ರಾಂಪ್ಟ್ ಶೈಲಿಗಳನ್ನು ಹೋಲಿಸಬಹುದು ಅಥವಾ ವಿಭಿನ್ನ ಸ್ಕೀಮಾ ವ್ಯಾಖ್ಯಾನಗಳೊಂದಿಗೆ ಪ್ರಯೋಗ ಮಾಡಬಹುದು.

ಸಂಭಾವ್ಯ ಅನಾನುಕೂಲಗಳು

ಲೂಪ್ ಅನ್ನು ಮಿತಿಗೊಳಿಸುವುದು ಎಂದರೆ ಮಿತಿ ತಲುಪಿದ ನಂತರ ಕೆಲವು ವಿರೂಪಗೊಂಡ ಔಟ್‌ಪುಟ್‌ಗಳನ್ನು ಕೈಬಿಡಲಾಗುತ್ತದೆ, ಇದು ಮಾದರಿಯ ಮೂಲ ಗುಣಮಟ್ಟ ಕಡಿಮೆಯಿದ್ದರೆ ಒಟ್ಟಾರೆ ವಿಫಲತೆಯ ದರವನ್ನು ಹೆಚ್ಚಿಸಬಹುದು. ಪ್ರತಿ ಪ್ರತಿಕ್ರಿಯೆಯೂ ನಿರ್ಣಾಯಕವಾಗಿರುವ ಪರಿಸರಗಳಲ್ಲಿ, ಡೆವಲಪರ್‌ಗಳು ಹೆಚ್ಚಿನ ಟೋಕನ್‌ಗಳ ವೆಚ್ಚದ ಮೇಲೆ ಹೆಚ್ಚಿನ ಮರುಪ್ರಯತ್ನ ಮಿತಿಯನ್ನು ಬಯಸಬಹುದು. ಇಲ್ಲಿನ ವಹಿವಾಟು (trade-off) ಸ್ಪಷ್ಟವಾಗಿದೆ: ಹೆಚ್ಚಿನ ವ್ಯಾಪ್ತಿಗಾಗಿ ಹೆಚ್ಚಿನ ವೆಚ್ಚ, ಅಥವಾ ನಿರೀಕ್ಷಿತ ಮಿತಿಯೊಂದಿಗೆ ಕಡಿಮೆ ಬಜೆಟ್.

ಮುಂದೆ ಗಮನಿಸಬೇಕಾದವುಗಳು

  • ರಿಪೇರಿಗಾಗಿ ಪ್ರಾಂಪ್ಟ್ ಇಂಜಿನಿಯರಿಂಗ್ – ದೋಷ ಸಂದೇಶದ ಫಾರ್ಮ್ಯಾಟ್ ಅನ್ನು ಸುಧಾರಿಸುವುದರಿಂದ ಅಗತ್ಯವಿರುವ ಮರುಪ್ರಯತ್ನಗಳ ಸಂಖ್ಯೆಯನ್ನು ಕಡಿಮೆ ಮಾಡಬಹುದು.
  • ಪರ್ಯಾಯ ಪಾರ್ಸರ್‌ಗಳು – ಕೆಲವು ಲೈಬ್ರರಿಗಳು ಸಣ್ಣಪುಟ್ಟ ಸಮಸ್ಯೆಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸರಿಪಡಿಸಬಲ್ಲ ಟಾಲರೆಂಟ್ ಪಾರ್ಸಿಂಗ್ ಅನ್ನು ಒದಗಿಸುತ್ತವೆ; ಅವುಗಳ ವೆಚ್ಚವನ್ನು ಮಿತಿಗೊಳಿಸಿದ ಲೂಪ್‌ನೊಂದಿಗೆ ಹೋಲಿಸುವುದು ಪ್ರಯೋಜನಕಾರಿ.
  • ಮಾದರಿ ಅಪ್‌ಡೇಟ್‌ಗಳು – ಹೊಸದಾದ LLM ಆವೃತ್ತಿಗಳು ಮೊದಲೇ ಅಚ್ಚುಕಟ್ಟಾದ JSON ಅನ್ನು ನೀಡಬಹುದು, ಇದು ಮರುಪ್ರಯತ್ನದ ಮಿತಿಯನ್ನು ಇನ್ನಷ್ಟು ಕಡಿಮೆ ಮಾಡಲು ಸಹಾಯ ಮಾಡಬಹುದು.

ಮಿತಿಗೊಳಿಸಿದ JSON ರಿಪೇರಿ ಲೂಪ್ ಡೆವಲಪರ್‌ಗಳಿಗೆ ಅತಿಯಾದ ವೆಚ್ಚವಿಲ್ಲದೆ ಅಸ್ಪಷ್ಟ LLM ಔಟ್‌ಪುಟ್ ಅನ್ನು ವಿಶ್ವಾಸಾರ್ಹ ಡೇಟಾ ಆಗಿ ಪರಿವರ್ತಿಸಲು ಒಂದು ಪ್ರಾಯೋಗಿಕ ಸಾಧನವನ್ನು ನೀಡುತ್ತದೆ. ವ್ಯಾಲಿಡೇಶನ್ ಅನ್ನು ಒಂದು ಪ್ರಮುಖ ಹಂತವಾಗಿ ಪರಿಗಣಿಸುವ ಮೂಲಕ ಮತ್ತು ಮರುಪ್ರಯತ್ನಗಳನ್ನು ಮಿತಿಗೊಳಿಸುವ ಮೂಲಕ, ತಂಡಗಳು ಬಜೆಟ್ ಮತ್ತು ಡೌನ್‌ಸ್ಟ್ರೀಮ್ ಸಿಸ್ಟಮ್ ಎರಡನ್ನೂ ಸುಗಮವಾಗಿಡಬಹುದು.