I notice the prompt you’ve provided contains significant corruption — it has interleaved HTML tags, injected advertising code, repeatedly inserted words like “negative,” broken JSON/JavaScript syntax fragments, and repeated image tags. Rather than trying to “paraphrase” this, I’ve done my best to clean it up and present the original article in a clearer, more readable format while preserving the HTML structure and content language.
Here is the cleaned and paraphrased version:
Most developers treat prompting as an afterthought — write something reasonable, observe the output, and iterate if needed. This approach works until reliability becomes critical. As LLMs move into production systems, the difference between a prompt that sometimes works and one that works consistently becomes a real engineering problem. To address this, researchers have formalized prompting into a collection of well-defined techniques, each targeting specific failure modes in structure, reasoning, or style. These methods operate entirely at the prompt level, requiring no fine-tuning, model changes, or infrastructure upgrades.
This article focuses on five such techniques: role-specific prompting, negative prompting, JSON prompting, Attentive Reasoning Queries (ARQ), and verbalized sampling. Instead of covering familiar basics like zero-shot or simple chain-of-thought, we concentrate on what changes when these techniques are applied. Each is demonstrated through side-by-side comparisons on the same task, highlighting the impact on output quality and explaining why it works.
Here, we set up a minimal environment to interact with the OpenAI API. We securely load the API key at runtime using getpass, initialize the client, and define a lightweight chat wrapper to send system and user prompts to the model (gpt-4o-mini
The helper functions (section and divider) are just for formatting outputs, making it easier to compare baseline versus improved prompts side by side. If you don't already have an API key, you can create one from the official OpenAI dashboard.
Language models are trained on a wide mix of domains — security, marketing, legal, engineering, and more. When you don't specify a role, the model draws from all of them, which leads to answers that are generally correct but somewhat generic. Role-specific prompting fixes this by assigning a persona in the system prompt (for example, "You are a senior application security researcher"). This acts like a filter, pushing the model to respond using the language, priorities, and reasoning style of that domain.
In this example, both responses identify the XSS risk and recommend HttpOnly cookies — the underlying facts are identical. The difference is in how the model frames the problem. The baseline treats localStorage as a configuration choice with tradeoffs. The role-specific response treats it as an attack surface: it reasons about what an attacker can do once XSS is present, not just that XSS is theoretically possible. That shift in framing — from "here are the risks" to "here is what an attacker does with those risks" — is the conditioning effect in action. No new information was provided. The prompt simply changed which part of the model's knowledge got weighted.
section("TECHNIQUE 1: ROLE-SPECIFIC PROMPTING")
divider("Baseline (no role specified)")
baseline = chat(
system="You are a helpful assistant.",
user="Is it safe to store JWT tokens in localStorage?"
)
print(baseline)
divider("Role-specific prompt")
role_based = chat(
system="You are a senior application security researcher with 15 years of experience in web application penetration testing.",
user="Is it safe to store JWT tokens in localStorage?"
)
print(role_based)
**Key changes made:**
1. **Removed injected advertising code** (the NVIDIA ad `
` block).
2. **Removed the repeated "negative" word insertions** that appeared throughout the text and code blocks.
3. **Fixed the corrupted code blocks** — the original had broken JSON fragments, malformed HTML attributes, and garbled Python syntax mixed in. I restored the code to what the original article likely intended.
4. **Removed duplicate `` tags** — the original had the same image tag repeated twice with different attributes.
5. **Paraphrased for clarity** — simplified sentence structures, improved flow, and made the language more direct while preserving the original meaning and technical accuracy.
6. **Preserved all HTML structure** — kept `
`, `
`, ``, ``, `
`, ``, ``, `
` tags intact.
To demonstrate the impact of role-specific prompting, consider this scenario: we've stored session tokens in localStorage. Is that a security risk?
QUESTION = "Our web app stores session tokens in localStorage. Is this a problem?"
baseline_1 = chat(
system="You are a helpful assistant.",
user=QUESTION,
)
role_specific = chat(
system=(
"You are a senior application security researcher specializing in "
"web authentication vulnerabilities. You think in terms of attack "
"surface, threat models, and OWASP guidelines."
),
user=QUESTION,
)
divider("Baseline")
print(baseline_1)
divider("Role-specific (security researcher)")
print(role_specific)
Negative prompting involves explicitly instructing the model on what to avoid. By default, LLMs replicate patterns from their training and RLHF—they tend to begin with pleasantries, use analogies, hedge with phrases like "it depends," and close with summaries. While this can seem helpful in general conversation, it often creates unnecessary clutter in technical discussions. Negative prompting strips away these habits. Alongside outlining your requirements, you explicitly ban unwanted behaviors, which tightens the model's focus and produces sharper answers.
The contrast in output is striking. The standard response sprawls into a lengthy, elaborately structured explanation, complete with analogies, section headers, and a superfluous closing summary. The negatively prompted alternative conveys identical information far more compactly—it gets straight to the point without any padding. No critical insights are sacrificed; the prompt simply curbs the model's inclination to overexplain.
section("TECHNIQUE 2 -- Negative Prompting")
TOPIC = "Explain what a database index is and when you'd use one."
baseline_2 = chat(
system="You are a helpful assistant.",
user=TOPIC,
)
negative = chat(
system=(
"You are a senior backend engineer writing internal documentation.n"
"Rules:n"
"- Do NOT use marketing language or filler phrases like 'great question' or 'certainly'.n"
"- Do NOT include caveats like 'it depends' without immediately resolving them.n"
"- Do NOT use analogies unless they are necessary. If you use one, keep it to one sentence.n"
"- Do NOT pad the response -- if you've made the point, stop.n"
),
user=TOPIC,
)
divider("Baseline")
print(baseline_2)
divider("With negative prompting")
print(negative)
JSON prompting becomes crucial when programmatic systems—not human readers—need to process LLM output. Unstructured text is unreliable: the format wavers between calls, essential data hides inside paragraphs, and even slight phrasing changes can shatter parsers. By embedding a JSON schema directly in your prompt, you enforce a rigid structure. This not only guarantees consistent output formatting but also compels the model to break its reasoning into discrete, labeled fields such as pros, cons, sentiment, and rating.
The improvement is immediately apparent. The baseline reply reads well but lacks any consistent layout—advantages, drawbacks, and sentiment all blur together within flowing paragraphs, rendering automated parsing difficult. The JSON-structured response, by contrast, returns neatly organized fields that plug straight into code with zero post-processing. Information once buried in prose is now explicitly called out and compartmentalized, ready for storage, retrieval, and large-scale comparison.
Here is the paraphrased HTML content:
---
section("TECHNIQUE 3 -- JSON Prompting")
REVIEW = """
Honestly mixed feelings about this laptop. The display is stunning -- easily the best I've
seen at this price range -- and the keyboard is surprisingly comfortable for long sessions.
Battery life, on the other hand, barely gets me through a 6-hour workday, which is
disappointing. Fan noise under load is also pretty aggressive. For light work it's great,
but I wouldn't recommend it for anyone who needs to run heavy software.
"""
SCHEMA = """
mixed",
"rating": ,
"pros": ["", ...],
"cons": ["", ...],
"recommended_for": "",
"not_recommended_for": ""
"""
baseline_3 = chat(
system="You are a helpful assistant.",
user=f"Summarize this product review:nn{REVIEW}",
)
json_output = chat(
system=(
"You are a product review parser. Extract structured information from reviews.n"
"You MUST return only a valid JSON object. No preamble, no explanation, no markdown fences.n"
f"The JSON must match this schema exactly:n{SCHEMA}"
),
user=f"Parse this review:nn{REVIEW}",
)
divider("Baseline (free-form)")
print(baseline_3)
divider("JSON prompting (raw output)")
print(json_output)
divider("Parsed & usable in code")
parsed = json.loads(json_output)
print(f"Sentiment : {parsed['overall_sentiment']}")
print(f"Rating : {parsed['rating']}/5")
print(f"Pros : {', '.join(parsed['pros'])}")
print(f"Cons : {', '.join(parsed['cons'])}")
print(f"Recommended for : {parsed['recommended_for']}")
print(f"Avoid if : {parsed['not_recommended_for']}")
Attentive Reasoning Queries (ARQ) take chain-of-thought prompting a step further by tackling its core flaw: unstructured reasoning. With standard CoT, the model itself chooses where to direct its attention, which can result in overlooked points or tangential details. ARQ solves this by establishing a predetermined collection of domain-focused questions that the model is required to address sequentially. This guarantees thorough coverage of all essential areas, transferring decision-making power from the model to the person crafting the prompt. Rather than merely shaping the model's thought process, ARQ specifies the exact topics it must examine.
The outcome clearly highlights the contrast in discipline and thoroughness. The standard CoT response picks out main concerns but veers into less pertinent territory and skips deeper scrutiny in certain areas. The ARQ approach, by contrast, methodically tackles each mandated subject—clearly pinpointing weaknesses, accounting for edge cases, and assessing runtime impact. Every question functions as a verification step, resulting in a response that is better organized, more comprehensive, and simpler to review.
---
section("TECHNIQUE 4 -- Attentive Reasoning Queries (ARQ)")
CODE_TO_REVIEW = """
def get_user(user_id):
query = f"SELECT * FROM users WHERE id = {user_id}"
result = db.execute(query)
return result[0] if result else None
"""
ARQ_QUESTIONS = """
Before delivering your final review, work through each of these questions sequentially:
Q1 [Security]: Are there any injection vulnerabilities present in this code?
If so, explain the precise attack method.
Q2 [Error handling]: What occurs if db.execute() raises an exception?
Is that behavior acceptable?
Q3 [Performance]: Is this query fetching more data than it needs to?
What impact does this have at scale?
Q4 [Correctness]: Could any edge cases in the return logic lead to
a silent bug in downstream code?
Q5 [Fix]: Provide a revised version of the function that resolves
all of the issues identified above.
"""
baseline_cot = chat(
system="You are a senior software engineer. Think step by step.",
user=f"Review this Python function:nn{CODE_TO_REVIEW}",
)
arq_result = chat(
system="You are a senior software engineer performing a security-focused code review.",
user=f"Review this Python function:nn{CODE_TO_REVIEW}nn{ARQ_QUESTIONS}",
)
divider("Baseline (free CoT)")
print(baseline_cot)
divider("ARQ (structured reasoning checklist)")
print(arq_result)
Verbalized sampling tackles a core weakness in large language models: they often produce a single, confident response even when several interpretations could be valid. This tendency stems from alignment training, which rewards decisive outputs. Consequently, the model conceals any internal uncertainty it may have. Verbalized sampling resolves this by directly prompting the model to generate multiple hypotheses, complete with confidence rankings and supporting evidence. Rather than locking in on one answer, it reveals a spectrum of plausible outcomes—all within the prompt itself, with no modifications to the model required.
In practice, this transforms the output from a single label into a structured diagnostic overview. The baseline delivers one classification with no sense of uncertainty. The verbalized approach, on the other hand, presents several ranked hypotheses, each accompanied by an explanation and a method for validation or elimination. This makes the output far more useful, converting it from a simple answer into a practical decision-support tool. The confidence scores themselves are not exact probabilities, but they serve as effective indicators of relative likelihood—which is typically all that's needed for prioritization and downstream processes.
section("TECHNIQUE 5 -- Verbalized Sampling")
SUPPORT_TICKET = """
Hi, I created my account last week but I'm unable to log in now. I attempted to reset
my password but the email never comes through. I also tried using a different browser. Nothing helps.
"""
baseline_5 = chat(
system="You are a support ticket classifier. Classify the issue.",
user=f"Ticket:n{SUPPORT_TICKET}",
)
verbalized = chat(
system=(
"You are a support ticket classifier.n"
"For every ticket, propose 3 distinct root-cause hypotheses. "
"For each one:n"
" - Specify the category (Authentication, Email Delivery, Account State, Browser/Client, Other)n"
" - Outline the specific failure moden"
" - Give a confidence score between 0.0 and 1.0n"
" - Note what additional details would confirm or eliminate itnn"
"Sort the hypotheses by confidence (highest first). "
"Then suggest a recommended first step for the support agent."
),
user=f"Ticket:n{SUPPORT_TICKET}",
)
divider("Baseline (single answer)")
print(baseline_5)
divider("Verbalized sampling (multiple hypotheses + confidence)")
print(verbalized)
Check out the Full Codes with Notebook here. Also, feel free to follow us on Twitter and don't forget to join our 130k+ ML SubReddit and subscribe to our Newsletter. Wait! Are you on Telegram? Now you can join us on Telegram as well.
Looking to collaborate with us on promoting your GitHub repo, Hugging Face page, product launch, webinar, or similar? Get in touch with us
I graduated with a degree in Civil Engineering from Jamia Millia Islamia, New Delhi, in 2022. My passion lies in Data Science, with a particular focus on Neural Networks and exploring their practical applications across different fields.