DocUA commited on
Commit
b2f09af
·
1 Parent(s): 014edbb

feat: Enhance OpenAI reasoning capabilities with configurable parameters

Browse files
Files changed (1) hide show
  1. main.py +67 -21
main.py CHANGED
@@ -71,6 +71,42 @@ def _log_prompt(provider: str, model: str, system: str, user: str) -> None:
71
  print(f"{_PROMPT_SEP}\n")
72
  # ============ End Debug Prompt Logging ============
73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  # Initialize embedding model and settings BEFORE importing components
75
  # Priority: OpenAI > Gemini > None
76
  embed_model = None
@@ -295,11 +331,16 @@ class RetrieverEvent(Event):
295
  class LLMAnalyzer:
296
  """Class for handling different LLM providers."""
297
 
298
- def __init__(self, provider: Any, model_name: Any, temperature: float = GENERATION_TEMPERATURE, max_tokens: Optional[int] = None):
 
 
299
  self.provider = provider
300
  self.model_name = model_name
301
  self.temperature = temperature
302
  self.max_tokens = max_tokens
 
 
 
303
 
304
  if provider == ModelProvider.OPENAI:
305
  if not OPENAI_API_KEY:
@@ -368,12 +409,12 @@ class LLMAnalyzer:
368
  # Reasoning models usually require temperature=1.0 or none
369
  if not is_reasoning_model:
370
  completion_params["temperature"] = self.temperature
371
-
372
- # Add GPT-5.2 specific parameters
373
- if "gpt-5" in model_val.lower():
374
- completion_params["reasoning_effort"] = "medium"
375
- completion_params["verbosity"] = "medium"
376
- completion_params["store"] = False
377
 
378
  # Log full prompts in debug mode
379
  _log_prompt("openai-analyzer", model_val, SYSTEM_PROMPT, prompt)
@@ -576,9 +617,13 @@ class PrecedentAnalysisWorkflow(Workflow):
576
  def __init__(self, provider: Any = ModelProvider.OPENAI,
577
  model_name: Any = AnalysisModelName.GPT4o_MINI,
578
  temperature: float = GENERATION_TEMPERATURE,
579
- max_tokens: Optional[int] = None):
 
 
 
580
  super().__init__()
581
- self.analyzer = LLMAnalyzer(provider, model_name, temperature, max_tokens)
 
582
 
583
  @step
584
  async def analyze(self, ctx: Context, ev: StartEvent) -> StopEvent:
