This commit is contained in:
liailing1026
2025-12-07 17:18:10 +08:00
parent ab8c9e294d
commit 23db6fc4a1
55 changed files with 16237 additions and 376 deletions

View File

@@ -1,3 +1,10 @@
import nest_asyncio
nest_asyncio.apply()
import os, sys, functools
print = functools.partial(print, flush=True) # 全局 flush
sys.stdout.reconfigure(line_buffering=True) # 3.7+ 有效
import asyncio
from flask import Flask, request, jsonify
import json
from DataProcess import Add_Collaboration_Brief_FrontEnd
@@ -19,11 +26,12 @@ import argparse
# initialize global variables
yaml_file = os.path.join(os.getcwd(), "config", "config.yaml")
yaml_data = {}
try:
with open(yaml_file, "r", encoding="utf-8") as file:
yaml_data = yaml.safe_load(file)
except Exception:
yaml_file = {}
yaml_data = {}
USE_CACHE: bool = os.getenv("USE_CACHE")
if USE_CACHE is None:
USE_CACHE = yaml_data.get("USE_CACHE", False)
@@ -35,14 +43,98 @@ Request_Cache: dict[str, str] = {}
app = Flask(__name__)
from jsonschema import validate, ValidationError
AGENT_SELECTION_SCHEMA = {
"type": "object",
"properties": {
"AgentSelectionPlan": {
"type": "array",
"items": {
"type": "string",
"minLength": 1, # 不允许空字符串
"pattern": r"^\S+$" # 不允许仅空白
},
"minItems": 1 # 至少选一个
}
},
"required": ["AgentSelectionPlan"],
"additionalProperties": False
}
BASE_PLAN_SCHEMA = {
"type": "object",
"properties": {
"Plan_Outline": {
"type": "array",
"items": {
"type": "object",
"properties": {
"StepName": {"type": "string"},
"TaskContent": {"type": "string"},
"InputObject_List":{"type": "array", "items": {"type": "string"}},
"OutputObject": {"type": "string"},
},
"required": ["StepName", "TaskContent", "InputObject_List", "OutputObject"],
"additionalProperties": False,
},
}
},
"required": ["Plan_Outline"],
"additionalProperties": False,
}
def safe_join(iterable, sep=""):
"""保证 join 前全是 strNone 变空串"""
return sep.join("" if x is None else str(x) for x in iterable)
def clean_agent_board(board):
"""把 AgentBoard 洗成只含 str 的字典列表"""
if not board:
return []
return [
{"Name": (a.get("Name") or "").strip(),
"Profile": (a.get("Profile") or "").strip()}
for a in board
if a and a.get("Name")
]
def clean_plan_outline(outline):
"""清洗 Plan_Outline 里的 None"""
if not isinstance(outline, list):
return []
for step in outline:
if not isinstance(step, dict):
continue
step["InputObject_List"] = [
str(i) for i in step.get("InputObject_List", []) if i is not None
]
step["OutputObject"] = str(step.get("OutputObject") or "")
step["StepName"] = str(step.get("StepName") or "")
step["TaskContent"] = str(step.get("TaskContent") or "")
return outline
@app.route("/fill_stepTask_TaskProcess", methods=["post"])
def Handle_fill_stepTask_TaskProcess():
incoming_data = request.get_json()
# print(f"[DEBUG] fill_stepTask_TaskProcess received data: {incoming_data}", flush=True)
# 验证必需参数
General_Goal = incoming_data.get("General Goal", "").strip()
stepTask_lackTaskProcess = incoming_data.get("stepTask_lackTaskProcess")
if not General_Goal:
return jsonify({"error": "General Goal is required and cannot be empty"}), 400
if not stepTask_lackTaskProcess:
return jsonify({"error": "stepTask_lackTaskProcess is required"}), 400
requestIdentifier = str(
(
"/fill_stepTask_TaskProcess",
incoming_data["General Goal"],
incoming_data["stepTask_lackTaskProcess"],
General_Goal,
stepTask_lackTaskProcess,
)
)
@@ -50,40 +142,54 @@ def Handle_fill_stepTask_TaskProcess():
if requestIdentifier in Request_Cache:
return jsonify(Request_Cache[requestIdentifier])
filled_stepTask = fill_stepTask_TaskProcess(
General_Goal=incoming_data["General Goal"],
stepTask=incoming_data["stepTask_lackTaskProcess"],
AgentProfile_Dict=AgentProfile_Dict,
)
try:
filled_stepTask = fill_stepTask_TaskProcess(
General_Goal=General_Goal,
stepTask=stepTask_lackTaskProcess,
AgentProfile_Dict=AgentProfile_Dict,
)
except Exception as e:
print(f"[ERROR] fill_stepTask_TaskProcess failed: {e}", flush=True)
return jsonify({"error": str(e)}), 500
filled_stepTask = Add_Collaboration_Brief_FrontEnd(filled_stepTask)
Request_Cache[requestIdentifier] = filled_stepTask
response = jsonify(filled_stepTask)
return response
@app.route("/agentSelectModify_init", methods=["post"])
@app.route("/agentSelectModify_init", methods=["POST"])
def Handle_agentSelectModify_init():
incoming_data = request.get_json()
requestIdentifier = str(
(
"/agentSelectModify_init",
incoming_data["General Goal"],
incoming_data["stepTask"],
)
)
incoming = request.get_json(silent=True) or {}
general_goal = (incoming.get("General Goal") or "").strip()
step_task = incoming.get("stepTask")
if not general_goal or not step_task:
return jsonify({"error": "Missing field"}), 400
if not AgentBoard: # 空 Board 直接返回
return jsonify({"AgentSelectionPlan": []})
req_id = str(("/agentSelectModify_init", general_goal, step_task))
if USE_CACHE and req_id in Request_Cache:
return jsonify(Request_Cache[req_id])
try:
clean_board = clean_agent_board(AgentBoard)
raw = AgentSelectModify_init(stepTask=step_task,
General_Goal=general_goal,
Agent_Board=clean_board)
if not isinstance(raw, dict):
raise ValueError("model returned non-dict")
plan = raw.get("AgentSelectionPlan") or []
cleaned = [str(x).strip() for x in plan if x is not None and str(x).strip()]
raw["AgentSelectionPlan"] = cleaned
validate(instance=raw, schema=AGENT_SELECTION_SCHEMA)
except Exception as exc:
print(f"[ERROR] AgentSelectModify_init: {exc}")
return jsonify({"error": str(exc)}), 500
if USE_CACHE:
if requestIdentifier in Request_Cache:
return jsonify(Request_Cache[requestIdentifier])
scoreTable = AgentSelectModify_init(
stepTask=incoming_data["stepTask"],
General_Goal=incoming_data["General Goal"],
Agent_Board=AgentBoard,
)
Request_Cache[requestIdentifier] = scoreTable
response = jsonify(scoreTable)
return response
Request_Cache[req_id] = raw
return jsonify(raw)
@app.route("/agentSelectModify_addAspect", methods=["post"])
@@ -98,7 +204,7 @@ def Handle_agentSelectModify_addAspect():
return jsonify(Request_Cache[requestIdentifier])
scoreTable = AgentSelectModify_addAspect(
aspectList=incoming_data["aspectList"], Agent_Board=AgentBoard
aspectList=incoming_data["aspectList"], Agent_Board=AgentBoard or []
)
Request_Cache[requestIdentifier] = scoreTable
response = jsonify(scoreTable)
@@ -108,11 +214,22 @@ def Handle_agentSelectModify_addAspect():
@app.route("/fill_stepTask", methods=["post"])
def Handle_fill_stepTask():
incoming_data = request.get_json()
# print(f"[DEBUG] fill_stepTask received data: {incoming_data}", flush=True)
# 验证必需参数
General_Goal = incoming_data.get("General Goal", "").strip()
stepTask = incoming_data.get("stepTask")
if not General_Goal:
return jsonify({"error": "General Goal is required and cannot be empty"}), 400
if not stepTask:
return jsonify({"error": "stepTask is required"}), 400
requestIdentifier = str(
(
"/fill_stepTask",
incoming_data["General Goal"],
incoming_data["stepTask"],
General_Goal,
stepTask,
)
)
@@ -120,12 +237,16 @@ def Handle_fill_stepTask():
if requestIdentifier in Request_Cache:
return jsonify(Request_Cache[requestIdentifier])
filled_stepTask = fill_stepTask(
General_Goal=incoming_data["General Goal"],
stepTask=incoming_data["stepTask"],
Agent_Board=AgentBoard,
AgentProfile_Dict=AgentProfile_Dict,
)
try:
filled_stepTask = fill_stepTask(
General_Goal=General_Goal,
stepTask=stepTask,
Agent_Board=AgentBoard,
AgentProfile_Dict=AgentProfile_Dict,
)
except Exception as e:
print(f"[ERROR] fill_stepTask failed: {e}", flush=True)
return jsonify({"error": str(e)}), 500
filled_stepTask = Add_Collaboration_Brief_FrontEnd(filled_stepTask)
Request_Cache[requestIdentifier] = filled_stepTask
response = jsonify(filled_stepTask)
@@ -198,31 +319,46 @@ def Handle_branch_TaskProcess():
return response
@app.route("/generate_basePlan", methods=["post"])
@app.route("/generate_basePlan", methods=["POST"])
def Handle_generate_basePlan():
incoming_data = request.get_json()
requestIdentifier = str(
(
"/generate_basePlan",
incoming_data["General Goal"],
incoming_data["Initial Input Object"],
incoming = request.get_json(silent=True) or {}
general_goal = (incoming.get("General Goal") or "").strip()
initial_objs = incoming.get("Initial Input Object") or []
if not general_goal:
return jsonify({"error": "General Goal is required"}), 400
# 1. 空 Board 直接短路
if not AgentBoard:
print("[SKIP] AgentBoard empty")
out = Add_Collaboration_Brief_FrontEnd({"Plan_Outline": []})
return jsonify(out)
req_id = str(("/generate_basePlan", general_goal, initial_objs))
if USE_CACHE and req_id in Request_Cache:
return jsonify(Request_Cache[req_id])
try:
# 2. 洗 Board → 调模型 → 洗返回
clean_board = clean_agent_board(AgentBoard)
raw_plan = asyncio.run(
generate_basePlan(
General_Goal=general_goal,
Agent_Board=clean_board,
AgentProfile_Dict=AgentProfile_Dict,
InitialObject_List=initial_objs,
)
)
)
raw_plan["Plan_Outline"] = clean_plan_outline(raw_plan.get("Plan_Outline"))
validate(instance=raw_plan, schema=BASE_PLAN_SCHEMA) # 可选,二次校验
except Exception as exc:
print(f"[ERROR] generate_basePlan failed: {exc}")
return jsonify({"error": "model call failed", "detail": str(exc)}), 500
out = Add_Collaboration_Brief_FrontEnd(raw_plan)
if USE_CACHE:
if requestIdentifier in Request_Cache:
return jsonify(Request_Cache[requestIdentifier])
basePlan = generate_basePlan(
General_Goal=incoming_data["General Goal"],
Agent_Board=AgentBoard,
AgentProfile_Dict=AgentProfile_Dict,
InitialObject_List=incoming_data["Initial Input Object"],
)
basePlan_withRenderSpec = Add_Collaboration_Brief_FrontEnd(basePlan)
Request_Cache[requestIdentifier] = basePlan_withRenderSpec
response = jsonify(basePlan_withRenderSpec)
return response
Request_Cache[req_id] = out
return jsonify(out)
@app.route("/executePlan", methods=["post"])
@@ -267,13 +403,11 @@ def Handle_saveRequestCashe():
@app.route("/setAgents", methods=["POST"])
def set_agents():
global AgentBoard, AgentProfile_Dict
AgentBoard = request.json
AgentProfile_Dict = {}
for item in AgentBoard:
name = item["Name"]
profile = item["Profile"]
AgentProfile_Dict[name] = profile
return jsonify({"code": 200, "content": "set agentboard successfully"})
board_in = request.json or []
# 先清洗再赋值
AgentBoard = clean_agent_board(board_in)
AgentProfile_Dict = {a["Name"]: a["Profile"] for a in AgentBoard}
return jsonify({"code": 200, "content": "AgentBoard set successfully"})
def init():