feat: 完成资源接入
This commit is contained in:
@@ -3,12 +3,15 @@
|
||||
import json
|
||||
|
||||
from langchain_core.messages import HumanMessage, SystemMessage
|
||||
from langchain_core.exceptions import OutputParserException
|
||||
from pydantic import BaseModel, ValidationError
|
||||
|
||||
from app.clients.llm import get_llm
|
||||
from app.processor.base import BaseNode
|
||||
from app.processor.state import QueryState
|
||||
from app.prompt.action import ACTION_SYSTEM_PROMPT
|
||||
from app.schemas.actions import ActionBatch
|
||||
from app.schemas.action_validation import ActionValidationError, schema_errors
|
||||
|
||||
|
||||
def can_generate_actions(state: QueryState) -> bool:
|
||||
@@ -38,57 +41,63 @@ class ActionNode(BaseNode):
|
||||
name = "action_node"
|
||||
|
||||
async def process(self, state: QueryState) -> QueryState:
|
||||
updated_state: QueryState = state.copy()
|
||||
if not can_generate_actions(state):
|
||||
raise ValueError(
|
||||
"ActionNode 当前只支持无需规划和资源的 move、resize、update 需求"
|
||||
)
|
||||
batch = await get_llm(ActionBatch).ainvoke(
|
||||
[
|
||||
SystemMessage(content=ACTION_SYSTEM_PROMPT),
|
||||
HumanMessage(
|
||||
content=json.dumps(
|
||||
{
|
||||
"input_context": state["input_context"].model_dump(
|
||||
mode="json"
|
||||
),
|
||||
"requirement": state["requirement"].model_dump(mode="json"),
|
||||
"change_scope": state["change_scope"].model_dump(
|
||||
mode="json"
|
||||
),
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
),
|
||||
]
|
||||
)
|
||||
batch = ActionBatch.model_validate(batch.model_dump())
|
||||
allowed = {}
|
||||
for change in state["requirement"].changes:
|
||||
for target_id in change.target_ids:
|
||||
allowed.setdefault(target_id, set()).add(change.operation)
|
||||
existing = {node.id for node in state["input_context"].screen.nodes}
|
||||
for action in batch.actions:
|
||||
if action.target_id not in existing:
|
||||
raise ValueError(f"动作引用了不存在的组件: {action.target_id}")
|
||||
if action.type not in allowed.get(action.target_id, set()):
|
||||
raise ValueError(
|
||||
f"动作超出需求范围: {action.target_id} / {action.type}"
|
||||
)
|
||||
expected = {
|
||||
(target, operation) for target, ops in allowed.items() for operation in ops
|
||||
payload = {
|
||||
"input_context": state["input_context"].model_dump(mode="json"),
|
||||
"requirement": state["requirement"].model_dump(mode="json"),
|
||||
"change_scope": state["change_scope"].model_dump(mode="json"),
|
||||
}
|
||||
actual = {(action.target_id, action.type) for action in batch.actions}
|
||||
if expected - actual:
|
||||
raise ValueError(
|
||||
f"动作遗漏了需求中的目标或操作: {sorted(expected - actual)}"
|
||||
if state.get("repair_plan") is not None:
|
||||
payload.update(
|
||||
repair_plan=state["repair_plan"].model_dump(mode="json"),
|
||||
previous_actions=[
|
||||
action.model_dump(mode="json")
|
||||
for action in state.get("actions") or []
|
||||
],
|
||||
validation_errors=[
|
||||
error.model_dump() for error in state.get("validation_errors", [])
|
||||
],
|
||||
)
|
||||
return {
|
||||
**state,
|
||||
"actions": batch.actions,
|
||||
"validation_passed": None,
|
||||
"validation_errors": [],
|
||||
"simulated_screen": None,
|
||||
}
|
||||
# 配置和网络错误继续抛出,仅模型输出错误进入内容修正循环
|
||||
llm_client = get_llm(ActionBatch)
|
||||
|
||||
updated_state["actions"] = None
|
||||
updated_state["validation_passed"] = None
|
||||
updated_state["validation_errors"] = []
|
||||
updated_state["simulated_screen"] = None
|
||||
updated_state["failure_reason"] = None
|
||||
updated_state["status"] = "running"
|
||||
|
||||
try:
|
||||
result = await llm_client.ainvoke(
|
||||
[
|
||||
SystemMessage(content=ACTION_SYSTEM_PROMPT),
|
||||
HumanMessage(content=json.dumps(payload, ensure_ascii=False)),
|
||||
]
|
||||
)
|
||||
batch = ActionBatch.model_validate(
|
||||
result.model_dump() if isinstance(result, BaseModel) else result
|
||||
)
|
||||
except ValidationError as error:
|
||||
updated_state["validation_passed"] = False
|
||||
updated_state["validation_errors"] = schema_errors(error)
|
||||
return updated_state
|
||||
except OutputParserException:
|
||||
updated_state["validation_passed"] = False
|
||||
updated_state["validation_errors"] = [
|
||||
ActionValidationError(
|
||||
code="generation_error",
|
||||
message="模型输出无法解析为 ActionBatch,请按协议重新生成",
|
||||
)
|
||||
]
|
||||
return updated_state
|
||||
|
||||
updated_state["actions"] = batch.actions
|
||||
return updated_state
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user