feat:优化执行步骤
This commit is contained in:
+64
-7
@@ -13,7 +13,7 @@ from langgraph.types import Command
|
||||
from pydantic import Field
|
||||
|
||||
from app.actions.batch import BatchError, run_batch
|
||||
from app.schemas.actions import Action, AddAction
|
||||
from app.schemas.actions import Action, AddAction, AgentAction
|
||||
from app.schemas.component_resource import ComponentCatalog
|
||||
from app.schemas.screen import Screen
|
||||
|
||||
@@ -51,21 +51,55 @@ def get_nodes(node_ids: list[str], runtime: ToolRuntime[ScreenAgentContext]) ->
|
||||
}
|
||||
|
||||
|
||||
def _result_text(actions: list[Action]) -> str:
|
||||
def _result_text(
|
||||
before: Screen,
|
||||
after: Screen,
|
||||
actions: list[Action],
|
||||
undeclared_sample: frozenset[str] = frozenset(),
|
||||
) -> str:
|
||||
"""执行结果:除了动作数量,还给出执行后的画布和每个组件的布局
|
||||
|
||||
模型提交后才第一次看到结果,能自己发现位置超出画布、互相重叠、没排整齐等问题再修正,
|
||||
不用靠重复提交来试;本次动过布局或新增的组件前面标 *,已删除的单独列出
|
||||
"""
|
||||
lines = [f"执行成功,共 {len(actions)} 个动作已生效"]
|
||||
if sample := [
|
||||
sample = [
|
||||
action.node.id
|
||||
for action in actions
|
||||
if isinstance(action, AddAction) and action.sample_data
|
||||
]
|
||||
# 模型没写 sample_data 时是后端按物料猜的;说明这一点和怎么改,否则模型只看到“用了示例数据”,
|
||||
# 以为是自己的数据没生效,会反复提交同样的内容
|
||||
if guessed := [item for item in sample if item in undeclared_sample]:
|
||||
lines.append(
|
||||
f"未写 sample_data,按物料默认标成了示例数据:{'、'.join(guessed)};"
|
||||
"如果这些组件展示的数据都来自大屏上已有的组件,把 sample_data 设为 false 重新提交整批,否则不用处理"
|
||||
)
|
||||
if declared := [item for item in sample if item not in undeclared_sample]:
|
||||
lines.append(f"标为示例数据的新增组件:{'、'.join(declared)}")
|
||||
|
||||
old_layouts = {node.id: node.layout for node in before.nodes}
|
||||
lines.append(
|
||||
f"执行后画布 {after.canvas.width:g}x{after.canvas.height:g},组件布局(* 为本次改动):"
|
||||
)
|
||||
for node in after.nodes:
|
||||
layout = node.layout
|
||||
mark = "*" if old_layouts.get(node.id) != layout else " "
|
||||
lines.append(
|
||||
f"{mark} {node.id} {node.type} "
|
||||
f"x={layout.x:g} y={layout.y:g} width={layout.width:g} height={layout.height:g}"
|
||||
)
|
||||
if removed := [
|
||||
item for item in old_layouts if item not in {n.id for n in after.nodes}
|
||||
]:
|
||||
lines.append(f"使用物料示例数据的新增组件:{'、'.join(sample)}")
|
||||
lines.append(f"已删除:{'、'.join(removed)}")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
@tool
|
||||
def apply_actions(
|
||||
actions: Annotated[
|
||||
list[Action],
|
||||
list[AgentAction],
|
||||
# 空的一批会清掉之前成功的结果;参数校验失败不改状态,之前的结果保留
|
||||
Field(min_length=1, description="至少一个动作;不需要修改时不要调用,直接回复"),
|
||||
],
|
||||
@@ -74,10 +108,11 @@ def apply_actions(
|
||||
"""提交本次要对大屏做的全部修改
|
||||
|
||||
每次调用都是完整的一批,从原始大屏开始按顺序模拟执行,不在上一次调用的结果上累加
|
||||
成功时返回执行后的画布和各组件布局,用它核对结果,不对再重新提交整批
|
||||
失败时整批不生效,返回带动作序号的错误,修正后重新提交整批;以最后一次调用的结果为准
|
||||
"""
|
||||
try:
|
||||
completed, _ = run_batch(
|
||||
completed, after = run_batch(
|
||||
runtime.context.screen, runtime.context.catalog, actions
|
||||
)
|
||||
except BatchError as error:
|
||||
@@ -93,12 +128,34 @@ def apply_actions(
|
||||
],
|
||||
}
|
||||
)
|
||||
# 和上一次成功的提交完全一样:结果早已生效,再提交不会有变化,直接告诉模型结束,不再空转
|
||||
if completed == runtime.state.get("actions"):
|
||||
return Command(
|
||||
update={
|
||||
"messages": [
|
||||
ToolMessage(
|
||||
"这一批的结果和上一次提交完全相同,已经生效,不要重复提交;"
|
||||
"任务完成就调用 AgentReply 回复用户,没完成就改成不同的内容",
|
||||
tool_call_id=runtime.tool_call_id,
|
||||
)
|
||||
],
|
||||
}
|
||||
)
|
||||
undeclared = frozenset(
|
||||
action.node.id
|
||||
for action in actions
|
||||
if isinstance(action, AddAction)
|
||||
and "sample_data" not in action.model_fields_set
|
||||
)
|
||||
return Command(
|
||||
update={
|
||||
"actions": completed,
|
||||
"apply_error": None,
|
||||
"messages": [
|
||||
ToolMessage(_result_text(completed), tool_call_id=runtime.tool_call_id)
|
||||
ToolMessage(
|
||||
_result_text(runtime.context.screen, after, completed, undeclared),
|
||||
tool_call_id=runtime.tool_call_id,
|
||||
)
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user