rename impact to review

This commit is contained in:
Aseem Saxena 2025-10-20 12:06:49 -07:00
parent e33c569365
commit 4c89091dcd
6 changed files with 55 additions and 88 deletions

View file

@ -1,30 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="pytest in tests" type="tests" factoryName="py.test" nameIsGenerated="true">
<module name="codeflash" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<option name="SDK_HOME" value="$USER_HOME$/mambaforge/envs/codeflash311/bin/python" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/cli" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<EXTENSION ID="net.ashald.envfile">
<option name="IS_ENABLED" value="false" />
<option name="IS_SUBST" value="false" />
<option name="IS_PATH_MACRO_SUPPORTED" value="false" />
<option name="IS_IGNORE_MISSING_FILES" value="false" />
<option name="IS_ENABLE_EXPERIMENTAL_INTEGRATIONS" value="false" />
<ENTRIES>
<ENTRY IS_ENABLED="true" PARSER="runconfig" IS_EXECUTABLE="false" />
</ENTRIES>
</EXTENSION>
<option name="_new_keywords" value="&quot;&quot;" />
<option name="_new_parameters" value="&quot;&quot;" />
<option name="_new_additionalArguments" value="&quot;&quot;" />
<option name="_new_target" value="&quot;$PROJECT_DIR$/cli/tests&quot;" />
<option name="_new_targetType" value="&quot;PATH&quot;" />
<method v="2" />
</configuration>
</component>

View file

