mirror of
https://github.com/codeflash-ai/codeflash-internal.git
synced 2026-05-04 18:25:18 +00:00
Raise LLMOutputUnparseable on empty LLM responses instead of silently returning ""
When Azure OpenAI or Anthropic returns null/empty content (content filter, truncation, transient failure), call_openai/call_anthropic now raise LLMOutputUnparseable instead of returning an empty string that silently flows through the pipeline and produces 422 "Could not generate any optimizations." All optimizer callers catch LLMOutputUnparseable to preserve cost tracking while returning None.
This commit is contained in:
parent
7355b05663
commit
9b3cd48048
8 changed files with 53 additions and 8 deletions
|
|
@ -198,6 +198,17 @@ class LLMClient:
|
|||
response = await self.anthropic_client.messages.create(**kwargs) # type: ignore[union-attr]
|
||||
content = "".join(block.text for block in response.content if hasattr(block, "text"))
|
||||
|
||||
if not content:
|
||||
logger.warning(
|
||||
"Anthropic returned empty content: model=%s, stop_reason=%s",
|
||||
llm.name,
|
||||
response.stop_reason,
|
||||
)
|
||||
raise LLMOutputUnparseable(
|
||||
f"Empty response from {llm.name} (stop_reason={response.stop_reason})",
|
||||
cost=calculate_llm_cost(response, llm),
|
||||
)
|
||||
|
||||
return LLMResponse(
|
||||
content=content,
|
||||
usage=LLMUsage(input_tokens=response.usage.input_tokens, output_tokens=response.usage.output_tokens),
|
||||
|
|
@ -216,8 +227,21 @@ class LLMClient:
|
|||
model=llm.name, messages=messages, max_tokens=max_tokens
|
||||
)
|
||||
|
||||
content = response.choices[0].message.content if response.choices else None
|
||||
if not content:
|
||||
finish = response.choices[0].finish_reason if response.choices else "unknown"
|
||||
logger.warning(
|
||||
"OpenAI returned empty content: model=%s, finish_reason=%s",
|
||||
llm.name,
|
||||
finish,
|
||||
)
|
||||
raise LLMOutputUnparseable(
|
||||
f"Empty response from {llm.name} (finish_reason={finish})",
|
||||
cost=calculate_llm_cost(response, llm),
|
||||
)
|
||||
|
||||
return LLMResponse(
|
||||
content=response.choices[0].message.content or "",
|
||||
content=content,
|
||||
usage=LLMUsage(
|
||||
input_tokens=response.usage.prompt_tokens if response.usage else 0,
|
||||
output_tokens=response.usage.completion_tokens if response.usage else 0,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from openai.types.chat import ChatCompletionSystemMessageParam, ChatCompletionUs
|
|||
from aiservice.analytics.posthog import ph
|
||||
from aiservice.common_utils import validate_trace_id
|
||||
from aiservice.env_specific import debug_log_sensitive_data, debug_log_sensitive_data_from_callable
|
||||
from aiservice.llm import llm_client
|
||||
from aiservice.llm import LLMOutputUnparseable, llm_client
|
||||
from aiservice.llm_models import LLM, OPTIMIZE_MODEL
|
||||
from authapp.auth import AuthenticatedRequest
|
||||
from authapp.user import get_user_by_id
|
||||
|
|
@ -119,6 +119,9 @@ async def optimize_java_code_single(
|
|||
python_version="N/A", # Not applicable for Java
|
||||
context=obs_context,
|
||||
)
|
||||
except LLMOutputUnparseable as e:
|
||||
debug_log_sensitive_data(f"Empty LLM response for Java source:\n{source_code}")
|
||||
return None, e.cost, optimize_model.name
|
||||
except Exception:
|
||||
debug_log_sensitive_data(f"Failed to generate code for Java source:\n{source_code}")
|
||||
return None, None, optimize_model.name
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from openai.types.chat import ChatCompletionSystemMessageParam, ChatCompletionUs
|
|||
|
||||
from aiservice.analytics.posthog import ph
|
||||
from aiservice.env_specific import debug_log_sensitive_data, debug_log_sensitive_data_from_callable
|
||||
from aiservice.llm import llm_client
|
||||
from aiservice.llm import LLMOutputUnparseable, llm_client
|
||||
from aiservice.llm_models import OPTIMIZE_MODEL
|
||||
from aiservice.validators.java_validator import validate_java_syntax
|
||||
from core.languages.java.optimizer import is_multi_context_java
|
||||
|
|
@ -166,6 +166,9 @@ Here is the code to optimize:
|
|||
python_version=f"Java {language_version}",
|
||||
context=obs_context,
|
||||
)
|
||||
except LLMOutputUnparseable as e:
|
||||
debug_log_sensitive_data(f"Empty LLM response for source:\n{source_code}")
|
||||
return None, e.cost, optimize_model.name
|
||||
except Exception:
|
||||
debug_log_sensitive_data(f"Failed to generate code for source:\n{source_code}")
|
||||
return None, None, optimize_model.name
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ from aiservice.analytics.posthog import ph
|
|||
from aiservice.common.markdown_utils import split_markdown_code
|
||||
from aiservice.common_utils import validate_trace_id
|
||||
from aiservice.env_specific import debug_log_sensitive_data, debug_log_sensitive_data_from_callable
|
||||
from aiservice.llm import llm_client
|
||||
from aiservice.llm import LLMOutputUnparseable, llm_client
|
||||
from aiservice.llm_models import LLM, OPTIMIZE_MODEL
|
||||
from aiservice.validators.javascript_validator import validate_javascript_syntax, validate_typescript_syntax
|
||||
from authapp.auth import AuthenticatedRequest
|
||||
|
|
@ -155,6 +155,9 @@ You MUST output the target file. You may also output helper files if you optimiz
|
|||
python_version=language_version, # Reusing python_version field for language version
|
||||
context=obs_context,
|
||||
)
|
||||
except LLMOutputUnparseable as e:
|
||||
debug_log_sensitive_data(f"Empty LLM response for source:\n{source_code}")
|
||||
return None, e.cost, optimize_model.name
|
||||
except Exception:
|
||||
debug_log_sensitive_data(f"Failed to generate code for source:\n{source_code}")
|
||||
return None, None, optimize_model.name
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ from openai.types.chat import ChatCompletionSystemMessageParam, ChatCompletionUs
|
|||
from aiservice.analytics.posthog import ph
|
||||
from aiservice.common.markdown_utils import split_markdown_code
|
||||
from aiservice.env_specific import debug_log_sensitive_data, debug_log_sensitive_data_from_callable
|
||||
from aiservice.llm import llm_client
|
||||
from aiservice.llm import LLMOutputUnparseable, llm_client
|
||||
from aiservice.llm_models import OPTIMIZE_MODEL
|
||||
from aiservice.validators.javascript_validator import validate_javascript_syntax, validate_typescript_syntax
|
||||
from core.languages.js_ts.context_helpers import is_multi_context_js, is_multi_context_ts
|
||||
|
|
@ -167,6 +167,9 @@ Here is the code to optimize:
|
|||
python_version=language_version, # Reusing python_version field for language version
|
||||
context=obs_context,
|
||||
)
|
||||
except LLMOutputUnparseable as e:
|
||||
debug_log_sensitive_data(f"Empty LLM response for source:\n{source_code}")
|
||||
return None, e.cost, optimize_model.name
|
||||
except Exception:
|
||||
debug_log_sensitive_data(f"Failed to generate code for source:\n{source_code}")
|
||||
return None, None, optimize_model.name
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ from aiservice.analytics.posthog import ph
|
|||
from aiservice.background import fire_and_forget
|
||||
from aiservice.common_utils import parse_python_version, validate_trace_id
|
||||
from aiservice.env_specific import debug_log_sensitive_data, debug_log_sensitive_data_from_callable
|
||||
from aiservice.llm import llm_client
|
||||
from aiservice.llm import LLMOutputUnparseable, llm_client
|
||||
from aiservice.llm_models import LLM, OPTIMIZE_MODEL
|
||||
from authapp.auth import AuthenticatedRequest
|
||||
from authapp.user import get_user_by_id
|
||||
|
|
@ -74,6 +74,9 @@ async def jit_rewrite_python_code_single(
|
|||
python_version=python_version_str,
|
||||
context=obs_context,
|
||||
)
|
||||
except LLMOutputUnparseable as e:
|
||||
debug_log_sensitive_data(f"Empty LLM response for source:\n{ctx.source_code}")
|
||||
return None, e.cost, jit_rewrite_model.name
|
||||
except Exception:
|
||||
debug_log_sensitive_data(f"Failed to generate code for source:\n{ctx.source_code}")
|
||||
return None, None, jit_rewrite_model.name
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from aiservice.analytics.posthog import ph
|
|||
from aiservice.background import fire_and_forget
|
||||
from aiservice.common_utils import parse_python_version, validate_trace_id
|
||||
from aiservice.env_specific import debug_log_sensitive_data, debug_log_sensitive_data_from_callable
|
||||
from aiservice.llm import llm_client
|
||||
from aiservice.llm import LLMOutputUnparseable, llm_client
|
||||
from aiservice.llm_models import LLM, OPTIMIZE_MODEL
|
||||
from authapp.user import get_user_by_id
|
||||
from core.languages.python.optimizer.context_utils.optimizer_context import BaseOptimizerContext
|
||||
|
|
@ -82,6 +82,9 @@ async def generate_optimization_candidate(
|
|||
python_version=python_version_str,
|
||||
context=obs_context,
|
||||
)
|
||||
except LLMOutputUnparseable as e:
|
||||
debug_log_sensitive_data(f"Empty LLM response for source:\n{ctx.source_code}")
|
||||
return None, e.cost, optimize_model.name
|
||||
except Exception:
|
||||
debug_log_sensitive_data(f"Failed to generate code for source:\n{ctx.source_code}")
|
||||
return None, None, optimize_model.name
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ from aiservice.background import fire_and_forget
|
|||
from aiservice.common.markdown_utils import split_markdown_code
|
||||
from aiservice.common_utils import parse_python_version, validate_trace_id
|
||||
from aiservice.env_specific import debug_log_sensitive_data, debug_log_sensitive_data_from_callable
|
||||
from aiservice.llm import llm_client
|
||||
from aiservice.llm import LLMOutputUnparseable, llm_client
|
||||
from aiservice.llm_models import OPTIMIZE_MODEL
|
||||
from aiservice.validators.javascript_validator import validate_javascript_syntax, validate_typescript_syntax
|
||||
from core.languages.java.optimizer_lp import optimize_java_code_line_profiler
|
||||
|
|
@ -90,6 +90,9 @@ async def optimize_python_code_line_profiler_single(
|
|||
python_version=python_version_str,
|
||||
context=obs_context,
|
||||
)
|
||||
except LLMOutputUnparseable as e:
|
||||
debug_log_sensitive_data(f"Empty LLM response for source:\n{ctx.source_code}")
|
||||
return None, e.cost, optimize_model.name
|
||||
except Exception:
|
||||
debug_log_sensitive_data(f"Failed to generate code for source:\n{ctx.source_code}")
|
||||
return None, None, optimize_model.name
|
||||
|
|
|
|||
Loading…
Reference in a new issue