Source code for haive.games.poker.engines

"""Poker agent LLM configurations and prompts.

This module defines the language model configurations and prompt templates
for different poker playing styles and roles. It includes:
    - Player prompt generation for different styles
    - Hand analysis prompt generation
    - LLM provider selection and configuration
    - Agent configuration creation

The module supports multiple LLM providers (Azure, DeepSeek, Anthropic, Gemini, Mistral) and
configures them with appropriate models and prompts for poker gameplay.

"""

import os

from haive.core.engine.aug_llm import AugLLMConfig
from haive.core.models.llm.base import (
    AnthropicLLMConfig,
    AzureLLMConfig,
    DeepSeekLLMConfig,
    GeminiLLMConfig,
    LLMProvider,
    MistralLLMConfig,
)
from langchain_core.prompts import ChatPromptTemplate

from haive.games.poker.models import AgentDecisionSchema


# === Poker Player Prompts ===
[docs] def generate_poker_prompt(player_style: str) -> ChatPromptTemplate: """Generate a structured prompt for a poker player.""" return ChatPromptTemplate.from_messages( [ ( "system", f"You are a {player_style} poker player in a game of Texas Hold'em. " "Your goal is to make strategic decisions based on your hand, the game state, " "opponent actions, and pot size. Your playing style should align with your description.", ), ( "human", "Game State:\n" "- Player Name: {player_id}\n" "- Position: {position_name}\n" "- Phase: {phase}\n" "- Hand: {hand}\n" "- Community Cards: {community_cards}\n" "- Chips: {chips}\n" "- Current Bet: {current_bet}\n" "- Pot Size: {pot_size}\n\n" "Recent Actions:\n{recent_actions}\n\n" "Players Summary:\n{player_states}\n\n" "Legal Moves: {legal_moves}\n\n" "Make your move and provide reasoning.", ), ] )
[docs] def generate_hand_analysis_prompt() -> ChatPromptTemplate: """Generate a structured prompt for poker hand analysis.""" return ChatPromptTemplate.from_messages( [ ( "system", "You are an expert poker hand analyzer. Your task is to evaluate the strength of hands, " "potential draws, and probabilities of winning given the board state.", ), ( "human", "Game State:\n" "- Player Hand: {hand}\n" "- Community Cards: {community_cards}\n" "- Opponent Actions: {recent_actions}\n\n" "Analyze the situation and determine the best move.", ), ] )
[docs] def get_available_providers() -> list[LLMProvider]: """Determine all available LLM providers based on environment variables.""" available_providers = [] # Check each provider individually to avoid using LLMProvider as dict key if os.getenv("DEEPSEEK_API_KEY"): available_providers.append(LLMProvider.DEEPSEEK) if os.getenv("ANTHROPIC_API_KEY"): available_providers.append(LLMProvider.ANTHROPIC) if os.getenv("AZURE_OPENAI_API_KEY"): available_providers.append(LLMProvider.AZURE) if os.getenv("GOOGLE_API_KEY"): available_providers.append(LLMProvider.GEMINI) if os.getenv("MISTRAL_API_KEY"): available_providers.append(LLMProvider.MISTRALAI) # If no providers are available, default to Azure if not available_providers: available_providers.append(LLMProvider.AZURE) return available_providers
[docs] def get_poker_llm_provider() -> LLMProvider: """Determine the best available LLM provider.""" providers = get_available_providers() # Define priority order priority_order = [ LLMProvider.DEEPSEEK, LLMProvider.ANTHROPIC, LLMProvider.GEMINI, LLMProvider.MISTRALAI, LLMProvider.AZURE, ] # Return the highest priority available provider for provider in priority_order: if provider in providers: return provider # Default fallback return LLMProvider.AZURE
[docs] def get_model_for_provider(provider: LLMProvider) -> str: """Get the best model for a given provider.""" # Avoid using dict with LLMProvider as key if provider == LLMProvider.DEEPSEEK: return "deepseek-chat" if provider == LLMProvider.ANTHROPIC: return "claude-3-opus-20240229" if provider == LLMProvider.GEMINI: return "gemini-1.5-pro" if provider == LLMProvider.MISTRALAI: return "mistral-large-latest" # Default to Azure model return "gpt-4o"
[docs] def create_llm_config_for_provider(provider: LLMProvider, **kwargs): """Create an LLM configuration for a specific provider.""" # Get the model name for this provider model = get_model_for_provider(provider) # Create the appropriate config class based on provider # Avoid using dict with LLMProvider as key if provider == LLMProvider.DEEPSEEK: config_class = DeepSeekLLMConfig elif provider == LLMProvider.ANTHROPIC: config_class = AnthropicLLMConfig elif provider == LLMProvider.GEMINI: config_class = GeminiLLMConfig elif provider == LLMProvider.MISTRALAI: config_class = MistralLLMConfig else: # Default to Azure config_class = AzureLLMConfig # Create base configuration with default values base_config = { "model": model, "temperature": 0.6, # "max_tokens": 150 } # Override defaults with any provided kwargs base_config.update(kwargs) return config_class(**base_config)
# === Poker Agent Configurations ===
[docs] def create_poker_agent_configs() -> dict[str, AugLLMConfig]: """Create structured configurations for poker agents.""" # Get primary provider with fallbacks provider = get_poker_llm_provider() llm_config = create_llm_config_for_provider(provider) return { "conservative_agent": AugLLMConfig( name="conservative_player", llm_config=llm_config, prompt_template=generate_poker_prompt("tight and risk-averse"), structured_output_model=AgentDecisionSchema, ), "aggressive_agent": AugLLMConfig( name="aggressive_player", llm_config=llm_config, prompt_template=generate_poker_prompt("aggressive and bluffs often"), structured_output_model=AgentDecisionSchema, ), "balanced_agent": AugLLMConfig( name="balanced_player", llm_config=llm_config, prompt_template=generate_poker_prompt("balanced and adaptive"), structured_output_model=AgentDecisionSchema, ), "loose_agent": AugLLMConfig( name="loose_player", llm_config=llm_config, prompt_template=generate_poker_prompt("loose and plays many hands"), structured_output_model=AgentDecisionSchema, ), "hand_analyzer": AugLLMConfig( name="hand_analyzer", llm_config=llm_config, prompt_template=generate_hand_analysis_prompt(), structured_output_model=AgentDecisionSchema, ), }
# Updated version of create_default_agent_configs to work with various # providers
[docs] def create_default_agent_configs(config): """Create default configurations for poker agents based on config.""" # The issue is here - we need to properly handle LLMProvider instances get_available_providers() # Create configurations for poker playing styles poker_configs = create_poker_agent_configs() # Add these to the config engines if not hasattr(config, "engines") or config.engines is None: config.engines = {} config.engines.update(poker_configs) return config
# === Exposed Agent Configuration === poker_agent_configs = create_poker_agent_configs()