修复轻量拓展分析 NL 触发第一轮测试反馈(PM 裁断)
- P0 目录截断:_rough_candidates 关键词源扩展 extension_id token 与参数 flag;命中数降序排序;MAX_CATALOG_CHARS 12000→24000;截断时 reason 注明 - P1a 过滤缺失 extension_id 的记录,不再产出 None 候选 - P1b hmmsearch/hmmer/blast/blastp 不再全量触发,改为按关键词源匹配子集;仅「拓展分析/扩展分析/extension」允许全量候选 - P2 extension_name 改为 extension_id 紧凑形式(去尾缀时间戳截 30 字符);message 中文模板(extension_id 为主、summary 括号补充) - P2 nl-import-paths:目录同名冲突 _1/_2 后缀;多路径先整体校验后复制
This commit is contained in:
+41
-10
@@ -4451,7 +4451,8 @@ async def nl_import_paths(req: NlImportPathsRequest):
|
||||
"""把服务器上的绝对路径(文件或目录)复制进当前 job 的 input/_nl_imports/。
|
||||
|
||||
供轻量拓展分析自然语言触发向导使用;路径必须真实存在且解析后位于
|
||||
/home/xzq/ 或 /data/ 之下。
|
||||
/home/xzq/ 或 /data/ 之下。所有路径先整体校验,任一非法直接 400,
|
||||
全部合法后才逐个复制。
|
||||
"""
|
||||
job_id = str(req.job_id or "").strip()
|
||||
if not job_id:
|
||||
@@ -4463,7 +4464,7 @@ async def nl_import_paths(req: NlImportPathsRequest):
|
||||
raise HTTPException(status_code=400, detail=f"无法创建 job 输入目录: {exc}") from exc
|
||||
|
||||
allowed_roots = ("/home/xzq/", "/data/")
|
||||
imported: dict[str, str] = {}
|
||||
sources: list[Path] = []
|
||||
for raw_path in req.paths or []:
|
||||
raw_text = str(raw_path or "").strip()
|
||||
if not raw_text:
|
||||
@@ -4483,8 +4484,12 @@ async def nl_import_paths(req: NlImportPathsRequest):
|
||||
status_code=400,
|
||||
detail=f"路径必须位于 {', '.join(allowed_roots)} 之下: {raw_text}",
|
||||
)
|
||||
target_dir = job_dir / "_nl_imports"
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
sources.append(source)
|
||||
|
||||
target_dir = job_dir / "_nl_imports"
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
imported: dict[str, str] = {}
|
||||
for source, raw_path in zip(sources, [str(p or "").strip() for p in req.paths or []]):
|
||||
if source.is_file():
|
||||
destination = target_dir / source.name
|
||||
candidate = destination
|
||||
@@ -4495,16 +4500,21 @@ async def nl_import_paths(req: NlImportPathsRequest):
|
||||
try:
|
||||
shutil.copy2(source, candidate)
|
||||
except OSError as exc:
|
||||
raise HTTPException(status_code=400, detail=f"复制文件失败: {raw_text}: {exc}") from exc
|
||||
raise HTTPException(status_code=400, detail=f"复制文件失败: {raw_path}: {exc}") from exc
|
||||
name = candidate.name
|
||||
else:
|
||||
destination = target_dir / source.name
|
||||
candidate = destination
|
||||
counter = 1
|
||||
while candidate.exists():
|
||||
candidate = target_dir / f"{source.name}_{counter}"
|
||||
counter += 1
|
||||
try:
|
||||
shutil.copytree(source, destination, dirs_exist_ok=True)
|
||||
shutil.copytree(source, candidate, dirs_exist_ok=True)
|
||||
except OSError as exc:
|
||||
raise HTTPException(status_code=400, detail=f"复制目录失败: {raw_text}: {exc}") from exc
|
||||
name = destination.name
|
||||
imported[raw_text] = f"input/{job_id}/_nl_imports/{name}"
|
||||
raise HTTPException(status_code=400, detail=f"复制目录失败: {raw_path}: {exc}") from exc
|
||||
name = candidate.name
|
||||
imported[raw_path] = f"input/{job_id}/_nl_imports/{name}"
|
||||
return {"success": True, "imported": imported}
|
||||
|
||||
|
||||
@@ -16553,6 +16563,7 @@ def _match_lightweight_extension_intent(message: str, job_id: str = "") -> dict[
|
||||
|
||||
返回 dict 含 lightweight=True;任何失败返回 {},绝不抛异常。
|
||||
"""
|
||||
records: list[dict] = []
|
||||
try:
|
||||
from gfa_core.extension_stage_lightweight import nl_intent
|
||||
|
||||
@@ -16571,10 +16582,20 @@ def _match_lightweight_extension_intent(message: str, job_id: str = "") -> dict[
|
||||
return {}
|
||||
if resolution is None or not resolution.extension_id:
|
||||
return {}
|
||||
summary_hint = ""
|
||||
for record in records:
|
||||
if str(record.get("extension_id") or "") != resolution.extension_id:
|
||||
continue
|
||||
candidate = record.get("semantic_candidate")
|
||||
if isinstance(candidate, dict):
|
||||
first_sentence = re.split(r"[。.!?;;]", str(candidate.get("function_summary") or ""))[0].strip()
|
||||
summary_hint = first_sentence[:60]
|
||||
break
|
||||
params = {
|
||||
"extension_id": resolution.extension_id,
|
||||
"extensionName": resolution.extension_name or resolution.extension_id,
|
||||
"extension_store": "lightweight",
|
||||
"function_summary": summary_hint,
|
||||
"llm_slots": {
|
||||
"input_overrides": resolution.input_overrides,
|
||||
"parameter_overrides": resolution.parameter_overrides,
|
||||
@@ -16584,6 +16605,16 @@ def _match_lightweight_extension_intent(message: str, job_id: str = "") -> dict[
|
||||
"confidence": resolution.confidence,
|
||||
"parse_reason": resolution.reason,
|
||||
}
|
||||
if summary_hint:
|
||||
message_text = (
|
||||
f"已识别为轻量拓展分析:{params['extension_id']}({summary_hint})。"
|
||||
"请按引导上传或选择输入文件并核对参数后执行。"
|
||||
)
|
||||
else:
|
||||
message_text = (
|
||||
f"已识别为轻量拓展分析:{params['extension_id']}。"
|
||||
"请按引导上传或选择输入文件并核对参数后执行。"
|
||||
)
|
||||
return {
|
||||
"stage": "extension_stage",
|
||||
"stages": ["extension_stage"],
|
||||
@@ -16596,7 +16627,7 @@ def _match_lightweight_extension_intent(message: str, job_id: str = "") -> dict[
|
||||
"taskType": "extension_stage",
|
||||
"lightweight": True,
|
||||
"confidence": resolution.confidence,
|
||||
"message": f"已识别为轻量拓展分析:{params['extensionName']}。请按引导上传或选择输入文件并核对参数后执行。",
|
||||
"message": message_text,
|
||||
"job_id": job_id,
|
||||
"workspace": str(PROJECT_ROOT / "workspace" / job_id) if job_id else "",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user