DocUA commited on
Commit
39e57fa
·
1 Parent(s): a3e169a

Fix OpenAI gpt-4.1 API parameters: role 'developer', max_completion_tokens, and reasoning effort support; update max_tokens in default config

Browse files
Files changed (2) hide show
  1. config/environments/default.yaml +4 -4
  2. main.py +56 -21
config/environments/default.yaml CHANGED
@@ -23,10 +23,10 @@ llama_index:
23
  # Generation Settings
24
  generation:
25
  max_tokens:
26
- openai: 4096
27
- anthropic: 4096
28
- gemini: 4096
29
- deepseek: 4096
30
  max_tokens_analysis: 4000
31
  temperature: 0.5
32
 
 
23
  # Generation Settings
24
  generation:
25
  max_tokens:
26
+ openai: 2048
27
+ anthropic: 2048
28
+ gemini: 2048
29
+ deepseek: 2048
30
  max_tokens_analysis: 4000
31
  temperature: 0.5
32
 
main.py CHANGED
@@ -244,7 +244,7 @@ class RetrieverEvent(Event):
244
  class LLMAnalyzer:
245
  """Class for handling different LLM providers."""
246
 
247
- def __init__(self, provider: ModelProvider, model_name: AnalysisModelName):
248
  self.provider = provider
249
  self.model_name = model_name
250
 
@@ -281,8 +281,15 @@ class LLMAnalyzer:
281
 
282
  async def _analyze_with_openai(self, prompt: str, response_schema: dict) -> str:
283
  """Analyze text using OpenAI."""
 
 
 
 
 
 
 
284
  messages = [
285
- ChatMessage(role="system", content=SYSTEM_PROMPT),
286
  ChatMessage(role="user", content=prompt)
287
  ]
288
 
@@ -295,19 +302,24 @@ class LLMAnalyzer:
295
  }
296
 
297
  try:
298
- response = self.client.chat.completions.create(
299
- model=self.model_name,
300
- messages=[{"role": m.role, "content": m.content} for m in messages],
301
- response_format=response_format,
302
- temperature=0
303
- )
 
 
 
 
 
304
  response_text = response.choices[0].message.content
305
 
306
  # Verify it's valid JSON
307
  json_data = extract_json_from_text(response_text)
308
  return json.dumps(json_data, ensure_ascii=False) if json_data else response_text
309
  except Exception as e:
310
- raise RuntimeError(f"Error in OpenAI analysis: {str(e)}")
311
 
312
  async def _analyze_with_deepseek(self, prompt: str) -> str:
313
  """Analyze text using DeepSeek."""