@ -1,7 +1,7 @@
import os
from typing import Any
from pydantic.dataclasses import dataclass
from typing import Optional, Any
# The following pricing information is based on public OpenAI and Claude documentation
@ -16,8 +16,8 @@ class LLM:
max_tokens: int
api_version: str = ""
# Add new pricing attributes in USD per 1M tokens
input_cost: Optional[float] = None
output_cost: Optional[float] = None
input_cost: float | None = None
output_cost: float | None = None
# name of the model deployment on Azure OpenAI Service
@ -129,14 +129,14 @@ class GPT_5(LLM):
def calculate_llm_cost(response: Any, llm: LLM) -> float | None:
"""
Calculates the cost of an OpenAI API chat completion call.
"""Calculates the cost of an OpenAI API chat completion call.
Args:
response (dict): The JSON response from the OpenAI API call.
Returns:
float: The total cost in USD, or None if the cost cannot be calculated.
"""
try:
usage = response.usage
@ -162,4 +162,4 @@ OPTIMIZE_MODEL: LLM = OpenAI_GPT_4_1()
REFINEMENT_MODEL: LLM = Anthropic_Claude_4()
EXPLAINATIONS_MODEL: LLM = Anthropic_Claude_4()
RANKING_MODEL: LLM = OpenAI_GPT_4_1()
OPTIMIZATION_IMPACT_MODEL: LLM = Anthropic_Claude_4()
OPTIMIZATION_REVIEW_MODEL: LLM = Anthropic_Claude_4()

View file

@ -19,10 +19,9 @@ Including another URLconf
# from django.contrib import admin
from django.urls import path
from explanations.explanations import explanations_api
from log_features.log_features import features_api
from optimization_impact.optimization_impact import optimization_impact_api
from optimization_review.optimization_review import optimization_review_api
from optimizer.optimizer import optimize_api
from optimizer.optimizer_line_profiler import optimize_line_profiler_api
from optimizer.refinement import refinement_api
@ -37,5 +36,5 @@ urlpatterns = [
path("ai/refinement", refinement_api.urls),
path("ai/explain", explanations_api.urls),
path("ai/rank", ranker_api.urls),
path("ai/optimization_impact", optimization_impact_api.urls),
path("ai/optimization_review", optimization_review_api.urls),
]

View file

@ -3,4 +3,4 @@ from django.apps import AppConfig
class OptimizationImpactConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "optimization_impact"
name = "optimization_review"

View file

@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, cast
import sentry_sdk
from aiservice.env_specific import create_claude_client, debug_log_sensitive_data
from aiservice.models.aimodels import OPTIMIZATION_IMPACT_MODEL, calculate_llm_cost
from aiservice.models.aimodels import OPTIMIZATION_REVIEW_MODEL, calculate_llm_cost
from log_features.log_event import update_metadata_optimization_event, update_optimization_cost
from ninja import NinjaAPI, Schema
from openai.types.chat import ChatCompletionSystemMessageParam, ChatCompletionUserMessageParam
@ -17,25 +17,25 @@ if TYPE_CHECKING:
from aiservice.models.aimodels import LLM
from aiservice.analytics.posthog import ph
optimization_impact_api = NinjaAPI(urls_namespace="optimization_impact")
optimization_review_api = NinjaAPI(urls_namespace="optimization_review")
class OptimizationImpactErrorSchema(Schema):
class OptimizationReviewErrorSchema(Schema):
error: str
class ImpactLevel(str, Enum):
class ReviewLevel(str, Enum):
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
class OptimizationImpactResponseSchema(Schema):
impact: ImpactLevel
impact_explanation: str
class OptimizationReviewResponseSchema(Schema):
review: ReviewLevel
review_explanation: str
class OptimizationImpactSchema(Schema):
class OptimizationReviewSchema(Schema):
trace_id: str
code_diff: str
original_runtime: str
@ -51,8 +51,8 @@ class OptimizationImpactSchema(Schema):
calling_fn_details: str
def _build_optimization_impact_messages(
data: OptimizationImpactSchema,
def _build_optimization_review_messages(
data: OptimizationReviewSchema,
) -> list[ChatCompletionSystemMessageParam | ChatCompletionUserMessageParam]:
system_prompt = """You are an expert software engineer who writes really fast programs and is an expert in optimizing runtime and memory requirements of a program by rewriting it. You have deep expertise in modern programming best practices, and clean code principles.
@ -133,77 +133,75 @@ Output as a json markdown block with the key named as 'rating' and value being o
return [system_message, user_message]
async def get_optimization_impact(
request,
data: OptimizationImpactSchema,
optimization_impact_model: LLM = OPTIMIZATION_IMPACT_MODEL, # noqa: ANN001
) -> tuple[int, OptimizationImpactResponseSchema | OptimizationImpactErrorSchema]:
"""Compute optimization impact via Claude."""
ph(request.user, "aiservice-optimization-impact-called")
async def get_optimization_review(
request, data: OptimizationReviewSchema, optimization_review_model: LLM = OPTIMIZATION_REVIEW_MODEL
) -> tuple[int, OptimizationReviewResponseSchema | OptimizationReviewErrorSchema]:
"""Compute optimization review via Claude."""
ph(request.user, "aiservice-optimization-review-called")
try:
messages = _build_optimization_impact_messages(data)
messages = _build_optimization_review_messages(data)
debug_log_sensitive_data(f"{messages[0]}{messages[1]}")
async with create_claude_client() as claude_client:
# Call Claude API with retries
response = await claude_client.with_options(max_retries=2).chat.completions.create(
model=optimization_impact_model.name, messages=messages
model=optimization_review_model.name, messages=messages
)
# Calculate and update cost
cost = calculate_llm_cost(response, optimization_impact_model)
cost = calculate_llm_cost(response, optimization_review_model)
if cost:
await update_optimization_cost(data.trace_id, cost)
# Extract impact text from Claude response
impact_text = cast("str", response.choices[0].message.content).strip()
match = re.match(r"(.*?)```json(?:\n|\\n)(.*?)```(.*)", impact_text, re.DOTALL | re.MULTILINE)
# Extract review text from Claude response
review_text = cast("str", response.choices[0].message.content).strip()
match = re.match(r"(.*?)```json(?:\n|\\n)(.*?)```(.*)", review_text, re.DOTALL | re.MULTILINE)
if match:
try:
impact_level = json.loads(match.group(2).lower().strip())
impact_explanation = match.group(1) + match.group(3)
impact = OptimizationImpactResponseSchema(
impact=impact_level["rating"], impact_explanation=impact_explanation
review_level = json.loads(match.group(2).lower().strip())
review_explanation = match.group(1) + match.group(3)
review = OptimizationReviewResponseSchema(
review=review_level["rating"], review_explanation=review_explanation
)
except Exception as e:
# invalid response
logging.exception("Invalid optimization impact response")
logging.exception("Invalid optimization review response")
sentry_sdk.capture_exception(e)
debug_log_sensitive_data(f"Invalid response : {e}")
return 500, OptimizationImpactErrorSchema(error="Invalid response")
else:
ph(request.user, "aiservice-optimization-impact-successful")
return 200, impact
ph(request.user, "aiservice-optimization-review-successful")
return 200, review
else:
return 500, OptimizationImpactErrorSchema(error="Invalid response")
return 500, OptimizationReviewErrorSchema(error="Invalid response")
except Exception as e:
logging.exception("Error in optimization_impact")
logging.exception("Error in optimization_review")
sentry_sdk.capture_exception(e)
return 500, OptimizationImpactErrorSchema(error="Internal server error")
return 500, OptimizationReviewErrorSchema(error="Internal server error")
@optimization_impact_api.post(
@optimization_review_api.post(
"/",
response={
200: OptimizationImpactResponseSchema,
400: OptimizationImpactErrorSchema,
500: OptimizationImpactErrorSchema,
200: OptimizationReviewResponseSchema,
400: OptimizationReviewErrorSchema,
500: OptimizationReviewErrorSchema,
},
)
async def optimization_impact(
request, data: OptimizationImpactSchema
) -> tuple[int, OptimizationImpactResponseSchema | OptimizationImpactErrorSchema]:
response_code, output = await get_optimization_impact(request, data)
async def optimization_review(
request, data: OptimizationReviewSchema
) -> tuple[int, OptimizationReviewResponseSchema | OptimizationReviewErrorSchema]:
response_code, output = await get_optimization_review(request, data)
try:
if response_code == 200:
impact_event = output.impact.value
impact_explanation = output.impact_explanation
review_event = output.review.value
review_explanation = output.review_explanation
else:
impact_event = output.error
impact_explanation = ""
review_event = output.error
review_explanation = ""
await update_metadata_optimization_event(
trace_id=data.trace_id, impact=impact_event, impact_explanation=impact_explanation
)
trace_id=data.trace_id, impact=review_event, impact_explanation=review_explanation
) # impact keyword left for legacy reasons, will work with Hesham to perform the migration carefully
except Exception as e: # noqa: BLE001
debug_log_sensitive_data(f"event logging failed for optimization impact {e}")
debug_log_sensitive_data(f"event logging failed for optimization review {e}")
return response_code, output