1+ """
2+ Test OpenAI reasoning model detection logic
3+ """
4+
5+ import unittest
6+ from unittest .mock import MagicMock
7+
8+
9+ class TestOpenAIReasoningModelDetection (unittest .TestCase ):
10+ """Test that OpenAI reasoning models are correctly identified"""
11+
12+ def test_reasoning_model_detection (self ):
13+ """Test various model names to ensure correct reasoning model detection"""
14+
15+ # Define the same constants as in the code
16+ OPENAI_REASONING_MODEL_PREFIXES = (
17+ # O-series reasoning models
18+ "o1-" , "o1" , # o1, o1-mini, o1-preview
19+ "o3-" , "o3" , # o3, o3-mini, o3-pro
20+ "o4-" , # o4-mini
21+ # GPT-5 series are also reasoning models
22+ "gpt-5-" , "gpt-5" # gpt-5, gpt-5-mini, gpt-5-nano
23+ )
24+
25+ def is_reasoning_model (model_name , api_base = "https://api.openai.com/v1" ):
26+ """Test function that mimics the logic in openai.py"""
27+ model_lower = str (model_name ).lower ()
28+ return (
29+ api_base == "https://api.openai.com/v1" and
30+ model_lower .startswith (OPENAI_REASONING_MODEL_PREFIXES )
31+ )
32+
33+ # Test cases: (model_name, expected_result, description)
34+ test_cases = [
35+ # Reasoning models - should return True
36+ ("o1" , True , "Base o1 model" ),
37+ ("o1-mini" , True , "o1-mini model" ),
38+ ("o1-preview" , True , "o1-preview model" ),
39+ ("o1-mini-2025-01-31" , True , "o1-mini with date" ),
40+ ("o3" , True , "Base o3 model" ),
41+ ("o3-mini" , True , "o3-mini model" ),
42+ ("o3-pro" , True , "o3-pro model" ),
43+ ("o4-mini" , True , "o4-mini model" ),
44+ ("gpt-5" , True , "Base gpt-5 model" ),
45+ ("gpt-5-mini" , True , "gpt-5-mini model" ),
46+ ("gpt-5-nano" , True , "gpt-5-nano model" ),
47+
48+ # Non-reasoning models - should return False
49+ ("gpt-4o-mini" , False , "gpt-4o-mini (not reasoning)" ),
50+ ("gpt-4o" , False , "gpt-4o (not reasoning)" ),
51+ ("gpt-4" , False , "gpt-4 (not reasoning)" ),
52+ ("gpt-3.5-turbo" , False , "gpt-3.5-turbo (not reasoning)" ),
53+ ("claude-3" , False , "Non-OpenAI model" ),
54+ ("gemini-pro" , False , "Non-OpenAI model" ),
55+
56+ # Edge cases
57+ ("O1-MINI" , True , "Uppercase o1-mini" ),
58+ ("GPT-5-MINI" , True , "Uppercase gpt-5-mini" ),
59+ ]
60+
61+ for model_name , expected , description in test_cases :
62+ with self .subTest (model = model_name , desc = description ):
63+ result = is_reasoning_model (model_name )
64+ self .assertEqual (
65+ result ,
66+ expected ,
67+ f"Model '{ model_name } ' ({ description } ): expected { expected } , got { result } "
68+ )
69+
70+ def test_non_openai_api_base (self ):
71+ """Test that non-OpenAI API bases don't trigger reasoning model logic"""
72+ OPENAI_REASONING_MODEL_PREFIXES = (
73+ "o1-" , "o1" , "o3-" , "o3" , "o4-" , "gpt-5-" , "gpt-5"
74+ )
75+
76+ def is_reasoning_model (model_name , api_base ):
77+ model_lower = str (model_name ).lower ()
78+ return (
79+ api_base == "https://api.openai.com/v1" and
80+ model_lower .startswith (OPENAI_REASONING_MODEL_PREFIXES )
81+ )
82+
83+ # Even reasoning model names should return False for non-OpenAI APIs
84+ test_cases = [
85+ ("o1-mini" , "https://api.anthropic.com/v1" , False ),
86+ ("gpt-5" , "https://generativelanguage.googleapis.com/v1beta/openai/" , False ),
87+ ("o3-mini" , "https://api.deepseek.com/v1" , False ),
88+ ]
89+
90+ for model_name , api_base , expected in test_cases :
91+ with self .subTest (model = model_name , api = api_base ):
92+ result = is_reasoning_model (model_name , api_base )
93+ self .assertEqual (
94+ result ,
95+ expected ,
96+ f"Model '{ model_name } ' with API '{ api_base } ' should return { expected } "
97+ )
98+
99+
100+ if __name__ == "__main__" :
101+ unittest .main ()
0 commit comments