"""
Pattern 50: Probabilistic Reasoning Pattern
Reasons under uncertainty using probability theory.
Features Bayesian inference, belief updates, and probabilistic queries.
"""
from typing import Dict, Any, List, Optional, Tuple
from dataclasses import dataclass, field
from collections import defaultdict
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
@dataclass
class ProbabilityDistribution:
"""Discrete probability distribution."""
variable: str
probabilities: Dict[Any, float]
def normalize(self):
"""Normalize probabilities to sum to 1."""
total = sum(self.probabilities.values())
if total > 0:
for key in self.probabilities:
self.probabilities[key] /= total
def get_prob(self, value: Any) -> float:
"""Get probability of a value."""
return self.probabilities.get(value, 0.0)
def most_likely(self) -> Tuple[Any, float]:
"""Get most likely value."""
if not self.probabilities:
return None, 0.0
max_val = max(self.probabilities.items(), key=lambda x: x[1])
return max_val
@dataclass
class Evidence:
"""Observed evidence."""
variable: str
value: Any
confidence: float = 1.0
class BayesianNetwork:
"""Simple Bayesian network for probabilistic reasoning."""
def __init__(self):
self.variables: Dict[str, ProbabilityDistribution] = {}
self.conditionals: Dict[str, Dict[Tuple, float]] = defaultdict(dict)
def add_prior(self, distribution: ProbabilityDistribution):
"""Add prior probability distribution."""
distribution.normalize()
self.variables[distribution.variable] = distribution
def add_conditional(self, variable: str, given_var: str,
given_value: Any, var_value: Any, probability: float):
"""Add conditional probability P(variable=var_value | given_var=given_value)."""
self.conditionals[variable][(given_var, given_value, var_value)] = probability
def query(self, variable: str, evidence: List[Evidence]) -> ProbabilityDistribution:
"""Query probability of variable given evidence (Bayesian inference)."""
if variable not in self.variables:
return ProbabilityDistribution(variable, {})
# Start with prior
posterior = self.variables[variable].probabilities.copy()
# Update with each piece of evidence using Bayes' rule
for ev in evidence:
if ev.variable == variable:
# Direct evidence
for value in list(posterior.keys()):
if value != ev.value:
posterior[value] *= (1 - ev.confidence)
else:
posterior[value] *= ev.confidence
else:
# Conditional evidence
for value in posterior.keys():
# P(variable=value | evidence)
conditional_key = (ev.variable, ev.value, value)
if conditional_key in self.conditionals[variable]:
likelihood = self.conditionals[variable][conditional_key]
posterior[value] *= likelihood * ev.confidence
result = ProbabilityDistribution(variable, posterior)
result.normalize()
return result
class ProbabilisticAgent:
"""Agent that reasons probabilistically."""
def __init__(self, name: str, model_name: str = "gpt-4"):
self.name = name
self.llm = ChatOpenAI(model=model_name, temperature=0.3)
self.belief_network = BayesianNetwork()
self.queries_made = 0
def update_beliefs(self, evidence: List[Evidence]):
"""Update beliefs based on evidence."""
print(f"\n {self.name}: Updating beliefs with evidence:")
for ev in evidence:
print(f" - {ev.variable} = {ev.value} (confidence: {ev.confidence:.2f})")
def query_belief(self, variable: str, evidence: List[Evidence]) -> ProbabilityDistribution:
"""Query belief about variable."""
self.queries_made += 1
print(f"\n {self.name}: Querying belief about '{variable}'")
posterior = self.belief_network.query(variable, evidence)
print(f" Posterior distribution:")
for value, prob in sorted(posterior.probabilities.items(),
key=lambda x: x[1], reverse=True):
print(f" {value}: {prob:.3f}")
return posterior
def make_decision(self, variable: str, evidence: List[Evidence]) -> Tuple[Any, float]:
"""Make decision based on probabilistic reasoning."""
posterior = self.query_belief(variable, evidence)
decision, confidence = posterior.most_likely()
print(f"\n {self.name}: Decision: {decision} (confidence: {confidence:.3f})")
return decision, confidence
class ProbabilisticReasoningPattern:
"""
Probabilistic Reasoning Pattern - Reason under uncertainty.
Agents use Bayesian inference to update beliefs and make decisions.
Handles uncertain evidence and probabilistic queries.
"""
def __init__(self):
self.agents: Dict[str, ProbabilisticAgent] = {}
def register_agent(self, agent: ProbabilisticAgent):
"""Register probabilistic agent."""
self.agents[agent.name] = agent
def run(self, scenarios: List[Dict[str, Any]]) -> Dict[str, Any]:
"""Execute probabilistic reasoning."""
print("=== Probabilistic Reasoning Pattern Demo ===\n")
decisions_made = 0
for scenario in scenarios:
print(f"\nScenario: {scenario.get('description', 'Unknown')}")
query_var = scenario.get("query")
evidence_list = [
Evidence(ev["variable"], ev["value"], ev.get("confidence", 1.0))
for ev in scenario.get("evidence", [])
]
for agent in self.agents.values():
agent.update_beliefs(evidence_list)
agent.make_decision(query_var, evidence_list)
decisions_made += 1
return {
"pattern": "ProbabilisticReasoning",
"total_agents": len(self.agents),
"scenarios": len(scenarios),
"decisions_made": decisions_made
}
# Example usage
if __name__ == "__main__":
print("=== Probabilistic Reasoning Pattern Demo ===\n")
# Create pattern
pattern = ProbabilisticReasoningPattern()
# Create agent
print("1. Creating probabilistic agent...")
agent = ProbabilisticAgent("DiagnosticAgent")
# Define probability model
print("\n2. Building Bayesian network...")
# Prior: Disease prevalence
agent.belief_network.add_prior(ProbabilityDistribution(
variable="disease",
probabilities={"flu": 0.1, "cold": 0.3, "covid": 0.05, "healthy": 0.55}
))
# Conditionals: P(symptom | disease)
# P(fever | disease)
agent.belief_network.add_conditional("disease", "symptom", "fever", "flu", 0.8)
agent.belief_network.add_conditional("disease", "symptom", "fever", "cold", 0.3)
agent.belief_network.add_conditional("disease", "symptom", "fever", "covid", 0.9)
agent.belief_network.add_conditional("disease", "symptom", "fever", "healthy", 0.1)
# P(cough | disease)
agent.belief_network.add_conditional("disease", "symptom", "cough", "flu", 0.6)
agent.belief_network.add_conditional("disease", "symptom", "cough", "cold", 0.8)
agent.belief_network.add_conditional("disease", "symptom", "cough", "covid", 0.7)
agent.belief_network.add_conditional("disease", "symptom", "cough", "healthy", 0.1)
# P(fatigue | disease)
agent.belief_network.add_conditional("disease", "symptom", "fatigue", "flu", 0.9)
agent.belief_network.add_conditional("disease", "symptom", "fatigue", "cold", 0.4)
agent.belief_network.add_conditional("disease", "symptom", "fatigue", "covid", 0.8)
agent.belief_network.add_conditional("disease", "symptom", "fatigue", "healthy", 0.2)
pattern.register_agent(agent)
# Test scenarios
print("\n3. Running diagnostic scenarios...")
scenarios = [
{
"description": "Patient with fever only",
"query": "disease",
"evidence": [
{"variable": "symptom", "value": "fever", "confidence": 0.9}
]
},
{
"description": "Patient with fever and cough",
"query": "disease",
"evidence": [
{"variable": "symptom", "value": "fever", "confidence": 0.9},
{"variable": "symptom", "value": "cough", "confidence": 0.8}
]
},
{
"description": "Patient with all symptoms",
"query": "disease",
"evidence": [
{"variable": "symptom", "value": "fever", "confidence": 0.9},
{"variable": "symptom", "value": "cough", "confidence": 0.8},
{"variable": "symptom", "value": "fatigue", "confidence": 0.85}
]
}
]
summary = pattern.run(scenarios)
print(f"\n4. Summary:")
print(f" Scenarios: {summary['scenarios']}")
print(f" Decisions Made: {summary['decisions_made']}")
print(f" Queries: {agent.queries_made}")
print("\nā Probabilistic reasoning handled uncertainty!")
Agentic Architecture Pattern: Probabilistic Reasoning
Pattern 50: 50 Probabilistic Reasoning – Line-by-Line Explanation
Overview
Pattern 50: Probabilistic Reasoning Pattern
Reasons under uncertainty using probability theory. Features Bayesian inference, belief updates, and probabilistic queries.
Code Structure Analysis
File Information
- Pattern Number: 50
- Pattern Name: 50 Probabilistic Reasoning
- File Path:
patterns\decision_making\50_probabilistic_reasoning.py - Total Lines: 256
Detailed Code Explanation
Module Docstring
"""
Pattern 50: Probabilistic Reasoning Pattern
Reasons under uncertainty using probability theory.
Features Bayesian inference, belief updates, and probabilistic queries.
"""
Explanation: This module docstring describes the purpose and key features of the 50 Probabilistic Reasoning pattern.
Imports Section
from typing import Dict, Any, List, Optional, Tuple
from dataclasses import dataclass, field
from collections import defaultdict
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI # First 20 imports shown
Explanation: The module imports necessary dependencies:
– from typing import Dict, Any, List, Optional, Tuple: Type hints for better code documentation
– from dataclasses import dataclass, field: Data class decorators for clean data structures
– from langchain_core.prompts import ChatPromptTemplate: LangChain framework integration
– from langchain_openai import ChatOpenAI: LangChain framework integration
Classes
ProbabilityDistribution (Line 16)
Description: Discrete probability distribution.
Methods:
normalize (Line 21)
def normalize(self):
"""Normalize probabilities to sum to 1."""
Purpose: Normalize probabilities to sum to 1.
Parameters:
– self: Instance reference
get_prob (Line 28)
def get_prob(self, value):
"""Get probability of a value."""
Purpose: Get probability of a value.
Parameters:
– self: Instance reference
– value: Parameter for value
most_likely (Line 32)
def most_likely(self):
"""Get most likely value."""
Purpose: Get most likely value.
Parameters:
– self: Instance reference
Evidence (Line 41)
Description: Observed evidence.
BayesianNetwork (Line 48)
Description: Simple Bayesian network for probabilistic reasoning.
Methods:
__init__ (Line 51)
def __init__(self):
"""No method docstring."""
Purpose: No method docstring.
Parameters:
– self: Instance reference
add_prior (Line 55)
def add_prior(self, distribution):
"""Add prior probability distribution."""
Purpose: Add prior probability distribution.
Parameters:
– self: Instance reference
– distribution: Parameter for distribution
add_conditional (Line 60)
def add_conditional(self, variable, given_var, given_value, var_value, probability):
"""Add conditional probability P(variable=var_value | given_var=given_value)."""
Purpose: Add conditional probability P(variable=var_value | given_var=given_value).
Parameters:
– self: Instance reference
– variable: Parameter for variable
– given_var: Parameter for given_var
– given_value: Parameter for given_value
– var_value: Parameter for var_value
– probability: Parameter for probability
query (Line 65)
def query(self, variable, evidence):
"""Query probability of variable given evidence (Bayesian inference)."""
Purpose: Query probability of variable given evidence (Bayesian inference).
Parameters:
– self: Instance reference
– variable: Parameter for variable
– evidence: Parameter for evidence
ProbabilisticAgent (Line 96)
Description: Agent that reasons probabilistically.
Methods:
__init__ (Line 99)
def __init__(self, name, model_name):
"""No method docstring."""
Purpose: No method docstring.
Parameters:
– self: Instance reference
– name: Identifier or label
– model_name: LLM model to use (e.g., “gpt-4”)
update_beliefs (Line 105)
def update_beliefs(self, evidence):
"""Update beliefs based on evidence."""
Purpose: Update beliefs based on evidence.
Parameters:
– self: Instance reference
– evidence: Parameter for evidence
query_belief (Line 111)
def query_belief(self, variable, evidence):
"""Query belief about variable."""
Purpose: Query belief about variable.
Parameters:
– self: Instance reference
– variable: Parameter for variable
– evidence: Parameter for evidence
make_decision (Line 125)
def make_decision(self, variable, evidence):
"""Make decision based on probabilistic reasoning."""
Purpose: Make decision based on probabilistic reasoning.
Parameters:
– self: Instance reference
– variable: Parameter for variable
– evidence: Parameter for evidence
ProbabilisticReasoningPattern (Line 134)
Description: Probabilistic Reasoning Pattern – Reason under uncertainty.
Agents use Bayesian inference to update beliefs and make decisions. Handles uncertain evidence and probabilistic queries.
Methods:
__init__ (Line 142)
def __init__(self):
"""No method docstring."""
Purpose: No method docstring.
Parameters:
– self: Instance reference
register_agent (Line 145)
def register_agent(self, agent):
"""Register probabilistic agent."""
Purpose: Register probabilistic agent.
Parameters:
– self: Instance reference
– agent: Parameter for agent
run (Line 149)
def run(self, scenarios):
"""Execute probabilistic reasoning."""
Purpose: Execute probabilistic reasoning.
Parameters:
– self: Instance reference
– scenarios: Parameter for scenarios
Design Patterns Used
- Strategy Pattern: Different execution strategies for various scenarios
- State Pattern: Managing different states in the workflow
- Chain of Responsibility: Sequential processing through workflow nodes
- Observer Pattern: Tracking and monitoring pattern execution
- Factory Pattern: Creating instances with proper configuration
Usage Example
# Initialize the pattern
pattern = ProbabilityDistribution(name="example", model_name="gpt-4")
# Configure and execute
result = pattern.execute(data={"key": "value"})
# Check results
print(result)
Key Concepts
- LLM Integration: Uses LangChain/OpenAI for intelligent decision-making
- Workflow Orchestration: LangGraph manages execution flow through nodes
- State Management: TypedDict defines workflow state structure
- Error Handling: Comprehensive error handling and fallback mechanisms
- Extensibility: Designed for easy customization and extension
Extension Points
This pattern can be extended by: 1. Adding custom workflow nodes 2. Implementing additional validation logic 3. Integrating with external services 4. Customizing LLM prompts and responses 5. Adding monitoring and logging capabilities
Leave a Reply