@@ -590,6 +590,54 @@ def build_user_prompt(
590590_cached_api_key : str | None = None
591591
592592
593+ def is_chat_model (model_name : str ) -> bool :
594+ """
595+ Determine if a model is a chat model or completion model.
596+
597+ Chat models use /v1/chat/completions endpoint.
598+ Completion models use /v1/completions endpoint.
599+
600+ Args:
601+ model_name: Model name (e.g., "gpt-4o", "gpt-5.1-codex", "o1")
602+
603+ Returns:
604+ True if chat model, False if completion model
605+ """
606+ model_lower = model_name .lower ()
607+
608+ # Completion models (use /v1/completions) - check these first (more specific)
609+ # Note: GPT-5.x-codex models are chat models, not completion models
610+ completion_model_patterns = [
611+ "text-" , # text-davinci-003, text-curie-001, etc.
612+ "davinci" , # davinci-003, etc.
613+ "curie" , # curie-001, etc.
614+ "babbage" , # babbage-001, etc.
615+ "ada" , # ada-001, etc.
616+ ]
617+
618+ for pattern in completion_model_patterns :
619+ if pattern in model_lower :
620+ return False
621+
622+ # Chat models (use /v1/chat/completions)
623+ # GPT-5.x series (including gpt-5.1-codex, gpt-5.2-codex) are chat models
624+ chat_model_patterns = [
625+ "gpt-4" , # gpt-4, gpt-4o, gpt-4-turbo, gpt-4o-mini
626+ "gpt-3.5" , # gpt-3.5-turbo
627+ "gpt-5" , # gpt-5.2, gpt-5.1, gpt-5.1-codex, gpt-5.2-codex, etc.
628+ "o1" , # o1, o1-mini, o3-mini
629+ "o3" , # o3-mini
630+ "claude" , # Claude models
631+ ]
632+
633+ for pattern in chat_model_patterns :
634+ if pattern in model_lower :
635+ return True
636+
637+ # Default: assume chat model for unknown models (most modern models are chat)
638+ return True
639+
640+
593641def get_api_key () -> str | None :
594642 """Get API key from environment or interactive input (cached)."""
595643 global _cached_api_key
@@ -640,18 +688,37 @@ def generate_with_openai(
640688 client = OpenAI (** client_kwargs )
641689
642690 try :
643- # GPT-5.2 and newer models use max_completion_tokens
644- response = client .chat .completions .create (
645- model = model ,
646- messages = [
647- {"role" : "system" , "content" : system_prompt },
648- {"role" : "user" , "content" : user_prompt },
649- ],
650- temperature = temperature ,
651- max_completion_tokens = max_completion_tokens ,
652- )
691+ # Determine if model is chat or completion model
692+ use_chat_api = is_chat_model (model )
653693
654- return response .choices [0 ].message .content
694+ if use_chat_api :
695+ # Chat models use /v1/chat/completions
696+ response = client .chat .completions .create (
697+ model = model ,
698+ messages = [
699+ {"role" : "system" , "content" : system_prompt },
700+ {"role" : "user" , "content" : user_prompt },
701+ ],
702+ temperature = temperature ,
703+ max_completion_tokens = max_completion_tokens ,
704+ )
705+ return response .choices [0 ].message .content
706+ else :
707+ # Completion models use /v1/completions
708+ # Combine system and user prompts
709+ full_prompt = f"{ system_prompt } \n \n { user_prompt } "
710+
711+ # Completion API uses max_tokens instead of max_completion_tokens
712+ # Use max_tokens if available, otherwise use max_completion_tokens
713+ max_tokens = model_config .get ("max_tokens" , max_completion_tokens )
714+
715+ response = client .completions .create (
716+ model = model ,
717+ prompt = full_prompt ,
718+ temperature = temperature ,
719+ max_tokens = max_tokens ,
720+ )
721+ return response .choices [0 ].text
655722 except Exception as e :
656723 error_msg = str (e )
657724 if "Connection" in error_msg or "getaddrinfo" in error_msg :
@@ -796,17 +863,34 @@ def optimize_prompt_with_ai(
796863
797864 try :
798865 print (" 🤖 Calling AI to optimize prompt..." )
799- response = client .chat .completions .create (
800- model = model ,
801- messages = [
802- {"role" : "system" , "content" : optimization_system_prompt },
803- {"role" : "user" , "content" : optimization_user_prompt },
804- ],
805- temperature = temperature ,
806- max_completion_tokens = max_completion_tokens ,
807- )
808866
809- optimized_content = response .choices [0 ].message .content
867+ # Determine if model is chat or completion model
868+ use_chat_api = is_chat_model (model )
869+
870+ if use_chat_api :
871+ # Chat models use /v1/chat/completions
872+ response = client .chat .completions .create (
873+ model = model ,
874+ messages = [
875+ {"role" : "system" , "content" : optimization_system_prompt },
876+ {"role" : "user" , "content" : optimization_user_prompt },
877+ ],
878+ temperature = temperature ,
879+ max_completion_tokens = max_completion_tokens ,
880+ )
881+ optimized_content = response .choices [0 ].message .content
882+ else :
883+ # Completion models use /v1/completions
884+ full_prompt = f"{ optimization_system_prompt } \n \n { optimization_user_prompt } "
885+ max_tokens = model_config .get ("max_tokens" , max_completion_tokens )
886+
887+ response = client .completions .create (
888+ model = model ,
889+ prompt = full_prompt ,
890+ temperature = temperature ,
891+ max_tokens = max_tokens ,
892+ )
893+ optimized_content = response .choices [0 ].text
810894
811895 # Parse optimized prompt
812896 if "---" in optimized_content :
0 commit comments