08: Temperature and Sampling Parameters

Chapter 08: Temperature and Sampling Parameters
Section titled “Chapter 08: Temperature and Sampling Parameters”Overview
Section titled “Overview”Temperature, top_p, and top_k are the control knobs that determine how predictable or creative Claude’s outputs will be. Understanding these parameters transforms your AI from a one-size-fits-all assistant into a precision tool that produces exactly the right balance of consistency and creativity for each use case.
This chapter teaches you how sampling works under the hood, when to use high vs low temperature, how to combine temperature with top_p and top_k, and how to choose the right parameters for different applications using the Claude-PHP-SDK.
By the end, you’ll confidently configure Claude for deterministic tasks like data extraction, creative tasks like content generation, and everything in between.
Prerequisites
Section titled “Prerequisites”Before starting, ensure you understand:
- ✓ Basic Claude API usage (Chapters 00-03)
- ✓ Prompt engineering fundamentals (Chapter 05)
- ✓ System prompts and role definition (Chapter 07)
- ✓ Basic probability concepts
Estimated Time: 45-60 minutes
What You’ll Build
Section titled “What You’ll Build”By the end of this chapter, you will have created:
- A
TemperatureGuideclass that recommends optimal temperature settings for different use cases - A
SamplingConfigManagerfor managing and validating sampling parameter configurations - A
DataExtractorclass using deterministic settings (temperature 0.0) for reliable data extraction - A
CreativeWriterclass using high temperature (1.5+) for generating unique content variations - A
CodeGeneratorclass using focused settings (temperature 0.3) for consistent code generation - An
AdaptiveAssistantthat automatically adjusts temperature based on message content - A
ConsistencyTestertool for measuring output consistency across different temperature settings - A
SamplingABTesterfor systematically testing and comparing different parameter configurations - A
SamplingCostAnalyzerto understand cost implications of different sampling strategies - Understanding of how stop sequences interact with sampling parameters
Objectives
Section titled “Objectives”By the end of this chapter, you will:
- Understand how language model sampling works at the token level
- Master temperature parameter control (0.0 = deterministic, 2.0 = creative)
- Learn top-p (nucleus sampling) and how it filters token choices
- Understand top-k sampling and when to use it
- Combine temperature, top_p, and top_k for fine-grained control
- Choose optimal sampling parameters for different use cases (extraction, generation, code)
- Build adaptive systems that adjust parameters based on context
- Measure and validate output consistency for production applications
- Test sampling parameters systematically using A/B testing frameworks
- Understand cost and performance implications of different sampling strategies
- Apply model-specific optimal parameters for different Claude models (Sonnet 4.5, Opus 4.1)
How Language Model Sampling Works
Section titled “How Language Model Sampling Works”Token Prediction Fundamentals
Section titled “Token Prediction Fundamentals”<?phpdeclare(strict_types=1);
/** * Conceptual demonstration of how Claude predicts the next token * * When Claude generates text, it: * 1. Looks at all tokens generated so far * 2. Calculates probability for EVERY possible next token * 3. Uses sampling parameters to choose which token to output * 4. Adds that token to the sequence * 5. Repeats until complete */
// Simplified example: Claude is completing "The best PHP framework is"// Here are the top predicted tokens and their probabilities:
$tokenProbabilities = [ 'Laravel' => 0.45, // 45% probability 'Symfony' => 0.25, // 25% 'CodeIgniter' => 0.10, // 10% 'Yii' => 0.08, // 8% 'Laminas' => 0.05, // 5% 'Slim' => 0.04, // 4% 'CakePHP' => 0.03, // 3% // ... thousands of other tokens with tiny probabilities];
// Different sampling strategies will choose different tokens// Let's simulate this:
function greedySampling(array $probs): string{ // Always pick the highest probability token arsort($probs); return array_key_first($probs);}
function temperatureSampling(array $probs, float $temperature): string{ // Adjust probabilities based on temperature $adjusted = []; foreach ($probs as $token => $prob) { // Higher temperature = flatter distribution (more random) // Lower temperature = sharper distribution (more deterministic) $adjusted[$token] = pow($prob, 1 / $temperature); }
// Normalize $sum = array_sum($adjusted); $normalized = array_map(fn($p) => $p / $sum, $adjusted);
// Sample randomly based on adjusted probabilities return weightedRandomChoice($normalized);}
function weightedRandomChoice(array $probabilities): string{ $rand = mt_rand() / mt_getrandmax(); $cumulative = 0;
foreach ($probabilities as $token => $probability) { $cumulative += $probability; if ($rand <= $cumulative) { return $token; } }
return array_key_first($probabilities);}
// Demonstrate different sampling strategiesecho "Original probabilities:\n";print_r($tokenProbabilities);echo "\n";
echo "Greedy sampling (always picks highest): ";echo greedySampling($tokenProbabilities) . "\n\n";
echo "Temperature = 0.3 (deterministic): ";echo temperatureSampling($tokenProbabilities, 0.3) . "\n";
echo "Temperature = 1.0 (balanced): ";echo temperatureSampling($tokenProbabilities, 1.0) . "\n";
echo "Temperature = 2.0 (creative): ";echo temperatureSampling($tokenProbabilities, 2.0) . "\n";Key Insight: Temperature doesn’t change what Claude knows, it changes which tokens get selected from the probability distribution.
::: tip Best Practice Start with the default temperature (1.0) and adjust based on your needs. Lower temperature for consistency, higher for creativity. Most production applications use temperatures between 0.0 and 1.5. :::
Temperature Parameter
Section titled “Temperature Parameter”What Temperature Controls
Section titled “What Temperature Controls”<?phpdeclare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
$prompt = 'Complete this sentence: The future of PHP is';
// Test different temperatures$temperatures = [0.0, 0.5, 1.0, 1.5, 2.0];
foreach ($temperatures as $temp) { echo "Temperature {$temp}:\n";
// Generate 3 completions to see variation for ($i = 1; $i <= 3; $i++) { $response = $client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 50, 'temperature' => $temp, 'messages' => [[ 'role' => 'user', 'content' => $prompt ]] );
echo " {$i}. " . ($response->content[0]->text ?? '') . "\n"; } echo "\n";}Expected pattern:
Temperature 0.0: 1. bright, with continued evolution... 2. bright, with continued evolution... 3. bright, with continued evolution... (Nearly identical - very deterministic)
Temperature 1.0: 1. bright, with continued evolution... 2. promising as the language evolves... 3. strong, particularly with modern features... (Some variation but still coherent)
Temperature 2.0: 1. absolutely revolutionary with quantum... 2. in serverless edge computing... 3. tied to blockchain and metaverse... (Much more creative/unpredictable)Temperature Scale Guide
Section titled “Temperature Scale Guide”<?phpdeclare(strict_types=1);
class TemperatureGuide{ public const DETERMINISTIC = 0.0; // Absolute consistency public const FOCUSED = 0.3; // Minimal variation public const BALANCED = 1.0; // Default, natural public const CREATIVE = 1.5; // More variety public const EXPERIMENTAL = 2.0; // Maximum creativity
public static function recommend(string $useCase): float { return match($useCase) { // Deterministic tasks 'data_extraction', 'json_parsing', 'structured_output', 'classification', 'fact_checking' => self::DETERMINISTIC,
// Focused but slightly flexible 'code_review', 'technical_documentation', 'translation', 'summarization' => self::FOCUSED,
// Balanced natural language 'general_qa', 'explanation', 'tutoring', 'conversational' => self::BALANCED,
// Creative tasks 'brainstorming', 'content_generation', 'story_writing', 'marketing_copy' => self::CREATIVE,
// Highly experimental 'ideation', 'creative_writing', 'unusual_perspectives' => self::EXPERIMENTAL,
default => self::BALANCED, }; }
public static function describe(float $temperature): string { return match(true) { $temperature < 0.3 => 'Highly deterministic - minimal variation', $temperature < 0.7 => 'Mostly deterministic - slight variation', $temperature < 1.2 => 'Balanced - natural variation', $temperature < 1.7 => 'Creative - increased variation', default => 'Highly creative - maximum variation', }; }}
// Usage examples$useCases = [ 'Extract contact info from business card', 'Write creative marketing tagline', 'Explain how Laravel routing works', 'Generate unique product descriptions', 'Parse JSON from unstructured text',];
foreach ($useCases as $useCase) { $category = match(true) { str_contains($useCase, 'Extract') => 'data_extraction', str_contains($useCase, 'creative') => 'content_generation', str_contains($useCase, 'Explain') => 'explanation', str_contains($useCase, 'Generate') => 'brainstorming', str_contains($useCase, 'Parse') => 'structured_output', default => 'general_qa' };
$temp = TemperatureGuide::recommend($category); $desc = TemperatureGuide::describe($temp);
echo "Use case: {$useCase}\n"; echo "Recommended 'temperature' => {$temp} ({$desc})\n\n";}Top-P (Nucleus Sampling)
Section titled “Top-P (Nucleus Sampling)”Understanding Top-P
Section titled “Understanding Top-P”Top-p (also called nucleus sampling) considers only the most probable tokens whose cumulative probability reaches the threshold p.
::: info
The default top_p value is typically 0.9, which works well for most use cases. Lower values (0.5-0.8) create more focused outputs, while higher values (0.95-1.0) allow more diversity.
:::
<?phpdeclare(strict_types=1);
/** * Demonstrates how top_p filters token choices */
// Token probabilities from Claude's prediction$tokenProbabilities = [ 'Laravel' => 0.35, 'Symfony' => 0.25, 'CodeIgniter' => 0.15, 'Yii' => 0.10, 'Laminas' => 0.05, 'Slim' => 0.04, 'CakePHP' => 0.03, 'Phalcon' => 0.02, 'FuelPHP' => 0.01,];
function applyTopP(array $probs, float $topP): array{ // Sort by probability descending arsort($probs);
$cumulative = 0; $filtered = [];
foreach ($probs as $token => $prob) { $cumulative += $prob; $filtered[$token] = $prob;
if ($cumulative >= $topP) { break; } }
return $filtered;}
// Compare different top_p values$topPValues = [0.5, 0.8, 0.9, 1.0];
foreach ($topPValues as $topP) { echo "top_p = {$topP}:\n";
$filtered = applyTopP($tokenProbabilities, $topP);
echo " Tokens considered: " . count($filtered) . "\n"; echo " Options: " . implode(', ', array_keys($filtered)) . "\n"; echo " Cumulative probability: " . round(array_sum($filtered) * 100, 1) . "%\n\n";}Output:
top_p = 0.5: Tokens considered: 2 Options: Laravel, Symfony Cumulative probability: 60%
top_p = 0.8: Tokens considered: 4 Options: Laravel, Symfony, CodeIgniter, Yii Cumulative probability: 85%
top_p = 0.9: Tokens considered: 5 Options: Laravel, Symfony, CodeIgniter, Yii, Laminas Cumulative probability: 90%
top_p = 1.0: Tokens considered: 9 Options: (all) Cumulative probability: 100%Top-P in Practice
Section titled “Top-P in Practice”<?phpdeclare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
function testTopP(ClaudePhp $client, float $topP): array{ $responses = [];
for ($i = 0; $i < 3; $i++) { $response = $client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 100, 'temperature' => 1.0, // Keep temperature constant 'top_p' => $topP, 'messages' => [[ 'role' => 'user', 'content' => 'Name 3 unique PHP frameworks:' ]] );
$responses[] = $response->content[0]->text ?? ''; }
return $responses;}
// Compare different top_p valuesecho "top_p = 0.5 (conservative):\n";$responses = testTopP($client, 0.5);foreach ($responses as $i => $resp) { echo " " . ($i + 1) . ". " . substr($resp, 0, 100) . "...\n";}echo "\n";
echo "top_p = 0.9 (standard):\n";$responses = testTopP($client, 0.9);foreach ($responses as $i => $resp) { echo " " . ($i + 1) . ". " . substr($resp, 0, 100) . "...\n";}echo "\n";
echo "top_p = 1.0 (all options):\n";$responses = testTopP($client, 1.0);foreach ($responses as $i => $resp) { echo " " . ($i + 1) . ". " . substr($resp, 0, 100) . "...\n";}Top-K Sampling
Section titled “Top-K Sampling”Understanding Top-K
Section titled “Understanding Top-K”Top-k limits consideration to only the k most probable tokens.
<?phpdeclare(strict_types=1);
/** * Top-k is simpler than top-p: just take the top k tokens */
function applyTopK(array $probs, int $topK): array{ // Sort by probability descending arsort($probs);
// Take only top k tokens return array_slice($probs, 0, $topK, true);}
$tokenProbabilities = [ 'Laravel' => 0.35, 'Symfony' => 0.25, 'CodeIgniter' => 0.15, 'Yii' => 0.10, 'Laminas' => 0.05, 'Slim' => 0.04, 'CakePHP' => 0.03, 'Phalcon' => 0.02, 'FuelPHP' => 0.01,];
$topKValues = [1, 3, 5, 10];
foreach ($topKValues as $k) { echo "top_k = {$k}:\n";
$filtered = applyTopK($tokenProbabilities, $k);
echo " Options: " . implode(', ', array_keys($filtered)) . "\n"; echo " Probability coverage: " . round(array_sum($filtered) * 100, 1) . "%\n\n";}Output:
top_k = 1: Options: Laravel Probability coverage: 35% (Most deterministic - only best option)
top_k = 3: Options: Laravel, Symfony, CodeIgniter Probability coverage: 75%
top_k = 5: Options: Laravel, Symfony, CodeIgniter, Yii, Laminas Probability coverage: 90%
top_k = 10: Options: (all 9 tokens) Probability coverage: 100%Top-K Usage
Section titled “Top-K Usage”<?phpdeclare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
// Note: Claude API doesn't expose top_k as directly as some models// But understanding it helps grasp sampling mechanics
// Conceptual usage (if supported by SDK/Model):$response = $client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 200, 'temperature' => 1.0, topK: 40, // Consider only top 40 tokens at each step 'messages' => [[ 'role' => 'user', 'content' => 'Generate a creative function name for user authentication' ]]);
// Lower top_k = more focused/conventional// Higher top_k = more creative/unusualCombining Sampling Parameters
Section titled “Combining Sampling Parameters”Temperature + Top-P Interaction
Section titled “Temperature + Top-P Interaction”<?phpdeclare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
class SamplingStrategy{ public function __construct( public readonly float $temperature, public readonly float $topP, public readonly string $description, public readonly array $bestFor ) {}}
class SamplingPresets{ public const STRATEGIES = [ 'deterministic' => [ 'temperature' => 0.0, 'top_p' => 1.0, 'description' => 'Maximum consistency, minimal variation', 'best_for' => ['data extraction', 'JSON parsing', 'classification'] ],
'focused' => [ 'temperature' => 0.3, 'top_p' => 0.8, 'description' => 'Consistent but not robotic', 'best_for' => ['code review', 'documentation', 'translation'] ],
'balanced' => [ 'temperature' => 1.0, 'top_p' => 0.9, 'description' => 'Natural variation, good for most tasks', 'best_for' => ['conversation', 'explanation', 'Q&A'] ],
'creative' => [ 'temperature' => 1.3, 'top_p' => 0.95, 'description' => 'Increased creativity while staying coherent', 'best_for' => ['brainstorming', 'content generation', 'writing'] ],
'experimental' => [ 'temperature' => 1.8, 'top_p' => 1.0, 'description' => 'Maximum creativity and exploration', 'best_for' => ['ideation', 'creative writing', 'novel solutions'] ], ];
public static function get(string $name): SamplingStrategy { $config = self::STRATEGIES[$name] ?? self::STRATEGIES['balanced'];
return new SamplingStrategy( 'temperature' => $config['temperature'], topP: $config['top_p'], description: $config['description'], bestFor: $config['best_for'] ); }
public static function forTask(string $task): SamplingStrategy { $task = strtolower($task);
foreach (self::STRATEGIES as $name => $config) { foreach ($config['best_for'] as $useCase) { if (str_contains($task, $useCase)) { return self::get($name); } } }
return self::get('balanced'); }}
// Usage$strategy = SamplingPresets::get('creative');
$response = $client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 500, 'temperature' => $strategy->temperature, topP: $strategy->topP, 'messages' => [[ 'role' => 'user', 'content' => 'Generate unique variable names for a payment processing system' ]]);
echo "Using strategy: {$strategy->description}\n";echo "Temperature: {$strategy->temperature}, Top-p: {$strategy->topP}\n\n";echo $response->content[0]->text ?? '';Configuration Manager
Section titled “Configuration Manager”<?phpdeclare(strict_types=1);
namespace CodeWithPHP\Claude;
class SamplingConfigManager{ private array $configs = []; private string $currentConfig = 'default';
public function __construct() { // Load default configurations $this->registerConfig('default', [ 'temperature' => 1.0, 'top_p' => 0.9, ]);
$this->registerConfig('deterministic', [ 'temperature' => 0.0, 'top_p' => 1.0, ]);
$this->registerConfig('creative', [ 'temperature' => 1.5, 'top_p' => 0.95, ]); }
public function registerConfig(string $name, array $config): void { $this->validateConfig($config); $this->configs[$name] = $config; }
public function useConfig(string $name): void { if (!isset($this->configs[$name])) { throw new \InvalidArgumentException("Config '{$name}' not found"); } $this->currentConfig = $name; }
public function getConfig(?string $name = null): array { $name = $name ?? $this->currentConfig; return $this->configs[$name] ?? $this->configs['default']; }
public function mergeConfig(array $overrides): array { return array_merge($this->getConfig(), $overrides); }
private function validateConfig(array $config): void { if (isset($config['temperature'])) { $temp = $config['temperature']; if ($temp < 0 || $temp > 2) { throw new \InvalidArgumentException('Temperature must be between 0 and 2'); } }
if (isset($config['top_p'])) { $topP = $config['top_p']; if ($topP < 0 || $topP > 1) { throw new \InvalidArgumentException('top_p must be between 0 and 1'); } } }
public function listConfigs(): array { return array_keys($this->configs); }}
// Usagerequire __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
$manager = new SamplingConfigManager();
// Register custom config$manager->registerConfig('code_generation', [ 'temperature' => 0.4, 'top_p' => 0.85,]);
// Use a config$manager->useConfig('code_generation');$configParams = $manager->getConfig();
// Using named arguments with array unpacking (PHP 8.1+)$response = $client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 1024, 'temperature' => $configParams['temperature'], topP: $configParams['top_p'], 'messages' => [[ 'role' => 'user', 'content' => 'Generate a PHP class for user authentication' ]]);Use Case Specific Configurations
Section titled “Use Case Specific Configurations”Data Extraction (Deterministic)
Section titled “Data Extraction (Deterministic)”<?phpdeclare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
class DataExtractor{ public function __construct( private Client $client ) {}
public function extractJSON(string $text, array $schema): array { $schemaDescription = json_encode($schema, JSON_PRETTY_PRINT);
$response = $this->client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 2048, 'temperature' => 0.0, // Maximum determinism topP: 1.0, 'system' => 'Extract structured data as valid JSON. Return ONLY the JSON object, no other text.', 'messages' => [[ 'role' => 'user', 'content' => "Extract data matching this schema:\n\n{$schemaDescription}\n\nFrom this text:\n\n{$text}" ]] );
$json = $response->content[0]->text ?? '';
// Clean potential markdown wrapping if (preg_match('/```json\s*(.*?)\s*```/s', $json, $matches)) { $json = $matches[1]; }
return json_decode($json, true) ?? []; }}
// Usagerequire __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
$extractor = new DataExtractor($client);
$businessCard = <<<TEXTJohn SmithSenior Software EngineerAcme CorporationEmail: john.smith@acme.comPhone: +1-555-123-4567Website: https://acme.comTEXT;
$schema = [ 'name' => 'string', 'title' => 'string', 'company' => 'string', 'email' => 'string', 'phone' => 'string', 'website' => 'string',];
$data = $extractor->extractJSON($businessCard, $schema);print_r($data);
// Run multiple times - should get IDENTICAL results// This is critical for reliable data processingContent Generation (Creative)
Section titled “Content Generation (Creative)”<?phpdeclare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
class CreativeWriter{ public function __construct( private Client $client ) {}
public function generateVariations( string $prompt, int $count = 5, float $temperature = 1.5 ): array { $variations = [];
for ($i = 0; $i < $count; $i++) { $response = $this->client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 500, 'temperature' => $temperature, // High for creativity topP: 0.95, // Broad token consideration 'messages' => [[ 'role' => 'user', 'content' => $prompt ]] );
$variations[] = $response->content[0]->text ?? ''; }
return $variations; }
public function generateUnique(string $prompt, array $previous = []): string { $attempt = 0; $maxAttempts = 10;
while ($attempt < $maxAttempts) { $response = $this->client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 500, 'temperature' => 1.6, // Higher for uniqueness topP: 0.98, 'messages' => [[ 'role' => 'user', 'content' => $prompt . "\n\nGenerate something completely unique and different from these:\n" . implode("\n", $previous) ]] );
$result = $response->content[0]->text ?? '';
// Check similarity against previous $isSimilar = false; foreach ($previous as $prev) { similar_text($prev, $result, $similarity); if ($similarity > 70) { $isSimilar = true; break; } }
if (!$isSimilar) { return $result; }
$attempt++; }
throw new \RuntimeException('Could not generate unique content'); }}
// Usagerequire __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
$writer = new CreativeWriter($client);
echo "Generating 5 creative taglines:\n\n";
$taglines = $writer->generateVariations( prompt: 'Create a catchy tagline for a modern PHP framework focused on developer experience', count: 5, 'temperature' => 1.5);
foreach ($taglines as $i => $tagline) { echo ($i + 1) . ". {$tagline}\n\n";}Code Generation (Focused)
Section titled “Code Generation (Focused)”<?phpdeclare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
class CodeGenerator{ public function __construct( private Client $client ) {}
public function generateFunction( string $description, array $parameters = [], ?string $returnType = null ): string { $paramsList = ''; foreach ($parameters as $name => $type) { $paramsList .= "{$type} \${$name}, "; } $paramsList = rtrim($paramsList, ', ');
$returnHint = $returnType ? ": {$returnType}" : '';
$response = $this->client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 1024, 'temperature' => 0.3, // Low for consistent, reliable code topP: 0.85, // Focused on conventional patterns 'system' => 'Generate clean PHP 8.4+ code following PSR-12 standards. Include type hints, return types, and PHPDoc comments.', 'messages' => [[ 'role' => 'user', 'content' => "Generate a PHP function:\n\nDescription: {$description}\nParameters: {$paramsList}\nReturn type: {$returnHint}\n\nUse declare(strict_types=1) and modern PHP features." ]] );
return $response->content[0]->text ?? ''; }
public function refactorCode(string $code, array $improvements = []): string { $improvementsList = implode("\n", array_map(fn($i) => "- {$i}", $improvements));
$response = $this->client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 2048, 'temperature' => 0.2, // Very focused - we want reliable refactoring topP: 0.8, 'system' => 'Refactor PHP code following best practices. Maintain functionality while improving code quality.', 'messages' => [[ 'role' => 'user', 'content' => "Refactor this code:\n\n```php\n{$code}\n```\n\nFocus on:\n{$improvementsList}" ]] );
return $response->content[0]->text ?? ''; }}
// Usagerequire __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
$generator = new CodeGenerator($client);
$function = $generator->generateFunction( description: 'Validate and sanitize email addresses', parameters: ['email' => 'string'], returnType: 'string|null');
echo $function;Adaptive Temperature Based on Context
Section titled “Adaptive Temperature Based on Context”Dynamic Temperature Adjustment
Section titled “Dynamic Temperature Adjustment”<?phpdeclare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
class AdaptiveAssistant{ public function __construct( private Client $client ) {}
public function respond(string $message): string { $temperature = $this->determineTemperature($message); $topP = $this->determineTopP($message);
$response = $this->client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 2048, 'temperature' => $temperature, 'top_p' => $topP, 'messages' => [[ 'role' => 'user', 'content' => $message ]] );
return $response->content[0]->text ?? ''; }
private function determineTemperature(string $message): float { $message = strtolower($message);
// Deterministic tasks if ($this->contains($message, ['extract', 'parse', 'classify', 'categorize', 'validate'])) { return 0.0; }
// Focused tasks if ($this->contains($message, ['review', 'analyze', 'explain', 'document', 'translate'])) { return 0.3; }
// Creative tasks if ($this->contains($message, ['generate', 'create', 'write', 'brainstorm', 'suggest'])) { return 1.5; }
// Code-related (focused) if ($this->contains($message, ['code', 'function', 'class', 'refactor', 'implement'])) { return 0.4; }
// Default: balanced return 1.0; }
private function determineTopP(string $message): float { $message = strtolower($message);
// Deterministic: consider all options if ($this->contains($message, ['extract', 'parse'])) { return 1.0; }
// Creative: broad consideration if ($this->contains($message, ['generate', 'brainstorm', 'unique'])) { return 0.95; }
// Standard return 0.9; }
private function contains(string $haystack, array $needles): bool { foreach ($needles as $needle) { if (str_contains($haystack, $needle)) { return true; } } return false; }}
// Usagerequire __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
$assistant = new AdaptiveAssistant($client);
// This will use low temperature (deterministic)echo $assistant->respond('Extract email addresses from this text: ...') . "\n\n";
// This will use high temperature (creative)echo $assistant->respond('Generate creative marketing taglines for...') . "\n\n";
// This will use medium-low temperature (focused)echo $assistant->respond('Review this PHP code for issues...') . "\n\n";Stop Sequences and Sampling Interaction
Section titled “Stop Sequences and Sampling Interaction”How Stop Sequences Affect Sampling
Section titled “How Stop Sequences Affect Sampling”Stop sequences interact with sampling parameters in important ways:
<?phpdeclare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
// Stop sequences can help control output length with high temperature// High temperature might generate longer outputs, but stop sequences provide a safety net
$response = $client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 1000, 'temperature' => 1.5, // High creativity topP: 0.95, 'stop_sequences' => ['</response>', '---END---'], // Stop when these appear 'messages' => [[ 'role' => 'user', 'content' => 'Generate a creative product description. End with </response>' ]]);
// Stop sequences work independently of sampling parameters// They provide deterministic stopping points regardless of temperature::: tip Best Practice Use stop sequences with high temperature to prevent runaway generation. Stop sequences provide deterministic control over output length, complementing the creative randomness of high temperature. :::
A/B Testing Sampling Parameters
Section titled “A/B Testing Sampling Parameters”Systematic Parameter Testing
Section titled “Systematic Parameter Testing”For production applications, systematically test different sampling parameters to find optimal settings:
<?phpdeclare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
class SamplingABTester{ public function __construct( private Client $client ) {}
public function testConfigurations( string $prompt, array $configurations, int $samplesPerConfig = 5 ): array { $results = [];
foreach ($configurations as $name => $config) { $responses = []; $totalTokens = 0; $totalTime = 0;
for ($i = 0; $i < $samplesPerConfig; $i++) { $start = microtime(true);
$response = $this->client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 500, 'temperature' => $config['temperature'] ?? 1.0, topP: $config['top_p'] ?? 0.9, 'messages' => [[ 'role' => 'user', 'content' => $prompt ]] );
$totalTime += microtime(true) - $start; $totalTokens += $response->usage->outputTokens ?? 0; $responses[] = $response->content[0]->text ?? ''; }
$results[$name] = [ 'config' => $config, 'responses' => $responses, 'avg_length' => array_sum(array_map('strlen', $responses)) / count($responses), 'avg_tokens' => $totalTokens / $samplesPerConfig, 'avg_time' => $totalTime / $samplesPerConfig, 'consistency' => $this->calculateConsistency($responses), 'uniqueness' => count(array_unique($responses)) / count($responses), ]; }
return $results; }
private function calculateConsistency(array $responses): float { if (count($responses) < 2) { return 1.0; }
$similarities = []; $count = count($responses);
for ($i = 0; $i < $count; $i++) { for ($j = $i + 1; $j < $count; $j++) { similar_text($responses[$i], $responses[$j], $percent); $similarities[] = $percent; } }
return array_sum($similarities) / count($similarities); }
public function recommendBestConfig(array $results, string $priority = 'balanced'): string { $scored = [];
foreach ($results as $name => $result) { $score = match($priority) { 'consistency' => $result['consistency'], 'creativity' => 1 - $result['consistency'], 'cost' => 1 / ($result['avg_tokens'] + 1), 'balanced' => ($result['consistency'] + (1 - $result['consistency']) + (1 / ($result['avg_tokens'] + 1))) / 3, default => $result['consistency'], };
$scored[$name] = $score; }
arsort($scored); return array_key_first($scored); }}
// Usagerequire __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
$tester = new SamplingABTester($client);
$configurations = [ 'deterministic' => ['temperature' => 0.0, 'top_p' => 1.0], 'focused' => ['temperature' => 0.3, 'top_p' => 0.8], 'balanced' => ['temperature' => 1.0, 'top_p' => 0.9], 'creative' => ['temperature' => 1.5, 'top_p' => 0.95],];
$results = $tester->testConfigurations( prompt: 'Generate a product tagline for a PHP framework', configurations: $configurations, samplesPerConfig: 5);
// Find best config for your priority$best = $tester->recommendBestConfig($results, priority: 'balanced');
echo "Recommended configuration: {$best}\n";print_r($results[$best]);Model-Specific Considerations
Section titled “Model-Specific Considerations”Optimal Parameters by Model
Section titled “Optimal Parameters by Model”Different Claude models may have slightly different optimal temperature ranges:
<?phpdeclare(strict_types=1);
class ModelSpecificSampling{ public const MODEL_GUIDELINES = [ 'claude-haiku-4-5-20251001' => [ 'deterministic' => ['temperature' => 0.0, 'top_p' => 1.0], 'balanced' => ['temperature' => 1.0, 'top_p' => 0.9], 'creative' => ['temperature' => 1.3, 'top_p' => 0.95], 'note' => 'Haiku is faster and cheaper - good for high-volume tasks', ], 'claude-sonnet-4-5' => [ 'deterministic' => ['temperature' => 0.0, 'top_p' => 1.0], 'balanced' => ['temperature' => 1.0, 'top_p' => 0.9], 'creative' => ['temperature' => 1.5, 'top_p' => 0.95], 'note' => 'Latest Sonnet model - best quality, use for complex tasks', ], 'claude-opus-4-1' => [ 'deterministic' => ['temperature' => 0.0, 'top_p' => 1.0], 'balanced' => ['temperature' => 1.0, 'top_p' => 0.9], 'creative' => ['temperature' => 1.5, 'top_p' => 0.95], 'note' => 'Most capable model - use for complex reasoning tasks', ], ];
public static function getRecommendedConfig(string $model, string $useCase): array { $guidelines = self::MODEL_GUIDELINES[$model] ?? self::MODEL_GUIDELINES['claude-sonnet-4-5'];
return match($useCase) { 'extraction', 'parsing', 'classification' => $guidelines['deterministic'], 'code', 'review', 'documentation' => ['temperature' => 0.3, 'top_p' => 0.8], 'conversation', 'qa', 'explanation' => $guidelines['balanced'], 'generation', 'brainstorming', 'creative' => $guidelines['creative'], default => $guidelines['balanced'], }; }}
// Usage$config = ModelSpecificSampling::getRecommendedConfig( 'model' => 'claude-sonnet-4-5', useCase: 'extraction');
echo "Recommended config: ";print_r($config);::: info Model Differences While sampling parameters work similarly across Claude models, newer models (like Sonnet 4.5) may handle high temperatures more gracefully than previous generations. Always test with your specific model and use case. :::
Performance and Cost Implications
Section titled “Performance and Cost Implications”Sampling Parameters and Token Usage
Section titled “Sampling Parameters and Token Usage”Higher temperature can lead to longer outputs, which increases token usage and costs:
<?phpdeclare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
class SamplingCostAnalyzer{ public function __construct( private Client $client ) {}
public function analyzeCostImpact( string $prompt, array $temperatures = [0.0, 0.5, 1.0, 1.5, 2.0], int $samples = 5 ): array { $results = [];
foreach ($temperatures as $temp) { $tokens = []; $lengths = [];
for ($i = 0; $i < $samples; $i++) { $response = $this->client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 1000, 'temperature' => $temp, 'messages' => [[ 'role' => 'user', 'content' => $prompt ]] );
$tokens[] = $response->usage->outputTokens ?? 0; $lengths[] = strlen($response->content[0]->text ?? ''); }
$results[] = [ 'temperature' => $temp, 'avg_tokens' => array_sum($tokens) / count($tokens), 'avg_length' => array_sum($lengths) / count($lengths), 'cost_per_1k_requests' => (array_sum($tokens) / count($tokens)) * 1000 * 0.003, // Example pricing ]; }
return $results; }}
// Usagerequire __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
$analyzer = new SamplingCostAnalyzer($client);
$results = $analyzer->analyzeCostImpact( prompt: 'Write a detailed product description', temperatures: [0.0, 1.0, 1.5, 2.0]);
foreach ($results as $result) { echo "Temperature {$result['temperature']}: "; echo "Avg {$result['avg_tokens']} tokens, "; echo "Est. cost per 1K requests: \${$result['cost_per_1k_requests']}\n";}::: warning Cost Consideration Higher temperature often produces longer, more varied outputs, which increases token usage and costs. For high-volume applications, test whether lower temperature with better prompts achieves similar results at lower cost. :::
Measuring Output Consistency
Section titled “Measuring Output Consistency”Consistency Tester
Section titled “Consistency Tester”<?phpdeclare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
class ConsistencyTester{ public function __construct( private Client $client ) {}
public function measureConsistency( string $prompt, float $temperature, int $samples = 10 ): array { $responses = [];
for ($i = 0; $i < $samples; $i++) { $response = $this->client->messages()->create( 'model' => 'claude-sonnet-4-5', 'max_tokens' => 500, 'temperature' => $temperature, 'messages' => [[ 'role' => 'user', 'content' => $prompt ]] );
$responses[] = $response->content[0]->text ?? ''; }
return [ 'responses' => $responses, 'unique_count' => count(array_unique($responses)), 'consistency_score' => $this->calculateConsistency($responses), 'average_length' => array_sum(array_map('strlen', $responses)) / count($responses), ]; }
private function calculateConsistency(array $responses): float { if (count($responses) < 2) { return 1.0; }
$similarities = []; $count = count($responses);
for ($i = 0; $i < $count; $i++) { for ($j = $i + 1; $j < $count; $j++) { similar_text($responses[$i], $responses[$j], $percent); $similarities[] = $percent; } }
return array_sum($similarities) / count($similarities); }
public function findOptimalTemperature( string $prompt, float $targetConsistency = 80.0, float $step = 0.1 ): float { $temperature = 0.0;
while ($temperature <= 2.0) { $result = $this->measureConsistency($prompt, $temperature, 5);
if ($result['consistency_score'] >= $targetConsistency) { return $temperature; }
$temperature += $step; }
return 0.0; // Fallback to deterministic }}
// Usagerequire __DIR__ . '/../vendor/autoload.php';
use ClaudePhp\ClaudePhp;
$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);
$tester = new ConsistencyTester($client);
echo "Testing consistency at different temperatures:\n\n";
foreach ([0.0, 0.5, 1.0, 1.5] as $temp) { echo "Temperature: {$temp}\n";
$result = $tester->measureConsistency( prompt: 'Name the top 3 PHP frameworks', 'temperature' => $temp, samples: 5 );
echo " Unique responses: {$result['unique_count']}/5\n"; echo " Consistency score: " . round($result['consistency_score'], 1) . "%\n"; echo " Avg length: " . round($result['average_length'], 0) . " chars\n\n";}Troubleshooting
Section titled “Troubleshooting”Error: “Call to undefined method messages()”
Section titled “Error: “Call to undefined method messages()””Symptom: Fatal error: Call to undefined method Claude\Claude3Api\ClaudePhp::messages()
Cause: Typically occurs if using an incorrect SDK version or invalid client instantiation.
Solution: Ensure you are using the Claude-PHP-SDK correctly with named parameters and proper configuration:
// Correct$client = new ClaudePhp( apiKey: $_ENV['ANTHROPIC_API_KEY']);$response = $client->messages()->create( 'model' => 'claude-sonnet-4-5', // ...);Problem: Inconsistent Outputs at Temperature 0.0
Section titled “Problem: Inconsistent Outputs at Temperature 0.0”Symptom: Even with temperature => 0.0, outputs vary slightly between runs.
Cause: While temperature 0.0 is highly deterministic, some variation can occur due to:
- Model updates from Anthropic
- Context window differences
- Floating-point precision in calculations
Solution: For absolute determinism, use 'temperature' => 0.0 with 'top_p' => 1.0 and consider caching results for identical inputs. For production data extraction, implement result validation and retry logic.
Error: “Temperature must be between 0 and 2”
Section titled “Error: “Temperature must be between 0 and 2””Symptom: InvalidArgumentException: Temperature must be between 0 and 2
Cause: Temperature value outside the valid range (0.0 to 2.0) usually caught by SDK or validation logic.
Solution: Validate temperature before API calls:
if ($temperature < 0 || $temperature > 2) { throw new \InvalidArgumentException('Temperature must be between 0 and 2');}Problem: High Temperature Produces Nonsensical Output
Section titled “Problem: High Temperature Produces Nonsensical Output”Symptom: With temperature => 2.0, outputs are creative but sometimes incoherent or off-topic.
Cause: Very high temperature increases randomness, which can reduce coherence.
Solution: For creative tasks, use moderate temperature (1.3-1.5) with appropriate topP (0.95). Combine with clear system prompts and constraints to maintain quality.
Exercises
Section titled “Exercises”Exercise 1: Temperature Optimizer
Section titled “Exercise 1: Temperature Optimizer”Build a system that automatically finds the optimal temperature for a given task based on requirements.
Requirements:
- Accept task description and consistency requirements
- Test multiple temperature values
- Measure output quality and consistency
- Return recommended temperature setting
Exercise 2: Multi-Strategy Generator
Section titled “Exercise 2: Multi-Strategy Generator”Create a content generator that uses different sampling strategies for different sections.
Requirements:
- Use low temperature for factual sections
- Use high temperature for creative sections
- Combine outputs coherently
- Track which strategy was used where
Exercise 3: Determinism Validator
Section titled “Exercise 3: Determinism Validator”Build a tool that validates whether responses are deterministic enough for production use.
Requirements:
- Run same prompt multiple times
- Compare outputs for consistency
- Flag non-deterministic behavior
- Recommend temperature adjustments
Solution Hints
For Exercise 1, create a test suite that runs prompts at different temperatures and scores results. For Exercise 2, parse content into sections and apply different strategies based on section type. For Exercise 3, use similarity scoring and statistical analysis to measure variance.
Further Reading
Section titled “Further Reading”- Claude-PHP-SDK on GitHub — The official community PHP SDK
- Anthropic API Documentation — Complete API reference and guides
- Claude-PHP-SDK Package — SDK package on Packagist
Wrap-up
Section titled “Wrap-up”Congratulations! You’ve mastered temperature and sampling parameters. Here’s what you accomplished:
- ✓ Understood token-level sampling — You learned how Claude predicts and selects tokens
- ✓ Mastered temperature control — You can now configure Claude for deterministic (0.0) to creative (2.0) outputs
- ✓ Learned top-p and top-k — You understand how these parameters filter token choices
- ✓ Built practical tools — Created classes for data extraction, content generation, and code generation with optimal settings
- ✓ Implemented adaptive systems — Built assistants that automatically adjust parameters based on context
- ✓ Measured consistency — Created tools to validate deterministic behavior for production use
- ✓ Tested systematically — Built A/B testing frameworks to find optimal parameters
- ✓ Understood costs — Analyzed how sampling parameters affect token usage and costs
- ✓ Applied model-specific guidance — Learned optimal parameters for different Claude models
These sampling parameters are essential for production AI applications. Whether you’re extracting structured data, generating creative content, or writing code, choosing the right parameters ensures Claude produces exactly the output you need.
Key Takeaways
Section titled “Key Takeaways”- ✓ Temperature controls creativity vs determinism (0.0 = deterministic, 2.0 = creative)
- ✓ Top-p (nucleus sampling) filters tokens by cumulative probability
- ✓ Top-k limits consideration to k most probable tokens
- ✓ Combine temperature + top_p for fine-grained control
- ✓ Use temperature 0.0 for data extraction and structured output
- ✓ Use temperature 1.5+ for creative content generation
- ✓ Match sampling parameters to your use case requirements
- ✓ Test consistency for production deterministic tasks
- ✓ Use stop sequences with high temperature to control output length
- ✓ A/B test different configurations to find optimal settings
- ✓ Consider cost implications: higher temperature often means more tokens
- ✓ Apply model-specific guidelines for different Claude models
Further Reading
Section titled “Further Reading”- Anthropic API Documentation — Sampling Parameters — Official guide to temperature, top_p, and top_k
- Chapter 09: Token Management and Counting — Learn about optimizing context windows and managing costs
- Chapter 15: Structured Outputs — See deterministic sampling in action for structured data extraction
- Chapter 26: Code Review Assistant — Example of focused temperature settings for code analysis
- Language Model Sampling Explained — Deep dive into sampling techniques and theory
Continue to Chapter 09: Token Management and Counting to learn about optimizing context windows and managing costs.
💻 Code Samples
Section titled “💻 Code Samples”All code examples from this chapter are available in the GitHub repository:
Clone and run locally:
git clone https://github.com/dalehurley/codewithphp.gitcd codewithphp/code/claude-php/chapter-08composer installexport ANTHROPIC_API_KEY="sk-ant-your-key-here"php examples/02-temperature-comparison.php