Files
my-v0-server/app/processor/nodes/reflection_node.py
T

135 lines
4.7 KiB
Python

"""分析失败动作,生成下一次修正建议"""
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())