feat: Agent 批量测试、作业助手与上传预览;Windows 启动脚本与文档- 新增 run_agent_test_cases 与示例 JSON、(红头)agent测试用例文档
- 扩展 test_agent_execution(--homework、UTF-8 控制台) - 后端:uploads 预览、file_read、工作流与对话落盘等 - 前端:AgentChatPreview 与设计器相关调整 - 忽略 redis二进制、agent_workspaces、uploads、tessdata 等本机产物 Made-with: Cursor
This commit is contained in:
@@ -812,6 +812,25 @@ class WorkflowEngine:
|
||||
logger.info(f"[rjb] 从嵌套上游输入提升 user_id 到节点 {node_id} 输入顶层")
|
||||
break
|
||||
|
||||
# Start→下游 带 sourceHandle 时 query/USER_INPUT/attachments 常在 right 内,提升到顶层供 LLM 与其它节点读取
|
||||
if isinstance(input_data, dict):
|
||||
_rk = input_data.get('right')
|
||||
if isinstance(_rk, dict):
|
||||
for _uk in (
|
||||
'query',
|
||||
'USER_INPUT',
|
||||
'user_input',
|
||||
'attachments',
|
||||
'text',
|
||||
'message',
|
||||
'content',
|
||||
):
|
||||
if input_data.get(_uk) not in (None, ''):
|
||||
continue
|
||||
if _uk in _rk and _rk[_uk] is not None:
|
||||
input_data[_uk] = _rk[_uk]
|
||||
logger.debug(f"[rjb] 从 right 提升到顶层: {_uk}")
|
||||
|
||||
logger.debug(f"[rjb] 节点输入结果: node_id={node_id}, input_data={input_data}")
|
||||
return input_data
|
||||
|
||||
@@ -1443,6 +1462,58 @@ class WorkflowEngine:
|
||||
if user_query:
|
||||
break
|
||||
|
||||
# Start→LLM 常见:边带 sourceHandle=right,Start 输出在 input_data["right"] 下,
|
||||
# 顶层无 query/USER_INPUT,旧逻辑会退化为 JSON 整包,模型看不到附件路径。
|
||||
if not user_query:
|
||||
for bucket in ("right", "left", "output", "data"):
|
||||
nested = input_data.get(bucket)
|
||||
if not isinstance(nested, dict):
|
||||
continue
|
||||
for key in (
|
||||
"query",
|
||||
"input",
|
||||
"text",
|
||||
"message",
|
||||
"content",
|
||||
"user_input",
|
||||
"USER_INPUT",
|
||||
):
|
||||
if key not in nested:
|
||||
continue
|
||||
value = nested[key]
|
||||
logger.info(
|
||||
f"[rjb] 从嵌套桶 {bucket}.{key} 提取 user_query 候选, type={type(value)}"
|
||||
)
|
||||
if isinstance(value, str):
|
||||
user_query = value
|
||||
logger.info(
|
||||
f"[rjb] 从{bucket}.{key} 提取到字符串 user_query 长度={len(value)}"
|
||||
)
|
||||
break
|
||||
if isinstance(value, dict):
|
||||
for sub_key in (
|
||||
"query",
|
||||
"input",
|
||||
"text",
|
||||
"message",
|
||||
"content",
|
||||
"user_input",
|
||||
"USER_INPUT",
|
||||
):
|
||||
if sub_key not in value:
|
||||
continue
|
||||
sv = value[sub_key]
|
||||
if isinstance(sv, str):
|
||||
user_query = sv
|
||||
logger.info(
|
||||
f"[rjb] 从{bucket}.{key}.{sub_key} 提取到 user_query"
|
||||
)
|
||||
break
|
||||
if user_query:
|
||||
break
|
||||
if user_query:
|
||||
break
|
||||
|
||||
# 如果还是没有,使用整个input_data(但排除系统字段)
|
||||
if not user_query:
|
||||
filtered_data = {k: v for k, v in input_data.items() if not k.startswith('_')}
|
||||
@@ -1607,6 +1678,12 @@ class WorkflowEngine:
|
||||
_tool_extra["max_iterations"] = max(1, min(int(_mi), 64))
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
_rt = node_data.get("request_timeout")
|
||||
if _rt is not None:
|
||||
try:
|
||||
_tool_extra["request_timeout"] = max(10.0, float(_rt))
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
result = await llm_service.call_llm_with_tools(
|
||||
prompt=prompt,
|
||||
tools=tools,
|
||||
@@ -4916,7 +4993,12 @@ class WorkflowEngine:
|
||||
if isinstance(_rj, dict):
|
||||
_ex.update(_rj)
|
||||
except Exception:
|
||||
pass
|
||||
# 非 JSON 但以 { 开头(如 Markdown),仍当作正文
|
||||
_ex['output'] = _ex['right']
|
||||
else:
|
||||
# LLM 节点 output 常为纯文本,经带 handle 的边落在 right;须写入 output,
|
||||
# 否则下游按 dict 拼接会把 user_id(preview_xxx)拼在回复末尾。
|
||||
_ex['output'] = _ex['right']
|
||||
input_data = _ex
|
||||
final_output = input_data
|
||||
|
||||
@@ -4983,7 +5065,28 @@ class WorkflowEngine:
|
||||
# 否则转换为纯文本(不是JSON)
|
||||
# 尝试提取所有文本字段并组合,但排除系统字段和用户查询字段
|
||||
text_parts = []
|
||||
exclude_keys = {'status', 'error', 'timestamp', 'node_id', 'execution_time', 'query', 'USER_INPUT', 'user_input', 'user_query'}
|
||||
exclude_keys = {
|
||||
'status',
|
||||
'error',
|
||||
'timestamp',
|
||||
'node_id',
|
||||
'execution_time',
|
||||
'query',
|
||||
'USER_INPUT',
|
||||
'user_input',
|
||||
'user_query',
|
||||
'user_id',
|
||||
'USER_ID',
|
||||
'userId',
|
||||
'attachments',
|
||||
'memory',
|
||||
'conversation_history',
|
||||
'user_profile',
|
||||
'context',
|
||||
'right',
|
||||
'left',
|
||||
'data',
|
||||
}
|
||||
# 优先使用input字段(LLM的实际输出)
|
||||
if 'input' in final_output and isinstance(final_output['input'], str):
|
||||
final_output = final_output['input']
|
||||
|
||||
Reference in New Issue
Block a user