Skip to content

Commit 8b20e6d

Browse files
committed
feat: support agent reflection at local
1 parent e38f0a9 commit 8b20e6d

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed

veadk/reflector/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.

veadk/reflector/base_reflector.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from abc import ABC, abstractmethod
16+
17+
from pydantic import BaseModel
18+
19+
from veadk import Agent
20+
21+
22+
class ReflectorResult(BaseModel):
23+
optimized_prompt: str
24+
"""Optimized system prompt"""
25+
26+
reason: str
27+
"""Reason for the optimized prompt"""
28+
29+
30+
class BaseReflector(ABC):
31+
def __init__(self, agent: Agent):
32+
self.agent = agent
33+
34+
@abstractmethod
35+
def reflect(self, traces: list[dict]) -> ReflectorResult:
36+
"""Do agent self-reflection and generate a optimized system prompt.
37+
38+
Args:
39+
traces (list[dict]): The traces for agent reflection.
40+
41+
Returns:
42+
str: The optimized system prompt.
43+
"""
44+
...

veadk/reflector/local_reflector.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import json
16+
import os
17+
18+
from typing_extensions import override
19+
20+
from veadk import Agent, Runner
21+
from veadk.reflector.base_reflector import BaseReflector, ReflectorResult
22+
23+
24+
class LocalReflector(BaseReflector):
25+
def __init__(self, agent: Agent):
26+
super().__init__(agent)
27+
28+
def _read_traces_from_dir(self, trace_dir: str) -> list[dict]:
29+
traces = []
30+
for file in os.listdir(trace_dir):
31+
if file.endswith(".json"):
32+
with open(os.path.join(trace_dir, file), "r") as f:
33+
traces.append(json.load(f))
34+
return traces
35+
36+
@override
37+
async def reflect(self, trace_file: str) -> ReflectorResult:
38+
assert os.path.isfile(trace_file), f"{trace_file} is not a file."
39+
assert trace_file.endswith(".json"), f"{trace_file} is not a valid json file."
40+
41+
with open(trace_file, "r") as f:
42+
traces = json.load(f)
43+
44+
agent = Agent(
45+
name="agent_reflector",
46+
description="Reflect the traces and generate a optimized system prompt.",
47+
instruction="""You are a helpful optimizer and reflector.
48+
49+
Your task is to reflect the traces and generate a optimized system prompt (based on the given agent's system prompt).
50+
51+
You should response in json format with two fields:
52+
- optimized_prompt: The optimized system prompt.
53+
- reason: The reason for the optimized prompt.
54+
""",
55+
output_schema=ReflectorResult,
56+
)
57+
runner = Runner(agent)
58+
59+
response = await runner.run(
60+
messages=f"The system prompt is: {self.agent.instruction}, and the history traces are: {traces}"
61+
)
62+
63+
if response:
64+
try:
65+
optimized_prompt = json.loads(response).get("optimized_prompt", "")
66+
reason = json.loads(response).get("reason", "")
67+
except Exception as e:
68+
optimized_prompt = ""
69+
reason = f"response from optimizer is not valid json: {e}, response: {response}"
70+
else:
71+
optimized_prompt = ""
72+
reason = "response from optimizer is empty"
73+
74+
return ReflectorResult(
75+
optimized_prompt=optimized_prompt,
76+
reason=reason,
77+
)

0 commit comments

Comments
 (0)