fix(llm): skip unsupported json_object mode for openrouter stepfun models
This commit is contained in:
@@ -437,6 +437,26 @@ class LLMClient:
|
|||||||
self.client = AsyncOpenAI(api_key=api_key, base_url=base_url)
|
self.client = AsyncOpenAI(api_key=api_key, base_url=base_url)
|
||||||
# [/DEF:LLMClient.__init__:Function]
|
# [/DEF:LLMClient.__init__:Function]
|
||||||
|
|
||||||
|
# [DEF:LLMClient._supports_json_response_format:Function]
|
||||||
|
# @PURPOSE: Detect whether provider/model is likely compatible with response_format=json_object.
|
||||||
|
# @PRE: Client initialized with base_url and default_model.
|
||||||
|
# @POST: Returns False for known-incompatible combinations to avoid avoidable 400 errors.
|
||||||
|
def _supports_json_response_format(self) -> bool:
|
||||||
|
base = (self.base_url or "").lower()
|
||||||
|
model = (self.default_model or "").lower()
|
||||||
|
|
||||||
|
# OpenRouter routes to many upstream providers; some models reject json_object mode.
|
||||||
|
if "openrouter.ai" in base:
|
||||||
|
incompatible_tokens = (
|
||||||
|
"stepfun/",
|
||||||
|
"step-",
|
||||||
|
":free",
|
||||||
|
)
|
||||||
|
if any(token in model for token in incompatible_tokens):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
# [/DEF:LLMClient._supports_json_response_format:Function]
|
||||||
|
|
||||||
# [DEF:LLMClient.get_json_completion:Function]
|
# [DEF:LLMClient.get_json_completion:Function]
|
||||||
# @PURPOSE: Helper to handle LLM calls with JSON mode and fallback parsing.
|
# @PURPOSE: Helper to handle LLM calls with JSON mode and fallback parsing.
|
||||||
# @PRE: messages is a list of valid message dictionaries.
|
# @PRE: messages is a list of valid message dictionaries.
|
||||||
@@ -460,19 +480,34 @@ class LLMClient:
|
|||||||
with belief_scope("get_json_completion"):
|
with belief_scope("get_json_completion"):
|
||||||
response = None
|
response = None
|
||||||
try:
|
try:
|
||||||
|
use_json_mode = self._supports_json_response_format()
|
||||||
try:
|
try:
|
||||||
logger.info(f"[get_json_completion] Attempting LLM call with JSON mode for model: {self.default_model}")
|
logger.info(
|
||||||
|
f"[get_json_completion] Attempting LLM call for model: {self.default_model} "
|
||||||
|
f"(json_mode={'on' if use_json_mode else 'off'})"
|
||||||
|
)
|
||||||
logger.info(f"[get_json_completion] Base URL being used: {self.base_url}")
|
logger.info(f"[get_json_completion] Base URL being used: {self.base_url}")
|
||||||
logger.info(f"[get_json_completion] Number of messages: {len(messages)}")
|
logger.info(f"[get_json_completion] Number of messages: {len(messages)}")
|
||||||
logger.info(f"[get_json_completion] API Key present: {bool(self.api_key and len(self.api_key) > 0)}")
|
logger.info(f"[get_json_completion] API Key present: {bool(self.api_key and len(self.api_key) > 0)}")
|
||||||
|
|
||||||
|
if use_json_mode:
|
||||||
response = await self.client.chat.completions.create(
|
response = await self.client.chat.completions.create(
|
||||||
model=self.default_model,
|
model=self.default_model,
|
||||||
messages=messages,
|
messages=messages,
|
||||||
response_format={"type": "json_object"}
|
response_format={"type": "json_object"}
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
response = await self.client.chat.completions.create(
|
||||||
|
model=self.default_model,
|
||||||
|
messages=messages
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if "JSON mode is not enabled" in str(e) or "400" in str(e):
|
if use_json_mode and (
|
||||||
|
"JSON mode is not enabled" in str(e)
|
||||||
|
or "json_object is not supported" in str(e).lower()
|
||||||
|
or "response_format" in str(e).lower()
|
||||||
|
or "400" in str(e)
|
||||||
|
):
|
||||||
logger.warning(f"[get_json_completion] JSON mode failed or not supported: {str(e)}. Falling back to plain text response.")
|
logger.warning(f"[get_json_completion] JSON mode failed or not supported: {str(e)}. Falling back to plain text response.")
|
||||||
response = await self.client.chat.completions.create(
|
response = await self.client.chat.completions.create(
|
||||||
model=self.default_model,
|
model=self.default_model,
|
||||||
|
|||||||
Reference in New Issue
Block a user