Files
NexQuant/rdagent/utils/agent/ret.py
T
amstrongzyf 32ecc61153 fix: refine the prompt to force complete code & refine the logic of running (#1069)
* change refine prompt for full code

* fix: fix the logic of running

* refine prompt

* fix some bugs

* fix

* add two guidelines

* refactor the code

* make costeer evaluator more logical

* refine eval prompt

* make costeer eval prompt markdown

* update code diff prompt

* correct pipeline

* feat: add apply_patch utility and update ret.py with patch functionality (#1071)

* restore to the right version

* fix the docstring

* fix extract_output fcn

* add inplace parameter to apply patch

* remove enable_runner_iteration and make the eval prompt same as main

* refine runner eval prompt based on main

* Update rdagent/scenarios/data_science/dev/runner/prompts.yaml

* add wait_retry

* refactor: move enable_runner_code_diff to DSRunnerCoSTEERSettings as diff_mode

* reformat and remove enable_runner_code_diff

---------

Co-authored-by: yuanteli <1957922024@qq.com>
Co-authored-by: Xu <v-xuminrui@microsoft.com>
Co-authored-by: Jensen Lee <91518020+Jensen246@users.noreply.github.com>
Co-authored-by: you-n-g <you-n-g@users.noreply.github.com>
Co-authored-by: Qizheng Li <jenssenlee@163.com>
2025-07-17 11:59:27 +08:00

103 lines
2.7 KiB
Python

"""
The output of a agent is very important.
We think this part can be shared.
"""
import json
import re
from abc import abstractclassmethod
from typing import Any
from rdagent.utils.agent.apply_patch import apply_patch_from_text
from rdagent.utils.agent.tpl import T
class AgentOut:
json_mode: bool = False # To get the output, is json_mode required.
@abstractclassmethod
def get_spec(cls, **context: Any) -> str:
raise NotImplementedError("Please implement the `get_spec` method")
@classmethod
def extract_output(cls, resp: str) -> Any:
raise resp
class PythonAgentOut(AgentOut):
@classmethod
def get_spec(cls):
return T(".tpl:PythonAgentOut").r()
@classmethod
def extract_output(cls, resp: str):
# We use lazy mode (.*?) to only extract the first code block in the response.
match = re.search(r".*```[Pp]ython\n(.*?)\n```.*", resp, re.DOTALL)
if match:
code = match.group(1)
code = re.sub(r"</?code>", "", code, flags=re.IGNORECASE)
return code
return resp
class MarkdownAgentOut(AgentOut):
@classmethod
def get_spec(cls):
return T(".tpl:MarkdownOut").r()
@classmethod
def extract_output(cls, resp: str):
match = re.search(r".*````markdown\n(.*)\n````.*", resp, re.DOTALL)
if match:
content = match.group(1)
return content
return resp
class BatchEditOut(AgentOut):
json_mode: bool = True
@classmethod
def get_spec(cls, with_del=True):
return T(".tpl:BatchEditOut").r(with_del=with_del)
@classmethod
def extract_output(cls, resp: str):
return json.loads(resp)
class PythonBatchEditOut(AgentOut):
@classmethod
def get_spec(cls, with_del=True):
return T(".tpl:PythonBatchEditOut").r(with_del=with_del)
@classmethod
def extract_output(cls, resp: str):
code_blocks = {}
pattern = re.compile(r"```(.*?)\n(.*?)\n```", re.DOTALL)
matches = pattern.findall(resp)
for match in matches:
file_name, code = match
code_blocks[file_name.strip()] = code.strip()
return code_blocks
class PythonBatchPatchOut(AgentOut):
@classmethod
def get_spec(cls):
return T(".tpl:PythonBatchPatchOut").r()
@classmethod
def extract_output(cls, resp: str) -> str:
# Step 1: extract patch by pattern
patch_pattern = re.compile(r"(\*\*\* Begin Patch\s*(.*?)\s*\*\*\* End Patch)", re.DOTALL)
match = patch_pattern.search(resp)
if match:
resp = match.group(1).rstrip()
# Step 2: apply the patch, this will modify the file in place
return apply_patch_from_text(resp, inplace=False)