code: from langchain_openai import ChatOpenAI
  from langchain_core.output_parsers import StrOutputParser
  from langchain.prompts import PromptTemplate
  from langchain.prompts.chat import ChatPromptTemplate
  from config.config import OPENAI_API_KEY
  from game.poker import PokerGameManager
  from db.db_utils import DatabaseManager
  import json
  
  class GPTPlayer:
      def __init__(self, db: DatabaseManager, model_name="gpt-3.5-turbo"):
          self.db = db
          llm = ChatOpenAI(model_name=model_name)
          output_parser = StrOutputParser()
          template = '''
          Imagine you're a poker bot in a heads-up Texas Hold'em game. Your play is optimal, 
          mixing strategic bluffs and strong hands. You raise on strength, going All-in only with the best hands. 
          Folding against a superior opponent hand, you call and check when fitting. Remember, only "call" the ALL-IN if your hand is better. 
          Please reply in the following JSON format: {{your_hand": "what is the current hand you are playing",  
          "opponents_hand": "what do you think your opponent has based on how he has played", "thought_process": "what is your thought process", 
          "action": "your action", "raise_amount": your raise amount if applicable}}
          Note: If the action you chose doesn't involve a raise, please do not include the "raise_amount" key in your JSON response.
          '''
          
          prompt = ChatPromptTemplate.from_messages([
              ("system", template),
              ("user", "{input}")
          ])
  
          self.chain = prompt | llm | output_parser
          
      def _extract_action(self, json_string, pokerGame: PokerGameManager):
          min_raise, max_raise = pokerGame.return_min_max_raise(1)
          try:
              json_data = json.loads(json_string)
              action = json_data['action'].capitalize()
              raise_amount = 0
              if action == "Raise":
                  raise_amount = json_data['raise_amount']
                  raise_amount = int(raise_amount)
                  
                  if raise_amount < min_raise:
                      raise_amount = min_raise
  
                  elif raise_amount > max_raise:
                      action = "All-in"
                      raise_amount = pokerGame.return_player_stack(1)
              self.db.record_gpt_action(action, raise_amount, json_string)
              return (action, raise_amount)
          except Exception as erro:
              return ("Default", 0)
  
  
      def pre_flop_small_blind(self, pokerGame: PokerGameManager):
          # return Call, Raise, Fold or All-in
          inputs = {
              'small_blind': pokerGame.small_blind,
              'big_blind': pokerGame.big_blind,
              'stack': pokerGame.return_player_stack(1),
              'opponents_stack': pokerGame.return_player_stack(0),
              'hand': pokerGame.players[1].return_long_hand(),
              'pot': pokerGame.current_pot,
              'amount_to_call': pokerGame.big_blind - pokerGame.small_blind
          }
  
          human_template = '''
          The small blind is {small_blind} chips and the big blind is {big_blind} chips.
          You have {stack} chips in your stack and your opponent has {opponents_stack} chips.
          Your hand is {hand}. The pot is {pot} chips.
          You are the small blind and it's your turn.
          It costs {amount_to_call} chips to call.
          What action would you take? (Call, Raise, All-in, or Fold)
          '''
  
          formatted_text = human_template.format(**inputs)
          response = self.chain.invoke({'input': formatted_text})
          return self._extract_action(response, pokerGame)
  
      def pre_flop_big_blind(self, pokerGame: PokerGameManager):
          # return Check, Raise, or All-in
          inputs = {
              'small_blind': pokerGame.small_blind,
              'big_blind': pokerGame.big_blind,
              'stack': pokerGame.return_player_stack(1),
              'opponents_stack': pokerGame.return_player_stack(0),
              'hand': pokerGame.players[1].return_long_hand(),
              'pot': pokerGame.current_pot,
              'amount_to_call': pokerGame.big_blind - pokerGame.small_blind
          }
  
          human_template = '''
          The small blind is {small_blind} chips and the big blind is {big_blind} chips.
          You have {stack} chips in your stack and your opponent has {opponents_stack} chips.
          Your hand is {hand}. The pot is {pot} chips.
          You are the small blind and it's your turn.
          It costs {amount_to_call} chips to call.
          What action would you take? (Check, Raise, or All-in)
          '''
  
          formatted_text = human_template.format(**inputs)
          response = self.chain.invoke({'input': formatted_text})
          return self._extract_action(response, pokerGame)
      
      def first_to_act(self, pokerGame: PokerGameManager):
          # return Check, Raise, or All-in
          inputs = {
              'small_blind': pokerGame.small_blind,
              'big_blind': pokerGame.big_blind,
              'stack': pokerGame.return_player_stack(1),
              'opponents_stack': pokerGame.return_player_stack(0),
              'hand': pokerGame.players[1].return_long_hand(),
              'pot': pokerGame.current_pot,
              'round': pokerGame.round,
              'community_cards': pokerGame.return_community_cards()
          }
  
          human_template = '''
          The small blind is {small_blind} chips and the big blind is {big_blind} chips.
          You have {stack} chips in your stack and your opponent has {opponents_stack} chips.
          Your hand is {hand}. The pot is {pot} chips.
          It's the {round} round and you're first to act. The community cards are {community_cards}.
          What action would you take? (Check, Raise, or All-in)
          '''
  
          formatted_text = human_template.format(**inputs)
          response = self.chain.invoke({'input': formatted_text})
          return self._extract_action(response, pokerGame)
      
      def player_check(self, pokerGame: PokerGameManager):
          # return Check, Raise, or All-in
          inputs = {
              'small_blind': pokerGame.small_blind,
              'big_blind': pokerGame.big_blind,
              'stack': pokerGame.return_player_stack(1),
              'opponents_stack': pokerGame.return_player_stack(0),
              'hand': pokerGame.players[1].return_long_hand(),
              'pot': pokerGame.current_pot,
              'round': pokerGame.round,
              'community_cards': pokerGame.return_community_cards()
          }
  
          human_template = """
          The small blind is {small_blind} chips and the big blind is {big_blind} chips.
          You have {stack} chips in your stack and your opponent has {opponents_stack} chips.
          Your hand is {hand}. The pot is {pot} chips.
          It is the {round} round and the action checks to you. The community cards are {community_cards}.
          Based on this information, what action would you like to take? (Check, Raise, or All-in).
          """        
          
          formatted_text = human_template.format(**inputs)
  
          response = self.chain.invoke({'input': formatted_text})
          return self._extract_action(response, pokerGame)
      
      def player_raise(self, pokerGame: PokerGameManager):
          # return Call, Raise, All-in, or Fold
          inputs = {
              'small_blind': pokerGame.small_blind,
              'big_blind': pokerGame.big_blind,
              'stack': pokerGame.return_player_stack(1),
              'opponents_stack': pokerGame.return_player_stack(0),
              'hand': pokerGame.players[1].return_long_hand(),
              'pot': pokerGame.current_pot,
              'round': pokerGame.round,
              'community_cards': pokerGame.return_community_cards(),
              'opponent_raise': pokerGame.current_bet,
              'amount_to_call': pokerGame.current_bet - pokerGame.players[1].round_pot_commitment
          }
  
          human_template = '''
          The small blind is {small_blind} chips and the big blind is {big_blind} chips.
          You have {stack} chips in your stack and your opponent has {opponents_stack} chips.
          Your hand is {hand}. The pot is {pot} chips.
          It's the {round} round. The community cards are {community_cards}.
          Your opponent has raised to {opponent_raise} chips.
          It costs {amount_to_call} chips to call.
          What action would you take? (Call, Raise, All-in, or Fold)
          '''
  
          formatted_text = human_template.format(**inputs)
  
          response = self.chain.invoke({'input': formatted_text})
          return self._extract_action(response, pokerGame)  
  
      def player_all_in(self, pokerGame: PokerGameManager):
          # return Call, or Fold
          amount_to_call = pokerGame.current_bet - pokerGame.players[1].round_pot_commitment
          if amount_to_call > pokerGame.return_player_stack(1):
              amount_to_call = pokerGame.return_player_stack(1)
          inputs = {
              'small_blind': pokerGame.small_blind,
              'big_blind': pokerGame.big_blind,
              'stack': pokerGame.return_player_stack(1),
              'hand': pokerGame.players[1].return_long_hand(),
              'pot': pokerGame.current_pot,
              'round': pokerGame.round,
              'community_cards': pokerGame.return_community_cards(),
              'opponent_raise': pokerGame.current_bet,
              'amount_to_call': amount_to_call
          }
  
          human_template = '''
          The small blind is {small_blind} chips and the big blind is {big_blind} chips.
          You have {stack} chips in your stack.
          Your hand is {hand}. The pot is {pot} chips.
          It's the {round} round. The community cards are {community_cards}.
          Your opponent has gone all in for {opponent_raise} chips.
          It costs {amount_to_call} chips to call.
          What action would you take? (Call, or Fold)
          '''
  
          formatted_text = human_template.format(**inputs)
          
          response = self.chain.invoke({'input': formatted_text})
          return self._extract_action(response, pokerGame)
  
apis: langchain_core.output_parsers.StrOutputParser langchain.prompts.chat.ChatPromptTemplate.from_messages langchain_openai.ChatOpenAI
extract_api: [((456, 489), 'langchain_openai.ChatOpenAI', 'ChatOpenAI', ([], {'model_name': 'model_name'}), '(model_name=model_name)\n', (466, 489), False, 'from langchain_openai import ChatOpenAI\n'), ((514, 531), 'langchain_core.output_parsers.StrOutputParser', 'StrOutputParser', ([], {}), '()\n', (529, 531), False, 'from langchain_core.output_parsers import StrOutputParser\n'), ((1408, 1485), 'langchain.prompts.chat.ChatPromptTemplate.from_messages', 'ChatPromptTemplate.from_messages', (["[('system', template), ('user', '{input}')]"], {}), "([('system', template), ('user', '{input}')])\n", (1440, 1485), False, 'from langchain.prompts.chat import ChatPromptTemplate\n'), ((1755, 1778), 'json.loads', 'json.loads', (['json_string'], {}), '(json_string)\n', (1765, 1778), False, 'import json\n')]