"""
Pattern 129: Clarification & Disambiguation
Description:
Detects ambiguous or unclear user inputs and asks targeted clarifying questions
to resolve uncertainties before proceeding.
Components:
- Ambiguity detection
- Clarification question generation
- Context tracking
- Progressive refinement
Use Cases:
- Conversational agents handling ambiguous queries
- Complex instruction following
- Reducing errors from misunderstanding
LangChain Implementation:
Uses LangChain to detect ambiguity and generate appropriate clarification questions.
"""
import os
from typing import List, Dict, Any, Optional
from dotenv import load_dotenv
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import JsonOutputParser, StrOutputParser
from langchain_openai import ChatOpenAI
from langchain_core.pydantic_v1 import BaseModel, Field
load_dotenv()
class AmbiguityAnalysis(BaseModel):
"""Analysis of ambiguity in user input"""
is_ambiguous: bool = Field(description="Whether input is ambiguous")
ambiguity_type: str = Field(description="Type of ambiguity: lexical, syntactic, semantic, referential")
confidence: float = Field(description="Confidence in ambiguity detection")
ambiguous_elements: List[str] = Field(description="Specific ambiguous elements")
clarification_needed: str = Field(description="What needs clarification")
class ClarificationQuestion(BaseModel):
"""A clarification question"""
question: str = Field(description="The clarification question")
options: Optional[List[str]] = Field(description="Possible options if applicable")
priority: int = Field(description="Priority (1=high, 3=low)")
class ClarificationAgent:
"""Agent for handling ambiguity and generating clarifications"""
def __init__(self, model: str = "gpt-4o-mini", temperature: float = 0.3):
self.llm = ChatOpenAI(model=model, temperature=temperature)
self.clarification_history: List[Dict[str, Any]] = []
# Ambiguity detection prompt
self.ambiguity_prompt = ChatPromptTemplate.from_messages([
("system", """Analyze the user's input for ambiguity or unclear elements.
Types of ambiguity:
- Lexical: Multiple meanings of a word (e.g., "bank" - financial or river)
- Syntactic: Sentence structure unclear (e.g., "I saw the man with the telescope")
- Semantic: Vague or imprecise meaning (e.g., "nearby", "soon")
- Referential: Unclear what something refers to (e.g., "it", "that thing")
Return JSON:
{{
"is_ambiguous": true/false,
"ambiguity_type": "type",
"confidence": 0.9,
"ambiguous_elements": ["element1", "element2"],
"clarification_needed": "what specifically needs clarification"
}}"""),
("user", "Input: {input}\n\nPrevious context: {context}")
])
# Clarification generation prompt
self.clarification_prompt = ChatPromptTemplate.from_messages([
("system", """Generate a helpful clarification question to resolve the ambiguity.
Make the question:
1. Specific and targeted
2. Easy to answer
3. Include options when helpful
4. Natural and conversational
Return JSON:
{{
"question": "the clarification question",
"options": ["option1", "option2"] or null,
"priority": 1-3
}}"""),
("user", """Input: {input}
Ambiguity: {ambiguity}
Elements needing clarification: {elements}
Generate a clarification question.""")
])
self.json_parser = JsonOutputParser()
def detect_ambiguity(self, user_input: str, context: str = "") -> AmbiguityAnalysis:
"""Detect if input is ambiguous"""
try:
chain = self.ambiguity_prompt | self.llm | self.json_parser
result = chain.invoke({"input": user_input, "context": context})
return AmbiguityAnalysis(**result)
except Exception as e:
print(f"Ambiguity detection error: {e}")
return AmbiguityAnalysis(
is_ambiguous=False,
ambiguity_type="unknown",
confidence=0.0,
ambiguous_elements=[],
clarification_needed=""
)
def generate_clarification(
self,
user_input: str,
analysis: AmbiguityAnalysis
) -> ClarificationQuestion:
"""Generate clarification question"""
try:
chain = self.clarification_prompt | self.llm | self.json_parser
result = chain.invoke({
"input": user_input,
"ambiguity": analysis.ambiguity_type,
"elements": ", ".join(analysis.ambiguous_elements)
})
return ClarificationQuestion(**result)
except Exception as e:
print(f"Clarification generation error: {e}")
return ClarificationQuestion(
question="Could you please provide more details?",
options=None,
priority=2
)
def process_input(self, user_input: str, context: str = "") -> Dict[str, Any]:
"""Process input and return clarification if needed"""
print(f"\n{'='*70}")
print(f"š Input: {user_input}")
# Detect ambiguity
analysis = self.detect_ambiguity(user_input, context)
print(f"\nš Analysis:")
print(f" Ambiguous: {analysis.is_ambiguous}")
print(f" Confidence: {analysis.confidence:.2f}")
result = {
"input": user_input,
"is_ambiguous": analysis.is_ambiguous,
"analysis": analysis,
"clarification": None
}
if analysis.is_ambiguous and analysis.confidence > 0.6:
print(f" Type: {analysis.ambiguity_type}")
print(f" Ambiguous elements: {', '.join(analysis.ambiguous_elements)}")
# Generate clarification
clarification = self.generate_clarification(user_input, analysis)
result["clarification"] = clarification
print(f"\nā Clarification needed:")
print(f" {clarification.question}")
if clarification.options:
print(f" Options:")
for i, opt in enumerate(clarification.options, 1):
print(f" {i}. {opt}")
# Store in history
self.clarification_history.append({
"input": user_input,
"analysis": analysis.dict(),
"clarification": clarification.dict()
})
else:
print(f"\nā
Input is clear, no clarification needed")
return result
def resolve_with_clarification(
self,
original_input: str,
clarification_response: str
) -> str:
"""Process clarified input"""
resolution_prompt = ChatPromptTemplate.from_messages([
("system", "Combine the original input with the clarification to form a complete, unambiguous statement."),
("user", """Original: {original}
Clarification response: {clarification}
Generate complete, unambiguous statement:""")
])
chain = resolution_prompt | self.llm | StrOutputParser()
resolved = chain.invoke({
"original": original_input,
"clarification": clarification_response
})
print(f"\nā
Resolved statement:")
print(f" {resolved}")
return resolved
def demonstrate_clarification():
"""Demonstrate clarification and disambiguation"""
print("=" * 80)
print("Pattern 129: Clarification & Disambiguation")
print("=" * 80)
agent = ClarificationAgent()
# Example 1: Lexical ambiguity
print("\n" + "=" * 80)
print("EXAMPLE 1: Lexical Ambiguity")
print("=" * 80)
ambiguous_inputs = [
"I need to go to the bank",
"Can you get me the bat?",
"Show me the rock music"
]
for input_text in ambiguous_inputs:
result = agent.process_input(input_text)
if result["clarification"]:
# Simulate user providing clarification
print(f"\n š¬ User provides clarification: Financial bank")
resolved = agent.resolve_with_clarification(
input_text,
"The financial institution"
)
# Example 2: Referential ambiguity
print("\n" + "=" * 80)
print("EXAMPLE 2: Referential Ambiguity")
print("=" * 80)
referential_inputs = [
("John told Mike he should leave", "Previous: John and Mike were arguing"),
("Put it on the table", "Previous: User has a box and a book"),
("I want the blue one", "Previous: Looking at shirts")
]
for input_text, context in referential_inputs:
agent.process_input(input_text, context)
# Example 3: Semantic vagueness
print("\n" + "=" * 80)
print("EXAMPLE 3: Semantic Vagueness")
print("=" * 80)
vague_inputs = [
"Schedule a meeting soon",
"I need a lot of storage",
"Find a nearby restaurant"
]
for input_text in vague_inputs:
agent.process_input(input_text)
# Example 4: Complex ambiguity
print("\n" + "=" * 80)
print("EXAMPLE 4: Complex Ambiguous Request")
print("=" * 80)
complex_input = "Book me a nice hotel room with a good view for my trip"
result = agent.process_input(complex_input)
if result["clarification"]:
print(f"\n š¬ User response: Paris, June 15-20, budget up to $200/night")
resolved = agent.resolve_with_clarification(
complex_input,
"Paris, France from June 15-20, 2024, budget $200 per night"
)
# Example 5: Clear input (no clarification needed)
print("\n" + "=" * 80)
print("EXAMPLE 5: Clear Input (No Clarification)")
print("=" * 80)
clear_inputs = [
"Set an alarm for 7:00 AM tomorrow",
"What is the capital of France?",
"Calculate 15% tip on $85.50"
]
for input_text in clear_inputs:
agent.process_input(input_text)
# Statistics
print("\n" + "=" * 80)
print("CLARIFICATION STATISTICS")
print("=" * 80)
print(f"\nTotal clarifications asked: {len(agent.clarification_history)}")
if agent.clarification_history:
print(f"\nAmbiguity types encountered:")
types = {}
for item in agent.clarification_history:
amb_type = item['analysis']['ambiguity_type']
types[amb_type] = types.get(amb_type, 0) + 1
for amb_type, count in types.items():
print(f" - {amb_type}: {count}")
# Summary
print("\n" + "=" * 80)
print("SUMMARY")
print("=" * 80)
print("""
Clarification & Disambiguation Pattern:
- Detects ambiguous or unclear user inputs
- Generates targeted clarification questions
- Resolves ambiguity through progressive refinement
- Improves accuracy and user satisfaction
Types of Ambiguity Handled:
ā Lexical - Multiple word meanings
ā Syntactic - Unclear sentence structure
ā Semantic - Vague or imprecise terms
ā Referential - Unclear references
Key Benefits:
ā Reduces errors from misunderstanding
ā Improves task completion accuracy
ā Better user experience
ā Handles complex, real-world inputs
ā Proactive problem prevention
Best Practices:
⢠Ask specific, targeted questions
⢠Provide options when helpful
⢠Keep questions natural and conversational
⢠Prioritize most important clarifications
⢠Track clarification history for learning
""")
if __name__ == "__main__":
demonstrate_clarification()
Agentic Design Pattern: Clarification
Pattern 129: Clarification – Line-by-Line Explanation
Overview
This document provides a detailed line-by-line explanation of the Clarification pattern implementation.
Pattern Description
Pattern 129: Clarification & Disambiguation
Description: Detects ambiguous or unclear user inputs and asks targeted clarifying questions to resolve uncertainties before proceeding.
Components: – Ambiguity detection – Clarification question generation – Context tracking – Progressive refinement
Use Cases: – Conversational agents handling ambiguous queries – Complex instruction following – Reducing errors from misunderstanding
LangChain Implementation: Uses LangChain to detect ambiguity and generate appropriate clarification questions.
File Statistics
- Total Lines: 354
- Classes: 3
- Functions: 1
- Constants: 0
Module Documentation
"""
Pattern 129: Clarification & Disambiguation
Description:
Detects ambiguous or unclear user inputs and asks targeted clarifying questions
to resolve uncertainties before proceeding.
Components:
- Ambiguity detection
- Clarification question generation
- Context tracking
- Progressive refinement
Use Cases:
- Conversational agents handling ambiguous queries
- Complex instruction following
- Reducing errors from misunderstanding
LangChain Implementation:
Uses LangChain to detect ambiguity and generate appropriate clarification questions.
"""
Purpose: This module implements the Clarification pattern, providing a structured approach to agent design and implementation.
Import Statements
Standard Library Imports
import langchain_core.output_parsers.JsonOutputParser
import langchain_core.output_parsers.StrOutputParser
import langchain_core.prompts.ChatPromptTemplate
import langchain_core.pydantic_v1.BaseModel
import langchain_core.pydantic_v1.Field
import os
import typing.Any
import typing.Dict
import typing.List
import typing.Optional
Purpose: Core Python functionality:
– langchain_core.output_parsers.JsonOutputParser: Regular expression operations
– langchain_core.output_parsers.StrOutputParser: Regular expression operations
– langchain_core.prompts.ChatPromptTemplate: Regular expression operations
– langchain_core.pydantic_v1.BaseModel: Regular expression operations
– langchain_core.pydantic_v1.Field: Regular expression operations
– os: Environment variable access and system operations
– typing.Any: Type hints for better code documentation (List, Dict, Any, Optional)
– typing.Dict: Type hints for better code documentation (List, Dict, Any, Optional)
– typing.List: Type hints for better code documentation (List, Dict, Any, Optional)
– typing.Optional: Type hints for better code documentation (List, Dict, Any, Optional)
LangChain Imports
from langchain_openai.ChatOpenAI
Purpose: LangChain framework components: – LLM Interface: Wrapper for OpenAI models – Chains: Composable building blocks for complex workflows
Other Imports
from dotenv.load_dotenv
Purpose: Additional dependencies for specialized functionality.
Classes
Class: AmbiguityAnalysis
Lines 35-41
Inherits from: BaseModel
Purpose:
Analysis of ambiguity in user input
Class: ClarificationQuestion
Lines 44-48
Inherits from: BaseModel
Purpose:
A clarification question
Class: ClarificationAgent
Lines 51-212
Purpose:
Agent for handling ambiguity and generating clarifications
Methods:
__init__(self, model, temperature)
Lines 54-102
Purpose: Initialize the class instance with required parameters.
Parameters:
– model: Language model instance
– temperature: Sampling temperature (0-1)
detect_ambiguity(self, user_input, context)
Lines 104-119
Purpose:
Detect if input is ambiguous
Parameters:
– user_input: Input data
– context: Context
Returns: AmbiguityAnalysis
generate_clarification(self, user_input, analysis)
Lines 121-142
Purpose:
Generate clarification question
Parameters:
– user_input: Input data
– analysis: Analysis
Returns: ClarificationQuestion
process_input(self, user_input, context)
Lines 144-187
Purpose:
Process input and return clarification if needed
Parameters:
– user_input: Input data
– context: Context
Returns: <ast.Subscript object at 0x000001A06D7EEA90>
resolve_with_clarification(self, original_input, clarification_response)
Lines 189-212
Purpose:
Process clarified input
Parameters:
– original_input: Input data
– clarification_response: Clarification response
Returns: str
Functions
demonstrate_clarification()
Lines 215-349
Purpose:
Demonstrate clarification and disambiguation
Key Concepts Summary
Pattern Overview
The Clarification pattern provides a structured approach to building AI agents with specific capabilities and behaviors. This implementation leverages LangChain’s composable components to create a robust and maintainable solution.
Core Components
- Agent Class: Main implementation of the pattern logic
- Prompt Engineering: Carefully crafted prompts to guide LLM behavior
- Tool Integration: Optional tools for extended functionality
- Memory Management: State handling across interactions
- Output Parsing: Structured response processing
When to Use
ā Good for: – Scenarios requiring this specific pattern’s strengths – Applications needing structured agent behavior – Systems where explainability is important – Production environments requiring reliability
ā Not ideal for: – Simple single-prompt tasks – Scenarios requiring different pattern characteristics – Resource-constrained environments (if computationally intensive)
Best Practices Demonstrated
1. Environment Configuration
- ā
Use
.envfiles for API keys - ā Never hardcode credentials
- ā Validate environment variables on startup
2. Error Handling
- ā Graceful degradation on failures
- ā Informative error messages
- ā Logging for debugging
3. Prompt Engineering
- ā Clear, specific instructions
- ā Structured output formats
- ā Few-shot examples when beneficial
4. Code Organization
- ā Separation of concerns (class-based design)
- ā Type hints for clarity
- ā Docstrings for documentation
5. Performance Optimization
- ā Appropriate temperature settings
- ā Token budget management
- ā Caching where applicable
LangChain Components Used
- ChatOpenAI: OpenAI model interface
- Chains: Sequential component composition
Why LangChain? – Composable abstractions for LLM applications – Rich ecosystem of integrations – Production-ready patterns – Active community and development
Execution Flow
1. Initialize agent with configuration
ā
2. Load environment and dependencies
ā
3. Prepare prompt with input data
ā
4. Invoke LLM through LangChain
ā
5. Parse and validate response
ā
6. Return formatted result
Key Decision Points: – Model selection (temperature, model type) – Prompt structure (few-shot vs zero-shot) – Error handling strategy – Output format validation
Performance Considerations
Computational Cost
- LLM Calls: Primary cost factor (based on tokens)
- Latency: Depends on model and input size
- Memory: Minimal for most patterns
Optimization Strategies
- Prompt Optimization: Minimize tokens while maintaining clarity
- Caching: Cache repeated queries/responses
- Model Selection: Use smaller models when appropriate
- Batch Processing: Group similar requests
- Streaming: For long responses, stream tokens
Cost Estimates (Approximate)
- GPT-3.5-turbo: ~$0.002 per request
- GPT-4: ~$0.03 per request
- GPT-4-turbo: ~$0.01 per request
Actual costs vary based on input/output token counts
Common Pitfalls to Avoid
1. Prompt Design Issues
ā Vague or ambiguous instructions
ā
Clear, specific, testable prompts
2. Error Handling
ā Ignoring API errors or rate limits
ā
Implement retry logic and graceful degradation
3. Token Management
ā Exceeding model token limits
ā
Truncate inputs, chunk processing
4. Security
ā Exposing API keys in code
ā
Use environment variables
5. Testing
ā Only testing happy paths
ā
Test edge cases, failures, malformed inputs
6. Cost Management
ā Unmonitored API usage
ā
Implement budgets, alerts, and monitoring
Further Improvements
Production Enhancements
- Monitoring: Add logging, metrics, tracing
- Validation: Input/output schema validation
- Rate Limiting: Implement request throttling
- Caching: Redis or in-memory cache for responses
- Async Support: Non-blocking operations for scalability
Feature Extensions
- Multi-Model Support: Switch between providers
- Fallback Models: Graceful degradation strategy
- Custom Tools: Domain-specific function calling
- Advanced Memory: Vector stores for long-term memory
- Evaluation: Automated testing and benchmarking
Code Quality
- Testing: Unit tests, integration tests
- Documentation: API docs, usage examples
- Type Safety: Stricter type hints
- Configuration: Externalized config files
Related Patterns
- Pattern 128
- Pattern 130
Pattern Families: – Reasoning Patterns (001-011) – Multi-Agent Patterns (012-019) – Tool Use Patterns (020-025) – Memory Patterns (026-031) – And many more…
Summary
The Clarification pattern provides a powerful approach to building AI agents with specific capabilities. This implementation demonstrates:
ā Key Strengths: – Clean, maintainable code structure – LangChain integration for composability – Type hints and documentation – Production-ready patterns
šÆ Best Use Cases: – Applications requiring this pattern’s characteristics – Systems needing structured agent behavior – Production environments requiring reliability
š Learning Resources: – LangChain Documentation: https://python.langchain.com/ – Pattern Documentation: See related patterns – OpenAI API Reference: https://platform.openai.com/docs/
File: 129_clarification.py
Total Lines: 354
Pattern Category: AI Agent Design Pattern #129
Generated from actual implementation code
For educational and reference purposes