@@ -604,29 +616,52 @@ def generate_legal_position(
604
  client = OpenAI(api_key=OPENAI_API_KEY)
605
  try:
606
  print(f"[DEBUG] OpenAI Generation - Model: {model_name}")
607
- response = client.chat.completions.create(
608
- model=model_name,
609
- messages=[
610
- {"role": "system", "content": system_prompt},
611
- {"role": "user", "content": content},
612
- ],
613
- temperature=GENERATION_TEMPERATURE,
614
- max_tokens=MAX_TOKENS_CONFIG["openai"],
615
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
616
  response_text = response.choices[0].message.content
617
- print(f"[DEBUG] OpenAI response length: {len(response_text)}")
618
 
619
  json_response = extract_json_from_text(response_text)
620
  if json_response and all(key in json_response for key in ["title", "text", "proceeding", "category"]):
621
  return json_response
622
  else:
623
- print(f"[WARNING] Invalid JSON structure from OpenAI. Text: {response_text[:300]}...")
624
  raise ValueError("Invalid JSON structure")
625
  except Exception as e:
626
  print(f"[ERROR] OpenAI generation/parsing failed: {e}")
627
  return {
628
  "title": "Автоматично сформований заголовок (OpenAI)",
629
- "text": response_text.strip() if 'response_text' in locals() else "Помилка при отриманні відповіді",
630
  "proceeding": "Не визначено",
631
  "category": "Помилка парсингу"
632
  }
 
244
  class LLMAnalyzer:
245
  """Class for handling different LLM providers."""
246
 
247
+ def __init__(self, provider: "ModelProvider", model_name: "AnalysisModelName"):
248
  self.provider = provider
249
  self.model_name = model_name
250
 
 
281
 
282
  async def _analyze_with_openai(self, prompt: str, response_schema: dict) -> str:
283
  """Analyze text using OpenAI."""
284
+ # Determine model name and if it's a reasoning model
285
+ model_val = self.model_name.value if hasattr(self.model_name, "value") else str(self.model_name)
286
+ is_reasoning_model = any(m in model_val.lower() for m in ["gpt-4.1", "gpt-4.5", "o1", "o3"])
287
+
288
+ # Use developer role for newer models
289
+ role = "developer" if is_reasoning_model else "system"
290
+
291
  messages = [
292
+ ChatMessage(role=role, content=SYSTEM_PROMPT),
293
  ChatMessage(role="user", content=prompt)
294
  ]
295
 
 
302
  }
303
 
304
  try:
305
+ completion_params = {
306
+ "model": model_val,
307
+ "messages": [{"role": m.role, "content": m.content} for m in messages],
308
+ "response_format": response_format,
309
+ }
310
+
311
+ # Reasoning models usually require temperature=1.0 or none
312
+ if not is_reasoning_model:
313
+ completion_params["temperature"] = 0
314
+
315
+ response = self.client.chat.completions.create(**completion_params)
316
  response_text = response.choices[0].message.content
317
 
318
  # Verify it's valid JSON
319
  json_data = extract_json_from_text(response_text)
320
  return json.dumps(json_data, ensure_ascii=False) if json_data else response_text
321
  except Exception as e:
322
+ raise RuntimeError(f"Error in OpenAI analysis ({model_val}): {str(e)}")
323
 
324
  async def _analyze_with_deepseek(self, prompt: str) -> str:
325
  """Analyze text using DeepSeek."""
 
616
  client = OpenAI(api_key=OPENAI_API_KEY)
617
  try:
618
  print(f"[DEBUG] OpenAI Generation - Model: {model_name}")
619
+
620
+ # Check for reasoning models (gpt-4.1, o1, etc.)
621
+ is_reasoning_model = any(m in model_name.lower() for m in ["gpt-4.1", "gpt-4.5", "o1", "o3"])
622
+
623
+ # Use developer role for newer models, system for others
624
+ role = "developer" if is_reasoning_model else "system"
625
+
626
+ messages = [
627
+ {"role": role, "content": system_prompt},
628
+ {"role": "user", "content": content},
629
+ ]
630
+
631
+ # Parameters for chat completion
632
+ completion_params = {
633
+ "model": model_name,
634
+ "messages": messages,
635
+ }
636
+
637
+ # Set tokens based on model capabilities
638
+ if is_reasoning_model:
639
+ completion_params["max_completion_tokens"] = MAX_TOKENS_CONFIG["openai"]
640
+ else:
641
+ completion_params["max_tokens"] = MAX_TOKENS_CONFIG["openai"]
642
+
643
+ # Handle thinking/reasoning
644
+ if thinking_enabled and is_reasoning_model:
645
+ completion_params["reasoning_effort"] = thinking_level.lower()
646
+ # Reasoning models usually don't support temperature or it must be 1.0
647
+ else:
648
+ completion_params["temperature"] = GENERATION_TEMPERATURE
649
+
650
+ response = client.chat.completions.create(**completion_params)
651
  response_text = response.choices[0].message.content
652
+ print(f"[DEBUG] OpenAI response length: {len(response_text) if response_text else 0}")
653
 
654
  json_response = extract_json_from_text(response_text)
655
  if json_response and all(key in json_response for key in ["title", "text", "proceeding", "category"]):
656
  return json_response
657
  else:
658
+ print(f"[WARNING] Invalid JSON structure from OpenAI. Text: {response_text[:300] if response_text else 'None'}...")
659
  raise ValueError("Invalid JSON structure")
660
  except Exception as e:
661
  print(f"[ERROR] OpenAI generation/parsing failed: {e}")
662
  return {
663
  "title": "Автоматично сформований заголовок (OpenAI)",
664
+ "text": response_text.strip() if 'response_text' in locals() and response_text else f"Помилка при отриманні відповіді: {str(e)}",
665
  "proceeding": "Не визначено",
666
  "category": "Помилка парсингу"
667
  }