Trae Agent LakeView 核心逻辑详解
概述
LakeView 是 Trae Agent 的智能步骤分析器,它使用独立的 LLM 对 Agent 的每一步执行进行语义理解和标签分类,帮助用户更直观地理解 Agent 的工作流程。
核心功能:
- 自动提取每一步的任务描述
- 智能分类步骤类型(写测试、验证、检查代码等)
- 使用表情符号直观展示步骤性质
- 在 CLI 中提供增强的可视化输出
核心架构
┌─────────────────────────────────────────────────────────────────┐
│ LakeView 架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Agent 执行步骤 │ │
│ │ (AgentStep: llm_response, tool_calls, ...) │ │
│ └────────────────────┬────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ LakeView.create_lakeview_step() │ │
│ │ 1. 转换步骤为文本描述 │ │
│ │ 2. 调用 Extractor LLM 提取任务描述 │ │
│ │ 3. 调用 Tagger LLM 分类步骤标签 │ │
│ │ 4. 生成 LakeViewStep 对象 │ │
│ └────────────────────┬────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ CLI Console 渲染 │ │
│ │ - 显示表情符号标签 │ │
│ │ - 显示任务描述 │ │
│ │ - 显示详细信息 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
核心类详解
1. LakeView - 主控制器
文件: trae_agent/utils/lake_view.py
class LakeView:
"""LakeView 主类,负责分析 Agent 步骤"""
def __init__(self, lake_view_config: LakeviewConfig | None):
if lake_view_config is None:
return
# 使用独立的模型配置
self.model_config = lake_view_config.model
# 创建独立的 LLM 客户端(与 Agent 使用不同的模型)
self.lakeview_llm_client: LLMClient = LLMClient(self.model_config)
# 存储历史步骤文本
self.steps: list[str] = []
设计特点:
- 使用独立的 LLM 客户端,与 Agent 的 LLM 分离
- 可以配置不同的模型(如用轻量级模型做分析)
- 维护步骤历史,用于上下文理解
2. LakeViewStep - 分析结果
@dataclass
class LakeViewStep:
"""LakeView 分析结果"""
desc_task: str # 任务描述(简洁,≤10词)
desc_details: str # 详细信息(补充,≤30词)
tags_emoji: str # 标签表情符号展示
示例:
LakeViewStep(
desc_task="The agent is examining source code",
desc_details="The agent is searching for 'function_name' in the code repository",
tags_emoji="👁️ EXAMINE_CODE"
)
核心流程
步骤分析流程
async def create_lakeview_step(self, agent_step: AgentStep) -> LakeViewStep | None:
"""为 Agent 步骤创建 LakeView 分析"""
# 1. 获取上一步的文本描述
previous_step_str = self.steps[-1] if len(self.steps) > 1 else "(none)"
# 2. 将当前步骤转换为文本
this_step_str = self._agent_step_str(agent_step)
if this_step_str:
# 3. 提取任务描述(使用 Extractor LLM)
desc_task, desc_details = await self.extract_task_in_step(
previous_step_str, this_step_str
)
# 4. 分类步骤标签(使用 Tagger LLM)
tags = await self.extract_tag_in_step(this_step_str)
# 5. 生成表情符号标签
tags_emoji = self.get_label(tags)
return LakeViewStep(desc_task, desc_details, tags_emoji)
return None
LLM Prompt 设计
1. Extractor Prompt - 任务提取
EXTRACTOR_PROMPT = """
Given the preceding excerpt, your job is to determine "what task is the agent performing in <this_step>".
Output your answer in two granularities: <task>...</task><details>...</details>.
In the <task> tag, the answer should be concise and general. It should omit ANY bug-specific details, and contain at most 10 words.
In the <details> tag, the answer should complement the <task> tag by adding bug-specific details. It should be informative and contain at most 30 words.
Examples:
<task>The agent is writing a reproduction test script.</task><details>The agent is writing "test_bug.py" to reproduce the bug in XXX-Project's create_foo method not comparing sizes correctly.</details>
<task>The agent is examining source code.</task><details>The agent is searching for "function_name" in the code repository, that is related to the "foo.py:function_name" line in the stack trace.</details>
<task>The agent is fixing the reproduction test script.</task><details>The agent is fixing "test_bug.py" that forgets to import the function "foo", causing a NameError.</details>
Now, answer the question "what task is the agent performing in <this_step>".
Again, provide only the answer with no other commentary. The format should be "<task>...</task><details>...</details>".
"""
设计要点:
- 两级描述: 简洁任务 + 详细补充
- 长度限制: task ≤10词, details ≤30词
- 示例引导: 提供具体示例帮助 LLM 理解格式
2. Tagger Prompt - 标签分类
TAGGER_PROMPT = """
Given the trajectory, your job is to determine "what task is the agent performing in the current step".
Output your answer by choosing the applicable tags in the below list for the current step.
If it is performing multiple tasks in one step, choose ALL applicable tags, separated by a comma.
<tags>
WRITE_TEST: It writes a test script to reproduce the bug, or modifies a non-working test script to fix problems found in testing.
VERIFY_TEST: It runs the reproduction test script to verify the testing environment is working.
EXAMINE_CODE: It views, searches, or explores the code repository to understand the cause of the bug.
WRITE_FIX: It modifies the source code to fix the identified bug.
VERIFY_FIX: It runs the reproduction test or existing tests to verify the fix indeed solves the bug.
REPORT: It reports to the user that the job is completed or some progress has been made.
THINK: It analyzes the bug through thinking, but does not perform concrete actions right now.
OUTLIER: A major part in this step does not fit into any tag above, such as running a shell command to install dependencies.
</tags>
<examples>
If the agent is opening a file to examine, output <tags>EXAMINE_CODE</tags>.
If the agent is fixing a known problem in the reproduction test script and then running it again, output <tags>WRITE_TEST,VERIFY_TEST</tags>.
If the agent is merely thinking about the root cause of the bug without other actions, output <tags>THINK</tags>.
</examples>
Output only the tags with no other commentary. The format should be <tags>...</tags>
"""
标签系统:
| 标签 | 表情 | 含义 |
|---|---|---|
WRITE_TEST | ☑️ | 编写测试脚本 |
VERIFY_TEST | ✅ | 验证测试环境 |
EXAMINE_CODE | 👁️ | 检查源代码 |
WRITE_FIX | 📝 | 编写修复代码 |
VERIFY_FIX | 🔥 | 验证修复效果 |
REPORT | 📣 | 报告进度/完成 |
THINK | 🧠 | 分析思考 |
OUTLIER | ⁉️ | 其他操作 |
核心方法详解
1. extract_task_in_step - 提取任务描述
async def extract_task_in_step(self, prev_step: str, this_step: str) -> tuple[str, str]:
"""使用 LLM 提取当前步骤的任务描述"""
# 构建消息
llm_messages = [
LLMMessage(
role="user",
content=f"The following is an excerpt of the steps trying to solve a software bug by an AI agent: <previous_step>{prev_step}</previous_step><this_step>{this_step}</this_step>",
),
LLMMessage(role="assistant", content="I understand."),
LLMMessage(role="user", content=EXTRACTOR_PROMPT),
LLMMessage(
role="assistant",
content="Sure. Here is the task the agent is performing: <task>The agent",
),
]
# 设置低温度,确保输出稳定
self.model_config.temperature = 0.1
# 调用 LLM
llm_response = self.lakeview_llm_client.chat(
model_config=self.model_config,
messages=llm_messages,
reuse_history=False, # 不使用历史上下文
)
content = llm_response.content.strip()
# 重试机制:确保格式正确
retry = 0
while retry < 10 and not self._is_valid_format(content):
retry += 1
llm_response = self.lakeview_llm_client.chat(...)
content = llm_response.content.strip()
# 解析结果
desc_task, _, desc_details = content.rpartition("</task>")
return desc_task, desc_details
关键设计:
- 低温度 (0.1): 确保输出稳定可预测
- 重试机制: 最多重试 10 次,确保格式正确
- 不使用历史:
reuse_history=False,每次独立调用
2. extract_tag_in_step - 提取标签
async def extract_tag_in_step(self, step: str) -> list[str]:
"""使用 LLM 分类步骤标签"""
# 格式化历史步骤
steps_fmt = "\n\n".join(
f'<step id="{ind + 1}">\n{s.strip()}\n</step>'
for ind, s in enumerate(self.steps)
)
# 长度限制:避免超出上下文窗口
if len(steps_fmt) > 300_000:
return []
llm_messages = [
LLMMessage(
role="user",
content=f"Below is the trajectory...\n\n{steps_fmt}\n\n<current_step>{step}</current_step>",
),
LLMMessage(role="assistant", content="I understand."),
LLMMessage(role="user", content=TAGGER_PROMPT),
LLMMessage(role="assistant", content="Sure. The tags are: <tags>"),
]
retry = 0
while retry < 10:
llm_response = self.lakeview_llm_client.chat(...)
content = "<tags>" + llm_response.content.lstrip()
# 使用正则提取标签
matched_tags = tags_re.findall(content)
tags = [tag.strip() for tag in matched_tags[0].split(",")]
# 验证所有标签都有效
if all(tag in KNOWN_TAGS for tag in tags):
return tags
retry += 1
return []
关键设计:
- 历史上下文: 提供完整轨迹帮助理解当前步骤
- 长度限制: 超过 300K 字符跳过,避免超时
- 正则提取: 使用
<tags>...</tags>正则精确提取 - 标签验证: 确保提取的标签在已知集合中
3. _agent_step_str - 步骤序列化
def _agent_step_str(self, agent_step: AgentStep) -> str | None:
"""将 AgentStep 转换为文本描述"""
if agent_step.llm_response is None:
return None
# 获取 LLM 回复内容
content = agent_step.llm_response.content.strip()
# 格式化工具调用
tool_calls_content = ""
if agent_step.llm_response.tool_calls is not None:
tool_calls_content = "\n".join(
f"[`{tool_call.name}`] `{tool_call.arguments}`"
for tool_call in agent_step.llm_response.tool_calls
)
content = f"{content}\n\nTool calls:\n{tool_calls_content}"
return content
输出示例:
I'll help you fix this bug. Let me first examine the code to understand the issue.
Tool calls:
[`view`] `{"path": "/repo/src/main.py"}`
[`bash`] `{"command": "grep -r \"function_name\" /repo"}`
与 CLI 模块的集成
CLIConsole 基类
文件: trae_agent/utils/cli/cli_console.py
class CLIConsole(ABC):
def __init__(self, mode: ConsoleMode, lakeview_config: LakeviewConfig | None = None):
self.mode: ConsoleMode = mode
self.set_lakeview(lakeview_config)
self.console_step_history: dict[int, ConsoleStep] = {}
def set_lakeview(self, lakeview_config: LakeviewConfig | None = None):
"""设置 LakeView 配置"""
if lakeview_config:
self.lake_view: LakeView | None = LakeView(lakeview_config)
else:
self.lake_view = None
SimpleConsole 实现
文件: trae_agent/utils/cli/simple_console.py
class SimpleConsole(CLIConsole):
def update_status(self, agent_step: AgentStep | None = None, ...):
"""更新状态,触发 LakeView 分析"""
# 如果启用了 LakeView,在后台生成分析
if (
self.lake_view
and not self.console_step_history[agent_step.step_number]
.lake_view_panel_generator
):
self.console_step_history[agent_step.step_number]\
.lake_view_panel_generator = asyncio.create_task(
self._create_lakeview_step_display(agent_step)
)
async def _create_lakeview_step_display(self, agent_step: AgentStep) -> Panel | None:
"""创建 LakeView 显示面板"""
if self.lake_view is None:
return None
# 调用 LakeView 分析
lake_view_step = await self.lake_view.create_lakeview_step(agent_step)
if lake_view_step is None:
return None
# 创建 Rich Panel
return Panel(
f"""[{lake_view_step.tags_emoji}] The agent [bold]{lake_view_step.desc_task}[/bold]
{lake_view_step.desc_details}""",
title=f"Step {agent_step.step_number} (Lakeview)",
border_style=color,
width=80,
)
async def _print_lakeview_summary(self):
"""打印 LakeView 总结"""
self.console.print("\n[bold]Lakeview Summary:[/bold]")
self.console.print("=" * 60)
for step in self.console_step_history.values():
if step.lake_view_panel_generator:
lake_view_panel = await step.lake_view_panel_generator
if lake_view_panel:
self.console.print(lake_view_panel)
异步设计:
asyncio.create_task(): 在后台异步执行 LakeView 分析- 不阻塞主 Agent 执行流程
- 最终汇总时等待并显示结果
配置集成
配置文件示例
# trae_config.yaml
model_providers:
openrouter:
api_key: sk-or-v1-xxx
provider: openrouter
base_url: https://openrouter.ai/api/v1
models:
trae_agent_model:
model_provider: openrouter
model: openai/gpt-4o
max_tokens: 4096
temperature: 0.5
# LakeView 使用独立的模型配置
lakeview_model:
model_provider: openrouter
model: openai/gpt-4o-mini # 可以使用轻量级模型
max_tokens: 2048
temperature: 0.1
agents:
trae_agent:
model: trae_agent_model
enable_lakeview: true # 启用 LakeView
max_steps: 200
# LakeView 配置
lakeview:
model: lakeview_model
核心文件索引
| 文件 | 职责 | 重要性 |
|---|---|---|
utils/lake_view.py | LakeView 核心实现 | ⭐⭐⭐ |
utils/cli/cli_console.py | CLI 基类和 LakeView 集成 | ⭐⭐⭐ |
utils/cli/simple_console.py | SimpleConsole 实现 | ⭐⭐⭐ |
utils/config.py | LakeviewConfig 配置类 | ⭐⭐ |
总结
| 特性 | 说明 |
|---|---|
| 独立 LLM | 使用独立的 LLM 客户端,可与 Agent 使用不同模型 |
| 异步执行 | 后台异步分析,不阻塞主流程 |
| 智能分类 | 8 种标签自动分类,表情符号直观展示 |
| 两级描述 | 简洁任务 + 详细补充 |
| 容错设计 | 重试机制、长度限制、格式验证 |
使用场景:
- 复杂的 bug 修复任务
- 需要理解 Agent 决策过程
- 教学演示和调试分析
性能考虑:
- LakeView 会增加额外的 LLM 调用开销
- 可以使用轻量级模型(如 gpt-4o-mini)降低成本
- 长轨迹可能触发长度限制,此时跳过标签分类
最后更新: 2026-03-16