@@ -805,16 +850,11 @@ def generate_legal_position(
805
  completion_params["max_tokens"] = max_tokens or MAX_TOKENS_CONFIG["openai"]
806
  completion_params["temperature"] = temperature
807
 
808
- # Handle thinking/reasoning for GPT-5.2 and other reasoning models
809
- if thinking_enabled and is_reasoning_model:
810
- # GPT-5.2 specific parameters
811
- if "gpt-5" in model_name.lower():
812
- completion_params["reasoning_effort"] = thinking_level.lower()
813
- completion_params["verbosity"] = openai_verbosity.lower()
814
- completion_params["store"] = False
815
- else:
816
- # For other reasoning models (gpt-4.1, o1, etc.)
817
- completion_params["reasoning_effort"] = thinking_level.lower()
818
 
819
  # Log full prompts in debug mode
820
  _log_prompt("openai", model_name, system_prompt, content)
@@ -1309,7 +1349,10 @@ async def analyze_action(
1309
  provider: str,
1310
  model_name: str,
1311
  temperature: float = GENERATION_TEMPERATURE,
1312
- max_tokens: Optional[int] = None
 
 
 
1313
  ) -> str:
1314
  """Analyze search results using AI."""
1315
  try:
@@ -1317,7 +1360,10 @@ async def analyze_action(
1317
  provider=ModelProvider(provider),
1318
  model_name=AnalysisModelName(model_name),
1319
  temperature=temperature,
1320
- max_tokens=max_tokens
 
 
 
1321
  )
1322
 
1323
  query = (
 
71
  print(f"{_PROMPT_SEP}\n")
72
  # ============ End Debug Prompt Logging ============
73
 
74
+ # ============ OpenAI Reasoning Helpers ============
75
+ # Valid reasoning_effort values accepted by the OpenAI API
76
+ _OPENAI_EFFORT_MAP = {
77
+ "none": None, # omit the parameter (model uses its own default)
78
+ "low": "low",
79
+ "medium": "medium",
80
+ "high": "high",
81
+ "xhigh": "high", # UI-only level, maps to highest valid API value
82
+ }
83
+
84
+
85
+ def _build_openai_reasoning_params(
86
+ model_name: str,
87
+ thinking_level: str = "medium",
88
+ openai_verbosity: str = "medium",
89
+ ) -> dict:
90
+ """Return extra completion params for OpenAI reasoning-capable models.
91
+
92
+ - reasoning_effort: mapped from thinking_level with UI→API value normalisation.
93
+ - verbosity: only for models that support it (gpt-5.* and o3*).
94
+ - store: always False so conversations are not stored in OpenAI history.
95
+ """
96
+ params: dict = {}
97
+
98
+ effort = _OPENAI_EFFORT_MAP.get(thinking_level.lower(), "medium")
99
+ if effort is not None:
100
+ params["reasoning_effort"] = effort
101
+
102
+ model_lower = model_name.lower()
103
+ if "gpt-5" in model_lower or model_lower.startswith("o3"):
104
+ params["verbosity"] = openai_verbosity.lower()
105
+
106
+ params["store"] = False
107
+ return params
108
+ # ============ End OpenAI Reasoning Helpers ============
109
+
110
  # Initialize embedding model and settings BEFORE importing components
111
  # Priority: OpenAI > Gemini > None
112
  embed_model = None
 
331
  class LLMAnalyzer:
332
  """Class for handling different LLM providers."""
333
 
334
+ def __init__(self, provider: Any, model_name: Any, temperature: float = GENERATION_TEMPERATURE,
335
+ max_tokens: Optional[int] = None, thinking_enabled: bool = False,
336
+ thinking_level: str = "medium", openai_verbosity: str = "medium"):
337
  self.provider = provider
338
  self.model_name = model_name
339
  self.temperature = temperature
340
  self.max_tokens = max_tokens
341
+ self.thinking_enabled = thinking_enabled
342
+ self.thinking_level = thinking_level
343
+ self.openai_verbosity = openai_verbosity
344
 
345
  if provider == ModelProvider.OPENAI:
346
  if not OPENAI_API_KEY:
 
409
  # Reasoning models usually require temperature=1.0 or none
410
  if not is_reasoning_model:
411
  completion_params["temperature"] = self.temperature
412
+
413
+ # Add reasoning parameters only when thinking is explicitly enabled
414
+ if is_reasoning_model and self.thinking_enabled:
415
+ completion_params.update(
416
+ _build_openai_reasoning_params(model_val, self.thinking_level, self.openai_verbosity)
417
+ )
418
 
419
  # Log full prompts in debug mode
420
  _log_prompt("openai-analyzer", model_val, SYSTEM_PROMPT, prompt)
 
617
  def __init__(self, provider: Any = ModelProvider.OPENAI,
618
  model_name: Any = AnalysisModelName.GPT4o_MINI,
619
  temperature: float = GENERATION_TEMPERATURE,
620
+ max_tokens: Optional[int] = None,
621
+ thinking_enabled: bool = False,
622
+ thinking_level: str = "medium",
623
+ openai_verbosity: str = "medium"):
624
  super().__init__()
625
+ self.analyzer = LLMAnalyzer(provider, model_name, temperature, max_tokens,
626
+ thinking_enabled, thinking_level, openai_verbosity)
627
 
628
  @step
629
  async def analyze(self, ctx: Context, ev: StartEvent) -> StopEvent:
 
850
  completion_params["max_tokens"] = max_tokens or MAX_TOKENS_CONFIG["openai"]
851
  completion_params["temperature"] = temperature
852
 
853
+ # Add reasoning parameters only when thinking is explicitly enabled by the user
854
+ if is_reasoning_model and thinking_enabled:
855
+ completion_params.update(
856
+ _build_openai_reasoning_params(model_name, thinking_level, openai_verbosity)
857
+ )
 
 
 
 
 
858
 
859
  # Log full prompts in debug mode
860
  _log_prompt("openai", model_name, system_prompt, content)
 
1349
  provider: str,
1350
  model_name: str,
1351
  temperature: float = GENERATION_TEMPERATURE,
1352
+ max_tokens: Optional[int] = None,
1353
+ thinking_enabled: bool = False,
1354
+ thinking_level: str = "medium",
1355
+ openai_verbosity: str = "medium"
1356
  ) -> str:
1357
  """Analyze search results using AI."""
1358
  try:
 
1360
  provider=ModelProvider(provider),
1361
  model_name=AnalysisModelName(model_name),
1362
  temperature=temperature,
1363
+ max_tokens=max_tokens,
1364
+ thinking_enabled=thinking_enabled,
1365
+ thinking_level=thinking_level,
1366
+ openai_verbosity=openai_verbosity
1367
  )
1368
 
1369
  query = (