2024-07-10 15:45:43 +08:00
|
|
|
import json
|
|
|
|
|
from pathlib import Path
|
2024-11-25 16:27:34 +08:00
|
|
|
from typing import Tuple
|
2024-07-10 15:45:43 +08:00
|
|
|
|
|
|
|
|
import numpy as np
|
|
|
|
|
from jinja2 import Environment, StrictUndefined
|
|
|
|
|
|
2025-02-18 13:38:13 +08:00
|
|
|
from rdagent.components.coder.CoSTEER.evaluators import CoSTEEREvaluator
|
2024-07-17 15:00:13 +08:00
|
|
|
from rdagent.components.coder.model_coder.model import ModelFBWorkspace, ModelTask
|
|
|
|
|
from rdagent.core.experiment import Task, Workspace
|
2024-07-10 15:45:43 +08:00
|
|
|
from rdagent.core.prompts import Prompts
|
2024-10-14 17:34:09 +08:00
|
|
|
from rdagent.oai.llm_conf import LLM_SETTINGS
|
2024-07-10 15:45:43 +08:00
|
|
|
from rdagent.oai.llm_utils import APIBackend
|
|
|
|
|
|
2024-11-25 16:27:34 +08:00
|
|
|
evaluate_prompts = Prompts(file_path=Path(__file__).parent / "prompts.yaml")
|
2024-07-10 15:45:43 +08:00
|
|
|
|
|
|
|
|
|
2025-01-17 22:53:05 +08:00
|
|
|
# This shape evaluator is also used in data_science
|
2024-10-21 15:56:04 +08:00
|
|
|
def shape_evaluator(prediction: np.ndarray, target_shape: Tuple = None) -> Tuple[str, bool]:
|
2024-07-10 15:45:43 +08:00
|
|
|
if target_shape is None or prediction is None:
|
2024-08-23 15:13:50 +08:00
|
|
|
return (
|
|
|
|
|
"No output generated from the model. No shape evaluation conducted.",
|
|
|
|
|
False,
|
|
|
|
|
)
|
2024-07-10 15:45:43 +08:00
|
|
|
pre_shape = prediction.shape
|
|
|
|
|
|
|
|
|
|
if pre_shape == target_shape:
|
|
|
|
|
return "The shape of the output is correct.", True
|
|
|
|
|
else:
|
2024-08-23 15:13:50 +08:00
|
|
|
return (
|
|
|
|
|
f"The shape of the output is incorrect. Expected {target_shape}, but got {pre_shape}.",
|
|
|
|
|
False,
|
|
|
|
|
)
|
2024-07-10 15:45:43 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def value_evaluator(
|
2024-10-21 15:56:04 +08:00
|
|
|
prediction: np.ndarray,
|
|
|
|
|
target: np.ndarray,
|
|
|
|
|
) -> Tuple[np.ndarray, bool]:
|
2024-08-01 18:08:23 +08:00
|
|
|
if prediction is None:
|
|
|
|
|
return "No output generated from the model. Skip value evaluation", False
|
|
|
|
|
elif target is None:
|
2024-08-23 15:13:50 +08:00
|
|
|
return (
|
|
|
|
|
"No ground truth output provided. Value evaluation not impractical",
|
|
|
|
|
False,
|
|
|
|
|
)
|
2024-07-10 15:45:43 +08:00
|
|
|
else:
|
|
|
|
|
# Calculate the mean absolute difference
|
2024-10-21 15:56:04 +08:00
|
|
|
diff = np.mean(np.abs(target - prediction))
|
2024-07-10 15:45:43 +08:00
|
|
|
return (
|
|
|
|
|
f"The value of the output is correct. The mean absolute difference is {diff}.",
|
|
|
|
|
diff < 0.1,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2025-02-18 13:38:13 +08:00
|
|
|
class ModelCodeEvaluator(CoSTEEREvaluator):
|
2024-07-10 15:45:43 +08:00
|
|
|
def evaluate(
|
|
|
|
|
self,
|
|
|
|
|
target_task: Task,
|
2024-07-17 15:00:13 +08:00
|
|
|
implementation: Workspace,
|
|
|
|
|
gt_implementation: Workspace,
|
2024-07-10 15:45:43 +08:00
|
|
|
model_execution_feedback: str = "",
|
|
|
|
|
model_value_feedback: str = "",
|
|
|
|
|
):
|
|
|
|
|
assert isinstance(target_task, ModelTask)
|
2024-07-17 15:00:13 +08:00
|
|
|
assert isinstance(implementation, ModelFBWorkspace)
|
2024-07-10 15:45:43 +08:00
|
|
|
if gt_implementation is not None:
|
2024-07-17 15:00:13 +08:00
|
|
|
assert isinstance(gt_implementation, ModelFBWorkspace)
|
2024-07-10 15:45:43 +08:00
|
|
|
|
2024-07-15 08:28:34 +00:00
|
|
|
model_task_information = target_task.get_task_information()
|
2025-01-17 22:53:05 +08:00
|
|
|
code = implementation.all_codes
|
2024-07-10 15:45:43 +08:00
|
|
|
|
|
|
|
|
system_prompt = (
|
|
|
|
|
Environment(undefined=StrictUndefined)
|
|
|
|
|
.from_string(evaluate_prompts["evaluator_code_feedback"]["system"])
|
2024-09-29 18:43:17 +08:00
|
|
|
.render(
|
2024-10-14 17:34:09 +08:00
|
|
|
scenario=(
|
2024-11-06 13:14:35 +08:00
|
|
|
self.scen.get_scenario_all_desc(target_task, filtered_tag=target_task.model_type)
|
2024-10-14 17:34:09 +08:00
|
|
|
if self.scen is not None
|
|
|
|
|
else "No scenario description."
|
|
|
|
|
)
|
2024-09-29 18:43:17 +08:00
|
|
|
)
|
2024-07-10 15:45:43 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
execution_feedback_to_render = model_execution_feedback
|
|
|
|
|
for _ in range(10): # 10 times to split the content is enough
|
|
|
|
|
user_prompt = (
|
|
|
|
|
Environment(undefined=StrictUndefined)
|
|
|
|
|
.from_string(
|
|
|
|
|
evaluate_prompts["evaluator_code_feedback"]["user"],
|
|
|
|
|
)
|
|
|
|
|
.render(
|
|
|
|
|
model_information=model_task_information,
|
|
|
|
|
code=code,
|
|
|
|
|
model_execution_feedback=execution_feedback_to_render,
|
|
|
|
|
model_value_feedback=model_value_feedback,
|
2025-01-17 22:53:05 +08:00
|
|
|
gt_code=gt_implementation.all_codes if gt_implementation else None,
|
2024-07-10 15:45:43 +08:00
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
if (
|
|
|
|
|
APIBackend().build_messages_and_calculate_token(
|
|
|
|
|
user_prompt=user_prompt,
|
|
|
|
|
system_prompt=system_prompt,
|
|
|
|
|
)
|
2024-10-14 17:34:09 +08:00
|
|
|
> LLM_SETTINGS.chat_token_limit
|
2024-07-10 15:45:43 +08:00
|
|
|
):
|
|
|
|
|
execution_feedback_to_render = execution_feedback_to_render[len(execution_feedback_to_render) // 2 :]
|
|
|
|
|
else:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
critic_response = APIBackend().build_messages_and_create_chat_completion(
|
|
|
|
|
user_prompt=user_prompt,
|
|
|
|
|
system_prompt=system_prompt,
|
|
|
|
|
json_mode=False,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return critic_response, None
|
|
|
|
|
|
|
|
|
|
|
2025-02-18 13:38:13 +08:00
|
|
|
class ModelFinalEvaluator(CoSTEEREvaluator):
|
2024-07-10 15:45:43 +08:00
|
|
|
def evaluate(
|
|
|
|
|
self,
|
|
|
|
|
target_task: Task,
|
2024-07-17 15:00:13 +08:00
|
|
|
implementation: Workspace,
|
|
|
|
|
gt_implementation: Workspace,
|
2024-07-10 15:45:43 +08:00
|
|
|
model_execution_feedback: str,
|
2024-12-03 13:55:28 +08:00
|
|
|
model_shape_feedback: str,
|
2024-07-10 15:45:43 +08:00
|
|
|
model_value_feedback: str,
|
|
|
|
|
model_code_feedback: str,
|
|
|
|
|
):
|
|
|
|
|
assert isinstance(target_task, ModelTask)
|
2024-07-17 15:00:13 +08:00
|
|
|
assert isinstance(implementation, ModelFBWorkspace)
|
2024-07-10 15:45:43 +08:00
|
|
|
if gt_implementation is not None:
|
2024-07-17 15:00:13 +08:00
|
|
|
assert isinstance(gt_implementation, ModelFBWorkspace)
|
2024-07-10 15:45:43 +08:00
|
|
|
|
|
|
|
|
system_prompt = (
|
|
|
|
|
Environment(undefined=StrictUndefined)
|
|
|
|
|
.from_string(evaluate_prompts["evaluator_final_feedback"]["system"])
|
2024-09-29 18:43:17 +08:00
|
|
|
.render(
|
2024-10-14 17:34:09 +08:00
|
|
|
scenario=(
|
2024-11-06 13:14:35 +08:00
|
|
|
self.scen.get_scenario_all_desc(target_task, filtered_tag=target_task.model_type)
|
2024-10-14 17:34:09 +08:00
|
|
|
if self.scen is not None
|
|
|
|
|
else "No scenario description."
|
|
|
|
|
)
|
2024-09-29 18:43:17 +08:00
|
|
|
)
|
2024-07-10 15:45:43 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
execution_feedback_to_render = model_execution_feedback
|
|
|
|
|
|
|
|
|
|
for _ in range(10): # 10 times to split the content is enough
|
|
|
|
|
user_prompt = (
|
|
|
|
|
Environment(undefined=StrictUndefined)
|
|
|
|
|
.from_string(
|
|
|
|
|
evaluate_prompts["evaluator_final_feedback"]["user"],
|
|
|
|
|
)
|
|
|
|
|
.render(
|
2024-07-15 08:28:34 +00:00
|
|
|
model_information=target_task.get_task_information(),
|
2024-07-10 15:45:43 +08:00
|
|
|
model_execution_feedback=execution_feedback_to_render,
|
2024-12-03 13:55:28 +08:00
|
|
|
model_shape_feedback=model_shape_feedback,
|
2024-07-10 15:45:43 +08:00
|
|
|
model_code_feedback=model_code_feedback,
|
|
|
|
|
model_value_feedback=model_value_feedback,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
if (
|
|
|
|
|
APIBackend().build_messages_and_calculate_token(
|
|
|
|
|
user_prompt=user_prompt,
|
|
|
|
|
system_prompt=system_prompt,
|
|
|
|
|
)
|
2024-10-14 17:34:09 +08:00
|
|
|
> LLM_SETTINGS.chat_token_limit
|
2024-07-10 15:45:43 +08:00
|
|
|
):
|
|
|
|
|
execution_feedback_to_render = execution_feedback_to_render[len(execution_feedback_to_render) // 2 :]
|
|
|
|
|
else:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
final_evaluation_dict = json.loads(
|
|
|
|
|
APIBackend().build_messages_and_create_chat_completion(
|
|
|
|
|
user_prompt=user_prompt,
|
|
|
|
|
system_prompt=system_prompt,
|
|
|
|
|
json_mode=True,
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
if isinstance(final_evaluation_dict["final_decision"], str) and final_evaluation_dict[
|
|
|
|
|
"final_decision"
|
|
|
|
|
].lower() in ("true", "false"):
|
|
|
|
|
final_evaluation_dict["final_decision"] = bool(final_evaluation_dict["final_decision"])
|
|
|
|
|
return (
|
|
|
|
|
final_evaluation_dict["final_feedback"],
|
|
|
|
|
final_evaluation_dict["final_decision"],
|
|
|
|
|
)
|