"""分析失败动作,生成下一次修正建议""" import json from langchain_core.exceptions import OutputParserException from langchain_core.messages import HumanMessage, SystemMessage from pydantic import BaseModel, ValidationError from app.actions.plan import plan_materials from app.clients.llm import get_llm from app.processor.base import BaseNode from app.processor.state import QueryState from app.prompt.reflection import REFLECTION_SYSTEM_PROMPT from app.schemas.action_repair import ActionRepairPlan class ReflectionNode(BaseNode): name = "reflection_node" async def process(self, state: QueryState) -> QueryState: updated_state: QueryState = state.copy() llm_client = get_llm(ActionRepairPlan) payload = { "input_context": state["input_context"].model_dump(mode="json"), "requirement": state["requirement"].model_dump(mode="json"), "actions": [ action.model_dump(mode="json") for action in state.get("actions") or [] ], "validation_errors": [ error.model_dump() for error in state["validation_errors"] ], "previous_repair_plan": state["repair_plan"].model_dump() if state.get("repair_plan") else None, } if state.get("screen_plan") is not None: payload["screen_plan"] = state["screen_plan"].model_dump(mode="json") payload["component_materials"] = plan_materials(state) try: result = await llm_client.ainvoke( [ SystemMessage(content=REFLECTION_SYSTEM_PROMPT), HumanMessage(content=json.dumps(payload, ensure_ascii=False)), ] ) plan = ActionRepairPlan.model_validate( result.model_dump() if isinstance(result, BaseModel) else result ) except (ValidationError, OutputParserException): updated_state["repair_plan"] = None updated_state["failure_reason"] = "未能生成有效的动作修正建议" return updated_state updated_state["repair_plan"] = plan updated_state["retry_count"] = state.get("retry_count", 0) + int(plan.retryable) updated_state["failure_reason"] = None if plan.retryable else plan.reason return updated_state if __name__ == "__main__": import asyncio from app.processor.nodes.input_node import InputNode from app.schemas.action_validation import ActionValidationError from app.schemas.actions import UpdateAction from app.schemas.requirement import Requirement async def main(): state = InputNode().process( { "request": { "prompt": "把标题改成月度销售额", "screen": { "canvas": {"width": 1920, "height": 1080}, "nodes": [ { "id": "chart", "type": "chart", "layout": { "x": 100, "y": 200, "width": 400, "height": 300, }, "props": {"title": "销售额"}, } ], }, } } ) state["requirement"] = Requirement( intent="modify_screen", goal="修改标题", needs_clarification=False, changes=[ { "target_scope": "nodes", "target_ids": ["chart"], "operation": "update", "parameters": {"title": "月度销售额"}, } ], ) state["actions"] = [ UpdateAction( target_id="chart", section="props", path=["option", "title"], value="月度销售额", ) ] state["validation_passed"] = False state["validation_errors"] = [ ActionValidationError( action_index=0, code="execution_error", message="中间路径不存在: props ['option']", ) ] node = ReflectionNode() final_state = await node.process(state) print( json.dumps( final_state, ensure_ascii=False, indent=2, default=lambda value: value.model_dump(mode="json"), ) ) asyncio.run(main())